Update MCLinker to work with LLVM 3.4.

This corresponds to merging upstream MCLinker with the following SHA:
6dcbf36cdb146d6f175ba2f18a9004753cafeaff

Change-Id: I1bc8c2ce4accc563450bc71ee295a6e47a0c0469
diff --git a/LICENSE.TXT b/LICENSE.TXT
index 8d5fff6..562a772 100644
--- a/LICENSE.TXT
+++ b/LICENSE.TXT
@@ -4,11 +4,13 @@
 University of Illinois/NCSA
 Open Source License
 
-Copyright (c) 2011-2011 MediaTek Inc.
+Copyright (c) 2011-2013 MediaTek Inc.
 All rights reserved.
 
 Developed by:
 
+    MCLinker Team.
+
     MediaTek Inc.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of
diff --git a/include/mcld/ADT/BinTree.h b/include/mcld/ADT/BinTree.h
index 76de607..4093b72 100644
--- a/include/mcld/ADT/BinTree.h
+++ b/include/mcld/ADT/BinTree.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_BINARY_TREE_H
-#define MCLD_BINARY_TREE_H
+#ifndef MCLD_ADT_BITREE_H
+#define MCLD_ADT_BITREE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -438,16 +438,16 @@
   //  @param DIRECT the direction of the connecting edge of the parent node.
   //  @param position the parent node
   //  @param value the value being pushed.
-  template<size_t DIRECT, class Pos>
-  BinaryTree& join(Pos position, const DataType& value) {
+  template<size_t DIRECT>
+  BinaryTree& join(TreeIteratorBase& pPosition, const DataType& pValue) {
     node_type *node = BinaryTreeBase<DataType>::createNode();
-    node->data = const_cast<DataType*>(&value);
-    if (position.isRoot())
-      proxy::hook<TreeIteratorBase::Leftward>(position.m_pNode,
-                          const_cast<const node_type*>(node));
+    node->data = const_cast<DataType*>(&pValue);
+
+    if (pPosition.isRoot())
+      pPosition.hook<TreeIteratorBase::Leftward>(node);
     else
-      proxy::hook<DIRECT>(position.m_pNode,
-                          const_cast<const node_type*>(node));
+      pPosition.hook<DIRECT>(node);
+
     return *this;
   }
 
@@ -456,14 +456,13 @@
   //  @param position the parent node
   //  @param the tree being joined.
   //  @return the joined tree
-  template<size_t DIRECT, class Pos>
-  BinaryTree& merge(Pos position, BinaryTree& pTree) {
+  template<size_t DIRECT>
+  BinaryTree& merge(TreeIteratorBase& pPosition, BinaryTree& pTree) {
     if (this == &pTree)
       return *this;
 
     if (!pTree.empty()) {
-      proxy::hook<DIRECT>(position.m_pNode,
-                        const_cast<const NodeBase*>(pTree.m_Root.node.left));
+      pPosition.hook<DIRECT>(pTree.m_Root.node.left);
       BinaryTreeBase<DataType>::m_Root.summon(
                                    pTree.BinaryTreeBase<DataType>::m_Root);
       BinaryTreeBase<DataType>::m_Root.delegate(pTree.m_Root);
diff --git a/include/mcld/ADT/Flags.h b/include/mcld/ADT/Flags.h
index d38d941..c6a41e8 100644
--- a/include/mcld/ADT/Flags.h
+++ b/include/mcld/ADT/Flags.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_FLAGS_H
-#define MCLD_FLAGS_H
+#ifndef MCLD_ADT_FLAGS_H
+#define MCLD_ADT_FLAGS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/ADT/GraphLite/Digraph.h b/include/mcld/ADT/GraphLite/Digraph.h
new file mode 100644
index 0000000..9e1b604
--- /dev/null
+++ b/include/mcld/ADT/GraphLite/Digraph.h
@@ -0,0 +1,85 @@
+//===- Digraph.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ADT_GRAPHLITE_DIGRAPH_H
+#define MCLD_ADT_GRAPHLITE_DIGRAPH_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/ADT/GraphLite/GraphBasicTypes.h>
+#include <stdint.h>
+
+namespace mcld {
+namespace graph {
+
+/** \class Digraph
+ *  \brief Digraph provides the common interface of all directed graphs.
+ */
+class Digraph : private Uncopyable
+{
+public:
+  typedef DirectedTag direction_tag;
+
+  class Node
+  {
+    friend class Digraph;
+  public:
+    Node() {}
+
+    bool operator==(const Node& pOther) const { return m_ID == pOther.m_ID; }
+    bool operator!=(const Node& pOther) const { return m_ID != pOther.m_ID; }
+
+  protected:
+    intptr_t m_ID;
+  };
+
+  class Arc
+  {
+    friend class Digraph;
+  public:
+    Arc();
+
+    bool operator==(const Node& pOther) const;
+    bool operator!=(const Node& pOther) const;
+
+    Node source() const;
+    Node target() const;
+
+  protected:
+    Arc(Digraph& pParent);
+
+  protected:
+    intptr_t m_ID;
+    Digraph* m_Parent;
+  };
+
+public:
+  Digraph();
+
+  Node addNode();
+
+  Arc addArc(const Node& pSource, const Node& pTarget);
+
+  void erase(const Node& pNode);
+
+  void erase(const Arc& pArc);
+
+  void clear();
+
+  unsigned int numOfNodes() const;
+
+  unsigned int numOfArcs() const;
+
+};
+
+} // namespace of graph
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/GraphLite/GraphBasicTypes.h b/include/mcld/ADT/GraphLite/GraphBasicTypes.h
new file mode 100644
index 0000000..5862bcb
--- /dev/null
+++ b/include/mcld/ADT/GraphLite/GraphBasicTypes.h
@@ -0,0 +1,29 @@
+//===- GraphBasicTypes.h --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ADT_GRAPHLITE_GRAPHBASICTYPES_H
+#define MCLD_ADT_GRAPHLITE_GRAPHBASICTYPES_H
+
+namespace mcld {
+namespace graph {
+
+/** \class UndirectedTag
+ *  \brief Undirected graph category.
+ */
+struct UndirectedTag {};
+
+/** \class DirectedTag
+ *  \brief Directed graph category.
+ */
+struct DirectedTag {};
+
+} // namespace of graph
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/GraphLite/ListDigraph.h b/include/mcld/ADT/GraphLite/ListDigraph.h
new file mode 100644
index 0000000..4ae2c50
--- /dev/null
+++ b/include/mcld/ADT/GraphLite/ListDigraph.h
@@ -0,0 +1,92 @@
+//===- ListDigraph.h ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ADT_GRAPHLITE_LISTDIGRAPH_H
+#define MCLD_ADT_GRAPHLITE_LISTDIGRAPH_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Support/GCFactory.h>
+
+namespace mcld {
+namespace graph {
+
+/** \class ListDigraph
+ *  \brief ListDigraph provides an linked-list inplementation of a graph.
+ *
+ *  ListDigraph is designed to get well performance for most algorithms of
+ *  graph theory.
+ *
+ *  Function        | Complexity | Best Complexity
+ *  ----------------|------------|--------------------------
+ *  Storage         | V + E      |
+ *  Add node        | O(1)       |
+ *  Add arc         | O(1)       |
+ *  Remove node     | O(E)       | O(#(fan-in) + #(fan-out))
+ *  Remove edge     | O(1)       |
+ *  Query adjacency | O(E)       | O(#(fan-in) + #(fan-out))
+ *
+ */
+class ListDigraph
+{
+public:
+  struct Node;
+  struct Arc;
+
+  struct Node {
+  public:
+    Node();
+
+  public:
+    Node *prev, *next;
+    Arc *first_in, *first_out;
+  };
+
+  struct Arc {
+  public:
+    Arc();
+
+  public:
+    Node *target, *source;
+    Arc *prev_in, *next_in;
+    Arc *prev_out, *next_out;
+  };
+
+public:
+  ListDigraph();
+
+  Node* addNode();
+
+  Arc* addArc(Node& pU, Node& pV);
+
+  void erase(Node& pNode);
+
+  void erase(Arc& pArc);
+
+  void clear();
+
+  void getHead(Node*& pNode) const { pNode = m_pNodeHead; }
+
+private:
+  typedef GCFactory<Node, 0> NodeList;
+  typedef GCFactory<Arc, 0> ArcList;
+
+private:
+  Node* m_pNodeHead;
+  Node* m_pFreeNodeHead;
+  Arc*  m_pFreeArcHead;
+
+  NodeList m_NodeList;
+  ArcList m_ArcList;
+};
+
+} // namespace of graph
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/HashBase.h b/include/mcld/ADT/HashBase.h
index 896f5b8..f3332a0 100644
--- a/include/mcld/ADT/HashBase.h
+++ b/include/mcld/ADT/HashBase.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_BASE_H
-#define MCLD_HASH_BASE_H
+#ifndef MCLD_ADT_HASHBASE_H
+#define MCLD_ADT_HASHBASE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/ADT/HashBase.tcc b/include/mcld/ADT/HashBase.tcc
index 165f4ae..50f6ac4 100644
--- a/include/mcld/ADT/HashBase.tcc
+++ b/include/mcld/ADT/HashBase.tcc
@@ -7,8 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 // internal non-member functions
+//===----------------------------------------------------------------------===//
 inline static unsigned int compute_bucket_count(unsigned int pNumOfBuckets)
 {
   static const unsigned int bucket_size[] =
@@ -30,8 +31,9 @@
   return (pNumOfBuckets+131101); // rare case. increase constantly
 }
 
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 // template implementation of HashBucket
+//===----------------------------------------------------------------------===//
 template<typename DataType>
 typename HashBucket<DataType>::entry_type*
 HashBucket<DataType>::getEmptyBucket()
@@ -48,8 +50,9 @@
   return tombstone;
 }
 
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 // template implementation of HashTableImpl
+//===----------------------------------------------------------------------===//
 template<typename HashEntryTy,
          typename HashFunctionTy>
 HashTableImpl<HashEntryTy, HashFunctionTy>::HashTableImpl()
diff --git a/include/mcld/ADT/HashEntry.h b/include/mcld/ADT/HashEntry.h
index c034783..5c3557f 100644
--- a/include/mcld/ADT/HashEntry.h
+++ b/include/mcld/ADT/HashEntry.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MCLD_HASH_ENTRY_H
-#define MCLD_HASH_ENTRY_H
+#ifndef MCLD_ADT_HASHENTRY_H
+#define MCLD_ADT_HASHENTRY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/ADT/HashEntryFactory.h b/include/mcld/ADT/HashEntryFactory.h
index 42aa5e7..91deab4 100644
--- a/include/mcld/ADT/HashEntryFactory.h
+++ b/include/mcld/ADT/HashEntryFactory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_ENTRY_FACTORY_H
-#define MCLD_HASH_ENTRY_FACTORY_H
+#ifndef MCLD_ADT_HASHENTRYFACTORY_H
+#define MCLD_ADT_HASHENTRYFACTORY_H
 
 namespace mcld {
 
diff --git a/include/mcld/ADT/HashIterator.h b/include/mcld/ADT/HashIterator.h
index 078b20a..c25870f 100644
--- a/include/mcld/ADT/HashIterator.h
+++ b/include/mcld/ADT/HashIterator.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_ITERATOR_H
-#define MCLD_HASH_ITERATOR_H
+#ifndef MCLD_ADT_HASHITERATOR_H
+#define MCLD_ADT_HASHITERATOR_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/ADT/HashTable.h b/include/mcld/ADT/HashTable.h
index 0b6757e..522ab48 100644
--- a/include/mcld/ADT/HashTable.h
+++ b/include/mcld/ADT/HashTable.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_TABLE_H
-#define MCLD_HASH_TABLE_H
+#ifndef MCLD_ADT_HASHTABLE_H
+#define MCLD_ADT_HASHTABLE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/ADT/SizeTraits.h b/include/mcld/ADT/SizeTraits.h
index dbd5d7b..3baf129 100644
--- a/include/mcld/ADT/SizeTraits.h
+++ b/include/mcld/ADT/SizeTraits.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SIZE_TRAITS_H
-#define MCLD_SIZE_TRAITS_H
+#ifndef MCLD_ADT_SIZETRAITS_H
+#define MCLD_ADT_SIZETRAITS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -153,6 +153,36 @@
            ((pData & 0x00000000000000FFULL) << 56));
 }
 
+template<size_t SIZE>
+typename SizeTraits<SIZE>::Word bswap(typename SizeTraits<SIZE>::Word pData);
+
+template<>
+inline SizeTraits<32>::Word bswap<32>(SizeTraits<32>::Word pData)
+{
+  return bswap32(pData);
+}
+
+template<>
+inline SizeTraits<64>::Word bswap<64>(SizeTraits<64>::Word pData)
+{
+  return bswap64(pData);
+}
+
+template <size_t WIDTH>
+inline uint64_t signExtend(uint64_t pVal)
+{
+  uint64_t mask = (~((uint64_t)0)) >> (64 - WIDTH);
+  uint64_t sign_bit = 1 << (WIDTH - 1);
+
+  return ((pVal & mask) ^ sign_bit) - sign_bit;
+}
+
+template <>
+inline uint64_t signExtend<64>(uint64_t pVal)
+{
+  return pVal;
+}
+
 template <size_t SizeOfStr, typename FieldType>
 class StringSizerHelper
 {
diff --git a/include/mcld/ADT/StringEntry.h b/include/mcld/ADT/StringEntry.h
index e6d1c20..3588c05 100644
--- a/include/mcld/ADT/StringEntry.h
+++ b/include/mcld/ADT/StringEntry.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_STRING_ENTRY_H
-#define MCLD_STRING_ENTRY_H
+#ifndef MCLD_ADT_STRINGENTRY_H
+#define MCLD_ADT_STRINGENTRY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/ADT/StringHash.h b/include/mcld/ADT/StringHash.h
index a9c0025..048f35f 100644
--- a/include/mcld/ADT/StringHash.h
+++ b/include/mcld/ADT/StringHash.h
@@ -6,15 +6,15 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_STRING_HASH_FUNCTION_H
-#define MCLD_STRING_HASH_FUNCTION_H
+#ifndef MCLD_ADT_STRINGHASH_H
+#define MCLD_ADT_STRINGHASH_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <llvm/ADT/StringRef.h>
 #include <llvm/Support/DataTypes.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <cctype>
+#include <cassert>
 #include <functional>
 
 namespace mcld {
@@ -43,7 +43,8 @@
 {
   uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    llvm::report_fatal_error("Undefined StringHash function.\n");
+    assert(false && "Undefined StringHash function.\n");
+    return 0;
   }
 };
 
diff --git a/include/mcld/ADT/TreeAllocator.h b/include/mcld/ADT/TreeAllocator.h
index 10de761..b2bb39b 100644
--- a/include/mcld/ADT/TreeAllocator.h
+++ b/include/mcld/ADT/TreeAllocator.h
@@ -6,13 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TREE_ALLOCATOR_H
-#define MCLD_TREE_ALLOCATOR_H
+#ifndef MCLD_ADT_TREEALLOCATOR_H
+#define MCLD_ADT_TREEALLOCATOR_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <set>
-#include "mcld/Support/GCFactory.h"
+#include <mcld/Support/GCFactory.h>
 
 namespace mcld {
 
diff --git a/include/mcld/ADT/TreeBase.h b/include/mcld/ADT/TreeBase.h
index 13eb474..bca375f 100644
--- a/include/mcld/ADT/TreeBase.h
+++ b/include/mcld/ADT/TreeBase.h
@@ -6,9 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TREE_BASE_H
-#define MCLD_TREE_BASE_H
-#include "mcld/ADT/TypeTraits.h"
+#ifndef MCLD_ADT_TREEBASE_H
+#define MCLD_ADT_TREEBASE_H
+#include <mcld/ADT/TypeTraits.h>
 
 #include <cstddef>
 #include <cassert>
@@ -28,18 +28,6 @@
   { }
 };
 
-namespace proxy
-{
-  template<size_t DIRECT>
-  inline void move(NodeBase *&X)
-  { assert(0 && "not allowed"); }
-
-  template<size_t DIRECT>
-  inline void hook(NodeBase *X, const NodeBase *Y)
-  { assert(0 && "not allowed"); }
-
-} // namespace of template proxy
-
 class TreeIteratorBase
 {
 public:
@@ -67,9 +55,10 @@
   virtual ~TreeIteratorBase(){};
 
   template<size_t DIRECT>
-  inline void move() {
-    proxy::move<DIRECT>(m_pNode);
-  }
+  void move() { assert(0 && "not allowed"); }
+
+  template<size_t DIRECT>
+  void hook(NodeBase* pNode) { assert(0 && "not allowed"); }
 
   bool isRoot() const
   { return (m_pNode->right == m_pNode); }
@@ -87,25 +76,29 @@
   { return this->m_pNode != y.m_pNode; }
 };
 
-namespace proxy
+template<> inline
+void TreeIteratorBase::move<TreeIteratorBase::Leftward>()
 {
-  template<>
-  inline void move<TreeIteratorBase::Leftward>(NodeBase *&X)
-  { X = X->left; }
+  this->m_pNode = this->m_pNode->left;
+}
 
-  template<>
-  inline void move<TreeIteratorBase::Rightward>(NodeBase *&X)
-  { X = X->right; }
+template<> inline
+void TreeIteratorBase::move<TreeIteratorBase::Rightward>()
+{
+  this->m_pNode = this->m_pNode->right;
+}
 
-  template<>
-  inline void hook<TreeIteratorBase::Leftward>(NodeBase *X, const NodeBase *Y)
-  { X->left = const_cast<NodeBase*>(Y); }
+template<> inline
+void TreeIteratorBase::hook<TreeIteratorBase::Leftward>(NodeBase* pOther)
+{
+  this->m_pNode->left = pOther;
+}
 
-  template<>
-  inline void hook<TreeIteratorBase::Rightward>(NodeBase* X, const NodeBase* Y)
-  { X->right = const_cast<NodeBase*>(Y); }
-
-} //namespace of template proxy
+template<> inline
+void TreeIteratorBase::hook<TreeIteratorBase::Rightward>(NodeBase* pOther)
+{
+  this->m_pNode->right = pOther;
+}
 
 template<typename DataType>
 class Node : public NodeBase
diff --git a/include/mcld/ADT/TypeTraits.h b/include/mcld/ADT/TypeTraits.h
index 90b2224..7f872da 100644
--- a/include/mcld/ADT/TypeTraits.h
+++ b/include/mcld/ADT/TypeTraits.h
@@ -6,16 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TYPE_TRAITS_H
-#define MCLD_TYPE_TRAITS_H
+#ifndef MCLD_ADT_TYPETRAITS_H
+#define MCLD_ADT_TYPETRAITS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
 #include <cstdlib>
 
-namespace mcld
-{
+namespace mcld {
+
 template<typename DataType>
 struct NonConstTraits;
 
diff --git a/include/mcld/ADT/Uncopyable.h b/include/mcld/ADT/Uncopyable.h
index 7ddfbe3..d899a0a 100644
--- a/include/mcld/ADT/Uncopyable.h
+++ b/include/mcld/ADT/Uncopyable.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_UNCOPYABLE_H
-#define MCLD_UNCOPYABLE_H
+#ifndef MCLD_ADT_UNCOPYABLE_H
+#define MCLD_ADT_UNCOPYABLE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/AttributeOption.h b/include/mcld/AttributeOption.h
index 18d7278..a0130d2 100644
--- a/include/mcld/AttributeOption.h
+++ b/include/mcld/AttributeOption.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ATTRIBUTE_OPTIONS_H
-#define MCLD_ATTRIBUTE_OPTIONS_H
+#ifndef MCLD_ATTRIBUTEOPTION_H
+#define MCLD_ATTRIBUTEOPTION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/BitcodeOption.h b/include/mcld/BitcodeOption.h
index 4e9a5e1..6d2b9b7 100644
--- a/include/mcld/BitcodeOption.h
+++ b/include/mcld/BitcodeOption.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_BITCODE_OPTIONS_H
-#define MCLD_BITCODE_OPTIONS_H
+#ifndef MCLD_BITCODEOPTION_H
+#define MCLD_BITCODEOPTION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/CodeGen/MCLinker.h b/include/mcld/CodeGen/MCLinker.h
index 34ddcb7..10423bb 100644
--- a/include/mcld/CodeGen/MCLinker.h
+++ b/include/mcld/CodeGen/MCLinker.h
@@ -28,10 +28,10 @@
 namespace mcld {
 
 class Module;
-class MemoryArea;
 class IRBuilder;
 class LinkerConfig;
 class Linker;
+class FileHandle;
 
 /** \class MCLinker
 *  \brief MCLinker provides a linking pass for standard compilation flow
@@ -54,7 +54,7 @@
   // - the standard symbols
   MCLinker(LinkerConfig& pConfig,
            mcld::Module& pModule,
-           MemoryArea& pOutput);
+           FileHandle& pFileHandle);
 
 public:
   virtual ~MCLinker();
@@ -71,7 +71,7 @@
 protected:
   LinkerConfig& m_Config;
   mcld::Module& m_Module;
-  MemoryArea& m_Output;
+  FileHandle& m_FileHandle;
   IRBuilder* m_pBuilder;
   Linker* m_pLinker;
 
diff --git a/include/mcld/Target/TargetMachine.h b/include/mcld/CodeGen/TargetMachine.h
similarity index 66%
rename from include/mcld/Target/TargetMachine.h
rename to include/mcld/CodeGen/TargetMachine.h
index 669e860..6454d87 100644
--- a/include/mcld/Target/TargetMachine.h
+++ b/include/mcld/CodeGen/TargetMachine.h
@@ -6,12 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_TARGET_MACHINE_H
-#define MCLD_TARGET_TARGET_MACHINE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/Target/TargetMachine.h>
+#ifndef MCLD_CODEGEN_TARGETMACHINE_H
+#define MCLD_CODEGEN_TARGETMACHINE_H
+#include <llvm/Support/CodeGen.h>
 #include <string>
 
 namespace llvm {
@@ -19,20 +16,22 @@
 class Target;
 class TargetData;
 class TargetMachine;
+class MCContext;
+class raw_ostream;
+class formatted_raw_ostream;
+namespace legacy {
 class PassManagerBase;
-
-} // namespace of llvm
+} // namepsace legacy
+} // namespace llvm
 
 namespace mcld {
 
 class Module;
 class Target;
-class MemoryArea;
+class FileHandle;
 class LinkerConfig;
 class ToolOutputFile;
 
-using namespace llvm;
-
 enum CodeGenFileType {
   CGFT_ASMFile,
   CGFT_OBJFile,
@@ -52,9 +51,10 @@
 public:
   /// Adapter of llvm::TargetMachine
   ///
-  MCLDTargetMachine(llvm::TargetMachine &pTM,
-                    const mcld::Target &pTarget,
-                    const std::string &pTriple);
+  MCLDTargetMachine(llvm::TargetMachine& pTM,
+                    const llvm::Target& pLLMVTarget,
+                    const mcld::Target& pMCLDTarget,
+                    const std::string& pTriple);
 
   virtual ~MCLDTargetMachine();
 
@@ -67,48 +67,41 @@
 
   /// appPassesToEmitFile - The target function which we has to modify as
   /// upstreaming.
-  bool addPassesToEmitFile(PassManagerBase &,
+  bool addPassesToEmitFile(llvm::legacy::PassManagerBase &,
                            mcld::ToolOutputFile& pOutput,
                            mcld::CodeGenFileType,
-                           CodeGenOpt::Level,
+                           llvm::CodeGenOpt::Level,
                            mcld::Module& pModule,
                            mcld::LinkerConfig& pConfig,
                            bool DisableVerify = true);
 
-  /// getDataLayout
-  const DataLayout *getDataLayout() const { return m_TM.getDataLayout(); }
-
-  /// setAsmVerbosityDefault
-  static void setAsmVerbosityDefault(bool pAsmVerbose) {
-    llvm::TargetMachine::setAsmVerbosityDefault(pAsmVerbose);
-  }
-
 private:
   /// addCommonCodeGenPasses - Add standard LLVM codegen passes used for
   /// both emitting to assembly files or machine code output.
-  bool addCommonCodeGenPasses(PassManagerBase &,
+  bool addCommonCodeGenPasses(llvm::legacy::PassManagerBase &,
                               mcld::CodeGenFileType,
-                              CodeGenOpt::Level,
+                              llvm::CodeGenOpt::Level,
                               bool DisableVerify,
                               llvm::MCContext *&OutCtx);
 
-  bool addCompilerPasses(PassManagerBase &pPM,
+  bool addCompilerPasses(llvm::legacy::PassManagerBase &pPM,
                          llvm::formatted_raw_ostream &pOutput,
                          llvm::MCContext *&OutCtx);
 
-  bool addAssemblerPasses(PassManagerBase &pPM,
+  bool addAssemblerPasses(llvm::legacy::PassManagerBase &pPM,
                           llvm::raw_ostream &pOutput,
                           llvm::MCContext *&OutCtx);
 
-  bool addLinkerPasses(PassManagerBase &pPM,
-                       LinkerConfig& pConfig,
-                       Module& pModule,
-                       mcld::MemoryArea& pOutput,
+  bool addLinkerPasses(llvm::legacy::PassManagerBase &pPM,
+                       mcld::LinkerConfig& pConfig,
+                       mcld::Module& pModule,
+                       mcld::FileHandle& pFileHandle,
                        llvm::MCContext *&OutCtx);
 
 private:
   llvm::TargetMachine &m_TM;
-  const mcld::Target *m_pTarget;
+  const llvm::Target *m_pLLVMTarget;
+  const mcld::Target *m_pMCLDTarget;
   const std::string& m_Triple;
 };
 
diff --git a/include/mcld/Config/Config.h b/include/mcld/Config/Config.h
index 94946df..9e52d54 100644
--- a/include/mcld/Config/Config.h
+++ b/include/mcld/Config/Config.h
@@ -40,5 +40,7 @@
 #define MCLD_SYMBOLS_PER_INPUT 128
 #define MCLD_RELOCATIONS_PER_INPUT 1024
 
+#define MCLD_SEGMENTS_PER_OUTPUT 8
+
 #endif
 
diff --git a/include/mcld/Fragment/AlignFragment.h b/include/mcld/Fragment/AlignFragment.h
index 14d0051..1175c07 100644
--- a/include/mcld/Fragment/AlignFragment.h
+++ b/include/mcld/Fragment/AlignFragment.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_ALIGNFRAGMENT_H
-#define MCLD_LD_ALIGNFRAGMENT_H
+#ifndef MCLD_FRAGMENT_ALIGNFRAGMENT_H
+#define MCLD_FRAGMENT_ALIGNFRAGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Fragment/FGNode.h b/include/mcld/Fragment/FGNode.h
deleted file mode 100644
index 0afee0e..0000000
--- a/include/mcld/Fragment/FGNode.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//===- 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/FillFragment.h b/include/mcld/Fragment/FillFragment.h
index af78237..aa32ec8 100644
--- a/include/mcld/Fragment/FillFragment.h
+++ b/include/mcld/Fragment/FillFragment.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_FILLFRAGMENT_H
-#define MCLD_LD_FILLFRAGMENT_H
+#ifndef MCLD_FRAGMENT_FILLFRAGMENT_H
+#define MCLD_FRAGMENT_FILLFRAGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Fragment/FragmentGraph.h b/include/mcld/Fragment/FragmentGraph.h
deleted file mode 100644
index 96d438f..0000000
--- a/include/mcld/Fragment/FragmentGraph.h
+++ /dev/null
@@ -1,177 +0,0 @@
-//===- 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
deleted file mode 100644
index 45ef85d..0000000
--- a/include/mcld/Fragment/FragmentLinker.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===- FragmentLinker.h ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides a number of APIs used by SectLinker.
-// These APIs do the things which a linker should do.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_FRAGMENT_FRAGMENT_LINKER_H
-#define MCLD_FRAGMENT_FRAGMENT_LINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <string>
-
-#include <mcld/LinkerConfig.h>
-#include <mcld/LD/LDFileFormat.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/Fragment/Relocation.h>
-#include <mcld/MC/MCLDInput.h>
-
-namespace mcld {
-
-class Module;
-class TargetLDBackend;
-class LinkerConfig;
-class MemoryArea;
-
-/** \class FragmentLinker
- *  \brief FragmentLinker provides a pass to link object files.
- */
-class FragmentLinker
-{
-public:
-  FragmentLinker(const LinkerConfig& pConfig,
-                 Module& pModule,
-                 TargetLDBackend& pBackend);
-
-  ~FragmentLinker();
-
-  bool finalizeSymbols();
-
-  /// applyRelocations - apply all relocation enties.
-  bool applyRelocations();
-
-  /// syncRelocationResult - After applying relocation, write back relocation target
-  /// data to output file.
-  void syncRelocationResult(MemoryArea& pOutput);
-
-private:
-  /// normalSyncRelocationResult - sync relocation result when producing shared
-  /// objects or executables
-  void normalSyncRelocationResult(MemoryArea& pOutput);
-
-  /// partialSyncRelocationResult - sync relocation result when doing partial
-  /// link
-  void partialSyncRelocationResult(MemoryArea& pOutput);
-
-  /// writeRelocationResult - helper function of syncRelocationResult, write
-  /// relocation target data to output
-  void writeRelocationResult(Relocation& pReloc, uint8_t* pOutput);
-
-private:
-  const LinkerConfig& m_Config;
-  Module& m_Module;
-  TargetLDBackend& m_Backend;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Fragment/FragmentRef.h b/include/mcld/Fragment/FragmentRef.h
index 3fce7c9..3bfd804 100644
--- a/include/mcld/Fragment/FragmentRef.h
+++ b/include/mcld/Fragment/FragmentRef.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_FRAGMENT_FRAGMENT_REFERENCE_H
-#define MCLD_FRAGMENT_FRAGMENT_REFERENCE_H
+#ifndef MCLD_FRAGMENT_FRAGMENTREF_H
+#define MCLD_FRAGMENT_FRAGMENTREF_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -78,17 +78,6 @@
 
   Offset getOutputOffset() const;
 
-  // -----  dereference  ----- //
-  Address deref();
-
-  ConstAddress deref() const;
-
-  Address operator*()
-  { return deref(); }
-
-  ConstAddress operator*() const
-  { return deref(); }
-
 private:
   friend FragmentRef& NullFragmentRef();
   friend class Chunk<FragmentRef, MCLD_SECTIONS_PER_INPUT>;
diff --git a/include/mcld/Fragment/NullFragment.h b/include/mcld/Fragment/NullFragment.h
index 1c84fae..3440453 100644
--- a/include/mcld/Fragment/NullFragment.h
+++ b/include/mcld/Fragment/NullFragment.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_NULL_FRAGMENT_H
-#define MCLD_LD_NULL_FRAGMENT_H
+#ifndef MCLD_FRAGMENT_NULLFRAGMENT_H
+#define MCLD_FRAGMENT_NULLFRAGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Fragment/RegionFragment.h b/include/mcld/Fragment/RegionFragment.h
index e077264..4f1908a 100644
--- a/include/mcld/Fragment/RegionFragment.h
+++ b/include/mcld/Fragment/RegionFragment.h
@@ -6,30 +6,29 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_REGION_FRAGMENT_H
-#define MCLD_LD_REGION_FRAGMENT_H
+#ifndef MCLD_FRAGMENT_REGIONFRAGMENT_H
+#define MCLD_FRAGMENT_REGIONFRAGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
 #include <mcld/Fragment/Fragment.h>
+#include <llvm/ADT/StringRef.h>
 
 namespace mcld {
 
-class MemoryRegion;
-
 /** \class RegionFragment
- *  \brief RegionFragment is a kind of Fragment containing mcld::MemoryRegion
+ *  \brief RegionFragment is a kind of Fragment containing input memory region
  */
 class RegionFragment : public Fragment
 {
 public:
-  RegionFragment(MemoryRegion& pRegion, SectionData* pSD = NULL);
+  RegionFragment(llvm::StringRef pRegion, SectionData* pSD = NULL);
 
   ~RegionFragment();
 
-  const MemoryRegion& getRegion() const { return m_Region; }
-  MemoryRegion&       getRegion()       { return m_Region; }
+  const llvm::StringRef getRegion() const { return m_Region; }
+  llvm::StringRef       getRegion()       { return m_Region; }
 
   static bool classof(const Fragment *F)
   { return F->getKind() == Fragment::Region; }
@@ -40,7 +39,7 @@
   size_t size() const;
 
 private:
-  MemoryRegion& m_Region;
+  llvm::StringRef m_Region;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Fragment/Relocation.h b/include/mcld/Fragment/Relocation.h
index e8c57e4..3824dd5 100644
--- a/include/mcld/Fragment/Relocation.h
+++ b/include/mcld/Fragment/Relocation.h
@@ -34,7 +34,7 @@
   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 uint32_t Type;
   typedef uint32_t Size;
 
 private:
diff --git a/include/mcld/Fragment/TargetFragment.h b/include/mcld/Fragment/TargetFragment.h
index 665fcea..76148ea 100644
--- a/include/mcld/Fragment/TargetFragment.h
+++ b/include/mcld/Fragment/TargetFragment.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_TARGET_FRAGMENT_H
-#define MCLD_LD_TARGET_FRAGMENT_H
+#ifndef MCLD_FRAGMENT_TARGETFRAGMENT_H
+#define MCLD_FRAGMENT_TARGETFRAGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/GeneralOptions.h b/include/mcld/GeneralOptions.h
index 77232ac..8348b6f 100644
--- a/include/mcld/GeneralOptions.h
+++ b/include/mcld/GeneralOptions.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_GENERAL_OPTIONS_H
-#define MCLD_GENERAL_OPTIONS_H
+#ifndef MCLD_GENERALOPTIONS_H
+#define MCLD_GENERALOPTIONS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -15,11 +15,11 @@
 #include <vector>
 #include <mcld/Support/RealPath.h>
 #include <mcld/Support/FileSystem.h>
-#include <mcld/MC/ZOption.h>
 
 namespace mcld {
 
 class Input;
+class ZOption;
 
 /** \class GeneralOptions
  *  \brief GeneralOptions collects the options that not be one of the
@@ -46,6 +46,10 @@
   typedef RpathList::iterator rpath_iterator;
   typedef RpathList::const_iterator const_rpath_iterator;
 
+  typedef std::vector<std::string> ScriptList;
+  typedef ScriptList::iterator script_iterator;
+  typedef ScriptList::const_iterator const_script_iterator;
+
   typedef std::vector<std::string> AuxiliaryList;
   typedef AuxiliaryList::iterator aux_iterator;
   typedef AuxiliaryList::const_iterator const_aux_iterator;
@@ -54,11 +58,6 @@
   GeneralOptions();
   ~GeneralOptions();
 
-  /// default link script
-  bool hasDefaultLDScript() const;
-  const char* defaultLDScript() const;
-  void setDefaultLDScript(const std::string& pFilename);
-
   /// trace
   void setTrace(bool pEnableTrace = true)
   { m_bTrace = pEnableTrace; }
@@ -84,15 +83,6 @@
   bool Bgroup() const
   { return m_Bgroup; }
 
-  bool hasEntry() const
-  { return !m_Entry.empty(); }
-
-  void setEntry(const std::string& pEntry)
-  { m_Entry = pEntry; }
-
-  const std::string& entry() const
-  { return m_Entry; }
-
   void setDyld(const std::string& pDyld)
   { m_Dyld = pDyld; }
 
@@ -132,10 +122,10 @@
   { return m_bColor; }
 
   void setNoUndefined(bool pEnable = true)
-  { m_bNoUndefined = pEnable; }
+  { m_NoUndefined = (pEnable?YES:NO); }
 
   void setMulDefs(bool pEnable = true)
-  { m_bMulDefs = pEnable; }
+  { m_MulDefs = (pEnable?YES:NO); }
 
   void setEhFrameHdr(bool pEnable = true)
   { m_bCreateEhFrameHdr = pEnable; }
@@ -146,8 +136,11 @@
   bool hasCombReloc() const
   { return m_bCombReloc; }
 
+  bool hasNoUndefined() const
+  { return (Unknown != m_NoUndefined); }
+
   bool isNoUndefined() const
-  { return m_bNoUndefined; }
+  { return (YES == m_NoUndefined); }
 
   bool hasStackSet() const
   { return (Unknown != m_ExecStack); }
@@ -165,7 +158,10 @@
   { return m_bLoadFltr; }
 
   bool hasMulDefs() const
-  { return m_bMulDefs; }
+  { return (Unknown != m_MulDefs); }
+
+  bool isMulDefs() const
+  { return (YES == m_MulDefs); }
 
   bool hasNoCopyReloc() const
   { return m_bNoCopyReloc; }
@@ -278,6 +274,26 @@
   bool printMap() const
   { return m_bPrintMap; }
 
+  void setWarnMismatch(bool pEnable = true)
+  { m_bWarnMismatch = pEnable; }
+
+  bool warnMismatch() const
+  { return m_bWarnMismatch; }
+
+  // --gc-sections
+  void setGCSections(bool pEnable = true)
+  { m_bGCSections = pEnable; }
+
+  bool GCSections() const
+  { return m_bGCSections; }
+
+  // --ld-generated-unwind-info
+  void setGenUnwindInfo(bool pEnable = true)
+  { m_bGenUnwindInfo = pEnable; }
+
+  bool genUnwindInfo() const
+  { return m_bGenUnwindInfo; }
+
   // -G, max GP size option
   void setGPSize(int gpsize)
   { m_GPSize = gpsize; }
@@ -299,6 +315,15 @@
   const_rpath_iterator rpath_end  () const { return m_RpathList.end();   }
   rpath_iterator       rpath_end  ()       { return m_RpathList.end();   }
 
+  // -----  link-in script  ----- //
+  const ScriptList& getScriptList() const { return m_ScriptList; }
+  ScriptList&       getScriptList()       { return m_ScriptList; }
+
+  const_script_iterator script_begin() const { return m_ScriptList.begin(); }
+  script_iterator       script_begin()       { return m_ScriptList.begin(); }
+  const_script_iterator script_end  () const { return m_ScriptList.end();   }
+  script_iterator       script_end  ()       { return m_ScriptList.end();   }
+
   // -----  filter and auxiliary filter  ----- //
   void setFilter(const std::string& pFilter)
   { m_Filter = pFilter; }
@@ -327,21 +352,20 @@
 private:
   Input* m_pDefaultBitcode;
   std::string m_DefaultLDScript;
-  std::string m_Entry;
   std::string m_Dyld;
   std::string m_SOName;
   int8_t m_Verbose;            // --verbose[=0,1,2]
   uint16_t m_MaxErrorNum;      // --error-limit=N
   uint16_t m_MaxWarnNum;       // --warning-limit=N
   status m_ExecStack;          // execstack, noexecstack
+  status m_NoUndefined;        // defs, --no-undefined
+  status m_MulDefs;            // muldefs, --allow-multiple-definition
   uint64_t m_CommPageSize;     // common-page-size=value
   uint64_t m_MaxPageSize;      // max-page-size=value
   bool m_bCombReloc     : 1;   // combreloc, nocombreloc
-  bool m_bNoUndefined   : 1;   // defs, --no-undefined
   bool m_bInitFirst     : 1;   // initfirst
   bool m_bInterPose     : 1;   // interpose
   bool m_bLoadFltr      : 1;   // loadfltr
-  bool m_bMulDefs       : 1;   // muldefs
   bool m_bNoCopyReloc   : 1;   // nocopyreloc
   bool m_bNoDefaultLib  : 1;   // nodefaultlib
   bool m_bNoDelete      : 1;   // nodelete
@@ -367,9 +391,13 @@
   bool m_bNewDTags: 1; // --enable-new-dtags
   bool m_bNoStdlib: 1; // -nostdlib
   bool m_bPrintMap: 1; // --print-map
+  bool m_bWarnMismatch: 1; // --no-warn-mismatch
+  bool m_bGCSections: 1; // --gc-sections
+  bool m_bGenUnwindInfo: 1; // --ld-generated-unwind-info
   uint32_t m_GPSize; // -G, --gpsize
   StripSymbolMode m_StripSymbols;
   RpathList m_RpathList;
+  ScriptList m_ScriptList;
   unsigned int m_HashStyle;
   std::string m_Filter;
   AuxiliaryList m_AuxiliaryList;
diff --git a/include/mcld/IRBuilder.h b/include/mcld/IRBuilder.h
index e9f1d13..7cacb36 100644
--- a/include/mcld/IRBuilder.h
+++ b/include/mcld/IRBuilder.h
@@ -14,7 +14,7 @@
 #ifndef MCLD_IRBUILDER_H
 #define MCLD_IRBUILDER_H
 
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/MC/InputBuilder.h>
 
 #include <mcld/LD/LDSection.h>
@@ -29,7 +29,6 @@
 
 #include <mcld/Support/Path.h>
 #include <mcld/Support/FileHandle.h>
-#include <mcld/Support/raw_mem_ostream.h>
 
 namespace mcld {
 
@@ -129,19 +128,6 @@
   Input* ReadInput(const std::string& pNameSpec);
 
   /// ReadInput - To read an input file and append it to the input tree.
-  ///
-  /// This function is like to add an input in the command line.
-  ///
-  /// LLVM compiler usually emits outputs by llvm::raw_ostream.
-  /// mcld::raw_mem_ostream inherits llvm::raw_ostream and is suitable to be
-  /// the output of LLVM compier. Users can connect LLVM compiler and MCLinker
-  /// by passing mcld::raw_mem_ostream from LLVM compiler to MCLinker.
-  ///
-  /// @param pMemOStream [in] The input raw_mem_stream
-  /// @param the create mcld::Input.
-  Input* ReadInput(raw_mem_ostream& pMemOStream);
-
-  /// ReadInput - To read an input file and append it to the input tree.
   /// Another way to open file manually. Use MCLinker's mcld::FileHandle.
   Input* ReadInput(FileHandle& pFileHandle);
 
@@ -470,6 +456,10 @@
                                    uint32_t pOffset,
                                    Relocation::Address pAddend = 0);
 
+  /// shouldForceLocal - The helper function for AddSymbol to check if the
+  /// symbols should be force to local symbols
+  bool shouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig);
+
 private:
   LDSymbol* addSymbolFromObject(const std::string& pName,
                                 ResolveInfo::Type pType,
diff --git a/include/mcld/InputTree.h b/include/mcld/InputTree.h
index 0c7e060..0213527 100644
--- a/include/mcld/InputTree.h
+++ b/include/mcld/InputTree.h
@@ -6,15 +6,15 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_INPUT_TREE_H
-#define MCLD_MC_INPUT_TREE_H
+#ifndef MCLD_INPUTTREE_H
+#define MCLD_INPUTTREE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
 #include <mcld/ADT/BinTree.h>
 #include <mcld/ADT/TypeTraits.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/Support/Path.h>
 
 #include <string>
@@ -182,16 +182,16 @@
   //  @param DIRECT the direction of the connecting edge of the parent node.
   //  @param position the parent node
   //  @param value the value being pushed.
-  template<size_t DIRECT, class Pos>
-  BinaryTree& join(Pos position, const Input& value) {
+  template<size_t DIRECT>
+  BinaryTree& join(TreeIteratorBase& pPosition, const Input& value) {
     node_type *node = BinaryTreeBase<Input>::createNode();
     node->data = const_cast<Input*>(&value);
-    if (position.isRoot())
-      proxy::hook<TreeIteratorBase::Leftward>(position.m_pNode,
-                          const_cast<const node_type*>(node));
+
+    if (pPosition.isRoot())
+      pPosition.hook<TreeIteratorBase::Leftward>(node);
     else
-      proxy::hook<DIRECT>(position.m_pNode,
-                          const_cast<const node_type*>(node));
+      pPosition.hook<DIRECT>(node);
+
     return *this;
   }
 
@@ -200,14 +200,13 @@
   //  @param position the parent node
   //  @param the tree being joined.
   //  @return the joined tree
-  template<size_t DIRECT, class Pos>
-  BinaryTree& merge(Pos position, BinaryTree& pTree) {
+  template<size_t DIRECT>
+  BinaryTree& merge(TreeIteratorBase& pPosition, BinaryTree& pTree) {
     if (this == &pTree)
       return *this;
 
     if (!pTree.empty()) {
-      proxy::hook<DIRECT>(position.m_pNode,
-                        const_cast<const NodeBase*>(pTree.m_Root.node.left));
+      pPosition.hook<DIRECT>(pTree.m_Root.node.left);
       BinaryTreeBase<Input>::m_Root.summon(
                                    pTree.BinaryTreeBase<Input>::m_Root);
       BinaryTreeBase<Input>::m_Root.delegate(pTree.m_Root);
@@ -248,20 +247,20 @@
    *  connects two nodes of the given iterators togather.
    */
   struct Mover {
-    virtual ~Mover() {}
-    virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const = 0;
+    virtual void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const = 0;
     virtual void move(TreeIteratorBase& pNode) const = 0;
+    virtual ~Mover() { }
   };
 
   /** \class Succeeder
    *  \brief class Succeeder moves the iterator afterward.
    */
   struct Succeeder : public Mover {
-    virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const {
-      proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
+    void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const {
+      pFrom.hook<Positional>(pTo);
     }
 
-    virtual void move(TreeIteratorBase& pNode) const {
+    void move(TreeIteratorBase& pNode) const {
       pNode.move<Positional>();
     }
   };
@@ -270,11 +269,11 @@
    *  \brief class Includer moves the iterator downward.
    */
   struct Includer : public Mover {
-    virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const {
-      proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
+    void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const {
+      pFrom.hook<Inclusive>(pTo);
     }
 
-    virtual void move(TreeIteratorBase& pNode) const {
+    void move(TreeIteratorBase& pNode) const {
       pNode.move<Inclusive>();
     }
   };
@@ -325,12 +324,12 @@
 mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot)
 {
   BinTreeTy::node_type* node = createNode();
+
   if (pRoot.isRoot())
-    proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
-        const_cast<const node_type*>(node));
+    pRoot.hook<TreeIteratorBase::Leftward>(node);
   else
-    proxy::hook<DIRECT>(pRoot.m_pNode,
-        const_cast<const node_type*>(node));
+    pRoot.hook<DIRECT>(node);
+
   return *this;
 }
 
@@ -340,12 +339,12 @@
 {
   BinTreeTy::node_type* node = createNode();
   node->data = &pInput;
+
   if (pRoot.isRoot())
-    proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
-                                         const_cast<const node_type*>(node));
+    pRoot.hook<TreeIteratorBase::Leftward>(node);
   else
-    proxy::hook<DIRECT>(pRoot.m_pNode,
-                        const_cast<const node_type*>(node));
+    pRoot.hook<DIRECT>(node);
+
   return *this;
 }
 
diff --git a/include/mcld/LD/Archive.h b/include/mcld/LD/Archive.h
index 7dc2205..26de7c3 100644
--- a/include/mcld/LD/Archive.h
+++ b/include/mcld/LD/Archive.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ARCHIVE_H
-#define MCLD_ARCHIVE_H
+#ifndef MCLD_LD_ARCHIVE_H
+#define MCLD_LD_ARCHIVE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -26,9 +26,6 @@
 class Input;
 class InputFactory;
 class InputBuilder;
-class AttributeFactory;
-class ContextFactory;
-class MemoryAreaFactory;
 
 /** \class Archive
  *  \brief This class define the interfacee to Archive files
@@ -40,6 +37,7 @@
   static const char   THIN_MAGIC[];        ///< magic of thin archive
   static const size_t MAGIC_LEN;           ///< length of magic string
   static const char   SVR4_SYMTAB_NAME[];  ///< SVR4 symtab entry name
+  static const char   IRIX6_SYMTAB_NAME[]; ///< Irix6 symtab entry name
   static const char   STRTAB_NAME[];       ///< Name of string table
   static const char   PAD[];               ///< inter-file align padding
   static const char   MEMBER_MAGIC[];      ///< fmag field magic #
@@ -98,7 +96,7 @@
 
 public:
   typedef HashTable<ArchiveMemberEntryType,
-                    hash::StringHash<hash::ELF>,
+                    hash::StringHash<hash::DJB>,
                     EntryFactory<ArchiveMemberEntryType> > ArchiveMemberMapType;
 
   struct Symbol
diff --git a/include/mcld/LD/ArchiveReader.h b/include/mcld/LD/ArchiveReader.h
index 5f24f49..eb6bec5 100644
--- a/include/mcld/LD/ArchiveReader.h
+++ b/include/mcld/LD/ArchiveReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ARCHIVE_READER_INTERFACE_H
-#define MCLD_ARCHIVE_READER_INTERFACE_H
+#ifndef MCLD_LD_ARCHIVEREADER_H
+#define MCLD_LD_ARCHIVEREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -16,6 +16,7 @@
 namespace mcld
 {
 
+class LinkerConfig;
 class Archive;
 
 /** \class ArchiveReader
@@ -34,7 +35,7 @@
   ArchiveReader();
   virtual ~ArchiveReader();
 
-  virtual bool readArchive(Archive& pArchive) = 0;
+  virtual bool readArchive(const LinkerConfig& pConfig, Archive& pArchive) = 0;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/BSDArchiveReader.h b/include/mcld/LD/BSDArchiveReader.h
index 7abeecc..fd49966 100644
--- a/include/mcld/LD/BSDArchiveReader.h
+++ b/include/mcld/LD/BSDArchiveReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_BSD_ARCHIVE_READER_H
-#define MCLD_BSD_ARCHIVE_READER_H
+#ifndef MCLD_LD_BSDARCHIVEREADER_H
+#define MCLD_LD_BSDARCHIVEREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -18,6 +18,7 @@
 
 class Input;
 class Archive;
+class LinkerConfig;
 
 /** \class BSDArchiveReader
  *  \brief BSDArchiveReader reads BSD-variant archive files.
@@ -29,8 +30,8 @@
   BSDArchiveReader();
   ~BSDArchiveReader();
 
-  bool readArchive(Archive& pArchive);
-  bool isMyFormat(Input& pInput) const;
+  bool readArchive(const LinkerConfig& pConfig, Archive& pArchive);
+  bool isMyFormat(Input& pInput, bool &pContinue) const;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/BinaryReader.h b/include/mcld/LD/BinaryReader.h
index e9c47db..6b61dba 100644
--- a/include/mcld/LD/BinaryReader.h
+++ b/include/mcld/LD/BinaryReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_Binary_READER_H
-#define MCLD_Binary_READER_H
+#ifndef MCLD_LD_BINARYREADER_H
+#define MCLD_LD_BINARYREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -25,16 +25,11 @@
  */
 class BinaryReader : public LDReader
 {
-protected:
-  BinaryReader()
-  { }
-
 public:
-  virtual ~BinaryReader()
-  { }
+  virtual ~BinaryReader() = 0;
 
-  virtual bool isMyFormat(Input& pInput) const
-  { return true; }
+  virtual bool isMyFormat(Input& pInput, bool &pContinue) const
+  { pContinue = true; return false; }
 
   virtual bool readBinary(Input& pFile) = 0;
 };
diff --git a/include/mcld/LD/BranchIsland.h b/include/mcld/LD/BranchIsland.h
index f340f0a..ca1543f 100644
--- a/include/mcld/LD/BranchIsland.h
+++ b/include/mcld/LD/BranchIsland.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_BRANCH_ISLAND_H
-#define MCLD_LD_BRANCH_ISLAND_H
+#ifndef MCLD_LD_BRANCHISLAND_H
+#define MCLD_LD_BRANCHISLAND_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -125,7 +125,7 @@
       size_t operator() (const Key& KEY) const
       {
         llvm::StringRef sym_name(KEY.symbol()->name());
-        hash::StringHash<hash::ELF> str_hasher;
+        hash::StringHash<hash::DJB> str_hasher;
         return (size_t((uintptr_t)KEY.prototype())) ^
                str_hasher(sym_name) ^
                KEY.addend();
diff --git a/include/mcld/LD/BranchIslandFactory.h b/include/mcld/LD/BranchIslandFactory.h
index 755cc31..9431fb3 100644
--- a/include/mcld/LD/BranchIslandFactory.h
+++ b/include/mcld/LD/BranchIslandFactory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_BRANCH_ISLAND_FACTORY_H
-#define MCLD_LD_BRANCH_ISLAND_FACTORY_H
+#ifndef MCLD_LD_BRANCHISLANDFACTORY_H
+#define MCLD_LD_BRANCHISLANDFACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -20,6 +20,7 @@
 {
 
 class Fragment;
+class Module;
 
 /** \class BranchIslandFactory
  *  \brief
@@ -37,6 +38,10 @@
 
   ~BranchIslandFactory();
 
+  /// group - group fragments and create islands when needed
+  /// @param pSectionData - the SectionData holds fragments need to be grouped
+  void group(Module& pModule);
+
   /// produce - produce a island for the given fragment
   /// @param pFragment - the fragment needs a branch island
   BranchIsland* produce(Fragment& pFragment);
diff --git a/include/mcld/LD/DWARFLineInfo.h b/include/mcld/LD/DWARFLineInfo.h
index 004d597..4f19312 100644
--- a/include/mcld/LD/DWARFLineInfo.h
+++ b/include/mcld/LD/DWARFLineInfo.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_DWARF_LINE_INFO_H
-#define MCLD_DWARF_LINE_INFO_H
+#ifndef MCLD_LD_DWARFLINEINFO_H
+#define MCLD_LD_DWARFLINEINFO_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/DiagAttribute.inc b/include/mcld/LD/DiagAttribute.inc
new file mode 100644
index 0000000..453ae65
--- /dev/null
+++ b/include/mcld/LD/DiagAttribute.inc
@@ -0,0 +1,19 @@
+// General
+DIAG(warn_unsupported_attribute_section_format, DiagnosticEngine::Warning, "unsupported format of attribute section in input %0 (version=%1).", "unsupported format of attribute section in input %0 (version=%1).")
+DIAG(warn_unrecognized_vendor_subsection, DiagnosticEngine::Warning, "skip unrecognized private vendor subsection with name '%0' in %1.", "skip unrecognized private vendor subsection with name '%0' in %1.")
+
+// ARM attributes
+DIAG(error_unknown_cpu_arch, DiagnosticEngine::Error, "input %0 has unknown CPU architecture profile.", "input %0 has unknown CPU architecture profile.")
+DIAG(warn_mismatch_cpu_arch_profile, DiagnosticEngine::Warning, "conflicting architecture profiles %0 in %1.", "conflicting architecture profiles %0 in %1.")
+DIAG(error_mismatch_mpextension_use, DiagnosticEngine::Error, "conflicting values from Tag_MPextension_use and Tag_MPextension_use_legacy in %0", "conflicting values from Tag_MPextension_use and Tag_MPextension_use_legacy in %0")
+DIAG(warn_mismatch_enum_size, DiagnosticEngine::Warning, "the size of enumerated data item in input %0 (value=%1) is not compatible with the output (value=%2).", "the size of enumerated data item in input %0 (value=%1) is not compatible with the output (value=%2).")
+DIAG(warn_mismatch_fp16_format, DiagnosticEngine::Warning, "conflicting 16-bit FP number format in %0", "conflicting 16-bit FP number format in %0")
+DIAG(warn_unrecognized_virtualization_use, DiagnosticEngine::Warning, "value of Tag_Virtualization_use cannot be recognized in %0 (value=%1).", "value of Tag_Virtualization_use cannot be recognized in %0 (value=%1).")
+DIAG(warn_mismatch_abi_wmmx_args, DiagnosticEngine::Warning, "%0 uses different way to pass WMMX parameters and results.", "%0 uses different way to pass WMMX parameters and results.")
+DIAG(warn_mismatch_pcs_config, DiagnosticEngine::Warning, "conflicting procedure call standard config in input %0.", "conflicting procedure call standard config in input %0.")
+DIAG(warn_mismatch_r9_use, DiagnosticEngine::Warning, "conflicting way to use R9 in input %0.", "conflicting way to use R9 in input %0.")
+DIAG(warn_conflict_rw_data_and_r9, DiagnosticEngine::Warning, "RW static data addressing (SB-relative) conflicts the use of R9 (Tag_ABI_PCS_R9_use) in input %0.", "RW static data addressing (SB-relative) conflicts the use of R9 (Tag_ABI_PCS_R9_use) in input %0.")
+DIAG(warn_mismatch_wchar_size, DiagnosticEngine::Warning, "incompatible size of wchar_t in input %0 (value=%1) with the output (value=%2).", "incompatible size of wchar_t in input %0 (value=%1) with the output (value=%2).")
+DIAG(warn_unknown_mandatory_attribute, DiagnosticEngine::Warning, "unknown mandatory attribute with tag %0 was ignored in %1.", "unknown mandatory attribute with tag %0 was ignored in %1.")
+DIAG(warn_unknown_attribute, DiagnosticEngine::Warning, "unknown attribute with tag %0 was ignored in %1.", "unknown attribute with tag %0 was ignored in %1.")
+DIAG(warn_mismatch_vfp_args, DiagnosticEngine::Warning, "%0 uses different way to pass the floating point parameter and results.", "%0 uses different way to pass the floating point parameter and results.")
diff --git a/include/mcld/LD/DiagCommonKinds.inc b/include/mcld/LD/DiagCommonKinds.inc
index e7d6328..539eafb 100644
--- a/include/mcld/LD/DiagCommonKinds.inc
+++ b/include/mcld/LD/DiagCommonKinds.inc
@@ -3,7 +3,7 @@
 DIAG(warn_cannot_open_search_dir, DiagnosticEngine::Warning, "can not open search directory `-L%0'", "can not open search directory `-L%0'")
 DIAG(err_no_inputs, DiagnosticEngine::Error, "no inputs", "no inputs")
 DIAG(err_empty_input, DiagnosticEngine::Error, "Empty input file `%0' : %1", "Empty input file `%0' : %1")
-DIAG(err_unrecognized_input_file, DiagnosticEngine::Fatal, "cannot recognize the format of file `%0'.\n  object format or given target machine (%1) is wrong.","cannot recognize the format of file `%0'.\n  object format or given target machine (%1) is wrong.")
+DIAG(warn_unrecognized_input_file, DiagnosticEngine::Warning, "cannot recognize the format of file `%0'.\n  object format or given target machine (%1) is incompatible.","cannot recognize the format of file `%0'.\n  object format or given target machine (%1) is incompatible.")
 DIAG(err_cannot_find_namespec, DiagnosticEngine::Fatal, "cannot recognize namespec -l%0", "cannot recognize namespec -l%0")
 DIAG(err_cannot_identify_option, DiagnosticEngine::Fatal, "unknown command line argument `%0' at %1", "unknown command line argument `%0' at %1")
 DIAG(err_mixed_shared_static_objects, DiagnosticEngine::Error, "cannot link shared objects with -static option.\nShared object `%0': %1", "cannot link shared objects with -static option.\nShared object `%0': %1")
@@ -40,7 +40,7 @@
 DIAG(fatal_cannot_init_target, DiagnosticEngine::Fatal, "Cannot initialize mcld::Target for given triple '%0'.\n(Detail: %1)", "Cannot initialize mcld::Target for given triple '%0'.\n(Detail: %1)")
 DIAG(fatal_cannot_init_lineinfo, DiagnosticEngine::Fatal, "Cannot initialize mcld::DiagnosticLineInfo for given triple '%0'", "Cannot initialize mcld::DiagnosticLineInfo for given triple '%0'")
 DIAG(fatal_cannot_init_backend, DiagnosticEngine::Fatal, "Cannot initialize mcld::TargetLDBackend for given triple '%0'.", "Cannot initialize mcld::TargetLDBackend for given triple '%0'.")
-DIAG(fatal_forbid_nest_group, DiagnosticEngine::Fatal, "May not nest groups", "May not nest groups")
+DIAG(fatal_forbid_nest_group, DiagnosticEngine::Fatal, "not matched --start-group and --end-group", "not matched --start-group and --end-group")
 DIAG(fatal_unwritable_output, DiagnosticEngine::Fatal, "unable to write output file %0", "unable to write output file %0")
 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.")
@@ -48,3 +48,6 @@
 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")
 DIAG(err_invalid_emulation, DiagnosticEngine::Error, "Invalid target emulation: `%0'.", "Invalid target emulation: `%0'.")
+DIAG(err_cannot_find_scriptfile, DiagnosticEngine::Fatal, "cannot open %0 file %1", "cannot open %0 file %1")
+DIAG(err_unsupported_archive, DiagnosticEngine::Error, "Unsupported archive type.", "Unsupported archive type.")
+DIAG(unexpected_frag_type, DiagnosticEngine::Unreachable, "Unexpected fragment type `%0' when constructing FG", "Unexpected fragment type `%0' when constructing FG")
diff --git a/include/mcld/LD/DiagLDScript.inc b/include/mcld/LD/DiagLDScript.inc
new file mode 100644
index 0000000..c752773
--- /dev/null
+++ b/include/mcld/LD/DiagLDScript.inc
@@ -0,0 +1,3 @@
+DIAG(err_unterminated_comment, DiagnosticEngine::Error, "%0:%1:%2: error: unterminated comment\n", "%0:%1:%2: error: unterminated comment\n")
+DIAG(err_syntax_error, DiagnosticEngine::Error, "%0:%1:%2: error: %3\n", "%0:%1:%2: error: %3\n")
+DIAG(err_assert_failed, DiagnosticEngine::Error,"Assertion failed: %0\n", "Assertion failed: %0\n")
diff --git a/include/mcld/LD/DiagRelocations.inc b/include/mcld/LD/DiagRelocations.inc
index 7ada05f..bacae6e 100644
--- a/include/mcld/LD/DiagRelocations.inc
+++ b/include/mcld/LD/DiagRelocations.inc
@@ -1,6 +1,7 @@
 DIAG(reloc_factory_has_not_config, DiagnosticEngine::Fatal, "Please call mcld::Linker::config before creating relocations", "Please call mcld::Linker::config before creating relocations")
 DIAG(unsupported_bitclass, DiagnosticEngine::Fatal, "Only supports 32 and 64 bits targets. (Target: %0, bitclass:%1)", "Only supports 32 and 64 bits targets. (Target: %0, bitclass:%1)")
-DIAG(undefined_reference, DiagnosticEngine::Fatal, "undefined reference to `%0'", "In %1:%2, variable %0 must be defined")
+DIAG(undefined_reference, DiagnosticEngine::Fatal, "%1(%2+%3): undefined reference to `%0'", "%1(%2+%3): undefined reference to `%0'")
+DIAG(undefined_reference_text, DiagnosticEngine::Fatal, "%1:%2:function %3: undefined reference to `%0'", "%1:%2: undefined reference to `%0'")
 DIAG(non_pic_relocation, DiagnosticEngine::Error, "attempt to generate unsupported relocation type `%0' for symbol `%1', recompile with -fPIC", "attempt to generate unsupported relocation type `%0' for symbol `%1, recompile with -fPIC")
 DIAG(base_relocation, DiagnosticEngine::Fatal, "relocation type `%0' is not supported for symbol `%1'\nPlease report to %2", "relocation type `%0' is not supported for symbol `%1'\nPlease report to %2")
 DIAG(dynamic_relocation, DiagnosticEngine::Fatal, "unexpected relocation type `%0' in object file", "unexpected relocation type `%0' in object file")
@@ -11,3 +12,4 @@
 DIAG(result_badreloc, DiagnosticEngine::Error, "applying relocation `%0' encounters unexpected opcode on symbol `%1'","applying relocation `%0' encounters unexpected opcode on symbol `%1'")
 DIAG(invalid_tls, DiagnosticEngine::Error, "TLS relocation against invalid symbol `%0' in section `%1'", "TLS relocation against invalid symbol `%0' in section `%1'")
 DIAG(unknown_reloc_section_type, DiagnosticEngine::Unreachable, "unknown relocation section type: `%0' in section `%1'", "unknown relocation section type: `%0' in section `%1'")
+DIAG(unsupport_cond_branch_reloc, DiagnosticEngine::Error, "applying relocation `%0', conditional branch to PLT in THUMB-2 not supported yet", "applying relocation `%0', conditional branch to PLT in THUMB-2 not supported yet")
diff --git a/include/mcld/LD/DiagSymbolResolutions.inc b/include/mcld/LD/DiagSymbolResolutions.inc
index 786eb4b..04113dc 100644
--- a/include/mcld/LD/DiagSymbolResolutions.inc
+++ b/include/mcld/LD/DiagSymbolResolutions.inc
@@ -8,3 +8,4 @@
 DIAG(indirect_refer_to_inexist, DiagnosticEngine::Fatal, "indirect symbol %0 points to a undefined symbol", "variable %0 is undefined")
 DIAG(multiple_definitions, DiagnosticEngine::Error, "multiple definition of symbol `%0'", "you define variable %0 twice")
 DIAG(undefined_situation, DiagnosticEngine::Unreachable, "reach undefined situation, action: %0, old(%1) -> new(%2)", "reach undefined situation, action: %0, old(%1) -> new(%2)")
+DIAG(multiple_absolute_definitions, DiagnosticEngine::Error, "inconsistent definitions of absolute symbol `%0': old(%1) -> new(%2)", "you defined an absolute symbol with different values")
diff --git a/include/mcld/LD/Diagnostic.h b/include/mcld/LD/Diagnostic.h
index 2e4db11..1982ef0 100644
--- a/include/mcld/LD/Diagnostic.h
+++ b/include/mcld/LD/Diagnostic.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTIC_H
-#define MCLD_DIAGNOSTIC_H
+#ifndef MCLD_LD_DIAGNOSTIC_H
+#define MCLD_LD_DIAGNOSTIC_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/DiagnosticEngine.h b/include/mcld/LD/DiagnosticEngine.h
index 1c825a2..b003955 100644
--- a/include/mcld/LD/DiagnosticEngine.h
+++ b/include/mcld/LD/DiagnosticEngine.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTIC_ENGINE_H
-#define MCLD_DIAGNOSTIC_ENGINE_H
+#ifndef MCLD_LD_DIAGNOSTICENGINE_H
+#define MCLD_LD_DIAGNOSTICENGINE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/DiagnosticInfos.h b/include/mcld/LD/DiagnosticInfos.h
index cb9bdbd..16ebbab 100644
--- a/include/mcld/LD/DiagnosticInfos.h
+++ b/include/mcld/LD/DiagnosticInfos.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTIC_INFORMATION_H
-#define MCLD_DIAGNOSTIC_INFORMATION_H
+#ifndef MCLD_LD_DIAGNOSTICINFORMATION_H
+#define MCLD_LD_DIAGNOSTICINFORMATION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -18,12 +18,14 @@
 namespace diag {
   enum ID {
 #define DIAG(ENUM, CLASS, ADDRMSG, LINEMSG) ENUM,
+#include "mcld/LD/DiagAttribute.inc"
 #include "mcld/LD/DiagCommonKinds.inc"
 #include "mcld/LD/DiagReaders.inc"
 #include "mcld/LD/DiagSymbolResolutions.inc"
 #include "mcld/LD/DiagRelocations.inc"
 #include "mcld/LD/DiagLayouts.inc"
 #include "mcld/LD/DiagGOTPLT.inc"
+#include "mcld/LD/DiagLDScript.inc"
 #undef DIAG
     NUM_OF_BUILDIN_DIAGNOSTIC_INFO
   };
diff --git a/include/mcld/LD/DiagnosticLineInfo.h b/include/mcld/LD/DiagnosticLineInfo.h
index 30f0546..db35287 100644
--- a/include/mcld/LD/DiagnosticLineInfo.h
+++ b/include/mcld/LD/DiagnosticLineInfo.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTICLINEINFO_H
-#define MCLD_DIAGNOSTICLINEINFO_H
+#ifndef MCLD_LD_DIAGNOSTICLINEINFO_H
+#define MCLD_LD_DIAGNOSTICLINEINFO_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/DiagnosticPrinter.h b/include/mcld/LD/DiagnosticPrinter.h
index b3617a7..7cf5c8e 100644
--- a/include/mcld/LD/DiagnosticPrinter.h
+++ b/include/mcld/LD/DiagnosticPrinter.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTIC_PRINTER_H
-#define MCLD_DIAGNOSTIC_PRINTER_H
+#ifndef MCLD_LD_DIAGNOSTICPRINTER_H
+#define MCLD_LD_DIAGNOSTICPRINTER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/DynObjFileFormat.h b/include/mcld/LD/DynObjFileFormat.h
index 7b1626d..e0972c3 100644
--- a/include/mcld/LD/DynObjFileFormat.h
+++ b/include/mcld/LD/DynObjFileFormat.h
@@ -1,4 +1,4 @@
-//===- header.h -----------------------------------------------------------===//
+//===- DynObjFileFormat.h -------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef DYNOBJFORMAT_H
-#define DYNOBJFORMAT_H
+#ifndef MCLD_LD_DYNOBJFILEFORMAT_H
+#define MCLD_LD_DYNOBJFILEFORMAT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/DynObjReader.h b/include/mcld/LD/DynObjReader.h
index ddc9500..8a7a6be 100644
--- a/include/mcld/LD/DynObjReader.h
+++ b/include/mcld/LD/DynObjReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_DYNAMIC_SHARED_OBJECT_READER_H
-#define MCLD_DYNAMIC_SHARED_OBJECT_READER_H
+#ifndef MCLD_LD_DYNOBJREADER_H
+#define MCLD_LD_DYNOBJREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/ELFBinaryReader.h b/include/mcld/LD/ELFBinaryReader.h
index fc3a067..9da4535 100644
--- a/include/mcld/LD/ELFBinaryReader.h
+++ b/include/mcld/LD/ELFBinaryReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_Binary_READER_H
-#define MCLD_ELF_Binary_READER_H
+#ifndef MCLD_LD_ELFBINARYREADER_H
+#define MCLD_LD_ELFBINARYREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -19,7 +19,6 @@
 class Module;
 class Input;
 class IRBuilder;
-class GNULDBackend;
 class LinkerConfig;
 
 /** \lclass ELFBinaryReader
@@ -28,16 +27,15 @@
 class ELFBinaryReader : public BinaryReader
 {
 public:
-  ELFBinaryReader(GNULDBackend& pBackend,
-                  IRBuilder& pBuilder,
-                  const LinkerConfig& pConfig);
+  ELFBinaryReader(IRBuilder& pBuilder, const LinkerConfig& pConfig);
 
   ~ELFBinaryReader();
 
-  virtual bool readBinary(Input& pInput);
+  bool isMyFormat(Input& pInput, bool &pContinue) const;
+
+  bool readBinary(Input& pInput);
 
 private:
-  GNULDBackend& m_Backend;
   IRBuilder& m_Builder;
   const LinkerConfig& m_Config;
 };
diff --git a/include/mcld/LD/ELFDynObjFileFormat.h b/include/mcld/LD/ELFDynObjFileFormat.h
index 2ee97a6..dd9cbb9 100644
--- a/include/mcld/LD/ELFDynObjFileFormat.h
+++ b/include/mcld/LD/ELFDynObjFileFormat.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_DYNAMIC_OBJECT_FILE_FROMAT_H
-#define MCLD_ELF_DYNAMIC_OBJECT_FILE_FROMAT_H
+#ifndef MCLD_LD_ELFDYNOBJFILEFROMAT_H
+#define MCLD_LD_ELFDYNOBJFILEFROMAT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/ELFDynObjReader.h b/include/mcld/LD/ELFDynObjReader.h
index f6d2067..23b96ad 100644
--- a/include/mcld/LD/ELFDynObjReader.h
+++ b/include/mcld/LD/ELFDynObjReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_DYNAMIC_SHARED_OBJECT_READER_H
-#define MCLD_ELF_DYNAMIC_SHARED_OBJECT_READER_H
+#ifndef MCLD_LD_ELFDYNOBJREADER_H
+#define MCLD_LD_ELFDYNOBJREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -35,7 +35,7 @@
   ~ELFDynObjReader();
 
   // -----  observers  ----- //
-  bool isMyFormat(Input &pFile) const;
+  bool isMyFormat(Input &pFile, bool &pContinue) const;
 
   // -----  readers  ----- //
   bool readHeader(Input& pFile);
diff --git a/include/mcld/LD/ELFObjectReader.h b/include/mcld/LD/ELFObjectReader.h
index 27e4489..a124676 100644
--- a/include/mcld/LD/ELFObjectReader.h
+++ b/include/mcld/LD/ELFObjectReader.h
@@ -46,7 +46,7 @@
   ~ELFObjectReader();
 
   // -----  observers  ----- //
-  bool isMyFormat(Input &pFile) const;
+  bool isMyFormat(Input &pFile, bool &pContinue) const;
 
   // -----  readers  ----- //
   bool readHeader(Input& pFile);
diff --git a/include/mcld/LD/ELFObjectWriter.h b/include/mcld/LD/ELFObjectWriter.h
index 12a5842..9caa76a 100644
--- a/include/mcld/LD/ELFObjectWriter.h
+++ b/include/mcld/LD/ELFObjectWriter.h
@@ -6,18 +6,20 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_OBJECT_WRITER_H
-#define MCLD_ELF_OBJECT_WRITER_H
+#ifndef MCLD_LD_ELFOBJWRITER_H
+#define MCLD_LD_ELFOBJWRITER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <mcld/LD/ObjectWriter.h>
 #include <cassert>
 
+#include <mcld/Support/FileOutputBuffer.h>
 #include <llvm/Support/system_error.h>
 
 namespace mcld {
 
+class EhFrame;
 class Module;
 class LinkerConfig;
 class GNULDBackend;
@@ -27,8 +29,6 @@
 class SectionData;
 class RelocData;
 class Output;
-class MemoryRegion;
-class MemoryArea;
 
 /** \class ELFObjectWriter
  *  \brief ELFObjectWriter writes the target-independent parts of object files.
@@ -42,10 +42,13 @@
 
   ~ELFObjectWriter();
 
-  llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput);
+  llvm::error_code writeObject(Module& pModule, FileOutputBuffer& pOutput);
+
+  size_t getOutputSize(const Module& pModule) const;
 
 private:
-  void writeSection(MemoryArea& pOutput, LDSection *section);
+  void writeSection(Module& pModule,
+                    FileOutputBuffer& pOutput, LDSection *section);
 
   GNULDBackend&       target()        { return m_Backend; }
 
@@ -55,7 +58,7 @@
   template<size_t SIZE>
   void writeELFHeader(const LinkerConfig& pConfig,
                       const Module& pModule,
-                      MemoryArea& pOutput) const;
+                      FileOutputBuffer& pOutput) const;
 
   uint64_t getEntryPoint(const LinkerConfig& pConfig,
                          const Module& pModule) const;
@@ -64,19 +67,21 @@
   template<size_t SIZE>
   void emitSectionHeader(const Module& pModule,
                          const LinkerConfig& pConfig,
-                         MemoryArea& pOutput) const;
+                         FileOutputBuffer& pOutput) const;
 
   // emitProgramHeader - emit ElfXX_Phdr
   template<size_t SIZE>
-  void emitProgramHeader(MemoryArea& pOutput) const;
+  void emitProgramHeader(FileOutputBuffer& pOutput) const;
 
   // emitShStrTab - emit .shstrtab
   void emitShStrTab(const LDSection& pShStrTab,
                     const Module& pModule,
-                    MemoryArea& pOutput);
+                    FileOutputBuffer& pOutput);
 
-  void emitSectionData(const LDSection& pSection,
-                       MemoryRegion& pRegion) const;
+  void emitSectionData(const LDSection& pSection, MemoryRegion& pRegion) const;
+
+  void emitEhFrame(Module& pModule,
+                   EhFrame& pFrame, MemoryRegion& pRegion) const;
 
   void emitRelocation(const LinkerConfig& pConfig,
                       const LDSection& pSection,
diff --git a/include/mcld/LD/ELFReader.h b/include/mcld/LD/ELFReader.h
index 9df21d3..6750ebd 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_H
-#define MCLD_ELF_READER_H
+#ifndef MCLD_LD_ELFREADER_H
+#define MCLD_LD_ELFREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -20,8 +20,6 @@
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MemoryArea.h>
 
 namespace mcld {
 
@@ -60,19 +58,19 @@
   { return sizeof(ELFHeader); }
 
   /// isELF - is this a ELF file
-  bool isELF(void* pELFHeader) const;
+  bool isELF(const void* pELFHeader) const;
 
   /// isMyEndian - is this ELF file in the same endian to me?
-  bool isMyEndian(void* pELFHeader) const;
+  bool isMyEndian(const void* pELFHeader) const;
 
   /// isMyMachine - is this ELF file generated for the same machine.
-  bool isMyMachine(void* pELFHeader) const;
+  bool isMyMachine(const void* pELFHeader) const;
 
   /// fileType - the file type of this file
-  Input::Type fileType(void* pELFHeader) const;
+  Input::Type fileType(const void* pELFHeader) const;
 
   /// readSectionHeaders - read ELF section header table and create LDSections
-  bool readSectionHeaders(Input& pInput, void* pELFHeader) const;
+  bool readSectionHeaders(Input& pInput, const void* pELFHeader) const;
 
   /// readRegularSection - read a regular section and create fragments.
   bool readRegularSection(Input& pInput, SectionData& pSD) const;
@@ -80,24 +78,24 @@
   /// readSymbols - read ELF symbols and create LDSymbol
   bool readSymbols(Input& pInput,
                    IRBuilder& pBuilder,
-                   const MemoryRegion& pRegion,
+                   llvm::StringRef 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;
+                             LDSection& pSymTab,
+                             uint32_t pSymIdx) const;
 
   /// readRela - read ELF rela and create Relocation
   bool readRela(Input& pInput,
                 LDSection& pSection,
-                const MemoryRegion& pRegion) const;
+                llvm::StringRef pRegion) const;
 
   /// readRel - read ELF rel and create Relocation
   bool readRel(Input& pInput,
                LDSection& pSection,
-               const MemoryRegion& pRegion) const;
+               llvm::StringRef pRegion) const;
 
   /// readDynamic - read ELF .dynamic in input dynobj
   bool readDynamic(Input& pInput) const;
@@ -150,19 +148,19 @@
   { return sizeof(ELFHeader); }
 
   /// isELF - is this a ELF file
-  bool isELF(void* pELFHeader) const;
+  bool isELF(const void* pELFHeader) const;
 
   /// isMyEndian - is this ELF file in the same endian to me?
-  bool isMyEndian(void* pELFHeader) const;
+  bool isMyEndian(const void* pELFHeader) const;
 
   /// isMyMachine - is this ELF file generated for the same machine.
-  bool isMyMachine(void* pELFHeader) const;
+  bool isMyMachine(const void* pELFHeader) const;
 
   /// fileType - the file type of this file
-  Input::Type fileType(void* pELFHeader) const;
+  Input::Type fileType(const void* pELFHeader) const;
 
   /// readSectionHeaders - read ELF section header table and create LDSections
-  bool readSectionHeaders(Input& pInput, void* pELFHeader) const;
+  bool readSectionHeaders(Input& pInput, const void* pELFHeader) const;
 
   /// readRegularSection - read a regular section and create fragments.
   bool readRegularSection(Input& pInput, SectionData& pSD) const;
@@ -170,24 +168,24 @@
   /// readSymbols - read ELF symbols and create LDSymbol
   bool readSymbols(Input& pInput,
                    IRBuilder& pBuilder,
-                   const MemoryRegion& pRegion,
+                   llvm::StringRef 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;
+                             LDSection& pSymTab,
+                             uint32_t pSymIdx) const;
 
   /// readRela - read ELF rela and create Relocation
   bool readRela(Input& pInput,
                 LDSection& pSection,
-                const MemoryRegion& pRegion) const;
+                llvm::StringRef pRegion) const;
 
   /// readRel - read ELF rel and create Relocation
   bool readRel(Input& pInput,
                LDSection& pSection,
-               const MemoryRegion& pRegion) const;
+               llvm::StringRef pRegion) const;
 
   /// readDynamic - read ELF .dynamic in input dynobj
   bool readDynamic(Input& pInput) const;
diff --git a/include/mcld/LD/ELFReaderIf.h b/include/mcld/LD/ELFReaderIf.h
index 245b542..0ce5992 100644
--- a/include/mcld/LD/ELFReaderIf.h
+++ b/include/mcld/LD/ELFReaderIf.h
@@ -1,4 +1,4 @@
-//===- ELFReader.h --------------------------------------------------------===//
+//===- ELFReaderIf.h ------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_READER_INTERFACE_H
-#define MCLD_ELF_READER_INTERFACE_H
+#ifndef MCLD_LD_ELFREADERIF_H
+#define MCLD_LD_ELFREADERIF_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -46,16 +46,16 @@
   virtual size_t getELFHeaderSize() const = 0;
 
   /// isELF - is this a ELF file
-  virtual bool isELF(void* pELFHeader) const = 0;
+  virtual bool isELF(const void* pELFHeader) const = 0;
 
   /// isMyEndian - is this ELF file in the same endian to me?
-  virtual bool isMyEndian(void* pELFHeader) const = 0;
+  virtual bool isMyEndian(const void* pELFHeader) const = 0;
 
   /// isMyMachine - is this ELF file generated for the same machine.
-  virtual bool isMyMachine(void* pELFHeader) const = 0;
+  virtual bool isMyMachine(const void* pELFHeader) const = 0;
 
   /// fileType - the file type of this file
-  virtual Input::Type fileType(void* pELFHeader) const = 0;
+  virtual Input::Type fileType(const void* pELFHeader) const = 0;
 
   /// target - the target backend
   const GNULDBackend& target() const { return m_Backend; }
@@ -63,7 +63,8 @@
 
 
   /// readSectionHeaders - read ELF section header table and create LDSections
-  virtual bool readSectionHeaders(Input& pInput, void* pELFHeader) const = 0;
+  virtual bool readSectionHeaders(Input& pInput,
+                                  const void* pELFHeader) const = 0;
 
   /// readRegularSection - read a regular section and create fragments.
   virtual bool readRegularSection(Input& pInput, SectionData& pSD) const = 0;
@@ -71,7 +72,7 @@
   /// readSymbols - read ELF symbols and create LDSymbol
   virtual bool readSymbols(Input& pInput,
                            IRBuilder& pBuilder,
-                           const MemoryRegion& pRegion,
+                           llvm::StringRef pRegion,
                            const char* StrTab) const = 0;
 
   /// readSignature - read a symbol from the given Input and index in symtab
@@ -83,12 +84,12 @@
   /// readRela - read ELF rela and create Relocation
   virtual bool readRela(Input& pInput,
                         LDSection& pSection,
-                        const MemoryRegion& pRegion) const = 0;
+                        llvm::StringRef pRegion) const = 0;
 
   /// readRel - read ELF rel and create Relocation
   virtual bool readRel(Input& pInput,
                        LDSection& pSection,
-                       const MemoryRegion& pRegion) const = 0;
+                       llvm::StringRef pRegion) const = 0;
 
   /// readDynamic - read ELF .dynamic in input dynobj
   virtual bool readDynamic(Input& pInput) const = 0;
diff --git a/include/mcld/LD/ELFSegment.h b/include/mcld/LD/ELFSegment.h
index d7f769e..5079b54 100644
--- a/include/mcld/LD/ELFSegment.h
+++ b/include/mcld/LD/ELFSegment.h
@@ -6,45 +6,52 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_SEGMENT_H
-#define MCLD_ELF_SEGMENT_H
+#ifndef MCLD_LD_ELFSEGMENT_H
+#define MCLD_LD_ELFSEGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/DataTypes.h>
-#include <mcld/LD/LDSection.h>
-#include <cassert>
 #include <vector>
 
 namespace mcld
 {
 
+class LDSection;
+
 /** \class ELFSegment
  *  \brief decribe the program header for ELF executable or shared object
  */
 class ELFSegment
 {
 public:
-  typedef std::vector<LDSection*>::iterator sect_iterator;
-  typedef std::vector<LDSection*>::const_iterator const_sect_iterator;
+  typedef std::vector<LDSection*> SectionList;
+  typedef SectionList::iterator iterator;
+  typedef SectionList::const_iterator const_iterator;
+  typedef SectionList::reverse_iterator reverse_iterator;
+  typedef SectionList::const_reverse_iterator const_reverse_iterator;
+
+private:
+  friend class Chunk<ELFSegment, MCLD_SEGMENTS_PER_OUTPUT>;
+  ELFSegment();
+  ELFSegment(uint32_t pType, uint32_t pFlag = llvm::ELF::PF_R);
+
 public:
-  ELFSegment(uint32_t pType,
-             uint32_t pFlag = llvm::ELF::PF_R,
-             uint64_t pOffset = 0,
-             uint64_t pVaddr = 0,
-             uint64_t pPaddr = 0,
-             uint64_t pFilesz = 0,
-             uint64_t pMemsz = 0,
-             uint64_t pAlign = 0,
-             uint64_t pMaxSectAlign = 0);
   ~ELFSegment();
 
   ///  -----  iterators  -----  ///
-  sect_iterator       begin()       { return m_SectionList.begin(); }
-  const_sect_iterator begin() const { return m_SectionList.begin(); }
-  sect_iterator       end()         { return m_SectionList.end(); }
-  const_sect_iterator end()   const { return m_SectionList.end(); }
+  iterator       begin()       { return m_SectionList.begin(); }
+  const_iterator begin() const { return m_SectionList.begin(); }
+  iterator       end()         { return m_SectionList.end(); }
+  const_iterator end()   const { return m_SectionList.end(); }
+
+  reverse_iterator       rbegin()       { return m_SectionList.rbegin(); }
+  const_reverse_iterator rbegin() const { return m_SectionList.rbegin(); }
+  reverse_iterator       rend()         { return m_SectionList.rend(); }
+  const_reverse_iterator rend()   const { return m_SectionList.rend(); }
 
   LDSection*       front()       { return m_SectionList.front(); }
   const LDSection* front() const { return m_SectionList.front(); }
@@ -52,35 +59,20 @@
   const LDSection* back()  const { return m_SectionList.back(); }
 
   ///  -----  observers  -----  ///
-  uint32_t type() const
-  { return m_Type; }
+  uint32_t type()   const { return m_Type; }
+  uint64_t offset() const { return m_Offset; }
+  uint64_t vaddr()  const { return m_Vaddr; }
+  uint64_t paddr()  const { return m_Paddr; }
+  uint64_t filesz() const { return m_Filesz; }
+  uint64_t memsz()  const { return m_Memsz; }
+  uint32_t flag()   const { return m_Flag; }
+  uint64_t align()  const { return std::max(m_Align, m_MaxSectionAlign); }
 
-  uint64_t offset() const
-  { return m_Offset; }
+  size_t size() const { return m_SectionList.size(); }
+  bool  empty() const { return m_SectionList.empty(); }
 
-  uint64_t vaddr() const
-  { return m_Vaddr; }
-
-  uint64_t paddr() const
-  { return m_Paddr; }
-
-  uint64_t filesz() const
-  { return m_Filesz; }
-
-  uint64_t memsz() const
-  { return m_Memsz; }
-
-  uint32_t flag() const
-  { return m_Flag; }
-
-  uint64_t align() const
-  { return std::max(m_Align, m_MaxSectionAlign); }
-
-  size_t numOfSections() const
-  { return m_SectionList.size(); }
-
+  bool isLoadSegment() const;
   bool isDataSegment() const;
-
   bool isBssSegment() const;
 
   ///  -----  modifiers  -----  ///
@@ -112,13 +104,14 @@
   void setAlign(uint64_t pAlign)
   { m_Align = pAlign; }
 
-  void addSection(LDSection* pSection)
-  {
-    assert(NULL != pSection);
-    if (pSection->align() > m_MaxSectionAlign)
-      m_MaxSectionAlign = pSection->align();
-    m_SectionList.push_back(pSection);
-  }
+  iterator insert(iterator pPos, LDSection* pSection);
+
+  void append(LDSection* pSection);
+
+  /* factory methods */
+  static ELFSegment* Create(uint32_t pType, uint32_t pFlag = llvm::ELF::PF_R);
+  static void Destroy(ELFSegment*& pSegment);
+  static void Clear();
 
 private:
   uint32_t m_Type;            // Type of segment
@@ -130,7 +123,7 @@
   uint64_t m_Memsz;           // # of bytes in mem image of segment (may be 0)
   uint64_t m_Align;           // alignment constraint
   uint64_t m_MaxSectionAlign; // max alignment of the sections in this segment
-  std::vector<LDSection*> m_SectionList;
+  SectionList m_SectionList;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFSegmentFactory.h b/include/mcld/LD/ELFSegmentFactory.h
index 5085a18..6df0389 100644
--- a/include/mcld/LD/ELFSegmentFactory.h
+++ b/include/mcld/LD/ELFSegmentFactory.h
@@ -6,38 +6,64 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELFSEGMENT_FACTORY_H
-#define MCLD_ELFSEGMENT_FACTORY_H
+#ifndef MCLD_LD_ELFSEGMENTFACTORY_H
+#define MCLD_LD_ELFSEGMENTFACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <mcld/Support/GCFactory.h>
-#include <mcld/LD/ELFSegment.h>
+
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/ELF.h>
+#include <vector>
 
 namespace mcld
 {
 
+class ELFSegment;
+class LDSection;
+
 /** \class ELFSegmentFactory
  *  \brief provide the interface to create and delete an ELFSegment
  */
-class ELFSegmentFactory : public GCFactory<ELFSegment, 0>
+class ELFSegmentFactory
 {
 public:
-  /// ELFSegmentFactory - the factory of ELFSegment
-  /// pNum is the magic number of the ELF segments in the output
-  ELFSegmentFactory(size_t pNum);
-  ~ELFSegmentFactory();
+  typedef std::vector<ELFSegment*> Segments;
+  typedef Segments::const_iterator const_iterator;
+  typedef Segments::iterator iterator;
+
+  const_iterator begin() const { return m_Segments.begin(); }
+  iterator       begin()       { return m_Segments.begin(); }
+  const_iterator end()   const { return m_Segments.end(); }
+  iterator       end()         { return m_Segments.end(); }
+
+  const ELFSegment* front() const { return m_Segments.front(); }
+  ELFSegment*       front()       { return m_Segments.front(); }
+  const ELFSegment* back()  const { return m_Segments.back(); }
+  ELFSegment*       back()        { return m_Segments.back(); }
+
+  size_t size() const { return m_Segments.size(); }
+
+  bool empty() const { return m_Segments.empty(); }
+
+  iterator find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear);
+
+  const_iterator
+  find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear) const;
+
+  iterator       find(uint32_t pType, const LDSection* pSection);
+
+  const_iterator find(uint32_t pType, const LDSection* pSection) const;
 
   /// produce - produce an empty ELF segment information.
   /// this function will create an ELF segment
   /// @param pType - p_type in ELF program header
   ELFSegment* produce(uint32_t pType, uint32_t pFlag = llvm::ELF::PF_R);
 
-  ELFSegment*
-  find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear);
+  void erase(iterator pSegment);
 
-  const ELFSegment*
-  find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear) const;
+private:
+  Segments m_Segments;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/EhFrame.h b/include/mcld/LD/EhFrame.h
index c067746..6663d0f 100644
--- a/include/mcld/LD/EhFrame.h
+++ b/include/mcld/LD/EhFrame.h
@@ -6,23 +6,30 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_EH_FRAME_H
-#define MCLD_LD_EH_FRAME_H
+#ifndef MCLD_LD_EHFRAME_H
+#define MCLD_LD_EHFRAME_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
 #include <mcld/Config/Config.h>
 #include <mcld/Fragment/RegionFragment.h>
-#include <mcld/Fragment/NullFragment.h>
+#include <mcld/LD/SectionData.h>
 #include <mcld/Support/Allocators.h>
 
+#include <llvm/ADT/StringRef.h>
+#include <list>
+#include <map>
+#include <set>
 #include <vector>
 
 namespace mcld {
 
+class Input;
+class Module;
 class LDSection;
-class SectionData;
+class ObjectLinker;
+class Relocation;
 
 /** \class EhFrame
  *  \brief EhFrame represents .eh_frame section
@@ -41,53 +48,128 @@
   EhFrame& operator=(const EhFrame&); // DO NOT IMPLEMENT
 
 public:
+  enum RecordType {
+    RECORD_UNKNOWN,
+    RECORD_INPUT,
+    RECORD_GENERATED
+  };
+
+  class CIE;
+  class FDE;
+
+  typedef std::vector<CIE*> CIEList;
+  typedef CIEList::iterator cie_iterator;
+  typedef CIEList::const_iterator const_cie_iterator;
+
+  typedef std::list<FDE*> FDEList;
+  typedef FDEList::iterator fde_iterator;
+  typedef FDEList::const_iterator const_fde_iterator;
+
+  typedef std::map</*offset*/size_t, CIE*> CIEMap;
+
+  // A super class of CIE and FDE, containing the same part
+  class Record : public RegionFragment
+  {
+  public:
+    Record(llvm::StringRef pRegion);
+    virtual ~Record();
+
+    const llvm::StringRef getRegion() const { return RegionFragment::getRegion(); }
+          llvm::StringRef getRegion()       { return RegionFragment::getRegion(); }
+    virtual RecordType getRecordType() const { return RECORD_UNKNOWN; }
+
+  private:
+    Record(const Record&);            // DO NOT IMPLEMENT
+    Record& operator=(const Record&); // DO NOT IMPLEMENT
+  };
+
   /** \class CIE
    *  \brief Common Information Entry.
    *  The CIE structure refers to LSB Core Spec 4.1, chap.10.6. Exception Frames.
    */
-  class CIE : public RegionFragment
+  class CIE : public Record
   {
   public:
-    CIE(MemoryRegion& pRegion);
+    CIE(llvm::StringRef pRegion);
+    ~CIE();
+
+    virtual RecordType getRecordType() const { return RECORD_INPUT; }
 
     void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; }
     uint8_t getFDEEncode() const { return m_FDEEncode; }
 
+    void setMergeable(bool pVal = true) { m_Mergeable = pVal; }
+    virtual bool getMergeable() const { return m_Mergeable; }
+
+    void setRelocation(const Relocation& pReloc) { m_pReloc = &pReloc; }
+    const Relocation* getRelocation() const { return m_pReloc; }
+
+    void setPersonalityOffset(uint64_t pOffset) { m_PersonalityOffset = pOffset; }
+    uint64_t getPersonalityOffset() const { return m_PersonalityOffset; }
+
+    void setPersonalityName(const std::string& pStr) { m_PersonalityName = pStr; }
+    const std::string& getPersonalityName() const { return m_PersonalityName; }
+
+    void setAugmentationData(const std::string& pStr) { m_AugmentationData = pStr; }
+    const std::string& getAugmentationData() const { return m_AugmentationData; }
+
+    void add(FDE& pFDE) { m_FDEs.push_back(&pFDE); }
+    void remove(FDE& pFDE) { m_FDEs.remove(&pFDE); }
+    void clearFDEs() { m_FDEs.clear(); }
+    size_t numOfFDEs() const { return m_FDEs.size(); }
+
+    const_fde_iterator begin() const { return m_FDEs.begin(); }
+    fde_iterator       begin()       { return m_FDEs.begin(); }
+    const_fde_iterator end() const { return m_FDEs.end(); }
+    fde_iterator       end()       { return m_FDEs.end(); }
+
   private:
     uint8_t m_FDEEncode;
+    bool m_Mergeable;
+    const Relocation* m_pReloc;
+    uint64_t m_PersonalityOffset;
+    std::string m_PersonalityName;
+    std::string m_AugmentationData;
+    FDEList m_FDEs;
   };
 
   /** \class FDE
    *  \brief Frame Description Entry
    *  The FDE structure refers to LSB Core Spec 4.1, chap.10.6. Exception Frames.
    */
-  class FDE : public RegionFragment
+  class FDE : public Record
   {
   public:
-    FDE(MemoryRegion& pRegion,
-        const CIE& pCIE,
-        uint32_t pDataStart);
+    FDE(llvm::StringRef pRegion, CIE& pCIE);
+    ~FDE();
 
-    const CIE& getCIE() const { return m_CIE; }
-
-    uint32_t getDataStart() const { return m_DataStart; }
+    void setCIE(CIE& pCIE);
+    const CIE& getCIE() const { return *m_pCIE; }
+    CIE&       getCIE()       { return *m_pCIE; }
 
   private:
-    const CIE& m_CIE;
-    uint32_t m_DataStart;
+    CIE* m_pCIE;  // Referenced CIE may change when merging.
   };
 
-  typedef std::vector<CIE*> CIEList;
+  // These are created for PLT
+  class GeneratedCIE : public CIE
+  {
+  public:
+    GeneratedCIE(llvm::StringRef pRegion);
+    ~GeneratedCIE();
 
-  // cie_iterator and const_cie_iterator must be a kind of random access iterator
-  typedef CIEList::iterator cie_iterator;
-  typedef CIEList::const_iterator const_cie_iterator;
+    virtual RecordType getRecordType() const { return RECORD_GENERATED; }
+    virtual bool getMergeable() const { return true; }
+  };
 
-  typedef std::vector<FDE*> FDEList;
+  class GeneratedFDE : public FDE
+  {
+  public:
+    GeneratedFDE(llvm::StringRef pRegion, CIE& pCIE);
+    ~GeneratedFDE();
 
-  // fde_iterator and const_fde_iterator must be a kind of random access iterator
-  typedef FDEList::iterator fde_iterator;
-  typedef FDEList::const_iterator const_fde_iterator;
+    virtual RecordType getRecordType() const { return RECORD_GENERATED; }
+  };
 
 public:
   static EhFrame* Create(LDSection& pSection);
@@ -97,7 +179,7 @@
   static void Clear();
 
   /// merge - move all data from pOther to this object.
-  EhFrame& merge(EhFrame& pOther);
+  EhFrame& merge(const Input& pInput, EhFrame& pInFrame);
 
   const LDSection& getSection() const;
   LDSection&       getSection();
@@ -106,17 +188,13 @@
   SectionData*       getSectionData()       { return m_pSectionData; }
 
   // -----  fragment  ----- //
-  /// addFragment - when we start treating CIEs and FDEs as regular fragments,
-  /// we call this function instead of addCIE() and addFDE().
-  void addFragment(RegionFragment& pFrag);
-
-  void addFragment(NullFragment& pFrag);
+  void addFragment(Fragment& pFrag);
 
   /// addCIE - add a CIE entry in EhFrame
-  void addCIE(CIE& pCIE);
+  void addCIE(CIE& pCIE, bool pAlsoAddFragment = true);
 
   /// addFDE - add a FDE entry in EhFrame
-  void addFDE(FDE& pFDE);
+  void addFDE(FDE& pFDE, bool pAlsoAddFragment = true);
 
   // -----  CIE  ----- //
   const_cie_iterator cie_begin() const { return m_CIEs.begin(); }
@@ -129,29 +207,54 @@
   const CIE& cie_back () const { return *m_CIEs.back(); }
   CIE&       cie_back ()       { return *m_CIEs.back(); }
 
+  bool emptyCIEs() const { return m_CIEs.empty(); }
   size_t numOfCIEs() const { return m_CIEs.size(); }
+  size_t numOfFDEs() const;
 
-  // -----  FDE  ----- //
-  const_fde_iterator fde_begin() const { return m_FDEs.begin(); }
-  fde_iterator       fde_begin()       { return m_FDEs.begin(); }
-  const_fde_iterator fde_end  () const { return m_FDEs.end(); }
-  fde_iterator       fde_end  ()       { return m_FDEs.end(); }
+  const CIEMap& getCIEMap() const { return m_FoundCIEs; }
+  CIEMap&       getCIEMap()       { return m_FoundCIEs; }
 
-  const FDE& fde_front() const { return *m_FDEs.front(); }
-  FDE&       fde_front()       { return *m_FDEs.front(); }
-  const FDE& fde_back () const { return *m_FDEs.back(); }
-  FDE&       fde_back ()       { return *m_FDEs.back(); }
+public:
+  size_t computeOffsetSize();
 
-  size_t numOfFDEs() const { return m_FDEs.size(); }
+  /// getDataStartOffset - Get the offset after length and ID field.
+  /// The offset is 8byte for 32b, and 16byte for 64b.
+  /// We can just use "BITCLASS/4" to represent offset.
+  template <size_t BITCLASS>
+  static size_t getDataStartOffset() { return BITCLASS / 4; }
+
+private:
+  // We needs to check if it is mergeable and check personality name
+  // before merging them. The important note is we must do this after
+  // ALL readSections done, that is the reason why we don't check this
+  // immediately when reading.
+  void setupAttributes(const LDSection* reloc_sect);
+  void removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocEhFrameSect);
+
+private:
+  void removeAndUpdateCIEForFDE(EhFrame& pInFrame, CIE& pInCIE, CIE& pOutCIE,
+                                const LDSection* reloc_sect);
+  void moveInputFragments(EhFrame& pInFrame);
+  void moveInputFragments(EhFrame& pInFrame, CIE& pInCIE, CIE* pOutCIE = 0);
 
 private:
   LDSection* m_pSection;
   SectionData* m_pSectionData;
 
+  // Each eh_frame has a list of CIE, and each CIE has a list of FDE
+  // pointing to the CIE itself. This is used by management when we are
+  // processing eh_frame merge.
+  // However, don't forget we need to handle the Fragments inside SectionData
+  // correctly since they are truly used when output emission.
   CIEList m_CIEs;
-  FDEList m_FDEs;
+
+  // We need this map to find the corresponding CIE for FDE. Not all FDE point
+  // to the nearest CIE.
+  CIEMap m_FoundCIEs;
 };
 
+bool operator==(const EhFrame::CIE&, const EhFrame::CIE&);
+
 } // namespace of mcld
 
 #endif
diff --git a/include/mcld/LD/EhFrameHdr.h b/include/mcld/LD/EhFrameHdr.h
index 3a5971d..2d7b0e9 100644
--- a/include/mcld/LD/EhFrameHdr.h
+++ b/include/mcld/LD/EhFrameHdr.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_EHFRAMEHDR_H
-#define MCLD_EHFRAMEHDR_H
+#ifndef MCLD_LD_EHFRAMEHDR_H
+#define MCLD_LD_EHFRAMEHDR_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -15,11 +15,11 @@
 #include <cassert>
 
 #include <mcld/LD/EhFrame.h>
+#include <mcld/Support/FileOutputBuffer.h>
 namespace mcld {
 
 class LDSection;
-class MemoryArea;
-class MemoryRegion;
+class FileOutputBuffer;
 
 /** \class EhFrameHdr
  *  \brief EhFrameHdr represents .eh_frame_hdr section.
@@ -47,13 +47,14 @@
 
   /// emitOutput - write out eh_frame_hdr
   template<size_t size>
-  void emitOutput(MemoryArea& pOutput)
+  void emitOutput(FileOutputBuffer& pOutput)
   { assert(false && "Call invalid EhFrameHdr::emitOutput"); }
 
 private:
   /// computePCBegin - return the address of FDE's pc
   /// @ref binutils gold: ehframe.cc:222
-  uint32_t computePCBegin(const EhFrame::FDE& pFDE, const MemoryRegion& pEhFrameRegion);
+  uint32_t computePCBegin(const EhFrame::FDE& pFDE,
+                          const MemoryRegion& pEhFrameRegion);
 
 private:
   /// .eh_frame_hdr section
@@ -68,7 +69,7 @@
 //===----------------------------------------------------------------------===//
 /// emitOutput - write out eh_frame_hdr
 template<>
-void EhFrameHdr::emitOutput<32>(MemoryArea& pOutput);
+void EhFrameHdr::emitOutput<32>(FileOutputBuffer& pOutput);
 
 } // namespace of mcld
 
diff --git a/include/mcld/LD/EhFrameReader.h b/include/mcld/LD/EhFrameReader.h
index 1ac0351..509debf 100644
--- a/include/mcld/LD/EhFrameReader.h
+++ b/include/mcld/LD/EhFrameReader.h
@@ -6,17 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_EH_FRAME_READER_H
-#define MCLD_EH_FRAME_READER_H
+#ifndef MCLD_LD_EHFRAMEREADER_H
+#define MCLD_LD_EHFRAMEREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <mcld/Support/MemoryRegion.h>
+#include <mcld/LD/EhFrame.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
 
 namespace mcld {
 
 class Input;
-class EhFrame;
 class LDSection;
 
 /** \class EhFrameReader
@@ -28,8 +29,8 @@
 class EhFrameReader
 {
 public:
-  typedef const uint8_t* ConstAddress;
-  typedef       uint8_t* Address;
+  typedef const char* ConstAddress;
+  typedef       char* Address;
 
 public:
   /// read - read an .eh_frame section and create the corresponding
@@ -70,29 +71,29 @@
   /// @param pSection - the input .eh_frame section
   /// @param pRegion - the memory region that needs to handle with.
   typedef bool (*Action)(EhFrame& pEhFrame,
-                         MemoryRegion& pRegion,
+                         llvm::StringRef pRegion,
                          const Token& pToken);
 private:
   /// scan - scan pData from pHandler for a token.
-  template<bool SAME_ENDIAN> Token
-  scan(ConstAddress pHandler, uint64_t pOffset, const MemoryRegion& pData) const;
+  template<bool SAME_ENDIAN> Token scan(ConstAddress pHandler,
+                                        uint64_t pOffset,
+                                        llvm::StringRef pData) const;
 
   static bool addCIE(EhFrame& pEhFrame,
-                     MemoryRegion& pRegion,
+                     llvm::StringRef pRegion,
                      const Token& pToken);
 
   static bool addFDE(EhFrame& pEhFrame,
-                     MemoryRegion& pRegion,
+                     llvm::StringRef pRegion,
                      const Token& pToken);
 
   static bool addTerm(EhFrame& pEhFrame,
-                      MemoryRegion& pRegion,
+                      llvm::StringRef pRegion,
                       const Token& pToken);
 
   static bool reject(EhFrame& pEhFrame,
-                     MemoryRegion& pRegion,
+                     llvm::StringRef pRegion,
                      const Token& pToken);
-
 };
 
 template<> bool
@@ -101,7 +102,7 @@
 template<> EhFrameReader::Token
 EhFrameReader::scan<true>(ConstAddress pHandler,
                           uint64_t pOffset,
-                          const MemoryRegion& pData) const;
+                          llvm::StringRef pData) const;
 
 } // namespace of mcld
 
diff --git a/include/mcld/LD/GNUArchiveReader.h b/include/mcld/LD/GNUArchiveReader.h
index 7a33ff4..1c2e10a 100644
--- a/include/mcld/LD/GNUArchiveReader.h
+++ b/include/mcld/LD/GNUArchiveReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_GNU_ARCHIVE_READER_H
-#define MCLD_GNU_ARCHIVE_READER_H
+#ifndef MCLD_LD_GNUARCHIVEREADER_H
+#define MCLD_LD_GNUARCHIVEREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -20,8 +20,8 @@
 class Module;
 class Input;
 class ELFObjectReader;
-class MemoryAreaFactory;
 class Archive;
+class LinkerConfig;
 
 /** \class GNUArchiveReader
  *  \brief GNUArchiveReader reads GNU archive files.
@@ -35,10 +35,10 @@
 
   /// readArchive - read an archive, include the needed members, and build up
   /// the subtree
-  bool readArchive(Archive& pArchive);
+  bool readArchive(const LinkerConfig& pConfig, Archive& pArchive);
 
   /// isMyFormat
-  bool isMyFormat(Input& input) const;
+  bool isMyFormat(Input& input, bool &pContinue) const;
 
 private:
   /// isArchive
@@ -78,13 +78,16 @@
 
   /// includeMember - include the object member in the given file offset, and
   /// return the size of the object
+  /// @param pConfig - LinkerConfig
   /// @param pArchiveRoot - the archive root
   /// @param pFileOffset  - file offset of the member header in the archive
-  size_t includeMember(Archive& pArchiveRoot, uint32_t pFileOffset);
+  size_t includeMember(const LinkerConfig& pConfig,
+                       Archive& pArchiveRoot,
+                       uint32_t pFileOffset);
 
   /// includeAllMembers - include all object members. This is called if
   /// --whole-archive is the attribute for this archive file.
-  bool includeAllMembers(Archive& pArchive);
+  bool includeAllMembers(const LinkerConfig& pConfig, Archive& pArchive);
 
 private:
   Module& m_Module;
diff --git a/include/mcld/LD/GarbageCollection.h b/include/mcld/LD/GarbageCollection.h
new file mode 100644
index 0000000..3476cd1
--- /dev/null
+++ b/include/mcld/LD/GarbageCollection.h
@@ -0,0 +1,94 @@
+//===- GarbageCollection.h ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LD_GARBAGECOLLECTION_H
+#define MCLD_LD_GARBAGECOLLECTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <map>
+#include <set>
+#include <vector>
+
+namespace mcld {
+
+class LDSection;
+class LinkerConfig;
+class Module;
+class TargetLDBackend;
+
+/** \class GarbageCollection
+ *  \brief Implementation of garbage collection for --gc-section.
+ *  @ref GNU gold, gc.
+ */
+class GarbageCollection
+{
+public:
+  typedef std::set<const LDSection*> SectionListTy;
+  typedef std::vector<const LDSection*> SectionVecTy;
+
+  /** \class SectionReachedListMap
+   *  \brief Map the section to the list of sections which it can reach directly
+   */
+  class SectionReachedListMap
+  {
+  public:
+    SectionReachedListMap() {}
+
+    /// addReference - add a reference from pFrom to pTo
+    void addReference(const LDSection& pFrom, const LDSection& pTo);
+
+    /// getReachedList - get the list of sections which can be reached by
+    /// pSection, create one if the list has not existed
+    SectionListTy& getReachedList(const LDSection& pSection);
+
+    /// findReachedList - find the list of sections which can be reached by
+    /// pSection, return NULL if the list not exists
+    SectionListTy* findReachedList(const LDSection& pSection);
+
+  private:
+    typedef std::map<const LDSection*, SectionListTy> ReachedSectionsTy;
+
+  private:
+    /// m_ReachedSections - map a section to the reachable sections list
+    ReachedSectionsTy m_ReachedSections;
+  };
+
+public:
+  GarbageCollection(const LinkerConfig& pConfig,
+                    const TargetLDBackend& pBackend,
+                    Module& pModule);
+  ~GarbageCollection();
+
+  /// run - do garbage collection
+  bool run();
+
+private:
+  void setUpReachedSections();
+  void findReferencedSections(SectionVecTy& pEntry);
+  void getEntrySections(SectionVecTy& pEntry);
+  void stripSections();
+
+private:
+  /// m_SectionReachedListMap - map the section to the list of sections which it
+  /// can reach directly
+  SectionReachedListMap m_SectionReachedListMap;
+
+  /// m_ReferencedSections - a list of sections which can be reached from entry
+  SectionListTy m_ReferencedSections;
+
+  const LinkerConfig& m_Config;
+  const TargetLDBackend& m_Backend;
+  Module& m_Module;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/Group.h b/include/mcld/LD/Group.h
index 31c4a68..30e8f63 100644
--- a/include/mcld/LD/Group.h
+++ b/include/mcld/LD/Group.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef LD_GROUP_H
-#define LD_GROUP_H
+#ifndef MCLD_LD_GROUP_H
+#define MCLD_LD_GROUP_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/GroupReader.h b/include/mcld/LD/GroupReader.h
index 01178a0..fa1e182 100644
--- a/include/mcld/LD/GroupReader.h
+++ b/include/mcld/LD/GroupReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_GROUPREADER_H
-#define MCLD_GROUPREADER_H
+#ifndef MCLD_LD_GROUPREADER_H
+#define MCLD_LD_GROUPREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -43,6 +43,7 @@
   /// readGroup - handle the input sub-tree wich its root is pRoot
   /// @param pRoot - the root Group node of the sub-tree
   bool readGroup(Module::input_iterator pRoot,
+                 Module::input_iterator pEnd,
                  InputBuilder& pBuilder,
                  const LinkerConfig& pConfig);
 
diff --git a/include/mcld/LD/LDContext.h b/include/mcld/LD/LDContext.h
index 3ab6ce1..c9f30ae 100644
--- a/include/mcld/LD/LDContext.h
+++ b/include/mcld/LD/LDContext.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LDCONTEXT_H
-#define MCLD_LDCONTEXT_H
+#ifndef MCLD_LD_LDCONTEXT_H
+#define MCLD_LD_LDCONTEXT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -72,6 +72,12 @@
   void addSymbol(LDSymbol* pSym)
   { m_SymTab.push_back(pSym); }
 
+  const_sym_iterator symTabBegin() const { return m_SymTab.begin(); }
+  sym_iterator       symTabBegin()       { return m_SymTab.begin(); }
+
+  const_sym_iterator symTabEnd() const { return m_SymTab.end(); }
+  sym_iterator       symTabEnd()       { return m_SymTab.end(); }
+
   // -----  relocations  ----- //
   const_sect_iterator relocSectBegin() const { return m_RelocSections.begin(); }
   sect_iterator       relocSectBegin()       { return m_RelocSections.begin(); }
diff --git a/include/mcld/LD/LDFileFormat.h b/include/mcld/LD/LDFileFormat.h
index 4fa58ce..fb5ab63 100644
--- a/include/mcld/LD/LDFileFormat.h
+++ b/include/mcld/LD/LDFileFormat.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LDFILE_FORMAT_H
-#define MCLD_LDFILE_FORMAT_H
+#ifndef MCLD_LD_LDFILEFORMAT_H
+#define MCLD_LD_LDFILEFORMAT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/LDReader.h b/include/mcld/LD/LDReader.h
index 4fde9f0..38bf24d 100644
--- a/include/mcld/LD/LDReader.h
+++ b/include/mcld/LD/LDReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_READER_INTERFACE_H
-#define MCLD_READER_INTERFACE_H
+#ifndef MCLD_LD_LDREADER_H
+#define MCLD_LD_LDREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -37,7 +37,7 @@
 public:
   virtual ~LDReader() { }
 
-  virtual bool isMyFormat(Input& pInput) const = 0;
+  virtual bool isMyFormat(Input& pInput, bool &pContinue) const = 0;
 
 };
 
diff --git a/include/mcld/LD/LDSymbol.h b/include/mcld/LD/LDSymbol.h
index b40213c..bebdd18 100644
--- a/include/mcld/LD/LDSymbol.h
+++ b/include/mcld/LD/LDSymbol.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_SYMBOL_H
-#define MCLD_LD_SYMBOL_H
+#ifndef MCLD_LD_LDSYMBOL_H
+#define MCLD_LD_LDSYMBOL_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -19,7 +19,12 @@
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/Support/Allocators.h>
 
-#include <llvm/Support/ManagedStatic.h>
+namespace llvm {
+
+// forware declaration
+template<class T> void* object_creator();
+
+} // namespace of llvm
 
 namespace mcld {
 
diff --git a/include/mcld/LD/MsgHandler.h b/include/mcld/LD/MsgHandler.h
index 9b1ed80..62def8e 100644
--- a/include/mcld/LD/MsgHandler.h
+++ b/include/mcld/LD/MsgHandler.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MESSAGE_HANDLER_H
-#define MCLD_MESSAGE_HANDLER_H
+#ifndef MCLD_LD_MSGHANDLER_H
+#define MCLD_LD_MSGHANDLER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/NamePool.h b/include/mcld/LD/NamePool.h
index 32354ea..7a8f816 100644
--- a/include/mcld/LD/NamePool.h
+++ b/include/mcld/LD/NamePool.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_NAME_POOL_H
-#define MCLD_NAME_POOL_H
+#ifndef MCLD_LD_NAMEPOOL_H
+#define MCLD_LD_NAMEPOOL_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -38,7 +38,14 @@
 class NamePool : private Uncopyable
 {
 public:
-  typedef HashTable<ResolveInfo, hash::StringHash<hash::ELF> > Table;
+  typedef HashTable<ResolveInfo, hash::StringHash<hash::DJB> > Table;
+  typedef Table::iterator syminfo_iterator;
+  typedef Table::const_iterator const_syminfo_iterator;
+
+  typedef GCFactory<ResolveInfo*, 128> FreeInfoSet;
+  typedef FreeInfoSet::iterator freeinfo_iterator;
+  typedef FreeInfoSet::const_iterator const_freeinfo_iterator;
+
   typedef size_t size_type;
 
 public:
@@ -56,7 +63,7 @@
                             ResolveInfo::Binding pBinding,
                             ResolveInfo::SizeType pSize,
                             ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
-  
+
   /// insertSymbol - insert a symbol and resolve the symbol immediately
   /// @param pOldInfo - if pOldInfo is not NULL, the old ResolveInfo being
   ///                   overriden is kept in pOldInfo.
@@ -69,6 +76,7 @@
                     ResolveInfo::Desc pDesc,
                     ResolveInfo::Binding pBinding,
                     ResolveInfo::SizeType pSize,
+                    LDSymbol::ValueType pValue,
                     ResolveInfo::Visibility pVisibility,
                     ResolveInfo* pOldInfo,
                     Resolver::Result& pResult);
@@ -93,15 +101,39 @@
   bool empty() const
   { return m_Table.empty(); }
 
+  // syminfo_iterator - traverse the ResolveInfo in the resolved HashTable
+  syminfo_iterator syminfo_begin()
+  { return m_Table.begin(); }
+
+  syminfo_iterator syminfo_end()
+  { return m_Table.end(); }
+
+  const_syminfo_iterator syminfo_begin() const
+  { return m_Table.begin(); }
+
+  const_syminfo_iterator syminfo_end() const
+  { return m_Table.end(); }
+
+  // freeinfo_iterator - traverse the ResolveInfo those do not need to be
+  // resolved, for example, local symbols
+  freeinfo_iterator freeinfo_begin()
+  { return m_FreeInfoSet.begin(); }
+
+  freeinfo_iterator freeinfo_end()
+  { return m_FreeInfoSet.end(); }
+
+  const_freeinfo_iterator freeinfo_begin() const
+  { return m_FreeInfoSet.begin(); }
+
+  const_freeinfo_iterator freeinfo_end() const
+  { return m_FreeInfoSet.end(); }
+
   // -----  capacity  ----- //
   void reserve(size_type pN);
 
   size_type capacity() const;
 
 private:
-  typedef GCFactory<ResolveInfo*, 128> FreeInfoSet;
-
-private:
   Resolver* m_pResolver;
   Table m_Table;
   FreeInfoSet m_FreeInfoSet;
diff --git a/include/mcld/LD/ObjectReader.h b/include/mcld/LD/ObjectReader.h
index 2ca3173..34427f8 100644
--- a/include/mcld/LD/ObjectReader.h
+++ b/include/mcld/LD/ObjectReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_OBJECT_READER_H
-#define MCLD_OBJECT_READER_H
+#ifndef MCLD_LD_OBJECTREADER_H
+#define MCLD_LD_OBJECTREADER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -29,7 +29,7 @@
 class ObjectReader : public LDReader
 {
 protected:
-  typedef HashTable<ResolveInfo, hash::StringHash<hash::ELF> > GroupSignatureMap;
+  typedef HashTable<ResolveInfo, hash::StringHash<hash::DJB> > GroupSignatureMap;
 
 protected:
   ObjectReader()
diff --git a/include/mcld/LD/ObjectWriter.h b/include/mcld/LD/ObjectWriter.h
index c1dcac6..2a42aed 100644
--- a/include/mcld/LD/ObjectWriter.h
+++ b/include/mcld/LD/ObjectWriter.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_OBJECT_WRITER_INTERFACE_H
-#define MCLD_OBJECT_WRITER_INTERFACE_H
+#ifndef MCLD_LD_OBJECTWRITER_H
+#define MCLD_LD_OBJECTWRITER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -16,7 +16,7 @@
 namespace mcld {
 
 class Module;
-class MemoryArea;
+class FileOutputBuffer;
 
 /** \class ObjectWriter
  *  \brief ObjectWriter provides a common interface for object file writers.
@@ -29,7 +29,10 @@
 public:
   virtual ~ObjectWriter();
 
-  virtual llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput) = 0;
+  virtual llvm::error_code writeObject(Module& pModule,
+                                       FileOutputBuffer& pOutput) = 0;
+
+  virtual size_t getOutputSize(const Module& pModule) const = 0;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/RelocData.h b/include/mcld/LD/RelocData.h
index b53151a..68bc7e1 100644
--- a/include/mcld/LD/RelocData.h
+++ b/include/mcld/LD/RelocData.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_RELOCATION_DATA_H
-#define MCLD_RELOCATION_DATA_H
+#ifndef MCLD_LD_RELOCDATA_H
+#define MCLD_LD_RELOCDATA_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -21,6 +21,8 @@
 #include <llvm/ADT/ilist_node.h>
 #include <llvm/Support/DataTypes.h>
 
+#include <list>
+
 namespace mcld {
 
 class LDSection;
@@ -73,6 +75,7 @@
   bool empty() const { return m_Relocations.empty(); }
 
   RelocData& append(Relocation& pRelocation);
+  Relocation& remove(Relocation& pRelocation);
 
   reference              front ()       { return m_Relocations.front();  }
   const_reference        front () const { return m_Relocations.front();  }
@@ -88,6 +91,18 @@
   const_reverse_iterator rend  () const { return m_Relocations.rend();   }
   reverse_iterator       rend  ()       { return m_Relocations.rend();   }
 
+  template<class Comparator> void sort(Comparator pComparator) {
+    /* FIXME: use llvm::iplist::sort */
+    std::list<Relocation*> relocs;
+    for (iterator it = begin(), ie = end(); it != ie; ++it)
+      relocs.push_back(it);
+    relocs.sort(pComparator);
+    m_Relocations.clear();
+    for (std::list<Relocation*>::iterator it = relocs.begin(),
+      ie = relocs.end(); it != ie; ++it)
+      m_Relocations.push_back(*it);
+  }
+
 private:
   RelocationListType m_Relocations;
   LDSection* m_pSection;
diff --git a/include/mcld/LD/Relocator.h b/include/mcld/LD/Relocator.h
index 54ea7e8..2828a5b 100644
--- a/include/mcld/LD/Relocator.h
+++ b/include/mcld/LD/Relocator.h
@@ -61,10 +61,21 @@
   /// @param pReloc - a read in relocation entry
   /// @param pInputSym - the input LDSymbol of relocation target symbol
   /// @param pSection - the section of relocation applying target
+  /// @param pInput - the input file of relocation
   virtual void scanRelocation(Relocation& pReloc,
                               IRBuilder& pBuilder,
                               Module& pModule,
-                              LDSection& pSection) = 0;
+                              LDSection& pSection,
+                              Input& pInput) = 0;
+
+  /// issueUndefRefError - Provides a basic version for undefined reference dump.
+  /// It will handle the filename and function name automatically.
+  /// @param pReloc - a read in relocation entry
+  /// @param pSection - the section of relocation applying target
+  /// @ param pInput - the input file of relocation
+  virtual void issueUndefRef(Relocation& pReloc,
+                             LDSection& pSection,
+                             Input& pInput);
 
   /// initializeScan - do initialization before scan relocations in pInput
   /// @return - return true for initialization success
diff --git a/include/mcld/LD/ResolveInfo.h b/include/mcld/LD/ResolveInfo.h
index 6f28169..9616719 100644
--- a/include/mcld/LD/ResolveInfo.h
+++ b/include/mcld/LD/ResolveInfo.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_RESOLVE_INFO_H
-#define MCLD_RESOLVE_INFO_H
+#ifndef MCLD_LD_RESOLVEINFO_H
+#define MCLD_LD_RESOLVEINFO_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -18,6 +18,7 @@
 namespace mcld {
 
 class LDSymbol;
+class LinkerConfig;
 
 /** \class ResolveInfo
  *  \brief ResolveInfo records the information about how to resolve a symbol.
@@ -142,6 +143,10 @@
     m_BitField |= indirect_flag;
   }
 
+  /// setInDyn - set if the symbol has been seen in the dynamic objects. Once
+  /// InDyn set, then it won't be set back to false
+  void setInDyn();
+
   // -----  observers  ----- //
   bool isNull() const;
 
@@ -167,6 +172,8 @@
 
   bool isIndirect() const;
 
+  bool isInDyn() const;
+
   uint32_t type() const;
 
   uint32_t desc() const;
@@ -207,6 +214,9 @@
   uint32_t bitfield() const
   { return m_BitField; }
 
+  // shouldForceLocal - check if this symbol should be forced to local
+  bool shouldForceLocal(const LinkerConfig& pConfig);
+
   // -----  For HashTable  ----- //
   bool compare(const key_type& pKey);
 
@@ -236,7 +246,11 @@
 
   static const uint32_t RESERVED_OFFSET    = 12;
   static const uint32_t RESERVED_MASK      = 0xF << RESERVED_OFFSET;
-  static const uint32_t NAME_LENGTH_OFFSET = 16;
+
+  static const uint32_t IN_DYN_OFFSET      = 16;
+  static const uint32_t IN_DYN_MASK        = 1   << IN_DYN_OFFSET;
+
+  static const uint32_t NAME_LENGTH_OFFSET = 17;
   static const uint32_t INFO_MASK          = 0xF;
   static const uint32_t RESOLVE_MASK       = 0xFFFF;
 
@@ -262,6 +276,7 @@
   static const uint32_t file_flag      = File     << TYPE_OFFSET;
   static const uint32_t string_flag    = 0        << SYMBOL_OFFSET;
   static const uint32_t symbol_flag    = 1        << SYMBOL_OFFSET;
+  static const uint32_t indyn_flag     = 1        << IN_DYN_OFFSET;
 
 private:
   ResolveInfo();
@@ -274,8 +289,8 @@
   SymOrInfo m_Ptr;
 
   /** m_BitField
-   *  31     ...    16 15    12 11     10..7 6      ..    5 4     3   2   1   0
-   * |length of m_Name|reserved|Symbol|Type |ELF visibility|Local|Com|Def|Dyn|Weak|
+   *  31     ...    17 16    15    12 11     10..7 6      ..    5 4     3   2   1   0
+   * |length of m_Name|InDyn|reserved|Symbol|Type |ELF visibility|Local|Com|Def|Dyn|Weak|
    */
   uint32_t m_BitField;
   char m_Name[];
diff --git a/include/mcld/LD/Resolver.h b/include/mcld/LD/Resolver.h
index d506a2d..069a167 100644
--- a/include/mcld/LD/Resolver.h
+++ b/include/mcld/LD/Resolver.h
@@ -6,13 +6,14 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SYMBOL_RESOLVER_H
-#define MCLD_SYMBOL_RESOLVER_H
+#ifndef MCLD_LD_RESOLVER_H
+#define MCLD_LD_RESOLVER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <string>
 #include <utility>
+#include <mcld/LD/LDSymbol.h>
 
 namespace mcld
 {
@@ -59,7 +60,7 @@
   /// @param pNew the symbol which is used to replace pOld
   virtual bool resolve(ResolveInfo & __restrict__ pOld,
                        const ResolveInfo & __restrict__ pNew,
-                       bool &pOverride) const = 0;
+                       bool &pOverride, LDSymbol::ValueType pValue) const = 0;
 
   /// resolveAgain - Can override by derived classes.
   /// @return the pointer to resolved ResolveInfo
diff --git a/include/mcld/LD/SectionData.h b/include/mcld/LD/SectionData.h
index 4f58afa..0a74961 100644
--- a/include/mcld/LD/SectionData.h
+++ b/include/mcld/LD/SectionData.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_SECTION_DATA_H
-#define MCLD_LD_SECTION_DATA_H
+#ifndef MCLD_LD_SECTIONDATA_H
+#define MCLD_LD_SECTIONDATA_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/SectionSymbolSet.h b/include/mcld/LD/SectionSymbolSet.h
index 801fe37..fe814a7 100644
--- a/include/mcld/LD/SectionSymbolSet.h
+++ b/include/mcld/LD/SectionSymbolSet.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTIONSYMBOLSET_H
-#define MCLD_SECTIONSYMBOLSET_H
+#ifndef MCLD_LD_SECTIONSYMBOLSET_H
+#define MCLD_LD_SECTIONSYMBOLSET_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/StaticResolver.h b/include/mcld/LD/StaticResolver.h
index 9fc6104..586e44d 100644
--- a/include/mcld/LD/StaticResolver.h
+++ b/include/mcld/LD/StaticResolver.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_STATIC_SYMBOL_RESOLVER_H
-#define MCLD_STATIC_SYMBOL_RESOLVER_H
+#ifndef MCLD_LD_STATICRESOLVER_H
+#define MCLD_LD_STATICRESOLVER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -111,7 +111,7 @@
   /// @param pNew the symbol which is used to replace pOld
   virtual bool resolve(ResolveInfo & __restrict__ pOld,
                        const ResolveInfo & __restrict__ pNew,
-                       bool &pOverride) const;
+                       bool &pOverride, LDSymbol::ValueType pValue) const;
 
 private:
   inline unsigned int getOrdinate(const ResolveInfo& pInfo) const {
diff --git a/include/mcld/LD/StubFactory.h b/include/mcld/LD/StubFactory.h
index 8548e5a..4298c16 100644
--- a/include/mcld/LD/StubFactory.h
+++ b/include/mcld/LD/StubFactory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_STUB_FACTORY_H
-#define MCLD_LD_STUB_FACTORY_H
+#ifndef MCLD_LD_STUBFACTORY_H
+#define MCLD_LD_STUBFACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LD/TextDiagnosticPrinter.h b/include/mcld/LD/TextDiagnosticPrinter.h
index 3e7d4c4..6400fa2 100644
--- a/include/mcld/LD/TextDiagnosticPrinter.h
+++ b/include/mcld/LD/TextDiagnosticPrinter.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TEXT_DIAGNOSTIC_PRINTER_H
-#define MCLD_TEXT_DIAGNOSTIC_PRINTER_H
+#ifndef MCLD_LD_TEXTDIAGNOSTICPRINTER_H
+#define MCLD_LD_TEXTDIAGNOSTICPRINTER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Linker.h b/include/mcld/Linker.h
index 83eb295..80f6586 100644
--- a/include/mcld/Linker.h
+++ b/include/mcld/Linker.h
@@ -27,7 +27,7 @@
 class ObjectLinker;
 
 class FileHandle;
-class MemoryArea;
+class FileOutputBuffer;
 
 /** \class Linker
 *  \brief Linker is a modular linker.
@@ -46,7 +46,7 @@
   bool normalize(Module& pModule, IRBuilder& pBuilder);
 
   /// resolve - To build up the topology of mcld::Module.
-  bool resolve();
+  bool resolve(Module& pModule);
 
   /// layout - To serialize the final result of the output mcld::Module.
   bool layout();
@@ -54,15 +54,15 @@
   /// 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 emit output mcld::Module to a FileOutputBuffer.
+  bool emit(FileOutputBuffer& 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);
+  bool emit(const Module& pModule, const std::string& pPath);
 
   /// emit - To emit output mcld::Module in the pFileDescriptor.
-  bool emit(int pFileDescriptor);
+  bool emit(const Module& pModule, int pFileDescriptor);
 
   bool reset();
 
diff --git a/include/mcld/LinkerConfig.h b/include/mcld/LinkerConfig.h
index 96dd5dc..a41be39 100644
--- a/include/mcld/LinkerConfig.h
+++ b/include/mcld/LinkerConfig.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LINKER_CONFIG_H
-#define MCLD_LINKER_CONFIG_H
+#ifndef MCLD_LINKERCONFIG_H
+#define MCLD_LINKERCONFIG_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/LinkerScript.h b/include/mcld/LinkerScript.h
index 91e4bdb..bdd0917 100644
--- a/include/mcld/LinkerScript.h
+++ b/include/mcld/LinkerScript.h
@@ -6,21 +6,26 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LINKER_SCRIPT_H
-#define MCLD_LINKER_SCRIPT_H
+#ifndef MCLD_LINKERSCRIPT_H
+#define MCLD_LINKERSCRIPT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <string>
+#include <vector>
 #include <llvm/ADT/StringRef.h>
 #include <mcld/ADT/StringEntry.h>
 #include <mcld/ADT/StringHash.h>
 #include <mcld/ADT/HashTable.h>
 #include <mcld/Object/SectionMap.h>
 #include <mcld/MC/SearchDirs.h>
+#include <mcld/Script/Assignment.h>
+#include <mcld/Script/AssertCmd.h>
 
 namespace mcld {
 
+class LDSymbol;
+
 /** \class LinkerScript
  *
  */
@@ -28,16 +33,16 @@
 {
 public:
   typedef HashTable<StringEntry<llvm::StringRef>,
-                    hash::StringHash<hash::ELF>,
+                    hash::StringHash<hash::DJB>,
                     StringEntryFactory<llvm::StringRef> > SymbolRenameMap;
 
   typedef HashTable<StringEntry<uint64_t>,
-                    hash::StringHash<hash::ELF>,
+                    hash::StringHash<hash::DJB>,
                     StringEntryFactory<uint64_t> > AddressMap;
 
-  typedef HashTable<StringEntry<llvm::StringRef>,
-                    hash::StringHash<hash::ELF>,
-                    StringEntryFactory<llvm::StringRef> > DefSymMap;
+  typedef std::vector<std::pair<LDSymbol*, Assignment> > Assignments;
+
+  typedef std::vector<AssertCmd> Assertions;
 
 public:
   LinkerScript();
@@ -53,8 +58,11 @@
   const SectionMap& sectionMap() const { return m_SectionMap; }
   SectionMap&       sectionMap()       { return m_SectionMap; }
 
-  const DefSymMap& defSymMap() const { return m_DefSymMap; }
-  DefSymMap&       defSymMap()       { return m_DefSymMap; }
+  const Assignments& assignments() const { return m_Assignments; }
+  Assignments&       assignments()       { return m_Assignments; }
+
+  const Assertions& assertions() const { return m_Assertions; }
+  Assertions&       assertions()       { return m_Assertions; }
 
   /// search directory
   const SearchDirs& directories() const { return m_SearchDirs; }
@@ -67,12 +75,29 @@
 
   bool hasSysroot() const;
 
+  /// entry point
+  const std::string& entry() const;
+
+  void setEntry(const std::string& pEntry);
+
+  bool hasEntry() const;
+
+  /// output filename
+  const std::string& outputFile() const;
+
+  void setOutputFile(const std::string& pOutputFile);
+
+  bool hasOutputFile() const;
+
 private:
   SymbolRenameMap m_SymbolRenames;
   AddressMap m_AddressMap;
   SectionMap m_SectionMap;
-  DefSymMap m_DefSymMap;
+  Assignments m_Assignments;
+  Assertions m_Assertions;
   SearchDirs m_SearchDirs;
+  std::string m_Entry;
+  std::string m_OutputFile;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/MC/Attribute.h b/include/mcld/MC/Attribute.h
index 11f6d26..a7c7176 100644
--- a/include/mcld/MC/Attribute.h
+++ b/include/mcld/MC/Attribute.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ATTRIBUTE_H
-#define MCLD_ATTRIBUTE_H
+#ifndef MCLD_MC_ATTRIBUTE_H
+#define MCLD_MC_ATTRIBUTE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/MC/AttributeSet.h b/include/mcld/MC/AttributeSet.h
index e50384d..97b20a9 100644
--- a/include/mcld/MC/AttributeSet.h
+++ b/include/mcld/MC/AttributeSet.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ATTRIBUTE_SET_H
-#define MCLD_ATTRIBUTE_SET_H
+#ifndef MCLD_MC_ATTRIBUTESET_H
+#define MCLD_MC_ATTRIBUTESET_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/MC/CommandAction.h b/include/mcld/MC/CommandAction.h
index a0ff909..19f74fd 100644
--- a/include/mcld/MC/CommandAction.h
+++ b/include/mcld/MC/CommandAction.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_COMMAND_ACTION_H
-#define MCLD_MC_COMMAND_ACTION_H
+#ifndef MCLD_MC_COMMANDACTION_H
+#define MCLD_MC_COMMANDACTION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -15,11 +15,13 @@
 #include <string>
 #include <mcld/Support/Path.h>
 #include <mcld/MC/InputAction.h>
+#include <mcld/Script/ScriptFile.h>
 
 namespace mcld {
 
 class SearchDirs;
 class InputBuilder;
+class LinkerConfig;
 
 //===----------------------------------------------------------------------===//
 // Derived InputAction
@@ -44,7 +46,7 @@
 public:
   NamespecAction(unsigned int pPosition,
                  const std::string &pNamespec,
-                 SearchDirs& pSearchDirs);
+                 const SearchDirs& pSearchDirs);
 
   const std::string &namespec() const { return m_Namespec; }
 
@@ -52,7 +54,7 @@
 
 private:
   std::string m_Namespec;
-  SearchDirs& m_SearchDirs;
+  const SearchDirs& m_SearchDirs;
 };
 
 /// BitcodeAction
@@ -159,6 +161,41 @@
   bool activate(InputBuilder&) const;
 };
 
+/// DefSymAction
+class DefSymAction : public InputAction
+{
+public:
+  explicit DefSymAction(unsigned int pPosition, std::string& pAssignment);
+
+  bool activate(InputBuilder&) const;
+
+  const std::string& assignment() const { return m_Assignment; }
+
+private:
+  std::string& m_Assignment;
+};
+
+/// ScriptAction
+class ScriptAction : public InputAction
+{
+public:
+  ScriptAction(unsigned int pPosition,
+               const std::string& pFileName,
+               ScriptFile::Kind pKind,
+               const SearchDirs& pSearchDirs);
+
+  bool activate(InputBuilder&) const;
+
+  const std::string& filename() const { return m_FileName; }
+
+  ScriptFile::Kind kind() const { return m_Kind; }
+
+private:
+  std::string m_FileName;
+  ScriptFile::Kind m_Kind;
+  const SearchDirs& m_SearchDirs;
+};
+
 } // end of namespace mcld
 
 #endif
diff --git a/include/mcld/MC/ContextFactory.h b/include/mcld/MC/ContextFactory.h
index dde2627..169dbfa 100644
--- a/include/mcld/MC/ContextFactory.h
+++ b/include/mcld/MC/ContextFactory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_CONTEXT_FACTORY_H
-#define MCLD_CONTEXT_FACTORY_H
+#ifndef MCLD_MC_CONTEXTFACTORY_H
+#define MCLD_MC_CONTEXTFACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/MC/FileAction.h b/include/mcld/MC/FileAction.h
index 4644405..269c700 100644
--- a/include/mcld/MC/FileAction.h
+++ b/include/mcld/MC/FileAction.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_FILE_ACTION_H
-#define MCLD_MC_FILE_ACTION_H
+#ifndef MCLD_MC_FILEACTION_H
+#define MCLD_MC_FILEACTION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -17,7 +17,6 @@
 namespace mcld {
 
 class ContextFactory;
-class MemoryAreaFactory;
 
 /** \class ContextAction
  *  \brief ContextAction is a command object to create input's LDContext.
diff --git a/include/mcld/MC/MCLDInput.h b/include/mcld/MC/Input.h
similarity index 95%
rename from include/mcld/MC/MCLDInput.h
rename to include/mcld/MC/Input.h
index 94b9479..a8e9c35 100644
--- a/include/mcld/MC/MCLDInput.h
+++ b/include/mcld/MC/Input.h
@@ -1,4 +1,4 @@
-//===- MCLDInput.h --------------------------------------------------------===//
+//===- Input.h ------------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -10,8 +10,8 @@
 //  Input class inherits MCLDFile, which is used to represent a input file
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_INPUT_H
-#define MCLD_INPUT_H
+#ifndef MCLD_MC_INPUT_H
+#define MCLD_MC_INPUT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -35,6 +35,7 @@
 public:
   enum Type {
     Unknown,
+    Binary,
     Object,
     Exec,
     DynObj,
diff --git a/include/mcld/MC/InputAction.h b/include/mcld/MC/InputAction.h
index fb7d660..4b94378 100644
--- a/include/mcld/MC/InputAction.h
+++ b/include/mcld/MC/InputAction.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_INPUT_ACTION_H
-#define MCLD_MC_INPUT_ACTION_H
+#ifndef MCLD_MC_INPUTACTION_H
+#define MCLD_MC_INPUTACTION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/MC/InputBuilder.h b/include/mcld/MC/InputBuilder.h
index 0301c15..1b2e8b9 100644
--- a/include/mcld/MC/InputBuilder.h
+++ b/include/mcld/MC/InputBuilder.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_INPUT_BUILDER_H
-#define MCLD_MC_INPUT_BUILDER_H
+#ifndef MCLD_MC_INPUTBUILDER_H
+#define MCLD_MC_INPUTBUILDER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -16,7 +16,7 @@
 #include <stack>
 
 #include <mcld/InputTree.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/Support/FileHandle.h>
 
 namespace mcld {
@@ -26,7 +26,6 @@
 class ContextFactory;
 class MemoryAreaFactory;
 class AttrConstraint;
-class raw_mem_ostream;
 
 /** \class InputBuilder
  *  \brief InputBuilder recieves InputActions and build the InputTree.
diff --git a/include/mcld/MC/InputFactory.h b/include/mcld/MC/InputFactory.h
index d644222..8c73d0b 100644
--- a/include/mcld/MC/InputFactory.h
+++ b/include/mcld/MC/InputFactory.h
@@ -6,13 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_INPUT_FACTORY_H
-#define MCLD_INPUT_FACTORY_H
+#ifndef MCLD_MC_INPUTFACTORY_H
+#define MCLD_MC_INPUTFACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <mcld/Support/GCFactory.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 
 namespace mcld {
 
diff --git a/include/mcld/MC/MCLDDirectory.h b/include/mcld/MC/MCLDDirectory.h
index 988f9d3..77692c0 100644
--- a/include/mcld/MC/MCLDDirectory.h
+++ b/include/mcld/MC/MCLDDirectory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MCLDDIRECTORY_H
-#define MCLD_MCLDDIRECTORY_H
+#ifndef MCLD_MC_MCLDDIRECTORY_H
+#define MCLD_MC_MCLDDIRECTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/MC/SearchDirs.h b/include/mcld/MC/SearchDirs.h
index 0c0c657..a3bcf39 100644
--- a/include/mcld/MC/SearchDirs.h
+++ b/include/mcld/MC/SearchDirs.h
@@ -12,7 +12,7 @@
 #include <gtest.h>
 #endif
 #include <mcld/ADT/Uncopyable.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/Support/Path.h>
 
 #include <llvm/ADT/StringRef.h>
diff --git a/include/mcld/MC/SymbolCategory.h b/include/mcld/MC/SymbolCategory.h
index 61c015e..9ecc5b9 100644
--- a/include/mcld/MC/SymbolCategory.h
+++ b/include/mcld/MC/SymbolCategory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SYMBOL_CATEGORY_H
-#define MCLD_SYMBOL_CATEGORY_H
+#ifndef MCLD_MC_SYMBOLCATEGORY_H
+#define MCLD_MC_SYMBOLCATEGORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/MC/ZOption.h b/include/mcld/MC/ZOption.h
index e451734..d9cd635 100644
--- a/include/mcld/MC/ZOption.h
+++ b/include/mcld/MC/ZOption.h
@@ -6,15 +6,15 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ZOPTION_H
-#define MCLD_ZOPTION_H
+#ifndef MCLD_MC_ZOPTION_H
+#define MCLD_MC_ZOPTION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
+
 #include <llvm/Support/DataTypes.h>
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class ZOption
  *  \brief The -z options for GNU ld compatibility.
@@ -50,19 +50,13 @@
 public:
   ZOption();
 
-  ~ZOption();
+  Kind kind() const { return m_Kind; }
 
-  Kind kind() const
-  { return m_Kind; }
+  void setKind(Kind pKind) { m_Kind = pKind; }
 
-  uint64_t pageSize() const
-  { return m_PageSize; }
+  uint64_t pageSize() const { return m_PageSize; }
 
-  void setKind(Kind pKind)
-  { m_Kind = pKind; }
-
-  void setPageSize(uint64_t pPageSize)
-  { m_PageSize = pPageSize; }
+  void setPageSize(uint64_t pPageSize) { m_PageSize = pPageSize; }
 
 private:
   Kind m_Kind;
diff --git a/include/mcld/Module.h b/include/mcld/Module.h
index 9ea9812..9dfb59e 100644
--- a/include/mcld/Module.h
+++ b/include/mcld/Module.h
@@ -16,25 +16,18 @@
 #include <gtest.h>
 #endif
 
-#include <vector>
-#include <string>
-#include <map>
-
-#include <mcld/LinkerScript.h>
 #include <mcld/InputTree.h>
-#include <mcld/ADT/HashTable.h>
-#include <mcld/ADT/HashEntry.h>
-#include <mcld/Support/GCFactoryListTraits.h>
-#include <mcld/Fragment/Fragment.h>
 #include <mcld/LD/NamePool.h>
 #include <mcld/LD/SectionSymbolSet.h>
 #include <mcld/MC/SymbolCategory.h>
-#include <mcld/MC/MCLDInput.h>
 
-#include <llvm/ADT/ilist.h>
+#include <vector>
+#include <string>
 
 namespace mcld {
 
+class Input;
+class LinkerScript;
 class LDSection;
 class LDSymbol;
 
diff --git a/include/mcld/Object/ObjectBuilder.h b/include/mcld/Object/ObjectBuilder.h
index 79f81a5..ec80528 100644
--- a/include/mcld/Object/ObjectBuilder.h
+++ b/include/mcld/Object/ObjectBuilder.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_OBJECT_OBJECT_BUILDER_H
-#define MCLD_OBJECT_OBJECT_BUILDER_H
+#ifndef MCLD_OBJECT_OBJECTBUILDER_H
+#define MCLD_OBJECT_OBJECTBUILDER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -27,6 +27,7 @@
 class RelocData;
 class Fragment;
 class Relocation;
+class Input;
 
 /** \class ObjectBuilder
  *  \brief ObjectBuilder recieve ObjectAction and build the mcld::Module.
@@ -67,7 +68,7 @@
   /// @param [in] pInputSection The merged input section.
   /// @return The merged output section. If the corresponding output sections
   /// is not defined, return NULL.
-  LDSection* MergeSection(LDSection& pInputSection);
+  LDSection* MergeSection(const Input& pInputFile, LDSection& pInputSection);
 
   /// MoveSectionData - move the fragment of pFrom to pTo section data.
   static bool MoveSectionData(SectionData& pFrom, SectionData& pTo);
diff --git a/include/mcld/Object/ObjectLinker.h b/include/mcld/Object/ObjectLinker.h
index 128cf64..5c8c5cc 100644
--- a/include/mcld/Object/ObjectLinker.h
+++ b/include/mcld/Object/ObjectLinker.h
@@ -6,39 +6,34 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-//
-// ObjectLinker plays the same role as GNU collect2 to prepare all implicit
-// parameters for FragmentLinker.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_OBJECT_OBJECT_LINKER_H
-#define MCLD_OBJECT_OBJECT_LINKER_H
+#ifndef MCLD_OBJECT_OBJECTLINKER_H
+#define MCLD_OBJECT_OBJECTLINKER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <stddef.h>
+#include <llvm/Support/DataTypes.h>
 
 namespace mcld {
 
 class Module;
 class LinkerConfig;
 class IRBuilder;
-class FragmentLinker;
 class TargetLDBackend;
-class MemoryArea;
-class MemoryAreaFactory;
+class FileOutputBuffer;
 class ObjectReader;
 class DynObjReader;
 class ArchiveReader;
 class GroupReader;
 class BinaryReader;
+class ScriptReader;
 class ObjectWriter;
 class DynObjWriter;
 class ExecWriter;
 class BinaryWriter;
+class Relocation;
+class ResolveInfo;
 
 /** \class ObjectLinker
- *  \brief ObjectLinker prepares parameters for FragmentLinker.
  */
 class ObjectLinker
 {
@@ -48,11 +43,7 @@
 
   ~ObjectLinker();
 
-  void setup(Module& pModule, IRBuilder& pBuilder);
-
-  /// initFragmentLinker - initialize FragmentLinker
-  ///  Connect all components in FragmentLinker
-  bool initFragmentLinker();
+  bool initialize(Module& pModule, IRBuilder& pBuilder);
 
   /// initStdSections - initialize standard sections of the output file.
   bool initStdSections();
@@ -69,9 +60,16 @@
   /// readRelocations - read all relocation entries
   bool readRelocations();
 
+  /// dataStrippingOpt - optimizations for reducing code size
+  void dataStrippingOpt();
+
   /// mergeSections - put allinput sections into output sections
   bool mergeSections();
 
+  /// addSymbolsToOutput - after all symbols has been resolved, add the symbol
+  /// to output
+  void addSymbolsToOutput(Module& pModule);
+
   /// allocateCommonSymobols - allocate fragments for common symbols to the
   /// corresponding sections
   bool allocateCommonSymbols();
@@ -122,18 +120,10 @@
   bool finalizeSymbolValue();
 
   /// emitOutput - emit the output file.
-  bool emitOutput(MemoryArea& pOutput);
+  bool emitOutput(FileOutputBuffer& pOutput);
 
   /// postProcessing - do modificatiion after all processes
-  bool postProcessing(MemoryArea& pOutput);
-
-  /// getLinker - get internal FragmentLinker object
-  const FragmentLinker* getLinker() const { return m_pLinker; }
-  FragmentLinker*       getLinker()       { return m_pLinker; }
-
-  /// hasInitLinker - has Linker been initialized?
-  bool hasInitLinker() const
-  { return (NULL != m_pLinker); }
+  bool postProcessing(FileOutputBuffer& pOutput);
 
   // -----  readers and writers  ----- //
   const ObjectReader*  getObjectReader () const { return m_pObjectReader;  }
@@ -151,12 +141,31 @@
   const BinaryReader*  getBinaryReader () const { return m_pBinaryReader;  }
   BinaryReader*        getBinaryReader ()       { return m_pBinaryReader;  }
 
+  const ScriptReader*  getScriptReader () const { return m_pScriptReader;  }
+  ScriptReader*        getScriptReader ()       { return m_pScriptReader;  }
+
   const ObjectWriter*  getWriter () const { return m_pWriter;  }
   ObjectWriter*        getWriter ()       { return m_pWriter;  }
 
 private:
+  /// normalSyncRelocationResult - sync relocation result when producing shared
+  /// objects or executables
+  void normalSyncRelocationResult(FileOutputBuffer& pOutput);
+
+  /// partialSyncRelocationResult - sync relocation result when doing partial
+  /// link
+  void partialSyncRelocationResult(FileOutputBuffer& pOutput);
+
+  /// writeRelocationResult - helper function of syncRelocationResult, write
+  /// relocation target data to output
+  void writeRelocationResult(Relocation& pReloc, uint8_t* pOutput);
+
+  /// addSymbolToOutput - add a symbol to output symbol table if it's not a
+  /// section symbol and not defined in the discarded section
+  void addSymbolToOutput(ResolveInfo& pInfo, Module& pModule);
+
+private:
   const LinkerConfig& m_Config;
-  FragmentLinker* m_pLinker;
   Module* m_pModule;
   IRBuilder* m_pBuilder;
 
@@ -168,6 +177,7 @@
   ArchiveReader* m_pArchiveReader;
   GroupReader*   m_pGroupReader;
   BinaryReader*  m_pBinaryReader;
+  ScriptReader*  m_pScriptReader;
   ObjectWriter*  m_pWriter;
 };
 
diff --git a/include/mcld/Object/SectionMap.h b/include/mcld/Object/SectionMap.h
index 37df4a3..e6e779d 100644
--- a/include/mcld/Object/SectionMap.h
+++ b/include/mcld/Object/SectionMap.h
@@ -6,82 +6,206 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTION_MAP_H
-#define MCLD_SECTION_MAP_H
+#ifndef MCLD_OBJECT_SECTIONMAP_H
+#define MCLD_OBJECT_SECTIONMAP_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
+#include <mcld/Script/OutputSectDesc.h>
+#include <mcld/Script/InputSectDesc.h>
+#include <mcld/Script/Assignment.h>
+#include <llvm/Support/DataTypes.h>
 #include <vector>
 #include <string>
 
-#include <llvm/Support/DataTypes.h>
-
 namespace mcld {
 
+class Fragment;
+class LDSection;
+
 /** \class SectionMap
- *  \brief descirbe the mappings of input section's name (or prefix) to
- *         its associated output section's name and offset
+ *  \brief descirbe how to map input sections into output sections
  */
 class SectionMap
 {
 public:
-  // a mapping in SectionMap is the triple of
-  // {input substr, output section's name, output section's offset}
-  struct NamePair
-  {
+  class Input {
   public:
-    NamePair();
-    NamePair(const std::string& pFrom, const std::string& pTo);
+    typedef std::vector<std::pair<Fragment*, Assignment> > DotAssignments;
+    typedef DotAssignments::const_iterator const_dot_iterator;
+    typedef DotAssignments::iterator dot_iterator;
 
-    bool isNull() const;
+    Input(const std::string& pName, InputSectDesc::KeepPolicy pPolicy);
+    Input(const InputSectDesc& pInputDesc);
 
-  public:
-    unsigned int hash;
-    std::string from;
-    std::string to;
+    InputSectDesc::KeepPolicy policy() const { return m_Policy; }
+
+    const InputSectDesc::Spec& spec() const { return m_Spec; }
+
+    const LDSection* getSection() const { return m_pSection; }
+    LDSection*       getSection()       { return m_pSection; }
+
+    const_dot_iterator dot_begin() const { return m_DotAssignments.begin(); }
+    dot_iterator       dot_begin()       { return m_DotAssignments.begin(); }
+    const_dot_iterator dot_end  () const { return m_DotAssignments.end(); }
+    dot_iterator       dot_end  ()       { return m_DotAssignments.end(); }
+
+    const DotAssignments& dotAssignments() const { return m_DotAssignments; }
+    DotAssignments&       dotAssignments()       { return m_DotAssignments; }
+
+  private:
+    InputSectDesc::KeepPolicy m_Policy;
+    InputSectDesc::Spec m_Spec;
+    LDSection* m_pSection;
+    DotAssignments m_DotAssignments;
   };
 
-  typedef std::vector<NamePair> NamePairList;
-  typedef NamePairList::iterator iterator;
-  typedef NamePairList::const_iterator const_iterator;
+  class Output {
+  public:
+    typedef std::vector<Input*> InputList;
+    typedef InputList::const_iterator const_iterator;
+    typedef InputList::iterator iterator;
+    typedef InputList::const_reference const_reference;
+    typedef InputList::reference reference;
 
-  /// NullName - the null object of NamePair
-  static NamePair NullName;
+    typedef std::vector<Assignment> DotAssignments;
+    typedef DotAssignments::const_iterator const_dot_iterator;
+    typedef DotAssignments::iterator dot_iterator;
+
+    Output(const std::string& pName);
+    Output(const OutputSectDesc& pOutputDesc);
+
+    const std::string& name() const { return m_Name; }
+
+    const OutputSectDesc::Prolog& prolog() const { return m_Prolog; }
+    OutputSectDesc::Prolog&       prolog()       { return m_Prolog; }
+
+    const OutputSectDesc::Epilog& epilog() const { return m_Epilog; }
+    OutputSectDesc::Epilog&       epilog()       { return m_Epilog; }
+
+    size_t order() const { return m_Order; }
+
+    void setOrder(size_t pOrder) { m_Order = pOrder; }
+
+    bool hasContent() const;
+
+    const LDSection* getSection() const { return m_pSection; }
+    LDSection*       getSection()       { return m_pSection; }
+
+    void setSection(LDSection* pSection) { m_pSection = pSection; }
+
+    const_iterator begin() const { return m_InputList.begin(); }
+    iterator       begin()       { return m_InputList.begin(); }
+    const_iterator end  () const { return m_InputList.end(); }
+    iterator       end  ()       { return m_InputList.end(); }
+
+    const_reference front() const { return m_InputList.front(); }
+    reference       front()       { return m_InputList.front(); }
+    const_reference back () const { return m_InputList.back(); }
+    reference       back ()       { return m_InputList.back(); }
+
+    size_t size() const { return m_InputList.size(); }
+
+    bool empty() const { return m_InputList.empty(); }
+
+    bool isDiscard() const { return m_bIsDiscard; }
+
+    void append(Input* pInput) { m_InputList.push_back(pInput); }
+
+    const_dot_iterator dot_begin() const { return m_DotAssignments.begin(); }
+    dot_iterator       dot_begin()       { return m_DotAssignments.begin(); }
+    const_dot_iterator dot_end  () const { return m_DotAssignments.end(); }
+    dot_iterator       dot_end  ()       { return m_DotAssignments.end(); }
+
+    const_dot_iterator find_first_explicit_dot() const;
+    dot_iterator       find_first_explicit_dot();
+
+    const_dot_iterator find_last_explicit_dot() const;
+    dot_iterator       find_last_explicit_dot();
+
+    const DotAssignments& dotAssignments() const { return m_DotAssignments; }
+    DotAssignments&       dotAssignments()       { return m_DotAssignments; }
+
+  private:
+    std::string m_Name;
+    OutputSectDesc::Prolog m_Prolog;
+    OutputSectDesc::Epilog m_Epilog;
+    LDSection* m_pSection;
+    size_t m_Order;
+    bool m_bIsDiscard;
+    InputList m_InputList;
+    DotAssignments m_DotAssignments;
+  };
+
+  struct SHOCompare
+  {
+    bool operator()(const Output* LHS, const Output* RHS) const
+    { return LHS->order() < RHS->order(); }
+  };
+
+  typedef std::pair<const Output*, const Input*> const_mapping;
+  typedef std::pair<Output*, Input*> mapping;
+
+  typedef std::vector<Output*> OutputDescList;
+  typedef OutputDescList::const_iterator const_iterator;
+  typedef OutputDescList::iterator iterator;
+  typedef OutputDescList::const_reference const_reference;
+  typedef OutputDescList::reference reference;
+
+  typedef OutputDescList::const_reverse_iterator const_reverse_iterator;
+  typedef OutputDescList::reverse_iterator reverse_iterator;
 
 public:
-  // get the possible output section name based on the mapping table
-  // return NullPair if not found
-  const NamePair& find(const std::string& pFrom) const;
-  NamePair&       find(const std::string& pFrom);
+  ~SectionMap();
 
-  const NamePair& find(const std::string& pFrom, unsigned int pHash) const;
-  NamePair&       find(const std::string& pFrom, unsigned int pHash);
+  const_mapping find(const std::string& pInputFile,
+                     const std::string& pInputSection) const;
+  mapping       find(const std::string& pInputFile,
+                     const std::string& pInputSection);
 
-  // add a mapping from input sub-string to output name.
-  // @param [in]  pFrom  the given input sub-string
-  // @param [in]  pTo    the mapped output string
-  // @param [out] pExist does pFrom exist?
-  NamePair& append(const std::string& pFrom,
-                   const std::string& pTo,
-                   bool& pExist);
+  const_iterator find(const std::string& pOutputSection) const;
+  iterator       find(const std::string& pOutputSection);
 
-  const_iterator begin() const { return m_NamePairList.begin(); }
-  iterator       begin()       { return m_NamePairList.begin(); }
-  const_iterator end  () const { return m_NamePairList.end(); }
-  iterator       end  ()       { return m_NamePairList.end(); }
+  std::pair<mapping, bool>
+  insert(const std::string& pInputSection,
+         const std::string& pOutputSection,
+         InputSectDesc::KeepPolicy pPolicy = InputSectDesc::NoKeep);
+  std::pair<mapping, bool>
+  insert(const InputSectDesc& pInputDesc, const OutputSectDesc& pOutputDesc);
 
-  bool           empty() const { return m_NamePairList.empty(); }
-  size_t         size () const { return m_NamePairList.size(); }
+  bool   empty() const { return m_OutputDescList.empty(); }
+  size_t size () const { return m_OutputDescList.size(); }
 
-  static unsigned int hash(const std::string& pString);
+  const_iterator begin() const { return m_OutputDescList.begin(); }
+  iterator       begin()       { return m_OutputDescList.begin(); }
+  const_iterator end  () const { return m_OutputDescList.end(); }
+  iterator       end  ()       { return m_OutputDescList.end(); }
+
+  const_reference front() const { return m_OutputDescList.front(); }
+  reference       front()       { return m_OutputDescList.front(); }
+  const_reference back () const { return m_OutputDescList.back(); }
+  reference       back ()       { return m_OutputDescList.back(); }
+
+  const_reverse_iterator rbegin() const { return m_OutputDescList.rbegin(); }
+  reverse_iterator       rbegin()       { return m_OutputDescList.rbegin(); }
+  const_reverse_iterator rend  () const { return m_OutputDescList.rend(); }
+  reverse_iterator       rend  ()       { return m_OutputDescList.rend(); }
+
+  iterator insert(iterator pPosition, LDSection* pSection);
+
+  // fixupDotSymbols - ensure the dot assignments are valid
+  void fixupDotSymbols();
 
 private:
-  bool matched(const NamePair& pNamePair,
-               const std::string& pInput,
-               unsigned int pHash) const;
+  bool matched(const Input& pInput,
+               const std::string& pInputFile,
+               const std::string& pInputSection) const;
+
+  bool matched(const WildcardPattern& pPattern, const std::string& pName) const;
+
 private:
-  NamePairList m_NamePairList;
+  OutputDescList m_OutputDescList;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Script/AssertCmd.h b/include/mcld/Script/AssertCmd.h
new file mode 100644
index 0000000..1e57375
--- /dev/null
+++ b/include/mcld/Script/AssertCmd.h
@@ -0,0 +1,58 @@
+//===- AssertCmd.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_ASSERTCMD_H
+#define MCLD_SCRIPT_ASSERTCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class RpnExpr;
+class Module;
+
+/** \class AssertCmd
+ *  \brief This class defines the interfaces to assert command.
+ */
+
+class AssertCmd : public ScriptCommand
+{
+public:
+  AssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage);
+
+  ~AssertCmd();
+
+  AssertCmd& operator=(const AssertCmd& pAssertCmd);
+
+  const RpnExpr& getRpnExpr() const { return m_RpnExpr; }
+  RpnExpr&       getRpnExpr()       { return m_RpnExpr; }
+
+  const std::string& message() const { return m_Message; }
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::ASSERT;
+  }
+
+  void activate(Module& pModule);
+
+private:
+  RpnExpr& m_RpnExpr;
+  std::string m_Message;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/Assignment.h b/include/mcld/Script/Assignment.h
new file mode 100644
index 0000000..068735d
--- /dev/null
+++ b/include/mcld/Script/Assignment.h
@@ -0,0 +1,87 @@
+//===- Assignment.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_ASSIGNMENT_H
+#define MCLD_SCRIPT_ASSIGNMENT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+
+namespace mcld
+{
+
+class Module;
+class RpnExpr;
+class SymOperand;
+class RpnEvaluator;
+
+/** \class Assignment
+ *  \brief This class defines the interfaces to assignment command.
+ */
+
+class Assignment : public ScriptCommand
+{
+public:
+  enum Level {
+    OUTSIDE_SECTIONS, // outside SECTIONS command
+    OUTPUT_SECTION,   // related to an output section
+    INPUT_SECTION     // related to an input section
+  };
+
+  enum Type {
+    DEFAULT,
+    HIDDEN,
+    PROVIDE,
+    PROVIDE_HIDDEN
+  };
+
+public:
+  Assignment(Level pLevel,
+             Type pType,
+             SymOperand& pSymbol,
+             RpnExpr& pRpnExpr);
+
+  ~Assignment();
+
+  Assignment& operator=(const Assignment& pAssignment);
+
+  Level level() const { return m_Level; }
+
+  Type type() const { return m_Type; }
+
+  const SymOperand& symbol() const { return m_Symbol; }
+  SymOperand&       symbol()       { return m_Symbol; }
+
+  const RpnExpr& getRpnExpr() const { return m_RpnExpr; }
+  RpnExpr&       getRpnExpr()       { return m_RpnExpr; }
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::ASSIGNMENT;
+  }
+
+  void activate(Module& pModule);
+
+  /// assign - evaluate the rhs and assign the result to lhs.
+  bool assign(RpnEvaluator& pEvaluator);
+
+private:
+  Level m_Level;
+  Type m_Type;
+  SymOperand& m_Symbol;
+  RpnExpr& m_RpnExpr;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/BinaryOp.h b/include/mcld/Script/BinaryOp.h
new file mode 100644
index 0000000..884c0c1
--- /dev/null
+++ b/include/mcld/Script/BinaryOp.h
@@ -0,0 +1,135 @@
+//===- BinaryOp.h ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_BINARYOP_H
+#define MCLD_SCRIPT_BINARYOP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Operator.h>
+#include <cstddef>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class BinaryOP
+ *  \brief This class defines the interfaces to an binary operator token.
+ */
+
+template<Operator::Type TYPE>
+class BinaryOp : public Operator
+{
+private:
+  friend class Operator;
+
+  BinaryOp()
+    : Operator(Operator::BINARY, TYPE), m_Size(0)
+  {
+    m_pOperand[0] = m_pOperand[1] = NULL;
+  }
+
+public:
+  ~BinaryOp()
+  {}
+
+  IntOperand* eval(const Module& pModule, const TargetLDBackend& pBackend);
+
+  void appendOperand(Operand* pOperand)
+  {
+    m_pOperand[m_Size++] = pOperand;
+    if (m_Size == 2)
+      m_Size = 0;
+  }
+
+private:
+  size_t m_Size;
+  Operand* m_pOperand[2];
+};
+
+template<>
+IntOperand* BinaryOp<Operator::MUL>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::DIV>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::MOD>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::ADD>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::SUB>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LSHIFT>::eval(const Module&,
+                                             const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::RSHIFT>::eval(const Module&,
+                                             const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LT>::eval(const Module&,
+                                         const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LE>::eval(const Module&,
+                                         const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::GT>::eval(const Module&,
+                                         const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::GE>::eval(const Module&,
+                                         const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::EQ>::eval(const Module&,
+                                         const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::NE>::eval(const Module&,
+                                         const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::BITWISE_AND>::eval(const Module&,
+                                                  const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::BITWISE_XOR>::eval(const Module&,
+                                                  const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::BITWISE_OR>::eval(const Module&,
+                                                 const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LOGICAL_AND>::eval(const Module&,
+                                                  const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LOGICAL_OR>::eval(const Module&,
+                                                 const TargetLDBackend&);
+
+template<>
+IntOperand* BinaryOp<Operator::ALIGN>::eval(const Module&,
+                                            const TargetLDBackend&);
+template<>
+IntOperand*
+BinaryOp<Operator::DATA_SEGMENT_RELRO_END>::eval(const Module&,
+                                                 const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::MAX>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::MIN>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::SEGMENT_START>::eval(const Module&,
+                                                    const TargetLDBackend&);
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/EntryCmd.h b/include/mcld/Script/EntryCmd.h
new file mode 100644
index 0000000..acbdd10
--- /dev/null
+++ b/include/mcld/Script/EntryCmd.h
@@ -0,0 +1,49 @@
+//===- EntryCmd.h ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_ENTRYCMD_H
+#define MCLD_SCRIPT_ENTRYCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class EntryCmd
+ *  \brief This class defines the interfaces to Entry command.
+ */
+
+class EntryCmd : public ScriptCommand
+{
+public:
+  EntryCmd(const std::string& pEntry);
+  ~EntryCmd();
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::ENTRY;
+  }
+
+  void activate(Module& pModule);
+
+private:
+  std::string m_Entry;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ExprToken.h b/include/mcld/Script/ExprToken.h
new file mode 100644
index 0000000..be248d5
--- /dev/null
+++ b/include/mcld/Script/ExprToken.h
@@ -0,0 +1,50 @@
+//===- ExprToken.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_EXPRTOKEN_H
+#define MCLD_SCRIPT_EXPRTOKEN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld
+{
+
+/** \class ExprToken
+ *  \brief This class defines the interfaces to an expression token.
+ */
+
+class ExprToken
+{
+public:
+  enum Kind {
+    OPERATOR,
+    OPERAND
+  };
+
+protected:
+  ExprToken(Kind pKind)
+    : m_Kind(pKind)
+  {}
+
+public:
+  virtual ~ExprToken()
+  {}
+
+  virtual void dump() const = 0;
+
+  Kind kind() const { return m_Kind; }
+
+private:
+  Kind m_Kind;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/FileToken.h b/include/mcld/Script/FileToken.h
new file mode 100644
index 0000000..92faab4
--- /dev/null
+++ b/include/mcld/Script/FileToken.h
@@ -0,0 +1,50 @@
+//===- FileToken.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_FILETOKEN_H
+#define MCLD_SCRIPT_FILETOKEN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/InputToken.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+
+namespace mcld
+{
+
+/** \class FileToken
+ *  \brief This class defines the interfaces to a filename in INPUT/GROUP
+ *         command.
+ */
+
+class FileToken : public InputToken
+{
+private:
+  friend class Chunk<FileToken, MCLD_SYMBOLS_PER_INPUT>;
+  FileToken();
+  FileToken(const std::string& pName, bool pAsNeeded);
+
+public:
+  ~FileToken();
+
+  static bool classof(const InputToken* pToken)
+  {
+    return pToken->type() == InputToken::File;
+  }
+
+  /* factory method */
+  static FileToken* create(const std::string& pName, bool pAsNeeded);
+  static void destroy(FileToken*& pToken);
+  static void clear();
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Script/FlexLexer.h b/include/mcld/Script/FlexLexer.h
new file mode 100644
index 0000000..f09ab20
--- /dev/null
+++ b/include/mcld/Script/FlexLexer.h
@@ -0,0 +1,215 @@
+//===- FlexLexer.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// -*-C++-*-
+// FlexLexer.h -- define interfaces for lexical analyzer classes generated
+// by flex
+
+// Copyright (c) 1993 The Regents of the University of California.
+// All rights reserved.
+//
+// This code is derived from software contributed to Berkeley by
+// Kent Williams and Tom Epperly.
+//
+//  Redistribution and use in source and binary forms, with or without
+//  modification, are permitted provided that the following conditions
+//  are met:
+
+//  1. Redistributions of source code must retain the above copyright
+//  notice, this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright
+//  notice, this list of conditions and the following disclaimer in the
+//  documentation and/or other materials provided with the distribution.
+
+//  Neither the name of the University nor the names of its contributors
+//  may be used to endorse or promote products derived from this software
+//  without specific prior written permission.
+
+//  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+//  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+//  PURPOSE.
+
+// This file defines FlexLexer, an abstract class which specifies the
+// external interface provided to flex C++ lexer objects, and yyFlexLexer,
+// which defines a particular lexer class.
+//
+// If you want to create multiple lexer classes, you use the -P flag
+// to rename each yyFlexLexer to some other xxFlexLexer.  You then
+// include <FlexLexer.h> in your other sources once per lexer class:
+//
+//	#undef yyFlexLexer
+//	#define yyFlexLexer xxFlexLexer
+//	#include <FlexLexer.h>
+//
+//	#undef yyFlexLexer
+//	#define yyFlexLexer zzFlexLexer
+//	#include <FlexLexer.h>
+//	...
+
+#ifndef __FLEX_LEXER_H
+// Never included before - need to define base class.
+#define __FLEX_LEXER_H
+
+#include <iostream>
+#  ifndef FLEX_STD
+#    define FLEX_STD std::
+#  endif
+
+extern "C++" {
+
+struct yy_buffer_state;
+typedef int yy_state_type;
+
+class FlexLexer {
+public:
+	virtual ~FlexLexer()	{ }
+
+	const char* YYText() const	{ return yytext; }
+	int YYLeng()	const	{ return yyleng; }
+
+	virtual void
+		yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0;
+	virtual struct yy_buffer_state*
+		yy_create_buffer( FLEX_STD istream* s, int size ) = 0;
+	virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0;
+	virtual void yyrestart( FLEX_STD istream* s ) = 0;
+
+	virtual int yylex() = 0;
+
+	// Call yylex with new input/output sources.
+	int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 )
+		{
+		switch_streams( new_in, new_out );
+		return yylex();
+		}
+
+	// Switch to new input/output streams.  A nil stream pointer
+	// indicates "keep the current one".
+	virtual void switch_streams( FLEX_STD istream* new_in = 0,
+					FLEX_STD ostream* new_out = 0 ) = 0;
+
+	int lineno() const		{ return yylineno; }
+
+	int debug() const		{ return yy_flex_debug; }
+	void set_debug( int flag )	{ yy_flex_debug = flag; }
+
+protected:
+	char* yytext;
+	int yyleng;
+	int yylineno;		// only maintained if you use %option yylineno
+	int yy_flex_debug;	// only has effect with -d or "%option debug"
+};
+
+}
+#endif // FLEXLEXER_H
+
+#if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce)
+// Either this is the first time through (yyFlexLexerOnce not defined),
+// or this is a repeated include to define a different flavor of
+// yyFlexLexer, as discussed in the flex manual.
+#define yyFlexLexerOnce
+
+extern "C++" {
+
+class yyFlexLexer : public FlexLexer {
+public:
+	// arg_yyin and arg_yyout default to the cin and cout, but we
+	// only make that assignment when initializing in yylex().
+	yyFlexLexer( FLEX_STD istream* arg_yyin = 0, FLEX_STD ostream* arg_yyout = 0 );
+
+	virtual ~yyFlexLexer();
+
+	void yy_switch_to_buffer( struct yy_buffer_state* new_buffer );
+	struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size );
+	void yy_delete_buffer( struct yy_buffer_state* b );
+	void yyrestart( FLEX_STD istream* s );
+
+	void yypush_buffer_state( struct yy_buffer_state* new_buffer );
+	void yypop_buffer_state();
+
+	virtual int yylex();
+	virtual void switch_streams( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 );
+	virtual int yywrap();
+
+protected:
+	virtual int LexerInput( char* buf, int max_size );
+	virtual void LexerOutput( const char* buf, int size );
+	virtual void LexerError( const char* msg );
+
+	void yyunput( int c, char* buf_ptr );
+	int yyinput();
+
+	void yy_load_buffer_state();
+	void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream* s );
+	void yy_flush_buffer( struct yy_buffer_state* b );
+
+	int yy_start_stack_ptr;
+	int yy_start_stack_depth;
+	int* yy_start_stack;
+
+	void yy_push_state( int new_state );
+	void yy_pop_state();
+	int yy_top_state();
+
+	yy_state_type yy_get_previous_state();
+	yy_state_type yy_try_NUL_trans( yy_state_type current_state );
+	int yy_get_next_buffer();
+
+	FLEX_STD istream* yyin;	// input source for default LexerInput
+	FLEX_STD ostream* yyout;	// output sink for default LexerOutput
+
+	// yy_hold_char holds the character lost when yytext is formed.
+	char yy_hold_char;
+
+	// Number of characters read into yy_ch_buf.
+	int yy_n_chars;
+
+	// Points to current character in buffer.
+	char* yy_c_buf_p;
+
+	int yy_init;		// whether we need to initialize
+	int yy_start;		// start state number
+
+	// Flag which is used to allow yywrap()'s to do buffer switches
+	// instead of setting up a fresh yyin.  A bit of a hack ...
+	int yy_did_buffer_switch_on_eof;
+
+
+	size_t yy_buffer_stack_top; /**< index of top of stack. */
+	size_t yy_buffer_stack_max; /**< capacity of stack. */
+	struct yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */
+	void yyensure_buffer_stack(void);
+
+	// The following are not always needed, but may be depending
+	// on use of certain flex features (like REJECT or yymore()).
+
+	yy_state_type yy_last_accepting_state;
+	char* yy_last_accepting_cpos;
+
+	yy_state_type* yy_state_buf;
+	yy_state_type* yy_state_ptr;
+
+	char* yy_full_match;
+	int* yy_full_state;
+	int yy_full_lp;
+
+	int yy_lp;
+	int yy_looking_for_trail_begin;
+
+	int yy_more_flag;
+	int yy_more_len;
+	int yy_more_offset;
+	int yy_prev_more_offset;
+};
+
+}
+
+#endif // yyFlexLexer || ! yyFlexLexerOnce
+
diff --git a/include/mcld/Script/GroupCmd.h b/include/mcld/Script/GroupCmd.h
new file mode 100644
index 0000000..3006c79
--- /dev/null
+++ b/include/mcld/Script/GroupCmd.h
@@ -0,0 +1,60 @@
+//===- GroupCmd.h ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_GROUPCMD_H
+#define MCLD_SCRIPT_GROUPCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+
+namespace mcld
+{
+
+class StringList;
+class InputTree;
+class InputBuilder;
+class GroupReader;
+class LinkerConfig;
+
+/** \class GroupCmd
+ *  \brief This class defines the interfaces to Group command.
+ */
+
+class GroupCmd : public ScriptCommand
+{
+public:
+  GroupCmd(StringList& pStringList,
+           InputTree& pInputTree,
+           InputBuilder& pBuilder,
+           GroupReader& m_GroupReader,
+           const LinkerConfig& pConfig);
+  ~GroupCmd();
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::GROUP;
+  }
+
+  void activate(Module& pModule);
+
+private:
+  StringList& m_StringList;
+  InputTree& m_InputTree;
+  InputBuilder& m_Builder;
+  GroupReader& m_GroupReader;
+  const LinkerConfig& m_Config;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/InputSectDesc.h b/include/mcld/Script/InputSectDesc.h
new file mode 100644
index 0000000..e2bbf8d
--- /dev/null
+++ b/include/mcld/Script/InputSectDesc.h
@@ -0,0 +1,105 @@
+//===- InputSectDesc.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_INPUTSECTDESC_H
+#define MCLD_SCRIPT_INPUTSECTDESC_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <mcld/Script/StringList.h>
+#include <cassert>
+
+namespace mcld
+{
+
+class WildcardPattern;
+class OutputSectDesc;
+
+/** \class InputSectDesc
+ *  \brief This class defines the interfaces to input section description.
+ */
+
+class InputSectDesc : public ScriptCommand
+{
+public:
+  enum KeepPolicy {
+    Keep,
+    NoKeep
+  };
+
+  struct Spec {
+    bool hasFile() const { return m_pWildcardFile != NULL; }
+    const WildcardPattern& file() const {
+      assert(hasFile());
+      return *m_pWildcardFile;
+    }
+
+    bool hasExcludeFiles() const {
+      return m_pExcludeFiles != NULL && !m_pExcludeFiles->empty();
+    }
+    const StringList& excludeFiles() const {
+      assert(hasExcludeFiles());
+      return *m_pExcludeFiles;
+    }
+
+    bool hasSections() const {
+      return m_pWildcardSections != NULL && !m_pWildcardSections->empty();
+    }
+    const StringList& sections() const {
+      assert(hasSections());
+      return *m_pWildcardSections;
+    }
+
+    bool operator==(const Spec& pRHS) const {
+      /* FIXME: currently I don't check the real content */
+      if (this == &pRHS)
+        return true;
+      if (m_pWildcardFile != pRHS.m_pWildcardFile)
+        return false;
+      if (m_pExcludeFiles != pRHS.m_pExcludeFiles)
+        return false;
+      if (m_pWildcardSections != pRHS.m_pWildcardSections)
+        return false;
+      return true;
+    }
+
+    WildcardPattern* m_pWildcardFile;
+    StringList* m_pExcludeFiles;
+    StringList* m_pWildcardSections;
+  };
+
+public:
+  InputSectDesc(KeepPolicy pPolicy,
+                const Spec& pSpec,
+                const OutputSectDesc& pOutputDesc);
+  ~InputSectDesc();
+
+  KeepPolicy policy() const { return m_KeepPolicy; }
+
+  const Spec& spec() const { return m_Spec; }
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::INPUT_SECT_DESC;
+  }
+
+  void activate(Module& pModule);
+
+private:
+  KeepPolicy m_KeepPolicy;
+  Spec m_Spec;
+  const OutputSectDesc& m_OutputSectDesc;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/InputToken.h b/include/mcld/Script/InputToken.h
new file mode 100644
index 0000000..8d89022
--- /dev/null
+++ b/include/mcld/Script/InputToken.h
@@ -0,0 +1,56 @@
+//===- InputToken.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_INPUTTOKEN_H
+#define MCLD_SCRIPT_INPUTTOKEN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/StrToken.h>
+
+namespace mcld
+{
+
+/** \class InputToken
+ *  \brief This class defines the interfaces to a file/namespec token.
+ */
+
+class InputToken : public StrToken
+{
+public:
+  enum Type {
+    Unknown,
+    File,
+    NameSpec
+  };
+
+protected:
+  InputToken();
+  InputToken(Type pType, const std::string& pName, bool pAsNeeded);
+
+public:
+  virtual ~InputToken();
+
+  Type type() const { return m_Type; }
+
+  bool asNeeded() const { return m_bAsNeeded; }
+
+  static bool classof(const StrToken* pToken)
+  {
+    return pToken->kind() == StrToken::Input;
+  }
+
+private:
+  Type m_Type;
+  bool m_bAsNeeded;
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Script/NameSpec.h b/include/mcld/Script/NameSpec.h
new file mode 100644
index 0000000..96cf95c
--- /dev/null
+++ b/include/mcld/Script/NameSpec.h
@@ -0,0 +1,50 @@
+//===- NameSpec.h ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_NAMESPEC_H
+#define MCLD_SCRIPT_NAMESPEC_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/InputToken.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+
+namespace mcld
+{
+
+/** \class NameSpec
+ *  \brief This class defines the interfaces to a namespec in INPUT/GROUP
+ *         command.
+ */
+
+class NameSpec : public InputToken
+{
+private:
+  friend class Chunk<NameSpec, MCLD_SYMBOLS_PER_INPUT>;
+  NameSpec();
+  NameSpec(const std::string& pName, bool pAsNeeded);
+
+public:
+  ~NameSpec();
+
+  static bool classof(const InputToken* pToken)
+  {
+    return pToken->type() == InputToken::NameSpec;
+  }
+
+  /* factory method */
+  static NameSpec* create(const std::string& pName, bool pAsNeeded);
+  static void destroy(NameSpec*& pToken);
+  static void clear();
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Script/NullaryOp.h b/include/mcld/Script/NullaryOp.h
new file mode 100644
index 0000000..95fdc18
--- /dev/null
+++ b/include/mcld/Script/NullaryOp.h
@@ -0,0 +1,65 @@
+//===- NullaryOp.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_NULLOP_H
+#define MCLD_SCRIPT_NULLOP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Operator.h>
+#include <cassert>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class NullaryOp
+ *  \brief This class defines the interfaces to an nullary operator token.
+ */
+
+template<Operator::Type TYPE>
+class NullaryOp : public Operator
+{
+private:
+  friend class Operator;
+
+  NullaryOp()
+    : Operator(Operator::NULLARY, TYPE)
+  {}
+
+public:
+  ~NullaryOp()
+  {}
+
+  IntOperand* eval(const Module& pModule, const TargetLDBackend& pBackend);
+
+  void appendOperand(Operand* pOperand)
+  {
+    assert(0);
+  }
+};
+
+template<>
+IntOperand* NullaryOp<Operator::SIZEOF_HEADERS>::eval(const Module&,
+                                                      const TargetLDBackend&);
+template<>
+IntOperand* NullaryOp<Operator::MAXPAGESIZE>::eval(const Module&,
+                                                   const TargetLDBackend&);
+
+template<>
+IntOperand* NullaryOp<Operator::COMMONPAGESIZE>::eval(const Module&,
+                                                      const TargetLDBackend&);
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/Operand.h b/include/mcld/Script/Operand.h
new file mode 100644
index 0000000..403701c
--- /dev/null
+++ b/include/mcld/Script/Operand.h
@@ -0,0 +1,241 @@
+//===- Operand.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OPERAND_H
+#define MCLD_SCRIPT_OPERAND_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ExprToken.h>
+#include <mcld/Object/SectionMap.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+#include <llvm/Support/DataTypes.h>
+#include <string>
+#include <cassert>
+
+namespace mcld
+{
+
+/** \class Operand
+ *  \brief This class defines the interfaces to an operand token.
+ */
+
+class Operand : public ExprToken
+{
+public:
+  enum Type {
+    SYMBOL,
+    INTEGER,
+    SECTION,
+    SECTION_DESC,
+    FRAGMENT
+  };
+
+protected:
+  Operand(Type pType);
+  virtual ~Operand();
+
+public:
+  Type type() const { return m_Type; }
+
+  virtual bool isDot() const { return false; }
+
+  virtual uint64_t value() const = 0;
+
+  static bool classof(const ExprToken* pToken)
+  {
+    return pToken->kind() == ExprToken::OPERAND;
+  }
+
+private:
+  Type m_Type;
+};
+
+/** \class SymOperand
+ *  \brief This class defines the interfaces to a symbol operand.
+ */
+
+class SymOperand : public Operand
+{
+private:
+  friend class Chunk<SymOperand, MCLD_SYMBOLS_PER_INPUT>;
+  SymOperand();
+  SymOperand(const std::string& pName);
+
+public:
+  void dump() const;
+
+  const std::string& name() const { return m_Name; }
+
+  bool isDot() const;
+
+  uint64_t value() const { return m_Value; }
+
+  void setValue(uint64_t pValue) { m_Value = pValue; }
+
+  static bool classof(const Operand* pOperand)
+  {
+    return pOperand->type() == Operand::SYMBOL;
+  }
+
+  /* factory method */
+  static SymOperand* create(const std::string& pName);
+  static void destroy(SymOperand*& pOperand);
+  static void clear();
+
+private:
+  std::string m_Name;
+  uint64_t m_Value;
+};
+
+/** \class IntOperand
+ *  \brief This class defines the interfaces to an integer operand.
+ */
+
+class IntOperand : public Operand
+{
+private:
+  friend class Chunk<IntOperand, MCLD_SYMBOLS_PER_INPUT>;
+  IntOperand();
+  IntOperand(uint64_t pValue);
+
+public:
+  void dump() const;
+
+  uint64_t value() const { return m_Value; }
+
+  void setValue(uint64_t pValue) { m_Value = pValue; }
+
+  static bool classof(const Operand* pOperand)
+  {
+    return pOperand->type() == Operand::INTEGER;
+  }
+
+  /* factory method */
+  static IntOperand* create(uint64_t pValue);
+  static void destroy(IntOperand*& pOperand);
+  static void clear();
+
+private:
+  uint64_t m_Value;
+};
+
+/** \class SectOperand
+ *  \brief This class defines the interfaces to an section name operand.
+ */
+class LDSection;
+
+class SectOperand : public Operand
+{
+private:
+  friend class Chunk<SectOperand, MCLD_SECTIONS_PER_INPUT>;
+  SectOperand();
+  SectOperand(const std::string& pName);
+
+public:
+  void dump() const;
+
+  const std::string& name() const { return m_Name; }
+
+  uint64_t value() const
+  {
+    assert(0);
+    return 0;
+  }
+
+  static bool classof(const Operand* pOperand)
+  {
+    return pOperand->type() == Operand::SECTION;
+  }
+
+  /* factory method */
+  static SectOperand* create(const std::string& pName);
+  static void destroy(SectOperand*& pOperand);
+  static void clear();
+
+private:
+  std::string m_Name;
+};
+
+/** \class SectDescOperand
+ *  \brief This class defines the interfaces to an section name operand.
+ */
+
+class SectDescOperand : public Operand
+{
+private:
+  friend class Chunk<SectDescOperand, MCLD_SECTIONS_PER_INPUT>;
+  SectDescOperand();
+  SectDescOperand(const SectionMap::Output* pOutputDesc);
+
+public:
+  void dump() const;
+
+  const SectionMap::Output* outputDesc() const { return m_pOutputDesc; }
+
+  uint64_t value() const
+  {
+    assert(0);
+    return 0;
+  }
+
+  static bool classof(const Operand* pOperand)
+  {
+    return pOperand->type() == Operand::SECTION_DESC;
+  }
+
+  /* factory method */
+  static SectDescOperand* create(const SectionMap::Output* pOutputDesc);
+  static void destroy(SectDescOperand*& pOperand);
+  static void clear();
+
+private:
+  const SectionMap::Output* m_pOutputDesc;
+};
+
+/** \class FragOperand
+ *  \brief This class defines the interfaces to a fragment operand.
+ */
+
+class Fragment;
+
+class FragOperand : public Operand
+{
+private:
+  friend class Chunk<FragOperand, MCLD_SYMBOLS_PER_INPUT>;
+  FragOperand();
+  FragOperand(Fragment& pFragment);
+
+public:
+  void dump() const;
+
+  const Fragment* frag() const { return m_pFragment; }
+  Fragment*       frag()       { return m_pFragment; }
+
+  uint64_t value() const;
+
+  static bool classof(const Operand* pOperand)
+  {
+    return pOperand->type() == Operand::FRAGMENT;
+  }
+
+  /* factory method */
+  static FragOperand* create(Fragment& pFragment);
+  static void destroy(FragOperand*& pOperand);
+  static void clear();
+
+private:
+  Fragment* m_pFragment;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/Operator.h b/include/mcld/Script/Operator.h
new file mode 100644
index 0000000..1fe8118
--- /dev/null
+++ b/include/mcld/Script/Operator.h
@@ -0,0 +1,231 @@
+//===- Operator.h ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OPERATOR_INTERFACE_H
+#define MCLD_SCRIPT_OPERATOR_INTERFACE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ExprToken.h>
+#include <llvm/Support/DataTypes.h>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class Operator
+ *  \brief This class defines the interfaces to an operator token.
+ */
+
+class Operator : public ExprToken
+{
+public:
+  enum Arity {
+    NULLARY,
+    UNARY,
+    BINARY,
+    TERNARY
+  };
+
+  enum Type {
+    /* arithmetic operator */
+    UNARY_PLUS  = 0,
+    UNARY_MINUS = 1,
+    LOGICAL_NOT = 2,
+    BITWISE_NOT = 3,
+    MUL         = 4,
+    DIV         = 5,
+    MOD         = 6,
+    ADD         = 7,
+    SUB         = 8,
+    LSHIFT      = 9,
+    RSHIFT      = 10,
+    LT          = 11,
+    LE          = 12,
+    GT          = 13,
+    GE          = 14,
+    EQ          = 15,
+    NE          = 16,
+    BITWISE_AND = 17,
+    BITWISE_XOR = 18,
+    BITWISE_OR  = 19,
+    LOGICAL_AND = 20,
+    LOGICAL_OR  = 21,
+    TERNARY_IF  = 22,
+    ASSIGN      = 23,
+    ADD_ASSIGN  = 24,
+    SUB_ASSIGN  = 25,
+    MUL_ASSIGN  = 26,
+    DIV_ASSIGN  = 27,
+    AND_ASSIGN  = 28,
+    OR_ASSIGN   = 29,
+    LS_ASSIGN   = 30,
+    RS_ASSIGN   = 31,
+    /* function */
+    ABSOLUTE               = 32,
+    ADDR                   = 33,
+    ALIGN                  = 34,
+    ALIGNOF                = 35,
+    BLOCK                  = 36,
+    DATA_SEGMENT_ALIGN     = 37,
+    DATA_SEGMENT_END       = 38,
+    DATA_SEGMENT_RELRO_END = 39,
+    DEFINED                = 40,
+    LENGTH                 = 41,
+    LOADADDR               = 42,
+    MAX                    = 43,
+    MIN                    = 44,
+    NEXT                   = 45,
+    ORIGIN                 = 46,
+    SEGMENT_START          = 47,
+    SIZEOF                 = 48,
+    SIZEOF_HEADERS         = 49,
+    MAXPAGESIZE            = 50,
+    COMMONPAGESIZE         = 51
+  };
+
+  static const char* OpNames[];
+
+protected:
+  Operator(Arity pArity, Type pType);
+
+  const IntOperand* result() const { return m_pIntOperand; }
+  IntOperand*       result()       { return m_pIntOperand; }
+
+public:
+  virtual ~Operator();
+
+  Arity arity() const { return m_Arity; }
+
+  Type type() const { return m_Type; }
+
+  virtual void dump() const;
+
+  virtual IntOperand* eval(const Module& pModule,
+                           const TargetLDBackend& pBackend) = 0;
+
+  virtual void appendOperand(Operand* pOperand) = 0;
+
+  static bool classof(const ExprToken* pToken)
+  {
+    return pToken->kind() == ExprToken::OPERATOR;
+  }
+
+  template<Operator::Type TYPE>
+  static Operator& create();
+
+private:
+  Arity m_Arity;
+  Type m_Type;
+  IntOperand* m_pIntOperand;
+};
+
+/* Nullary operator */
+template<>
+Operator& Operator::create<Operator::SIZEOF_HEADERS>();
+template<>
+Operator& Operator::create<Operator::MAXPAGESIZE>();
+template<>
+Operator& Operator::create<Operator::COMMONPAGESIZE>();
+
+/* Unary operator */
+template<>
+Operator& Operator::create<Operator::UNARY_PLUS>();
+template<>
+Operator& Operator::create<Operator::UNARY_MINUS>();
+template<>
+Operator& Operator::create<Operator::LOGICAL_NOT>();
+template<>
+Operator& Operator::create<Operator::BITWISE_NOT>();
+
+template<>
+Operator& Operator::create<Operator::ABSOLUTE>();
+template<>
+Operator& Operator::create<Operator::ADDR>();
+template<>
+Operator& Operator::create<Operator::ALIGNOF>();
+template<>
+Operator& Operator::create<Operator::DATA_SEGMENT_END>();
+template<>
+Operator& Operator::create<Operator::DEFINED>();
+template<>
+Operator& Operator::create<Operator::LENGTH>();
+template<>
+Operator& Operator::create<Operator::LOADADDR>();
+template<>
+Operator& Operator::create<Operator::NEXT>();
+template<>
+Operator& Operator::create<Operator::ORIGIN>();
+template<>
+Operator& Operator::create<Operator::SIZEOF>();
+
+/* Binary operator */
+template<>
+Operator& Operator::create<Operator::MUL>();
+template<>
+Operator& Operator::create<Operator::DIV>();
+template<>
+Operator& Operator::create<Operator::MOD>();
+template<>
+Operator& Operator::create<Operator::ADD>();
+template<>
+Operator& Operator::create<Operator::SUB>();
+template<>
+Operator& Operator::create<Operator::LSHIFT>();
+template<>
+Operator& Operator::create<Operator::RSHIFT>();
+template<>
+Operator& Operator::create<Operator::LT>();
+template<>
+Operator& Operator::create<Operator::LE>();
+template<>
+Operator& Operator::create<Operator::GT>();
+template<>
+Operator& Operator::create<Operator::GE>();
+template<>
+Operator& Operator::create<Operator::EQ>();
+template<>
+Operator& Operator::create<Operator::NE>();
+template<>
+Operator& Operator::create<Operator::BITWISE_AND>();
+template<>
+Operator& Operator::create<Operator::BITWISE_XOR>();
+template<>
+Operator& Operator::create<Operator::BITWISE_OR>();
+template<>
+Operator& Operator::create<Operator::LOGICAL_AND>();
+template<>
+Operator& Operator::create<Operator::LOGICAL_OR>();
+
+template<>
+Operator& Operator::create<Operator::ALIGN>();
+template<>
+Operator& Operator::create<Operator::DATA_SEGMENT_RELRO_END>();
+template<>
+Operator& Operator::create<Operator::MAX>();
+template<>
+Operator& Operator::create<Operator::MIN>();
+template<>
+Operator& Operator::create<Operator::SEGMENT_START>();
+
+/* Ternary operator */
+template<>
+Operator& Operator::create<Operator::TERNARY_IF>();
+
+template<>
+Operator&
+Operator::create<Operator::DATA_SEGMENT_ALIGN>();
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/OutputArchCmd.h b/include/mcld/Script/OutputArchCmd.h
new file mode 100644
index 0000000..51b75cc
--- /dev/null
+++ b/include/mcld/Script/OutputArchCmd.h
@@ -0,0 +1,49 @@
+//===- OutputArchCmd.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OUTPUTARCHCMD_H
+#define MCLD_SCRIPT_OUTPUTARCHCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class OutputArchCmd
+ *  \brief This class defines the interfaces to OutputArch command.
+ */
+
+class OutputArchCmd : public ScriptCommand
+{
+public:
+  OutputArchCmd(const std::string& pArch);
+  ~OutputArchCmd();
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::OUTPUT_ARCH;
+  }
+
+  void activate(Module& pModule);
+
+private:
+  std::string m_Arch;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/OutputCmd.h b/include/mcld/Script/OutputCmd.h
new file mode 100644
index 0000000..0a63891
--- /dev/null
+++ b/include/mcld/Script/OutputCmd.h
@@ -0,0 +1,50 @@
+//===- OutputCmd.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OUTPUTCMD_H
+#define MCLD_SCRIPT_OUTPUTCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class OutputCmd
+ *  \brief This class defines the interfaces to Output command.
+ */
+
+class OutputCmd : public ScriptCommand
+{
+public:
+  OutputCmd(const std::string& pOutputFile);
+
+  ~OutputCmd();
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::OUTPUT;
+  }
+
+  void activate(Module& pModule);
+
+private:
+  std::string m_OutputFile;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/OutputFormatCmd.h b/include/mcld/Script/OutputFormatCmd.h
new file mode 100644
index 0000000..b716e81
--- /dev/null
+++ b/include/mcld/Script/OutputFormatCmd.h
@@ -0,0 +1,63 @@
+//===- OutputFormatCmd.h --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OUTPUTFORMATCMD_H
+#define MCLD_SCRIPT_OUTPUTFORMATCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class OutputFormatCmd
+ *  \brief This class defines the interfaces to OutputFormat command.
+ */
+
+class OutputFormatCmd : public ScriptCommand
+{
+public:
+  typedef std::vector<std::string> FormatList;
+  typedef FormatList::const_iterator const_iterator;
+  typedef FormatList::iterator iterator;
+
+public:
+  OutputFormatCmd(const std::string& pFormat);
+  OutputFormatCmd(const std::string& pDefault,
+                  const std::string& pBig,
+                  const std::string& pLittle);
+  ~OutputFormatCmd();
+
+  const_iterator begin() const { return m_FormatList.begin(); }
+  iterator       begin()       { return m_FormatList.begin(); }
+  const_iterator end()   const { return m_FormatList.end(); }
+  iterator       end()         { return m_FormatList.end(); }
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::OUTPUT_FORMAT;
+  }
+
+  void activate(Module& pModule);
+
+private:
+  FormatList m_FormatList;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/OutputSectDesc.h b/include/mcld/Script/OutputSectDesc.h
new file mode 100644
index 0000000..3c5187b
--- /dev/null
+++ b/include/mcld/Script/OutputSectDesc.h
@@ -0,0 +1,214 @@
+//===- OutputSectDesc.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OUTPUTSECTDESC_H
+#define MCLD_SCRIPT_OUTPUTSECTDESC_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <vector>
+#include <string>
+#include <cassert>
+
+namespace mcld
+{
+
+class RpnExpr;
+class StringList;
+
+/** \class OutputSectDesc
+ *  \brief This class defines the interfaces to output section description.
+ */
+
+class OutputSectDesc : public ScriptCommand
+{
+public:
+  enum Type {
+    LOAD, // ALLOC
+    NOLOAD,
+    DSECT,
+    COPY,
+    INFO,
+    OVERLAY
+  };
+
+  enum Constraint {
+    NO_CONSTRAINT,
+    ONLY_IF_RO,
+    ONLY_IF_RW
+  };
+
+  struct Prolog {
+    bool hasVMA() const { return m_pVMA != NULL; }
+    const RpnExpr& vma() const {
+      assert(hasVMA());
+      return *m_pVMA;
+    }
+    RpnExpr& vma() {
+      assert(hasVMA());
+      return *m_pVMA;
+    }
+
+    void setType(Type pType) {
+      m_Type = pType;
+    }
+
+    Type type() const { return m_Type; }
+
+    bool hasLMA() const { return m_pLMA != NULL; }
+    const RpnExpr& lma() const {
+      assert(hasLMA());
+      return *m_pLMA;
+    }
+    RpnExpr& lma() {
+      assert(hasLMA());
+      return *m_pLMA;
+    }
+
+    bool hasAlign() const { return m_pAlign != NULL; }
+    const RpnExpr& align() const {
+      assert(hasAlign());
+      return *m_pAlign;
+    }
+
+    bool hasSubAlign() const { return m_pSubAlign != NULL; }
+    const RpnExpr& subAlign() const {
+      assert(hasSubAlign());
+      return *m_pSubAlign;
+    }
+
+    Constraint constraint() const { return m_Constraint; }
+
+    bool operator==(const Prolog& pRHS) const {
+      /* FIXME: currently I don't check the real content */
+      if (this == &pRHS)
+        return true;
+      if (m_pVMA != pRHS.m_pVMA)
+        return false;
+      if (m_Type != pRHS.m_Type)
+        return false;
+      if (m_pLMA!= pRHS.m_pLMA)
+        return false;
+      if (m_pAlign != pRHS.m_pAlign)
+        return false;
+      if (m_pSubAlign != pRHS.m_pSubAlign)
+        return false;
+      if (m_Constraint != pRHS.m_Constraint)
+        return false;
+      return true;
+    }
+
+    RpnExpr* m_pVMA;
+    Type m_Type;
+    RpnExpr* m_pLMA;
+    RpnExpr* m_pAlign;
+    RpnExpr* m_pSubAlign;
+    Constraint m_Constraint;
+  };
+
+  struct Epilog {
+    bool hasRegion() const { return m_pRegion != NULL; }
+    const std::string& region() const {
+      assert(hasRegion());
+      return *m_pRegion;
+    }
+
+    bool hasLMARegion() const { return m_pLMARegion != NULL; }
+    const std::string& lmaRegion() const {
+      assert(hasLMARegion());
+      return *m_pLMARegion;
+    }
+
+    bool hasPhdrs() const { return m_pPhdrs != NULL; }
+    const StringList& phdrs() const {
+      assert(hasPhdrs());
+      return *m_pPhdrs;
+    }
+
+    bool hasFillExp() const { return m_pFillExp != NULL; }
+    const RpnExpr& fillExp() const {
+      assert(hasFillExp());
+      return *m_pFillExp;
+    }
+
+    bool operator==(const Epilog& pRHS) const {
+      /* FIXME: currently I don't check the real content */
+      if (this == &pRHS)
+        return true;
+      if (m_pRegion != pRHS.m_pRegion)
+        return false;
+      if (m_pLMARegion != pRHS.m_pLMARegion)
+        return false;
+      if (m_pPhdrs != pRHS.m_pPhdrs)
+        return false;
+      if (m_pFillExp != pRHS.m_pFillExp)
+        return false;
+      return true;
+    }
+
+    const std::string* m_pRegion;
+    const std::string* m_pLMARegion;
+    StringList* m_pPhdrs;
+    RpnExpr* m_pFillExp;
+  };
+
+  typedef std::vector<ScriptCommand*> OutputSectCmds;
+  typedef OutputSectCmds::const_iterator const_iterator;
+  typedef OutputSectCmds::iterator iterator;
+  typedef OutputSectCmds::const_reference const_reference;
+  typedef OutputSectCmds::reference reference;
+
+public:
+  OutputSectDesc(const std::string& pName, const Prolog& pProlog);
+  ~OutputSectDesc();
+
+  const_iterator  begin() const { return m_OutputSectCmds.begin(); }
+  iterator        begin()       { return m_OutputSectCmds.begin(); }
+  const_iterator  end()   const { return m_OutputSectCmds.end(); }
+  iterator        end()         { return m_OutputSectCmds.end(); }
+
+  const_reference front() const { return m_OutputSectCmds.front(); }
+  reference       front()       { return m_OutputSectCmds.front(); }
+  const_reference back()  const { return m_OutputSectCmds.back(); }
+  reference       back()        { return m_OutputSectCmds.back(); }
+
+  const std::string& name() const { return m_Name; }
+
+  size_t size() const { return m_OutputSectCmds.size(); }
+
+  bool empty() const { return m_OutputSectCmds.empty(); }
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::OUTPUT_SECT_DESC;
+  }
+
+  void activate(Module& pModule);
+
+  void push_back(ScriptCommand* pCommand);
+
+  void setEpilog(const Epilog& pEpilog);
+
+  const Prolog& prolog() const { return m_Prolog; }
+
+  const Epilog& epilog() const { return m_Epilog; }
+
+private:
+  OutputSectCmds m_OutputSectCmds;
+  std::string m_Name;
+  Prolog m_Prolog;
+  Epilog m_Epilog;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/RpnEvaluator.h b/include/mcld/Script/RpnEvaluator.h
new file mode 100644
index 0000000..7e35e86
--- /dev/null
+++ b/include/mcld/Script/RpnEvaluator.h
@@ -0,0 +1,36 @@
+//===- RpnEvaluator.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_RPNEVALUATOR_H
+#define MCLD_SCRIPT_RPNEVALUATOR_H
+
+namespace mcld {
+
+class RpnExpr;
+class Module;
+class TargetLDBackend;
+
+/** \class RpnEvaluator
+ *  \brief RpnEvaluator evaluate a rpn expression
+ */
+class RpnEvaluator
+{
+public:
+  RpnEvaluator(const Module& pModule, const TargetLDBackend& pBackend);
+
+  // evaluate a valid expression and set the value in the second parameter
+  bool eval(const RpnExpr& pExpr, uint64_t& pResult);
+
+private:
+  const Module& m_Module;
+  const TargetLDBackend& m_Backend;
+};
+
+} // mcld
+
+#endif
diff --git a/include/mcld/Script/RpnExpr.h b/include/mcld/Script/RpnExpr.h
new file mode 100644
index 0000000..96b11e9
--- /dev/null
+++ b/include/mcld/Script/RpnExpr.h
@@ -0,0 +1,81 @@
+//===- RPNExpr.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_RPNEXPR_H
+#define MCLD_SCRIPT_RPNEXPR_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+#include <mcld/Object/SectionMap.h>
+#include <vector>
+
+namespace mcld
+{
+
+class ExprToken;
+class Fragment;
+
+/** \class RpnExpr
+ *  \brief This class defines the interfaces to a rpn expression.
+ */
+
+class RpnExpr
+{
+public:
+  typedef std::vector<ExprToken*> TokenQueue;
+  typedef TokenQueue::const_iterator const_iterator;
+  typedef TokenQueue::iterator iterator;
+
+private:
+  friend class Chunk<RpnExpr, MCLD_SYMBOLS_PER_INPUT>;
+  RpnExpr();
+
+public:
+  ~RpnExpr();
+
+  const_iterator begin() const { return m_TokenQueue.begin(); }
+  iterator       begin()       { return m_TokenQueue.begin(); }
+  const_iterator end()   const { return m_TokenQueue.end(); }
+  iterator       end()         { return m_TokenQueue.end(); }
+
+  size_t size() const { return m_TokenQueue.size(); }
+
+  bool empty() const { return m_TokenQueue.empty(); }
+
+  bool hasDot() const;
+
+  void dump() const;
+
+  void push_back(ExprToken* pToken);
+
+  iterator insert(iterator pPosition, ExprToken* pToken);
+
+  void erase(iterator pPosition);
+
+  /* factory methods */
+  static RpnExpr* create();
+  static void destroy(RpnExpr*& pRpnExpr);
+  static void clear();
+
+  // buildHelperExpr - build the helper expr:
+  //                   ADDR ( `output_sect' ) + SIZEOF ( `output_sect' )
+  static RpnExpr* buildHelperExpr(SectionMap::iterator pIter);
+  // buildHelperExpr - build the helper expr: `fragment'
+  static RpnExpr* buildHelperExpr(Fragment& pFrag);
+
+private:
+  TokenQueue m_TokenQueue;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ScriptCommand.h b/include/mcld/Script/ScriptCommand.h
new file mode 100644
index 0000000..06e07eb
--- /dev/null
+++ b/include/mcld/Script/ScriptCommand.h
@@ -0,0 +1,60 @@
+//===- ScriptCommand.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_COMMAND_H
+#define MCLD_SCRIPT_COMMAND_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld {
+
+class Module;
+
+/** \class ScriptCommand
+ *  \brief This class defines the interfaces to a script command.
+ */
+class ScriptCommand
+{
+public:
+  enum Kind {
+    ENTRY,
+    OUTPUT_FORMAT,
+    GROUP,
+    OUTPUT,
+    SEARCH_DIR,
+    OUTPUT_ARCH,
+    ASSERT,
+    ASSIGNMENT,
+    SECTIONS,
+    OUTPUT_SECT_DESC,
+    INPUT_SECT_DESC
+  };
+
+protected:
+  ScriptCommand(Kind pKind)
+    : m_Kind(pKind)
+  {}
+
+public:
+  virtual ~ScriptCommand() = 0;
+
+  virtual void dump() const = 0;
+
+  virtual void activate(Module&) = 0;
+
+  Kind getKind() const { return m_Kind; }
+
+private:
+  Kind m_Kind;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ScriptFile.h b/include/mcld/Script/ScriptFile.h
new file mode 100644
index 0000000..03662e3
--- /dev/null
+++ b/include/mcld/Script/ScriptFile.h
@@ -0,0 +1,165 @@
+//===- ScriptFile.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SCRIPTFILE_H
+#define MCLD_SCRIPT_SCRIPTFILE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Assignment.h>
+#include <mcld/Script/OutputSectDesc.h>
+#include <mcld/Script/InputSectDesc.h>
+#include <vector>
+#include <string>
+
+namespace mcld
+{
+
+class ScriptCommand;
+class Input;
+class InputTree;
+class InputBuilder;
+class GroupReader;
+class LinkerConfig;
+class RpnExpr;
+class StringList;
+class Module;
+
+/** \class ScriptFile
+ *  \brief This class defines the interfaces to a linker script file.
+ */
+
+class ScriptFile
+{
+public:
+  enum Kind {
+    LDScript,      // -T
+    Expression,    // --defsym
+    VersionScript, // --version-script
+    DynamicList,   // --dynamic-list
+    Unknown
+  };
+
+  typedef std::vector<ScriptCommand*> CommandQueue;
+  typedef CommandQueue::const_iterator const_iterator;
+  typedef CommandQueue::iterator iterator;
+  typedef CommandQueue::const_reference const_reference;
+  typedef CommandQueue::reference reference;
+
+public:
+  ScriptFile(Kind pKind, Input& pInput, InputBuilder& pBuilder);
+  ~ScriptFile();
+
+  const_iterator  begin() const { return m_CommandQueue.begin(); }
+  iterator        begin()       { return m_CommandQueue.begin(); }
+  const_iterator  end()   const { return m_CommandQueue.end(); }
+  iterator        end()         { return m_CommandQueue.end(); }
+
+  const_reference front() const { return m_CommandQueue.front(); }
+  reference       front()       { return m_CommandQueue.front(); }
+  const_reference back()  const { return m_CommandQueue.back(); }
+  reference       back()        { return m_CommandQueue.back(); }
+
+  const Input& input() const { return m_Input; }
+  Input&       input()       { return m_Input; }
+
+  size_t size() const { return m_CommandQueue.size(); }
+
+  Kind getKind() const { return m_Kind; }
+
+  const InputTree& inputs() const { return *m_pInputTree; }
+  InputTree&       inputs()       { return *m_pInputTree; }
+
+  const std::string& name() const { return m_Name; }
+  std::string&       name()       { return m_Name; }
+
+  void dump() const;
+  void activate(Module& pModule);
+
+  /// ENTRY(symbol)
+  void addEntryPoint(const std::string& pSymbol);
+
+  /// OUTPUT_FORMAT(bfdname)
+  /// OUTPUT_FORMAT(default, big, little)
+  void addOutputFormatCmd(const std::string& pFormat);
+  void addOutputFormatCmd(const std::string& pDefault,
+                          const std::string& pBig,
+                          const std::string& pLittle);
+
+  /// GROUP(file, file, ...)
+  /// GROUP(file file ...)
+  void addGroupCmd(StringList& pStringList,
+                   GroupReader& pGroupReader,
+                   const LinkerConfig& pConfig);
+
+  /// OUTPUT(filename)
+  void addOutputCmd(const std::string& pFileName);
+
+  /// SEARCH_DIR(path)
+  void addSearchDirCmd(const std::string& pPath);
+
+  /// OUTPUT_ARCH(bfdarch)
+  void addOutputArchCmd(const std::string& pArch);
+
+  /// ASSERT(exp, message)
+  void addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage);
+
+  /// assignment
+  void addAssignment(const std::string& pSymbol,
+                     RpnExpr& pRpnExpr,
+                     Assignment::Type pType = Assignment::DEFAULT);
+
+  bool hasSectionsCmd() const;
+
+  void enterSectionsCmd();
+
+  void leaveSectionsCmd();
+
+  void enterOutputSectDesc(const std::string& pName,
+                           const OutputSectDesc::Prolog& pProlog);
+
+  void leaveOutputSectDesc(const OutputSectDesc::Epilog& pEpilog);
+
+  void addInputSectDesc(InputSectDesc::KeepPolicy pPolicy,
+                        const InputSectDesc::Spec& pSpec);
+
+  RpnExpr* createRpnExpr();
+  const RpnExpr* getCurrentRpnExpr() const { return m_pRpnExpr; }
+  RpnExpr*       getCurrentRpnExpr()       { return m_pRpnExpr; }
+
+  StringList* createStringList();
+  const StringList* getCurrentStringList() const { return m_pStringList; }
+  StringList*       getCurrentStringList()       { return m_pStringList; }
+
+  void setAsNeeded(bool pEnable = true);
+  bool asNeeded() const { return m_bAsNeeded; }
+
+  static const std::string& createParserStr(const char* pText, size_t pLength);
+
+  static void clearParserStrPool();
+
+private:
+  Kind m_Kind;
+  Input& m_Input;
+  std::string m_Name;
+  InputTree* m_pInputTree;
+  InputBuilder& m_Builder;
+  CommandQueue m_CommandQueue;
+  bool m_bHasSectionsCmd;
+  bool m_bInSectionsCmd;
+  bool m_bInOutputSectDesc;
+  RpnExpr* m_pRpnExpr;
+  StringList* m_pStringList;
+  bool m_bAsNeeded;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ScriptReader.h b/include/mcld/Script/ScriptReader.h
new file mode 100644
index 0000000..14a667f
--- /dev/null
+++ b/include/mcld/Script/ScriptReader.h
@@ -0,0 +1,49 @@
+//===- ScriptReader.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SCRIPTREADER_H
+#define MCLD_SCRIPT_SCRIPTREADER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/LD/LDReader.h>
+
+namespace mcld {
+
+class Module;
+class ScriptFile;
+class Input;
+class GroupReader;
+class LinkerConfig;
+class LinkerScript;
+class TargetLDBackend;
+
+class ScriptReader : public LDReader
+{
+public:
+  ScriptReader(GroupReader& pGroupReader);
+
+  ~ScriptReader();
+
+  /// readScript
+  bool readScript(const LinkerConfig& pConfig, ScriptFile& pScriptFile);
+
+  /// isMyFormat
+  bool isMyFormat(Input& pInput, bool &pContinue) const;
+
+  GroupReader& getGroupReader() { return m_GroupReader; }
+
+private:
+  GroupReader& m_GroupReader;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ScriptScanner.h b/include/mcld/Script/ScriptScanner.h
new file mode 100644
index 0000000..43897e5
--- /dev/null
+++ b/include/mcld/Script/ScriptScanner.h
@@ -0,0 +1,62 @@
+//===- ScriptScanner.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SCRIPTSCANNER_H
+#define MCLD_SCRIPT_SCRIPTSCANNER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#ifndef __FLEX_LEXER_H
+#include "FlexLexer.h"
+#endif
+
+#ifndef YY_DECL
+#define YY_DECL                                                       \
+  mcld::ScriptParser::token_type                                      \
+  mcld::ScriptScanner::lex(mcld::ScriptParser::semantic_type* yylval, \
+                           mcld::ScriptParser::location_type* yylloc, \
+                           const mcld::ScriptFile& pScriptFile)
+#endif
+
+#include <mcld/Script/ScriptFile.h>
+#include "ScriptParser.h"
+#include <stack>
+
+namespace mcld {
+
+/** \class ScriptScanner
+ *
+ */
+class ScriptScanner : public yyFlexLexer
+{
+public:
+  ScriptScanner(std::istream* yyin = NULL, std::ostream* yyout = NULL);
+
+  virtual ~ScriptScanner();
+
+  virtual ScriptParser::token_type lex(ScriptParser::semantic_type* yylval,
+                                       ScriptParser::location_type* yylloc,
+                                       const ScriptFile& pScriptFile);
+
+  void setLexState(ScriptFile::Kind pKind);
+
+  void popLexState();
+
+private:
+  void enterComments(ScriptParser::location_type& pLocation);
+
+private:
+  ScriptFile::Kind m_Kind;
+  std::stack<ScriptFile::Kind> m_StateStack;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/SearchDirCmd.h b/include/mcld/Script/SearchDirCmd.h
new file mode 100644
index 0000000..f695a76
--- /dev/null
+++ b/include/mcld/Script/SearchDirCmd.h
@@ -0,0 +1,49 @@
+//===- SearchDirCmd.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SEARCHDIRCMD_H
+#define MCLD_SCRIPT_SEARCHDIRCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class SearchDirCmd
+ *  \brief This class defines the interfaces to SEARCH_DIR command.
+ */
+
+class SearchDirCmd : public ScriptCommand
+{
+public:
+  SearchDirCmd(const std::string& pPath);
+  ~SearchDirCmd();
+
+  void dump() const;
+
+  void activate(Module& pModule);
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::SEARCH_DIR;
+  }
+
+private:
+  std::string m_Path;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/SectionsCmd.h b/include/mcld/Script/SectionsCmd.h
new file mode 100644
index 0000000..afff1b1
--- /dev/null
+++ b/include/mcld/Script/SectionsCmd.h
@@ -0,0 +1,72 @@
+//===- SectionsCmd.h ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SECTIONSCMD_H
+#define MCLD_SCRIPT_SECTIONSCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <llvm/Support/DataTypes.h>
+#include <vector>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class SectionsCmd
+ *  \brief This class defines the interfaces to SECTIONS command.
+ */
+
+class SectionsCmd : public ScriptCommand
+{
+public:
+  typedef std::vector<ScriptCommand*> SectionCommands;
+  typedef SectionCommands::const_iterator const_iterator;
+  typedef SectionCommands::iterator iterator;
+  typedef SectionCommands::const_reference const_reference;
+  typedef SectionCommands::reference reference;
+
+public:
+  SectionsCmd();
+  ~SectionsCmd();
+
+  const_iterator  begin() const { return m_SectionCommands.begin(); }
+  iterator        begin()       { return m_SectionCommands.begin(); }
+  const_iterator  end()   const { return m_SectionCommands.end(); }
+  iterator        end()         { return m_SectionCommands.end(); }
+
+  const_reference front() const { return m_SectionCommands.front(); }
+  reference       front()       { return m_SectionCommands.front(); }
+  const_reference back()  const { return m_SectionCommands.back(); }
+  reference       back()        { return m_SectionCommands.back(); }
+
+  size_t size() const { return m_SectionCommands.size(); }
+
+  bool empty() const { return m_SectionCommands.empty(); }
+
+  void dump() const;
+
+  static bool classof(const ScriptCommand* pCmd)
+  {
+    return pCmd->getKind() == ScriptCommand::SECTIONS;
+  }
+
+  void activate(Module& pModule);
+
+  void push_back(ScriptCommand* pCommand);
+
+private:
+  SectionCommands m_SectionCommands;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/StrToken.h b/include/mcld/Script/StrToken.h
new file mode 100644
index 0000000..359b0be
--- /dev/null
+++ b/include/mcld/Script/StrToken.h
@@ -0,0 +1,67 @@
+//===- StrToken.h ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_STRTOKEN_H
+#define MCLD_SCRIPT_STRTOKEN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+#include <string>
+
+namespace mcld
+{
+
+/** \class StrToken
+ *  \brief This class defines the interfaces to a element in EXCLUDE_FILE list
+ *         or in Output Section Phdr, or be a base class of other str token.
+ */
+
+class StrToken
+{
+public:
+  enum Kind {
+    Unknown,
+    String,
+    Input,
+    Wildcard
+  };
+
+private:
+  friend class Chunk<StrToken, MCLD_SYMBOLS_PER_INPUT>;
+protected:
+  StrToken();
+  StrToken(Kind pKind, const std::string& pString);
+
+public:
+  virtual ~StrToken();
+
+  Kind kind() const { return m_Kind; }
+
+  const std::string& name() const { return m_Name; }
+
+  static bool classof(const StrToken* pToken)
+  {
+    return pToken->kind() == StrToken::String;
+  }
+
+  /* factory method */
+  static StrToken* create(const std::string& pString);
+  static void destroy(StrToken*& pToken);
+  static void clear();
+
+private:
+  Kind m_Kind;
+  std::string m_Name;
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Script/StringList.h b/include/mcld/Script/StringList.h
new file mode 100644
index 0000000..da27e41
--- /dev/null
+++ b/include/mcld/Script/StringList.h
@@ -0,0 +1,72 @@
+//===- StringList.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_STRINGLIST_H
+#define MCLD_SCRIPT_STRINGLIST_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Config/Config.h>
+#include <mcld/Support/Allocators.h>
+#include <vector>
+
+namespace mcld
+{
+
+class StrToken;
+
+/** \class StringList
+ *  \brief This class defines the interfaces to StringList.
+ */
+
+class StringList
+{
+public:
+  typedef std::vector<StrToken*> Tokens;
+  typedef Tokens::const_iterator const_iterator;
+  typedef Tokens::iterator iterator;
+  typedef Tokens::const_reference const_reference;
+  typedef Tokens::reference reference;
+
+private:
+  friend class Chunk<StringList, MCLD_SYMBOLS_PER_INPUT>;
+  StringList();
+
+public:
+  ~StringList();
+
+  const_iterator  begin() const { return m_Tokens.begin(); }
+  iterator        begin()       { return m_Tokens.begin(); }
+  const_iterator  end()   const { return m_Tokens.end(); }
+  iterator        end()         { return m_Tokens.end(); }
+
+  const_reference front() const { return m_Tokens.front(); }
+  reference       front()       { return m_Tokens.front(); }
+  const_reference back()  const { return m_Tokens.back(); }
+  reference       back()        { return m_Tokens.back(); }
+
+  bool empty() const { return m_Tokens.empty(); }
+
+  void push_back(StrToken* pToken);
+
+  void dump() const;
+
+  /* factory methods */
+  static StringList* create();
+  static void destroy(StringList*& pStringList);
+  static void clear();
+
+private:
+  Tokens m_Tokens;
+};
+
+} // namepsace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/TernaryOp.h b/include/mcld/Script/TernaryOp.h
new file mode 100644
index 0000000..0517b4a
--- /dev/null
+++ b/include/mcld/Script/TernaryOp.h
@@ -0,0 +1,71 @@
+//===- TernaryOp.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_TERNARYOP_H
+#define MCLD_SCRIPT_TERNARYOP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Operator.h>
+#include <cstddef>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class TernaryOP
+ *  \brief This class defines the interfaces to an binary operator token.
+ */
+
+template<Operator::Type TYPE>
+class TernaryOp : public Operator
+{
+private:
+  friend class Operator;
+
+  TernaryOp()
+    : Operator(Operator::TERNARY, TYPE)
+  {
+    m_pOperand[0] = m_pOperand[1] = m_pOperand[2] = NULL;
+  }
+
+public:
+  ~TernaryOp()
+  {}
+
+  IntOperand* eval(const Module& pModule, const TargetLDBackend& pBackend);
+
+  void appendOperand(Operand* pOperand)
+  {
+    m_pOperand[m_Size++] = pOperand;
+    if (m_Size == 3)
+      m_Size = 0;
+  }
+
+private:
+  size_t m_Size;
+  Operand* m_pOperand[3];
+};
+
+template<>
+IntOperand* TernaryOp<Operator::TERNARY_IF>::eval(const Module&,
+                                                  const TargetLDBackend&);
+
+template<>
+IntOperand*
+TernaryOp<Operator::DATA_SEGMENT_ALIGN>::eval(const Module&,
+                                              const TargetLDBackend&);
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/UnaryOp.h b/include/mcld/Script/UnaryOp.h
new file mode 100644
index 0000000..6b79b3c
--- /dev/null
+++ b/include/mcld/Script/UnaryOp.h
@@ -0,0 +1,102 @@
+//===- UnaryOp.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_UNARYOP_H
+#define MCLD_SCRIPT_UNARYOP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Operator.h>
+#include <cstddef>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class UnaryOp
+ *  \brief This class defines the interfaces to an unary operator token.
+ */
+
+template<Operator::Type TYPE>
+class UnaryOp : public Operator
+{
+private:
+  friend class Operator;
+
+  UnaryOp()
+    : Operator(Operator::UNARY, TYPE), m_pOperand(NULL)
+  {}
+
+public:
+  ~UnaryOp()
+  {}
+
+  IntOperand* eval(const Module& pModule, const TargetLDBackend& pBackend);
+
+  void appendOperand(Operand* pOperand)
+  {
+    m_pOperand = pOperand;
+  }
+
+private:
+  Operand* m_pOperand;
+};
+
+template<>
+IntOperand* UnaryOp<Operator::UNARY_PLUS>::eval(const Module&,
+                                                const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::UNARY_MINUS>::eval(const Module&,
+                                                 const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::LOGICAL_NOT>::eval(const Module&,
+                                                 const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::BITWISE_NOT>::eval(const Module&,
+                                                 const TargetLDBackend&);
+
+template<>
+IntOperand* UnaryOp<Operator::ABSOLUTE>::eval(const Module&,
+                                              const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::ADDR>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::ALIGNOF>::eval(const Module&,
+                                             const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::DATA_SEGMENT_END>::eval(const Module&,
+                                                      const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::DEFINED>::eval(const Module&,
+                                             const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::LENGTH>::eval(const Module&,
+                                            const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::LOADADDR>::eval(const Module&,
+                                              const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::NEXT>::eval(const Module&,
+                                          const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::ORIGIN>::eval(const Module&,
+                                            const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::SIZEOF>::eval(const Module&,
+                                            const TargetLDBackend&);
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/WildcardPattern.h b/include/mcld/Script/WildcardPattern.h
new file mode 100644
index 0000000..0c91435
--- /dev/null
+++ b/include/mcld/Script/WildcardPattern.h
@@ -0,0 +1,71 @@
+//===- WildcardPattern.h --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_WILDCARDPATTERN_H
+#define MCLD_SCRIPT_WILDCARDPATTERN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/StrToken.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+#include <llvm/ADT/StringRef.h>
+
+namespace mcld
+{
+
+/** \class WildcardPattern
+ *  \brief This class defines the interfaces to Input Section Wildcard Patterns
+ */
+
+class WildcardPattern : public StrToken
+{
+public:
+  enum SortPolicy {
+    SORT_NONE,
+    SORT_BY_NAME,
+    SORT_BY_ALIGNMENT,
+    SORT_BY_NAME_ALIGNMENT,
+    SORT_BY_ALIGNMENT_NAME,
+    SORT_BY_INIT_PRIORITY
+  };
+
+private:
+  friend class Chunk<WildcardPattern, MCLD_SYMBOLS_PER_INPUT>;
+  WildcardPattern();
+  WildcardPattern(const std::string& pPattern, SortPolicy pPolicy);
+
+public:
+  ~WildcardPattern();
+
+  SortPolicy sortPolicy() const { return m_SortPolicy; }
+
+  bool isPrefix() const { return m_bIsPrefix; }
+
+  llvm::StringRef prefix() const;
+
+  static bool classof(const StrToken* pToken)
+  {
+    return pToken->kind() == StrToken::Wildcard;
+  }
+
+  /* factory method */
+  static WildcardPattern* create(const std::string& pPattern,
+                                 SortPolicy pPolicy);
+  static void destroy(WildcardPattern*& pToken);
+  static void clear();
+
+private:
+  SortPolicy m_SortPolicy;
+  bool m_bIsPrefix;
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Support/CommandLine.h b/include/mcld/Support/CommandLine.h
index 00907fe..6cb0fae 100644
--- a/include/mcld/Support/CommandLine.h
+++ b/include/mcld/Support/CommandLine.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_COMMANDLINE_H
-#define MCLD_COMMANDLINE_H
+#ifndef MCLD_SUPPORT_COMMANDLINE_H
+#define MCLD_SUPPORT_COMMANDLINE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/DefSymParser.h b/include/mcld/Support/DefSymParser.h
deleted file mode 100644
index a721b48..0000000
--- a/include/mcld/Support/DefSymParser.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- DefSymParser.h -----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_DEFSYM_PARSER_H
-#define MCLD_DEFSYM_PARSER_H
-
-#include <mcld/Module.h>
-#include <llvm/ADT/StringRef.h>
-
-namespace mcld {
-
-/** \class DefSymParser
- *  \brief DefSymParser parses --defsym option.
- */
-class DefSymParser
-{
-public:
-  DefSymParser(const Module& pModule);
-
-  // parse a valid expression and set the value in the second parameter
-  bool parse(llvm::StringRef, uint64_t&);
-
-private:
-  const Module& m_Module;
-};
-
-} // mcld
-
-#endif
diff --git a/include/mcld/Support/Directory.h b/include/mcld/Support/Directory.h
index 66ba118..2bf8f06 100644
--- a/include/mcld/Support/Directory.h
+++ b/include/mcld/Support/Directory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_DIRECTORY_H
-#define MCLD_DIRECTORY_H
+#ifndef MCLD_SUPPORT_DIRECTORY_H
+#define MCLD_SUPPORT_DIRECTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/FileHandle.h b/include/mcld/Support/FileHandle.h
index f9fe73a..9f551b9 100644
--- a/include/mcld/Support/FileHandle.h
+++ b/include/mcld/Support/FileHandle.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_FILE_HANDLE_H
-#define MCLD_FILE_HANDLE_H
+#ifndef MCLD_SUPPORT_FILEHANDLE_H
+#define MCLD_SUPPORT_FILEHANDLE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/FileOutputBuffer.h b/include/mcld/Support/FileOutputBuffer.h
new file mode 100644
index 0000000..a49ffb7
--- /dev/null
+++ b/include/mcld/Support/FileOutputBuffer.h
@@ -0,0 +1,72 @@
+//===- FileOutputBuffer.h -------------------------------------------------===//
+//
+//                     the mclinker project
+//
+// this file is distributed under the university of illinois open source
+// license. see license.txt for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SUPPORT_FILEOUTPUTBUFFER_H
+#define MCLD_SUPPORT_FILEOUTPUTBUFFER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/MemoryRegion.h>
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/FileSystem.h>
+#include <llvm/Support/system_error.h>
+
+namespace mcld {
+
+class FileHandle;
+
+/// FileOutputBuffer - This interface is borrowed from llvm bassically, and we
+/// may use ostream to emit output later.
+class FileOutputBuffer {
+public:
+  /// Factory method to create an OutputBuffer object which manages a read/write
+  /// buffer of the specified size. When committed, the buffer will be written
+  /// to the file at the specified path.
+  static llvm::error_code create(FileHandle& pFileHandle,
+                                 size_t pSize,
+                                 llvm::OwningPtr<FileOutputBuffer>& pResult);
+
+  /// Returns a pointer to the start of the buffer.
+  uint8_t* getBufferStart() {
+    return (uint8_t*)m_pRegion->data();
+  }
+
+  /// Returns a pointer to the end of the buffer.
+  uint8_t* getBufferEnd() {
+    return (uint8_t*)m_pRegion->data() + m_pRegion->size();
+  }
+
+  /// Returns size of the buffer.
+  size_t getBufferSize() const {
+    return m_pRegion->size();
+  }
+
+  MemoryRegion request(size_t pOffset, size_t pLength);
+
+  /// Returns path where file will show up if buffer is committed.
+  llvm::StringRef getPath() const;
+
+  ~FileOutputBuffer();
+
+private:
+  FileOutputBuffer(const FileOutputBuffer &);
+  FileOutputBuffer &operator=(const FileOutputBuffer &);
+
+  FileOutputBuffer(llvm::sys::fs::mapped_file_region* pRegion,
+                   FileHandle& pFileHandle);
+
+  llvm::OwningPtr<llvm::sys::fs::mapped_file_region> m_pRegion;
+  FileHandle& m_FileHandle;
+};
+
+} // namespace mcld
+
+#endif
diff --git a/include/mcld/Support/FileSystem.h b/include/mcld/Support/FileSystem.h
index 927346e..e0dddd7 100644
--- a/include/mcld/Support/FileSystem.h
+++ b/include/mcld/Support/FileSystem.h
@@ -11,8 +11,8 @@
 // path class.
 //===----------------------------------------------------------------------===//
 
-#ifndef MCLD_FILE_SYSTEM_H
-#define MCLD_FILE_SYSTEM_H
+#ifndef MCLD_SUPPORT_FILESYSTEM_H
+#define MCLD_SUPPORT_FILESYSTEM_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/GCFactory.h b/include/mcld/Support/GCFactory.h
index 6679f41..9ae8650 100644
--- a/include/mcld/Support/GCFactory.h
+++ b/include/mcld/Support/GCFactory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_GC_FACTORY_H
-#define MCLD_GC_FACTORY_H
+#ifndef MCLD_SUPPORT_GCFACTORY_H
+#define MCLD_SUPPORT_GCFACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/GCFactoryListTraits.h b/include/mcld/Support/GCFactoryListTraits.h
index 986f6f6..b7d44d3 100644
--- a/include/mcld/Support/GCFactoryListTraits.h
+++ b/include/mcld/Support/GCFactoryListTraits.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_GC_FACTORY_LIST_TRAITS_H
-#define MCLD_GC_FACTORY_LIST_TRAITS_H
+#ifndef MCLD_SUPPORT_GCFACTORYLISTTRAITS_H
+#define MCLD_SUPPORT_GCFACTORYLISTTRAITS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/HandleToArea.h b/include/mcld/Support/HandleToArea.h
deleted file mode 100644
index 8c24db7..0000000
--- a/include/mcld/Support/HandleToArea.h
+++ /dev/null
@@ -1,118 +0,0 @@
-//===- HandleToArea.h -----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_FILE_HANDLE_TO_MEMORY_AREA_H
-#define MCLD_FILE_HANDLE_TO_MEMORY_AREA_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/ADT/Uncopyable.h>
-#include <mcld/ADT/TypeTraits.h>
-#include <mcld/ADT/StringHash.h>
-#include <mcld/Support/Path.h>
-#include <mcld/Support/FileHandle.h>
-#include <vector>
-
-namespace mcld {
-
-class MemoryArea;
-
-/** \class HandleToArea
- *
- *  Special double-key associative container. Keys are Path and file handler,
- *  associative value is MemoryArea.
- *
- *  For high performance, HandleToArea is not designed to contain unique
- *  <key, value> pair. The key and value may be duplicated.
- *
- *  Like FileHandle, HandleToArea should neither throw exception nor call
- *  expressive diagnostic.
- */
-class HandleToArea : private Uncopyable
-{
-private:
-  struct Bucket {
-    unsigned int hash_value;
-    FileHandle* handle;
-    MemoryArea* area;
-  };
-
-  // the best data structure is a binary search tree.
-  // However, by the shrinking time-to-market constraint, I used
-  // vector and sequential search here.
-  typedef std::vector<Bucket> HandleToAreaMap;
-
-  typedef hash::StringHash<hash::BKDR> HashFunction;
-
-public:
-  typedef HandleToAreaMap::iterator iterator;
-  typedef HandleToAreaMap::const_iterator const_iterator;
-
-public:
-  struct Result {
-  public:
-    Result(FileHandle* pHandle, MemoryArea* pArea)
-      : handle(pHandle), area(pArea) { }
-
-  public:
-    FileHandle* handle;
-    MemoryArea* area;
-  };
-
-  struct ConstResult {
-  public:
-    ConstResult(const FileHandle* pHandle, const MemoryArea* pArea)
-      : handle(pHandle), area(pArea) { }
-
-  public:
-    const FileHandle* handle;
-    const MemoryArea* area;
-  };
-
-public:
-  bool push_back(FileHandle* pHandle, MemoryArea* pArea);
-
-  bool erase(MemoryArea* pArea);
-
-  bool erase(const sys::fs::Path& pPath);
-
-  Result findFirst(const sys::fs::Path& pPath);
-
-  ConstResult findFirst(const sys::fs::Path& pPath) const;
-
-  iterator begin()
-  { return m_AreaMap.begin(); }
-
-  iterator end()
-  { return m_AreaMap.end(); }
-
-  const_iterator begin() const
-  { return m_AreaMap.begin(); }
-
-  const_iterator end() const
-  { return m_AreaMap.end(); }
-
-  // -----  capacity  ----- //
-  bool empty() const
-  { return m_AreaMap.empty(); }
-
-  size_t size() const
-  { return m_AreaMap.size(); }
-
-  HandleToArea() : m_AreaMap() { }
-
-  ~HandleToArea() { }
-
-private:
-  HandleToAreaMap m_AreaMap;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/LEB128.h b/include/mcld/Support/LEB128.h
index 816ed72..e44966a 100644
--- a/include/mcld/Support/LEB128.h
+++ b/include/mcld/Support/LEB128.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MCLD_LEB128_H
-#define MCLD_LEB128_H
+#ifndef MCLD_SUPPORT_LEB128_H
+#define MCLD_SUPPORT_LEB128_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/MemoryArea.h b/include/mcld/Support/MemoryArea.h
index d3ae9b7..18ea985 100644
--- a/include/mcld/Support/MemoryArea.h
+++ b/include/mcld/Support/MemoryArea.h
@@ -6,43 +6,22 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SUPPORT_MEMORY_AREA_H
-#define MCLD_SUPPORT_MEMORY_AREA_H
+#ifndef MCLD_SUPPORT_MEMORYAREA_H
+#define MCLD_SUPPORT_MEMORYAREA_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
 #include <mcld/ADT/Uncopyable.h>
-#include <cstddef>
-#include <map>
 
-#if defined(ENABLE_UNITTEST)
-namespace mcldtest {
-  class MemoryAreaTest;
-} // namespace of mcldtest
-#endif
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/MemoryBuffer.h>
 
 namespace mcld {
 
-class Space;
-class FileHandle;
-class MemoryRegion;
-
 /** \class MemoryArea
- *  \brief MemoryArea is used to manage distinct MemoryRegions of address space.
- *
- *  Good linkers must well manipulate memory mapped I/O and dynamic memory.
- *  In MCLinker, MemoryArea is the decision-maker to use memory mapped I/O or
- *  dynamic memory. When a client requests MemoryArea for a piece of memory
- *  to hold a part of a file, MemoryArea is going to see whether the requested
- *  part of the file is already in any existing memory which is requested
- *  before. If it is, MemoryArea creates a new MemoryRegion within the memory
- *  requested before. Otherwise, MemoryArea uses memory mapped I/O or dynamic
- *  memory to load the file.
- *
- *  If the part a file being loaded is larger than 3/4 pages, MemoryArea uses
- *  memory mapped I/O to load the file. Otherwise, MemoryArea uses dynamic
- *  memory to read the content of file into the memory space.
+ *  \brief MemoryArea is used to manage input read-only memory space.
  */
 class MemoryArea : private Uncopyable
 {
@@ -52,72 +31,22 @@
   // If the given file handler is read-only, client can not request a region
   // that out of the file size.
   // @param pFileHandle - file handler
-  explicit MemoryArea(FileHandle& pFileHandle);
+  explicit MemoryArea(llvm::StringRef pFilename);
 
-  // constructor by set universal space.
-  // Client can not request a region that out of the universal space.
-  // @param pUniverse - file handler
-  explicit MemoryArea(Space& pUniverse);
-
-  // destructor
-  ~MemoryArea();
+  explicit MemoryArea(const char* pMemBuffer, size_t pSize);
 
   // request - create a MemoryRegion within a sufficient space
   // find an existing space to hold the MemoryRegion.
   // if MemoryArea does not find such space, then it creates a new space and
   // assign a MemoryRegion into the space.
-  MemoryRegion* request(size_t pOffset, size_t pLength);
+  llvm::StringRef request(size_t pOffset, size_t pLength);
 
-  // release - release a MemoryRegion.
-  // release a MemoryRegion does not cause
-  void release(MemoryRegion* pRegion);
-
-  // clear - release all memory regions.
-  void clear();
-
-  const FileHandle* handler() const { return m_pFileHandle; }
-  FileHandle*       handler()       { return m_pFileHandle; }
-
-  bool hasHandler() const { return (NULL != m_pFileHandle); }
-
-  // -----  space list methods  ----- //
-  Space* find(size_t pOffset, size_t pLength);
-
-  const Space* find(size_t pOffset, size_t pLength) const;
+  size_t size() const;
 
 private:
-  class Key {
-  public:
-    Key(size_t pOffset, size_t pLength)
-    : m_Offset(pOffset), m_Length(pLength)
-    { }
-
-    size_t offset() const { return m_Offset; }
-
-    size_t length() const { return m_Length; }
-
-    struct Compare {
-      bool operator()(const Key& KEY1, const Key& KEY2) const
-      {
-        return KEY1.offset() + KEY1.length() < KEY2.offset() ||
-               (KEY1.offset() < KEY2.offset() &&
-                (KEY1.offset() + KEY1.length() < KEY2.offset() + KEY2.length()));
-      }
-    };
-
-  private:
-    size_t m_Offset;
-    size_t m_Length;
-  };
-
-  typedef std::multimap<Key, Space*, Key::Compare> SpaceMapType;
-
-private:
-  SpaceMapType m_SpaceMap;
-  FileHandle* m_pFileHandle;
+  llvm::OwningPtr<llvm::MemoryBuffer> m_pMemoryBuffer;
 };
 
 } // namespace of mcld
 
 #endif
-
diff --git a/include/mcld/Support/MemoryAreaFactory.h b/include/mcld/Support/MemoryAreaFactory.h
index b28f096..302fbd1 100644
--- a/include/mcld/Support/MemoryAreaFactory.h
+++ b/include/mcld/Support/MemoryAreaFactory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SUPPORT_MEMORY_AREA_FACTORY_H
-#define MCLD_SUPPORT_MEMORY_AREA_FACTORY_H
+#ifndef MCLD_SUPPORT_MEMORYAREAFACTORY_H
+#define MCLD_SUPPORT_MEMORYAREAFACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -15,7 +15,7 @@
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/Path.h>
 #include <mcld/Support/FileHandle.h>
-#include <mcld/Support/HandleToArea.h>
+#include <llvm/ADT/StringMap.h>
 
 namespace mcld
 {
@@ -63,12 +63,10 @@
   MemoryArea* produce(int pFD, FileHandle::OpenMode pMode);
 
   void destruct(MemoryArea* pArea);
-
 private:
-  HandleToArea m_HandleToArea;
+  llvm::StringMap<MemoryArea*> m_AreaMap;
 };
 
 } // namespace of mcld
 
 #endif
-
diff --git a/include/mcld/Support/MemoryRegion.h b/include/mcld/Support/MemoryRegion.h
index 0984873..0d18f59 100644
--- a/include/mcld/Support/MemoryRegion.h
+++ b/include/mcld/Support/MemoryRegion.h
@@ -6,112 +6,24 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef LD_MEMORY_REGION_H
-#define LD_MEMORY_REGION_H
+#ifndef MCLD_SUPPORT_MEMORYREGION_H
+#define MCLD_SUPPORT_MEMORYREGION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
-#include <mcld/Config/Config.h>
-#include <mcld/ADT/Uncopyable.h>
-#include <mcld/Support/Allocators.h>
-#include <mcld/Support/Space.h>
+#include <mcld/ADT/TypeTraits.h>
+#include <llvm/ADT/ArrayRef.h>
+#include <llvm/Support/DataTypes.h>
 
 namespace mcld {
 
-class MemoryArea;
+typedef NonConstTraits<uint8_t>::pointer Address;
+typedef ConstTraits<uint8_t>::pointer ConstAddress;
 
-/** \class MemoryRegion
- *  \brief MemoryRegion is a range of virtual memory which is mapped onto a
- *  range of files which is opened by MemoryArea.
- *
- *  MemoryArea maps a file onto virtual memory. Clients can get a range of
- *  mapped memory space by requesting a MemoryRegion from MemoryArea, and
- *  read/write the mapped file through the MemoryRegion.
- *
- *  When two different MemoryRegion may overlap memory space, race condition
- *  may occurs. Clients must call MemoryRegion::sync() explicit to tell the
- *  MemoryArea when to synchronize the virtual memory space with the mapped
- *  file.
- */
-class MemoryRegion : private Uncopyable
-{
-friend class Chunk<MemoryRegion, MCLD_REGION_CHUNK_SIZE>;
-friend class RegionFactory;
-friend class MemoryArea;
+typedef llvm::ArrayRef<uint8_t> ConstMemoryRegion;
+typedef llvm::MutableArrayRef<uint8_t> MemoryRegion;
 
-public:
-  typedef Space::Address Address;
-  typedef Space::ConstAddress ConstAddress;
-
-private:
-  MemoryRegion();
-
-  MemoryRegion(const Address pVMAStart, size_t pSize);
-
-  ~MemoryRegion();
-
-  void setParent(Space& pSpace) { m_pParent = &pSpace; }
-
-public:
-  /// Create - To wrap a piece of memory and to create a new region.
-  /// This function wraps a piece of memory and to create a new region. Region
-  /// is just a wraper, it is not responsible for deallocate the given memory.
-  ///
-  /// @param pStart [in] The start address of a piece of memory
-  /// @param pSize  [in] The size of the given memory
-  static MemoryRegion* Create(void* pStart, size_t pSize);
-
-  /// Create - To wrap a piece of memory and to create a new region.
-  /// This function wraps a piece of memory and to create a new region. Region
-  /// is just a wraper, it is not responsible for deallocate the given memory.
-  ///
-  /// If a wrapped memory comes from a Space, then we say the space is the
-  /// parent of the region. pSpace is a memory counting container. It remembers
-  /// the number of regions in it. A space which has no region will be removed
-  /// quickly.
-  ///
-  /// The wrapped memory will be deallocated by Space when the space has no
-  /// region used it.
-  ///
-  /// @param pStart [in] The start address of a piece of memory
-  /// @param pSize  [in] The size of the given memory
-  /// @param pSpace [in] The parent space.
-  static MemoryRegion* Create(void* pStart, size_t pSize, Space& pSpace);
-
-  /// Destroy - To destroy the region
-  /// If the region has a parent space, it will be also remove from the space.
-  ///
-  /// @param pRegion [in, out] pRegion is set to NULL if the destruction is
-  /// success.
-  static void Destroy(MemoryRegion*& pRegion);
-
-  const Space* parent() const { return m_pParent; }
-  Space*       parent()       { return m_pParent; }
-
-  bool hasParent() const { return (NULL != m_pParent); }
-
-  ConstAddress start() const { return m_VMAStart; }
-  Address      start()       { return m_VMAStart; }
-
-  ConstAddress end() const { return m_VMAStart+m_Length; }
-  Address      end()       { return m_VMAStart+m_Length; }
-
-  size_t size() const { return m_Length; }
-
-  ConstAddress getBuffer(size_t pOffset = 0) const
-  { return m_VMAStart+pOffset; }
- 
-  Address getBuffer(size_t pOffset = 0)
-  { return m_VMAStart+pOffset; }
-
-private:
-  Space* m_pParent;
-  Address m_VMAStart;
-  size_t m_Length;
-};
-
-} // namespace of mcld
+} // namespace mcld
 
 #endif
-
diff --git a/include/mcld/Support/MsgHandling.h b/include/mcld/Support/MsgHandling.h
index d00132c..778ec68 100644
--- a/include/mcld/Support/MsgHandling.h
+++ b/include/mcld/Support/MsgHandling.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MESSAGE_HANDLING_H
-#define MCLD_MESSAGE_HANDLING_H
+#ifndef MCLD_SUPPORT_MSGHANDLING_H
+#define MCLD_SUPPORT_MSGHANDLING_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/Path.h b/include/mcld/Support/Path.h
index 13e8ddb..fe7914e 100644
--- a/include/mcld/Support/Path.h
+++ b/include/mcld/Support/Path.h
@@ -10,8 +10,8 @@
 // filesystem (v3), but modified to remove exception handling and the
 // path class.
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_PATH_H
-#define MCLD_PATH_H
+#ifndef MCLD_SUPPORT_PATH_H
+#define MCLD_SUPPORT_PATH_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/PathCache.h b/include/mcld/Support/PathCache.h
index 50c6984..37857dc 100644
--- a/include/mcld/Support/PathCache.h
+++ b/include/mcld/Support/PathCache.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_PATHCACHE_H
-#define MCLD_PATHCACHE_H
+#ifndef MCLD_SUPPORT_PATHCACHE_H
+#define MCLD_SUPPORT_PATHCACHE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/RealPath.h b/include/mcld/Support/RealPath.h
index 6c0cd40..0369f25 100644
--- a/include/mcld/Support/RealPath.h
+++ b/include/mcld/Support/RealPath.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_REAL_PATH_H
-#define MCLD_REAL_PATH_H
+#ifndef MCLD_SUPPORT_REALPATH_H
+#define MCLD_SUPPORT_REALPATH_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/RegionFactory.h b/include/mcld/Support/RegionFactory.h
deleted file mode 100644
index fd90186..0000000
--- a/include/mcld/Support/RegionFactory.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- RegionFactory.h ----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SUPPORT_REGION_FACTORY_H
-#define MCLD_SUPPORT_REGION_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/Config/Config.h>
-#include <mcld/Support/GCFactory.h>
-#include <mcld/Support/MemoryRegion.h>
-
-namespace mcld {
-
-class MemoryArea;
-
-/** \class RegionFactory
- *  \brief RegionFactory produces and destroys MemoryRegions
- *
- */
-class RegionFactory : public GCFactory<MemoryRegion, MCLD_REGION_CHUNK_SIZE>
-{
-public:
-  typedef GCFactory<MemoryRegion, MCLD_REGION_CHUNK_SIZE> Alloc;
-  typedef MemoryRegion::Address Address;
-  typedef MemoryRegion::ConstAddress ConstAddress;
-
-public:
-  MemoryRegion* produce(Address pVMAStart, size_t pSize);
-
-  void destruct(MemoryRegion* pRegion);
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/Space.h b/include/mcld/Support/Space.h
deleted file mode 100644
index cdf69b0..0000000
--- a/include/mcld/Support/Space.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===- Space.h ------------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_MEMORY_SPACE_H
-#define MCLD_MEMORY_SPACE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/Support/DataTypes.h>
-#include <mcld/ADT/TypeTraits.h>
-
-namespace mcld {
-
-class FileHandle;
-class MemoryRegion;
-
-/** \class Space
- *  \brief Space contains a chunk of memory space that does not overlap with
- *  the other Space.
- *
- */
-class Space
-{
-public:
-  enum Type
-  {
-    ALLOCATED_ARRAY,
-    MMAPED,
-    EXTERNAL,
-    UNALLOCATED
-  };
-
-  typedef NonConstTraits<uint8_t>::pointer Address;
-  typedef ConstTraits<uint8_t>::pointer ConstAddress;
-
-private:
-  Space();
-
-  ~Space();
-
-  Space(Type pType, void* pMemBuffer, size_t pSize);
-
-public:
-  void setStart(size_t pOffset)
-  { m_StartOffset = pOffset; }
-
-  Address memory()
-  { return m_Data; }
-
-  ConstAddress memory() const
-  { return m_Data; }
-
-  size_t start() const
-  { return m_StartOffset; }
-
-  size_t size() const
-  { return m_Size; }
-
-  Type type() const
-  { return m_Type; }
-
-  void addRegion(MemoryRegion& pRegion)
-  { ++m_RegionCount; }
-
-  void removeRegion(MemoryRegion& pRegion)
-  { --m_RegionCount; }
-
-  size_t numOfRegions() const
-  { return m_RegionCount; }
-
-  /// Create - Create a Space from external memory
-  static Space* Create(void* pMemBuffer, size_t pSize);
-
-  /// Create - Create a Space from FileHandler
-  static Space* Create(FileHandle& pHandler, size_t pOffset, size_t pSize);
-
-  static void Destroy(Space*& pSpace);
-  
-  static void Release(Space* pSpace, FileHandle& pHandler);
-
-  static void Sync(Space* pSpace, FileHandle& pHandler);
-
-private:
-  Address m_Data;
-  uint32_t m_StartOffset;
-  uint32_t m_Size;
-  uint16_t m_RegionCount;
-  Type m_Type : 2;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/SystemUtils.h b/include/mcld/Support/SystemUtils.h
index 8f8507a..f15fccf 100644
--- a/include/mcld/Support/SystemUtils.h
+++ b/include/mcld/Support/SystemUtils.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SYSTEM_UTILS_H
-#define MCLD_SYSTEM_UTILS_H
+#ifndef MCLD_SUPPORT_SYSTEMUTILS_H
+#define MCLD_SUPPORT_SYSTEMUTILS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/Target.h b/include/mcld/Support/Target.h
new file mode 100644
index 0000000..021fc2e
--- /dev/null
+++ b/include/mcld/Support/Target.h
@@ -0,0 +1,105 @@
+//===- Target.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SUPPORT_TARGET_H
+#define MCLD_SUPPORT_TARGET_H
+#include <string>
+#include <list>
+
+namespace llvm {
+class Target;
+class Triple;
+class TargetMachine;
+} // namespace of llvm
+
+namespace mcld {
+
+class MCLDTargetMachine;
+class TargetRegistry;
+class MCLinker;
+class LinkerScript;
+class LinkerConfig;
+class Module;
+class FileHandle;
+class DiagnosticLineInfo;
+class TargetLDBackend;
+
+/** \class Target
+ *  \brief Target collects target specific information
+ */
+class Target
+{
+  friend class mcld::MCLDTargetMachine;
+  friend class mcld::TargetRegistry;
+
+public:
+  typedef unsigned int (*TripleMatchQualityFnTy)(const llvm::Triple& pTriple);
+
+  typedef MCLDTargetMachine *(*TargetMachineCtorTy)(const llvm::Target &,
+                                                    const mcld::Target &,
+                                                    llvm::TargetMachine &,
+                                                    const std::string&);
+
+  typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple,
+                                      LinkerConfig&,
+                                      Module&,
+                                      FileHandle& pFileHandle);
+
+  typedef bool (*EmulationFnTy)(LinkerScript&, LinkerConfig&);
+
+  typedef TargetLDBackend  *(*TargetLDBackendCtorTy)(const LinkerConfig&);
+
+  typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&,
+                                                          const std::string&);
+
+public:
+  Target();
+
+  /// getName - get the target name
+  const char* name() const { return Name; }
+
+  unsigned int getTripleQuality(const llvm::Triple& pTriple) const;
+
+  /// createTargetMachine - create target-specific TargetMachine
+  MCLDTargetMachine* createTargetMachine(const std::string& pTriple,
+                                         const llvm::Target& pTarget,
+                                         llvm::TargetMachine& pTM) const;
+
+  /// createMCLinker - create target-specific MCLinker
+  MCLinker *createMCLinker(const std::string &pTriple,
+                           LinkerConfig& pConfig,
+                           Module& pModule,
+                           FileHandle& pFileHandle) const;
+
+  /// emulate - given MCLinker default values for the other aspects of the
+  /// target system.
+  bool emulate(LinkerScript& pScript, LinkerConfig& pConfig) const;
+
+  /// createLDBackend - create target-specific LDBackend
+  TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const;
+
+  /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
+  DiagnosticLineInfo* createDiagnosticLineInfo(const mcld::Target& pTarget,
+                                               const std::string& pTriple) const;
+
+private:
+  /// Name - The target name
+  const char* Name;
+
+  TripleMatchQualityFnTy TripleMatchQualityFn;
+  TargetMachineCtorTy TargetMachineCtorFn;
+  MCLinkerCtorTy MCLinkerCtorFn;
+  EmulationFnTy EmulationFn;
+  TargetLDBackendCtorTy TargetLDBackendCtorFn;
+  DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn;
+};
+
+} //end namespace mcld
+
+#endif
+
diff --git a/include/mcld/Support/TargetRegistry.h b/include/mcld/Support/TargetRegistry.h
index aabb06d..1ae6245 100644
--- a/include/mcld/Support/TargetRegistry.h
+++ b/include/mcld/Support/TargetRegistry.h
@@ -6,9 +6,11 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_REGISTRY_H
-#define MCLD_TARGET_REGISTRY_H
-#include <llvm/Support/TargetRegistry.h>
+#ifndef MCLD_SUPPORT_TARGETREGISTRY_H
+#define MCLD_SUPPORT_TARGETREGISTRY_H
+#include <mcld/Support/Target.h>
+#include <llvm/ADT/Triple.h>
+
 #include <string>
 #include <list>
 
@@ -21,122 +23,9 @@
 
 namespace mcld {
 
-class Module;
-class LinkerConfig;
-class LinkerScript;
-class MemoryArea;
-class MCLDTargetMachine;
-class TargetRegistry;
-class MCLinker;
-class TargetLDBackend;
-class AttributeFactory;
-class InputFactory;
-class ContextFactory;
-class DiagnosticLineInfo;
-
-//===----------------------------------------------------------------------===//
-/// Target - mcld::Target is an object adapter of llvm::Target
-//===----------------------------------------------------------------------===//
-class Target
-{
-  friend class mcld::MCLDTargetMachine;
-  friend class mcld::TargetRegistry;
-public:
-  typedef mcld::MCLDTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &,
-                                                          llvm::TargetMachine &,
-                                                          const std::string&);
-
-  typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple,
-                                      LinkerConfig&,
-                                      Module&,
-                                      MemoryArea& pOutput);
-
-  typedef bool (*EmulationFnTy)(LinkerScript&, LinkerConfig&);
-
-  typedef TargetLDBackend  *(*TargetLDBackendCtorTy)(const llvm::Target&,
-                                                     const LinkerConfig&);
-
-  typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&,
-                                                          const std::string&);
-
-public:
-  Target();
-
-  void setTarget(const llvm::Target& pTarget)
-  { m_pT = &pTarget; }
-
-  mcld::MCLDTargetMachine *createTargetMachine(const std::string &pTriple,
-                          const std::string &pCPU, const std::string &pFeatures,
-                          const llvm::TargetOptions &Options,
-                          llvm::Reloc::Model RM = llvm::Reloc::Default,
-                          llvm::CodeModel::Model CM = llvm::CodeModel::Default,
-                          llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default) const
-  {
-    if (TargetMachineCtorFn && m_pT) {
-      llvm::TargetMachine *tm = m_pT->createTargetMachine(pTriple, pCPU, pFeatures, Options, RM, CM, OL);
-      if (tm)
-        return TargetMachineCtorFn(*this, *tm, pTriple);
-    }
-    return NULL;
-  }
-
-  /// createMCLinker - create target-specific MCLinker
-  ///
-  /// @return created MCLinker
-  MCLinker *createMCLinker(const std::string &pTriple,
-                           LinkerConfig& pConfig,
-                           Module& pModule,
-                           MemoryArea& pOutput) const {
-    if (!MCLinkerCtorFn)
-      return NULL;
-    return MCLinkerCtorFn(pTriple, pConfig, pModule, pOutput);
-  }
-
-  /// emulate - given MCLinker default values for the other aspects of the
-  /// target system.
-  bool emulate(LinkerScript& pScript, LinkerConfig& pConfig) const {
-    if (!EmulationFn)
-      return false;
-    return EmulationFn(pScript, pConfig);
-  }
-
-  /// createLDBackend - create target-specific LDBackend
-  ///
-  /// @return created TargetLDBackend
-  TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const
-  {
-    if (!TargetLDBackendCtorFn)
-      return NULL;
-    return TargetLDBackendCtorFn(*get(), pConfig);
-  }
-
-  /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
-  DiagnosticLineInfo* createDiagnosticLineInfo(const mcld::Target& pTarget,
-                                               const std::string& pTriple) const
-  {
-    if (!DiagnosticLineInfoCtorFn)
-      return NULL;
-    return DiagnosticLineInfoCtorFn(pTarget, pTriple);
-  }
-
-  const llvm::Target* get() const { return m_pT; }
-
-private:
-  // -----  function pointers  ----- //
-  TargetMachineCtorTy TargetMachineCtorFn;
-  MCLinkerCtorTy MCLinkerCtorFn;
-  EmulationFnTy EmulationFn;
-  TargetLDBackendCtorTy TargetLDBackendCtorFn;
-  DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn;
-
-  // -----  adapted llvm::Target  ----- //
-  const llvm::Target* m_pT;
-};
-
-//===----------------------------------------------------------------------===//
-/// TargetRegistry - mcld::TargetRegistry is an object adapter of
-/// llvm::TargetRegistry
-///
+/** \class TargetRegistry
+ *  \brief TargetRegistry is an object adapter of llvm::TargetRegistry
+ */
 class TargetRegistry
 {
 public:
@@ -161,7 +50,9 @@
   /// this is done by initializing all targets at program startup.
   ///
   /// @param T - The target being registered.
-  static void RegisterTarget(mcld::Target &T);
+  static void RegisterTarget(Target& pTarget,
+                             const char* pName,
+                             Target::TripleMatchQualityFnTy pQualityFn);
 
   /// RegisterTargetMachine - Register a TargetMachine implementation for the
   /// given target.
@@ -221,16 +112,23 @@
       T.DiagnosticLineInfoCtorFn = Fn;
   }
 
-  /// lookupTarget - Lookup a target based on a llvm::Target.
-  ///
-  /// @param T - The llvm::Target to find
-  static const mcld::Target *lookupTarget(const llvm::Target& T);
-
-  /// lookupTarget - function wrapper of llvm::TargetRegistry::lookupTarget
+  /// lookupTarget - Look up MCLinker target
   ///
   /// @param Triple - The Triple string
   /// @param Error  - The returned error message
-  static const mcld::Target *lookupTarget(const std::string &Triple,
+  static const mcld::Target *lookupTarget(const std::string& pTriple,
+                                          std::string& pError);
+
+  /// lookupTarget - Look up MCLinker target by an architecture name
+  /// and a triple. If the architecture name is not empty, then the
+  /// the lookup is done mainly by architecture. Otherwise, the target
+  /// triple is used.
+  ///
+  /// @param pArch   - The architecture name
+  /// @param pTriple - The target triple
+  /// @param pError  - The returned error message
+  static const mcld::Target *lookupTarget(const std::string& pArchName,
+                                          llvm::Triple& pTriple,
                                           std::string &Error);
 };
 
@@ -240,22 +138,27 @@
 /// Target TheFooTarget; // The global target instance.
 ///
 /// extern "C" void MCLDInitializeFooTargetInfo() {
-///   RegisterTarget X(TheFooTarget, "foo", "Foo description");
+///   RegisterTarget<llvm::Foo> X(TheFooTarget, "foo", "Foo description");
 /// }
+template<llvm::Triple::ArchType TargetArchType = llvm::Triple::UnknownArch>
 struct RegisterTarget
 {
-  RegisterTarget(mcld::Target &T, const char *Name) {
-    llvm::TargetRegistry::iterator TIter, TEnd = llvm::TargetRegistry::end();
-    // lookup llvm::Target
-    for( TIter=llvm::TargetRegistry::begin(); TIter!=TEnd; ++TIter ) {
-      if( 0==strcmp(TIter->getName(), Name) )
-        break;
+public:
+  RegisterTarget(mcld::Target &pTarget, const char* pName) {
+    // if we've registered one, then return immediately.
+    TargetRegistry::iterator target, ie = TargetRegistry::end();
+    for (target = TargetRegistry::begin(); target != ie; ++target) {
+      if (0 == strcmp((*target)->name(), pName))
+        return;
     }
 
-    if (TIter != TEnd)
-      T.setTarget(*TIter);
+    TargetRegistry::RegisterTarget(pTarget, pName, &getTripleMatchQuality);
+  }
 
-    TargetRegistry::RegisterTarget(T);
+  static unsigned int getTripleMatchQuality(const llvm::Triple& pTriple) {
+    if (pTriple.getArch() == TargetArchType)
+      return 20;
+    return 0;
   }
 };
 
@@ -275,10 +178,11 @@
   }
 
 private:
-  static mcld::MCLDTargetMachine *Allocator(const mcld::Target &T,
-                                            llvm::TargetMachine& TM,
-                                            const std::string &Triple) {
-    return new TargetMachineImpl(TM, T, Triple);
+  static MCLDTargetMachine *Allocator(const llvm::Target& pLLVMTarget,
+                                      const mcld::Target& pMCLDTarget,
+                                      llvm::TargetMachine& pTM,
+                                      const std::string& pTriple) {
+    return new TargetMachineImpl(pTM, pLLVMTarget, pMCLDTarget, pTriple);
   }
 };
 
diff --git a/include/mcld/Support/TargetSelect.h b/include/mcld/Support/TargetSelect.h
index 7fcb74a..0b2be2a 100644
--- a/include/mcld/Support/TargetSelect.h
+++ b/include/mcld/Support/TargetSelect.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_SELECT_H
-#define MCLD_TARGET_SELECT_H
+#ifndef MCLD_SUPPORT_TARGETSELECT_H
+#define MCLD_SUPPORT_TARGETSELECT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/ToolOutputFile.h b/include/mcld/Support/ToolOutputFile.h
index 4dfc4e6..f1186c3 100644
--- a/include/mcld/Support/ToolOutputFile.h
+++ b/include/mcld/Support/ToolOutputFile.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_SUPPORT_TOOL_OUTPUT_FILE_H
-#define MCLD_SUPPORT_TOOL_OUTPUT_FILE_H
+#ifndef MCLD_SUPPORT_TOOLOUTPUTFILE_H
+#define MCLD_SUPPORT_TOOLOUTPUTFILE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -23,12 +23,9 @@
 
 class Path;
 class FileHandle;
-class MemoryArea;
-class raw_mem_ostream;
 
 /** \class ToolOutputFile
- *  \brief ToolOutputFile contains a raw_mem_ostream and adds extra new
- *  features:
+ *  \brief ToolOutputFile has the following features:
  *   - The file is automatically deleted if the process is killed.
  *   - The file is automatically deleted when the TooOutputFile object is
  *     destoryed unless the client calls keep().
@@ -36,21 +33,21 @@
 class ToolOutputFile
 {
 public:
-  ToolOutputFile(const std::string& pPath,
+  ToolOutputFile(const sys::fs::Path& pPath,
                  FileHandle::OpenMode pMode,
                  FileHandle::Permission pPermission);
 
   ~ToolOutputFile();
 
-  /// mem_os - Return the contained raw_mem_ostream.
-  raw_mem_ostream &mem_os();
+  /// fd - Retutn the output file handle
+  FileHandle& fd() { return m_FileHandle; }
 
-  /// os - Return the contained formatted_raw_ostream
+  /// os - Return the contained raw_fd_ostream
+  llvm::raw_fd_ostream& os();
+
+  /// formatted_os - Return the contained formatted_raw_ostream
   llvm::formatted_raw_ostream& formatted_os();
 
-  /// memory - Return the contained MemoryArea.
-  MemoryArea& memory();
-
   /// keep - Indicate that the tool's job wrt this output file has been
   /// successful and the file should not be deleted.
   void keep();
@@ -59,7 +56,7 @@
   class CleanupInstaller
   {
   public:
-    explicit CleanupInstaller(const std::string& pPath);
+    explicit CleanupInstaller(const sys::fs::Path& pPath);
 
     ~CleanupInstaller();
 
@@ -67,19 +64,16 @@
     bool Keep;
 
   private:
-    std::string m_Path;
+    sys::fs::Path m_Path;
   }; 
 
 private:
   FileHandle m_FileHandle;
   CleanupInstaller m_Installer;
-  MemoryArea* m_pMemoryArea;
-  raw_mem_ostream* m_pOStream;
-  llvm::formatted_raw_ostream* m_pFOStream;
-
+  llvm::raw_fd_ostream* m_pFdOstream;
+  llvm::formatted_raw_ostream* m_pFormattedOstream;
 };
 
 } // namespace of mcld
 
 #endif
-
diff --git a/include/mcld/Support/UniqueGCFactory.h b/include/mcld/Support/UniqueGCFactory.h
index 3147bab..73c1110 100644
--- a/include/mcld/Support/UniqueGCFactory.h
+++ b/include/mcld/Support/UniqueGCFactory.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_UNIQUE_GCFACTORY_H
-#define MCLD_UNIQUE_GCFACTORY_H
+#ifndef MCLD_SUPPORT_UNIQUEGCFACTORY_H
+#define MCLD_SUPPORT_UNIQUEGCFACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Support/raw_mem_ostream.h b/include/mcld/Support/raw_mem_ostream.h
deleted file mode 100644
index b2db64a..0000000
--- a/include/mcld/Support/raw_mem_ostream.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===- raw_mem_ostream.h --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_RAW_MEMORY_AREA_OSTREAM_H
-#define MCLD_RAW_MEMORY_AREA_OSTREAM_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <string>
-
-#include <llvm/Support/raw_ostream.h>
-
-namespace mcld {
-
-class MemoryArea;
-
-class raw_mem_ostream : public llvm::raw_ostream
-{
-public:
-  /// constructor - pMemoryArea must be writable.
-  explicit raw_mem_ostream(MemoryArea &pMemoryArea);
-
-  ~raw_mem_ostream();
-
-  MemoryArea& getMemoryArea() {
-    flush();
-    return m_MemoryArea;
-  }
-
-private:
-  /// write_impl - See raw_ostream::write_impl.
-  virtual void write_impl(const char *pPtr, size_t pSize);
-
-  /// current_pos - Return the current position within the stream, not
-  /// counting the bytes currently in the buffer.
-  virtual uint64_t current_pos() const;
-
-private:
-  MemoryArea& m_MemoryArea;
-  uint64_t m_Position;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/raw_ostream.h b/include/mcld/Support/raw_ostream.h
index 0e2cc40..6274e49 100644
--- a/include/mcld/Support/raw_ostream.h
+++ b/include/mcld/Support/raw_ostream.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_RAW_OSTREAM_H
-#define MCLD_RAW_OSTREAM_H
+#ifndef MCLD_SUPPORT_RAWOSTREAM_H
+#define MCLD_SUPPORT_RAWOSTREAM_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Target/DarwinLDBackend.h b/include/mcld/Target/DarwinLDBackend.h
index d55055a..9003812 100644
--- a/include/mcld/Target/DarwinLDBackend.h
+++ b/include/mcld/Target/DarwinLDBackend.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef DARWINLDBACKEND_H
-#define DARWINLDBACKEND_H
+#ifndef MCLD_TARGET_DARWINLDBACKEND_H
+#define MCLD_TARGET_DARWINLDBACKEND_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Target/ELFAttribute.h b/include/mcld/Target/ELFAttribute.h
new file mode 100644
index 0000000..7d9d30d
--- /dev/null
+++ b/include/mcld/Target/ELFAttribute.h
@@ -0,0 +1,125 @@
+//===- ELFAttribute.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_ELFATTRIBUTE_H
+#define MCLD_TARGET_ELFATTRIBUTE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Target/ELFAttributeData.h>
+
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/StringRef.h>
+
+namespace mcld {
+
+class ELFAttributeData;
+class GNULDBackend;
+class Input;
+class LDSection;
+class LinkerConfig;
+
+/** \class ELFAttribute
+ *  \brief ELFAttribute is the attribute section in an ELF file.
+ */
+class ELFAttribute
+{
+public:
+  // ARM [ABI-addenda], 2.2.3.
+  static const char   FormatVersion = 'A';
+  static const size_t FormatVersionFieldSize = sizeof(FormatVersion); // a byte
+  static const size_t SubsectionLengthFieldSize = 4; // a 4-byte integer
+
+  // MinimalELFAttributeSubsectionSize is the minimal number of bytes a valid
+  // subsection in ELF attribute section should have.
+  static const size_t MinimalELFAttributeSubsectionSize
+      = 1 /* Tag_File, see ARM [ABI-addenda], 2.2.4 */ +
+        4 /* byte-size, see ARM [ABI-addenda], 2.2.4 */;
+
+  // MinimalELFAttributeSectionSize is the minimal number of bytes a valid ELF
+  // attribute section should have.
+  static const size_t MinimalELFAttributeSectionSize
+      = FormatVersionFieldSize + SubsectionLengthFieldSize +
+        2 /* vendor-name, a char plus '\0', see ARM [ABI-addenda], 2.2.3 */ +
+        1 * MinimalELFAttributeSubsectionSize;
+
+public:
+  ELFAttribute(const GNULDBackend &pBackend, const LinkerConfig& pConfig)
+    : m_Backend(pBackend), m_Config(pConfig) { }
+
+  ~ELFAttribute();
+
+public:
+  /// merge - merge attributes from input (attribute) section
+  bool merge(const Input &pInput, LDSection &pInputAttrSectHdr);
+
+  /// sizeOutput - calculate the number of bytes required to encode this
+  /// attribute data section
+  size_t sizeOutput() const;
+
+  /// emit - encode and write out this attribute section
+  size_t emit(MemoryRegion &pRegion) const;
+
+  inline const GNULDBackend &backend() const { return m_Backend; }
+
+  inline const LinkerConfig &config() const { return m_Config; }
+
+  // Place vendor's attribute data under the management.
+  void registerAttributeData(ELFAttributeData& pAttrData);
+
+private:
+  /** \class Subsection
+   *  \brief A helper class to wrap ELFAttributeData and to provide general
+   *  interfaces for ELFAttribute to operate on
+   */
+  class Subsection {
+  public:
+    Subsection(ELFAttribute &pParent, ELFAttributeData &pAttrData)
+      : m_Parent(pParent), m_AttrData(pAttrData) { }
+
+  public:
+    bool isMyAttribute(llvm::StringRef pVendorName) const
+    {
+      return (m_AttrData.getVendorName() == pVendorName);
+    }
+
+    /// merge -  Merge the attributes from the section in the input data.
+    bool merge(const Input &pInput, ConstAddress pData, size_t pSize);
+
+    /// sizeOutput - calculate the number of bytes required to encode this
+    /// subsection
+    size_t sizeOutput() const;
+
+    /// emit - write out this attribute subsection to the buffer.
+    size_t emit(char *pBuf) const;
+
+  private:
+    // The attribute section this subsection belongs to
+    ELFAttribute &m_Parent;
+
+    // The attribute data containing in this subsection
+    ELFAttributeData &m_AttrData;
+  };
+
+  // Obtain the corresponding subsection of the specified vendor
+  Subsection *getSubsection(llvm::StringRef pVendorName) const;
+
+private:
+  const GNULDBackend &m_Backend;
+
+  const LinkerConfig &m_Config;
+
+  // There is at most two subsections ("aeabi" and "gnu") in most cases.
+  llvm::SmallVector<Subsection*, 2> m_Subsections;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Target/ELFAttributeData.h b/include/mcld/Target/ELFAttributeData.h
new file mode 100644
index 0000000..1cb9ad7
--- /dev/null
+++ b/include/mcld/Target/ELFAttributeData.h
@@ -0,0 +1,114 @@
+//===- ELFAttributeData.h -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_ELFATTRIBUTEDATA_H
+#define MCLD_TARGET_ELFATTRIBUTEDATA_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <stdint.h>
+#include <string>
+#include <utility>
+
+namespace mcld {
+
+class ELFAttributeValue;
+class Input;
+class LinkerConfig;
+
+/** \class ELFAttributeData
+ *  \brief ELFAttributeData handles data in vendor attribute subsection.
+ */
+class ELFAttributeData
+{
+public:
+  typedef uint32_t TagType;
+
+  // Generic attribute tags shared between all vendors
+  enum {
+    Tag_NULL          = 0,
+    Tag_File          = 1,
+    Tag_Section       = 2,
+    Tag_Symbol        = 3,
+  };
+
+public:
+  ELFAttributeData(const char* pVendor) : m_Vendor(pVendor) { }
+
+  virtual ~ELFAttributeData() { }
+
+public:
+  inline const std::string &getVendorName() const { return m_Vendor; }
+
+  /// getAttributeValue - query the data store for the attribute value of the
+  /// given tag.
+  virtual const ELFAttributeValue *getAttributeValue(TagType pTag) const = 0;
+
+  /// getOrCreateAttributeValue - obtain attribute value for the given tag and
+  /// create if it does not exist.
+  ///
+  /// It returns a pair containing the attribute value instance (guaranteed to
+  /// be non-NULL) and a boolean value indicating whether the instance is newly
+  /// created (true) or not (false.)
+  virtual std::pair<ELFAttributeValue*, bool>
+      getOrCreateAttributeValue(TagType pTag) = 0;
+
+  /// preMerge - hooks to call before starting merge the attribute data in an
+  /// input.
+  virtual bool preMerge(const Input &pInput) { return true; }
+
+  /// merge - implement logics to merge input attribute to the output.
+  virtual bool merge(const LinkerConfig& pConfig, const Input &pInput,
+                     TagType pTag, const ELFAttributeValue& pInAttr) = 0;
+
+  /// postMerge - hooks to call after finishing merge the attribute data from an
+  /// input.
+  virtual bool postMerge(const LinkerConfig& pConfig, const Input &pInput)
+  { return true; }
+
+  /// sizeOutput - obtain number of bytes required to encode the attribute data.
+  virtual size_t sizeOutput() const = 0;
+
+  /// emit - write out attribute data to the buffer and return the number of
+  /// bytes written
+  virtual size_t emit(char *pBuf) const = 0;
+
+public:
+  /// ReadTag - read an attribute tag from input buffer.
+  ///
+  /// If the read succeeds, pBuf moves to the new position just pass the end of
+  /// the tag in the buffer and pBufSize decreases the size of tag in the
+  /// buffer. Otherwise, this function will return false and change nothing
+  /// except leaving undefined value in pTag.
+  static bool ReadTag(TagType& pTag, const char* &pBuf, size_t &pBufSize);
+
+  /// ReadValue - read an attribute value from input buffer
+  ///
+  /// Similar with ReadTag() while this reads attribute value from the input
+  /// buffer. Note that the value type of the attribute must be properly set in
+  /// pValue prior the call.
+  static bool ReadValue(ELFAttributeValue& pValue, const char* &pBuf,
+                        size_t &pBufSize);
+
+  /// WriteAttribute - write an attribute tag plus value to buffer.
+  ///
+  /// On success, the pBuf moves to the new position just pass the end of the
+  /// attribute data just written. Otherwise, it returns false and leaves pBuf
+  /// in an undefined position. Note that buffer is guaranteed to be able to
+  /// contain the attribute data.
+  static bool WriteAttribute(TagType pTag, const ELFAttributeValue& pValue,
+                             char* &pBuf);
+
+private:
+  const std::string m_Vendor;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Target/ELFAttributeValue.h b/include/mcld/Target/ELFAttributeValue.h
new file mode 100644
index 0000000..0af3c97
--- /dev/null
+++ b/include/mcld/Target/ELFAttributeValue.h
@@ -0,0 +1,125 @@
+//===- ELFAttributeValue.h ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_ELFATTRIBUTEVALUE_H
+#define MCLD_TARGET_ELFATTRIBUTEVALUE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+
+namespace mcld
+{
+
+/** \class ELFAttributeValue
+ *  \brief ELFAttributeValue stroes the value of an attribute tag. The attribtue
+ *  tag itself is not stored in this object.
+ */
+class ELFAttributeValue
+{
+public:
+  // Type of value that an attribute tag holds.
+  enum Type {
+    // The value contains no data and has unknown type.
+    Uninitialized = 0,
+
+    // The value contains integer data.
+    Int           = 1L << 0,
+
+    // The value contains string data.
+    String        = 1L << 1,
+
+    // This is for attribute in which "default value" (0 for int type and empty
+    // string for string type) has special meaning for them. That is, the
+    // default value is "disabled" and meaningful for those attribute.
+    NoDefault     = 1L << 2,
+  };
+
+public:
+  ELFAttributeValue()
+    : m_Type(Uninitialized), m_IntValue(0), m_StringValue() { }
+
+  ~ELFAttributeValue() { }
+
+public:
+  unsigned int type() const
+  { return m_Type; }
+
+  void setType(unsigned int pType)
+  { m_Type = pType; }
+
+  unsigned int getIntValue() const
+  { return m_IntValue; }
+
+  void setIntValue(unsigned int pIntValue)
+  { m_IntValue = pIntValue; }
+
+  const std::string &getStringValue() const
+  { return m_StringValue; }
+
+  void setStringValue(const std::string &pStringValue)
+  { m_StringValue = pStringValue; }
+
+  void setStringValue(const char *pStringValue, size_t pSize)
+  { m_StringValue.assign(pStringValue, pSize); }
+
+  void setStringValue(const char *pStringValue)
+  { m_StringValue.assign(pStringValue); }
+
+  size_t getSize() const;
+
+  inline bool isUninitialized() const
+  { return (m_Type == Uninitialized); }
+
+  inline bool isInitialized() const
+  { return !isUninitialized(); }
+
+  inline bool isIntValue() const
+  { return (m_Type & Int); }
+
+  inline bool isStringValue() const
+  { return (m_Type & String); }
+
+  inline bool hasNoDefault() const
+  { return (m_Type & NoDefault); }
+
+  bool isDefaultValue() const;
+
+  // Returns true if this attribute value should be emitted to the output.
+  inline bool shouldEmit() const {
+    // Attribute with non-default value should be emitted.
+    return !isDefaultValue();
+  }
+
+  bool equals(const ELFAttributeValue& pValue) const;
+
+  bool operator==(const ELFAttributeValue& pValue) const
+  { return equals(pValue); }
+  bool operator!=(const ELFAttributeValue& pValue) const
+  { return !equals(pValue); }
+
+  /// reset - reset this value to the uninitialized state
+  void reset()
+  {
+    m_Type = Uninitialized;
+    m_IntValue = 0;
+    m_StringValue.clear();
+    return;
+  }
+
+private:
+  unsigned int m_Type;
+
+  unsigned int m_IntValue;
+  std::string m_StringValue;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Target/ELFDynamic.h b/include/mcld/Target/ELFDynamic.h
index 62f534d..c9b257f 100644
--- a/include/mcld/Target/ELFDynamic.h
+++ b/include/mcld/Target/ELFDynamic.h
@@ -6,14 +6,15 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_DYNAMIC_SECTION_H
-#define MCLD_ELF_DYNAMIC_SECTION_H
+#ifndef MCLD_TARGET_ELFDYNAMIC_H
+#define MCLD_TARGET_ELFDYNAMIC_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
-#include <llvm/Support/ELF.h>
 #include <mcld/LD/LDSection.h>
+#include <mcld/Support/FileOutputBuffer.h>
+#include <llvm/Support/ELF.h>
 #include <vector>
 #include <cstring>
 
@@ -22,7 +23,6 @@
 class ELFFileFormat;
 class GNULDBackend;
 class LinkerConfig;
-class MemoryRegion;
 
 namespace elf_dynamic {
 
diff --git a/include/mcld/Target/ELFEmulation.h b/include/mcld/Target/ELFEmulation.h
index 9d35792..2a79f11 100644
--- a/include/mcld/Target/ELFEmulation.h
+++ b/include/mcld/Target/ELFEmulation.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_EMULATION_H
-#define MCLD_ELF_EMULATION_H
+#ifndef MCLD_TARGET_ELFEMULATION_H
+#define MCLD_TARGET_ELFEMULATION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/include/mcld/Target/ELFMCLinker.h b/include/mcld/Target/ELFMCLinker.h
index 76f46e8..2cead3b 100644
--- a/include/mcld/Target/ELFMCLinker.h
+++ b/include/mcld/Target/ELFMCLinker.h
@@ -11,8 +11,8 @@
 // This pass set up default parameters for ELF.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_SECTION_LINKER_H
-#define MCLD_ELF_SECTION_LINKER_H
+#ifndef MCLD_TARGET_ELFMCLINKER_H
+#define MCLD_TARGET_ELFMCLINKER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -22,13 +22,14 @@
 
 class Module;
 class Output;
+class FileHandle;
 
 class ELFMCLinker : public MCLinker
 {
 public:
   ELFMCLinker(LinkerConfig& pConfig,
               mcld::Module& pModule,
-              MemoryArea& pOutput);
+              FileHandle& pFileHandle);
 
   virtual ~ELFMCLinker();
 };
diff --git a/include/mcld/Target/GNUInfo.h b/include/mcld/Target/GNUInfo.h
index 86a29ba..247d817 100644
--- a/include/mcld/Target/GNUInfo.h
+++ b/include/mcld/Target/GNUInfo.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_GNU_INFO_H
-#define MCLD_TARGET_GNU_INFO_H
+#ifndef MCLD_TARGET_GNUINFO_H
+#define MCLD_TARGET_GNUINFO_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -36,7 +36,7 @@
   uint8_t OSABI() const;
 
   /// ABIVersion - the value of e_ident[EI_ABIVRESION]
-  uint8_t ABIVersion() const { return 0x0; }
+  virtual uint8_t ABIVersion() const { return 0x0; }
 
   /// defaultTextSegmentAddr - target should specify its own default start address
   /// of the text segment. esp. for exec.
@@ -65,7 +65,7 @@
   /// here. If target favors the different size, please override this function
   virtual uint64_t abiPageSize() const { return 0x1000; }
 
-private:
+protected:
   const llvm::Triple& m_Triple;
 };
 
diff --git a/include/mcld/Target/GNULDBackend.h b/include/mcld/Target/GNULDBackend.h
index 3384eae..0d23964 100644
--- a/include/mcld/Target/GNULDBackend.h
+++ b/include/mcld/Target/GNULDBackend.h
@@ -6,31 +6,21 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_GNU_LDBACKEND_H
-#define MCLD_TARGET_GNU_LDBACKEND_H
+#ifndef MCLD_TARGET_GNULDBACKEND_H
+#define MCLD_TARGET_GNULDBACKEND_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <mcld/Target/TargetLDBackend.h>
 
-#include <llvm/Support/ELF.h>
-#include <mcld/ADT/HashTable.h>
-#include <mcld/ADT/HashEntry.h>
-#include <mcld/LD/ELFDynObjFileFormat.h>
-#include <mcld/LD/ELFExecFileFormat.h>
-#include <mcld/LD/ELFObjectFileFormat.h>
+#include <mcld/Module.h>
 #include <mcld/LD/GNUArchiveReader.h>
-#include <mcld/LD/ELFObjectReader.h>
 #include <mcld/LD/ELFDynObjReader.h>
 #include <mcld/LD/ELFBinaryReader.h>
+#include <mcld/LD/ELFObjectReader.h>
 #include <mcld/LD/ELFObjectWriter.h>
-#include <mcld/LD/ELFSegment.h>
-#include <mcld/LD/ELFSegmentFactory.h>
-#include <mcld/Target/ELFDynamic.h>
-#include <mcld/Target/GNUInfo.h>
 
-#include <mcld/Support/GCFactory.h>
-#include <mcld/Module.h>
+#include <llvm/Support/ELF.h>
 
 namespace mcld {
 
@@ -42,6 +32,15 @@
 class BranchIslandFactory;
 class StubFactory;
 class GNUInfo;
+class ELFFileFormat;
+class ELFSegmentFactory;
+class ELFAttribute;
+class ELFDynamic;
+class ELFDynObjFileFormat;
+class ELFExecFileFormat;
+class ELFObjectFileFormat;
+class LinkerScript;
+class Relocation;
 
 /** \class GNULDBackend
  *  \brief GNULDBackend provides a common interface for all GNU Unix-OS
@@ -110,6 +109,9 @@
   /// getSegmentStartAddr - this function returns the start address of the segment
   uint64_t getSegmentStartAddr(const LinkerScript& pScript) const;
 
+  /// sizeShstrtab - compute the size of .shstrtab
+  void sizeShstrtab(Module& pModule);
+
   /// sizeNamePools - compute the size of regular name pools
   /// In ELF executable files, regular name pools are .symtab, .strtab.,
   /// .dynsym, .dynstr, and .hash
@@ -120,25 +122,25 @@
                                    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, FileOutputBuffer& pOutput);
 
   /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
-  virtual void emitDynNamePools(Module& pModule, MemoryArea& pOutput);
+  virtual void emitDynNamePools(Module& pModule, FileOutputBuffer& pOutput);
 
   /// emitELFHashTab - emit .hash
   virtual void emitELFHashTab(const Module::SymbolTable& pSymtab,
-                              MemoryArea& pOutput);
+                              FileOutputBuffer& pOutput);
 
   /// emitGNUHashTab - emit .gnu.hash
   virtual void emitGNUHashTab(Module::SymbolTable& pSymtab,
-                              MemoryArea& pOutput);
+                              FileOutputBuffer& pOutput);
 
   /// 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();
 
   /// emitInterp - emit the .interp
-  virtual void emitInterp(MemoryArea& pOutput);
+  virtual void emitInterp(FileOutputBuffer& pOutput);
 
   /// hasEntryInStrTab - symbol has an entry in a .strtab
   virtual bool hasEntryInStrTab(const LDSymbol& pSym) const;
@@ -169,16 +171,11 @@
   virtual unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const
   { return (unsigned int)-1; }
 
-  /// numOfSegments - return the number of segments
-  /// if the target favors other ways to emit program header, please override
-  /// this function
-  size_t numOfSegments() const { return m_ELFSegmentTable.size(); }
+  /// elfSegmentTable - return the reference of the elf segment table
+  ELFSegmentFactory&       elfSegmentTable();
 
   /// elfSegmentTable - return the reference of the elf segment table
-  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;
 
   /// commonPageSize - the common page size of the target machine
   uint64_t commonPageSize() const;
@@ -198,6 +195,58 @@
   /// update the output section flags based on input section flags.
   virtual bool updateSectionFlags(LDSection& pTo, const LDSection& pFrom);
 
+  /// readRelocation - read ELF32_Rel entry
+  virtual bool readRelocation(const llvm::ELF::Elf32_Rel& pRel,
+                              uint32_t& pType,
+                              uint32_t& pSymIdx,
+                              uint32_t& pOffset) const;
+
+  /// readRelocation - read ELF32_Rela entry
+  virtual bool readRelocation(const llvm::ELF::Elf32_Rela& pRel,
+                              uint32_t& pType,
+                              uint32_t& pSymIdx,
+                              uint32_t& pOffset,
+                              int32_t& pAddend) const;
+
+  /// readRelocation - read ELF64_Rel entry
+  virtual bool readRelocation(const llvm::ELF::Elf64_Rel& pRel,
+                              uint32_t& pType,
+                              uint32_t& pSymIdx,
+                              uint64_t& pOffset) const;
+
+  /// readRel - read ELF64_Rela entry
+  virtual bool readRelocation(const llvm::ELF::Elf64_Rela& pRel,
+                              uint32_t& pType,
+                              uint32_t& pSymIdx,
+                              uint64_t& pOffset,
+                              int64_t& pAddend) const;
+
+  /// emitRelocation - write data to the ELF32_Rel entry
+  virtual void emitRelocation(llvm::ELF::Elf32_Rel& pRel,
+                              uint32_t pType,
+                              uint32_t pSymIdx,
+                              uint32_t pOffset) const;
+
+  /// emitRelocation - write data to the ELF32_Rela entry
+  virtual void emitRelocation(llvm::ELF::Elf32_Rela& pRel,
+                              uint32_t pType,
+                              uint32_t pSymIdx,
+                              uint32_t pOffset,
+                              int32_t pAddend) const;
+
+  /// emitRelocation - write data to the ELF64_Rel entry
+  virtual void emitRelocation(llvm::ELF::Elf64_Rel& pRel,
+                              uint32_t pType,
+                              uint32_t pSymIdx,
+                              uint64_t pOffset) const;
+
+  /// emitRelocation - write data to the ELF64_Rela entry
+  virtual void emitRelocation(llvm::ELF::Elf64_Rela& pRel,
+                              uint32_t pType,
+                              uint32_t pSymIdx,
+                              uint64_t pOffset,
+                              int64_t pAddend) const;
+
   /// symbolNeedsPLT - return whether the symbol needs a PLT entry
   /// @ref Google gold linker, symtab.h:596
   bool symbolNeedsPLT(const ResolveInfo& pSym) const;
@@ -223,11 +272,11 @@
 
   /// isDynamicSymbol
   /// @ref Google gold linker: symtab.cc:311
-  bool isDynamicSymbol(const LDSymbol& pSymbol);
+  bool isDynamicSymbol(const LDSymbol& pSymbol) const;
 
   /// isDynamicSymbol
   /// @ref Google gold linker: symtab.cc:311
-  bool isDynamicSymbol(const ResolveInfo& pResolveInfo);
+  bool isDynamicSymbol(const ResolveInfo& pResolveInfo) const;
 
   virtual ResolveInfo::Desc getSymDesc(uint16_t pShndx) const {
     return ResolveInfo::Define;
@@ -247,6 +296,9 @@
   LDSymbol& getTBSSSymbol();
   const LDSymbol& getTBSSSymbol() const;
 
+  /// getEntry - get the entry point name
+  llvm::StringRef getEntry(const Module& pModule) const;
+
   //  -----  relaxation  -----  //
   /// initBRIslandFactory - initialize the branch island factory for relaxation
   bool initBRIslandFactory();
@@ -267,7 +319,27 @@
   /// checkAndSetHasTextRel - check pSection flag to set HasTextRel
   void checkAndSetHasTextRel(const LDSection& pSection);
 
+  /// sortRelocation - sort the dynamic relocations to let dynamic linker
+  /// process relocations more efficiently
+  void sortRelocation(LDSection& pSection);
+
+  /// createAndSizeEhFrameHdr - This is seperated since we may add eh_frame
+  /// entry in the middle
+  void createAndSizeEhFrameHdr(Module& pModule);
+
+  /// attribute - the attribute section data.
+  ELFAttribute& attribute() { return *m_pAttribute; }
+
+  /// attribute - the attribute section data.
+  const ELFAttribute& attribute() const { return *m_pAttribute; }
+
 protected:
+  /// getRelEntrySize - the size in BYTE of rel type relocation
+  virtual size_t getRelEntrySize() = 0;
+
+  /// getRelEntrySize - the size in BYTE of rela type relocation
+  virtual size_t getRelaEntrySize() = 0;
+
   uint64_t getSymbolSize(const LDSymbol& pSymbol) const;
 
   uint64_t getSymbolInfo(const LDSymbol& pSymbol) const;
@@ -315,33 +387,19 @@
 
   /// getSegmentFlag - give a section flag and return the corresponding segment
   /// flag
-  inline uint32_t getSegmentFlag(const uint32_t pSectionFlag)
-  {
-    uint32_t flag = llvm::ELF::PF_R;
-    if (0 != (pSectionFlag & llvm::ELF::SHF_WRITE))
-      flag |= llvm::ELF::PF_W;
-    if (0 != (pSectionFlag & llvm::ELF::SHF_EXECINSTR))
-      flag |= llvm::ELF::PF_X;
-    return flag;
-  }
+  inline uint32_t getSegmentFlag(const uint32_t pSectionFlag);
 
   /// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
   void setupGNUStackInfo(Module& pModule);
 
-  /// setupRelro - setup the offset constraint of PT_RELRO
-  void setupRelro(Module& pModule);
+  /// setOutputSectionOffset - helper function to set output sections' offset.
+  void setOutputSectionOffset(Module& pModule);
 
-  /// setOutputSectionOffset - helper function to set a group of output sections'
-  /// offset, and set pSectBegin to pStartOffset if pStartOffset is not -1U.
-  void setOutputSectionOffset(Module& pModule,
-                              Module::iterator pSectBegin,
-                              Module::iterator pSectEnd,
-                              uint64_t pStartOffset = -1U);
+  /// setOutputSectionAddress - helper function to set output sections' address.
+  void setOutputSectionAddress(Module& pModule);
 
-  /// setOutputSectionOffset - helper function to set output sections' address.
-  void setOutputSectionAddress(Module& pModule,
-                               Module::iterator pSectBegin,
-                               Module::iterator pSectEnd);
+  /// placeOutputSections - place output sections based on SectionMap
+  void placeOutputSections(Module& pModule);
 
   /// layout - layout method
   void layout(Module& pModule);
@@ -359,7 +417,7 @@
   virtual void doPostLayout(Module& pModule, IRBuilder& pLinker) = 0;
 
   /// postProcessing - Backend can do any needed modification in the final stage
-  void postProcessing(MemoryArea& pOutput);
+  void postProcessing(FileOutputBuffer& pOutput);
 
   /// dynamic - the dynamic section of the target machine.
   virtual ELFDynamic& dynamic() = 0;
@@ -380,56 +438,48 @@
   virtual bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished)
   { return false; }
 
-  /// getRelEntrySize - the size in BYTE of rel type relocation
-  virtual size_t getRelEntrySize() = 0;
-
-  /// getRelEntrySize - the size in BYTE of rela type relocation
-  virtual size_t getRelaEntrySize() = 0;
-
 protected:
   // Based on Kind in LDFileFormat to define basic section orders for ELF, and
   // refer gold linker to add more enumerations to handle Regular and BSS kind
   enum SectionOrder {
-    SHO_INTERP = 1,          // .interp
-    SHO_RO_NOTE,             // .note.ABI-tag, .note.gnu.build-id
-    SHO_NAMEPOOL,            // *.hash, .dynsym, .dynstr
-    SHO_RELOCATION,          // .rel.*, .rela.*
-    SHO_REL_PLT,             // .rel.plt should come after other .rel.*
-    SHO_INIT,                // .init
-    SHO_PLT,                 // .plt
-    SHO_TEXT,                // .text
-    SHO_FINI,                // .fini
-    SHO_RO,                  // .rodata
-    SHO_EXCEPTION,           // .eh_frame_hdr, .eh_frame, .gcc_except_table
-    SHO_TLS_DATA,            // .tdata
-    SHO_TLS_BSS,             // .tbss
-    SHO_RELRO_LOCAL,         // .data.rel.ro.local
-    SHO_RELRO,               // .data.rel.ro,
-    SHO_RELRO_LAST,          // for x86 to adjust .got if needed
-    SHO_NON_RELRO_FIRST,     // for x86 to adjust .got.plt if needed
-    SHO_DATA,                // .data
-    SHO_LARGE_DATA,          // .ldata
-    SHO_RW_NOTE,             //
-    SHO_SMALL_DATA,          // .sdata
-    SHO_SMALL_BSS,           // .sbss
-    SHO_BSS,                 // .bss
-    SHO_LARGE_BSS,           // .lbss
-    SHO_UNDEFINED,           // default order
-    SHO_STRTAB               // .strtab
+    SHO_NULL = 0,        // NULL
+    SHO_INTERP,          // .interp
+    SHO_RO_NOTE,         // .note.ABI-tag, .note.gnu.build-id
+    SHO_NAMEPOOL,        // *.hash, .dynsym, .dynstr
+    SHO_RELOCATION,      // .rel.*, .rela.*
+    SHO_REL_PLT,         // .rel.plt should come after other .rel.*
+    SHO_INIT,            // .init
+    SHO_PLT,             // .plt
+    SHO_TEXT,            // .text
+    SHO_FINI,            // .fini
+    SHO_RO,              // .rodata
+    SHO_EXCEPTION,       // .eh_frame_hdr, .eh_frame, .gcc_except_table
+    SHO_TLS_DATA,        // .tdata
+    SHO_TLS_BSS,         // .tbss
+    SHO_RELRO_LOCAL,     // .data.rel.ro.local
+    SHO_RELRO,           // .data.rel.ro,
+    SHO_RELRO_LAST,      // for x86 to adjust .got if needed
+    SHO_NON_RELRO_FIRST, // for x86 to adjust .got.plt if needed
+    SHO_DATA,            // .data
+    SHO_LARGE_DATA,      // .ldata
+    SHO_RW_NOTE,         //
+    SHO_SMALL_DATA,      // .sdata
+    SHO_SMALL_BSS,       // .sbss
+    SHO_BSS,             // .bss
+    SHO_LARGE_BSS,       // .lbss
+    SHO_UNDEFINED,       // default order
+    SHO_STRTAB           // .strtab
   };
 
-  typedef std::pair<LDSection*, unsigned int> SHOEntry;
-
-  struct SHOCompare
+  // for -z combreloc
+  struct RelocCompare
   {
-    bool operator()(const SHOEntry& X, const SHOEntry& Y) const
-    { return X.second < Y.second; }
-  };
-
-  struct SymCompare
-  {
-    bool operator()(const LDSymbol* X, const LDSymbol* Y) const
-    { return (X==Y); }
+    RelocCompare(const GNULDBackend& pBackend)
+      : m_Backend(pBackend) {
+    }
+    bool operator()(const Relocation* X, const Relocation* Y) const;
+  private:
+    const GNULDBackend& m_Backend;
   };
 
   // for gnu style hash table
@@ -440,6 +490,12 @@
     bool operator()(const LDSymbol* X, const LDSymbol* Y) const;
   };
 
+  struct SymCompare
+  {
+    bool operator()(const LDSymbol* X, const LDSymbol* Y) const
+    { return (X==Y); }
+  };
+
   struct SymPtrHash
   {
     size_t operator()(const LDSymbol* pKey) const
@@ -467,7 +523,7 @@
   GNUInfo* m_pInfo;
 
   // ELF segment factory
-  ELFSegmentFactory m_ELFSegmentTable;
+  ELFSegmentFactory* m_pELFSegmentTable;
 
   // branch island factory
   BranchIslandFactory* m_pBRIslandFactory;
@@ -481,6 +537,9 @@
   // section .eh_frame_hdr
   EhFrameHdr* m_pEhFrameHdr;
 
+  // attribute section
+  ELFAttribute* m_pAttribute;
+
   // ----- dynamic flags ----- //
   // DF_TEXTREL of DT_FLAGS
   bool m_bHasTextRel;
diff --git a/include/mcld/Target/GOT.h b/include/mcld/Target/GOT.h
index 9b61bcd..eb73741 100644
--- a/include/mcld/Target/GOT.h
+++ b/include/mcld/Target/GOT.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_GLOBAL_OFFSET_TABLE_H
-#define MCLD_GLOBAL_OFFSET_TABLE_H
+#ifndef MCLD_TARGET_GOT_H
+#define MCLD_TARGET_GOT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -80,13 +80,6 @@
   // finalizeSectionSize - set LDSection size
   virtual void finalizeSectionSize();
 
-  /// reserve - reseve number of pNum of empty entries
-  /// Before layout, we scan all relocations to determine if GOT entries are
-  /// needed. If an entry is needed, the empty entry is reserved for layout
-  /// to adjust the fragment offset. After that, we fill up the entries when
-  /// applying relocations.
-  virtual void reserve(size_t pNum = 1) = 0;
-
 protected:
   LDSection& m_Section;
   SectionData* m_SectionData;
diff --git a/include/mcld/Target/KeyEntryMap.h b/include/mcld/Target/KeyEntryMap.h
new file mode 100644
index 0000000..8136687
--- /dev/null
+++ b/include/mcld/Target/KeyEntryMap.h
@@ -0,0 +1,204 @@
+//===- KeyEntryMap.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_KEYENTRYMAP_H
+#define MCLD_TARGET_KEYENTRYMAP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+#include <list>
+
+namespace mcld {
+
+/** \class KeyEntryMap
+ *  \brief KeyEntryMap is a <const KeyType*, ENTRY*> map.
+ */
+template<typename KEY, typename ENTRY>
+class KeyEntryMap
+{
+public:
+  typedef KEY   KeyType;
+  typedef ENTRY EntryType;
+
+private:
+  struct EntryPair {
+    EntryPair(EntryType* pEntry1, EntryType* pEntry2)
+     : entry1(pEntry1), entry2(pEntry2)
+    {}
+
+    EntryType* entry1;
+    EntryType* entry2;
+  };
+
+  /// EntryOrPair - A key may mapping to a signal entry or a pair of entries,
+  /// user is responsible for the type of Mapping.entry
+  union EntryOrPair {
+    EntryType* entry_ptr;
+    EntryPair* pair_ptr;
+  };
+
+  struct Mapping {
+    const KeyType* key;
+    EntryOrPair entry;
+  };
+
+  typedef std::vector<Mapping> KeyEntryPool;
+  typedef std::list<EntryPair> PairListType;
+
+public:
+  typedef typename KeyEntryPool::iterator iterator;
+  typedef typename KeyEntryPool::const_iterator const_iterator;
+
+public:
+  /// lookUp - look up the entry mapping to pKey
+  const EntryType* lookUp(const KeyType& pKey) const;
+  EntryType*       lookUp(const KeyType& pKey);
+
+  /// lookUpFirstEntry - look up the first entry mapping to pKey
+  const EntryType* lookUpFirstEntry(const KeyType& pKey) const;
+  EntryType*       lookUpFirstEntry(const KeyType& pKey);
+
+  /// lookUpSecondEntry - look up the second entry mapping to pKey
+  const EntryType* lookUpSecondEntry(const KeyType& pKey) const;
+  EntryType*       lookUpSecondEntry(const KeyType& pKey);
+
+  void record(const KeyType& pKey, EntryType& pEntry);
+  void record(const KeyType& pKey,
+              EntryType& pEntry1,
+              EntryType& pEntry2);
+
+  bool   empty() const { return m_Pool.empty(); }
+  size_t size () const { return m_Pool.size(); }
+
+  const_iterator begin() const { return m_Pool.begin(); }
+  iterator       begin()       { return m_Pool.begin(); }
+  const_iterator end  () const { return m_Pool.end();   }
+  iterator       end  ()       { return m_Pool.end();   }
+
+  void reserve(size_t pSize) { m_Pool.reserve(pSize); }
+
+private:
+  KeyEntryPool m_Pool;
+
+  /// m_Pairs - the EntryPairs
+  PairListType m_Pairs;
+};
+
+template<typename KeyType, typename EntryType>
+const EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUp(const KeyType& pKey) const
+{
+  const_iterator mapping, mEnd = m_Pool.end();
+  for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+    if (mapping->key == &pKey) {
+      return mapping->entry.entry_ptr;
+    }
+  }
+
+  return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUp(const KeyType& pKey)
+{
+  iterator mapping, mEnd = m_Pool.end();
+  for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+    if (mapping->key == &pKey) {
+      return mapping->entry.entry_ptr;
+    }
+  }
+
+  return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+const EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUpFirstEntry(const KeyType& pKey) const
+{
+  const_iterator mapping, mEnd = m_Pool.end();
+  for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+    if (mapping->key == &pKey) {
+      return mapping->entry.pair_ptr->entry1;
+    }
+  }
+
+  return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUpFirstEntry(const KeyType& pKey)
+{
+  const_iterator mapping, mEnd = m_Pool.end();
+  for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+    if (mapping->key == &pKey) {
+      return mapping->entry.pair_ptr->entry1;
+    }
+  }
+
+  return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+const EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUpSecondEntry(const KeyType& pKey) const
+{
+  const_iterator mapping, mEnd = m_Pool.end();
+  for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+    if (mapping->key == &pKey) {
+      return mapping->entry.pair_ptr->entry2;
+    }
+  }
+
+  return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUpSecondEntry(const KeyType& pKey)
+{
+  const_iterator mapping, mEnd = m_Pool.end();
+  for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+    if (mapping->key == &pKey) {
+      return mapping->entry.pair_ptr->entry2;
+    }
+  }
+
+  return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+void
+KeyEntryMap<KeyType, EntryType>::record(const KeyType& pKey, EntryType& pEntry)
+{
+  Mapping mapping;
+  mapping.key = &pKey;
+  mapping.entry.entry_ptr = &pEntry;
+  m_Pool.push_back(mapping);
+}
+
+template<typename KeyType, typename EntryType>
+void
+KeyEntryMap<KeyType, EntryType>::record(const KeyType& pKey,
+                                  EntryType& pEntry1,
+                                  EntryType& pEntry2)
+{
+  Mapping mapping;
+  mapping.key = &pKey;
+  m_Pairs.push_back(EntryPair(&pEntry1, &pEntry2));
+  mapping.entry.pair_ptr = &m_Pairs.back();
+  m_Pool.push_back(mapping);
+}
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Target/OutputRelocSection.h b/include/mcld/Target/OutputRelocSection.h
index b0f8f2d..a109843 100644
--- a/include/mcld/Target/OutputRelocSection.h
+++ b/include/mcld/Target/OutputRelocSection.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_OUTPUT_RELOCATION_SECTION_H
-#define MCLD_OUTPUT_RELOCATION_SECTION_H
+#ifndef MCLD_TARGET_OUTPUTRELOCSECTION_H
+#define MCLD_TARGET_OUTPUTRELOCSECTION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -32,6 +32,9 @@
 
   ~OutputRelocSection();
 
+  /// create - create an dynamic relocation entry
+  Relocation* create();
+
   void reserveEntry(size_t pNum=1);
 
   Relocation* consumeEntry();
diff --git a/include/mcld/Target/PLT.h b/include/mcld/Target/PLT.h
index 5d91446..7305a74 100644
--- a/include/mcld/Target/PLT.h
+++ b/include/mcld/Target/PLT.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_PROCEDURE_LINKAGE_TABLE_H
-#define MCLD_PROCEDURE_LINKAGE_TABLE_H
+#ifndef MCLD_TARGET_PLT_H
+#define MCLD_TARGET_PLT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -22,7 +22,7 @@
 class ResolveInfo;
 
 /** \class PLTEntryDefaultBase
- *  \brief PLTEntryDefaultBase provides the default interface for PLE Entry
+ *  \brief PLTEntryDefaultBase provides the default interface for PLT Entry
  */
 class PLTEntryBase : public TargetFragment
 {
@@ -33,7 +33,7 @@
 
   virtual ~PLTEntryBase()
   {
-    delete m_pValue;
+    free(m_pValue);
   }
 
   void setValue(unsigned char* pValue)
@@ -81,10 +81,6 @@
 
   virtual ~PLT();
 
-  /// reserveEntry - reseve the number of pNum of empty entries
-  /// The empty entris are reserved for layout to adjust the fragment offset.
-  virtual void reserveEntry(size_t pNum = 1) = 0;
-
   // finalizeSectionSize - set LDSection size
   virtual void finalizeSectionSize() = 0;
 
diff --git a/include/mcld/Target/SymbolEntryMap.h b/include/mcld/Target/SymbolEntryMap.h
deleted file mode 100644
index fc5ea93..0000000
--- a/include/mcld/Target/SymbolEntryMap.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===- SymbolEntryMap.h ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_SYMBOL_ENTRY_MAP_H
-#define MCLD_TARGET_SYMBOL_ENTRY_MAP_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <vector>
-
-namespace mcld {
-
-class ResolveInfo;
-
-/** \class SymbolEntryMap
- *  \brief SymbolEntryMap is a <const ResolveInfo*, ENTRY*> map.
- */
-template<typename ENTRY>
-class SymbolEntryMap
-{
-public:
-  typedef ENTRY EntryType;
-
-private:
-  struct Mapping {
-    const ResolveInfo* symbol;
-    EntryType*   entry;
-  };
-
-  typedef std::vector<Mapping> SymbolEntryPool;
-
-public:
-  typedef typename SymbolEntryPool::iterator iterator;
-  typedef typename SymbolEntryPool::const_iterator const_iterator;
-
-public:
-  const EntryType* lookUp(const ResolveInfo& pSymbol) const;
-  EntryType*       lookUp(const ResolveInfo& pSymbol);
-
-  void record(const ResolveInfo& pSymbol, EntryType& pEntry);
-
-  bool   empty() const { return m_Pool.empty(); }
-  size_t size () const { return m_Pool.size(); }
-
-  const_iterator begin() const { return m_Pool.begin(); }
-  iterator       begin()       { return m_Pool.begin(); }
-  const_iterator end  () const { return m_Pool.end();   }
-  iterator       end  ()       { return m_Pool.end();   }
-
-  void reserve(size_t pSize) { m_Pool.reserve(pSize); }
-
-private:
-  SymbolEntryPool m_Pool;
-
-};
-
-template<typename EntryType>
-const EntryType*
-SymbolEntryMap<EntryType>::lookUp(const ResolveInfo& pSymbol) const
-{
-  const_iterator mapping, mEnd = m_Pool.end();
-  for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
-    if (mapping->symbol == &pSymbol) {
-      return mapping->entry;
-    }
-  }
-
-  return NULL;
-}
-
-template<typename EntryType>
-EntryType*
-SymbolEntryMap<EntryType>::lookUp(const ResolveInfo& pSymbol)
-{
-  iterator mapping, mEnd = m_Pool.end();
-  for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
-    if (mapping->symbol == &pSymbol) {
-      return mapping->entry;
-    }
-  }
-
-  return NULL;
-}
-
-template<typename EntryType>
-void
-SymbolEntryMap<EntryType>::record(const ResolveInfo& pSymbol, EntryType& pEntry)
-{
-  Mapping mapping;
-  mapping.symbol = &pSymbol;
-  mapping.entry = &pEntry;
-  m_Pool.push_back(mapping);
-}
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Target/TargetLDBackend.h b/include/mcld/Target/TargetLDBackend.h
index d3f14b2..29fb395 100644
--- a/include/mcld/Target/TargetLDBackend.h
+++ b/include/mcld/Target/TargetLDBackend.h
@@ -1,4 +1,4 @@
-//===-- llvm/Target/TargetLDBackend.h - Target LD Backend -----*- C++ -*-===//
+//===-- TargetLDBackend.h - Target LD Backend -------------------*- C++ -*-===//
 //
 //                     The MCLinker Project
 //
@@ -9,36 +9,34 @@
 #ifndef MCLD_TARGET_TARGETLDBACKEND_H
 #define MCLD_TARGET_TARGETLDBACKEND_H
 
+#include <llvm/ADT/StringRef.h>
 #include <llvm/Support/DataTypes.h>
+#include <mcld/LD/GarbageCollection.h>
 
 namespace mcld {
 
-class Module;
-class LinkerConfig;
-class IRBuilder;
-class Relocation;
-class RelocationFactory;
-class Relocator;
-class Layout;
 class ArchiveReader;
-class ObjectReader;
-class DynObjReader;
 class BinaryReader;
-class ObjectWriter;
+class BinaryWriter;
+class BranchIslandFactory;
+class DynObjReader;
 class DynObjWriter;
 class ExecWriter;
-class BinaryWriter;
-class LDFileFormat;
-class LDSymbol;
-class LDSection;
-class SectionData;
+class FileOutputBuffer;
+class SectionReachedListMap;
+class IRBuilder;
 class Input;
-class GOT;
-class MemoryArea;
-class MemoryAreaFactory;
-class BranchIslandFactory;
-class StubFactory;
+class LDSection;
+class LDSymbol;
+class Layout;
+class LinkerConfig;
+class Module;
 class ObjectBuilder;
+class ObjectReader;
+class ObjectWriter;
+class Relocator;
+class SectionData;
+class StubFactory;
 
 //===----------------------------------------------------------------------===//
 /// TargetLDBackend - Generic interface to target specific assembler backends.
@@ -84,7 +82,7 @@
   virtual void postLayout(Module& pModule, IRBuilder& pBuilder) = 0;
 
   /// postProcessing - Backend can do any needed modification in the final stage
-  virtual void postProcessing(MemoryArea& pOutput) = 0;
+  virtual void postProcessing(FileOutputBuffer& pOutput) = 0;
 
   /// section start offset in the output file
   virtual size_t sectionStartOffset() const = 0;
@@ -112,9 +110,17 @@
   virtual bool allocateCommonSymbols(Module& pModule) = 0;
 
   /// mergeSection - merge target dependent sections.
-  virtual bool mergeSection(Module& pModule, LDSection& pInputSection)
+  virtual bool mergeSection(Module& pModule,
+                            const Input& pInputFile,
+                            LDSection& pInputSection)
   { return true; }
 
+  /// setUpReachedSectionsForGC - set the reference between two sections for
+  /// some special target sections. GC will set up the reference for the Regular
+  /// and BSS sections. Backends can also set up the reference if need.
+  virtual void setUpReachedSectionsForGC(const Module& pModule,
+        GarbageCollection::SectionReachedListMap& pSectReachedListMap) const { }
+
   /// 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
@@ -130,6 +136,9 @@
   /// In ELF executables, this is the length of dynamic linker's path name
   virtual void sizeInterp() = 0;
 
+  /// getEntry - get the entry point name
+  virtual llvm::StringRef getEntry(const Module& pModule) const = 0;
+
   // -----  relaxation  ----- //
   virtual bool initBRIslandFactory() = 0;
   virtual bool initStubFactory() = 0;
@@ -144,6 +153,20 @@
   /// mayRelax - return true if the backend needs to do relaxation
   virtual bool mayRelax() = 0;
 
+  /// commonPageSize - the common page size of the target machine
+  virtual uint64_t commonPageSize() const = 0;
+
+  /// abiPageSize - the abi page size of the target machine
+  virtual uint64_t abiPageSize() const = 0;
+
+  /// sortRelocation - sort the dynamic relocations to let dynamic linker
+  /// process relocations more efficiently
+  virtual void sortRelocation(LDSection& pSection) = 0;
+
+  /// createAndSizeEhFrameHdr - This is seperated since we may add eh_frame
+  /// entry in the middle
+  virtual void createAndSizeEhFrameHdr(Module& pModule) = 0;
+
 protected:
   const LinkerConfig& config() const { return m_Config; }
 
diff --git a/include/mcld/TargetOptions.h b/include/mcld/TargetOptions.h
index dfdd773..5f7e339 100644
--- a/include/mcld/TargetOptions.h
+++ b/include/mcld/TargetOptions.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_OPTIONS_H
-#define MCLD_TARGET_OPTIONS_H
+#ifndef MCLD_TARGETOPTIONS_H
+#define MCLD_TARGETOPTIONS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -44,6 +44,10 @@
 
   void setTriple(const llvm::Triple& pTriple);
 
+  const std::string& getArch() const { return m_ArchName; }
+
+  void setArch(const std::string& pArchName);
+
   const std::string& getTargetCPU() const { return m_TargetCPU; }
 
   void setTargetCPU(const std::string& pCPU);
@@ -68,6 +72,7 @@
 
 private:
   llvm::Triple m_Triple;
+  std::string m_ArchName;
   std::string m_TargetCPU;
   std::string m_TargetFS;
   Endian m_Endian;
diff --git a/lib/ADT/GraphLite/Digraph.cpp b/lib/ADT/GraphLite/Digraph.cpp
new file mode 100644
index 0000000..301f9fa
--- /dev/null
+++ b/lib/ADT/GraphLite/Digraph.cpp
@@ -0,0 +1,88 @@
+//===- Digraph.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/ADT/GraphLite/Digraph.h>
+
+using namespace mcld::graph;
+
+//===----------------------------------------------------------------------===//
+// Digraph::Arc
+//===----------------------------------------------------------------------===//
+Digraph::Arc::Arc()
+{
+}
+
+bool Digraph::Arc::operator==(const Digraph::Node& pOther) const
+{
+  return true;
+}
+
+bool Digraph::Arc::operator!=(const Digraph::Node& pOther) const
+{
+  return true;
+}
+
+Digraph::Node Digraph::Arc::source() const
+{
+  return Node();
+}
+
+Digraph::Node Digraph::Arc::target() const
+{
+  return Node();
+}
+
+Digraph::Arc::Arc(Digraph& pParent)
+{
+}
+
+
+//===----------------------------------------------------------------------===//
+// Digraph
+//===----------------------------------------------------------------------===//
+Digraph::Digraph()
+{
+}
+
+
+Digraph::Node Digraph::addNode()
+{
+  return Node();
+}
+
+
+Digraph::Arc
+Digraph::addArc(const Digraph::Node& pSource, const Digraph::Node& pTarget)
+{
+  return Arc();
+}
+
+
+void Digraph::erase(const Digraph::Node& pNode)
+{
+}
+
+
+void Digraph::erase(const Digraph::Arc& pArc)
+{
+}
+
+
+void Digraph::clear()
+{
+}
+
+unsigned int Digraph::numOfNodes() const
+{
+  return 0;
+}
+
+unsigned int Digraph::numOfArcs() const
+{
+  return 0;
+}
diff --git a/lib/ADT/GraphLite/ListDigraph.cpp b/lib/ADT/GraphLite/ListDigraph.cpp
new file mode 100644
index 0000000..fcf957b
--- /dev/null
+++ b/lib/ADT/GraphLite/ListDigraph.cpp
@@ -0,0 +1,178 @@
+//===- ListDigraph.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/ADT/GraphLite/ListDigraph.h>
+
+using namespace mcld::graph;
+
+//===----------------------------------------------------------------------===//
+// ListDigraph::Node
+//===----------------------------------------------------------------------===//
+ListDigraph::Node::Node()
+  : prev(NULL), next(NULL), first_in(NULL), first_out(NULL) {
+}
+
+//===----------------------------------------------------------------------===//
+// ListDigraph::Arc
+//===----------------------------------------------------------------------===//
+ListDigraph::Arc::Arc()
+  : target(NULL), source(NULL),
+    prev_in(NULL), next_in(NULL), prev_out(NULL), next_out(NULL) {
+}
+
+//===----------------------------------------------------------------------===//
+// ListDigraph
+//===----------------------------------------------------------------------===//
+ListDigraph::ListDigraph()
+  : m_pNodeHead(NULL), m_pFreeNodeHead(NULL), m_pFreeArcHead(NULL),
+    m_NodeList(32), m_ArcList(32) {
+}
+
+
+ListDigraph::Node* ListDigraph::addNode()
+{
+  // 1. find an available free node
+  Node* result = NULL;
+  if (NULL == m_pFreeNodeHead) {
+    result = m_NodeList.allocate();
+    new (result) Node();
+  }
+  else {
+    result = m_pFreeNodeHead;
+    m_pFreeNodeHead = m_pFreeNodeHead->next;
+  }
+
+  // 2. set up linkages
+  result->prev = NULL;
+  result->next = m_pNodeHead;
+
+  // 3. reset head node
+  if (NULL != m_pNodeHead) {
+    m_pNodeHead->prev = result;
+  }
+  m_pNodeHead = result;
+
+  return result;
+}
+
+
+ListDigraph::Arc* ListDigraph::addArc(Node& pU, Node& pV)
+{
+  // 1. find an available free arc
+  Arc* result = NULL;
+  if (NULL == m_pFreeArcHead) {
+    result = m_ArcList.allocate();
+    new (result) Arc();
+  }
+  else {
+    result = m_pFreeArcHead;
+    m_pFreeArcHead = m_pFreeArcHead->next_in;
+  }
+
+  // 2. set up arc
+  result->source = &pU;
+  result->target = &pV;
+
+  // 3. set up fan-out linked list
+  result->next_out = pU.first_out;
+  if (NULL != pU.first_out) {
+    pU.first_out->prev_out = result;
+  }
+  pU.first_out = result;
+
+  // 4. set up fan-in linked list
+  result->next_in = pV.first_in;
+  if (NULL != pV.first_in) {
+    pV.first_in->prev_in = result;
+  }
+  pV.first_in = result;
+
+  return result;
+}
+
+void ListDigraph::erase(ListDigraph::Node& pNode)
+{
+  // 1. connect previous node and next node.
+  if (NULL != pNode.next) {
+    pNode.next->prev = pNode.prev;
+  }
+
+  if (NULL != pNode.prev) {
+    pNode.prev->next = pNode.next;
+  }
+  else { // pNode.prev is NULL => pNode is the head
+    m_pNodeHead = pNode.next;
+  }
+
+  // 2. remove all fan-in arcs
+  Arc* fan_in = pNode.first_in;
+  while(NULL != fan_in) {
+    Arc* next_in = fan_in->next_in;
+    erase(*fan_in);
+    fan_in = next_in;
+  }
+
+  // 3. remove all fan-out arcs
+  Arc* fan_out = pNode.first_out;
+  while(NULL != fan_out) {
+    Arc* next_out = fan_out->next_out;
+    erase(*fan_out);
+    fan_out = next_out;
+  }
+
+  // 4. put pNode in the free node list
+  pNode.next = m_pFreeNodeHead;
+  pNode.prev = NULL;
+  if (NULL != m_pFreeNodeHead)
+    m_pFreeNodeHead->prev = &pNode;
+  m_pFreeNodeHead = &pNode;
+}
+
+
+void ListDigraph::erase(ListDigraph::Arc& pArc)
+{
+  // 1. remove from the fan-out list
+  if (NULL != pArc.prev_out) {
+    pArc.prev_out->next_out = pArc.next_out;
+  }
+  else { // pArc.prev_out is NULL => pArc is the first_out of the source
+    pArc.source->first_out = pArc.next_out;
+  }
+
+  if (NULL != pArc.next_out) {
+    pArc.next_out->prev_out = pArc.prev_out;
+  }
+
+  // 2. remove from the fan-in list
+  if (NULL != pArc.prev_in) {
+    pArc.prev_in->next_in = pArc.next_in;
+  }
+  else {
+    pArc.target->first_in = pArc.next_in;
+  }
+
+  if (NULL != pArc.next_in) {
+    pArc.next_in->prev_in = pArc.prev_in;
+  }
+
+  // 3. put pArc in the free arc list
+  // Use fan-in links to chain the free list
+  pArc.next_in = m_pFreeArcHead;
+  m_pFreeArcHead = &pArc;
+}
+
+
+void ListDigraph::clear()
+{
+  m_pNodeHead = NULL;
+  m_pFreeNodeHead = NULL;
+  m_pFreeArcHead = NULL;
+  m_NodeList.clear();
+  m_ArcList.clear();
+}
+
diff --git a/lib/CodeGen/MCLDTargetMachine.cpp b/lib/CodeGen/MCLDTargetMachine.cpp
index a695f29..272e775 100644
--- a/lib/CodeGen/MCLDTargetMachine.cpp
+++ b/lib/CodeGen/MCLDTargetMachine.cpp
@@ -6,15 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/Target/TargetMachine.h>
+#include <mcld/CodeGen/TargetMachine.h>
 
 #include <mcld/Module.h>
 #include <mcld/LinkerConfig.h>
 #include <mcld/CodeGen/MCLinker.h>
-#include <mcld/Support/raw_mem_ostream.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/Support/ToolOutputFile.h>
-#include <mcld/Support/MemoryArea.h>
 #include <mcld/Target/TargetLDBackend.h>
 
 #include <llvm/ADT/OwningPtr.h>
@@ -59,7 +57,6 @@
 // Enable or disable FastISel. Both options are needed, because
 // FastISel is enabled by default with -fast, and we wish to be
 // able to enable or disable fast-isel independently from -O0.
-
 static cl::opt<cl::boolOrDefault>
 ArgEnableFastISelOption("lfast-isel", cl::Hidden,
   cl::desc("Enable the \"fast\" instruction selector"));
@@ -90,28 +87,34 @@
 }
 
 
-//===---------------------------------------------------------------------===//
-/// MCLDTargetMachine
+//===----------------------------------------------------------------------===//
+// MCLDTargetMachine
 //===----------------------------------------------------------------------===//
 mcld::MCLDTargetMachine::MCLDTargetMachine(llvm::TargetMachine &pTM,
-                                           const mcld::Target& pTarget,
+                                           const llvm::Target& pLLVMTarget,
+                                           const mcld::Target& pMCLDTarget,
                                            const std::string& pTriple)
-  : m_TM(pTM), m_pTarget(&pTarget), m_Triple(pTriple) {
+  : m_TM(pTM),
+    m_pLLVMTarget(&pLLVMTarget),
+    m_pMCLDTarget(&pMCLDTarget),
+    m_Triple(pTriple) {
 }
 
-mcld::MCLDTargetMachine::~MCLDTargetMachine() {
-  m_pTarget = 0;
+mcld::MCLDTargetMachine::~MCLDTargetMachine()
+{
+  m_pLLVMTarget = NULL;
+  m_pMCLDTarget = NULL;
 }
 
 const mcld::Target& mcld::MCLDTargetMachine::getTarget() const
 {
-  return *m_pTarget;
+  return *m_pMCLDTarget;
 }
 
 /// Turn exception handling constructs into something the code generators can
 /// handle.
 static void addPassesToHandleExceptions(llvm::TargetMachine *TM,
-                                        PassManagerBase &PM) {
+                                        llvm::legacy::PassManagerBase &PM) {
   switch (TM->getMCAsmInfo()->getExceptionHandlingType()) {
   case llvm::ExceptionHandling::SjLj:
     // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
@@ -137,9 +140,10 @@
 }
 
 
-static llvm::MCContext *addPassesToGenerateCode(llvm::LLVMTargetMachine *TM,
-                                                PassManagerBase &PM,
-                                                bool DisableVerify)
+static llvm::MCContext *
+addPassesToGenerateCode(llvm::LLVMTargetMachine *TM,
+                        llvm::legacy::PassManagerBase &PM,
+                        bool DisableVerify)
 {
   // Targets may override createPassConfig to provide a target-specific sublass.
   TargetPassConfig *PassConfig = TM->createPassConfig(PM);
@@ -184,7 +188,8 @@
 
 }
 
-bool mcld::MCLDTargetMachine::addPassesToEmitFile(PassManagerBase &pPM,
+bool
+mcld::MCLDTargetMachine::addPassesToEmitFile(llvm::legacy::PassManagerBase &pPM,
                                              mcld::ToolOutputFile& pOutput,
                                              mcld::CodeGenFileType pFileType,
                                              CodeGenOpt::Level pOptLvl,
@@ -222,7 +227,7 @@
     if (getTM().hasMCSaveTempLabels())
       Context->setAllowTemporaryLabels(false);
     if (addAssemblerPasses(pPM,
-                           pOutput.mem_os(),
+                           pOutput.formatted_os(),
                            Context))
       return true;
     break;
@@ -232,7 +237,7 @@
     if (addLinkerPasses(pPM,
                         pConfig,
                         pModule,
-                        pOutput.memory(),
+                        pOutput.fd(),
                         Context))
       return true;
     break;
@@ -242,7 +247,7 @@
     if (addLinkerPasses(pPM,
                         pConfig,
                         pModule,
-                        pOutput.memory(),
+                        pOutput.fd(),
                         Context))
       return true;
     break;
@@ -252,7 +257,7 @@
     if (addLinkerPasses(pPM,
                         pConfig,
                         pModule,
-                        pOutput.memory(),
+                        pOutput.fd(),
                         Context))
       return true;
     break;
@@ -262,7 +267,7 @@
     if (addLinkerPasses(pPM,
                         pConfig,
                         pModule,
-                        pOutput.memory(),
+                        pOutput.fd(),
                         Context))
       return true;
     break;
@@ -271,9 +276,10 @@
   return false;
 }
 
-bool mcld::MCLDTargetMachine::addCompilerPasses(PassManagerBase &pPM,
-                                                llvm::formatted_raw_ostream &pOutput,
-                                                llvm::MCContext *&Context)
+bool
+mcld::MCLDTargetMachine::addCompilerPasses(llvm::legacy::PassManagerBase &pPM,
+                                           llvm::formatted_raw_ostream &pOutput,
+                                           llvm::MCContext *&Context)
 {
   const MCAsmInfo &MAI = *getTM().getMCAsmInfo();
   const MCInstrInfo &MII = *getTM().getInstrInfo();
@@ -281,32 +287,31 @@
   const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
 
   MCInstPrinter *InstPrinter =
-    getTarget().get()->createMCInstPrinter(MAI.getAssemblerDialect(), MAI,
-                                           MII,
-                                           *Context->getRegisterInfo(), STI);
+    m_pLLVMTarget->createMCInstPrinter(MAI.getAssemblerDialect(), MAI,
+                                       MII, *Context->getRegisterInfo(), STI);
 
   MCCodeEmitter* MCE = 0;
   MCAsmBackend *MAB = 0;
   if (ArgShowMCEncoding) {
-    MCE = getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context);
-    MAB = getTarget().get()->createMCAsmBackend(m_Triple,
-                                                getTM().getTargetCPU());
+    MCE = m_pLLVMTarget->createMCCodeEmitter(MII, MRI, STI, *Context);
+    MAB = m_pLLVMTarget->createMCAsmBackend(MRI, m_Triple,
+                                            getTM().getTargetCPU());
   }
 
 
   // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
   OwningPtr<MCStreamer> AsmStreamer(
-    getTarget().get()->createAsmStreamer(*Context, pOutput,
-                                         getVerboseAsm(),
-                                         getTM().hasMCUseLoc(),
-                                         getTM().hasMCUseCFI(),
-                                         getTM().hasMCUseDwarfDirectory(),
-                                         InstPrinter,
-                                         MCE, MAB,
-                                         ArgShowMCInst));
+    m_pLLVMTarget->createAsmStreamer(*Context, pOutput,
+                                     getVerboseAsm(),
+                                     getTM().hasMCUseLoc(),
+                                     getTM().hasMCUseCFI(),
+                                     getTM().hasMCUseDwarfDirectory(),
+                                     InstPrinter,
+                                     MCE, MAB,
+                                     ArgShowMCInst));
 
   llvm::MachineFunctionPass* funcPass =
-    getTarget().get()->createAsmPrinter(getTM(), *AsmStreamer.get());
+    m_pLLVMTarget->createAsmPrinter(getTM(), *AsmStreamer.get());
 
   if (funcPass == 0)
     return true;
@@ -316,35 +321,32 @@
   return false;
 }
 
-bool mcld::MCLDTargetMachine::addAssemblerPasses(PassManagerBase &pPM,
-                                                 llvm::raw_ostream &pOutput,
-                                                 llvm::MCContext *&Context)
+bool
+mcld::MCLDTargetMachine::addAssemblerPasses(llvm::legacy::PassManagerBase &pPM,
+                                            llvm::raw_ostream &pOutput,
+                                            llvm::MCContext *&Context)
 {
   // MCCodeEmitter
   const MCInstrInfo &MII = *getTM().getInstrInfo();
   const MCRegisterInfo &MRI = *getTM().getRegisterInfo();
   const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
   MCCodeEmitter* MCE =
-    getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context);
+    m_pLLVMTarget->createMCCodeEmitter(MII, MRI, STI, *Context);
 
   // MCAsmBackend
   MCAsmBackend* MAB =
-    getTarget().get()->createMCAsmBackend(m_Triple,getTM().getTargetCPU());
+    m_pLLVMTarget->createMCAsmBackend(MRI, m_Triple, getTM().getTargetCPU());
   if (MCE == 0 || MAB == 0)
     return true;
 
   // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
-  OwningPtr<MCStreamer> AsmStreamer(getTarget().get()->createMCObjectStreamer(
-                                                              m_Triple,
-                                                              *Context,
-                                                              *MAB,
-                                                              pOutput,
-                                                              MCE,
-                                                              getTM().hasMCRelaxAll(),
-                                                              getTM().hasMCNoExecStack()));
+  OwningPtr<MCStreamer> AsmStreamer(m_pLLVMTarget->createMCObjectStreamer(
+    m_Triple, *Context, *MAB, pOutput, MCE, getTM().hasMCRelaxAll(),
+    getTM().hasMCNoExecStack()));
+
   AsmStreamer.get()->InitSections();
-  MachineFunctionPass *funcPass = getTarget().get()->createAsmPrinter(getTM(),
-                                                                      *AsmStreamer.get());
+  MachineFunctionPass *funcPass =
+    m_pLLVMTarget->createAsmPrinter(getTM(), *AsmStreamer.get());
   if (funcPass == 0)
     return true;
   // If successful, createAsmPrinter took ownership of AsmStreamer
@@ -353,29 +355,27 @@
   return false;
 }
 
-bool mcld::MCLDTargetMachine::addLinkerPasses(PassManagerBase &pPM,
-                                              LinkerConfig& pConfig,
-                                              mcld::Module& pModule,
-                                              mcld::MemoryArea& pOutput,
-                                              llvm::MCContext *&Context)
+bool
+mcld::MCLDTargetMachine::addLinkerPasses(llvm::legacy::PassManagerBase &pPM,
+                                         LinkerConfig& pConfig,
+                                         mcld::Module& pModule,
+                                         mcld::FileHandle& pFileHandle,
+                                         llvm::MCContext *&Context)
 {
-  if (NULL == pOutput.handler())
-    return true;
-
   // set up output's SOName
   if (pConfig.options().soname().empty()) {
     // if the output is a shared object, and the option -soname was not
     // enable, set soname as the output file name. soname must be UTF-8 string.
-    pModule.setName(pOutput.handler()->path().filename().native());
-  }
-  else {
-    pModule.setName(pConfig.options().soname());
+    pConfig.options().setSOName(pFileHandle.path().filename().native());
   }
 
-  MachineFunctionPass* funcPass = getTarget().createMCLinker(m_Triple,
-                                                             pConfig,
-                                                             pModule,
-                                                             pOutput);
+  // set up output module name
+  pModule.setName(pFileHandle.path().filename().native());
+
+  MachineFunctionPass* funcPass = m_pMCLDTarget->createMCLinker(m_Triple,
+                                                                pConfig,
+                                                                pModule,
+                                                                pFileHandle);
   if (NULL == funcPass)
     return true;
 
diff --git a/lib/CodeGen/MCLinker.cpp b/lib/CodeGen/MCLinker.cpp
index 683cc89..471b0af 100644
--- a/lib/CodeGen/MCLinker.cpp
+++ b/lib/CodeGen/MCLinker.cpp
@@ -14,6 +14,7 @@
 
 #include <mcld/Module.h>
 #include <mcld/LinkerConfig.h>
+#include <mcld/LinkerScript.h>
 #include <mcld/InputTree.h>
 #include <mcld/Linker.h>
 #include <mcld/IRBuilder.h>
@@ -26,7 +27,6 @@
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/FileHandle.h>
 #include <mcld/Support/raw_ostream.h>
-#include <mcld/Support/MemoryArea.h>
 
 #include <llvm/IR/Module.h>
 #include <llvm/Support/CommandLine.h>
@@ -186,15 +186,24 @@
                      cl::aliasopt(ArgEndGroupList));
 
 //===----------------------------------------------------------------------===//
+// --defsym
+//===----------------------------------------------------------------------===//
+static cl::list<std::string>
+ArgDefSymList("defsym",
+              cl::ZeroOrMore,
+              cl::desc("Define a symbol"),
+              cl::value_desc("symbol=expression"));
+
+//===----------------------------------------------------------------------===//
 // MCLinker
 //===----------------------------------------------------------------------===//
 MCLinker::MCLinker(LinkerConfig& pConfig,
                    mcld::Module& pModule,
-                   MemoryArea& pOutput)
+                   FileHandle& pFileHandle)
   : MachineFunctionPass(m_ID),
     m_Config(pConfig),
     m_Module(pModule),
-    m_Output(pOutput),
+    m_FileHandle(pFileHandle),
     m_pBuilder(NULL),
     m_pLinker(NULL) {
 }
@@ -225,7 +234,7 @@
   if (!m_pLinker->link(m_Module, *m_pBuilder))
     return true;
 
-  if (!m_pLinker->emit(m_Output))
+  if (!m_pLinker->emit(m_Module, m_FileHandle.handler()))
     return true;
 
   return false;
@@ -258,10 +267,34 @@
                        ArgBStaticList.size() +
                        ArgStartGroupList.size() +
                        ArgEndGroupList.size() +
+                       ArgDefSymList.size() +
                        1; // bitcode
   std::vector<InputAction*> actions;
   actions.reserve(num_actions);
 
+  // -----  scripts  ----- //
+  /// -T
+  if (!m_Config.options().getScriptList().empty()) {
+    GeneralOptions::const_script_iterator ii, ie = m_Config.options().script_end();
+    for (ii = m_Config.options().script_begin(); ii != ie; ++ii) {
+      actions.push_back(new ScriptAction(0x0,
+                                         *ii,
+                                         ScriptFile::LDScript,
+                                         m_Module.getScript().directories()));
+      actions.push_back(new ContextAction(0x0));
+      actions.push_back(new MemoryAreaAction(0x0, FileHandle::ReadOnly));
+    }
+  }
+
+  /// --defsym
+  cl::list<std::string>::iterator defsym, dsBegin, dsEnd;
+  dsBegin = ArgDefSymList.begin();
+  dsEnd = ArgDefSymList.end();
+  for (defsym = dsBegin; defsym != dsEnd; ++defsym) {
+    unsigned int pos = ArgDefSymList.getPosition(defsym - dsBegin);
+    actions.push_back(new DefSymAction(pos, *defsym));
+  }
+
   // -----  inputs  ----- //
   cl::list<mcld::sys::fs::Path>::iterator input, inBegin, inEnd;
   inBegin = ArgInputObjectFiles.begin();
@@ -277,11 +310,10 @@
   cl::list<std::string>::iterator namespec, nsBegin, nsEnd;
   nsBegin = ArgNameSpecList.begin();
   nsEnd = ArgNameSpecList.end();
-  mcld::Module& module = pBuilder.getModule();
   for (namespec = nsBegin; namespec != nsEnd; ++namespec) {
     unsigned int pos = ArgNameSpecList.getPosition(namespec - nsBegin);
     actions.push_back(new NamespecAction(pos, *namespec,
-                                         module.getScript().directories()));
+                                         m_Module.getScript().directories()));
     actions.push_back(new ContextAction(pos));
     actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
   }
diff --git a/lib/Core/Environment.cpp b/lib/Core/Environment.cpp
index 0aa7536..5755fe7 100644
--- a/lib/Core/Environment.cpp
+++ b/lib/Core/Environment.cpp
@@ -9,8 +9,6 @@
 #include <mcld/Environment.h>
 #include <mcld/Support/TargetSelect.h>
 
-#include <llvm/Support/TargetSelect.h>
-
 void mcld::Initialize()
 {
   static bool is_initialized = false;
@@ -18,7 +16,6 @@
   if (is_initialized)
     return;
 
-  llvm::InitializeAllTargets();
   mcld::InitializeAllTargets();
   mcld::InitializeAllEmulations();
   mcld::InitializeAllDiagnostics();
diff --git a/lib/Core/GeneralOptions.cpp b/lib/Core/GeneralOptions.cpp
index 71dcb95..442ae51 100644
--- a/lib/Core/GeneralOptions.cpp
+++ b/lib/Core/GeneralOptions.cpp
@@ -7,7 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/GeneralOptions.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
+#include <mcld/MC/ZOption.h>
 
 using namespace mcld;
 
@@ -20,14 +21,14 @@
     m_MaxErrorNum(-1),
     m_MaxWarnNum(-1),
     m_ExecStack(Unknown),
+    m_NoUndefined(Unknown),
+    m_MulDefs(Unknown),
     m_CommPageSize(0x0),
     m_MaxPageSize(0x0),
     m_bCombReloc(true),
-    m_bNoUndefined(false),
     m_bInitFirst(false),
     m_bInterPose(false),
     m_bLoadFltr(false),
-    m_bMulDefs(false),
     m_bNoCopyReloc(false),
     m_bNoDefaultLib(false),
     m_bNoDelete(false),
@@ -52,6 +53,9 @@
     m_bFatalWarnings(false),
     m_bNewDTags(false),
     m_bNoStdlib(false),
+    m_bWarnMismatch(true),
+    m_bGCSections(false),
+    m_bGenUnwindInfo(true),
     m_GPSize(8),
     m_StripSymbols(KeepAllSymbols),
     m_HashStyle(SystemV) {
@@ -61,20 +65,6 @@
 {
 }
 
-bool GeneralOptions::hasDefaultLDScript() const
-{
-  return true;
-}
-
-const char* GeneralOptions::defaultLDScript() const
-{
-  return NULL;
-}
-
-void GeneralOptions::setDefaultLDScript(const std::string& pFilename)
-{
-}
-
 void GeneralOptions::setSOName(const std::string& pName)
 {
   size_t pos = pName.find_last_of(sys::fs::separator);
@@ -94,7 +84,7 @@
       m_bCombReloc = false;
       break;
     case ZOption::Defs:
-      m_bNoUndefined = true;
+      m_NoUndefined = YES;
       break;
     case ZOption::ExecStack:
       m_ExecStack = YES;
@@ -112,7 +102,7 @@
       m_bLoadFltr = true;
       break;
     case ZOption::MulDefs:
-      m_bMulDefs = true;
+      m_MulDefs = YES;
       break;
     case ZOption::NoCopyReloc:
       m_bNoCopyReloc = true;
diff --git a/lib/Core/IRBuilder.cpp b/lib/Core/IRBuilder.cpp
index 1b9747e..080a122 100644
--- a/lib/Core/IRBuilder.cpp
+++ b/lib/Core/IRBuilder.cpp
@@ -7,14 +7,17 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/IRBuilder.h>
+#include <mcld/LinkerScript.h>
 #include <mcld/LD/ELFReader.h>
 #include <mcld/Object/ObjectBuilder.h>
 #include <mcld/LD/SectionData.h>
 #include <mcld/LD/EhFrame.h>
 #include <mcld/LD/RelocData.h>
 #include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/ELF.h>
 #include <mcld/Fragment/FragmentRef.h>
+#include <llvm/ADT/StringRef.h>
 
 using namespace mcld;
 
@@ -66,6 +69,7 @@
   case llvm::ELF::SHT_STRTAB:
   case llvm::ELF::SHT_HASH:
   case llvm::ELF::SHT_DYNAMIC:
+  case llvm::ELF::SHT_SYMTAB_SHNDX:
     return LDFileFormat::NamePool;
   case llvm::ELF::SHT_RELA:
   case llvm::ELF::SHT_REL:
@@ -92,22 +96,6 @@
   return LDFileFormat::MetaData;
 }
 
-bool ShouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig)
-{
-  // 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 != pConfig.codeGenType() &&
-      (pInfo.visibility() == ResolveInfo::Hidden ||
-         pInfo.visibility() == ResolveInfo::Internal) &&
-      (pInfo.isGlobal() || pInfo.isWeak()) &&
-      (pInfo.isDefine() || pInfo.isCommon()))
-    return true;
-  return false;
-}
-
 //===----------------------------------------------------------------------===//
 // IRBuilder
 //===----------------------------------------------------------------------===//
@@ -197,29 +185,6 @@
 }
 
 /// ReadInput - To read an input file and append it to the input tree.
-Input* IRBuilder::ReadInput(raw_mem_ostream& pMemOStream)
-{
-  Input* input = NULL;
-  if (pMemOStream.getMemoryArea().hasHandler()) {
-    m_InputBuilder.createNode<InputTree::Positional>(
-                               "memory ostream",
-                               pMemOStream.getMemoryArea().handler()->path());
-
-    input = *m_InputBuilder.getCurrentNode();
-    m_InputBuilder.setContext(*input);
-    input->setMemArea(&pMemOStream.getMemoryArea());
-  }
-  else {
-    m_InputBuilder.createNode<InputTree::Positional>("memory ostream", "NAN");
-    input = *m_InputBuilder.getCurrentNode();
-    m_InputBuilder.setContext(*input, false);
-    input->setMemArea(&pMemOStream.getMemoryArea());
-  }
-
-  return input;
-}
-
-/// ReadInput - To read an input file and append it to the input tree.
 Input* IRBuilder::ReadInput(FileHandle& pFileHandle)
 {
   m_InputBuilder.createNode<InputTree::Positional>("file handler",
@@ -377,12 +342,8 @@
   if (0 == pLength)
     return new FillFragment(0x0, 0, 0);
 
-  MemoryRegion* region = pInput.memArea()->request(pOffset, pLength);
-
-  if (NULL == region)
-    return new FillFragment(0x0, 0, 0);
-
-  return new RegionFragment(*region);
+  llvm::StringRef region = pInput.memArea()->request(pOffset, pLength);
+  return new RegionFragment(region);
 }
 
 /// CreateRegion - To create a region fragment wrapping the given memory
@@ -391,11 +352,8 @@
   if (0 == pLength)
     return new FillFragment(0x0, 0, 0);
 
-  MemoryRegion* region = MemoryRegion::Create(pMemory, pLength);
-  if (NULL == region)
-    return new FillFragment(0x0, 0, 0);
-
-  return new RegionFragment(*region);
+  llvm::StringRef region(reinterpret_cast<const char*>(pMemory), pLength);
+  return new RegionFragment(region);
 }
 
 /// AppendFragment - To append pFrag to the given SectionData pSD
@@ -527,7 +485,7 @@
   else {
     // if the symbol is not local, insert and resolve it immediately
     m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
-                                        pSize, pVisibility,
+                                        pSize, pValue, pVisibility,
                                         &old_info, resolved_result);
   }
 
@@ -566,36 +524,6 @@
     output_sym->setFragmentRef(pFragmentRef);
     output_sym->setValue(pValue);
   }
-
-  // Step 4. Adjust the position of output LDSymbol.
-  // After symbol resolution, visibility is changed to the most restrict one.
-  // we need to arrange its position in the output symbol. We arrange the
-  // positions by sorting symbols in SymbolCategory.
-  if (pType != ResolveInfo::Section) {
-    if (!has_output_sym) {
-      // We merge sections when reading them. So we do not need to output symbols
-      // with section type
-
-      // 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))
-        m_Module.getSymbolTable().forceLocal(*output_sym);
-      else {
-        // the symbol should not be forcefully local.
-        m_Module.getSymbolTable().add(*output_sym);
-      }
-    }
-    else if (resolved_result.overriden) {
-      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
-        m_Module.getSymbolTable().arrange(*output_sym, old_info);
-      }
-    }
-  }
-
   return input_sym;
 }
 
@@ -628,7 +556,7 @@
   // resolved_result is a triple <resolved_info, existent, override>
   Resolver::Result resolved_result;
   m_Module.getNamePool().insertSymbol(pName, true, pType, pDesc,
-                                      pBinding, pSize, pVisibility,
+                                      pBinding, pSize, pValue, pVisibility,
                                       NULL, resolved_result);
 
   // the return ResolveInfo should not NULL
@@ -642,25 +570,13 @@
   input_sym->setFragmentRef(FragmentRef::Null());
   input_sym->setValue(pValue);
 
-  LDSymbol* output_sym = NULL;
+  // this symbol is seen in a dynamic object, set the InDyn flag
+  resolved_result.info->setInDyn();
+
   if (!resolved_result.existent) {
     // we get a new symbol, leave it as NULL
     resolved_result.info->setSymPtr(NULL);
   }
-  else {
-    // we saw the symbol before, but the output_sym still may be NULL.
-    output_sym = resolved_result.info->outSymbol();
-  }
-
-  if (output_sym != NULL) {
-    // 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)) {
-      m_Module.getSymbolTable().forceLocal(*output_sym);
-    }
-  }
-
   return input_sym;
 }
 
@@ -673,20 +589,11 @@
                                      uint32_t pOffset,
                                      Relocation::Address pAddend)
 {
-  // FIXME: we should dicard sections and symbols first instead
-  // if the symbol is in the discarded input section, then we also need to
-  // discard this relocation.
-  ResolveInfo* resolve_info = pSym.resolveInfo();
-  if (!pSym.hasFragRef() &&
-      ResolveInfo::Section == resolve_info->type() &&
-      ResolveInfo::Undefined == resolve_info->desc())
-    return NULL;
-
   FragmentRef* frag_ref = FragmentRef::Create(*pSection.getLink(), pOffset);
 
   Relocation* relocation = Relocation::Create(pType, *frag_ref, pAddend);
 
-  relocation->setSymInfo(resolve_info);
+  relocation->setSymInfo(pSym.resolveInfo());
   pSection.getRelocData()->append(*relocation);
 
   return relocation;
@@ -711,7 +618,7 @@
     // create a ResolveInfo
     Resolver::Result result;
     m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc,
-                                        pBinding, pSize, pVisibility,
+                                        pBinding, pSize, pValue, pVisibility,
                                         NULL, result);
     assert(!result.existent);
 
@@ -719,7 +626,7 @@
     output_sym = LDSymbol::Create(*result.info);
     result.info->setSymPtr(output_sym);
 
-    if (ShouldForceLocal(*result.info, m_Config))
+    if (result.info->shouldForceLocal(m_Config))
       m_Module.getSymbolTable().forceLocal(*output_sym);
     else
       m_Module.getSymbolTable().add(*output_sym);
@@ -822,7 +729,7 @@
   Resolver::Result result;
   ResolveInfo old_info;
   m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
-                                      pSize, pVisibility,
+                                      pSize, pValue, pVisibility,
                                       &old_info, result);
 
   LDSymbol* output_sym = result.info->outSymbol();
@@ -840,7 +747,7 @@
 
   // After symbol resolution, the visibility is changed to the most restrict.
   // arrange the output position
-  if (ShouldForceLocal(*result.info, m_Config))
+  if (result.info->shouldForceLocal(m_Config))
     m_Module.getSymbolTable().forceLocal(*output_sym);
   else if (has_output_sym)
     m_Module.getSymbolTable().arrange(*output_sym, old_info);
diff --git a/lib/Core/InputTree.cpp b/lib/Core/InputTree.cpp
index 15f6f5e..5df91d8 100644
--- a/lib/Core/InputTree.cpp
+++ b/lib/Core/InputTree.cpp
@@ -24,7 +24,7 @@
     return *this;
 
   if (!pTree.empty()) {
-    pMover.connect(pRoot, iterator(pTree.m_Root.node.right));
+    pMover.connect(pRoot, pTree.m_Root.node.right);
     BinaryTreeBase<Input>::m_Root.summon(
         pTree.BinaryTreeBase<Input>::m_Root);
     BinaryTreeBase<Input>::m_Root.delegate(pTree.m_Root);
@@ -37,7 +37,7 @@
                                  const InputTree::Mover& pMover)
 {
   NodeBase* node = createNode();
-  pMover.connect(pRoot, iterator(node));
+  pMover.connect(pRoot, node);
   return *this;
 }
 
@@ -47,7 +47,7 @@
 {
   BinaryTree<Input>::node_type* node = createNode();
   node->data = &pInput;
-  pMover.connect(pRoot, iterator(node));
+  pMover.connect(pRoot, node);
   return *this;
 }
 
diff --git a/lib/Core/Linker.cpp b/lib/Core/Linker.cpp
index 1361402..464f039 100644
--- a/lib/Core/Linker.cpp
+++ b/lib/Core/Linker.cpp
@@ -14,7 +14,7 @@
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/Support/FileHandle.h>
-#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/FileOutputBuffer.h>
 #include <mcld/Support/raw_ostream.h>
 
 #include <mcld/Object/ObjectLinker.h>
@@ -24,9 +24,12 @@
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/SectionData.h>
 #include <mcld/LD/RelocData.h>
+#include <mcld/LD/ObjectWriter.h>
 #include <mcld/Fragment/Relocation.h>
 #include <mcld/Fragment/FragmentRef.h>
 
+#include <llvm/ADT/OwningPtr.h>
+
 #include <cassert>
 
 using namespace mcld;
@@ -67,7 +70,7 @@
   if (!normalize(pModule, pBuilder))
     return false;
 
-  if (!resolve())
+  if (!resolve(pModule))
     return false;
 
   return layout();
@@ -82,10 +85,8 @@
 
   m_pObjLinker = new ObjectLinker(*m_pConfig, *m_pBackend);
 
-  m_pObjLinker->setup(pModule, pBuilder);
-
-  // 2. - initialize FragmentLinker
-  if (!m_pObjLinker->initFragmentLinker())
+  // 2. - initialize ObjectLinker
+  if (!m_pObjLinker->initialize(pModule, pBuilder))
     return false;
 
   // 3. - initialize output's standard sections
@@ -159,7 +160,7 @@
   return true;
 }
 
-bool Linker::resolve()
+bool Linker::resolve(Module& pModule)
 {
   assert(NULL != m_pConfig);
   assert(m_pObjLinker != NULL);
@@ -172,7 +173,11 @@
   //   To collect all edges in the reference graph.
   m_pObjLinker->readRelocations();
 
-  // 7. - merge all sections
+
+  // 7. - data stripping optimizations
+  m_pObjLinker->dataStrippingOpt();
+
+  // 8. - merge all sections
   //   Push sections into Module's SectionTable.
   //   Merge sections that have the same name.
   //   Maintain them as fragments in the section.
@@ -181,10 +186,16 @@
   if (!m_pObjLinker->mergeSections())
     return false;
 
-  // 8. - allocateCommonSymbols
+  // 9.a - add symbols to output
+  //  After all input symbols have been resolved, add them to output symbol
+  //  table at once
+  m_pObjLinker->addSymbolsToOutput(pModule);
+
+  // 9.b - allocateCommonSymbols
   //   Allocate fragments for common symbols to the corresponding sections.
   if (!m_pObjLinker->allocateCommonSymbols())
     return false;
+
   return true;
 }
 
@@ -192,38 +203,38 @@
 {
   assert(NULL != m_pConfig && NULL != m_pObjLinker);
 
-  // 9. - add standard symbols, target-dependent symbols and script symbols
+  // 10. - add standard symbols, target-dependent symbols and script symbols
   // m_pObjLinker->addUndefSymbols();
   if (!m_pObjLinker->addStandardSymbols() ||
       !m_pObjLinker->addTargetSymbols() ||
       !m_pObjLinker->addScriptSymbols())
     return false;
 
-  // 10. - scan all relocation entries by output symbols.
+  // 11. - 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();
 
-  // 11.a - init relaxation stuff.
+  // 12.a - init relaxation stuff.
   m_pObjLinker->initStubs();
 
-  // 11.b - pre-layout
+  // 12.b - pre-layout
   m_pObjLinker->prelayout();
 
-  // 11.c - linear layout
+  // 12.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();
 
-  // 11.d - post-layout (create segment, instruction relaxing)
+  // 12.d - post-layout (create segment, instruction relaxing)
   m_pObjLinker->postlayout();
 
-  // 12. - finalize symbol value
+  // 13. - finalize symbol value
   m_pObjLinker->finalizeSymbolValue();
 
-  // 13. - apply relocations
+  // 14. - apply relocations
   m_pObjLinker->relocation();
 
   if (!Diagnose())
@@ -231,12 +242,12 @@
   return true;
 }
 
-bool Linker::emit(MemoryArea& pOutput)
+bool Linker::emit(FileOutputBuffer& pOutput)
 {
-  // 13. - write out output
+  // 15. - write out output
   m_pObjLinker->emitOutput(pOutput);
 
-  // 14. - post processing
+  // 16. - post processing
   m_pObjLinker->postProcessing(pOutput);
 
   if (!Diagnose())
@@ -245,10 +256,23 @@
   return true;
 }
 
-bool Linker::emit(const std::string& pPath)
+bool Linker::emit(const Module& pModule, const std::string& pPath)
 {
   FileHandle file;
-  FileHandle::Permission perm = FileHandle::Permission(0x755);
+  FileHandle::Permission perm;
+  switch (m_pConfig->codeGenType()) {
+    case mcld::LinkerConfig::Unknown:
+    case mcld::LinkerConfig::Object:
+      perm = mcld::FileHandle::Permission(0x644);
+      break;
+    case mcld::LinkerConfig::DynObj:
+    case mcld::LinkerConfig::Exec:
+    case mcld::LinkerConfig::Binary:
+      perm = mcld::FileHandle::Permission(0x755);
+      break;
+    default: assert(0 && "Unknown file type");
+  }
+
   if (!file.open(pPath,
             FileHandle::ReadWrite | FileHandle::Truncate | FileHandle::Create,
             perm)) {
@@ -256,25 +280,28 @@
     return false;
   }
 
-  MemoryArea* output = new MemoryArea(file);
+  llvm::OwningPtr<FileOutputBuffer> output;
+  FileOutputBuffer::create(file,
+                           m_pObjLinker->getWriter()->getOutputSize(pModule),
+                           output);
 
-  bool result = emit(*output);
-
-  delete output;
+  bool result = emit(*output.get());
   file.close();
   return result;
 }
 
-bool Linker::emit(int pFileDescriptor)
+bool Linker::emit(const Module& pModule, int pFileDescriptor)
 {
   FileHandle file;
   file.delegate(pFileDescriptor);
-  MemoryArea* output = new MemoryArea(file);
 
-  bool result = emit(*output);
+  llvm::OwningPtr<FileOutputBuffer> output;
+  FileOutputBuffer::create(file,
+                           m_pObjLinker->getWriter()->getOutputSize(pModule),
+                           output);
 
-  delete output;
-  file.close();
+  bool result = emit(*output.get());
+
   return result;
 }
 
@@ -308,9 +335,14 @@
   assert(NULL != m_pConfig);
 
   std::string error;
-  m_pTarget = mcld::TargetRegistry::lookupTarget(m_pConfig->targets().triple().str(), error);
+  llvm::Triple triple(m_pConfig->targets().triple());
+
+  m_pTarget = mcld::TargetRegistry::lookupTarget(m_pConfig->targets().getArch(),
+                                                 triple, error);
+  m_pConfig->targets().setTriple(triple);
+
   if (NULL == m_pTarget) {
-    fatal(diag::fatal_cannot_init_target) << m_pConfig->targets().triple().str() << error;
+    fatal(diag::fatal_cannot_init_target) << triple.str() << error;
     return false;
   }
   return true;
diff --git a/lib/Core/LinkerScript.cpp b/lib/Core/LinkerScript.cpp
index 4bee579..2e891e2 100644
--- a/lib/Core/LinkerScript.cpp
+++ b/lib/Core/LinkerScript.cpp
@@ -36,3 +36,32 @@
   return !sysroot().empty();
 }
 
+const std::string& LinkerScript::entry() const
+{
+  return m_Entry;
+}
+
+void LinkerScript::setEntry(const std::string& pEntry)
+{
+  m_Entry = pEntry;
+}
+
+bool LinkerScript::hasEntry() const
+{
+  return !m_Entry.empty();
+}
+
+const std::string& LinkerScript::outputFile() const
+{
+  return m_OutputFile;
+}
+
+void LinkerScript::setOutputFile(const std::string& pOutputFile)
+{
+  m_OutputFile = pOutputFile;
+}
+
+bool LinkerScript::hasOutputFile() const
+{
+  return !m_OutputFile.empty();
+}
diff --git a/lib/Core/TargetOptions.cpp b/lib/Core/TargetOptions.cpp
index 4f2cea2..710899c 100644
--- a/lib/Core/TargetOptions.cpp
+++ b/lib/Core/TargetOptions.cpp
@@ -38,6 +38,11 @@
   m_Triple.setTriple(pTriple);
 }
 
+void TargetOptions::setArch(const std::string& pArchName)
+{
+  m_ArchName = pArchName;
+}
+
 void TargetOptions::setTargetCPU(const std::string& pCPU)
 {
   m_TargetCPU = pCPU;
diff --git a/lib/Fragment/Android.mk b/lib/Fragment/Android.mk
index 6e875a8..743232f 100644
--- a/lib/Fragment/Android.mk
+++ b/lib/Fragment/Android.mk
@@ -2,10 +2,8 @@
 
 mcld_fragment_SRC_FILES := \
   AlignFragment.cpp \
-  FGNode.cpp \
   FillFragment.cpp \
   Fragment.cpp \
-  FragmentLinker.cpp \
   FragmentRef.cpp \
   NullFragment.cpp \
   RegionFragment.cpp \
diff --git a/lib/Fragment/FGNode.cpp b/lib/Fragment/FGNode.cpp
deleted file mode 100644
index 92706ba..0000000
--- a/lib/Fragment/FGNode.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- 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
deleted file mode 100644
index 3140447..0000000
--- a/lib/Fragment/FragmentGraph.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-//===- 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
deleted file mode 100644
index 5a4b53f..0000000
--- a/lib/Fragment/FragmentLinker.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-//===- FragmentLinker.cpp -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the FragmentLinker class
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Fragment/FragmentLinker.h>
-
-#include <llvm/Support/Host.h>
-#include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/Casting.h>
-
-#include <mcld/LinkerConfig.h>
-#include <mcld/Module.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/BranchIslandFactory.h>
-#include <mcld/LD/Resolver.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/RelocationFactory.h>
-#include <mcld/LD/RelocData.h>
-#include <mcld/LD/Relocator.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Fragment/Relocation.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// FragmentLinker
-//===----------------------------------------------------------------------===//
-/// Constructor
-FragmentLinker::FragmentLinker(const LinkerConfig& pConfig,
-                               Module& pModule,
-                               TargetLDBackend& pBackend)
-
-  : m_Config(pConfig),
-    m_Module(pModule),
-    m_Backend(pBackend) {
-}
-
-/// Destructor
-FragmentLinker::~FragmentLinker()
-{
-}
-
-bool FragmentLinker::finalizeSymbols()
-{
-  Module::sym_iterator symbol, symEnd = m_Module.sym_end();
-  for (symbol = m_Module.sym_begin(); symbol != symEnd; ++symbol) {
-
-    if ((*symbol)->resolveInfo()->isAbsolute() ||
-        (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
-      // absolute symbols or symbols with function type should have
-      // zero value
-      (*symbol)->setValue(0x0);
-      continue;
-    }
-
-    if ((*symbol)->resolveInfo()->type() == ResolveInfo::ThreadLocal) {
-      m_Backend.finalizeTLSSymbol(**symbol);
-      continue;
-    }
-
-    if ((*symbol)->hasFragRef()) {
-      // set the virtual address of the symbol. If the output file is
-      // relocatable object file, the section's virtual address becomes zero.
-      // And the symbol's value become section relative offset.
-      uint64_t value = (*symbol)->fragRef()->getOutputOffset();
-      assert(NULL != (*symbol)->fragRef()->frag());
-      uint64_t addr = (*symbol)->fragRef()->frag()->getParent()->getSection().addr();
-      (*symbol)->setValue(value + addr);
-      continue;
-    }
-  }
-
-  return true;
-}
-
-//===----------------------------------------------------------------------===//
-// Relocation Operations
-//===----------------------------------------------------------------------===//
-bool FragmentLinker::applyRelocations()
-{
-  // when producing relocatables, no need to apply relocation
-  if (LinkerConfig::Object == m_Config.codeGenType())
-    return true;
-
-  // apply all relocations of all inputs
-  Module::obj_iterator input, inEnd = m_Module.obj_end();
-  for (input = m_Module.obj_begin(); input != inEnd; ++input) {
-    m_Backend.getRelocator()->initializeApply(**input);
-    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
-    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
-      // bypass the reloc section if
-      // 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, rEnd = (*rs)->getRelocData()->end();
-      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
-        Relocation* relocation = llvm::cast<Relocation>(reloc);
-        relocation->apply(*m_Backend.getRelocator());
-      } // for all relocations
-    } // for all relocation section
-    m_Backend.getRelocator()->finalizeApply(**input);
-  } // for all inputs
-
-  // apply relocations created by relaxation
-  BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory();
-  BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
-  for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
-    BranchIsland& island = *facIter;
-    BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
-    for (iter = island.reloc_begin(); iter != iterEnd; ++iter)
-      (*iter)->apply(*m_Backend.getRelocator());
-  }
-  return true;
-}
-
-
-void FragmentLinker::syncRelocationResult(MemoryArea& pOutput)
-{
-  if (LinkerConfig::Object != m_Config.codeGenType())
-    normalSyncRelocationResult(pOutput);
-  else
-    partialSyncRelocationResult(pOutput);
-  return;
-}
-
-void FragmentLinker::normalSyncRelocationResult(MemoryArea& pOutput)
-{
-  MemoryRegion* region = pOutput.request(0, pOutput.handler()->size());
-
-  uint8_t* data = region->getBuffer();
-
-  // sync all relocations of all inputs
-  Module::obj_iterator input, inEnd = m_Module.obj_end();
-  for (input = m_Module.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
-      // 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, rEnd = (*rs)->getRelocData()->end();
-      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
-        Relocation* relocation = llvm::cast<Relocation>(reloc);
-
-        // bypass the relocation with NONE type. This is to avoid overwrite the
-        // target result by NONE type relocation if there is a place which has
-        // two relocations to apply to, and one of it is NONE type. The result
-        // we want is the value of the other relocation result. For example,
-        // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
-        // the same place
-        if (0x0 == relocation->type())
-          continue;
-        writeRelocationResult(*relocation, data);
-      } // for all relocations
-    } // for all relocation section
-  } // for all inputs
-
-  // sync relocations created by relaxation
-  BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory();
-  BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
-  for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
-    BranchIsland& island = *facIter;
-    BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
-    for (iter = island.reloc_begin(); iter != iterEnd; ++iter) {
-      Relocation* reloc = *iter;
-      writeRelocationResult(*reloc, data);
-    }
-  }
-
-  pOutput.clear();
-}
-
-void FragmentLinker::partialSyncRelocationResult(MemoryArea& pOutput)
-{
-  MemoryRegion* region = pOutput.request(0, pOutput.handler()->size());
-
-  uint8_t* data = region->getBuffer();
-
-  // traverse outputs' LDSection to get RelocData
-  Module::iterator sectIter, sectEnd = m_Module.end();
-  for (sectIter = m_Module.begin(); sectIter != sectEnd; ++sectIter) {
-    if (LDFileFormat::Relocation != (*sectIter)->kind())
-      continue;
-
-    RelocData* reloc_data = (*sectIter)->getRelocData();
-    RelocData::iterator relocIter, relocEnd = reloc_data->end();
-    for (relocIter = reloc_data->begin(); relocIter != relocEnd; ++relocIter) {
-      Relocation* reloc = llvm::cast<Relocation>(relocIter);
-
-      // bypass the relocation with NONE type. This is to avoid overwrite the
-      // target result by NONE type relocation if there is a place which has
-      // two relocations to apply to, and one of it is NONE type. The result
-      // we want is the value of the other relocation result. For example,
-      // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
-      // the same place
-      if (0x0 == reloc->type())
-        continue;
-      writeRelocationResult(*reloc, data);
-    }
-  }
-
-  pOutput.clear();
-}
-
-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();
-
-  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(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);
-         break;
-
-       case 64u:
-         tmp_data = mcld::bswap64(pReloc.target());
-         std::memcpy(target_addr, &tmp_data, 8);
-         break;
-
-       default:
-         break;
-    }
-  }
-  else
-    std::memcpy(target_addr, &pReloc.target(),
-                                      pReloc.size(*m_Backend.getRelocator())/8);
-}
-
diff --git a/lib/Fragment/FragmentRef.cpp b/lib/Fragment/FragmentRef.cpp
index 9383e87..a22beca 100644
--- a/lib/Fragment/FragmentRef.cpp
+++ b/lib/Fragment/FragmentRef.cpp
@@ -8,21 +8,20 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/Fragment/FragmentRef.h>
 
-#include <cstring>
-#include <cassert>
-
-#include <llvm/Support/Casting.h>
-#include <llvm/Support/ManagedStatic.h>
-
 #include <mcld/Fragment/Fragment.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/SectionData.h>
 #include <mcld/LD/EhFrame.h>
 #include <mcld/Support/GCFactory.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Fragment/RegionFragment.h>
 #include <mcld/Fragment/Stub.h>
 
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/Casting.h>
+#include <llvm/Support/ManagedStatic.h>
+
+#include <cassert>
+
 using namespace mcld;
 
 typedef GCFactory<FragmentRef, MCLD_SECTIONS_PER_INPUT> FragRefFactory;
@@ -61,13 +60,18 @@
       break;
     frag = frag->getNextNode();
   }
-
+  if ((frag != NULL) && (frag->size() != 0)) {
+    if (offset == 0)
+      frag = frag->getNextNode();
+    else
+      offset += frag->size();
+  }
 
   if (NULL == frag)
     return Null();
 
   FragmentRef* result = g_FragRefFactory->allocate();
-  new (result) FragmentRef(*frag, offset + frag->size());
+  new (result) FragmentRef(*frag, offset);
 
   return result;
 }
@@ -132,7 +136,7 @@
       if (total_length < (total_offset+pNBytes))
         pNBytes = total_length - total_offset;
 
-      std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes);
+      std::memcpy(pDest, region_frag->getRegion().begin() + total_offset, pNBytes);
       return;
     }
     case Fragment::Stub: {
@@ -150,40 +154,6 @@
   }
 }
 
-FragmentRef::Address FragmentRef::deref()
-{
-  if (NULL == m_pFragment)
-    return NULL;
-  Address base = NULL;
-  switch(m_pFragment->getKind()) {
-    case Fragment::Region:
-      base = static_cast<RegionFragment*>(m_pFragment)->getRegion().getBuffer();
-      break;
-    case Fragment::Alignment:
-    case Fragment::Fillment:
-    default:
-      return NULL;
-  }
-  return base + m_Offset;
-}
-
-FragmentRef::ConstAddress FragmentRef::deref() const
-{
-  if (NULL == m_pFragment)
-    return NULL;
-  ConstAddress base = NULL;
-  switch(m_pFragment->getKind()) {
-    case Fragment::Region:
-      base = static_cast<const RegionFragment*>(m_pFragment)->getRegion().getBuffer();
-      break;
-    case Fragment::Alignment:
-    case Fragment::Fillment:
-    default:
-      return NULL;
-  }
-  return base + m_Offset;
-}
-
 FragmentRef::Offset FragmentRef::getOutputOffset() const
 {
   Offset result = 0;
@@ -191,4 +161,3 @@
     result = m_pFragment->getOffset();
   return (result + m_Offset);
 }
-
diff --git a/lib/Fragment/RegionFragment.cpp b/lib/Fragment/RegionFragment.cpp
index 363a0f2..c8971b8 100644
--- a/lib/Fragment/RegionFragment.cpp
+++ b/lib/Fragment/RegionFragment.cpp
@@ -7,14 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/Fragment/RegionFragment.h>
-#include <mcld/Support/MemoryRegion.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
 // RegionFragment
 //===----------------------------------------------------------------------===//
-RegionFragment::RegionFragment(MemoryRegion& pRegion, SectionData* pSD)
+RegionFragment::RegionFragment(llvm::StringRef pRegion, SectionData* pSD)
   : Fragment(Fragment::Region, pSD), m_Region(pRegion) {
 }
 
diff --git a/lib/Fragment/Relocation.cpp b/lib/Fragment/Relocation.cpp
index fd042ea..1537c0c 100644
--- a/lib/Fragment/Relocation.cpp
+++ b/lib/Fragment/Relocation.cpp
@@ -91,8 +91,10 @@
 Relocation::Address Relocation::symValue() const
 {
   if (m_pSymInfo->type() == ResolveInfo::Section &&
-     m_pSymInfo->outSymbol()->hasFragRef()) {
-    return m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection().addr();
+      m_pSymInfo->outSymbol()->hasFragRef()) {
+    const FragmentRef* fragRef = m_pSymInfo->outSymbol()->fragRef();
+    return fragRef->frag()->getParent()->getSection().addr() +
+           fragRef->getOutputOffset();
   }
   return m_pSymInfo->outSymbol()->value();
 }
@@ -156,4 +158,3 @@
     m_Addend += offset;
   }
 }
-
diff --git a/lib/LD/Archive.cpp b/lib/LD/Archive.cpp
index ee2edea..864cedb 100644
--- a/lib/LD/Archive.cpp
+++ b/lib/LD/Archive.cpp
@@ -8,11 +8,8 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/Archive.h>
 #include <mcld/MC/InputBuilder.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/AttributeSet.h>
-#include <mcld/MC/ContextFactory.h>
+#include <mcld/MC/Input.h>
 #include <llvm/ADT/StringRef.h>
-#include <mcld/Support/MemoryAreaFactory.h>
 #include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
@@ -23,6 +20,7 @@
 const char   Archive::THIN_MAGIC[]       = "!<thin>\n";
 const size_t Archive::MAGIC_LEN          = sizeof(Archive::MAGIC) - 1;
 const char   Archive::SVR4_SYMTAB_NAME[] = "/               ";
+const char   Archive::IRIX6_SYMTAB_NAME[]= "/SYM64/         ";
 const char   Archive::STRTAB_NAME[]      = "//              ";
 const char   Archive::PAD[]              = "\n";
 const char   Archive::MEMBER_MAGIC[]     = "`\n";
diff --git a/lib/LD/BSDArchiveReader.cpp b/lib/LD/BSDArchiveReader.cpp
index bd59844..57d3a52 100644
--- a/lib/LD/BSDArchiveReader.cpp
+++ b/lib/LD/BSDArchiveReader.cpp
@@ -6,7 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/LD/BSDArchiveReader.h>
 #include <mcld/LD/Archive.h>
 
@@ -20,14 +20,16 @@
 {
 }
 
-bool BSDArchiveReader::readArchive(Archive& pArchive)
+bool BSDArchiveReader::readArchive(const LinkerConfig& pConfig,
+                                   Archive& pArchive)
 {
   // TODO
   return true;
 }
 
-bool BSDArchiveReader::isMyFormat(Input& pInput) const
+bool BSDArchiveReader::isMyFormat(Input& pInput, bool &pContinue) const
 {
+  pContinue = true;
   // TODO
   return false;
 }
diff --git a/lib/LD/BinaryReader.cpp b/lib/LD/BinaryReader.cpp
new file mode 100644
index 0000000..f5c439f
--- /dev/null
+++ b/lib/LD/BinaryReader.cpp
@@ -0,0 +1,19 @@
+//===- BinaryReader.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/BinaryReader.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// BinaryReader
+//===----------------------------------------------------------------------===//
+BinaryReader::~BinaryReader()
+{
+}
+
diff --git a/lib/LD/BranchIslandFactory.cpp b/lib/LD/BranchIslandFactory.cpp
index 6a61481..116f075 100644
--- a/lib/LD/BranchIslandFactory.cpp
+++ b/lib/LD/BranchIslandFactory.cpp
@@ -8,6 +8,9 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/BranchIslandFactory.h>
 #include <mcld/Fragment/Fragment.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Module.h>
 
 using namespace mcld;
 
@@ -31,43 +34,40 @@
 {
 }
 
+/// group - group fragments and create islands when needed
+/// @param pSectionData - the SectionData holds fragments need to be grouped
+void BranchIslandFactory::group(Module& pModule)
+{
+  /* Currently only support relaxing .text section! */
+  LDSection* text = pModule.getSection(".text");
+  if (text != NULL && text->hasSectionData()) {
+    SectionData& sd = *text->getSectionData();
+    uint64_t group_end = m_MaxBranchRange - m_MaxIslandSize;
+    for (SectionData::iterator it = sd.begin(), ie = sd.end(); it != ie; ++it) {
+      if ((*it).getOffset() + (*it).size() > group_end) {
+        Fragment* frag = (*it).getPrevNode();
+        while (frag != NULL && frag->getKind() == Fragment::Alignment) {
+          frag = frag->getPrevNode();
+        }
+        if (frag != NULL) {
+          produce(*frag);
+          group_end = (*it).getOffset() + m_MaxBranchRange - m_MaxIslandSize;
+        }
+      }
+    }
+    if (find(sd.back()) == NULL)
+      produce(sd.back());
+  }
+}
+
 /// produce - produce a island for the given fragment
 /// @param pFragment - the fragment needs a branch island
 BranchIsland* BranchIslandFactory::produce(Fragment& pFragment)
 {
-  assert(NULL == find(pFragment));
-  uint64_t island_offset = pFragment.getOffset() + m_MaxBranchRange -
-                           (pFragment.getOffset() % m_MaxBranchRange);
-
-  // find out the last fragment whose offset is smaller than the calculated
-  // offset of the island
-  Fragment* frag = &pFragment;
-  while (NULL != frag->getNextNode()) {
-    if (frag->getNextNode()->getOffset() > island_offset)
-      break;
-    frag = frag->getNextNode();
-  }
-
-  // fall back one step if needed
-  if (NULL != frag &&
-      (frag->getOffset() + frag->size()) > island_offset)
-    frag = frag->getPrevNode();
-
-  // check not to break the alignment constraint in the target section
-  // (i.e., do not insert the island after a Alignment fragment)
-  while (NULL != frag &&
-         Fragment::Alignment == frag->getKind()) {
-    frag = frag->getPrevNode();
-  }
-
-  // can not find an entry fragment to bridge the island
-  if (NULL == frag)
-    return NULL;
-
   BranchIsland *island = allocate();
-  new (island) BranchIsland(*frag,           // entry fragment to the island
+  new (island) BranchIsland(pFragment,       // entry fragment to the island
                             m_MaxIslandSize, // the max size of the island
-                            size() - 1u);     // index in the island factory
+                            size() - 1u);    // index in the island factory
   return island;
 }
 
@@ -76,7 +76,7 @@
 BranchIsland* BranchIslandFactory::find(const Fragment& pFragment)
 {
   // Currently we always find the island in a forward direction.
-  // TODO: If we can search backward, then we may reduce the number of islands.
+  // TODO: If we can search backward, then we may reduce the number of stubs.
   for (iterator it = begin(), ie = end(); it != ie; ++it) {
     if ((pFragment.getOffset() < (*it).offset()) &&
         ((pFragment.getOffset() + m_MaxBranchRange) >= (*it).offset()))
diff --git a/lib/LD/DiagnosticInfos.cpp b/lib/LD/DiagnosticInfos.cpp
index 3219d4a..943b046 100644
--- a/lib/LD/DiagnosticInfos.cpp
+++ b/lib/LD/DiagnosticInfos.cpp
@@ -42,12 +42,14 @@
 static const DiagStaticInfo DiagCommonInfo[] = {
 #define DIAG(ENUM, CLASS, ADDRDESC, LOCDESC) \
   { diag::ENUM, CLASS, STR_SIZE(ADDRDESC, uint16_t), ADDRDESC },
+#include "mcld/LD/DiagAttribute.inc"
 #include "mcld/LD/DiagCommonKinds.inc"
 #include "mcld/LD/DiagReaders.inc"
 #include "mcld/LD/DiagSymbolResolutions.inc"
 #include "mcld/LD/DiagRelocations.inc"
 #include "mcld/LD/DiagLayouts.inc"
 #include "mcld/LD/DiagGOTPLT.inc"
+#include "mcld/LD/DiagLDScript.inc"
 #undef DIAG
   { 0, DiagnosticEngine::None, 0, 0}
 };
@@ -58,11 +60,14 @@
 static const DiagStaticInfo DiagLoCInfo[] = {
 #define DIAG(ENUM, CLASS, ADDRDESC, LOCDESC) \
   { diag::ENUM, CLASS, STR_SIZE(LOCDESC, uint16_t), LOCDESC },
+#include "mcld/LD/DiagAttribute.inc"
+#include "mcld/LD/DiagCommonKinds.inc"
 #include "mcld/LD/DiagReaders.inc"
 #include "mcld/LD/DiagSymbolResolutions.inc"
 #include "mcld/LD/DiagRelocations.inc"
 #include "mcld/LD/DiagLayouts.inc"
 #include "mcld/LD/DiagGOTPLT.inc"
+#include "mcld/LD/DiagLDScript.inc"
 #undef DIAG
   { 0, DiagnosticEngine::None, 0, 0}
 };
@@ -114,12 +119,13 @@
 
   switch (ID) {
     case diag::multiple_definitions: {
-      if (m_Config.options().hasMulDefs()) {
+      if (m_Config.options().isMulDefs()) {
         severity = DiagnosticEngine::Ignore;
       }
       break;
     }
-    case diag::undefined_reference: {
+    case diag::undefined_reference:
+    case diag::undefined_reference_text: {
       // we have not implement --unresolved-symbols=method yet. So far, MCLinker
       // provides the easier --allow-shlib-undefined and --no-undefined (i.e. -z defs)
       switch(m_Config.codeGenType()) {
diff --git a/lib/LD/DynObjReader.cpp b/lib/LD/DynObjReader.cpp
index 60b5cf7..552e893 100644
--- a/lib/LD/DynObjReader.cpp
+++ b/lib/LD/DynObjReader.cpp
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include "mcld/LD/DynObjReader.h"
 #include "mcld/Target/TargetLDBackend.h"
-#include "mcld/MC/MCLDInput.h"
+#include "mcld/MC/Input.h"
 
 using namespace mcld;
 
diff --git a/lib/LD/ELFBinaryReader.cpp b/lib/LD/ELFBinaryReader.cpp
index 68deea0..ee537c2 100644
--- a/lib/LD/ELFBinaryReader.cpp
+++ b/lib/LD/ELFBinaryReader.cpp
@@ -10,9 +10,8 @@
 
 #include <mcld/IRBuilder.h>
 #include <mcld/LinkerConfig.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/Support/MemoryArea.h>
-#include <mcld/Target/GNULDBackend.h>
 
 #include <llvm/Support/ELF.h>
 
@@ -24,13 +23,9 @@
 // ELFBinaryReader
 //===----------------------------------------------------------------------===//
 /// constructor
-ELFBinaryReader::ELFBinaryReader(GNULDBackend& pBackend,
-                                 IRBuilder& pBuilder,
+ELFBinaryReader::ELFBinaryReader(IRBuilder& pBuilder,
                                  const LinkerConfig& pConfig)
-  : BinaryReader(),
-    m_Backend(pBackend),
-    m_Builder(pBuilder),
-    m_Config(pConfig) {
+  : m_Builder(pBuilder), m_Config(pConfig) {
 }
 
 /// destructor
@@ -38,6 +33,12 @@
 {
 }
 
+bool ELFBinaryReader::isMyFormat(Input& pInput, bool &pContinue) const
+{
+  pContinue = true;
+  return m_Config.options().isBinaryInput();
+}
+
 bool ELFBinaryReader::readBinary(Input& pInput)
 {
   // section: NULL
@@ -57,7 +58,7 @@
 
 
   SectionData* data = m_Builder.CreateSectionData(*data_sect);
-  size_t data_size = pInput.memArea()->handler()->size();
+  size_t data_size = pInput.memArea()->size();
   Fragment* frag = m_Builder.CreateRegion(pInput, 0x0, data_size);
   m_Builder.AppendFragment(*frag, *data);
 
diff --git a/lib/LD/ELFDynObjReader.cpp b/lib/LD/ELFDynObjReader.cpp
index 4f8c7ba..ebeba63 100644
--- a/lib/LD/ELFDynObjReader.cpp
+++ b/lib/LD/ELFDynObjReader.cpp
@@ -11,10 +11,11 @@
 #include <mcld/LinkerConfig.h>
 #include <mcld/IRBuilder.h>
 #include <mcld/LD/ELFReader.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/Support/MemoryRegion.h>
+#include <mcld/MC/Input.h>
 #include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MemoryArea.h>
 
+#include <llvm/ADT/StringRef.h>
 #include <llvm/ADT/Twine.h>
 #include <llvm/ADT/OwningPtr.h>
 #include <llvm/Support/ErrorHandling.h>
@@ -44,27 +45,34 @@
 }
 
 /// isMyFormat
-bool ELFDynObjReader::isMyFormat(Input &pInput) const
+bool ELFDynObjReader::isMyFormat(Input &pInput, bool &pContinue) const
 {
   assert(pInput.hasMemArea());
 
   // Don't warning about the frequently requests.
   // MemoryArea has a list of cache to handle this.
   size_t hdr_size = m_pELFReader->getELFHeaderSize();
-  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
-                                                   hdr_size);
+  if (pInput.memArea()->size() < hdr_size)
+    return false;
 
-  uint8_t* ELF_hdr = region->start();
+  llvm::StringRef region = pInput.memArea()->request(pInput.fileOffset(),
+                                                     hdr_size);
+
+  const char* ELF_hdr = region.begin();
   bool result = true;
-  if (!m_pELFReader->isELF(ELF_hdr))
+  if (!m_pELFReader->isELF(ELF_hdr)) {
+    pContinue = true;
     result = false;
-  else if (!m_pELFReader->isMyEndian(ELF_hdr))
+  } else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr)) {
+    pContinue = true;
     result = false;
-  else if (!m_pELFReader->isMyMachine(ELF_hdr))
+  } else if (!m_pELFReader->isMyEndian(ELF_hdr)) {
+    pContinue = false;
     result = false;
-  else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr))
+  } else if (!m_pELFReader->isMyMachine(ELF_hdr)) {
+    pContinue = false;
     result = false;
-  pInput.memArea()->release(region);
+  }
   return result;
 }
 
@@ -74,12 +82,11 @@
   assert(pInput.hasMemArea());
 
   size_t hdr_size = m_pELFReader->getELFHeaderSize();
-  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
-                                                   hdr_size);
-  uint8_t* ELF_hdr = region->start();
+  llvm::StringRef region = pInput.memArea()->request(pInput.fileOffset(),
+                                                     hdr_size);
+  const char* ELF_hdr = region.begin();
 
   bool shdr_result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
-  pInput.memArea()->release(region);
 
   // read .dynamic to get the correct SONAME
   bool dyn_result = m_pELFReader->readDynamic(pInput);
@@ -108,17 +115,14 @@
     return false;
   }
 
-  MemoryRegion* symtab_region = pInput.memArea()->request(
-              pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
+  llvm::StringRef symtab_region = pInput.memArea()->request(
+      pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
 
-  MemoryRegion* strtab_region = pInput.memArea()->request(
-              pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
-  char* strtab = reinterpret_cast<char*>(strtab_region->start());
+  llvm::StringRef strtab_region = pInput.memArea()->request(
+      pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
+  const char* strtab = strtab_region.begin();
   bool result = m_pELFReader->readSymbols(pInput, m_Builder,
-                                          *symtab_region, strtab);
-  pInput.memArea()->release(symtab_region);
-  pInput.memArea()->release(strtab_region);
-
+                                          symtab_region, strtab);
   return result;
 }
 
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index b645570..a34739a 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -8,21 +8,23 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/ELFObjectReader.h>
 
-#include <string>
-#include <cassert>
-
-#include <llvm/Support/ELF.h>
-#include <llvm/ADT/Twine.h>
-
 #include <mcld/IRBuilder.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/LD/ELFReader.h>
 #include <mcld/LD/EhFrameReader.h>
 #include <mcld/LD/EhFrame.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/MemoryArea.h>
 #include <mcld/Object/ObjectBuilder.h>
 
+#include <llvm/Support/ELF.h>
+#include <llvm/ADT/Twine.h>
+#include <llvm/ADT/StringRef.h>
+
+#include <string>
+#include <cassert>
+
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
@@ -57,27 +59,34 @@
 }
 
 /// isMyFormat
-bool ELFObjectReader::isMyFormat(Input &pInput) const
+bool ELFObjectReader::isMyFormat(Input &pInput, bool &pContinue) const
 {
   assert(pInput.hasMemArea());
 
   // Don't warning about the frequently requests.
   // MemoryArea has a list of cache to handle this.
   size_t hdr_size = m_pELFReader->getELFHeaderSize();
-  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
+  if (pInput.memArea()->size() < hdr_size)
+    return false;
+
+  llvm::StringRef region = pInput.memArea()->request(pInput.fileOffset(),
                                                      hdr_size);
 
-  uint8_t* ELF_hdr = region->start();
+  const char* ELF_hdr = region.begin();
   bool result = true;
-  if (!m_pELFReader->isELF(ELF_hdr))
+  if (!m_pELFReader->isELF(ELF_hdr)) {
+    pContinue = true;
     result = false;
-  else if (!m_pELFReader->isMyEndian(ELF_hdr))
+  } else if (Input::Object != m_pELFReader->fileType(ELF_hdr)) {
+    pContinue = true;
     result = false;
-  else if (!m_pELFReader->isMyMachine(ELF_hdr))
+  } else if (!m_pELFReader->isMyEndian(ELF_hdr)) {
+    pContinue = false;
     result = false;
-  else if (Input::Object != m_pELFReader->fileType(ELF_hdr))
+  } else if (!m_pELFReader->isMyMachine(ELF_hdr)) {
+    pContinue = false;
     result = false;
-  pInput.memArea()->release(region);
+  }
   return result;
 }
 
@@ -87,11 +96,13 @@
   assert(pInput.hasMemArea());
 
   size_t hdr_size = m_pELFReader->getELFHeaderSize();
-  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
+  if (pInput.memArea()->size() < hdr_size)
+    return false;
+
+  llvm::StringRef region = pInput.memArea()->request(pInput.fileOffset(),
                                                      hdr_size);
-  uint8_t* ELF_hdr = region->start();
+  const char* ELF_hdr = region.begin();
   bool result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
-  pInput.memArea()->release(region);
   return result;
 }
 
@@ -110,9 +121,9 @@
       case LDFileFormat::Group: {
         assert(NULL != (*section)->getLink());
         ResolveInfo* signature =
-              m_pELFReader->readSignature(pInput,
-                                          *(*section)->getLink(),
-                                          (*section)->getInfo());
+            m_pELFReader->readSignature(pInput,
+                                        *(*section)->getLink(),
+                                        (*section)->getInfo());
 
         bool exist = false;
         if (0 == signature->nameSize() &&
@@ -127,18 +138,17 @@
         if (exist) {
           // if this is not the first time we see this group signature, then
           // ignore all the members in this group (set Ignore)
-          MemoryRegion* region = pInput.memArea()->request(
+          llvm::StringRef region = pInput.memArea()->request(
                pInput.fileOffset() + (*section)->offset(), (*section)->size());
-          llvm::ELF::Elf32_Word* value =
-                     reinterpret_cast<llvm::ELF::Elf32_Word*>(region->start());
+          const llvm::ELF::Elf32_Word* value =
+              reinterpret_cast<const llvm::ELF::Elf32_Word*>(region.begin());
 
-          size_t size = region->size() / sizeof(llvm::ELF::Elf32_Word);
+          size_t size = region.size() / sizeof(llvm::ELF::Elf32_Word);
           if (llvm::ELF::GRP_COMDAT == *value) {
             for (size_t index = 1; index < size; ++index) {
               pInput.context()->getSection(value[index])->setKind(LDFileFormat::Ignore);
             }
           }
-          pInput.memArea()->release(region);
         }
         ResolveInfo::Destroy(signature);
         break;
@@ -212,10 +222,9 @@
       case LDFileFormat::EhFrame: {
         EhFrame* eh_frame = IRBuilder::CreateEhFrame(**section);
 
-        if (m_Config.options().hasEhFrameHdr() &&
+        // We don't really parse EhFrame if this is a partial linking
+        if ((m_Config.codeGenType() != LinkerConfig::Object) &&
             (m_ReadFlag & ParseEhFrame)) {
-
-          // if --eh-frame-hdr option is given, parse .eh_frame.
           if (!m_pEhFrameReader->read<32, true>(pInput, *eh_frame)) {
             // if we failed to parse a .eh_frame, we should not parse the rest
             // .eh_frame.
@@ -284,17 +293,15 @@
     return false;
   }
 
-  MemoryRegion* symtab_region = pInput.memArea()->request(
-             pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
-  MemoryRegion* strtab_region = pInput.memArea()->request(
-             pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
-  char* strtab = reinterpret_cast<char*>(strtab_region->start());
+  llvm::StringRef symtab_region = pInput.memArea()->request(
+      pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
+  llvm::StringRef strtab_region = pInput.memArea()->request(
+      pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
+  const char* strtab = strtab_region.begin();
   bool result = m_pELFReader->readSymbols(pInput,
                                           m_Builder,
-                                          *symtab_region,
+                                          symtab_region,
                                           strtab);
-  pInput.memArea()->release(symtab_region);
-  pInput.memArea()->release(strtab_region);
   return result;
 }
 
@@ -310,30 +317,26 @@
 
     uint32_t offset = pInput.fileOffset() + (*rs)->offset();
     uint32_t size = (*rs)->size();
-    MemoryRegion* region = mem->request(offset, size);
+    llvm::StringRef region = mem->request(offset, size);
     IRBuilder::CreateRelocData(**rs); ///< create relocation data for the header
     switch ((*rs)->type()) {
       case llvm::ELF::SHT_RELA: {
-        if (!m_pELFReader->readRela(pInput, **rs, *region)) {
-          mem->release(region);
+        if (!m_pELFReader->readRela(pInput, **rs, region)) {
           return false;
         }
         break;
       }
       case llvm::ELF::SHT_REL: {
-        if (!m_pELFReader->readRel(pInput, **rs, *region)) {
-          mem->release(region);
+        if (!m_pELFReader->readRel(pInput, **rs, region)) {
           return false;
         }
         break;
       }
       default: { ///< should not enter
-        mem->release(region);
         return false;
       }
     } // end of switch
 
-    mem->release(region);
   } // end of for all relocation data
 
   return true;
diff --git a/lib/LD/ELFObjectWriter.cpp b/lib/LD/ELFObjectWriter.cpp
index ddd3551..dca6936 100644
--- a/lib/LD/ELFObjectWriter.cpp
+++ b/lib/LD/ELFObjectWriter.cpp
@@ -10,23 +10,24 @@
 
 #include <mcld/Module.h>
 #include <mcld/LinkerConfig.h>
+#include <mcld/LinkerScript.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/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/LD/ELFFileFormat.h>
+#include <mcld/Target/GNUInfo.h>
 
 #include <llvm/Support/ErrorHandling.h>
 #include <llvm/Support/system_error.h>
@@ -50,9 +51,10 @@
 {
 }
 
-void ELFObjectWriter::writeSection(MemoryArea& pOutput, LDSection *section)
+void ELFObjectWriter::writeSection(Module& pModule,
+                                   FileOutputBuffer& pOutput, LDSection *section)
 {
-  MemoryRegion* region;
+  MemoryRegion region;
   // Request output region
   switch (section->kind()) {
   case LDFileFormat::Note:
@@ -66,10 +68,8 @@
   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"));
+    if (region.size() == 0) {
+      return;
     }
     break;
   }
@@ -94,19 +94,22 @@
   // 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);
+    emitSectionData(*section, region);
+    break;
+  case LDFileFormat::EhFrame:
+    emitEhFrame(pModule, *section->getEhFrame(), region);
     break;
   case LDFileFormat::Relocation:
-    emitRelocation(m_Config, *section, *region);
+    // sort relocation for the benefit of the dynamic linker.
+    target().sortRelocation(*section);
+
+    emitRelocation(m_Config, *section, region);
     break;
   case LDFileFormat::Target:
-    target().emitSectionData(*section, *region);
+    target().emitSectionData(*section, region);
     break;
   default:
     llvm_unreachable("invalid section kind");
@@ -114,7 +117,7 @@
 }
 
 llvm::error_code ELFObjectWriter::writeObject(Module& pModule,
-                                              MemoryArea& pOutput)
+                                              FileOutputBuffer& pOutput)
 {
   bool is_dynobj = m_Config.codeGenType() == LinkerConfig::DynObj;
   bool is_exec = m_Config.codeGenType() == LinkerConfig::Exec;
@@ -144,17 +147,17 @@
     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);
+      if (llvm::ELF::PT_LOAD == (*seg)->type()) {
+        ELFSegment::iterator sect, sectEnd = (*seg)->end();
+        for (sect = (*seg)->begin(); sect != sectEnd; ++sect)
+          writeSection(pModule, pOutput, *sect);
       }
     }
   } else {
     // Write out regular ELF sections
     Module::iterator sect, sectEnd = pModule.end();
     for (sect = pModule.begin(); sect != sectEnd; ++sect)
-      writeSection(pOutput, *sect);
+      writeSection(pModule, pOutput, *sect);
 
     emitShStrTab(target().getOutputFormat()->getShStrTab(), pModule, pOutput);
 
@@ -180,23 +183,37 @@
       return make_error_code(errc::not_supported);
   }
 
-  pOutput.clear();
   return llvm::make_error_code(llvm::errc::success);
 }
 
+// getOutputSize - count the final output size
+size_t ELFObjectWriter::getOutputSize(const Module& pModule) const
+{
+  if (m_Config.targets().is32Bits()) {
+    return getLastStartOffset<32>(pModule) +
+           sizeof(ELFSizeTraits<32>::Shdr) * pModule.size();
+  } else if (m_Config.targets().is64Bits()) {
+    return getLastStartOffset<64>(pModule) +
+           sizeof(ELFSizeTraits<64>::Shdr) * pModule.size();
+  } else {
+    assert(0 && "Invalid ELF Class");
+    return 0;
+  }
+}
+
 // writeELFHeader - emit ElfXX_Ehdr
 template<size_t SIZE>
 void ELFObjectWriter::writeELFHeader(const LinkerConfig& pConfig,
                                      const Module& pModule,
-                                     MemoryArea& pOutput) const
+                                     FileOutputBuffer& 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();
+  MemoryRegion region = pOutput.request(0, sizeof(ElfXX_Ehdr));
+  ElfXX_Ehdr* header = (ElfXX_Ehdr*)region.begin();
 
   memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
 
@@ -235,7 +252,7 @@
   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_phnum     = target().elfSegmentTable().size();
   header->e_shentsize = sizeof(ElfXX_Shdr);
   header->e_shnum     = pModule.size();
   header->e_shstrndx  = pModule.getSection(".shstrtab")->index();
@@ -245,15 +262,10 @@
 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();
-
+  llvm::StringRef entry_name = target().getEntry(pModule);
   uint64_t result = 0x0;
 
-  bool issue_warning = (pConfig.options().hasEntry() &&
+  bool issue_warning = (pModule.getScript().hasEntry() &&
                         LinkerConfig::Object != pConfig.codeGenType() &&
                         LinkerConfig::DynObj != pConfig.codeGenType());
 
@@ -290,16 +302,16 @@
 template<size_t SIZE>
 void ELFObjectWriter::emitSectionHeader(const Module& pModule,
                                         const LinkerConfig& pConfig,
-                                        MemoryArea& pOutput) const
+                                        FileOutputBuffer& 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();
+  MemoryRegion region = pOutput.request(getLastStartOffset<SIZE>(pModule),
+                                        header_size);
+  ElfXX_Shdr* shdr = (ElfXX_Shdr*)region.begin();
 
   // Iterate the SectionTable in LDContext
   unsigned int sectIdx = 0;
@@ -324,7 +336,7 @@
 
 // emitProgramHeader - emit ElfXX_Phdr
 template<size_t SIZE>
-void ELFObjectWriter::emitProgramHeader(MemoryArea& pOutput) const
+void ELFObjectWriter::emitProgramHeader(FileOutputBuffer& pOutput) const
 {
   typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
   typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;
@@ -334,24 +346,24 @@
   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);
+  MemoryRegion region = pOutput.request(start_offset,
+      target().elfSegmentTable().size() * phdr_size);
 
-  ElfXX_Phdr* phdr = (ElfXX_Phdr*)region->start();
+  ElfXX_Phdr* phdr = (ElfXX_Phdr*)region.begin();
 
   // 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();
+    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();
   }
 }
 
@@ -359,11 +371,11 @@
 void
 ELFObjectWriter::emitShStrTab(const LDSection& pShStrTab,
                               const Module& pModule,
-                              MemoryArea& pOutput)
+                              FileOutputBuffer& pOutput)
 {
   // write out data
-  MemoryRegion* region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
-  unsigned char* data = region->start();
+  MemoryRegion region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
+  char* data = (char*)region.begin();
   size_t shstrsize = 0;
   Module::const_iterator section, sectEnd = pModule.end();
   for (section = pModule.begin(); section != sectEnd; ++section) {
@@ -394,6 +406,50 @@
   emitSectionData(*sd, pRegion);
 }
 
+/// emitEhFrame
+void ELFObjectWriter::emitEhFrame(Module& pModule,
+                                  EhFrame& pFrame, MemoryRegion& pRegion) const
+{
+  emitSectionData(*pFrame.getSectionData(), pRegion);
+
+  // Patch FDE field (offset to CIE)
+  for (EhFrame::cie_iterator i = pFrame.cie_begin(), e = pFrame.cie_end();
+       i != e; ++i) {
+    EhFrame::CIE& cie = **i;
+    for (EhFrame::fde_iterator fi = cie.begin(), fe = cie.end();
+         fi != fe; ++fi) {
+      EhFrame::FDE& fde = **fi;
+      if (fde.getRecordType() == EhFrame::RECORD_GENERATED) {
+        // Patch PLT offset
+        LDSection* plt_sect = pModule.getSection(".plt");
+        assert (plt_sect && "We have no plt but have corresponding eh_frame?");
+        uint64_t plt_offset = plt_sect->offset();
+        // FDE entry for PLT is always 32-bit
+        uint64_t fde_offset = pFrame.getSection().offset() + fde.getOffset() +
+                              EhFrame::getDataStartOffset<32>();
+        int32_t offset = fde_offset - plt_offset;
+        if (plt_offset < fde_offset)
+          offset = -offset;
+        memcpy(pRegion.begin() + fde.getOffset() +
+                                 EhFrame::getDataStartOffset<32>(),
+                                 &offset, 4);
+        uint32_t size = plt_sect->size();
+        memcpy(pRegion.begin() + fde.getOffset() +
+                                 EhFrame::getDataStartOffset<32>() + 4,
+                                 &size, 4);
+      }
+      uint64_t fde_cie_ptr_offset = fde.getOffset() +
+                                    EhFrame::getDataStartOffset<32>() -
+                                    /*ID*/4;
+      uint64_t cie_start_offset = cie.getOffset();
+      int32_t offset = fde_cie_ptr_offset - cie_start_offset;
+      if (fde_cie_ptr_offset < cie_start_offset)
+        offset = -offset;
+      memcpy(pRegion.begin() + fde_cie_ptr_offset, &offset, 4);
+    } // for loop fde_iterator
+  } // for loop cie_iterator
+}
+
 /// emitRelocation
 void ELFObjectWriter::emitRelocation(const LinkerConfig& pConfig,
                                      const LDSection& pSection,
@@ -435,34 +491,36 @@
   typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
   typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
 
-  ElfXX_Rel* rel = reinterpret_cast<ElfXX_Rel*>(pRegion.start());
+  ElfXX_Rel* rel = reinterpret_cast<ElfXX_Rel*>(pRegion.begin());
 
   const Relocation* relocation = 0;
   const FragmentRef* frag_ref = 0;
 
   for (RelocData::const_iterator it = pRelocData.begin(),
        ie = pRelocData.end(); it != ie; ++it, ++rel) {
+    ElfXX_Addr r_offset = 0;
+    ElfXX_Word r_sym = 0;
 
     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>(
+      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());
+      r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
     }
-    ElfXX_Word Index;
+
     if( relocation->symInfo() == NULL )
-      Index = 0;
+      r_sym = 0;
     else
-      Index = static_cast<ElfXX_Word>(
+      r_sym = static_cast<ElfXX_Word>(
               target().getSymbolIdx(relocation->symInfo()->outSymbol()));
 
-    rel->setSymbolAndType(Index, relocation->type());
+    target().emitRelocation(*rel, relocation->type(), r_sym, r_offset);
   }
 }
 
@@ -476,36 +534,37 @@
   typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
   typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;
 
-  ElfXX_Rela* rel = reinterpret_cast<ElfXX_Rela*>(pRegion.start());
+  ElfXX_Rela* rel = reinterpret_cast<ElfXX_Rela*>(pRegion.begin());
 
   const Relocation* relocation = 0;
   const FragmentRef* frag_ref = 0;
 
   for (RelocData::const_iterator it = pRelocData.begin(),
        ie = pRelocData.end(); it != ie; ++it, ++rel) {
+    ElfXX_Addr r_offset = 0;
+    ElfXX_Word r_sym = 0;
 
     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>(
+      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());
+      r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
     }
 
-    ElfXX_Word Index;
     if( relocation->symInfo() == NULL )
-      Index = 0;
+      r_sym = 0;
     else
-      Index = static_cast<ElfXX_Word>(
+      r_sym = static_cast<ElfXX_Word>(
               target().getSymbolIdx(relocation->symInfo()->outSymbol()));
 
-    rel->setSymbolAndType(Index, relocation->type());
-    rel->r_addend = relocation->addend();
+    target().emitRelocation(*rel, relocation->type(),
+                            r_sym, r_offset, relocation->addend());
   }
 }
 
@@ -532,6 +591,12 @@
     return sizeof(ElfXX_Word);
   if (llvm::ELF::SHT_DYNAMIC == pSection.type())
     return sizeof(ElfXX_Dyn);
+  // FIXME: We should get the entsize from input since the size of each
+  // character is specified in the section header's sh_entsize field.
+  // For example, traditional string is 0x1, UCS-2 is 0x2, ... and so on.
+  // Ref: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html
+  if (pSection.flag() & llvm::ELF::SHF_STRINGS)
+    return 0x1;
   return 0x0;
 }
 
@@ -607,8 +672,8 @@
     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);
+        const char* from = region_frag.getRegion().begin();
+        memcpy(pRegion.begin() + cur_offset, from, size);
         break;
       }
       case Fragment::Alignment: {
@@ -617,7 +682,7 @@
         uint64_t count = size / align_frag.getValueSize();
         switch (align_frag.getValueSize()) {
           case 1u:
-            std::memset(pRegion.getBuffer(cur_offset),
+            std::memset(pRegion.begin() + cur_offset,
                         align_frag.getValue(),
                         count);
             break;
@@ -638,7 +703,7 @@
 
         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),
+          std::memset(pRegion.begin() + cur_offset,
                       fill_frag.getValue(),
                       fill_frag.getValueSize());
         }
@@ -646,7 +711,7 @@
       }
       case Fragment::Stub: {
         const Stub& stub_frag = llvm::cast<Stub>(*fragIter);
-        memcpy(pRegion.getBuffer(cur_offset), stub_frag.getContent(), size);
+        memcpy(pRegion.begin() + cur_offset, stub_frag.getContent(), size);
         break;
       }
       case Fragment::Null: {
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index f7b047f..119f8a7 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -13,8 +13,9 @@
 #include <mcld/LD/EhFrame.h>
 #include <mcld/LD/SectionData.h>
 #include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Target/GNUInfo.h>
 #include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/MemoryArea.h>
 #include <mcld/Object/ObjectBuilder.h>
 
 #include <cstring>
@@ -42,10 +43,10 @@
 }
 
 /// isELF - is this a ELF file
-bool ELFReader<32, true>::isELF(void* pELFHeader) const
+bool ELFReader<32, true>::isELF(const void* pELFHeader) const
 {
-  llvm::ELF::Elf32_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf32_Ehdr* hdr =
+      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
   if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
     return true;
   return false;
@@ -66,13 +67,13 @@
 /// readSymbols - read ELF symbols and create LDSymbol
 bool ELFReader<32, true>::readSymbols(Input& pInput,
                                       IRBuilder& pBuilder,
-                                      const MemoryRegion& pRegion,
+                                      llvm::StringRef pRegion,
                                       const char* pStrTab) const
 {
   // get number of symbols
   size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf32_Sym);
   const llvm::ELF::Elf32_Sym* symtab =
-                 reinterpret_cast<const llvm::ELF::Elf32_Sym*>(pRegion.start());
+      reinterpret_cast<const llvm::ELF::Elf32_Sym*>(pRegion.begin());
 
   uint32_t st_name  = 0x0;
   uint32_t st_value = 0x0;
@@ -144,22 +145,22 @@
       ld_name = std::string(pStrTab + st_name);
     }
 
-    LDSymbol *psym =
-        pBuilder.AddSymbol(pInput,
-                           ld_name,
-                           ld_type,
-                           ld_desc,
-                           ld_binding,
-                           st_size,
-                           ld_value,
-                           section, ld_vis);
+    LDSymbol* psym = pBuilder.AddSymbol(pInput,
+                                        ld_name,
+                                        ld_type,
+                                        ld_desc,
+                                        ld_binding,
+                                        st_size,
+                                        ld_value,
+                                        section,
+                                        ld_vis);
 
-    if ( is_dyn_obj
-         && NULL!=psym
-         && ResolveInfo::Undefined!=ld_desc
-         && (ResolveInfo::Global==ld_binding ||
-             ResolveInfo::Weak==ld_binding)
-         && ResolveInfo::Object==ld_type ) {
+    if (is_dyn_obj
+        && NULL != psym
+        && ResolveInfo::Undefined != ld_desc
+        && (ResolveInfo::Global == ld_binding ||
+            ResolveInfo::Weak == ld_binding)
+        && ResolveInfo::Object == ld_type) {
       AliasInfo p;
       p.pt_alias = psym;
       p.ld_binding = ld_binding;
@@ -174,9 +175,9 @@
   //        1. eliminate code duplication
   //        2. easy to know if a symbol is from .so
   //           (so that it may be a potential alias)
-  if ( is_dyn_obj ) {
+  if (is_dyn_obj) {
     // sort symbols by symbol value and then weak before strong
-    std::sort( potential_aliases.begin(), potential_aliases.end(), less);
+    std::sort(potential_aliases.begin(), potential_aliases.end(), less);
 
     // for each weak symbol, find out all its aliases, and
     // then link them as a circular list in Module
@@ -189,16 +190,16 @@
       Module& pModule = pBuilder.getModule();
       std::vector<AliasInfo>::iterator alias_it = sym_it+1;
       while(alias_it!=sym_e) {
-        if ( sym_it->ld_value != alias_it->ld_value )
+        if (sym_it->ld_value != alias_it->ld_value)
           break;
 
-        if (sym_it+1==alias_it)
+        if (sym_it + 1 == alias_it)
           pModule.CreateAliasList(*sym_it->pt_alias->resolveInfo());
         pModule.addAlias(*alias_it->pt_alias->resolveInfo());
         ++alias_it;
       }
 
-      sym_it = alias_it-1;
+      sym_it = alias_it - 1;
     }// end of for loop
   }
 
@@ -211,30 +212,21 @@
 /// ELFReader::readRela - read ELF rela and create Relocation
 bool ELFReader<32, true>::readRela(Input& pInput,
                                    LDSection& pSection,
-                                   const MemoryRegion& pRegion) const
+                                   llvm::StringRef pRegion) const
 {
   // get the number of rela
   size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rela);
   const llvm::ELF::Elf32_Rela* relaTab =
-                reinterpret_cast<const llvm::ELF::Elf32_Rela*>(pRegion.start());
+      reinterpret_cast<const llvm::ELF::Elf32_Rela*>(pRegion.begin());
 
   for (size_t idx=0; idx < entsize; ++idx) {
+    Relocation::Type r_type = 0x0;
+    uint32_t r_sym = 0x0;
     uint32_t r_offset = 0x0;
-    uint32_t r_info   = 0x0;
     int32_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::bswap32(relaTab[idx].r_offset);
-      r_info   = mcld::bswap32(relaTab[idx].r_info);
-      r_addend = mcld::bswap32(relaTab[idx].r_addend);
-    }
+    if (!target().readRelocation(relaTab[idx], r_type, r_sym, r_offset, r_addend))
+      return false;
 
-    uint8_t  r_type = static_cast<unsigned char>(r_info);
-    uint32_t r_sym  = (r_info >> 8);
     LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
     if (NULL == symbol) {
       fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
@@ -248,27 +240,20 @@
 /// readRel - read ELF rel and create Relocation
 bool ELFReader<32, true>::readRel(Input& pInput,
                                   LDSection& pSection,
-                                  const MemoryRegion& pRegion) const
+                                  llvm::StringRef pRegion) const
 {
   // get the number of rel
   size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rel);
   const llvm::ELF::Elf32_Rel* relTab =
-                 reinterpret_cast<const llvm::ELF::Elf32_Rel*>(pRegion.start());
+      reinterpret_cast<const llvm::ELF::Elf32_Rel*>(pRegion.begin());
 
   for (size_t idx=0; idx < entsize; ++idx) {
+    Relocation::Type r_type = 0x0;
+    uint32_t r_sym = 0x0;
     uint32_t r_offset = 0x0;
-    uint32_t r_info   = 0x0;
-    if (llvm::sys::IsLittleEndianHost) {
-      r_offset = relTab[idx].r_offset;
-      r_info   = relTab[idx].r_info;
-    }
-    else {
-      r_offset = mcld::bswap32(relTab[idx].r_offset);
-      r_info   = mcld::bswap32(relTab[idx].r_info);
-    }
 
-    uint8_t  r_type = static_cast<unsigned char>(r_info);
-    uint32_t r_sym  = (r_info >> 8);
+    if (!target().readRelocation(relTab[idx], r_type, r_sym, r_offset))
+      return false;
 
     LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
     if (NULL == symbol) {
@@ -281,19 +266,19 @@
 }
 
 /// isMyEndian - is this ELF file in the same endian to me?
-bool ELFReader<32, true>::isMyEndian(void* pELFHeader) const
+bool ELFReader<32, true>::isMyEndian(const void* pELFHeader) const
 {
-  llvm::ELF::Elf32_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf32_Ehdr* hdr =
+      reinterpret_cast<const llvm::ELF::Elf32_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<32, true>::isMyMachine(void* pELFHeader) const
+bool ELFReader<32, true>::isMyMachine(const void* pELFHeader) const
 {
-  llvm::ELF::Elf32_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf32_Ehdr* hdr =
+      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
 
   if (llvm::sys::IsLittleEndianHost)
     return (hdr->e_machine == target().getInfo().machine());
@@ -301,10 +286,10 @@
 }
 
 /// fileType - return the file type
-Input::Type ELFReader<32, true>::fileType(void* pELFHeader) const
+Input::Type ELFReader<32, true>::fileType(const void* pELFHeader) const
 {
-  llvm::ELF::Elf32_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf32_Ehdr* hdr =
+      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
   uint32_t type = 0x0;
   if (llvm::sys::IsLittleEndianHost)
     type = hdr->e_type;
@@ -327,11 +312,11 @@
 }
 
 /// readSectionHeaders - read ELF section header table and create LDSections
-bool
-ELFReader<32, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
+bool ELFReader<32, true>::readSectionHeaders(Input& pInput,
+                                             const void* pELFHeader) const
 {
-  llvm::ELF::Elf32_Ehdr* ehdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf32_Ehdr* ehdr =
+      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
 
   uint32_t shoff     = 0x0;
   uint16_t shentsize = 0x0;
@@ -355,8 +340,8 @@
   if (0x0 == shoff)
     return true;
 
-  llvm::ELF::Elf32_Shdr *shdr = NULL;
-  MemoryRegion* shdr_region = NULL;
+  const llvm::ELF::Elf32_Shdr *shdr = NULL;
+  llvm::StringRef shdr_region;
   uint32_t sh_name      = 0x0;
   uint32_t sh_type      = 0x0;
   uint32_t sh_flags     = 0x0;
@@ -370,7 +355,7 @@
   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());
+    shdr = reinterpret_cast<const llvm::ELF::Elf32_Shdr*>(shdr_region.begin());
 
     if (llvm::sys::IsLittleEndianHost) {
       sh_size = shdr->sh_size;
@@ -380,7 +365,6 @@
       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;
@@ -392,8 +376,8 @@
 
   shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
                                           shnum * shentsize);
-  llvm::ELF::Elf32_Shdr * shdrTab =
-    reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
+  const llvm::ELF::Elf32_Shdr* shdrTab =
+      reinterpret_cast<const llvm::ELF::Elf32_Shdr*>(shdr_region.begin());
 
   // get .shstrtab first
   shdr = &shdrTab[shstrtab];
@@ -406,10 +390,9 @@
     sh_size   = mcld::bswap32(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());
+  llvm::StringRef sect_name_region = pInput.memArea()->request(
+      pInput.fileOffset() + sh_offset, sh_size);
+  const char* sect_name = sect_name_region.begin();
 
   LinkInfoList link_info_list;
 
@@ -454,21 +437,12 @@
   // 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()) {
+    if (LDFileFormat::Relocation == info->section->kind())
       info->section->setLink(pInput.context()->getSection(info->sh_info));
-      continue;
-    }
+    else
+      info->section->setLink(pInput.context()->getSection(info->sh_link));
   }
 
-  pInput.memArea()->release(shdr_region);
-  pInput.memArea()->release(sect_name_region);
-
   return true;
 }
 
@@ -484,10 +458,10 @@
 
   uint32_t offset = pInput.fileOffset() + symtab->offset() +
                       sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
-  MemoryRegion* symbol_region =
-                pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
-  llvm::ELF::Elf32_Sym* entry =
-                reinterpret_cast<llvm::ELF::Elf32_Sym*>(symbol_region->start());
+  llvm::StringRef symbol_region =
+      pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
+  const llvm::ELF::Elf32_Sym* entry =
+      reinterpret_cast<const llvm::ELF::Elf32_Sym*>(symbol_region.begin());
 
   uint32_t st_name  = 0x0;
   uint8_t  st_info  = 0x0;
@@ -504,12 +478,11 @@
     st_shndx = mcld::bswap16(entry->st_shndx);
   }
 
-  MemoryRegion* strtab_region = pInput.memArea()->request(
-                       pInput.fileOffset() + strtab->offset(), strtab->size());
+  llvm::StringRef 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));
+  llvm::StringRef ld_name(strtab_region.begin() + st_name);
 
   ResolveInfo* result = ResolveInfo::Create(ld_name);
   result->setSource(pInput.type() == Input::DynObj);
@@ -518,10 +491,6 @@
   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;
 }
 
@@ -538,17 +507,15 @@
     fatal(diag::err_cannot_read_section) << ".dynstr";
   }
 
-  MemoryRegion* dynamic_region = pInput.memArea()->request(
-           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
+  llvm::StringRef 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);
+  llvm::StringRef dynstr_region = pInput.memArea()->request(
+      pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
 
   const llvm::ELF::Elf32_Dyn* dynamic =
-    (llvm::ELF::Elf32_Dyn*) dynamic_region->start();
-  const char* dynstr = (const char*) dynstr_region->start();
+      reinterpret_cast<const llvm::ELF::Elf32_Dyn*>(dynamic_region.begin());
+  const char* dynstr = dynstr_region.begin();
   bool hasSOName = false;
   size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
 
@@ -584,8 +551,6 @@
   if (!hasSOName)
     pInput.setName(pInput.path().filename().native());
 
-  pInput.memArea()->release(dynamic_region);
-  pInput.memArea()->release(dynstr_region);
   return true;
 }
 
@@ -603,10 +568,10 @@
 }
 
 /// isELF - is this a ELF file
-bool ELFReader<64, true>::isELF(void* pELFHeader) const
+bool ELFReader<64, true>::isELF(const void* pELFHeader) const
 {
-  llvm::ELF::Elf64_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf64_Ehdr* hdr =
+      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
   if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
     return true;
   return false;
@@ -627,13 +592,13 @@
 /// readSymbols - read ELF symbols and create LDSymbol
 bool ELFReader<64, true>::readSymbols(Input& pInput,
                                       IRBuilder& pBuilder,
-                                      const MemoryRegion& pRegion,
+                                      llvm::StringRef pRegion,
                                       const char* pStrTab) const
 {
   // get number of symbols
-  size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf64_Sym);
+  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());
+      reinterpret_cast<const llvm::ELF::Elf64_Sym*>(pRegion.begin());
 
   uint32_t st_name  = 0x0;
   uint64_t st_value = 0x0;
@@ -705,22 +670,22 @@
       ld_name = std::string(pStrTab + st_name);
     }
 
-    LDSymbol *psym =
-            pBuilder.AddSymbol(pInput,
-                               ld_name,
-                               ld_type,
-                               ld_desc,
-                               ld_binding,
-                               st_size,
-                               ld_value,
-                               section, ld_vis);
+    LDSymbol* psym = pBuilder.AddSymbol(pInput,
+                                        ld_name,
+                                        ld_type,
+                                        ld_desc,
+                                        ld_binding,
+                                        st_size,
+                                        ld_value,
+                                        section,
+                                        ld_vis);
 
-    if ( is_dyn_obj
-         && NULL!=psym
-         && ResolveInfo::Undefined!=ld_desc
-         && (ResolveInfo::Global==ld_binding ||
-             ResolveInfo::Weak==ld_binding)
-         && ResolveInfo::Object==ld_type ) {
+    if (is_dyn_obj
+        && NULL != psym
+        && ResolveInfo::Undefined != ld_desc
+        && (ResolveInfo::Global == ld_binding ||
+            ResolveInfo::Weak == ld_binding)
+        && ResolveInfo::Object == ld_type ) {
       AliasInfo p;
       p.pt_alias = psym;
       p.ld_binding = ld_binding;
@@ -731,9 +696,9 @@
   } // end of for loop
 
   // analyze weak alias here
-  if ( is_dyn_obj ) {
+  if (is_dyn_obj) {
     // sort symbols by symbol value and then weak before strong
-    std::sort( potential_aliases.begin(), potential_aliases.end(), less);
+    std::sort(potential_aliases.begin(), potential_aliases.end(), less);
 
     // for each weak symbol, find out all its aliases, and
     // then link them as a circular list in Module
@@ -746,16 +711,16 @@
       Module& pModule = pBuilder.getModule();
       std::vector<AliasInfo>::iterator alias_it = sym_it+1;
       while(alias_it!=sym_e) {
-        if ( sym_it->ld_value != alias_it->ld_value )
+        if (sym_it->ld_value != alias_it->ld_value)
           break;
 
-        if (sym_it+1==alias_it)
+        if (sym_it + 1 == alias_it)
           pModule.CreateAliasList(*sym_it->pt_alias->resolveInfo());
         pModule.addAlias(*alias_it->pt_alias->resolveInfo());
         ++alias_it;
       }
 
-      sym_it = alias_it-1;
+      sym_it = alias_it - 1;
     }// end of for loop
   }
   return true;
@@ -767,30 +732,23 @@
 /// ELFReader::readRela - read ELF rela and create Relocation
 bool ELFReader<64, true>::readRela(Input& pInput,
                                    LDSection& pSection,
-                                   const MemoryRegion& pRegion) const
+                                   llvm::StringRef 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());
+      reinterpret_cast<const llvm::ELF::Elf64_Rela*>(pRegion.begin());
 
   for (size_t idx=0; idx < entsize; ++idx) {
+    Relocation::Type r_type = 0x0;
+    uint32_t r_sym = 0x0;
     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);
+    if (!target().readRelocation(relaTab[idx],
+                                 r_type, r_sym, r_offset, r_addend)) {
+      return false;
     }
 
-    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();
@@ -804,27 +762,19 @@
 /// readRel - read ELF rel and create Relocation
 bool ELFReader<64, true>::readRel(Input& pInput,
                                   LDSection& pSection,
-                                  const MemoryRegion& pRegion) const
+                                  llvm::StringRef 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());
+      reinterpret_cast<const llvm::ELF::Elf64_Rel*>(pRegion.begin());
 
   for (size_t idx=0; idx < entsize; ++idx) {
+    Relocation::Type r_type = 0x0;
+    uint32_t r_sym = 0x0;
     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);
+    if (!target().readRelocation(relTab[idx], r_type, r_sym, r_offset))
+      return false;
 
     LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
     if (NULL == symbol) {
@@ -837,19 +787,19 @@
 }
 
 /// isMyEndian - is this ELF file in the same endian to me?
-bool ELFReader<64, true>::isMyEndian(void* pELFHeader) const
+bool ELFReader<64, true>::isMyEndian(const void* pELFHeader) const
 {
-  llvm::ELF::Elf64_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf64_Ehdr* hdr =
+      reinterpret_cast<const 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
+bool ELFReader<64, true>::isMyMachine(const void* pELFHeader) const
 {
-  llvm::ELF::Elf64_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf64_Ehdr* hdr =
+      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
 
   if (llvm::sys::IsLittleEndianHost)
     return (hdr->e_machine == target().getInfo().machine());
@@ -857,10 +807,10 @@
 }
 
 /// fileType - return the file type
-Input::Type ELFReader<64, true>::fileType(void* pELFHeader) const
+Input::Type ELFReader<64, true>::fileType(const void* pELFHeader) const
 {
-  llvm::ELF::Elf64_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf64_Ehdr* hdr =
+      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
   uint32_t type = 0x0;
   if (llvm::sys::IsLittleEndianHost)
     type = hdr->e_type;
@@ -883,11 +833,11 @@
 }
 
 /// readSectionHeaders - read ELF section header table and create LDSections
-bool
-ELFReader<64, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
+bool ELFReader<64, true>::readSectionHeaders(Input& pInput,
+                                             const void* pELFHeader) const
 {
-  llvm::ELF::Elf64_Ehdr* ehdr =
-                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
+  const llvm::ELF::Elf64_Ehdr* ehdr =
+      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
 
   uint64_t shoff     = 0x0;
   uint16_t shentsize = 0x0;
@@ -911,8 +861,8 @@
   if (0x0 == shoff)
     return true;
 
-  llvm::ELF::Elf64_Shdr *shdr = NULL;
-  MemoryRegion* shdr_region = NULL;
+  const llvm::ELF::Elf64_Shdr *shdr = NULL;
+  llvm::StringRef shdr_region;
   uint32_t sh_name      = 0x0;
   uint32_t sh_type      = 0x0;
   uint64_t sh_flags     = 0x0;
@@ -926,7 +876,7 @@
   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());
+    shdr = reinterpret_cast<const llvm::ELF::Elf64_Shdr*>(shdr_region.begin());
 
     if (llvm::sys::IsLittleEndianHost) {
       sh_size = shdr->sh_size;
@@ -936,7 +886,6 @@
       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;
@@ -948,8 +897,8 @@
 
   shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
                                           shnum * shentsize);
-  llvm::ELF::Elf64_Shdr * shdrTab =
-    reinterpret_cast<llvm::ELF::Elf64_Shdr*>(shdr_region->start());
+  const llvm::ELF::Elf64_Shdr* shdrTab =
+      reinterpret_cast<const llvm::ELF::Elf64_Shdr*>(shdr_region.begin());
 
   // get .shstrtab first
   shdr = &shdrTab[shstrtab];
@@ -962,10 +911,9 @@
     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());
+  llvm::StringRef sect_name_region = pInput.memArea()->request(
+      pInput.fileOffset() + sh_offset, sh_size);
+  const char* sect_name = sect_name_region.begin();
 
   LinkInfoList link_info_list;
 
@@ -1010,21 +958,12 @@
   // 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()) {
+    if (LDFileFormat::Relocation == info->section->kind())
       info->section->setLink(pInput.context()->getSection(info->sh_info));
-      continue;
-    }
+    else
+      info->section->setLink(pInput.context()->getSection(info->sh_link));
   }
 
-  pInput.memArea()->release(shdr_region);
-  pInput.memArea()->release(sect_name_region);
-
   return true;
 }
 
@@ -1040,10 +979,10 @@
 
   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());
+  llvm::StringRef symbol_region =
+      pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf64_Sym));
+  const llvm::ELF::Elf64_Sym* entry =
+      reinterpret_cast<const llvm::ELF::Elf64_Sym*>(symbol_region.begin());
 
   uint32_t st_name  = 0x0;
   uint8_t  st_info  = 0x0;
@@ -1060,12 +999,11 @@
     st_shndx = mcld::bswap16(entry->st_shndx);
   }
 
-  MemoryRegion* strtab_region = pInput.memArea()->request(
-                       pInput.fileOffset() + strtab->offset(), strtab->size());
+  llvm::StringRef 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));
+  llvm::StringRef ld_name(strtab_region.begin() + st_name);
 
   ResolveInfo* result = ResolveInfo::Create(ld_name);
   result->setSource(pInput.type() == Input::DynObj);
@@ -1074,10 +1012,6 @@
   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;
 }
 
@@ -1094,17 +1028,15 @@
     fatal(diag::err_cannot_read_section) << ".dynstr";
   }
 
-  MemoryRegion* dynamic_region = pInput.memArea()->request(
-           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
+  llvm::StringRef 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);
+  llvm::StringRef dynstr_region = pInput.memArea()->request(
+      pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
 
   const llvm::ELF::Elf64_Dyn* dynamic =
-    (llvm::ELF::Elf64_Dyn*) dynamic_region->start();
-  const char* dynstr = (const char*) dynstr_region->start();
+      reinterpret_cast<const llvm::ELF::Elf64_Dyn*>(dynamic_region.begin());
+  const char* dynstr = dynstr_region.begin();
   bool hasSOName = false;
   size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf64_Dyn);
 
@@ -1140,8 +1072,5 @@
   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
index 4d56b14..7d72596 100644
--- a/lib/LD/ELFReaderIf.cpp
+++ b/lib/LD/ELFReaderIf.cpp
@@ -13,10 +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>
 
 #include <cstring>
 
diff --git a/lib/LD/ELFSegment.cpp b/lib/LD/ELFSegment.cpp
index ae328ca..1c09514 100644
--- a/lib/LD/ELFSegment.cpp
+++ b/lib/LD/ELFSegment.cpp
@@ -7,61 +7,100 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/ELFSegment.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/Support/GCFactory.h>
+#include <mcld/Config/Config.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <cassert>
 
 using namespace mcld;
 
-//==========================
+typedef GCFactory<ELFSegment, MCLD_SEGMENTS_PER_OUTPUT> ELFSegmentFactory;
+static llvm::ManagedStatic<ELFSegmentFactory> g_ELFSegmentFactory;
+
+//===----------------------------------------------------------------------===//
 // ELFSegment
-ELFSegment::ELFSegment(uint32_t pType,
-                       uint32_t pFlag,
-                       uint64_t pOffset,
-                       uint64_t pVaddr,
-                       uint64_t pPaddr,
-                       uint64_t pFilesz,
-                       uint64_t pMemsz,
-                       uint64_t pAlign,
-                       uint64_t pMaxSectAlign)
+//===----------------------------------------------------------------------===//
+ELFSegment::ELFSegment()
+  : m_Type(llvm::ELF::PT_NULL),
+    m_Flag(llvm::ELF::PF_R),
+    m_Offset(0x0),
+    m_Vaddr(0x0),
+    m_Paddr(0x0),
+    m_Filesz(0x0),
+    m_Memsz(0x0),
+    m_Align(0x0),
+    m_MaxSectionAlign(0x0)
+{
+}
+
+ELFSegment::ELFSegment(uint32_t pType, uint32_t pFlag)
   : m_Type(pType),
     m_Flag(pFlag),
-    m_Offset(pOffset),
-    m_Vaddr(pVaddr),
-    m_Paddr(pPaddr),
-    m_Filesz(pFilesz),
-    m_Memsz(pMemsz),
-    m_Align(pAlign),
-    m_MaxSectionAlign(pMaxSectAlign) {
+    m_Offset(0x0),
+    m_Vaddr(0x0),
+    m_Paddr(0x0),
+    m_Filesz(0x0),
+    m_Memsz(0x0),
+    m_Align(0x0),
+    m_MaxSectionAlign(0x0)
+{
 }
 
 ELFSegment::~ELFSegment()
 {
 }
 
+bool ELFSegment::isLoadSegment() const
+{
+  return type() == llvm::ELF::PT_LOAD;
+}
+
 bool ELFSegment::isDataSegment() const
 {
-  bool result = false;
-  if ((type() == llvm::ELF::PT_LOAD) && (flag() & llvm::ELF::PF_W) != 0x0) {
-    for (const_sect_iterator it = begin(), ie = end(); it != ie; ++it) {
-      if ((*it)->kind() != LDFileFormat::BSS) {
-        result = true;
-        break;
-      }
-    }
-  }
-  return result;
+  return (type() == llvm::ELF::PT_LOAD) && ((flag() & llvm::ELF::PF_W) != 0x0);
 }
 
 bool ELFSegment::isBssSegment() const
 {
-  bool result = false;
-  if ((type() == llvm::ELF::PT_LOAD) && (flag() & llvm::ELF::PF_W) != 0x0) {
-    const_sect_iterator it = begin(), ie = end();
-    for (; it != ie; ++it) {
-      if ((*it)->kind() != LDFileFormat::BSS)
-        break;
-    }
-    if (it == ie)
-      result = true;
+  if (!isDataSegment())
+    return false;
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+    if ((*it)->kind() != LDFileFormat::BSS)
+      return false;
   }
-  return result;
+  return true;
 }
 
+ELFSegment::iterator ELFSegment::insert(ELFSegment::iterator pPos,
+                                        LDSection* pSection)
+{
+  return m_SectionList.insert(pPos, pSection);
+}
+
+void ELFSegment::append(LDSection* pSection)
+{
+  assert(NULL != pSection);
+  if (pSection->align() > m_MaxSectionAlign)
+    m_MaxSectionAlign = pSection->align();
+  m_SectionList.push_back(pSection);
+}
+
+ELFSegment* ELFSegment::Create(uint32_t pType, uint32_t pFlag)
+{
+  ELFSegment* seg = g_ELFSegmentFactory->allocate();
+  new (seg) ELFSegment(pType, pFlag);
+  return seg;
+}
+
+void ELFSegment::Destroy(ELFSegment*& pSegment)
+{
+  g_ELFSegmentFactory->destroy(pSegment);
+  g_ELFSegmentFactory->deallocate(pSegment);
+  pSegment = NULL;
+}
+
+void ELFSegment::Clear()
+{
+  g_ELFSegmentFactory->clear();
+}
diff --git a/lib/LD/ELFSegmentFactory.cpp b/lib/LD/ELFSegmentFactory.cpp
index af0f588..4d06629 100644
--- a/lib/LD/ELFSegmentFactory.cpp
+++ b/lib/LD/ELFSegmentFactory.cpp
@@ -7,58 +7,83 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/ELFSegment.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // ELFSegmentFactory
+//===----------------------------------------------------------------------===//
 
-ELFSegmentFactory::ELFSegmentFactory(size_t pNum)
-  : GCFactory<ELFSegment, 0>(pNum)
-{
-}
-
-ELFSegmentFactory::~ELFSegmentFactory()
-{
-}
-
-/// produce - produce an empty ELF segment information.
-/// this function will create an ELF segment
-/// @param pType - p_type in ELF program header
-ELFSegment* ELFSegmentFactory::produce(uint32_t pType, uint32_t pFlag)
-{
-  ELFSegment* segment = allocate();
-  new (segment) ELFSegment(pType, pFlag);
-  return segment;
-}
-
-ELFSegment*
+ELFSegmentFactory::iterator
 ELFSegmentFactory::find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear)
 {
   iterator segment, segEnd = end();
   for (segment = begin(); segment != segEnd; ++segment) {
-    if ((*segment).type() == pType &&
-        ((*segment).flag() & pFlagSet) == pFlagSet &&
-        ((*segment).flag() & pFlagClear) == 0x0) {
-      return &(*segment);
+    if ((*segment)->type() == pType &&
+        ((*segment)->flag() & pFlagSet) == pFlagSet &&
+        ((*segment)->flag() & pFlagClear) == 0x0) {
+      return segment;
     }
   }
-  return NULL;
+  return segEnd;
 }
 
-const ELFSegment*
+ELFSegmentFactory::const_iterator
 ELFSegmentFactory::find(uint32_t pType,
                         uint32_t pFlagSet,
                         uint32_t pFlagClear) const
 {
   const_iterator segment, segEnd = end();
   for (segment = begin(); segment != segEnd; ++segment) {
-    if ((*segment).type() == pType &&
-        ((*segment).flag() & pFlagSet) == pFlagSet &&
-        ((*segment).flag() & pFlagClear) == 0x0) {
-      return &(*segment);
+    if ((*segment)->type() == pType &&
+        ((*segment)->flag() & pFlagSet) == pFlagSet &&
+        ((*segment)->flag() & pFlagClear) == 0x0) {
+      return segment;
     }
   }
-  return NULL;
+  return segEnd;
 }
 
+ELFSegmentFactory::iterator
+ELFSegmentFactory::find(uint32_t pType, const LDSection* pSection)
+{
+  iterator segment, segEnd = end();
+  for (segment = begin(); segment != segEnd; ++segment) {
+    if ((*segment)->type() == pType) {
+      ELFSegment::iterator sect, sectEnd = (*segment)->end();
+      for (sect = (*segment)->begin(); sect != sectEnd; ++sect) {
+        if (*sect == pSection)
+          return segment;
+      } // for each section
+    }
+  } // for each segment
+  return segEnd;
+}
+
+ELFSegmentFactory::const_iterator
+ELFSegmentFactory::find(uint32_t pType, const LDSection* pSection) const
+{
+  const_iterator segment, segEnd = end();
+  for (segment = begin(); segment != segEnd; ++segment) {
+    if ((*segment)->type() == pType) {
+      ELFSegment::const_iterator sect, sectEnd = (*segment)->end();
+      for (sect = (*segment)->begin(); sect != sectEnd; ++sect) {
+        if (*sect == pSection)
+          return segment;
+      } // for each section
+    }
+  } // for each segment
+  return segEnd;
+}
+
+ELFSegment* ELFSegmentFactory::produce(uint32_t pType, uint32_t pFlag)
+{
+  m_Segments.push_back(ELFSegment::Create(pType, pFlag));
+  return back();
+}
+
+void ELFSegmentFactory::erase(iterator pSegment)
+{
+  m_Segments.erase(pSegment);
+}
diff --git a/lib/LD/EhFrame.cpp b/lib/LD/EhFrame.cpp
index 0bd6511..5ac3e72 100644
--- a/lib/LD/EhFrame.cpp
+++ b/lib/LD/EhFrame.cpp
@@ -6,11 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/Fragment/Relocation.h>
 #include <mcld/LD/EhFrame.h>
+#include <mcld/LD/LDContext.h>
 #include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/SectionData.h>
+#include <mcld/MC/Input.h>
 #include <mcld/Object/ObjectBuilder.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/GCFactory.h>
 
 #include <llvm/Support/ManagedStatic.h>
@@ -22,21 +27,66 @@
 static llvm::ManagedStatic<EhFrameFactory> g_EhFrameFactory;
 
 //===----------------------------------------------------------------------===//
+// EhFrame::Record
+//===----------------------------------------------------------------------===//
+EhFrame::Record::Record(llvm::StringRef pRegion)
+  : RegionFragment(pRegion) {
+}
+
+EhFrame::Record::~Record()
+{
+  // llvm::iplist will manage and delete the fragments
+}
+
+//===----------------------------------------------------------------------===//
 // EhFrame::CIE
 //===----------------------------------------------------------------------===//
-EhFrame::CIE::CIE(MemoryRegion& pRegion)
-  : RegionFragment(pRegion) {
+EhFrame::CIE::CIE(llvm::StringRef pRegion)
+  : EhFrame::Record(pRegion),
+    m_FDEEncode(0u), m_Mergeable(false), m_pReloc(0), m_PersonalityOffset(0) {
+}
+
+EhFrame::CIE::~CIE()
+{
 }
 
 //===----------------------------------------------------------------------===//
 // EhFrame::FDE
 //===----------------------------------------------------------------------===//
-EhFrame::FDE::FDE(MemoryRegion& pRegion,
-                  const EhFrame::CIE& pCIE,
-                  uint32_t pDataStart)
-  : RegionFragment(pRegion),
-    m_CIE(pCIE),
-    m_DataStart(pDataStart) {
+EhFrame::FDE::FDE(llvm::StringRef pRegion, EhFrame::CIE& pCIE)
+  : EhFrame::Record(pRegion), m_pCIE(&pCIE) {
+}
+
+EhFrame::FDE::~FDE()
+{
+}
+
+void EhFrame::FDE::setCIE(EhFrame::CIE& pCIE)
+{
+  m_pCIE = &pCIE;
+  m_pCIE->add(*this);
+}
+
+//===----------------------------------------------------------------------===//
+// EhFrame::GeneratedCIE
+//===----------------------------------------------------------------------===//
+EhFrame::GeneratedCIE::GeneratedCIE(llvm::StringRef pRegion)
+  : EhFrame::CIE(pRegion) {
+}
+
+EhFrame::GeneratedCIE::~GeneratedCIE()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// EhFrame::GeneratedFDE
+//===----------------------------------------------------------------------===//
+EhFrame::GeneratedFDE::GeneratedFDE(llvm::StringRef pRegion, CIE &pCIE)
+  : EhFrame::FDE(pRegion, pCIE) {
+}
+
+EhFrame::GeneratedFDE::~GeneratedFDE()
+{
 }
 
 //===----------------------------------------------------------------------===//
@@ -54,8 +104,6 @@
 
 EhFrame::~EhFrame()
 {
-  // Since all CIEs, FDEs and regular fragments are stored in iplist, iplist
-  // will delete the fragments and we do not need to handle with it.
 }
 
 EhFrame* EhFrame::Create(LDSection& pSection)
@@ -89,52 +137,247 @@
   return *m_pSection;
 }
 
-void EhFrame::addFragment(RegionFragment& pFrag)
+void EhFrame::addFragment(Fragment& pFrag)
 {
   uint32_t offset = 0;
   if (!m_pSectionData->empty())
     offset = m_pSectionData->back().getOffset() + m_pSectionData->back().size();
 
   m_pSectionData->getFragmentList().push_back(&pFrag);
+  pFrag.setParent(m_pSectionData);
   pFrag.setOffset(offset);
 }
 
-void EhFrame::addFragment(NullFragment& pFrag)
-{
-  uint32_t offset = 0;
-  if (!m_pSectionData->empty())
-    offset = m_pSectionData->back().getOffset() + m_pSectionData->back().size();
-
-  m_pSectionData->getFragmentList().push_back(&pFrag);
-  pFrag.setOffset(offset);
-}
-
-void EhFrame::addCIE(EhFrame::CIE& pCIE)
+void EhFrame::addCIE(EhFrame::CIE& pCIE, bool pAlsoAddFragment)
 {
   m_CIEs.push_back(&pCIE);
-  addFragment(pCIE);
+  if (pAlsoAddFragment)
+    addFragment(pCIE);
 }
 
-void EhFrame::addFDE(EhFrame::FDE& pFDE)
+void EhFrame::addFDE(EhFrame::FDE& pFDE, bool pAlsoAddFragment)
 {
-  m_FDEs.push_back(&pFDE);
-  addFragment(pFDE);
+  pFDE.getCIE().add(pFDE);
+  if (pAlsoAddFragment)
+    addFragment(pFDE);
 }
 
-EhFrame& EhFrame::merge(EhFrame& pOther)
+size_t EhFrame::numOfFDEs() const
 {
-  ObjectBuilder::MoveSectionData(*pOther.getSectionData(), *m_pSectionData);
+  // FDE number only used by .eh_frame_hdr computation, and the number of CIE
+  // is usually not too many. It is worthy to compromise space by time
+  size_t size = 0u;
+  for (const_cie_iterator i = cie_begin(), e = cie_end(); i != e; ++i)
+    size += (*i)->numOfFDEs();
+  return size;
+}
 
-  m_CIEs.reserve(pOther.numOfCIEs() + m_CIEs.size());
-  for (cie_iterator cie = pOther.cie_begin(); cie != pOther.cie_end(); ++cie)
-    m_CIEs.push_back(*cie);
+EhFrame& EhFrame::merge(const Input& pInput, EhFrame& pFrame)
+{
+  assert (this != &pFrame);
+  if (pFrame.emptyCIEs()) {
+    // May be a partial linking, or the eh_frame has no data.
+    // Just append the fragments.
+    moveInputFragments(pFrame);
+    return *this;
+  }
 
-  m_FDEs.reserve(pOther.numOfFDEs() + m_FDEs.size());
-  for (fde_iterator fde = pOther.fde_begin(); fde != pOther.fde_end(); ++fde)
-    m_FDEs.push_back(*fde);
+  const LDContext& ctx = *pInput.context();
+  const LDSection* rel_sec = 0;
+  for (LDContext::const_sect_iterator ri = ctx.relocSectBegin(),
+       re = ctx.relocSectEnd(); ri != re; ++ri) {
+    if ((*ri)->getLink() == &pFrame.getSection()) {
+      rel_sec = *ri;
+      break;
+    }
+  }
+  pFrame.setupAttributes(rel_sec);
 
-  pOther.m_CIEs.clear();
-  pOther.m_FDEs.clear();
+  // Most CIE will be merged, so we don't reserve space first.
+  for (cie_iterator i = pFrame.cie_begin(), e = pFrame.cie_end(); i != e; ++i) {
+    CIE& input_cie = **i;
+    // CIE number is usually very few, so we just use vector sequential search.
+    if (!input_cie.getMergeable()) {
+      moveInputFragments(pFrame, input_cie);
+      addCIE(input_cie, /*AlsoAddFragment=*/false);
+      continue;
+    }
+
+    cie_iterator out_i = cie_begin();
+    for (cie_iterator out_e = cie_end(); out_i != out_e; ++out_i) {
+      CIE& output_cie = **out_i;
+      if (output_cie == input_cie) {
+        // This input CIE can be merged
+        moveInputFragments(pFrame, input_cie, &output_cie);
+        removeAndUpdateCIEForFDE(pFrame, input_cie, output_cie, rel_sec);
+        break;
+      }
+    }
+    if (out_i == cie_end()) {
+      moveInputFragments(pFrame, input_cie);
+      addCIE(input_cie, /*AlsoAddFragment=*/false);
+    }
+  }
   return *this;
 }
 
+void EhFrame::setupAttributes(const LDSection* rel_sec)
+{
+  for (cie_iterator i = cie_begin(), e = cie_end(); i != e; ++i) {
+    CIE* cie = *i;
+    removeDiscardedFDE(*cie, rel_sec);
+
+    if (cie->getPersonalityName().size() == 0) {
+      // There's no personality data encoding inside augmentation string.
+      cie->setMergeable();
+    } else {
+      if (!rel_sec) {
+        // No relocation to eh_frame section
+        assert (cie->getPersonalityName() != "" &&
+                "PR name should be a symbol address or offset");
+        continue;
+      }
+      const RelocData* reloc_data = rel_sec->getRelocData();
+      for (RelocData::const_iterator ri = reloc_data->begin(),
+           re = reloc_data->end(); ri != re; ++ri) {
+        const Relocation& rel = *ri;
+        if (rel.targetRef().getOutputOffset() == cie->getOffset() +
+                                                 cie->getPersonalityOffset()) {
+          cie->setMergeable();
+          cie->setPersonalityName(rel.symInfo()->outSymbol()->name());
+          cie->setRelocation(rel);
+          break;
+        }
+      }
+
+      assert (cie->getPersonalityName() != "" &&
+              "PR name should be a symbol address or offset");
+    }
+  }
+}
+
+void EhFrame::removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocSect)
+{
+  if (!pRelocSect)
+    return;
+
+  typedef std::vector<FDE*> FDERemoveList;
+  FDERemoveList to_be_removed_fdes;
+  const RelocData* reloc_data = pRelocSect->getRelocData();
+  for (fde_iterator i = pCIE.begin(), e = pCIE.end(); i != e; ++i) {
+    FDE& fde = **i;
+    for (RelocData::const_iterator ri = reloc_data->begin(),
+         re = reloc_data->end(); ri != re; ++ri) {
+      const Relocation& rel = *ri;
+      if (rel.targetRef().getOutputOffset() == fde.getOffset() +
+                                               getDataStartOffset<32>()) {
+        bool has_section = rel.symInfo()->outSymbol()->hasFragRef();
+        if (!has_section)
+          // The section was discarded, just ignore this FDE.
+          // This may happen when redundant group section was read.
+          to_be_removed_fdes.push_back(&fde);
+        break;
+      }
+    }
+  }
+
+  for (FDERemoveList::iterator i = to_be_removed_fdes.begin(),
+       e = to_be_removed_fdes.end(); i != e; ++i) {
+    FDE& fde = **i;
+    fde.getCIE().remove(fde);
+
+    // FIXME: This traverses relocations from the beginning on each FDE, which
+    // may cause performance degration. Actually relocations will be sequential
+    // order, so we can bookkeep the previously found relocation for next use.
+    // Note: We must ensure FDE order is ordered.
+    for (RelocData::const_iterator ri = reloc_data->begin(),
+         re = reloc_data->end(); ri != re; ) {
+      Relocation& rel = const_cast<Relocation&>(*ri++);
+      if (rel.targetRef().getOutputOffset() >= fde.getOffset() &&
+          rel.targetRef().getOutputOffset() < fde.getOffset() + fde.size()) {
+        const_cast<RelocData*>(reloc_data)->remove(rel);
+      }
+    }
+  }
+}
+
+void EhFrame::removeAndUpdateCIEForFDE(EhFrame& pInFrame, CIE& pInCIE,
+                                       CIE& pOutCIE, const LDSection* rel_sect)
+{
+  // Make this relocation to be ignored.
+  Relocation* rel = const_cast<Relocation*>(pInCIE.getRelocation());
+  if (rel && rel_sect)
+    const_cast<RelocData*>(rel_sect->getRelocData())->remove(*rel);
+
+  // Update the CIE-pointed FDEs
+  for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i)
+    (*i)->setCIE(pOutCIE);
+
+  // We cannot know whether there are references to this fragment, so just
+  // keep it in input fragment list instead of memory deallocation
+  pInCIE.clearFDEs();
+}
+
+void EhFrame::moveInputFragments(EhFrame& pInFrame)
+{
+  SectionData& in_sd = *pInFrame.getSectionData();
+  SectionData::FragmentListType& in_frag_list = in_sd.getFragmentList();
+  SectionData& out_sd = *getSectionData();
+  SectionData::FragmentListType& out_frag_list = out_sd.getFragmentList();
+
+  while (!in_frag_list.empty()) {
+    Fragment* frag = in_frag_list.remove(in_frag_list.begin());
+    out_frag_list.push_back(frag);
+    frag->setParent(&out_sd);
+  }
+}
+
+void EhFrame::moveInputFragments(EhFrame& pInFrame,
+                                 CIE& pInCIE, CIE* pOutCIE)
+{
+  SectionData& in_sd = *pInFrame.getSectionData();
+  SectionData::FragmentListType& in_frag_list = in_sd.getFragmentList();
+  SectionData& out_sd = *getSectionData();
+  SectionData::FragmentListType& out_frag_list = out_sd.getFragmentList();
+
+  if (!pOutCIE) {
+    // Newly inserted
+    Fragment* frag = in_frag_list.remove(SectionData::iterator(pInCIE));
+    out_frag_list.push_back(frag);
+    frag->setParent(&out_sd);
+    for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) {
+      frag = in_frag_list.remove(SectionData::iterator(**i));
+      out_frag_list.push_back(frag);
+      frag->setParent(&out_sd);
+    }
+    return;
+  }
+
+  SectionData::iterator cur_iter(*pOutCIE);
+  assert (cur_iter != out_frag_list.end());
+  for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) {
+    Fragment* frag = in_frag_list.remove(SectionData::iterator(**i));
+    cur_iter = out_frag_list.insertAfter(cur_iter, frag);
+    frag->setParent(&out_sd);
+  }
+}
+
+size_t EhFrame::computeOffsetSize()
+{
+  size_t offset = 0u;
+  SectionData::FragmentListType& frag_list = getSectionData()->getFragmentList();
+  for (SectionData::iterator i = frag_list.begin(), e = frag_list.end();
+       i != e; ++i) {
+    Fragment& frag = *i;
+    frag.setOffset(offset);
+    offset += frag.size();
+  }
+  getSection().setSize(offset);
+  return offset;
+}
+
+bool mcld::operator==(const EhFrame::CIE& p1, const EhFrame::CIE& p2)
+{
+  return p1.getPersonalityName() == p2.getPersonalityName() &&
+         p1.getAugmentationData() == p2.getAugmentationData();
+}
diff --git a/lib/LD/EhFrameHdr.cpp b/lib/LD/EhFrameHdr.cpp
index 89b828f..74516d1 100644
--- a/lib/LD/EhFrameHdr.cpp
+++ b/lib/LD/EhFrameHdr.cpp
@@ -8,8 +8,6 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/EhFrameHdr.h>
 
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/LD/EhFrame.h>
 #include <mcld/LD/LDSection.h>
 
@@ -39,16 +37,15 @@
 //===----------------------------------------------------------------------===//
 /// emitOutput<32> - write out eh_frame_hdr
 template<>
-void EhFrameHdr::emitOutput<32>(MemoryArea& pOutput)
+void EhFrameHdr::emitOutput<32>(FileOutputBuffer& pOutput)
 {
-  MemoryRegion* ehframehdr_region =
-    pOutput.request(m_EhFrameHdr.offset(), m_EhFrameHdr.size());
+  MemoryRegion ehframehdr_region = pOutput.request(m_EhFrameHdr.offset(),
+                                                   m_EhFrameHdr.size());
 
-  MemoryRegion* ehframe_region =
-    pOutput.request(m_EhFrame.offset(),
-                    m_EhFrame.size());
+  MemoryRegion ehframe_region = pOutput.request(m_EhFrame.offset(),
+                                                m_EhFrame.size());
 
-  uint8_t* data = (uint8_t*)ehframehdr_region->start();
+  uint8_t* data = ehframehdr_region.begin();
   // version
   data[0] = 1;
   // eh_frame_ptr_enc
@@ -80,16 +77,21 @@
     // prepare the binary search table
     typedef std::vector<bit32::Entry> SearchTableType;
     SearchTableType search_table;
-    EhFrame::const_fde_iterator fde, fde_end = m_EhFrame.getEhFrame()->fde_end();
-    for(fde = m_EhFrame.getEhFrame()->fde_begin(); fde != fde_end; ++fde) {
-      assert(*fde != NULL);
-      SizeTraits<32>::Offset offset;
-      SizeTraits<32>::Address fde_pc;
-      SizeTraits<32>::Address fde_addr;
-      offset = (*fde)->getOffset();
-      fde_pc = computePCBegin(**fde, *ehframe_region);
-      fde_addr = m_EhFrame.addr() + offset;
-      search_table.push_back(std::make_pair(fde_pc, fde_addr));
+
+    for (EhFrame::const_cie_iterator i = m_EhFrame.getEhFrame()->cie_begin(),
+         e = m_EhFrame.getEhFrame()->cie_end(); i != e; ++i) {
+      EhFrame::CIE& cie = **i;
+      for (EhFrame::const_fde_iterator fi = cie.begin(), fe = cie.end();
+           fi != fe; ++fi) {
+        EhFrame::FDE& fde = **fi;
+        SizeTraits<32>::Offset offset;
+        SizeTraits<32>::Address fde_pc;
+        SizeTraits<32>::Address fde_addr;
+        offset = fde.getOffset();
+        fde_pc = computePCBegin(fde, ehframe_region);
+        fde_addr = m_EhFrame.addr() + offset;
+        search_table.push_back(std::make_pair(fde_pc, fde_addr));
+      }
     }
 
     std::sort(search_table.begin(), search_table.end(), bit32::EntryCompare);
@@ -103,8 +105,6 @@
       bst[id++] = (*entry).second - m_EhFrameHdr.addr();
     }
   }
-  pOutput.release(ehframehdr_region);
-  pOutput.release(ehframe_region);
 }
 
 //===----------------------------------------------------------------------===//
@@ -168,9 +168,9 @@
   }
 
   SizeTraits<32>::Address pc = 0x0;
-  const uint8_t* offset = (const uint8_t*) pEhFrameRegion.start() +
+  const uint8_t* offset = (const uint8_t*) pEhFrameRegion.begin() +
                           pFDE.getOffset() +
-                          pFDE.getDataStart();
+                          EhFrame::getDataStartOffset<32>();
   std::memcpy(&pc, offset, pc_size);
 
   // adjust the signed value
@@ -184,7 +184,8 @@
     case DW_EH_PE_absptr:
       break;
     case DW_EH_PE_pcrel:
-      pc += m_EhFrame.addr() + pFDE.getOffset() + pFDE.getDataStart();
+      pc += m_EhFrame.addr() + pFDE.getOffset() +
+                               EhFrame::getDataStartOffset<32>();
       break;
     case DW_EH_PE_datarel:
       // TODO
diff --git a/lib/LD/EhFrameReader.cpp b/lib/LD/EhFrameReader.cpp
index 69a7a05..49950a0 100644
--- a/lib/LD/EhFrameReader.cpp
+++ b/lib/LD/EhFrameReader.cpp
@@ -8,14 +8,15 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/EhFrameReader.h>
 
+#include <mcld/Fragment/NullFragment.h>
+#include <mcld/MC/Input.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/MemoryArea.h>
+
 #include <llvm/ADT/StringRef.h>
 #include <llvm/Support/Dwarf.h>
-
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MsgHandling.h>
+#include <llvm/Support/LEB128.h>
 
 using namespace mcld;
 using namespace llvm::dwarf;
@@ -45,7 +46,7 @@
 template<> EhFrameReader::Token
 EhFrameReader::scan<true>(ConstAddress pHandler,
                           uint64_t pOffset,
-                          const MemoryRegion& pData) const
+                          llvm::StringRef pData) const
 {
   Token result;
   result.file_off = pOffset;
@@ -71,6 +72,8 @@
     extended |= data[cur_idx++];
     result.size = extended + 12;
     result.data_off = 16;
+    // 64-bit obj file still uses 32-bit eh_frame.
+    assert (false && "We don't support 64-bit eh_frame.");
   }
   else {
     result.size = length + 4;
@@ -129,17 +132,17 @@
 
   // get file offset and address
   uint64_t file_off = pInput.fileOffset() + section.offset();
-  MemoryRegion* sect_reg =
-                       pInput.memArea()->request(file_off, section.size());
-  ConstAddress handler = (ConstAddress)sect_reg->start();
+  llvm::StringRef sect_reg =
+      pInput.memArea()->request(file_off, section.size());
+  ConstAddress handler = (ConstAddress)sect_reg.begin();
 
   State cur_state = Q0;
   while (Reject != cur_state && Accept != cur_state) {
 
-    Token token = scan<true>(handler, file_off, *sect_reg);
-    MemoryRegion* entry = pInput.memArea()->request(token.file_off, token.size);
+    Token token = scan<true>(handler, file_off, sect_reg);
+    llvm::StringRef entry = pInput.memArea()->request(token.file_off, token.size);
 
-    if (!transition[cur_state][token.kind](pEhFrame, *entry, token)) {
+    if (!transition[cur_state][token.kind](pEhFrame, entry, token)) {
       // fail to scan
       debug(diag::debug_cannot_scan_eh) << pInput.name();
       return false;
@@ -148,9 +151,9 @@
     file_off += token.size;
     handler += token.size;
 
-    if (handler == sect_reg->end())
+    if (handler == sect_reg.end())
       cur_state = Accept;
-    else if (handler > sect_reg->end()) {
+    else if (handler > sect_reg.end()) {
       cur_state = Reject;
     }
     else
@@ -166,12 +169,14 @@
 }
 
 bool EhFrameReader::addCIE(EhFrame& pEhFrame,
-                           MemoryRegion& pRegion,
+                           llvm::StringRef pRegion,
                            const EhFrameReader::Token& pToken)
 {
   // skip Length, Extended Length and CIE ID.
-  ConstAddress handler = pRegion.start() + pToken.data_off;
+  ConstAddress handler = pRegion.begin() + pToken.data_off;
   ConstAddress cie_end = pRegion.end();
+  ConstAddress handler_start = handler;
+  uint64_t pr_ptr_data_offset = pToken.data_off;
 
   // the version should be 1 or 3
   uint8_t version = *handler++;
@@ -211,6 +216,7 @@
     EhFrame::CIE* cie = new EhFrame::CIE(pRegion);
     cie->setFDEEncode(llvm::dwarf::DW_EH_PE_absptr);
     pEhFrame.addCIE(*cie);
+    pEhFrame.getCIEMap().insert(std::make_pair(pToken.file_off, cie));
     return true;
   }
 
@@ -222,12 +228,13 @@
 
   // parse the Augmentation String to get the FDE encodeing if 'z' existed
   uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr;
+  std::string augdata;
+  std::string pr_ptr_data;
   if ('z' == augment[0]) {
-
-    // skip the Augumentation Data Length
-    if (!skip_LEB128(&handler, cie_end)) {
-      return false;
-    }
+    unsigned offset;
+    size_t augdata_size = llvm::decodeULEB128((const uint8_t*)handler, &offset);
+    handler += offset;
+    augdata = std::string((const char*)handler, augdata_size);
 
     // parse the Augmentation String
     for (size_t i = 1; i < augment.size(); ++i) {
@@ -285,6 +292,8 @@
           if (static_cast<uint32_t>(cie_end - handler) < per_length) {
             return false;
           }
+          pr_ptr_data_offset += handler - handler_start;
+          pr_ptr_data = std::string((const char*)handler, per_length);
           handler += per_length;
           break;
         } // end of case 'P'
@@ -316,38 +325,46 @@
   // create and push back the CIE entry
   EhFrame::CIE* cie = new EhFrame::CIE(pRegion);
   cie->setFDEEncode(fde_encoding);
+  cie->setPersonalityOffset(pr_ptr_data_offset);
+  cie->setPersonalityName(pr_ptr_data);
+  cie->setAugmentationData(augdata);
   pEhFrame.addCIE(*cie);
+  pEhFrame.getCIEMap().insert(std::make_pair(pToken.file_off, cie));
   return true;
 }
 
 bool EhFrameReader::addFDE(EhFrame& pEhFrame,
-                           MemoryRegion& pRegion,
+                           llvm::StringRef pRegion,
                            const EhFrameReader::Token& pToken)
 {
   if (pToken.data_off == pRegion.size())
     return false;
 
+  const int32_t offset = *(const int32_t*) (pRegion.begin() + pToken.data_off
+                                            - 4);
+  size_t cie_offset = (size_t) ((int64_t) (pToken.file_off + 4) -
+                                (int32_t) offset);
+
+  EhFrame::CIEMap::iterator iter = pEhFrame.getCIEMap().find(cie_offset);
+  if (iter == pEhFrame.getCIEMap().end())
+    return false;
+
   // create and push back the FDE entry
-  EhFrame::FDE* fde = new EhFrame::FDE(pRegion,
-                                       pEhFrame.cie_back(),
-                                       pToken.data_off);
+  EhFrame::FDE* fde = new EhFrame::FDE(pRegion, *iter->second);
   pEhFrame.addFDE(*fde);
   return true;
 }
 
 bool EhFrameReader::addTerm(EhFrame& pEhFrame,
-                            MemoryRegion& pRegion,
+                            llvm::StringRef pRegion,
                             const EhFrameReader::Token& pToken)
 {
-  RegionFragment* frag = new RegionFragment(pRegion);
-  pEhFrame.addFragment(*frag);
   return true;
 }
 
 bool EhFrameReader::reject(EhFrame& pEhFrame,
-                           MemoryRegion& pRegion,
+                           llvm::StringRef pRegion,
                            const EhFrameReader::Token& pToken)
 {
   return true;
 }
-
diff --git a/lib/LD/GNUArchiveReader.cpp b/lib/LD/GNUArchiveReader.cpp
index e391b20..3dc95a5 100644
--- a/lib/LD/GNUArchiveReader.cpp
+++ b/lib/LD/GNUArchiveReader.cpp
@@ -10,14 +10,14 @@
 
 #include <mcld/Module.h>
 #include <mcld/InputTree.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/MC/Attribute.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/ELFObjectReader.h>
 #include <mcld/Support/FileSystem.h>
 #include <mcld/Support/FileHandle.h>
 #include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/Path.h>
 #include <mcld/ADT/SizeTraits.h>
@@ -42,19 +42,22 @@
 }
 
 /// isMyFormat
-bool GNUArchiveReader::isMyFormat(Input& pInput) const
+bool GNUArchiveReader::isMyFormat(Input& pInput, bool &pContinue) const
 {
   assert(pInput.hasMemArea());
-  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
-                                                   Archive::MAGIC_LEN);
-  const char* str = reinterpret_cast<const char*>(region->getBuffer());
+  if (pInput.memArea()->size() < Archive::MAGIC_LEN)
+    return false;
+
+  llvm::StringRef region =
+      pInput.memArea()->request(pInput.fileOffset(), Archive::MAGIC_LEN);
+  const char* str = region.begin();
 
   bool result = false;
   assert(NULL != str);
+  pContinue = true;
   if (isArchive(str) || isThinArchive(str))
     result = true;
 
-  pInput.memArea()->release(region);
   return result;
 }
 
@@ -74,27 +77,27 @@
 bool GNUArchiveReader::isThinArchive(Input& pInput) const
 {
   assert(pInput.hasMemArea());
-  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
-                                                   Archive::MAGIC_LEN);
-  const char* str = reinterpret_cast<const char*>(region->getBuffer());
+  llvm::StringRef region =
+      pInput.memArea()->request(pInput.fileOffset(), Archive::MAGIC_LEN);
+  const char* str = region.begin();
 
   bool result = false;
   assert(NULL != str);
   if (isThinArchive(str))
     result = true;
 
-  pInput.memArea()->release(region);
   return result;
 }
 
-bool GNUArchiveReader::readArchive(Archive& pArchive)
+bool GNUArchiveReader::readArchive(const LinkerConfig& pConfig,
+                                   Archive& pArchive)
 {
   // bypass the empty archive
-  if (Archive::MAGIC_LEN == pArchive.getARFile().memArea()->handler()->size())
+  if (Archive::MAGIC_LEN == pArchive.getARFile().memArea()->size())
     return true;
 
   if (pArchive.getARFile().attribute()->isWholeArchive())
-    return includeAllMembers(pArchive);
+    return includeAllMembers(pConfig, pArchive);
 
   // if this is the first time read this archive, setup symtab and strtab
   if (pArchive.getSymbolTable().empty()) {
@@ -133,7 +136,7 @@
 
       if (Archive::Symbol::Include == status) {
         // include the object member from the given offset
-        includeMember(pArchive, pArchive.getObjFileOffset(idx));
+        includeMember(pConfig, pArchive, pArchive.getObjFileOffset(idx));
         willSymResolved = true;
       } // end of if
     } // end of for
@@ -159,11 +162,11 @@
 {
   assert(pArchiveFile.hasMemArea());
 
-  MemoryRegion* header_region =
+  llvm::StringRef header_region =
     pArchiveFile.memArea()->request((pArchiveFile.fileOffset() + pFileOffset),
                                     sizeof(Archive::MemberHeader));
   const Archive::MemberHeader* header =
-    reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
+    reinterpret_cast<const Archive::MemberHeader*>(header_region.begin());
 
   assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
 
@@ -233,59 +236,71 @@
                                         input_path);
   }
 
-  pArchiveFile.memArea()->release(header_region);
   return member;
 }
 
+template <size_t SIZE>
+static void readSymbolTableEntries(Archive& pArchive, llvm::StringRef pMemRegion)
+{
+  typedef typename SizeTraits<SIZE>::Offset Offset;
+
+  const Offset* data = reinterpret_cast<const Offset*>(pMemRegion.begin());
+
+  // read the number of symbols
+  Offset number = 0;
+  if (llvm::sys::IsLittleEndianHost)
+    number = mcld::bswap<SIZE>(*data);
+  else
+    number = *data;
+
+  // set up the pointers for file offset and name offset
+  ++data;
+  const char* name = reinterpret_cast<const char*>(data + number);
+
+  // add the archive symbols
+  for (Offset i = 0; i < number; ++i) {
+    if (llvm::sys::IsLittleEndianHost)
+      pArchive.addSymbol(name, mcld::bswap<SIZE>(*data));
+    else
+      pArchive.addSymbol(name, *data);
+    name += strlen(name) + 1;
+    ++data;
+  }
+}
+
 /// readSymbolTable - read the archive symbol map (armap)
 bool GNUArchiveReader::readSymbolTable(Archive& pArchive)
 {
   assert(pArchive.getARFile().hasMemArea());
 
-  MemoryRegion* header_region =
+  llvm::StringRef header_region =
     pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
                                              Archive::MAGIC_LEN),
                                             sizeof(Archive::MemberHeader));
   const Archive::MemberHeader* header =
-    reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
+    reinterpret_cast<const Archive::MemberHeader*>(header_region.begin());
   assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
 
   int symtab_size = atoi(header->size);
   pArchive.setSymTabSize(symtab_size);
 
   if (!pArchive.getARFile().attribute()->isWholeArchive()) {
-    MemoryRegion* symtab_region =
-      pArchive.getARFile().memArea()->request(
-                                            (pArchive.getARFile().fileOffset() +
-                                             Archive::MAGIC_LEN +
-                                             sizeof(Archive::MemberHeader)),
-                                            symtab_size);
-    const uint32_t* data =
-      reinterpret_cast<const uint32_t*>(symtab_region->getBuffer());
+    llvm::StringRef symtab_region = pArchive.getARFile().memArea()->request(
+        (pArchive.getARFile().fileOffset() +
+         Archive::MAGIC_LEN +
+         sizeof(Archive::MemberHeader)),
+        symtab_size);
 
-    // read the number of symbols
-    uint32_t number = 0;
-    if (llvm::sys::IsLittleEndianHost)
-      number = mcld::bswap32(*data);
+    if (0 == strncmp(header->name, Archive::SVR4_SYMTAB_NAME,
+                                   strlen(Archive::SVR4_SYMTAB_NAME)))
+      readSymbolTableEntries<32>(pArchive, symtab_region);
+    else if (0 == strncmp(header->name, Archive::IRIX6_SYMTAB_NAME,
+                                        strlen(Archive::IRIX6_SYMTAB_NAME)))
+      readSymbolTableEntries<64>(pArchive, symtab_region);
     else
-      number = *data;
+      unreachable(diag::err_unsupported_archive);
 
-    // set up the pointers for file offset and name offset
-    ++data;
-    const char* name = reinterpret_cast<const char*>(data + number);
-
-    // add the archive symbols
-    for (uint32_t i = 0; i < number; ++i) {
-      if (llvm::sys::IsLittleEndianHost)
-        pArchive.addSymbol(name, mcld::bswap32(*data));
-      else
-        pArchive.addSymbol(name, *data);
-      name += strlen(name) + 1;
-      ++data;
-    }
-    pArchive.getARFile().memArea()->release(symtab_region);
   }
-  pArchive.getARFile().memArea()->release(header_region);
   return true;
 }
 
@@ -301,29 +316,26 @@
 
   assert(pArchive.getARFile().hasMemArea());
 
-  MemoryRegion* header_region =
+  llvm::StringRef header_region =
     pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
                                              offset),
                                             sizeof(Archive::MemberHeader));
   const Archive::MemberHeader* header =
-    reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
+    reinterpret_cast<const Archive::MemberHeader*>(header_region.begin());
 
   assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
 
   if (0 == memcmp(header->name, Archive::STRTAB_NAME, sizeof(header->name))) {
     // read the extended name table
     int strtab_size = atoi(header->size);
-    MemoryRegion* strtab_region =
+    llvm::StringRef strtab_region =
       pArchive.getARFile().memArea()->request(
                                    (pArchive.getARFile().fileOffset() +
                                     offset + sizeof(Archive::MemberHeader)),
                                    strtab_size);
-    const char* strtab =
-      reinterpret_cast<const char*>(strtab_region->getBuffer());
+    const char* strtab = strtab_region.begin();
     pArchive.getStrTable().assign(strtab, strtab_size);
-    pArchive.getARFile().memArea()->release(strtab_region);
   }
-  pArchive.getARFile().memArea()->release(header_region);
   return true;
 }
 
@@ -346,9 +358,12 @@
 
 /// includeMember - include the object member in the given file offset, and
 /// return the size of the object
+/// @param pConfig - LinkerConfig
 /// @param pArchiveRoot - the archive root
 /// @param pFileOffset  - file offset of the member header in the archive
-size_t GNUArchiveReader::includeMember(Archive& pArchive, uint32_t pFileOffset)
+size_t GNUArchiveReader::includeMember(const LinkerConfig& pConfig,
+                                       Archive& pArchive,
+                                       uint32_t pFileOffset)
 {
   Input* cur_archive = &(pArchive.getARFile());
   Input* member = NULL;
@@ -382,8 +397,9 @@
     // direction to Afterward for next insertion in this subtree
     parent->move->move(parent->lastPos);
     parent->move = &InputTree::Afterward;
+    bool doContinue = false;
 
-    if (m_ELFObjectReader.isMyFormat(*member)) {
+    if (m_ELFObjectReader.isMyFormat(*member, doContinue)) {
       member->setType(Input::Object);
       pArchive.addObjectMember(pFileOffset, parent->lastPos);
       m_ELFObjectReader.readHeader(*member);
@@ -391,7 +407,7 @@
       m_ELFObjectReader.readSymbols(*member);
       m_Module.getObjectList().push_back(member);
     }
-    else if (isMyFormat(*member)) {
+    else if (doContinue && isMyFormat(*member, doContinue)) {
       member->setType(Input::Archive);
       // when adding a new archive node, set the iterator to archive
       // itself, and set the direction to Downward
@@ -401,13 +417,18 @@
       cur_archive = member;
       file_offset = nested_offset;
     }
+    else {
+      warning(diag::warn_unrecognized_input_file) << member->path()
+        << pConfig.targets().triple().str();
+    }
   } while (Input::Object != member->type());
   return size;
 }
 
 /// includeAllMembers - include all object members. This is called if
 /// --whole-archive is the attribute for this archive file.
-bool GNUArchiveReader::includeAllMembers(Archive& pArchive)
+bool GNUArchiveReader::includeAllMembers(const LinkerConfig& pConfig,
+                                         Archive& pArchive)
 {
   // read the symtab of the archive
   readSymbolTable(pArchive);
@@ -431,12 +452,12 @@
     begin_offset += sizeof(Archive::MemberHeader) +
                     pArchive.getStrTable().size();
   }
-  uint32_t end_offset = pArchive.getARFile().memArea()->handler()->size();
+  uint32_t end_offset = pArchive.getARFile().memArea()->size();
   for (uint32_t offset = begin_offset;
        offset < end_offset;
        offset += sizeof(Archive::MemberHeader)) {
 
-    size_t size = includeMember(pArchive, offset);
+    size_t size = includeMember(pConfig, pArchive, offset);
 
     if (!isThinAR) {
       offset += size;
diff --git a/lib/LD/GarbageCollection.cpp b/lib/LD/GarbageCollection.cpp
new file mode 100644
index 0000000..4ea40ac
--- /dev/null
+++ b/lib/LD/GarbageCollection.cpp
@@ -0,0 +1,343 @@
+//===- GarbageCollection.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/LD/GarbageCollection.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/LinkerScript.h>
+#include <mcld/Module.h>
+#include <mcld/Target/TargetLDBackend.h>
+
+#include <llvm/Support/Casting.h>
+
+#include <queue>
+#if !defined(MCLD_ON_WIN32)
+#include <fnmatch.h>
+#define fnmatch0(pattern,string) (fnmatch(pattern,string,0) == 0)
+#else
+#include <windows.h>
+#include <shlwapi.h>
+#define fnmatch0(pattern,string) (PathMatchSpec(string, pattern) == true)
+#endif
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Non-member functions
+//===----------------------------------------------------------------------===//
+// FIXME: these rules should be added into SectionMap, while currently adding to
+// SectionMap will cause the output order change in .text section and leads to
+// the .ARM.exidx order incorrect. We should sort the .ARM.exidx.
+static const char* pattern_to_keep[] =
+{
+  ".text*personality*",
+  ".data*personality*",
+  ".gnu.linkonce.d*personality*",
+  ".sdata*personality*"
+};
+
+/// shouldKeep - check the section name for the keep sections
+static bool shouldKeep(const std::string& pName)
+{
+  static const unsigned int pattern_size =
+                           sizeof(pattern_to_keep) / sizeof(pattern_to_keep[0]);
+  for (unsigned int i=0; i < pattern_size; ++i) {
+    if (fnmatch0(pattern_to_keep[i], pName.c_str()))
+      return true;
+  }
+  return false;
+}
+
+/// shouldProcessGC - check if the section kind is handled in GC
+static bool mayProcessGC(const LDSection& pSection)
+{
+  if (pSection.kind() == LDFileFormat::Regular ||
+      pSection.kind() == LDFileFormat::BSS ||
+      pSection.kind() == LDFileFormat::GCCExceptTable)
+    return true;
+  return false;
+}
+
+//===----------------------------------------------------------------------===//
+// GarbageCollection::SectionReachedListMap
+//===----------------------------------------------------------------------===//
+void
+GarbageCollection::SectionReachedListMap::addReference(const LDSection& pFrom,
+                                                       const LDSection& pTo)
+{
+  m_ReachedSections[&pFrom].insert(&pTo);
+}
+
+GarbageCollection::SectionListTy&
+GarbageCollection::SectionReachedListMap::getReachedList(
+                                                      const LDSection& pSection)
+{
+  return m_ReachedSections[&pSection];
+}
+
+GarbageCollection::SectionListTy*
+GarbageCollection::SectionReachedListMap::findReachedList(
+                                                      const LDSection& pSection)
+{
+  ReachedSectionsTy::iterator it = m_ReachedSections.find(&pSection);
+  if (it == m_ReachedSections.end())
+    return NULL;
+  return &it->second;
+}
+
+//===----------------------------------------------------------------------===//
+// GarbageCollection
+//===----------------------------------------------------------------------===//
+GarbageCollection::GarbageCollection(const LinkerConfig& pConfig,
+                                     const TargetLDBackend& pBackend,
+                                     Module& pModule)
+  : m_Config(pConfig), m_Backend(pBackend), m_Module(pModule)
+{
+}
+
+GarbageCollection::~GarbageCollection()
+{
+}
+
+bool GarbageCollection::run()
+{
+  // 1. traverse all the relocations to set up the reached sections of each
+  // section
+  setUpReachedSections();
+  m_Backend.setUpReachedSectionsForGC(m_Module, m_SectionReachedListMap);
+
+  // 2. get all sections defined the entry point
+  SectionVecTy entry;
+  getEntrySections(entry);
+
+  // 3. find all the referenced sections those can be reached by entry
+  findReferencedSections(entry);
+
+  // 4. stripSections - set the unreached sections to Ignore
+  stripSections();
+  return true;
+}
+
+void GarbageCollection::setUpReachedSections()
+{
+  // traverse all the input relocations to setup the reached sections
+  Module::obj_iterator input, inEnd = m_Module.obj_end();
+  for (input = m_Module.obj_begin(); input != inEnd; ++input) {
+    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+      // bypass the discarded relocation section
+      // 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)
+      LDSection* reloc_sect = *rs;
+      LDSection* apply_sect = reloc_sect->getLink();
+      if ((LDFileFormat::Ignore == reloc_sect->kind()) ||
+          (!reloc_sect->hasRelocData()))
+        continue;
+
+      // bypass the apply target sections which are not handled by gc
+      if (!mayProcessGC(*apply_sect))
+        continue;
+
+      bool add_first = false;
+      SectionListTy* reached_sects = NULL;
+      RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end();
+      for (reloc_it = reloc_sect->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
+        // reference
+        if (NULL == sym)
+          continue;
+        if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
+          continue;
+
+        // only the target symbols defined in the concerned sections can make
+        // the reference
+        const LDSection* target_sect =
+                &sym->outSymbol()->fragRef()->frag()->getParent()->getSection();
+        if (!mayProcessGC(*target_sect))
+          continue;
+
+        // setup the reached list, if we first add the element to reached list
+        // of this section, create an entry in ReachedSections map
+        if (!add_first) {
+          reached_sects = &m_SectionReachedListMap.getReachedList(*apply_sect);
+          add_first = true;
+        }
+        reached_sects->insert(target_sect);
+      }
+      reached_sects = NULL;
+      add_first = false;
+    }
+  }
+}
+
+void GarbageCollection::getEntrySections(SectionVecTy& pEntry)
+{
+  // all the KEEP sections defined in ldscript are entries, traverse all the
+  // input sections and check the SectionMap to find the KEEP sections
+  Module::obj_iterator obj, objEnd = m_Module.obj_end();
+  SectionMap& sect_map = m_Module.getScript().sectionMap();
+  for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
+    const std::string input_name = (*obj)->name();
+    LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
+    for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
+      LDSection* section = *sect;
+      if (!mayProcessGC(*section))
+        continue;
+
+      SectionMap::Input* sm_input =
+                              sect_map.find(input_name, section->name()).second;
+      if (((sm_input != NULL) && (InputSectDesc::Keep == sm_input->policy())) ||
+          shouldKeep(section->name()))
+        pEntry.push_back(section);
+    }
+  }
+
+  // get the sections those the entry symbols defined in
+  if (LinkerConfig::Exec == m_Config.codeGenType() ||
+                                                   m_Config.options().isPIE()) {
+    // when building executable
+    // 1. the entry symbol is the entry
+    LDSymbol* entry_sym =
+                m_Module.getNamePool().findSymbol(m_Backend.getEntry(m_Module));
+    assert(NULL != entry_sym);
+    pEntry.push_back(&entry_sym->fragRef()->frag()->getParent()->getSection());
+
+    // 2. the symbols have been seen in dynamice objects are entries
+    NamePool::syminfo_iterator info_it,
+                                info_end = m_Module.getNamePool().syminfo_end();
+    for (info_it = m_Module.getNamePool().syminfo_begin(); info_it != info_end;
+                                                                    ++info_it) {
+      ResolveInfo* info = info_it.getEntry();
+      if (!info->isDefine() || info->isLocal())
+        continue;
+
+      if (!info->isInDyn())
+        continue;
+
+      LDSymbol* sym = info->outSymbol();
+      if (NULL == sym || !sym->hasFragRef())
+        continue;
+
+      // only the target symbols defined in the concerned sections can be
+      // entries
+      const LDSection* sect =
+                             &sym->fragRef()->frag()->getParent()->getSection();
+      if (!mayProcessGC(*sect))
+        continue;
+
+      pEntry.push_back(sect);
+    }
+  }
+
+  else {
+    // when building shared objects, the global define symbols are entries
+    NamePool::syminfo_iterator info_it,
+                                info_end = m_Module.getNamePool().syminfo_end();
+    for (info_it = m_Module.getNamePool().syminfo_begin(); info_it != info_end;
+                                                                    ++info_it) {
+      ResolveInfo* info = info_it.getEntry();
+      if (!info->isDefine() ||
+          info->isLocal()   ||
+          info->shouldForceLocal(m_Config))
+        continue;
+      LDSymbol* sym = info->outSymbol();
+      if (NULL == sym || !sym->hasFragRef())
+        continue;
+
+      // only the target symbols defined in the concerned sections can be
+      // entries
+      const LDSection* sect =
+                             &sym->fragRef()->frag()->getParent()->getSection();
+      if (!mayProcessGC(*sect))
+        continue;
+      pEntry.push_back(sect);
+    }
+  }
+}
+
+void GarbageCollection::findReferencedSections(SectionVecTy& pEntry)
+{
+  // list of sections waiting to be processed
+  typedef std::queue<const LDSection*> WorkListTy;
+  WorkListTy work_list;
+  // start from each entry, resolve the transitive closure
+  SectionVecTy::iterator entry_it, entry_end = pEntry.end();
+  for (entry_it = pEntry.begin(); entry_it != entry_end; ++entry_it) {
+    // add entry point to work list
+    work_list.push(*entry_it);
+
+    // add section from the work_list to the referencedSections until every
+    // reached sections are added
+    while (!work_list.empty()) {
+      const LDSection* sect = work_list.front();
+      work_list.pop();
+      // add section to the ReferencedSections, if the section has been put into
+      // referencedSections, skip this section
+      if (!m_ReferencedSections.insert(sect).second)
+        continue;
+
+      // get the section reached list, if the section do not has one, which
+      // means no referenced between it and other sections, then skip it
+      SectionListTy* reach_list =
+                                 m_SectionReachedListMap.findReachedList(*sect);
+      if (NULL == reach_list)
+        continue;
+
+      // put the reached sections to work list, skip the one already be in
+      // referencedSections
+      SectionListTy::iterator it, end = reach_list->end();
+      for (it = reach_list->begin(); it != end; ++it) {
+        if (m_ReferencedSections.find(*it) == m_ReferencedSections.end())
+          work_list.push(*it);
+      }
+    }
+  }
+}
+
+void GarbageCollection::stripSections()
+{
+  // Traverse all the input Regular and BSS sections, if a section is not found
+  // in the ReferencedSections, then it should be garbage collected
+  Module::obj_iterator obj, objEnd = m_Module.obj_end();
+  for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
+    LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
+    for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
+      LDSection* section = *sect;
+      if (!mayProcessGC(*section))
+        continue;
+
+      if (m_ReferencedSections.find(section) == m_ReferencedSections.end())
+        section->setKind(LDFileFormat::Ignore);
+    }
+  }
+
+  // Traverse all the relocation sections, if its target section is set to
+  // Ignore, then set the relocation section to Ignore as well
+  Module::obj_iterator input, inEnd = m_Module.obj_end();
+  for (input = m_Module.obj_begin(); input != inEnd; ++input) {
+    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+      LDSection* reloc_sect = *rs;
+      if (LDFileFormat::Ignore == reloc_sect->getLink()->kind())
+        reloc_sect->setKind(LDFileFormat::Ignore);
+    }
+  }
+}
+
diff --git a/lib/LD/GroupReader.cpp b/lib/LD/GroupReader.cpp
index a5b612b..b3e6f9e 100644
--- a/lib/LD/GroupReader.cpp
+++ b/lib/LD/GroupReader.cpp
@@ -36,6 +36,7 @@
 }
 
 bool GroupReader::readGroup(Module::input_iterator pRoot,
+                            Module::input_iterator pEnd,
                             InputBuilder& pBuilder,
                             const LinkerConfig& pConfig)
 {
@@ -50,12 +51,8 @@
 
   Module::input_iterator input = --pRoot;
 
-  // Since the end of a sub-tree is the same node to the end of whole tree, we
-  // take the end of the whole input tree for conventience.
-  Module::input_iterator input_end = m_Module.input_end();
-
   // first time read the sub-tree
-  while (input != input_end) {
+  while (input != pEnd) {
     // already got type - for example, bitcode or external OIR (object
     // intermediate representation)
     if ((*input)->type() == Input::Script ||
@@ -75,25 +72,26 @@
       continue;
     }
 
+    bool doContinue = false;
     // is an archive
-    if (m_ArchiveReader.isMyFormat(**input)) {
+    if (m_ArchiveReader.isMyFormat(**input, doContinue)) {
       (*input)->setType(Input::Archive);
       // record the Archive used by each archive node
       Archive* ar = new Archive(**input, pBuilder);
       ArchiveListEntry* entry = new ArchiveListEntry(*ar, input);
       ar_list.push_back(entry);
       // read archive
-      m_ArchiveReader.readArchive(*ar);
+      m_ArchiveReader.readArchive(pConfig, *ar);
       cur_obj_cnt += ar->numOfObjectMember();
     }
     // read input as a binary file
-    else if (pConfig.options().isBinaryInput()) {
+    else if (doContinue && m_BinaryReader.isMyFormat(**input, doContinue)) {
       (*input)->setType(Input::Object);
       m_BinaryReader.readBinary(**input);
       m_Module.getObjectList().push_back(*input);
     }
     // is a relocatable object file
-    else if (m_ObjectReader.isMyFormat(**input)) {
+    else if (doContinue && m_ObjectReader.isMyFormat(**input, doContinue)) {
       (*input)->setType(Input::Object);
       m_ObjectReader.readHeader(**input);
       m_ObjectReader.readSections(**input);
@@ -103,15 +101,15 @@
       ++non_ar_obj_cnt;
     }
     // is a shared object file
-    else if (m_DynObjReader.isMyFormat(**input)) {
+    else if (doContinue && m_DynObjReader.isMyFormat(**input, doContinue)) {
       (*input)->setType(Input::DynObj);
       m_DynObjReader.readHeader(**input);
       m_DynObjReader.readSymbols(**input);
       m_Module.getLibraryList().push_back(*input);
     }
     else {
-      fatal(diag::err_unrecognized_input_file) << (*input)->path()
-                                               << pConfig.targets().triple().str();
+      warning(diag::warn_unrecognized_input_file) << (*input)->path()
+        << pConfig.targets().triple().str();
     }
     ++input;
   }
@@ -128,7 +126,7 @@
       // if --whole-archive is given to this archive, no need to read it again
       if ( ar.getARFile().attribute()->isWholeArchive())
         continue;
-      m_ArchiveReader.readArchive(ar);
+      m_ArchiveReader.readArchive(pConfig, ar);
       cur_obj_cnt += ar.numOfObjectMember();
     }
   }
diff --git a/lib/LD/LDFileFormat.cpp b/lib/LD/LDFileFormat.cpp
index bb878b8..d1f0b80 100644
--- a/lib/LD/LDFileFormat.cpp
+++ b/lib/LD/LDFileFormat.cpp
@@ -7,7 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/LDFileFormat.h>
-#include <mcld/Fragment/FragmentLinker.h>
 
 using namespace mcld;
 
diff --git a/lib/LD/NamePool.cpp b/lib/LD/NamePool.cpp
index 7fb8688..151b1dd 100644
--- a/lib/LD/NamePool.cpp
+++ b/lib/LD/NamePool.cpp
@@ -59,6 +59,7 @@
                               ResolveInfo::Desc pDesc,
                               ResolveInfo::Binding pBinding,
                               ResolveInfo::SizeType pSize,
+                              LDSymbol::ValueType pValue,
                               ResolveInfo::Visibility pVisibility,
                               ResolveInfo* pOldInfo,
                               Resolver::Result& pResult)
@@ -102,7 +103,7 @@
   // symbol resolution
   bool override = false;
   unsigned int action = Resolver::LastAction;
-  if (m_pResolver->resolve(*old_symbol, *new_symbol, override)) {
+  if (m_pResolver->resolve(*old_symbol, *new_symbol, override, pValue)) {
     pResult.info      = old_symbol;
     pResult.existent  = true;
     pResult.overriden = override;
diff --git a/lib/LD/RelocData.cpp b/lib/LD/RelocData.cpp
index 1c9411d..8379872 100644
--- a/lib/LD/RelocData.cpp
+++ b/lib/LD/RelocData.cpp
@@ -53,3 +53,9 @@
   return *this;
 }
 
+Relocation& RelocData::remove(Relocation& pRelocation)
+{
+  iterator iter(pRelocation);
+  Relocation* rel = m_Relocations.remove(iter);
+  return *rel;
+}
diff --git a/lib/LD/Relocator.cpp b/lib/LD/Relocator.cpp
index 767588a..dc9445b 100644
--- a/lib/LD/Relocator.cpp
+++ b/lib/LD/Relocator.cpp
@@ -6,16 +6,48 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/Config/Config.h>
 #include <mcld/Fragment/Fragment.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/LD/LDSection.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/Relocator.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/SectionData.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Module.h>
+#if HAVE_CXXABI_H
+#include <cxxabi.h>
+#endif
+#include <sstream>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
+// Helper functions
+//===----------------------------------------------------------------------===//
+std::string demangleSymbol(const std::string& mangled_name) {
+#if HAVE_CXXABI_H
+  // __cxa_demangle needs manually handle the memory release, so we wrap
+  // it into this helper function.
+  size_t output_leng;
+  int status;
+  char* buffer = abi::__cxa_demangle(mangled_name.c_str(), /*buffer=*/0,
+                                     &output_leng, &status);
+  if (status != 0) { // Failed
+    return mangled_name;
+  }
+  std::string demangled_name(buffer);
+  free(buffer);
+
+  return demangled_name;
+#else
+  return mangled_name;
+#endif
+}
+
+
+//===----------------------------------------------------------------------===//
 // Relocator
 //===----------------------------------------------------------------------===//
 Relocator::~Relocator()
@@ -46,3 +78,52 @@
   }
 }
 
+void Relocator::issueUndefRef(Relocation& pReloc,
+                              LDSection& pSection,
+                              Input& pInput)
+{
+  FragmentRef::Offset undef_sym_pos = pReloc.targetRef().offset();
+  std::string sect_name(pSection.name());
+  sect_name = sect_name.substr(sect_name.find('.', /*pos=*/1));  // Drop .rel(a) prefix
+
+  std::string reloc_sym(pReloc.symInfo()->name());
+  if (reloc_sym.substr(0, 2) == "_Z")
+    reloc_sym = demangleSymbol(reloc_sym);
+
+  std::stringstream ss;
+  ss << "0x" << std::hex << undef_sym_pos;
+  std::string undef_sym_pos_hex(ss.str());
+
+  if (sect_name.substr(0, 5) != ".text") {
+    // Function name is only valid for text section
+    fatal(diag::undefined_reference) << reloc_sym
+                                     << pInput.path()
+                                     << sect_name
+                                     << undef_sym_pos_hex;
+    return;
+  }
+
+  std::string caller_file_name;
+  std::string caller_func_name;
+  for (LDContext::sym_iterator i = pInput.context()->symTabBegin(),
+       e = pInput.context()->symTabEnd(); i != e; ++i) {
+    LDSymbol& sym = **i;
+    if (sym.resolveInfo()->type() == ResolveInfo::File)
+      caller_file_name = sym.resolveInfo()->name();
+
+    if (sym.resolveInfo()->type() == ResolveInfo::Function &&
+        sym.value() <= undef_sym_pos &&
+        sym.value() + sym.size() > undef_sym_pos) {
+      caller_func_name = sym.name();
+      break;
+    }
+  }
+
+  if (caller_func_name.substr(0, 2) == "_Z")
+    caller_func_name = demangleSymbol(caller_func_name);
+
+  fatal(diag::undefined_reference_text) << reloc_sym
+                                        << pInput.path()
+                                        << caller_file_name
+                                        << caller_func_name;
+}
diff --git a/lib/LD/ResolveInfo.cpp b/lib/LD/ResolveInfo.cpp
index 4d1f72b..ca26d63 100644
--- a/lib/LD/ResolveInfo.cpp
+++ b/lib/LD/ResolveInfo.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/LDSection.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Support/GCFactory.h>
 #include <llvm/Support/ManagedStatic.h>
 #include <cstdlib>
@@ -90,6 +91,11 @@
     m_BitField &= (~dynamic_flag);
 }
 
+void ResolveInfo::setInDyn()
+{
+  m_BitField |= indyn_flag;
+}
+
 void ResolveInfo::setType(uint32_t pType)
 {
   m_BitField &= ~TYPE_MASK;
@@ -200,6 +206,11 @@
   return (string_flag == (m_BitField & SYMBOL_MASK));
 }
 
+bool ResolveInfo::isInDyn() const
+{
+  return (indyn_flag == (m_BitField & IN_DYN_MASK));
+}
+
 uint32_t ResolveInfo::type() const
 {
   return (m_BitField & TYPE_MASK) >> TYPE_OFFSET;
@@ -239,22 +250,37 @@
   return (0 == std::memcmp(m_Name, pKey.data(), length));
 }
 
+bool ResolveInfo::shouldForceLocal(const LinkerConfig& pConfig)
+{
+  // 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 != pConfig.codeGenType() &&
+      (visibility() == ResolveInfo::Hidden ||
+       visibility() == ResolveInfo::Internal) &&
+      (isGlobal() || isWeak()) &&
+      (isDefine() || isCommon()))
+    return true;
+  return false;
+}
 //===----------------------------------------------------------------------===//
 // ResolveInfo Factory Methods
 //===----------------------------------------------------------------------===//
 ResolveInfo* ResolveInfo::Create(const ResolveInfo::key_type& pKey)
 {
-  ResolveInfo* result = static_cast<ResolveInfo*>(
+  ResolveInfo* info = static_cast<ResolveInfo*>(
                           malloc(sizeof(ResolveInfo)+pKey.size()+1));
-  if (NULL == result)
+  if (NULL == info)
     return NULL;
 
-  new (result) ResolveInfo();
-  std::memcpy(result->m_Name, pKey.data(), pKey.size());
-  result->m_Name[pKey.size()] = '\0';
-  result->m_BitField &= ~ResolveInfo::RESOLVE_MASK;
-  result->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET);
-  return result;
+  new (info) ResolveInfo(); // call constructor at the `result` address.
+  std::memcpy(info->m_Name, pKey.data(), pKey.size());
+  info->m_Name[pKey.size()] = '\0';
+  info->m_BitField &= ~ResolveInfo::RESOLVE_MASK;
+  info->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET);
+  return info;
 }
 
 void ResolveInfo::Destroy(ResolveInfo*& pInfo)
diff --git a/lib/LD/StaticResolver.cpp b/lib/LD/StaticResolver.cpp
index 6401262..21826ef 100644
--- a/lib/LD/StaticResolver.cpp
+++ b/lib/LD/StaticResolver.cpp
@@ -20,14 +20,14 @@
 
 bool StaticResolver::resolve(ResolveInfo& __restrict__ pOld,
                              const ResolveInfo& __restrict__ pNew,
-                             bool &pOverride) const
+                             bool &pOverride, LDSymbol::ValueType pValue) const
 {
 
   /* The state table itself.
    * The first index is a link_row and the second index is a bfd_link_hash_type.
    *
    * Cs -> all rest kind of common (d_C, wd_C)
-   * Is -> all kind of indeirect
+   * Is -> all kind of indirect
    */
   static const enum LinkAction link_action[LAST_ORD][LAST_ORD] =
   {
@@ -169,6 +169,20 @@
       }
       /* Fall through */
       case MDEF: {       /* multiple definition error.  */
+        if (pOld.isDefine() && pNew.isDefine() &&
+            pOld.isAbsolute() && pNew.isAbsolute() &&
+            (pOld.desc() == pNew.desc() || pOld.desc() == ResolveInfo::NoType ||
+             pNew.desc() == ResolveInfo::NoType)) {
+          if (pOld.outSymbol()->value() == pValue) {
+            pOverride = true;
+            old->override(pNew);
+            break;
+          } else {
+            error(diag::multiple_absolute_definitions) << pNew.name()
+              << pOld.outSymbol()->value() << pValue;
+            break;
+          }
+        }
         error(diag::multiple_definitions) << pNew.name();
         break;
       }
diff --git a/lib/LD/StubFactory.cpp b/lib/LD/StubFactory.cpp
index 0124ec0..3d7c56a 100644
--- a/lib/LD/StubFactory.cpp
+++ b/lib/LD/StubFactory.cpp
@@ -50,11 +50,10 @@
     // find the island for the input relocation
     BranchIsland* island = pBRIslandFactory.find(*(pReloc.targetRef().frag()));
     if (NULL == island) {
-      island = pBRIslandFactory.produce(*(pReloc.targetRef().frag()));
+      return NULL;
     }
 
     // find if there is such a stub in the island already
-    assert(NULL != island);
     Stub* stub = island->findStub(prototype, pReloc);
     if (NULL != stub) {
       // reset the branch target to the stub instead!
diff --git a/lib/MC/Android.mk b/lib/MC/Android.mk
index 0f8911b..cbd1962 100644
--- a/lib/MC/Android.mk
+++ b/lib/MC/Android.mk
@@ -9,8 +9,8 @@
   InputAction.cpp  \
   InputBuilder.cpp  \
   InputFactory.cpp  \
+  Input.cpp \
   MCLDDirectory.cpp \
-  MCLDInput.cpp \
   SearchDirs.cpp  \
   SymbolCategory.cpp  \
   ZOption.cpp
diff --git a/lib/MC/CommandAction.cpp b/lib/MC/CommandAction.cpp
index 91b5904..bae5fbf 100644
--- a/lib/MC/CommandAction.cpp
+++ b/lib/MC/CommandAction.cpp
@@ -11,6 +11,8 @@
 #include <mcld/MC/SearchDirs.h>
 #include <mcld/MC/Attribute.h>
 #include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/LinkerConfig.h>
 
 using namespace mcld;
 
@@ -35,13 +37,13 @@
 //===----------------------------------------------------------------------===//
 NamespecAction::NamespecAction(unsigned int pPosition,
                                const std::string &pNamespec,
-                               SearchDirs& pSearchDirs)
+                               const SearchDirs& pSearchDirs)
   : InputAction(pPosition), m_Namespec(pNamespec), m_SearchDirs(pSearchDirs) {
 }
 
 bool NamespecAction::activate(InputBuilder& pBuilder) const
 {
-  sys::fs::Path* path = NULL;
+  const sys::fs::Path* path = NULL;
   // find out the real path of the namespec.
   if (pBuilder.getConstraint().isSharedSystem()) {
     // In the system with shared object support, we can find both archive
@@ -218,3 +220,63 @@
   return true;
 }
 
+//===----------------------------------------------------------------------===//
+// DefSymAction
+//===----------------------------------------------------------------------===//
+DefSymAction::DefSymAction(unsigned int pPosition, std::string& pAssignment)
+  : InputAction(pPosition), m_Assignment(pAssignment) {
+}
+
+bool DefSymAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.createNode<InputTree::Positional>("defsym", "NAN");
+  Input* input = *pBuilder.getCurrentNode();
+  pBuilder.setContext(*input, false);
+
+  m_Assignment.append(";");
+  pBuilder.setMemory(*input, &m_Assignment[0], m_Assignment.size());
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// ScriptAction
+//===----------------------------------------------------------------------===//
+ScriptAction::ScriptAction(unsigned int pPosition,
+                           const std::string& pFileName,
+                           ScriptFile::Kind pKind,
+                           const SearchDirs& pSearchDirs)
+  : InputAction(pPosition),
+    m_FileName(pFileName),
+    m_Kind(pKind),
+    m_SearchDirs(pSearchDirs) {
+}
+
+bool ScriptAction::activate(InputBuilder& pBuilder) const
+{
+  sys::fs::Path path(m_FileName);
+
+  if (!exists(path)) {
+    const sys::fs::Path* res = m_SearchDirs.find(m_FileName, Input::Script);
+    if (res == NULL) {
+      switch (m_Kind) {
+      case ScriptFile::LDScript:
+        fatal(diag::err_cannot_find_scriptfile) << "linker script" << m_FileName;
+        break;
+      case ScriptFile::VersionScript:
+        fatal(diag::err_cannot_find_scriptfile) << "version script" << m_FileName;
+        break;
+      case ScriptFile::DynamicList:
+        fatal(diag::err_cannot_find_scriptfile) << "dynamic list" << m_FileName;
+        break;
+      default:
+        break;
+      }
+      return false;
+    }
+    path.assign(res->native());
+  }
+
+  pBuilder.createNode<InputTree::Positional>(path.stem().native(), path);
+
+  return true;
+}
diff --git a/lib/MC/FileAction.cpp b/lib/MC/FileAction.cpp
index 8660558..1c7e5ae 100644
--- a/lib/MC/FileAction.cpp
+++ b/lib/MC/FileAction.cpp
@@ -7,10 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/MC/FileAction.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/MC/InputBuilder.h>
-#include <mcld/MC/ContextFactory.h>
-#include <mcld/Support/MemoryAreaFactory.h>
 
 using namespace mcld;
 
diff --git a/lib/MC/MCLDInput.cpp b/lib/MC/Input.cpp
similarity index 90%
rename from lib/MC/MCLDInput.cpp
rename to lib/MC/Input.cpp
index a10466b..2d948c2 100644
--- a/lib/MC/MCLDInput.cpp
+++ b/lib/MC/Input.cpp
@@ -1,4 +1,4 @@
-//===- MCLDInput.cpp ------------------------------------------------------===//
+//===- Input.cpp ----------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,10 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
 #include <mcld/MC/Attribute.h>
 #include <mcld/LD/LDContext.h>
-#include <mcld/Support/MemoryArea.h>
 
 using namespace mcld;
 
@@ -71,7 +70,5 @@
 {
   // Attribute is deleted by AttributeFactory
   // MemoryArea is deleted by MemoryAreaFactory
-  if (NULL != m_pMemArea)
-    m_pMemArea->clear();
 }
 
diff --git a/lib/MC/InputBuilder.cpp b/lib/MC/InputBuilder.cpp
index 9142801..842c476 100644
--- a/lib/MC/InputBuilder.cpp
+++ b/lib/MC/InputBuilder.cpp
@@ -131,10 +131,6 @@
                              FileHandle::Permission pPerm)
 {
   MemoryArea *memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm);
-
-  if (!memory->handler()->isGood())
-    return false;
-
   pInput.setMemArea(memory);
   return true;
 }
diff --git a/lib/MC/SearchDirs.cpp b/lib/MC/SearchDirs.cpp
index 940553e..971f866 100644
--- a/lib/MC/SearchDirs.cpp
+++ b/lib/MC/SearchDirs.cpp
@@ -73,89 +73,136 @@
   return insert(pPath.native());
 }
 
-mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec, mcld::Input::Type pType)
+mcld::sys::fs::Path*
+SearchDirs::find(const std::string& pNamespec, mcld::Input::Type pType)
 {
-  assert(Input::DynObj == pType || Input::Archive == pType);
+  assert(Input::DynObj  == pType ||
+         Input::Archive == pType ||
+         Input::Script  == pType);
 
   std::string file;
-  SpecToFilename(pNamespec, file);
+  switch(pType) {
+  case Input::Script:
+    file.assign(pNamespec);
+    break;
+  case Input::DynObj:
+  case Input::Archive :
+    SpecToFilename(pNamespec, file);
+    break;
+  default:
+    break;
+  } // end of switch
+
   // for all MCLDDirectorys
   DirList::iterator mcld_dir, mcld_dir_end = m_DirList.end();
-  for (mcld_dir=m_DirList.begin(); mcld_dir!=mcld_dir_end; ++mcld_dir) {
+  for (mcld_dir = m_DirList.begin(); mcld_dir != mcld_dir_end; ++mcld_dir) {
     // for all entries in MCLDDirectory
     MCLDDirectory::iterator entry = (*mcld_dir)->begin();
     MCLDDirectory::iterator enEnd = (*mcld_dir)->end();
 
     switch(pType) {
-      case Input::DynObj: {
-        while (entry!=enEnd) {
-          if (file == entry.path()->stem().native() ) {
-            if(mcld::sys::fs::detail::shared_library_extension == entry.path()->extension().native()) {
-              return entry.path();
-            }
-          }
-          ++entry;
-        }
+    case Input::Script: {
+      while (entry != enEnd) {
+        if (file == entry.path()->filename())
+          return entry.path();
+        ++entry;
       }
-      /** Fall through **/
-      case Input::Archive : {
-        entry = (*mcld_dir)->begin();
-        enEnd = (*mcld_dir)->end();
-        while ( entry!=enEnd ) {
-          if (file == entry.path()->stem().native() &&
-            mcld::sys::fs::detail::static_library_extension == entry.path()->extension().native()) {
+      break;
+    }
+    case Input::DynObj: {
+      while (entry != enEnd) {
+        if (file == entry.path()->stem().native() ) {
+          if (mcld::sys::fs::detail::shared_library_extension ==
+                entry.path()->extension().native()) {
             return entry.path();
           }
-          ++entry;
         }
+        ++entry;
       }
-      default:
-        break;
+    }
+    /** Fall through **/
+    case Input::Archive : {
+      entry = (*mcld_dir)->begin();
+      enEnd = (*mcld_dir)->end();
+      while (entry != enEnd) {
+        if (file == entry.path()->stem().native() &&
+            mcld::sys::fs::detail::static_library_extension ==
+              entry.path()->extension().native()) {
+          return entry.path();
+        }
+        ++entry;
+      }
+    }
+    default:
+      break;
     } // end of switch
-  } // end of while
+  } // end of for
   return NULL;
 }
 
 const mcld::sys::fs::Path*
 SearchDirs::find(const std::string& pNamespec, mcld::Input::Type pType) const
 {
-  assert(Input::DynObj == pType || Input::Archive == pType);
+  assert(Input::DynObj  == pType ||
+         Input::Archive == pType ||
+         Input::Script  == pType);
 
   std::string file;
-  SpecToFilename(pNamespec, file);
+  switch(pType) {
+  case Input::Script:
+    file.assign(pNamespec);
+    break;
+  case Input::DynObj:
+  case Input::Archive :
+    SpecToFilename(pNamespec, file);
+    break;
+  default:
+    break;
+  } // end of switch
+
   // for all MCLDDirectorys
   DirList::const_iterator mcld_dir, mcld_dir_end = m_DirList.end();
-  for (mcld_dir=m_DirList.begin(); mcld_dir!=mcld_dir_end; ++mcld_dir) {
+  for (mcld_dir = m_DirList.begin(); mcld_dir != mcld_dir_end; ++mcld_dir) {
     // for all entries in MCLDDirectory
     MCLDDirectory::iterator entry = (*mcld_dir)->begin();
     MCLDDirectory::iterator enEnd = (*mcld_dir)->end();
 
     switch(pType) {
-      case Input::DynObj: {
-        while (entry!=enEnd) {
-          if (file == entry.path()->stem().native() ) {
-            if(mcld::sys::fs::detail::shared_library_extension == entry.path()->extension().native()) {
-              return entry.path();
-            }
-          }
-          ++entry;
-        }
+    case Input::Script: {
+      while (entry != enEnd) {
+        if (file == entry.path()->filename())
+          return entry.path();
+        ++entry;
       }
-      /** Fall through **/
-      case Input::Archive : {
-        entry = (*mcld_dir)->begin();
-        enEnd = (*mcld_dir)->end();
-        while ( entry!=enEnd ) {
-          if (file == entry.path()->stem().native() &&
-            mcld::sys::fs::detail::static_library_extension == entry.path()->extension().native()) {
+      break;
+    }
+    case Input::DynObj: {
+      while (entry != enEnd) {
+        if (file == entry.path()->stem().native() ) {
+          if (mcld::sys::fs::detail::shared_library_extension ==
+                entry.path()->extension().native()) {
             return entry.path();
           }
-          ++entry;
         }
+        ++entry;
       }
-      default:
-        break;
+    }
+    /** Fall through **/
+    case Input::Archive : {
+      entry = (*mcld_dir)->begin();
+      enEnd = (*mcld_dir)->end();
+      while ( entry!=enEnd ) {
+        if (file == entry.path()->stem().native() &&
+            mcld::sys::fs::detail::static_library_extension ==
+              entry.path()->extension().native()) {
+          return entry.path();
+        }
+        ++entry;
+      }
+    }
+    default:
+      break;
     } // end of switch
-  } // end of while
+  } // end of for 
   return NULL;
 }
diff --git a/lib/MC/ZOption.cpp b/lib/MC/ZOption.cpp
index a58562d..8b11765 100644
--- a/lib/MC/ZOption.cpp
+++ b/lib/MC/ZOption.cpp
@@ -10,16 +10,10 @@
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // ZOption
-
+//===----------------------------------------------------------------------===//
 ZOption::ZOption()
-  : m_Kind(Unknown),
-    m_PageSize(0x0)
-{
-}
-
-ZOption::~ZOption()
-{
+  : m_Kind(Unknown), m_PageSize(0x0) {
 }
 
diff --git a/lib/Object/ObjectBuilder.cpp b/lib/Object/ObjectBuilder.cpp
index f5c9fe5..6738c3c 100644
--- a/lib/Object/ObjectBuilder.cpp
+++ b/lib/Object/ObjectBuilder.cpp
@@ -10,6 +10,7 @@
 
 #include <mcld/Module.h>
 #include <mcld/LinkerConfig.h>
+#include <mcld/LinkerScript.h>
 #include <mcld/IRBuilder.h>
 #include <mcld/Object/SectionMap.h>
 #include <mcld/LD/LDSection.h>
@@ -40,20 +41,35 @@
                                         uint32_t pAlign)
 {
   // try to get one from output LDSection
-  const SectionMap::NamePair& pair = m_Module.getScript().sectionMap().find(pName);
-  std::string output_name = (pair.isNull())?pName:pair.to;
-  LDSection* output_sect = LDSection::Create(output_name, pKind, pType, pFlag);
-  output_sect->setAlign(pAlign);
-  m_Module.getSectionTable().push_back(output_sect);
+  SectionMap::const_mapping pair =
+    m_Module.getScript().sectionMap().find("*", pName);
+
+  std::string output_name = (pair.first == NULL) ? pName : pair.first->name();
+
+  LDSection* output_sect = m_Module.getSection(output_name);
+  if (NULL == output_sect) {
+    output_sect = LDSection::Create(pName, pKind, pType, pFlag);
+    output_sect->setAlign(pAlign);
+    m_Module.getSectionTable().push_back(output_sect);
+  }
   return output_sect;
 }
 
 /// MergeSection - merge the pInput section to the pOutput section
-LDSection* ObjectBuilder::MergeSection(LDSection& pInputSection)
+LDSection* ObjectBuilder::MergeSection(const Input& pInputFile,
+                                       LDSection& pInputSection)
 {
-  const SectionMap::NamePair& pair =
-              m_Module.getScript().sectionMap().find(pInputSection.name());
-  std::string output_name = (pair.isNull())?pInputSection.name():pair.to;
+  SectionMap::mapping pair =
+    m_Module.getScript().sectionMap().find(pInputFile.path().native(),
+                                           pInputSection.name());
+
+  if (pair.first != NULL && pair.first->isDiscard()) {
+    pInputSection.setKind(LDFileFormat::Ignore);
+    return NULL;
+  }
+
+  std::string output_name = (pair.first == NULL) ?
+                            pInputSection.name() : pair.first->name();
   LDSection* target = m_Module.getSection(output_name);
 
   if (NULL == target) {
@@ -66,11 +82,6 @@
   }
 
   switch (target->kind()) {
-    // Some *OUTPUT sections should not be merged.
-    case LDFileFormat::Relocation:
-    case LDFileFormat::NamePool:
-      /** do nothing **/
-      return target;
     case LDFileFormat::EhFrame: {
       EhFrame* eh_frame = NULL;
       if (target->hasEhFrame())
@@ -78,16 +89,22 @@
       else
         eh_frame = IRBuilder::CreateEhFrame(*target);
 
-      eh_frame->merge(*pInputSection.getEhFrame());
-			UpdateSectionAlign(*target, pInputSection);
+      eh_frame->merge(pInputFile, *pInputSection.getEhFrame());
+      UpdateSectionAlign(*target, pInputSection);
       return target;
     }
     default: {
+      if (!target->hasSectionData())
+        IRBuilder::CreateSectionData(*target);
+
       SectionData* data = NULL;
-      if (target->hasSectionData())
+      if (pair.first != NULL) {
+        assert(pair.second != NULL);
+        data = pair.second->getSection()->getSectionData();
+      } else {
+        // orphan section
         data = target->getSectionData();
-      else
-        data = IRBuilder::CreateSectionData(*target);
+      }
 
       if (MoveSectionData(*pInputSection.getSectionData(), *data)) {
         UpdateSectionAlign(*target, pInputSection);
@@ -104,7 +121,7 @@
 {
   assert(&pFrom != &pTo && "Cannot move section data to itself!");
 
-  uint32_t offset = pTo.getSection().size();
+  uint64_t offset = pTo.getSection().size();
   AlignFragment* align = NULL;
   if (pFrom.getSection().align() > 1) {
     // if the align constraint is larger than 1, append an alignment
@@ -149,7 +166,7 @@
                                        uint32_t pAlignConstraint)
 {
   // get initial offset.
-  uint32_t offset = 0;
+  uint64_t offset = 0;
   if (!pSD.empty())
     offset = pSD.back().getOffset() + pSD.back().size();
 
diff --git a/lib/Object/ObjectLinker.cpp b/lib/Object/ObjectLinker.cpp
index 1b16f95..f5eec4c 100644
--- a/lib/Object/ObjectLinker.cpp
+++ b/lib/Object/ObjectLinker.cpp
@@ -9,6 +9,7 @@
 #include <mcld/Object/ObjectLinker.h>
 
 #include <mcld/LinkerConfig.h>
+#include <mcld/LinkerScript.h>
 #include <mcld/Module.h>
 #include <mcld/InputTree.h>
 #include <mcld/IRBuilder.h>
@@ -20,27 +21,37 @@
 #include <mcld/LD/DynObjReader.h>
 #include <mcld/LD/GroupReader.h>
 #include <mcld/LD/BinaryReader.h>
+#include <mcld/LD/GarbageCollection.h>
 #include <mcld/LD/ObjectWriter.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/RelocData.h>
 #include <mcld/LD/Relocator.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/Script/ScriptFile.h>
+#include <mcld/Script/ScriptReader.h>
+#include <mcld/Script/Assignment.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Script/RpnEvaluator.h>
 #include <mcld/Support/RealPath.h>
-#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/FileOutputBuffer.h>
 #include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/DefSymParser.h>
 #include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Fragment/Relocation.h>
 #include <mcld/Object/ObjectBuilder.h>
 
 #include <llvm/Support/Casting.h>
-
+#include <llvm/Support/Host.h>
 
 using namespace llvm;
 using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ObjectLinker
+//===----------------------------------------------------------------------===//
 ObjectLinker::ObjectLinker(const LinkerConfig& pConfig,
                            TargetLDBackend& pLDBackend)
   : m_Config(pConfig),
-    m_pLinker(NULL),
     m_pModule(NULL),
     m_pBuilder(NULL),
     m_LDBackend(pLDBackend),
@@ -49,54 +60,39 @@
     m_pArchiveReader(NULL),
     m_pGroupReader(NULL),
     m_pBinaryReader(NULL),
+    m_pScriptReader(NULL),
     m_pWriter(NULL) {
 }
 
 ObjectLinker::~ObjectLinker()
 {
-  delete m_pLinker;
   delete m_pObjectReader;
   delete m_pDynObjReader;
   delete m_pArchiveReader;
   delete m_pGroupReader;
   delete m_pBinaryReader;
+  delete m_pScriptReader;
   delete m_pWriter;
 }
 
-void ObjectLinker::setup(Module& pModule, IRBuilder& pBuilder)
+bool ObjectLinker::initialize(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
-///  Connect all components with FragmentLinker
-bool ObjectLinker::initFragmentLinker()
-{
-  if (NULL == m_pLinker) {
-    m_pLinker = new FragmentLinker(m_Config,
-                                   *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_pBuilder);
   m_pArchiveReader = m_LDBackend.createArchiveReader(*m_pModule);
   m_pDynObjReader  = m_LDBackend.createDynObjReader(*m_pBuilder);
   m_pBinaryReader  = m_LDBackend.createBinaryReader(*m_pBuilder);
   m_pGroupReader   = new GroupReader(*m_pModule, *m_pObjectReader,
                          *m_pDynObjReader, *m_pArchiveReader, *m_pBinaryReader);
+  m_pScriptReader  = new ScriptReader(*m_pGroupReader);
   m_pWriter        = m_LDBackend.createWriter();
 
   // initialize Relocator
   m_LDBackend.initRelocator();
+
   return true;
 }
 
@@ -122,7 +118,8 @@
   for (input = m_pModule->input_begin(); input!=inEnd; ++input) {
     // is a group node
     if (isGroup(input)) {
-      getGroupReader()->readGroup(input, m_pBuilder->getInputBuilder(), m_Config);
+      getGroupReader()->readGroup(input, inEnd, m_pBuilder->getInputBuilder(),
+                                  m_Config);
       continue;
     }
 
@@ -143,14 +140,15 @@
       continue;
     }
 
+    bool doContinue = false;
     // read input as a binary file
-    if (m_Config.options().isBinaryInput()) {
+    if (getBinaryReader()->isMyFormat(**input, doContinue)) {
       (*input)->setType(Input::Object);
       getBinaryReader()->readBinary(**input);
       m_pModule->getObjectList().push_back(*input);
     }
     // is a relocatable object file
-    else if (getObjectReader()->isMyFormat(**input)) {
+    else if (doContinue && getObjectReader()->isMyFormat(**input, doContinue)) {
       (*input)->setType(Input::Object);
       getObjectReader()->readHeader(**input);
       getObjectReader()->readSections(**input);
@@ -158,25 +156,39 @@
       m_pModule->getObjectList().push_back(*input);
     }
     // is a shared object file
-    else if (getDynObjReader()->isMyFormat(**input)) {
+    else if (doContinue && getDynObjReader()->isMyFormat(**input, doContinue)) {
       (*input)->setType(Input::DynObj);
       getDynObjReader()->readHeader(**input);
       getDynObjReader()->readSymbols(**input);
       m_pModule->getLibraryList().push_back(*input);
     }
     // is an archive
-    else if (getArchiveReader()->isMyFormat(**input)) {
+    else if (doContinue && getArchiveReader()->isMyFormat(**input, doContinue)) {
       (*input)->setType(Input::Archive);
       Archive archive(**input, m_pBuilder->getInputBuilder());
-      getArchiveReader()->readArchive(archive);
+      getArchiveReader()->readArchive(m_Config, archive);
       if(archive.numOfObjectMember() > 0) {
         m_pModule->getInputTree().merge<InputTree::Inclusive>(input,
-                                                            archive.inputs());
+                                                              archive.inputs());
+      }
+    }
+    // try to parse input as a linker script
+    else if (doContinue && getScriptReader()->isMyFormat(**input, doContinue)) {
+      ScriptFile script(ScriptFile::LDScript, **input,
+                        m_pBuilder->getInputBuilder());
+      if (getScriptReader()->readScript(m_Config, script)) {
+        (*input)->setType(Input::Script);
+        script.activate(*m_pModule);
+        if (script.inputs().size() > 0) {
+          m_pModule->getInputTree().merge<InputTree::Inclusive>(input,
+            script.inputs());
+        }
       }
     }
     else {
-      fatal(diag::err_unrecognized_input_file) << (*input)->path()
-                                          << m_Config.targets().triple().str();
+      if (m_Config.options().warnMismatch())
+        warning(diag::warn_unrecognized_input_file) << (*input)->path()
+          << m_Config.targets().triple().str();
     }
   } // end of for
 }
@@ -217,6 +229,16 @@
   return true;
 }
 
+void ObjectLinker::dataStrippingOpt()
+{
+  // Garbege collection
+  if (m_Config.options().GCSections()) {
+    GarbageCollection GC(m_Config, m_LDBackend, *m_pModule);
+    GC.run();
+  }
+  return;
+}
+
 /// readRelocations - read all relocation entries
 ///
 /// All symbols should be read and resolved before this function.
@@ -247,14 +269,21 @@
         // Some *INPUT sections should not be merged.
         case LDFileFormat::Ignore:
         case LDFileFormat::Null:
-        case LDFileFormat::Relocation:
         case LDFileFormat::NamePool:
         case LDFileFormat::Group:
         case LDFileFormat::StackNote:
           // skip
           continue;
+        case LDFileFormat::Relocation: {
+          if (!(*sect)->hasRelocData())
+            continue; // skip
+
+          if ((*sect)->getLink()->kind() == LDFileFormat::Ignore)
+            (*sect)->setKind(LDFileFormat::Ignore);
+          break;
+        }
         case LDFileFormat::Target:
-          if (!m_LDBackend.mergeSection(*m_pModule, **sect)) {
+          if (!m_LDBackend.mergeSection(*m_pModule, **obj, **sect)) {
             error(diag::err_cannot_merge_section) << (*sect)->name()
                                                   << (*obj)->name();
             return false;
@@ -265,16 +294,12 @@
             continue; // skip
 
           LDSection* out_sect = NULL;
-          if (NULL == (out_sect = builder.MergeSection(**sect))) {
-            error(diag::err_cannot_merge_section) << (*sect)->name()
-                                                  << (*obj)->name();
-            return false;
-          }
-
-          if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
-            error(diag::err_cannot_merge_section) << (*sect)->name()
-                                                  << (*obj)->name();
-            return false;
+          if (NULL != (out_sect = builder.MergeSection(**obj, **sect))) {
+            if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
+              error(diag::err_cannot_merge_section) << (*sect)->name()
+                                                    << (*obj)->name();
+              return false;
+            }
           }
           break;
         }
@@ -283,25 +308,105 @@
             continue; // skip
 
           LDSection* out_sect = NULL;
-          if (NULL == (out_sect = builder.MergeSection(**sect))) {
-            error(diag::err_cannot_merge_section) << (*sect)->name()
-                                                  << (*obj)->name();
-            return false;
-          }
-
-          if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
-            error(diag::err_cannot_merge_section) << (*sect)->name()
-                                                  << (*obj)->name();
-            return false;
+          if (NULL != (out_sect = builder.MergeSection(**obj, **sect))) {
+            if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
+              error(diag::err_cannot_merge_section) << (*sect)->name()
+                                                    << (*obj)->name();
+              return false;
+            }
           }
           break;
         }
       } // end of switch
     } // for each section
   } // for each obj
+
+  RpnEvaluator evaluator(*m_pModule, m_LDBackend);
+  SectionMap::iterator out, outBegin, outEnd;
+  outBegin = m_pModule->getScript().sectionMap().begin();
+  outEnd = m_pModule->getScript().sectionMap().end();
+  for (out = outBegin; out != outEnd; ++out) {
+    uint64_t out_align = 0x0, in_align = 0x0;
+    LDSection* out_sect = (*out)->getSection();
+    SectionMap::Output::iterator in, inBegin, inEnd;
+    inBegin = (*out)->begin();
+    inEnd = (*out)->end();
+
+    // force input alignment from ldscript if any
+    if ((*out)->prolog().hasSubAlign()) {
+      evaluator.eval((*out)->prolog().subAlign(), in_align);
+    }
+
+    for (in = inBegin; in != inEnd; ++in) {
+      LDSection* in_sect = (*in)->getSection();
+      if ((*out)->prolog().hasSubAlign())
+        in_sect->setAlign(in_align);
+
+      if (builder.MoveSectionData(*in_sect->getSectionData(),
+                                  *out_sect->getSectionData())) {
+        builder.UpdateSectionAlign(*out_sect, *in_sect);
+        m_LDBackend.updateSectionFlags(*out_sect, *in_sect);
+      }
+    } // for each input section description
+
+    // force output alignment from ldscript if any
+    if ((*out)->prolog().hasAlign()) {
+      evaluator.eval((*out)->prolog().align(), out_align);
+      out_sect->setAlign(out_align);
+    }
+
+    if ((*out)->hasContent()) {
+      LDSection* target = m_pModule->getSection((*out)->name());
+      assert(target != NULL && target->hasSectionData());
+      if (builder.MoveSectionData(*out_sect->getSectionData(),
+                                  *target->getSectionData())) {
+        builder.UpdateSectionAlign(*target, *out_sect);
+        m_LDBackend.updateSectionFlags(*target, *out_sect);
+      }
+    }
+  } // for each output section description
+
   return true;
 }
 
+void ObjectLinker::addSymbolToOutput(ResolveInfo& pInfo, Module& pModule)
+{
+  // section symbols will be defined by linker later, we should not add section
+  // symbols to output here
+  if (ResolveInfo::Section == pInfo.type() || NULL == pInfo.outSymbol())
+    return;
+
+  // if the symbols defined in the Ignore sections (e.g. discared by GC), then
+  // not to put them to output
+  if (pInfo.outSymbol()->hasFragRef() && LDFileFormat::Ignore ==
+        pInfo.outSymbol()->fragRef()->frag()->getParent()->getSection().kind())
+    return;
+
+  if (pInfo.shouldForceLocal(m_Config))
+    pModule.getSymbolTable().forceLocal(*pInfo.outSymbol());
+  else
+    pModule.getSymbolTable().add(*pInfo.outSymbol());
+}
+
+void ObjectLinker::addSymbolsToOutput(Module& pModule)
+{
+  // Traverse all the free ResolveInfo and add the output symobols to output
+  NamePool::freeinfo_iterator free_it,
+                              free_end = pModule.getNamePool().freeinfo_end();
+  for (free_it = pModule.getNamePool().freeinfo_begin(); free_it != free_end;
+                                                                      ++free_it)
+    addSymbolToOutput(**free_it, pModule);
+
+
+  // Traverse all the resolveInfo and add the output symbol to output
+  NamePool::syminfo_iterator info_it,
+                             info_end = pModule.getNamePool().syminfo_end();
+  for (info_it = pModule.getNamePool().syminfo_begin(); info_it != info_end;
+                                                                      ++info_it)
+    addSymbolToOutput(*info_it.getEntry(), pModule);
+}
+
+
 /// addStandardSymbols - shared object and executable files need some
 /// standard symbols
 ///   @return if there are some input symbols with the same name to the
@@ -331,40 +436,63 @@
 /// scripts.
 bool ObjectLinker::addScriptSymbols()
 {
-  const LinkerScript& script = m_pModule->getScript();
-  LinkerScript::DefSymMap::const_entry_iterator it;
-  LinkerScript::DefSymMap::const_entry_iterator ie = script.defSymMap().end();
-  // go through the entire defSymMap
-  for (it = script.defSymMap().begin(); it != ie; ++it) {
-    const llvm::StringRef sym =  it.getEntry()->key();
-    ResolveInfo* old_info = m_pModule->getNamePool().findInfo(sym);
+  LinkerScript& script = m_pModule->getScript();
+  LinkerScript::Assignments::iterator it, ie = script.assignments().end();
+  // go through the entire symbol assignments
+  for (it = script.assignments().begin(); it != ie; ++it) {
+    LDSymbol* symbol = NULL;
+    assert((*it).second.symbol().type() == Operand::SYMBOL);
+    const llvm::StringRef symName =  (*it).second.symbol().name();
+    ResolveInfo::Type       type = ResolveInfo::NoType;
+    ResolveInfo::Visibility vis  = ResolveInfo::Default;
+    size_t size = 0;
+    ResolveInfo* old_info = m_pModule->getNamePool().findInfo(symName);
     // if the symbol does not exist, we can set type to NOTYPE
     // else we retain its type, same goes for size - 0 or retain old value
     // and visibility - Default or retain
     if (old_info != NULL) {
-      if(!m_pBuilder->AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
-                             sym,
-                             static_cast<ResolveInfo::Type>(old_info->type()),
-                             ResolveInfo::Define,
-                             ResolveInfo::Absolute,
-                             old_info->size(),
-                             0x0,
-                             FragmentRef::Null(),
-                             old_info->visibility()))
-        return false;
+      type = static_cast<ResolveInfo::Type>(old_info->type());
+      vis = old_info->visibility();
+      size = old_info->size();
     }
-    else {
-      if (!m_pBuilder->AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
-                             sym,
-                             ResolveInfo::NoType,
-                             ResolveInfo::Define,
-                             ResolveInfo::Absolute,
-                             0x0,
-                             0x0,
-                             FragmentRef::Null(),
-                             ResolveInfo::Default))
-        return false;
+
+    // Add symbol and refine the visibility if needed
+    // FIXME: bfd linker would change the binding instead, but currently
+    //        ABS is also a kind of Binding in ResolveInfo.
+    switch ((*it).second.type()) {
+    case Assignment::HIDDEN:
+      vis = ResolveInfo::Hidden;
+      // Fall through
+    case Assignment::DEFAULT:
+      symbol =
+        m_pBuilder->AddSymbol<IRBuilder::Force,
+                              IRBuilder::Unresolve>(symName,
+                                                    type,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Absolute,
+                                                    size,
+                                                    0x0,
+                                                    FragmentRef::Null(),
+                                                    vis);
+      break;
+    case Assignment::PROVIDE_HIDDEN:
+      vis = ResolveInfo::Hidden;
+      // Fall through
+    case Assignment::PROVIDE:
+      symbol =
+        m_pBuilder->AddSymbol<IRBuilder::AsReferred,
+                              IRBuilder::Unresolve>(symName,
+                                                    type,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Absolute,
+                                                    size,
+                                                    0x0,
+                                                    FragmentRef::Null(),
+                                                    vis);
+      break;
     }
+    // Set symbol of this assignment.
+    (*it).first = symbol;
   }
   return true;
 }
@@ -387,10 +515,18 @@
       RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
       for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
         Relocation* relocation = llvm::cast<Relocation>(reloc);
+
+        // bypass the reloc if the symbol is in the discarded input section
+        ResolveInfo* info = relocation->symInfo();
+        if (!info->outSymbol()->hasFragRef() &&
+            ResolveInfo::Section == info->type() &&
+            ResolveInfo::Undefined == info->desc())
+           continue;
+
         // scan relocation
         if (LinkerConfig::Object != m_Config.codeGenType())
           m_LDBackend.getRelocator()->scanRelocation(
-                                    *relocation, *m_pBuilder, *m_pModule, **rs);
+                                    *relocation, *m_pBuilder, *m_pModule, **rs, **input);
         else
           m_LDBackend.getRelocator()->partialScanRelocation(
                                                  *relocation, *m_pModule, **rs);
@@ -450,12 +586,18 @@
   /// In ELF, will compute  the size of.symtab, .strtab, .dynsym, .dynstr,
   /// .hash and .shstrtab sections.
   ///
-  /// dump all symbols and strings from FragmentLinker and build the format-dependent
+  /// dump all symbols and strings from ObjectLinker and build the format-dependent
   /// hash table.
   /// @note sizeNamePools replies on LinkerConfig::CodePosition. Must determine
   /// code position model before calling GNULDBackend::sizeNamePools()
   m_LDBackend.sizeNamePools(*m_pModule);
 
+  // Do this after backend prelayout since it may add eh_frame entries.
+  LDSection* eh_frame_sect = m_pModule->getSection(".eh_frame");
+  if (eh_frame_sect && eh_frame_sect->hasEhFrame())
+    eh_frame_sect->getEhFrame()->computeOffsetSize();
+  m_LDBackend.createAndSizeEhFrameHdr(*m_pModule);
+
   return true;
 }
 
@@ -478,30 +620,69 @@
 }
 
 /// finalizeSymbolValue - finalize the resolved symbol value.
-///   Before relocate(), after layout(), FragmentLinker should correct value of all
+///   Before relocate(), after layout(), ObjectLinker should correct value of all
 ///   symbol.
 bool ObjectLinker::finalizeSymbolValue()
 {
-  bool finalized = m_pLinker->finalizeSymbols() && m_LDBackend.finalizeSymbols();
-  bool scriptSymsAdded = true;
-  uint64_t symVal;
-  const LinkerScript& script = m_pModule->getScript();
-  LinkerScript::DefSymMap::const_entry_iterator it;
-  LinkerScript::DefSymMap::const_entry_iterator ie = script.defSymMap().end();
+  Module::sym_iterator symbol, symEnd = m_pModule->sym_end();
+  for (symbol = m_pModule->sym_begin(); symbol != symEnd; ++symbol) {
 
-  DefSymParser parser(*m_pModule);
-  for (it = script.defSymMap().begin(); it != ie; ++it) {
-    llvm::StringRef symName =  it.getEntry()->key();
-    llvm::StringRef expr =  it.getEntry()->value();
+    if ((*symbol)->resolveInfo()->isAbsolute() ||
+        (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
+      // absolute symbols should just use its value directly (i.e., the result
+      // of symbol resolution)
+      continue;
+    }
 
-    LDSymbol* symbol = m_pModule->getNamePool().findSymbol(symName);
-    assert(NULL != symbol && "--defsym symbol should be in the name pool");
-    scriptSymsAdded &= parser.parse(expr, symVal);
-    if (!scriptSymsAdded)
-      break;
-    symbol->setValue(symVal);
+    if ((*symbol)->resolveInfo()->type() == ResolveInfo::ThreadLocal) {
+      m_LDBackend.finalizeTLSSymbol(**symbol);
+      continue;
+    }
+
+    if ((*symbol)->hasFragRef()) {
+      // set the virtual address of the symbol. If the output file is
+      // relocatable object file, the section's virtual address becomes zero.
+      // And the symbol's value become section relative offset.
+      uint64_t value = (*symbol)->fragRef()->getOutputOffset();
+      assert(NULL != (*symbol)->fragRef()->frag());
+      uint64_t addr =
+        (*symbol)->fragRef()->frag()->getParent()->getSection().addr();
+      (*symbol)->setValue(value + addr);
+      continue;
+    }
   }
-  return finalized && scriptSymsAdded ;
+
+  RpnEvaluator evaluator(*m_pModule, m_LDBackend);
+  bool finalized = m_LDBackend.finalizeSymbols();
+  bool scriptSymsFinalized = true;
+  LinkerScript& script = m_pModule->getScript();
+  LinkerScript::Assignments::iterator assign, assignEnd;
+  assignEnd = script.assignments().end();
+  for (assign = script.assignments().begin(); assign != assignEnd; ++assign) {
+    LDSymbol* symbol = (*assign).first;
+    Assignment& assignment = (*assign).second;
+
+    if (symbol == NULL)
+      continue;
+
+    scriptSymsFinalized &= assignment.assign(evaluator);
+    if (!scriptSymsFinalized)
+      break;
+
+    symbol->setValue(assignment.symbol().value());
+  } // for each script symbol assignment
+
+  bool assertionsPassed = true;
+  LinkerScript::Assertions::iterator assert, assertEnd;
+  assertEnd = script.assertions().end();
+  for (assert = script.assertions().begin(); assert != assertEnd; ++assert) {
+    uint64_t res = 0x0;
+    evaluator.eval((*assert).getRpnExpr(), res);
+    if (res == 0x0)
+      fatal(diag::err_assert_failed) << (*assert).message();
+  } // for each assertion in ldscript
+
+  return finalized && scriptSymsFinalized && assertionsPassed;
 }
 
 /// relocate - applying relocation entries and create relocation
@@ -511,20 +692,66 @@
 /// and push_back into the relocation section
 bool ObjectLinker::relocation()
 {
-  return m_pLinker->applyRelocations();
+  // when producing relocatables, no need to apply relocation
+  if (LinkerConfig::Object == m_Config.codeGenType())
+    return true;
+
+  // apply all relocations of all inputs
+  Module::obj_iterator input, inEnd = m_pModule->obj_end();
+  for (input = m_pModule->obj_begin(); input != inEnd; ++input) {
+    m_LDBackend.getRelocator()->initializeApply(**input);
+    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+      // bypass the reloc section if
+      // 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, rEnd = (*rs)->getRelocData()->end();
+      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
+        Relocation* relocation = llvm::cast<Relocation>(reloc);
+
+        // bypass the reloc if the symbol is in the discarded input section
+        ResolveInfo* info = relocation->symInfo();
+        if (!info->outSymbol()->hasFragRef() &&
+            ResolveInfo::Section == info->type() &&
+            ResolveInfo::Undefined == info->desc())
+          continue;
+
+        relocation->apply(*m_LDBackend.getRelocator());
+      } // for all relocations
+    } // for all relocation section
+    m_LDBackend.getRelocator()->finalizeApply(**input);
+  } // for all inputs
+
+  // apply relocations created by relaxation
+  BranchIslandFactory* br_factory = m_LDBackend.getBRIslandFactory();
+  BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
+  for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
+    BranchIsland& island = *facIter;
+    BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
+    for (iter = island.reloc_begin(); iter != iterEnd; ++iter)
+      (*iter)->apply(*m_LDBackend.getRelocator());
+  }
+  return true;
 }
 
 /// emitOutput - emit the output file.
-bool ObjectLinker::emitOutput(MemoryArea& pOutput)
+bool ObjectLinker::emitOutput(FileOutputBuffer& pOutput)
 {
   return llvm::errc::success == getWriter()->writeObject(*m_pModule, pOutput);
 }
 
 
 /// postProcessing - do modification after all processes
-bool ObjectLinker::postProcessing(MemoryArea& pOutput)
+bool ObjectLinker::postProcessing(FileOutputBuffer& pOutput)
 {
-  m_pLinker->syncRelocationResult(pOutput);
+  if (LinkerConfig::Object != m_Config.codeGenType())
+    normalSyncRelocationResult(pOutput);
+  else
+    partialSyncRelocationResult(pOutput);
 
   // emit .eh_frame_hdr
   // eh_frame_hdr should be emitted after syncRelocation, because eh_frame_hdr
@@ -533,3 +760,125 @@
   return true;
 }
 
+void ObjectLinker::normalSyncRelocationResult(FileOutputBuffer& pOutput)
+{
+  uint8_t* data = pOutput.getBufferStart();
+
+  // sync all relocations of all inputs
+  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
+      // 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, rEnd = (*rs)->getRelocData()->end();
+      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
+        Relocation* relocation = llvm::cast<Relocation>(reloc);
+
+        // bypass the reloc if the symbol is in the discarded input section
+        ResolveInfo* info = relocation->symInfo();
+        if (!info->outSymbol()->hasFragRef() &&
+            ResolveInfo::Section == info->type() &&
+            ResolveInfo::Undefined == info->desc())
+          continue;
+
+        // bypass the relocation with NONE type. This is to avoid overwrite the
+        // target result by NONE type relocation if there is a place which has
+        // two relocations to apply to, and one of it is NONE type. The result
+        // we want is the value of the other relocation result. For example,
+        // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
+        // the same place
+        if (0x0 == relocation->type())
+          continue;
+        writeRelocationResult(*relocation, data);
+      } // for all relocations
+    } // for all relocation section
+  } // for all inputs
+
+  // sync relocations created by relaxation
+  BranchIslandFactory* br_factory = m_LDBackend.getBRIslandFactory();
+  BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
+  for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
+    BranchIsland& island = *facIter;
+    BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
+    for (iter = island.reloc_begin(); iter != iterEnd; ++iter) {
+      Relocation* reloc = *iter;
+      writeRelocationResult(*reloc, data);
+    }
+  }
+}
+
+void ObjectLinker::partialSyncRelocationResult(FileOutputBuffer& pOutput)
+{
+  uint8_t* data = pOutput.getBufferStart();
+
+  // traverse outputs' LDSection to get RelocData
+  Module::iterator sectIter, sectEnd = m_pModule->end();
+  for (sectIter = m_pModule->begin(); sectIter != sectEnd; ++sectIter) {
+    if (LDFileFormat::Relocation != (*sectIter)->kind())
+      continue;
+
+    RelocData* reloc_data = (*sectIter)->getRelocData();
+    RelocData::iterator relocIter, relocEnd = reloc_data->end();
+    for (relocIter = reloc_data->begin(); relocIter != relocEnd; ++relocIter) {
+      Relocation* reloc = llvm::cast<Relocation>(relocIter);
+
+      // bypass the relocation with NONE type. This is to avoid overwrite the
+      // target result by NONE type relocation if there is a place which has
+      // two relocations to apply to, and one of it is NONE type. The result
+      // we want is the value of the other relocation result. For example,
+      // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
+      // the same place
+      if (0x0 == reloc->type())
+        continue;
+      writeRelocationResult(*reloc, data);
+    }
+  }
+}
+
+void ObjectLinker::writeRelocationResult(Relocation& pReloc, uint8_t* pOutput)
+{
+  // get output file offset
+  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(pReloc.size(*m_LDBackend.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);
+         break;
+
+       case 64u:
+         tmp_data = mcld::bswap64(pReloc.target());
+         std::memcpy(target_addr, &tmp_data, 8);
+         break;
+
+       default:
+         break;
+    }
+  }
+  else
+    std::memcpy(target_addr, &pReloc.target(),
+                                      pReloc.size(*m_LDBackend.getRelocator())/8);
+}
+
diff --git a/lib/Object/SectionMap.cpp b/lib/Object/SectionMap.cpp
index d3da574..64c4a87 100644
--- a/lib/Object/SectionMap.cpp
+++ b/lib/Object/SectionMap.cpp
@@ -7,112 +7,385 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/Object/SectionMap.h>
-#include <mcld/ADT/StringHash.h>
+#include <mcld/Script/Assignment.h>
+#include <mcld/Script/WildcardPattern.h>
+#include <mcld/Script/StringList.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Script/Operator.h>
+#include <mcld/Script/RpnExpr.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Fragment/NullFragment.h>
+#include <llvm/Support/Casting.h>
 #include <cassert>
 #include <cstring>
+#include <climits>
+#if !defined(MCLD_ON_WIN32)
+#include <fnmatch.h>
+#define fnmatch0(pattern,string) (fnmatch(pattern,string,0) == 0)
+#else
+#include <windows.h>
+#include <shlwapi.h>
+#define fnmatch0(pattern,string) (PathMatchSpec(string, pattern) == true)
+#endif
 
 using namespace mcld;
-
-
-SectionMap::NamePair SectionMap::NullName;
-
 //===----------------------------------------------------------------------===//
-// SectionMap::NamePair
+// SectionMap::Input
 //===----------------------------------------------------------------------===//
-SectionMap::NamePair::NamePair()
-  : hash(-1) {
-}
-
-SectionMap::NamePair::NamePair(const std::string& pFrom, const std::string& pTo)
-  : from(pFrom), to(pTo) {
-  hash = SectionMap::hash(pFrom);
-}
-
-bool SectionMap::NamePair::isNull() const
+SectionMap::Input::Input(const std::string& pName,
+                         InputSectDesc::KeepPolicy pPolicy)
+  : m_Policy(pPolicy)
 {
-  return (&NullName == this);
+  m_Spec.m_pWildcardFile =
+    WildcardPattern::create("*", WildcardPattern::SORT_NONE);
+  m_Spec.m_pExcludeFiles = NULL;
+
+  StringList* sections = StringList::create();
+  sections->push_back(
+    WildcardPattern::create(pName, WildcardPattern::SORT_NONE));
+  m_Spec.m_pWildcardSections = sections;
+
+  m_pSection = LDSection::Create(pName, LDFileFormat::Regular, 0, 0);
+  SectionData* sd = SectionData::Create(*m_pSection);
+  m_pSection->setSectionData(sd);
+  new NullFragment(sd);
+  new NullFragment(sd);
+}
+
+SectionMap::Input::Input(const InputSectDesc& pInputDesc)
+  : m_Policy(pInputDesc.policy())
+{
+  m_Spec.m_pWildcardFile = pInputDesc.spec().m_pWildcardFile;
+  m_Spec.m_pExcludeFiles = pInputDesc.spec().m_pExcludeFiles;
+  m_Spec.m_pWildcardSections = pInputDesc.spec().m_pWildcardSections;
+  m_pSection = LDSection::Create("", LDFileFormat::Regular, 0, 0);
+  SectionData* sd = SectionData::Create(*m_pSection);
+  m_pSection->setSectionData(sd);
+  new NullFragment(sd);
+  new NullFragment(sd);
+}
+
+//===----------------------------------------------------------------------===//
+// SectionMap::Output
+//===----------------------------------------------------------------------===//
+SectionMap::Output::Output(const std::string& pName)
+  : m_Name(pName),
+    m_Order(UINT_MAX)
+{
+  m_Prolog.m_pVMA = NULL;
+  m_Prolog.m_Type = OutputSectDesc::LOAD;
+  m_Prolog.m_pLMA = NULL;
+  m_Prolog.m_pAlign = NULL;
+  m_Prolog.m_pSubAlign = NULL;
+  m_Prolog.m_Constraint = OutputSectDesc::NO_CONSTRAINT;
+
+  m_Epilog.m_pRegion = NULL;
+  m_Epilog.m_pLMARegion = NULL;
+  m_Epilog.m_pPhdrs = NULL;
+  m_Epilog.m_pFillExp = NULL;
+
+  m_pSection = LDSection::Create(pName, LDFileFormat::Regular, 0, 0);
+  SectionData* sd = SectionData::Create(*m_pSection);
+  m_pSection->setSectionData(sd);
+
+  m_bIsDiscard = pName.compare("/DISCARD/") == 0;
+}
+
+SectionMap::Output::Output(const OutputSectDesc& pOutputDesc)
+  : m_Name(pOutputDesc.name()),
+    m_Prolog(pOutputDesc.prolog()),
+    m_Epilog(pOutputDesc.epilog()),
+    m_Order(UINT_MAX)
+{
+  m_pSection = LDSection::Create(m_Name, LDFileFormat::Regular, 0, 0);
+  SectionData* sd = SectionData::Create(*m_pSection);
+  m_pSection->setSectionData(sd);
+
+  m_bIsDiscard = m_Name.compare("/DISCARD/") == 0;
+}
+
+bool SectionMap::Output::hasContent() const
+{
+  return m_pSection != NULL && m_pSection->size() != 0;
+}
+
+SectionMap::Output::const_dot_iterator
+SectionMap::Output::find_first_explicit_dot() const
+{
+  for (const_dot_iterator it = dot_begin(), ie = dot_end(); it != ie; ++it) {
+    if ((*it).type() == Assignment::DEFAULT)
+      return it;
+  }
+  return dot_end();
+}
+
+SectionMap::Output::dot_iterator SectionMap::Output::find_first_explicit_dot()
+{
+  for (dot_iterator it = dot_begin(), ie = dot_end(); it != ie; ++it) {
+    if ((*it).type() == Assignment::DEFAULT)
+      return it;
+  }
+  return dot_end();
+}
+
+SectionMap::Output::const_dot_iterator
+SectionMap::Output::find_last_explicit_dot() const
+{
+  typedef DotAssignments::const_reverse_iterator CONST_RIT;
+  for (CONST_RIT rit = dotAssignments().rbegin(), rie = dotAssignments().rend();
+    rit != rie; ++rit) {
+    if ((*rit).type() == Assignment::DEFAULT) {
+      return dot_begin() +
+             (dotAssignments().size() - (rit - dotAssignments().rbegin()) - 1);
+    }
+  }
+  return dot_end();
+}
+
+SectionMap::Output::dot_iterator SectionMap::Output::find_last_explicit_dot()
+{
+  typedef DotAssignments::reverse_iterator RIT;
+  for (RIT rit = dotAssignments().rbegin(), rie = dotAssignments().rend();
+    rit != rie; ++rit) {
+    if ((*rit).type() == Assignment::DEFAULT) {
+      return dot_begin() +
+             (dotAssignments().size() - (rit - dotAssignments().rbegin()) - 1);
+    }
+  }
+  return dot_end();
 }
 
 //===----------------------------------------------------------------------===//
 // SectionMap
 //===----------------------------------------------------------------------===//
-const SectionMap::NamePair& SectionMap::find(const std::string& pFrom) const
+SectionMap::~SectionMap()
 {
-  unsigned int hash = SectionMap::hash(pFrom);
-  return find(pFrom, hash);
-}
-
-SectionMap::NamePair& SectionMap::find(const std::string& pFrom)
-{
-  unsigned int hash = SectionMap::hash(pFrom);
-  return find(pFrom, hash);
-}
-
-const SectionMap::NamePair&
-SectionMap::find(const std::string& pFrom, unsigned int pHash) const
-{
-  NamePairList::const_iterator name_hash, nEnd = m_NamePairList.end();
-  for (name_hash = m_NamePairList.begin(); name_hash != nEnd; ++name_hash) {
-    if (matched(*name_hash, pFrom, pHash)) {
-      return *name_hash;
+  iterator out, outBegin = begin(), outEnd = end();
+  for (out = outBegin; out != outEnd; ++out) {
+    if (*out != NULL) {
+      Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
+      for (in = inBegin; in != inEnd; ++in) {
+        if (*in != NULL)
+          delete *in;
+      }
+      delete *out;
     }
   }
-  return NullName;
 }
 
-SectionMap::NamePair&
-SectionMap::find(const std::string& pFrom, unsigned int pHash)
+SectionMap::const_mapping
+SectionMap::find(const std::string& pInputFile,
+                 const std::string& pInputSection) const
 {
-  NamePairList::iterator name_hash, nEnd = m_NamePairList.end();
-  for (name_hash = m_NamePairList.begin(); name_hash != nEnd; ++name_hash) {
-    if (matched(*name_hash, pFrom, pHash)) {
-      return *name_hash;
+  const_iterator out, outBegin = begin(), outEnd = end();
+  for (out = outBegin; out != outEnd; ++out) {
+    Output::const_iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
+    for (in = inBegin; in != inEnd; ++in) {
+      if (matched(**in, pInputFile, pInputSection))
+        return std::make_pair(*out, *in);
     }
   }
-  return NullName;
+  return std::make_pair((const Output*)NULL, (const Input*)NULL);
 }
 
-SectionMap::NamePair& SectionMap::append(const std::string &pFrom,
-                                         const std::string &pTo,
-                                         bool &pExist)
+SectionMap::mapping SectionMap::find(const std::string& pInputFile,
+                                     const std::string& pInputSection)
 {
-  NamePair& result = find(pFrom);
-  if (!result.isNull()) {
-    pExist = true;
-    return result;
+  iterator out, outBegin = begin(), outEnd = end();
+  for (out = outBegin; out != outEnd; ++out) {
+    Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
+    for (in = inBegin; in != inEnd; ++in) {
+      if (matched(**in, pInputFile, pInputSection))
+        return std::make_pair(*out, *in);
+    }
+  }
+  return std::make_pair((Output*)NULL, (Input*)NULL);
+}
+
+SectionMap::const_iterator
+SectionMap::find(const std::string& pOutputSection) const
+{
+  const_iterator out, outBegin = begin(), outEnd = end();
+  for (out = outBegin; out != outEnd; ++out) {
+    if ((*out)->name().compare(pOutputSection) == 0)
+      return out;
+  }
+  return outEnd;
+}
+
+SectionMap::iterator
+SectionMap::find(const std::string& pOutputSection)
+{
+  iterator out, outBegin = begin(), outEnd = end();
+  for (out = outBegin; out != outEnd; ++out) {
+    if ((*out)->name().compare(pOutputSection) == 0)
+      return out;
+  }
+  return outEnd;
+}
+
+std::pair<SectionMap::mapping, bool>
+SectionMap::insert(const std::string& pInputSection,
+                   const std::string& pOutputSection,
+                   InputSectDesc::KeepPolicy pPolicy)
+{
+  iterator out, outBegin = begin(), outEnd = end();
+  for (out = outBegin; out != outEnd; ++out) {
+    if ((*out)->name().compare(pOutputSection) == 0)
+      break;
+  }
+  if (out != end()) {
+    Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
+    for (in = inBegin; in != inEnd; ++in) {
+      if ((*in)->getSection()->name().compare(pInputSection) == 0)
+        break;
+    }
+
+    if (in != (*out)->end()) {
+      return std::make_pair(std::make_pair(*out, *in), false);
+    } else {
+      Input* input = new Input(pInputSection, pPolicy);
+      (*out)->append(input);
+      return std::make_pair(std::make_pair(*out, input), true);
+    }
   }
 
-  pExist = false;
-  NamePair entry(pFrom, pTo);
-  m_NamePairList.push_back(entry);
-  return m_NamePairList.back();
+  Output* output = new Output(pOutputSection);
+  m_OutputDescList.push_back(output);
+  Input* input = new Input(pInputSection, pPolicy);
+  output->append(input);
+
+  return std::make_pair(std::make_pair(output, input), true);
 }
 
-bool SectionMap::matched(const NamePair& pNamePair,
-                         const std::string& pInput,
-                         unsigned int pHashValue) const
+std::pair<SectionMap::mapping, bool>
+SectionMap::insert(const InputSectDesc& pInputDesc,
+                   const OutputSectDesc& pOutputDesc)
 {
-  if ('*' == pNamePair.from[0])
-    return true;
+  iterator out, outBegin = begin(), outEnd = end();
+  for (out = outBegin; out != outEnd; ++out) {
+    if ((*out)->name().compare(pOutputDesc.name()) == 0 &&
+        (*out)->prolog() == pOutputDesc.prolog() &&
+        (*out)->epilog() == pOutputDesc.epilog())
+      break;
+  }
 
-  if (pNamePair.from.size() > pInput.size())
-    return false;
+  if (out != end()) {
+    Output::iterator in, inBegin = (*out)->begin(), inEnd = (*out)->end();
+    for (in = inBegin; in != inEnd; ++in) {
+      if ((*in)->policy() == pInputDesc.policy() &&
+          (*in)->spec() == pInputDesc.spec())
+        break;
+    }
 
-  if (!hash::StringHash<hash::ES>::may_include(pNamePair.hash, pHashValue))
-    return false;
+    if (in != (*out)->end()) {
+      return std::make_pair(std::make_pair(*out, *in), false);
+    } else {
+      Input* input = new Input(pInputDesc);
+      (*out)->append(input);
+      return std::make_pair(std::make_pair(*out, input), true);
+    }
+  }
 
-  if (0 == strncmp(pInput.c_str(),
-                   pNamePair.from.c_str(),
-                   pNamePair.from.size())) {
-    return true;
+  Output* output = new Output(pOutputDesc);
+  m_OutputDescList.push_back(output);
+  Input* input = new Input(pInputDesc);
+  output->append(input);
+
+  return std::make_pair(std::make_pair(output, input), true);
+}
+
+SectionMap::iterator
+SectionMap::insert(iterator pPosition, LDSection* pSection)
+{
+  Output* output = new Output(pSection->name());
+  output->append(new Input(pSection->name(), InputSectDesc::NoKeep));
+  output->setSection(pSection);
+  return m_OutputDescList.insert(pPosition, output);
+}
+
+bool SectionMap::matched(const SectionMap::Input& pInput,
+                         const std::string& pInputFile,
+                         const std::string& pInputSection) const
+{
+  if (pInput.spec().hasFile() && !matched(pInput.spec().file(), pInputFile))
+      return false;
+
+  if (pInput.spec().hasExcludeFiles()) {
+    StringList::const_iterator file, fileEnd;
+    fileEnd = pInput.spec().excludeFiles().end();
+    for (file = pInput.spec().excludeFiles().begin(); file != fileEnd; ++file) {
+      if (matched(llvm::cast<WildcardPattern>(**file), pInputFile)) {
+        return false;
+      }
+    }
+  }
+
+  if (pInput.spec().hasSections()) {
+    StringList::const_iterator sect, sectEnd = pInput.spec().sections().end();
+    for (sect = pInput.spec().sections().begin(); sect != sectEnd; ++sect) {
+      if (matched(llvm::cast<WildcardPattern>(**sect), pInputSection)) {
+        return true;
+      }
+    }
   }
 
   return false;
 }
 
-unsigned int SectionMap::hash(const std::string& pString)
+bool SectionMap::matched(const WildcardPattern& pPattern,
+                         const std::string& pName) const
 {
-  static hash::StringHash<hash::ES> hash_func;
-  return hash_func(pString);
+  if (pPattern.isPrefix()) {
+    llvm::StringRef name(pName);
+    return name.startswith(pPattern.prefix());
+  } else {
+    return fnmatch0(pPattern.name().c_str(), pName.c_str());
+  }
 }
 
+// fixupDotSymbols - ensure the dot symbols are valid
+void SectionMap::fixupDotSymbols()
+{
+  for (iterator it = begin() + 1, ie = end(); it != ie; ++it) {
+    // fixup the 1st explicit dot assignment if needed
+    if (!(*it)->dotAssignments().empty()) {
+      Output::dot_iterator dot = (*it)->find_first_explicit_dot();
+      if (dot != (*it)->dot_end() &&
+          (*dot).symbol().isDot() &&
+          (*dot).getRpnExpr().hasDot()) {
+        Assignment assign(Assignment::OUTPUT_SECTION,
+                          Assignment::DEFAULT,
+                          *SymOperand::create("."),
+                          *RpnExpr::buildHelperExpr(it - 1));
+        Output::dot_iterator ref = (*it)->dotAssignments().insert(dot, assign);
+        for (RpnExpr::iterator tok = (*dot).getRpnExpr().begin(),
+          tokEnd = (*dot).getRpnExpr().end();  tok != tokEnd; ++tok) {
+          if ((*tok)->kind() == ExprToken::OPERAND &&
+              llvm::cast<Operand>(*tok)->isDot())
+            *tok = &((*ref).symbol());
+        } // for each token in the RHS expr of the dot assignment
+      }
+    }
+
+    // fixup dot in output VMA if needed
+    if ((*it)->prolog().hasVMA() && (*it)->prolog().vma().hasDot()) {
+      Output::dot_iterator dot = (*it)->find_last_explicit_dot();
+      if (dot == (*it)->dot_end()) {
+        Assignment assign(Assignment::OUTPUT_SECTION,
+                          Assignment::DEFAULT,
+                          *SymOperand::create("."),
+                          *RpnExpr::buildHelperExpr(it - 1));
+        dot = (*it)->dotAssignments().insert(dot, assign);
+      }
+      for (RpnExpr::iterator tok = (*it)->prolog().vma().begin(),
+        tokEnd = (*it)->prolog().vma().end();  tok != tokEnd; ++tok) {
+        if ((*tok)->kind() == ExprToken::OPERAND &&
+            llvm::cast<Operand>(*tok)->isDot())
+          *tok = &((*dot).symbol());
+      } // for each token in the RHS expr of the dot assignment
+    }
+
+  } // for each output section
+}
diff --git a/lib/Script/AssertCmd.cpp b/lib/Script/AssertCmd.cpp
new file mode 100644
index 0000000..618731d
--- /dev/null
+++ b/lib/Script/AssertCmd.cpp
@@ -0,0 +1,48 @@
+//===- AssertCmd.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/AssertCmd.h>
+#include <mcld/Script/RpnExpr.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Module.h>
+#include <mcld/LinkerScript.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// AssertCmd
+//===----------------------------------------------------------------------===//
+AssertCmd::AssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage)
+  : ScriptCommand(ScriptCommand::ASSERT),
+    m_RpnExpr(pRpnExpr),
+    m_Message(pMessage)
+{
+}
+
+AssertCmd::~AssertCmd()
+{
+}
+
+AssertCmd& AssertCmd::operator=(const AssertCmd& pAssertCmd)
+{
+  return *this;
+}
+
+void AssertCmd::dump() const
+{
+  mcld::outs() << "Assert ( ";
+
+  m_RpnExpr.dump();
+
+  mcld::outs() << " , " << m_Message << " )\n";
+}
+
+void AssertCmd::activate(Module& pModule)
+{
+  pModule.getScript().assertions().push_back(*this);
+}
diff --git a/lib/Script/Assignment.cpp b/lib/Script/Assignment.cpp
new file mode 100644
index 0000000..a7e0f46
--- /dev/null
+++ b/lib/Script/Assignment.cpp
@@ -0,0 +1,175 @@
+//===- Assignment.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/Assignment.h>
+#include <mcld/Script/RpnExpr.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Script/Operator.h>
+#include <mcld/Script/RpnEvaluator.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Module.h>
+#include <llvm/Support/Casting.h>
+#include <cassert>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Assignment
+//===----------------------------------------------------------------------===//
+Assignment::Assignment(Level pLevel,
+                       Type pType,
+                       SymOperand& pSymbol,
+                       RpnExpr& pRpnExpr)
+  : ScriptCommand(ScriptCommand::ASSIGNMENT),
+    m_Level(pLevel),
+    m_Type(pType),
+    m_Symbol(pSymbol),
+    m_RpnExpr(pRpnExpr)
+{
+}
+
+Assignment::~Assignment()
+{
+}
+
+Assignment& Assignment::operator=(const Assignment& pAssignment)
+{
+  return *this;
+}
+
+void Assignment::dump() const
+{
+  switch (type()) {
+  case DEFAULT:
+    break;
+  case HIDDEN:
+    mcld::outs() << "HIDDEN ( ";
+    break;
+  case PROVIDE:
+    mcld::outs() << "PROVIDE ( ";
+    break;
+  case PROVIDE_HIDDEN:
+    mcld::outs() << "PROVIDE_HIDDEN ( ";
+    break;
+  default:
+    break;
+  }
+
+  m_Symbol.dump();
+
+  mcld::outs() << " = ";
+
+  m_RpnExpr.dump();
+
+  if (type() != DEFAULT)
+    mcld::outs() << " )";
+
+  mcld::outs() << ";\n";
+}
+
+void Assignment::activate(Module& pModule)
+{
+  bool isLhsDot = m_Symbol.isDot();
+  LinkerScript& script = pModule.getScript();
+  switch (m_Level) {
+  case OUTSIDE_SECTIONS:
+    assert(!isLhsDot);
+    script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
+    break;
+
+  case OUTPUT_SECTION: {
+    bool hasDotInRhs = m_RpnExpr.hasDot();
+    SectionMap::reference out = script.sectionMap().back();
+    if (hasDotInRhs) {
+      if (!isLhsDot && out->dotAssignments().empty()) {
+        // . = ADDR ( `prev_output_sect' ) + SIZEOF ( `prev_output_sect' )
+        SectionMap::iterator prev = script.sectionMap().begin() +
+                                    script.sectionMap().size() - 2;
+        Assignment assign(OUTPUT_SECTION,
+                          HIDDEN,
+                          *SymOperand::create("."),
+                          *RpnExpr::buildHelperExpr(prev));
+        out->dotAssignments().push_back(assign);
+      }
+
+      if (!out->dotAssignments().empty()) {
+        Assignment& prevDotAssign = out->dotAssignments().back();
+        // If this is the 1st explicit assignment that includes both lhs dot and
+        // rhs dot, then because of possible orphan sections, we are unable to
+        // substitute the rhs dot now.
+        if (!isLhsDot || prevDotAssign.type() == DEFAULT) {
+          for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
+            it != ie; ++it) {
+            // substitute the rhs dot with the appropriate helper expr
+            if ((*it)->kind() == ExprToken::OPERAND &&
+                llvm::cast<Operand>(*it)->isDot())
+              *it = &(prevDotAssign.symbol());
+          } // for each expression token
+        }
+      }
+    }
+
+    if (isLhsDot) {
+      out->dotAssignments().push_back(*this);
+    } else {
+      script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
+    }
+
+    break;
+  }
+
+  case INPUT_SECTION: {
+    bool hasDotInRhs = m_RpnExpr.hasDot();
+    SectionMap::Output::reference in = script.sectionMap().back()->back();
+    if (hasDotInRhs) {
+      if (in->dotAssignments().empty()) {
+        // . = `frag'
+        RpnExpr* expr =
+          RpnExpr::buildHelperExpr(in->getSection()->getSectionData()->front());
+        Assignment assign(INPUT_SECTION,
+                          HIDDEN,
+                          *SymOperand::create("."),
+                          *expr);
+        in->dotAssignments().push_back(std::make_pair((Fragment*)NULL, assign));
+      }
+
+      Assignment& prevDotAssign = in->dotAssignments().back().second;
+      for (RpnExpr::iterator it = m_RpnExpr.begin(), ie = m_RpnExpr.end();
+        it != ie; ++it) {
+        // substitute the rhs dot with the appropriate helper expr
+        if ((*it)->kind() == ExprToken::OPERAND &&
+            llvm::cast<Operand>(*it)->isDot())
+          *it = &(prevDotAssign.symbol());
+      } // end of for
+    }
+
+    if (isLhsDot) {
+      in->dotAssignments().push_back(
+        std::make_pair(in->getSection()->getSectionData()->front().getNextNode(),
+                       *this));
+    } else {
+      script.assignments().push_back(std::make_pair((LDSymbol*)NULL, *this));
+    }
+
+    break;
+  }
+
+  } // end of switch
+}
+
+bool Assignment::assign(RpnEvaluator& pEvaluator)
+{
+  uint64_t result = 0;
+  bool success = pEvaluator.eval(m_RpnExpr, result);
+  if (success)
+    m_Symbol.setValue(result);
+  return success;
+}
diff --git a/lib/Script/BinaryOp.cpp b/lib/Script/BinaryOp.cpp
new file mode 100644
index 0000000..863eb34
--- /dev/null
+++ b/lib/Script/BinaryOp.cpp
@@ -0,0 +1,268 @@
+//===- BinaryOp.cpp -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/BinaryOp.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/ADT/SizeTraits.h>
+#include <mcld/Module.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <llvm/Support/Casting.h>
+#include <cassert>
+
+using namespace mcld;
+//===----------------------------------------------------------------------===//
+// BinaryOp
+//===----------------------------------------------------------------------===//
+template<>
+IntOperand* BinaryOp<Operator::MUL>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() * m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::DIV>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() / m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::MOD>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() % m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::ADD>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() + m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::SUB>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() - m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::LSHIFT>::eval(const Module& pModule,
+                                             const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() << m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::RSHIFT>::eval(const Module& pModule,
+                                             const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() >> m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::LT>::eval(const Module& pModule,
+                                         const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() < m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::LE>::eval(const Module& pModule,
+                                         const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() <= m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::GT>::eval(const Module& pModule,
+                                         const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() > m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::GE>::eval(const Module& pModule,
+                                         const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() >= m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::EQ>::eval(const Module& pModule,
+                                         const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() == m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::NE>::eval(const Module& pModule,
+                                         const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() != m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand*
+BinaryOp<Operator::BITWISE_AND>::eval(const Module& pModule,
+                                      const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() & m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand*
+BinaryOp<Operator::BITWISE_XOR>::eval(const Module& pModule,
+                                      const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() ^ m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand*
+BinaryOp<Operator::BITWISE_OR>::eval(const Module& pModule,
+                                     const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() | m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand*
+BinaryOp<Operator::LOGICAL_AND>::eval(const Module& pModule,
+                                      const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() && m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand*
+BinaryOp<Operator::LOGICAL_OR>::eval(const Module& pModule,
+                                     const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand[0]->value() || m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::ALIGN>::eval(const Module& pModule,
+                                            const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  uint64_t value = m_pOperand[0]->value();
+  uint64_t align = m_pOperand[1]->value();
+  alignAddress(value, align);
+  res->setValue(value);
+  return res;
+}
+
+template<>
+IntOperand*
+BinaryOp<Operator::DATA_SEGMENT_RELRO_END>::eval(const Module& pModule,
+  const TargetLDBackend& pBackend)
+{
+  /* FIXME: Currently we handle relro in a different way, and now the result
+     of this expression won't affect DATA_SEGMENT_ALIGN. */
+  IntOperand* res = result();
+  uint64_t value = m_pOperand[0]->value() + m_pOperand[1]->value();
+  alignAddress(value, pBackend.commonPageSize());
+  res->setValue(value);
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::MAX>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  if (m_pOperand[0]->value() >= m_pOperand[1]->value())
+    res->setValue(m_pOperand[0]->value());
+  else
+    res->setValue(m_pOperand[1]->value());
+  return res;
+}
+
+template<>
+IntOperand* BinaryOp<Operator::MIN>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  if (m_pOperand[0]->value() <= m_pOperand[1]->value())
+    res->setValue(m_pOperand[0]->value());
+  else
+    res->setValue(m_pOperand[1]->value());
+  return res;
+}
+
+
+/* SEGMENT_START(segment, default) */
+template<>
+IntOperand*
+BinaryOp<Operator::SEGMENT_START>::eval(const Module& pModule,
+                                        const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  /* Currently we look up segment address from -T command line options. */
+  SectOperand* sect = llvm::cast<SectOperand>(m_pOperand[0]);
+  const LinkerScript::AddressMap& addressMap =
+    pModule.getScript().addressMap();
+  LinkerScript::AddressMap::const_iterator addr;
+  if (sect->name().compare("text-segment") == 0)
+    addr = addressMap.find(".text");
+  else if (sect->name().compare("data-segment") == 0)
+    addr = addressMap.find(".data");
+  else if (sect->name().compare("bss-segment") == 0)
+    addr = addressMap.find(".bss");
+  else
+    addr = addressMap.find(sect->name());
+
+  if (addr != addressMap.end())
+    res->setValue(addr.getEntry()->value());
+  else {
+    assert(m_pOperand[1]->type() == Operand::INTEGER);
+    res->setValue(m_pOperand[1]->value());
+  }
+  return res;
+}
diff --git a/lib/Script/CMakeLists.txt b/lib/Script/CMakeLists.txt
new file mode 100644
index 0000000..6fed079
--- /dev/null
+++ b/lib/Script/CMakeLists.txt
@@ -0,0 +1,40 @@
+# flex+bison settings
+find_package(BISON)
+find_package(FLEX)
+BISON_TARGET(PARSER ScriptParser.yy ${CMAKE_CURRENT_BINARY_DIR}/ScriptParser.cpp)
+FLEX_TARGET(LEXER ScriptScanner.ll ${CMAKE_CURRENT_BINARY_DIR}/ScriptScanner.cpp)
+ADD_FLEX_BISON_DEPENDENCY(LEXER PARSER)
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+add_mcld_library(MCLDScript
+  AssertCmd.cpp
+  Assignment.cpp
+  BinaryOp.cpp
+  EntryCmd.cpp
+  FileToken.cpp
+  GroupCmd.cpp
+  InputSectDesc.cpp
+  InputToken.cpp
+  NameSpec.cpp
+  NullaryOp.cpp
+  Operand.cpp
+  Operator.cpp
+  OutputArchCmd.cpp
+  OutputCmd.cpp
+  OutputFormatCmd.cpp
+  OutputSectDesc.cpp
+  RpnEvaluator.cpp
+  RpnExpr.cpp
+  ScriptCommand.cpp
+  ScriptFile.cpp
+  ScriptReader.cpp
+  SearchDirCmd.cpp
+  SectionsCmd.cpp
+  StrToken.cpp
+  StringList.cpp
+  TernaryOp.cpp
+  UnaryOp.cpp
+  WildcardPattern.cpp
+  ${BISON_PARSER_OUTPUTS}
+  ${FLEX_LEXER_OUTPUTS}
+  )
diff --git a/lib/Script/EntryCmd.cpp b/lib/Script/EntryCmd.cpp
new file mode 100644
index 0000000..9e33c53
--- /dev/null
+++ b/lib/Script/EntryCmd.cpp
@@ -0,0 +1,40 @@
+//===- EntryCmd.cpp -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/EntryCmd.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/Module.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// EntryCmd
+//===----------------------------------------------------------------------===//
+EntryCmd::EntryCmd(const std::string& pEntry)
+  : ScriptCommand(ScriptCommand::ENTRY),
+    m_Entry(pEntry)
+{
+}
+
+EntryCmd::~EntryCmd()
+{
+}
+
+void EntryCmd::dump() const
+{
+  mcld::outs() << "ENTRY ( " << m_Entry << " )\n";
+}
+
+void EntryCmd::activate(Module& pModule)
+{
+  LinkerScript& script = pModule.getScript();
+  if (!script.hasEntry())
+    script.setEntry(m_Entry);
+}
+
diff --git a/lib/Script/FileToken.cpp b/lib/Script/FileToken.cpp
new file mode 100644
index 0000000..2247d6e
--- /dev/null
+++ b/lib/Script/FileToken.cpp
@@ -0,0 +1,51 @@
+//===- FileToken.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/FileToken.h>
+#include <mcld/Support/GCFactory.h>
+#include <llvm/Support/ManagedStatic.h>
+
+using namespace mcld;
+
+typedef GCFactory<FileToken, MCLD_SYMBOLS_PER_INPUT> FileTokenFactory;
+static llvm::ManagedStatic<FileTokenFactory> g_FileTokenFactory;
+
+//===----------------------------------------------------------------------===//
+// FileToken
+//===----------------------------------------------------------------------===//
+FileToken::FileToken()
+{
+}
+
+FileToken::FileToken(const std::string& pName, bool pAsNeeded)
+  : InputToken(InputToken::File, pName, pAsNeeded)
+{
+}
+
+FileToken::~FileToken()
+{
+}
+
+FileToken* FileToken::create(const std::string& pName, bool pAsNeeded)
+{
+  FileToken* result = g_FileTokenFactory->allocate();
+  new (result) FileToken(pName, pAsNeeded);
+  return result;
+}
+
+void FileToken::destroy(FileToken*& pFileToken)
+{
+  g_FileTokenFactory->destroy(pFileToken);
+  g_FileTokenFactory->deallocate(pFileToken);
+  pFileToken = NULL;
+}
+
+void FileToken::clear()
+{
+  g_FileTokenFactory->clear();
+}
diff --git a/lib/Script/GroupCmd.cpp b/lib/Script/GroupCmd.cpp
new file mode 100644
index 0000000..4673242
--- /dev/null
+++ b/lib/Script/GroupCmd.cpp
@@ -0,0 +1,165 @@
+//===- GroupCmd.cpp -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/GroupCmd.h>
+#include <mcld/Script/StringList.h>
+#include <mcld/Script/InputToken.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/Support/Path.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/InputTree.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/LD/GroupReader.h>
+#include <llvm/Support/Casting.h>
+#include <cassert>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// GroupCmd
+//===----------------------------------------------------------------------===//
+GroupCmd::GroupCmd(StringList& pStringList,
+                   InputTree& pInputTree,
+                   InputBuilder& pBuilder,
+                   GroupReader& pGroupReader,
+                   const LinkerConfig& pConfig)
+  : ScriptCommand(ScriptCommand::GROUP),
+    m_StringList(pStringList),
+    m_InputTree(pInputTree),
+    m_Builder(pBuilder),
+    m_GroupReader(pGroupReader),
+    m_Config(pConfig)
+{
+}
+
+GroupCmd::~GroupCmd()
+{
+}
+
+void GroupCmd::dump() const
+{
+  mcld::outs() << "GROUP ( ";
+  bool prev = false, cur = false;
+  for (StringList::const_iterator it = m_StringList.begin(),
+    ie = m_StringList.end(); it != ie; ++it) {
+    assert((*it)->kind() == StrToken::Input);
+    InputToken* input = llvm::cast<InputToken>(*it);
+    cur = input->asNeeded();
+    if (!prev && cur)
+      mcld::outs() << "AS_NEEDED ( ";
+    else if (prev && !cur)
+      mcld::outs() << " )";
+
+    if (input->type() == InputToken::NameSpec)
+      mcld::outs() << "-l";
+    mcld::outs() << input->name() << " ";
+
+    prev = cur;
+  }
+
+  if (!m_StringList.empty() && prev)
+    mcld::outs() << " )";
+
+  mcld::outs() << " )\n";
+}
+
+void GroupCmd::activate(Module& pModule)
+{
+  LinkerScript& script = pModule.getScript();
+  // construct the Group tree
+  m_Builder.setCurrentTree(m_InputTree);
+  // --start-group
+  m_Builder.enterGroup();
+  InputTree::iterator group = m_Builder.getCurrentNode();
+
+  for (StringList::const_iterator it = m_StringList.begin(),
+    ie = m_StringList.end(); it != ie; ++it) {
+
+    assert((*it)->kind() == StrToken::Input);
+    InputToken* token = llvm::cast<InputToken>(*it);
+    if (token->asNeeded())
+      m_Builder.getAttributes().setAsNeeded();
+    else
+      m_Builder.getAttributes().unsetAsNeeded();
+
+    switch (token->type()) {
+    case InputToken::File: {
+      sys::fs::Path path;
+
+      // 1. Looking for file in the sysroot prefix, if a sysroot prefix is
+      // configured and the filename starts with '/'
+      if (script.hasSysroot() &&
+          (token->name().size() > 0 && token->name()[0] == '/')) {
+          path = script.sysroot();
+          path.append(token->name());
+      } else {
+        // 2. Try to open the file in CWD
+        path.assign(token->name());
+        if (!sys::fs::exists(path)) {
+          // 3. Search through the library search path
+          sys::fs::Path* p =
+            script.directories().find(token->name(), Input::Script);
+          if (p != NULL)
+            path = *p;
+        }
+      }
+
+      if (!sys::fs::exists(path))
+        fatal(diag::err_cannot_open_input) << path.filename() << path;
+
+      m_Builder.createNode<InputTree::Positional>(
+        path.filename().native(), path, Input::Unknown);
+      break;
+    }
+    case InputToken::NameSpec: {
+      const sys::fs::Path* path = NULL;
+      // find out the real path of the namespec.
+      if (m_Builder.getConstraint().isSharedSystem()) {
+        // In the system with shared object support, we can find both archive
+        // and shared object.
+        if (m_Builder.getAttributes().isStatic()) {
+          // with --static, we must search an archive.
+          path = script.directories().find(token->name(), Input::Archive);
+        } else {
+          // otherwise, with --Bdynamic, we can find either an archive or a
+          // shared object.
+          path = script.directories().find(token->name(), Input::DynObj);
+        }
+      } else {
+        // In the system without shared object support, only look for an archive
+        path = script.directories().find(token->name(), Input::Archive);
+      }
+
+      if (NULL == path)
+        fatal(diag::err_cannot_find_namespec) << token->name();
+
+      m_Builder.createNode<InputTree::Positional>(
+        token->name(), *path, Input::Unknown);
+      break;
+    }
+    default:
+      assert(0 && "Invalid script token in GROUP!");
+      break;
+    } // end of switch
+
+    Input* input = *m_Builder.getCurrentNode();
+    assert(input != NULL);
+    if (!m_Builder.setMemory(*input, FileHandle::ReadOnly))
+      error(diag::err_cannot_open_input) << input->name() << input->path();
+    m_Builder.setContext(*input);
+  }
+
+  // --end-group
+  m_Builder.exitGroup();
+
+  // read the group
+  m_GroupReader.readGroup(group, m_InputTree.end(), m_Builder, m_Config);
+}
+
diff --git a/lib/Script/InputSectDesc.cpp b/lib/Script/InputSectDesc.cpp
new file mode 100644
index 0000000..842b720
--- /dev/null
+++ b/lib/Script/InputSectDesc.cpp
@@ -0,0 +1,102 @@
+//===- InputSectDesc.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/InputSectDesc.h>
+#include <mcld/Script/WildcardPattern.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/Module.h>
+#include <llvm/Support/Casting.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// InputSectDesc
+//===----------------------------------------------------------------------===//
+InputSectDesc::InputSectDesc(KeepPolicy pPolicy,
+                             const Spec& pSpec,
+                             const OutputSectDesc& pOutputDesc)
+  : ScriptCommand(ScriptCommand::INPUT_SECT_DESC),
+    m_KeepPolicy(pPolicy),
+    m_Spec(pSpec),
+    m_OutputSectDesc(pOutputDesc)
+{
+}
+
+InputSectDesc::~InputSectDesc()
+{
+}
+
+void InputSectDesc::dump() const
+{
+  if (m_KeepPolicy == Keep)
+    mcld::outs() << "KEEP (";
+
+  assert (m_Spec.hasFile());
+  if (m_Spec.file().sortPolicy() == WildcardPattern::SORT_BY_NAME)
+    mcld::outs() << "SORT (";
+
+  mcld::outs() << m_Spec.file().name();
+
+  if (m_Spec.hasSections()) {
+    mcld::outs() << "(";
+
+    if (m_Spec.hasExcludeFiles()) {
+      mcld::outs() << "EXCLUDE_FILE (";
+      for (StringList::const_iterator it = m_Spec.excludeFiles().begin(),
+        ie = m_Spec.excludeFiles().end(); it != ie; ++it) {
+        mcld::outs() << (*it)->name() << " ";
+      }
+      mcld::outs() << ")";
+    }
+
+    if (m_Spec.hasSections()) {
+      for (StringList::const_iterator it = m_Spec.sections().begin(),
+        ie = m_Spec.sections().end(); it != ie; ++it) {
+        assert((*it)->kind() == StrToken::Wildcard);
+        WildcardPattern* wildcard = llvm::cast<WildcardPattern>(*it);
+
+        switch (wildcard->sortPolicy()) {
+        case WildcardPattern::SORT_BY_NAME:
+          mcld::outs() << "SORT (";
+          break;
+        case WildcardPattern::SORT_BY_ALIGNMENT:
+          mcld::outs() << "SORT_BY_ALIGNMENT (";
+          break;
+        case WildcardPattern::SORT_BY_NAME_ALIGNMENT:
+          mcld::outs() << "SORT_BY_NAME_ALIGNMENT (";
+          break;
+        case WildcardPattern::SORT_BY_ALIGNMENT_NAME:
+          mcld::outs() << "SORT_BY_ALIGNMENT_NAME (";
+          break;
+        default:
+          break;
+        }
+
+        mcld::outs() << wildcard->name() << " ";
+
+        if (wildcard->sortPolicy() != WildcardPattern::SORT_NONE)
+          mcld::outs() << ")";
+      }
+    }
+    mcld::outs() << ")";
+  }
+
+  if (m_Spec.file().sortPolicy() == WildcardPattern::SORT_BY_NAME)
+    mcld::outs() << ")";
+
+  if (m_KeepPolicy == Keep)
+    mcld::outs() << ")";
+
+  mcld::outs() << "\n";
+}
+
+void InputSectDesc::activate(Module& pModule)
+{
+  pModule.getScript().sectionMap().insert(*this, m_OutputSectDesc);
+}
diff --git a/lib/Script/InputToken.cpp b/lib/Script/InputToken.cpp
new file mode 100644
index 0000000..45b006a
--- /dev/null
+++ b/lib/Script/InputToken.cpp
@@ -0,0 +1,28 @@
+//===- InputToken.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/InputToken.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// InputToken
+//===----------------------------------------------------------------------===//
+InputToken::InputToken()
+  : m_Type(Unknown), m_bAsNeeded(false)
+{
+}
+
+InputToken::InputToken(Type pType, const std::string& pName, bool pAsNeeded)
+  : StrToken(StrToken::Input, pName), m_Type(pType), m_bAsNeeded(pAsNeeded)
+{
+}
+
+InputToken::~InputToken()
+{
+}
diff --git a/lib/Script/NameSpec.cpp b/lib/Script/NameSpec.cpp
new file mode 100644
index 0000000..da7a62c
--- /dev/null
+++ b/lib/Script/NameSpec.cpp
@@ -0,0 +1,51 @@
+//===- NameSpec.cpp -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/NameSpec.h>
+#include <mcld/Support/GCFactory.h>
+#include <llvm/Support/ManagedStatic.h>
+
+using namespace mcld;
+
+typedef GCFactory<NameSpec, MCLD_SYMBOLS_PER_INPUT> NameSpecFactory;
+static llvm::ManagedStatic<NameSpecFactory> g_NameSpecFactory;
+
+//===----------------------------------------------------------------------===//
+// NameSpec
+//===----------------------------------------------------------------------===//
+NameSpec::NameSpec()
+{
+}
+
+NameSpec::NameSpec(const std::string& pName, bool pAsNeeded)
+  : InputToken(InputToken::NameSpec, pName, pAsNeeded)
+{
+}
+
+NameSpec::~NameSpec()
+{
+}
+
+NameSpec* NameSpec::create(const std::string& pName, bool pAsNeeded)
+{
+  NameSpec* result = g_NameSpecFactory->allocate();
+  new (result) NameSpec(pName, pAsNeeded);
+  return result;
+}
+
+void NameSpec::destroy(NameSpec*& pNameSpec)
+{
+  g_NameSpecFactory->destroy(pNameSpec);
+  g_NameSpecFactory->deallocate(pNameSpec);
+  pNameSpec = NULL;
+}
+
+void NameSpec::clear()
+{
+  g_NameSpecFactory->clear();
+}
diff --git a/lib/Script/NullaryOp.cpp b/lib/Script/NullaryOp.cpp
new file mode 100644
index 0000000..69382ec
--- /dev/null
+++ b/lib/Script/NullaryOp.cpp
@@ -0,0 +1,45 @@
+//===- NullaryOp.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/NullaryOp.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Target/TargetLDBackend.h>
+
+using namespace mcld;
+//===----------------------------------------------------------------------===//
+// NullaryOp
+//===----------------------------------------------------------------------===//
+template<>
+IntOperand*
+NullaryOp<Operator::SIZEOF_HEADERS>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(pBackend.sectionStartOffset());
+  return res;
+}
+
+template<>
+IntOperand*
+NullaryOp<Operator::MAXPAGESIZE>::eval(const Module& pModule,
+                                       const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(pBackend.abiPageSize());
+  return res;
+}
+
+template<>
+IntOperand*
+NullaryOp<Operator::COMMONPAGESIZE>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(pBackend.commonPageSize());
+  return res;
+}
diff --git a/lib/Script/Operand.cpp b/lib/Script/Operand.cpp
new file mode 100644
index 0000000..690ba9b
--- /dev/null
+++ b/lib/Script/Operand.cpp
@@ -0,0 +1,241 @@
+//===- Operand.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/Operand.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/GCFactory.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Fragment/Fragment.h>
+#include <llvm/Support/ManagedStatic.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Operand
+//===----------------------------------------------------------------------===//
+Operand::Operand(Type pType)
+  : ExprToken(ExprToken::OPERAND), m_Type(pType)
+{
+}
+
+Operand::~Operand()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// SymOperand
+//===----------------------------------------------------------------------===//
+typedef GCFactory<SymOperand, MCLD_SYMBOLS_PER_INPUT> SymOperandFactory;
+static llvm::ManagedStatic<SymOperandFactory> g_SymOperandFactory;
+
+SymOperand::SymOperand()
+  : Operand(Operand::SYMBOL), m_Value(0)
+{
+}
+
+SymOperand::SymOperand(const std::string& pName)
+  : Operand(Operand::SYMBOL), m_Name(pName), m_Value(0)
+{
+}
+
+void SymOperand::dump() const
+{
+  mcld::outs() << m_Name;
+}
+
+bool SymOperand::isDot() const
+{
+  assert(!m_Name.empty());
+  return m_Name.size() == 1 && m_Name[0] == '.';
+}
+
+SymOperand* SymOperand::create(const std::string& pName)
+{
+  SymOperand* result = g_SymOperandFactory->allocate();
+  new (result) SymOperand(pName);
+  return result;
+}
+
+void SymOperand::destroy(SymOperand*& pOperand)
+{
+  g_SymOperandFactory->destroy(pOperand);
+  g_SymOperandFactory->deallocate(pOperand);
+  pOperand = NULL;
+}
+
+void SymOperand::clear()
+{
+  g_SymOperandFactory->clear();
+}
+
+//===----------------------------------------------------------------------===//
+// IntOperand
+//===----------------------------------------------------------------------===//
+typedef GCFactory<IntOperand, MCLD_SYMBOLS_PER_INPUT> IntOperandFactory;
+static llvm::ManagedStatic<IntOperandFactory> g_IntOperandFactory;
+
+IntOperand::IntOperand()
+  : Operand(Operand::INTEGER), m_Value(0)
+{
+}
+
+IntOperand::IntOperand(uint64_t pValue)
+  : Operand(Operand::INTEGER), m_Value(pValue)
+{
+}
+
+void IntOperand::dump() const
+{
+  mcld::outs() << m_Value;
+}
+
+IntOperand* IntOperand::create(uint64_t pValue)
+{
+  IntOperand* result = g_IntOperandFactory->allocate();
+  new (result) IntOperand(pValue);
+  return result;
+}
+
+void IntOperand::destroy(IntOperand*& pOperand)
+{
+  g_IntOperandFactory->destroy(pOperand);
+  g_IntOperandFactory->deallocate(pOperand);
+  pOperand = NULL;
+}
+
+void IntOperand::clear()
+{
+  g_IntOperandFactory->clear();
+}
+
+//===----------------------------------------------------------------------===//
+// SectOperand
+//===----------------------------------------------------------------------===//
+typedef GCFactory<SectOperand, MCLD_SECTIONS_PER_INPUT> SectOperandFactory;
+static llvm::ManagedStatic<SectOperandFactory> g_SectOperandFactory;
+SectOperand::SectOperand()
+  : Operand(Operand::SECTION)
+{
+}
+
+SectOperand::SectOperand(const std::string& pName)
+  : Operand(Operand::SECTION), m_Name(pName)
+{
+}
+
+void SectOperand::dump() const
+{
+  mcld::outs() << m_Name;
+}
+
+SectOperand* SectOperand::create(const std::string& pName)
+{
+  SectOperand* result = g_SectOperandFactory->allocate();
+  new (result) SectOperand(pName);
+  return result;
+}
+
+void SectOperand::destroy(SectOperand*& pOperand)
+{
+  g_SectOperandFactory->destroy(pOperand);
+  g_SectOperandFactory->deallocate(pOperand);
+  pOperand = NULL;
+}
+
+void SectOperand::clear()
+{
+  g_SectOperandFactory->clear();
+}
+
+//===----------------------------------------------------------------------===//
+// SectDescOperand
+//===----------------------------------------------------------------------===//
+typedef GCFactory<SectDescOperand,
+                  MCLD_SECTIONS_PER_INPUT> SectDescOperandFactory;
+static llvm::ManagedStatic<SectDescOperandFactory> g_SectDescOperandFactory;
+SectDescOperand::SectDescOperand()
+  : Operand(Operand::SECTION_DESC), m_pOutputDesc(NULL)
+{
+}
+
+SectDescOperand::SectDescOperand(const SectionMap::Output* pOutputDesc)
+  : Operand(Operand::SECTION_DESC), m_pOutputDesc(pOutputDesc)
+{
+}
+
+void SectDescOperand::dump() const
+{
+  assert(m_pOutputDesc != NULL);
+  mcld::outs() << m_pOutputDesc->getSection()->name();
+}
+
+SectDescOperand* SectDescOperand::create(const SectionMap::Output* pOutputDesc)
+{
+  SectDescOperand* result = g_SectDescOperandFactory->allocate();
+  new (result) SectDescOperand(pOutputDesc);
+  return result;
+}
+
+void SectDescOperand::destroy(SectDescOperand*& pOperand)
+{
+  g_SectDescOperandFactory->destroy(pOperand);
+  g_SectDescOperandFactory->deallocate(pOperand);
+  pOperand = NULL;
+}
+
+void SectDescOperand::clear()
+{
+  g_SectDescOperandFactory->clear();
+}
+
+//===----------------------------------------------------------------------===//
+// FragOperand
+//===----------------------------------------------------------------------===//
+typedef GCFactory<FragOperand, MCLD_SYMBOLS_PER_INPUT> FragOperandFactory;
+static llvm::ManagedStatic<FragOperandFactory> g_FragOperandFactory;
+
+FragOperand::FragOperand()
+  : Operand(Operand::FRAGMENT), m_pFragment(NULL)
+{
+}
+
+FragOperand::FragOperand(Fragment& pFragment)
+  : Operand(Operand::FRAGMENT), m_pFragment(&pFragment)
+{
+}
+
+void FragOperand::dump() const
+{
+  mcld::outs() << "fragment";
+}
+
+uint64_t FragOperand::value() const
+{
+  return m_pFragment->getOffset() +
+         m_pFragment->getParent()->getSection().addr();
+}
+
+FragOperand* FragOperand::create(Fragment& pFragment)
+{
+  FragOperand* result = g_FragOperandFactory->allocate();
+  new (result) FragOperand(pFragment);
+  return result;
+}
+
+void FragOperand::destroy(FragOperand*& pOperand)
+{
+  g_FragOperandFactory->destroy(pOperand);
+  g_FragOperandFactory->deallocate(pOperand);
+  pOperand = NULL;
+}
+
+void FragOperand::clear()
+{
+  g_FragOperandFactory->clear();
+}
diff --git a/lib/Script/Operator.cpp b/lib/Script/Operator.cpp
new file mode 100644
index 0000000..e50a255
--- /dev/null
+++ b/lib/Script/Operator.cpp
@@ -0,0 +1,390 @@
+//===- Operator.cpp -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/Operator.h>
+#include <mcld/Script/NullaryOp.h>
+#include <mcld/Script/UnaryOp.h>
+#include <mcld/Script/BinaryOp.h>
+#include <mcld/Script/TernaryOp.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Support/raw_ostream.h>
+
+using namespace mcld;
+//===----------------------------------------------------------------------===//
+// Operator
+//===----------------------------------------------------------------------===//
+const char* Operator::OpNames[] = {
+  "+",
+  "-",
+  "!",
+  "~",
+  "*",
+  "/",
+  "%",
+  "+",
+  "-",
+  "<<",
+  ">>",
+  "<",
+  "<=",
+  ">",
+  ">=",
+  "==",
+  "!=",
+  "&",
+  "^",
+  "|",
+  "&&",
+  "||",
+  "?:",
+  "=",
+  "+=",
+  "-=",
+  "*=",
+  "/=",
+  "&=",
+  "|=",
+  "<<=",
+  ">>=",
+  "ABSOLUTE",
+  "ADDR",
+  "ALIGN",
+  "ALIGNOF",
+  "BLOCK",
+  "DATA_SEGMENT_ALIGN",
+  "DATA_SEGMENT_END",
+  "DATA_SEGMENT_RELRO_END",
+  "DEFINED",
+  "LENGTH",
+  "LOADADDR",
+  "MAX",
+  "MIN",
+  "NEXT",
+  "ORIGIN",
+  "SEGMENT_START",
+  "SIZEOF",
+  "SIZEOF_HEADERS",
+  "MAXPAGESIZE",
+  "COMMONPAGESIZE"
+};
+
+Operator::Operator(Arity pArity,
+                   Type pType)
+  : ExprToken(ExprToken::OPERATOR),
+    m_Arity(pArity),
+    m_Type(pType)
+{
+  m_pIntOperand = IntOperand::create(0);
+}
+
+Operator::~Operator()
+{
+}
+
+void Operator::dump() const
+{
+  mcld::outs() << OpNames[type()];
+}
+
+/* Nullary operator */
+template<>
+Operator& Operator::create<Operator::SIZEOF_HEADERS>()
+{
+  static NullaryOp<Operator::SIZEOF_HEADERS> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::MAXPAGESIZE>()
+{
+  static NullaryOp<Operator::MAXPAGESIZE> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::COMMONPAGESIZE>()
+{
+  static NullaryOp<Operator::COMMONPAGESIZE> op;
+  return op;
+}
+
+/* Unary operator */
+template<>
+Operator& Operator::create<Operator::UNARY_PLUS>()
+{
+  static UnaryOp<Operator::UNARY_PLUS> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::UNARY_MINUS>()
+{
+  static UnaryOp<Operator::UNARY_MINUS> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::LOGICAL_NOT>()
+{
+  static UnaryOp<Operator::LOGICAL_NOT> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::BITWISE_NOT>()
+{
+  static UnaryOp<Operator::BITWISE_NOT> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::ABSOLUTE>()
+{
+  static UnaryOp<Operator::ABSOLUTE> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::ADDR>()
+{
+  static UnaryOp<Operator::ADDR> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::ALIGNOF>()
+{
+  static UnaryOp<Operator::ALIGNOF> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::DATA_SEGMENT_END>()
+{
+  static UnaryOp<Operator::DATA_SEGMENT_END> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::DEFINED>()
+{
+  static UnaryOp<Operator::DEFINED> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::LENGTH>()
+{
+  static UnaryOp<Operator::LENGTH> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::LOADADDR>()
+{
+  static UnaryOp<Operator::LOADADDR> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::NEXT>()
+{
+  static UnaryOp<Operator::NEXT> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::ORIGIN>()
+{
+  static UnaryOp<Operator::ORIGIN> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::SIZEOF>()
+{
+  static UnaryOp<Operator::SIZEOF> op;
+  return op;
+}
+
+/* Binary operator */
+template<>
+Operator& Operator::create<Operator::MUL>()
+{
+  static BinaryOp<Operator::MUL> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::DIV>()
+{
+  static BinaryOp<Operator::DIV> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::MOD>()
+{
+  static BinaryOp<Operator::MOD> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::ADD>()
+{
+  static BinaryOp<Operator::ADD> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::SUB>()
+{
+  static BinaryOp<Operator::SUB> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::LSHIFT>()
+{
+  static BinaryOp<Operator::LSHIFT> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::RSHIFT>()
+{
+  static BinaryOp<Operator::RSHIFT> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::LT>()
+{
+  static BinaryOp<Operator::LT> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::LE>()
+{
+  static BinaryOp<Operator::LE> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::GT>()
+{
+  static BinaryOp<Operator::GT> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::GE>()
+{
+  static BinaryOp<Operator::GE> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::EQ>()
+{
+  static BinaryOp<Operator::EQ> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::NE>()
+{
+  static BinaryOp<Operator::NE> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::BITWISE_AND>()
+{
+  static BinaryOp<Operator::BITWISE_AND> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::BITWISE_XOR>()
+{
+  static BinaryOp<Operator::BITWISE_XOR> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::BITWISE_OR>()
+{
+  static BinaryOp<Operator::BITWISE_OR> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::LOGICAL_AND>()
+{
+  static BinaryOp<Operator::LOGICAL_AND> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::LOGICAL_OR>()
+{
+  static BinaryOp<Operator::LOGICAL_OR> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::ALIGN>()
+{
+  static BinaryOp<Operator::ALIGN> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::DATA_SEGMENT_RELRO_END>()
+{
+  static BinaryOp<Operator::DATA_SEGMENT_RELRO_END> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::MAX>()
+{
+  static BinaryOp<Operator::MAX> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::MIN>()
+{
+  static BinaryOp<Operator::MIN> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::SEGMENT_START>()
+{
+  static BinaryOp<Operator::SEGMENT_START> op;
+  return op;
+}
+
+/* Ternary operator */
+template<>
+Operator& Operator::create<Operator::TERNARY_IF>()
+{
+  static TernaryOp<Operator::TERNARY_IF> op;
+  return op;
+}
+
+template<>
+Operator& Operator::create<Operator::DATA_SEGMENT_ALIGN>()
+{
+  static TernaryOp<Operator::DATA_SEGMENT_ALIGN> op;
+  return op;
+}
diff --git a/lib/Script/OutputArchCmd.cpp b/lib/Script/OutputArchCmd.cpp
new file mode 100644
index 0000000..4393b84
--- /dev/null
+++ b/lib/Script/OutputArchCmd.cpp
@@ -0,0 +1,36 @@
+//===- OutputArchCmd.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/OutputArchCmd.h>
+#include <mcld/Support/raw_ostream.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// OutputArchCmd
+//===----------------------------------------------------------------------===//
+OutputArchCmd::OutputArchCmd(const std::string& pArch)
+  : ScriptCommand(ScriptCommand::OUTPUT_ARCH),
+    m_Arch(pArch)
+{
+}
+
+OutputArchCmd::~OutputArchCmd()
+{
+}
+
+void OutputArchCmd::dump() const
+{
+  mcld::outs() << "OUTPUT_ARCH ( " << m_Arch << " )\n";
+}
+
+void OutputArchCmd::activate(Module& pModule)
+{
+  // TODO
+}
+
diff --git a/lib/Script/OutputCmd.cpp b/lib/Script/OutputCmd.cpp
new file mode 100644
index 0000000..c37adcc
--- /dev/null
+++ b/lib/Script/OutputCmd.cpp
@@ -0,0 +1,41 @@
+//===- OutputCmd.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/OutputCmd.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/Module.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// OutputCmd
+//===----------------------------------------------------------------------===//
+OutputCmd::OutputCmd(const std::string& pOutputFile)
+  : ScriptCommand(ScriptCommand::OUTPUT),
+    m_OutputFile(pOutputFile)
+{
+}
+
+OutputCmd::~OutputCmd()
+{
+}
+
+void OutputCmd::dump() const
+{
+  mcld::outs() << "OUTPUT ( " << m_OutputFile << " )\n";
+}
+
+void OutputCmd::activate(Module& pModule)
+{
+  pModule.getScript().setOutputFile(m_OutputFile);
+  // TODO: set the output name if there is no `-o filename' on the cmdline.
+  // This option is to define a default name for the output file other than the
+  // usual default of a.out.
+}
+
diff --git a/lib/Script/OutputFormatCmd.cpp b/lib/Script/OutputFormatCmd.cpp
new file mode 100644
index 0000000..eca9df5
--- /dev/null
+++ b/lib/Script/OutputFormatCmd.cpp
@@ -0,0 +1,53 @@
+//===- OutputFormatCmd.cpp ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/OutputFormatCmd.h>
+#include <mcld/Support/raw_ostream.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// OutputFormatCmd
+//===----------------------------------------------------------------------===//
+OutputFormatCmd::OutputFormatCmd(const std::string& pFormat)
+  : ScriptCommand(ScriptCommand::OUTPUT_FORMAT)
+{
+  m_FormatList.push_back(pFormat);
+}
+
+OutputFormatCmd::OutputFormatCmd(const std::string& pDefault,
+                                 const std::string& pBig,
+                                 const std::string& pLittle)
+  : ScriptCommand(ScriptCommand::OUTPUT_FORMAT)
+{
+  m_FormatList.push_back(pDefault);
+  m_FormatList.push_back(pBig);
+  m_FormatList.push_back(pLittle);
+}
+
+OutputFormatCmd::~OutputFormatCmd()
+{
+}
+
+void OutputFormatCmd::dump() const
+{
+  mcld::outs() << "OUTPUT_FORMAT ( ";
+  assert(m_FormatList.size() == 1 || m_FormatList.size() == 3);
+  for (size_t i = 0; i < m_FormatList.size(); ++i) {
+    if (i != 0)
+      mcld::outs() << " , ";
+    mcld::outs() << m_FormatList[i];
+  }
+  mcld::outs() << " )\n";
+}
+
+void OutputFormatCmd::activate(Module& pModule)
+{
+  // TODO
+}
+
diff --git a/lib/Script/OutputSectDesc.cpp b/lib/Script/OutputSectDesc.cpp
new file mode 100644
index 0000000..3442c4e
--- /dev/null
+++ b/lib/Script/OutputSectDesc.cpp
@@ -0,0 +1,196 @@
+//===- OutputSectDesc.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/OutputSectDesc.h>
+#include <mcld/Script/RpnExpr.h>
+#include <mcld/Script/StringList.h>
+#include <mcld/Script/StrToken.h>
+#include <mcld/Script/InputSectDesc.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/Module.h>
+#include <llvm/Support/Casting.h>
+#include <cassert>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// OutputSectDesc
+//===----------------------------------------------------------------------===//
+OutputSectDesc::OutputSectDesc(const std::string& pName,
+                               const Prolog& pProlog)
+  : ScriptCommand(ScriptCommand::OUTPUT_SECT_DESC),
+    m_Name(pName),
+    m_Prolog(pProlog)
+{
+}
+
+OutputSectDesc::~OutputSectDesc()
+{
+  for (iterator it = begin(), ie = end(); it != ie; ++it) {
+    if (*it != NULL)
+      delete *it;
+  }
+}
+
+void OutputSectDesc::dump() const
+{
+  mcld::outs() << m_Name << "\t";
+
+  if (m_Prolog.hasVMA()) {
+    m_Prolog.vma().dump();
+    mcld::outs() << "\t";
+  }
+
+  switch (m_Prolog.type()) {
+  case NOLOAD:
+    mcld::outs() << "(NOLOAD)";
+    break;
+  case DSECT:
+    mcld::outs() << "(DSECT)";
+    break;
+  case COPY:
+    mcld::outs() << "(COPY)";
+    break;
+  case INFO:
+    mcld::outs() << "(INFO)";
+    break;
+  case OVERLAY:
+    mcld::outs() << "(OVERLAY)";
+    break;
+  default:
+    break;
+  }
+  mcld::outs() << ":\n";
+
+  if (m_Prolog.hasLMA()) {
+    mcld::outs() << "\tAT ( ";
+    m_Prolog.lma().dump();
+    mcld::outs() << " )\n";
+  }
+
+  if (m_Prolog.hasAlign()) {
+    mcld::outs() << "\tALIGN ( ";
+    m_Prolog.align().dump();
+    mcld::outs() << " )\n";
+  }
+
+  if (m_Prolog.hasSubAlign()) {
+    mcld::outs() << "\tSUBALIGN ( ";
+    m_Prolog.subAlign().dump();
+    mcld::outs() << " )\n";
+  }
+
+  switch (m_Prolog.constraint()) {
+  case ONLY_IF_RO:
+    mcld::outs() << "\tONLY_IF_RO\n";
+    break;
+  case ONLY_IF_RW:
+    mcld::outs() << "\tONLY_IF_RW\n";
+    break;
+  default:
+    break;
+  }
+
+  mcld::outs() << "\t{\n";
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+    switch ((*it)->getKind()) {
+    case ScriptCommand::ASSIGNMENT:
+    case ScriptCommand::INPUT_SECT_DESC:
+      mcld::outs() << "\t\t";
+      (*it)->dump();
+      break;
+    default:
+      assert(0);
+      break;
+    }
+  }
+  mcld::outs() << "\t}";
+
+  if (m_Epilog.hasRegion())
+    mcld::outs() << "\t>" << m_Epilog.region();
+  if (m_Epilog.hasLMARegion())
+    mcld::outs() << "\tAT>" << m_Epilog.lmaRegion();
+
+  if (m_Epilog.hasPhdrs()) {
+    for (StringList::const_iterator it = m_Epilog.phdrs().begin(),
+      ie = m_Epilog.phdrs().end(); it != ie; ++it) {
+      assert((*it)->kind() == StrToken::String);
+      mcld::outs() << ":" << (*it)->name() << " ";
+    }
+  }
+
+  if (m_Epilog.hasFillExp()) {
+    mcld::outs() << "= ";
+    m_Epilog.fillExp().dump();
+  }
+  mcld::outs() << "\n";
+}
+
+void OutputSectDesc::push_back(ScriptCommand* pCommand)
+{
+  switch (pCommand->getKind()) {
+  case ScriptCommand::ASSIGNMENT:
+  case ScriptCommand::INPUT_SECT_DESC:
+    m_OutputSectCmds.push_back(pCommand);
+    break;
+  default:
+    assert(0);
+    break;
+  }
+}
+
+void OutputSectDesc::setEpilog(const Epilog& pEpilog)
+{
+  m_Epilog.m_pRegion    = pEpilog.m_pRegion;
+  m_Epilog.m_pLMARegion = pEpilog.m_pLMARegion;
+  m_Epilog.m_pPhdrs     = pEpilog.m_pPhdrs;
+  m_Epilog.m_pFillExp   = pEpilog.m_pFillExp;
+}
+
+void OutputSectDesc::activate(Module& pModule)
+{
+  // Assignment in an output section
+  OutputSectCmds assignments;
+
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+    switch ((*it)->getKind()) {
+    case ScriptCommand::ASSIGNMENT:
+      assignments.push_back(*it);
+      break;
+    case ScriptCommand::INPUT_SECT_DESC: {
+      (*it)->activate(pModule);
+
+      for (iterator assign = assignments.begin(), assignEnd = assignments.end();
+        assign != assignEnd; ++assign) {
+        (*assign)->activate(pModule);
+      }
+      assignments.clear();
+      break;
+    }
+    default:
+      assert(0);
+      break;
+    }
+  }
+
+  if (!assignments.empty()) {
+    InputSectDesc::Spec spec;;
+    spec.m_pWildcardFile = NULL;
+    spec.m_pExcludeFiles = NULL;
+    spec.m_pWildcardSections = NULL;
+    InputSectDesc inputDesc(InputSectDesc::Keep, spec, *this);
+    pModule.getScript().sectionMap().insert(inputDesc, *this);
+
+    for (iterator assign = assignments.begin(), assignEnd = assignments.end();
+      assign != assignEnd; ++assign) {
+      (*assign)->activate(pModule);
+    }
+    assignments.clear();
+  }
+}
diff --git a/lib/Script/RpnEvaluator.cpp b/lib/Script/RpnEvaluator.cpp
new file mode 100644
index 0000000..52cb79f
--- /dev/null
+++ b/lib/Script/RpnEvaluator.cpp
@@ -0,0 +1,114 @@
+//===- RpnEvaluator.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Script/RpnExpr.h>
+#include <mcld/Script/RpnEvaluator.h>
+#include <mcld/Script/ExprToken.h>
+#include <mcld/Script/Operator.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Module.h>
+#include <llvm/Support/Casting.h>
+#include <llvm/Support/DataTypes.h>
+#include <stack>
+#include <cassert>
+
+using namespace mcld;
+
+RpnEvaluator::RpnEvaluator(const Module& pModule,
+                           const TargetLDBackend& pBackend)
+  : m_Module(pModule),
+    m_Backend(pBackend)
+{
+}
+
+bool RpnEvaluator::eval(const RpnExpr& pExpr, uint64_t& pResult)
+{
+  std::stack<Operand*> operandStack;
+  for (RpnExpr::const_iterator it = pExpr.begin(), ie = pExpr.end(); it != ie;
+    ++it) {
+    switch((*it)->kind()) {
+    case ExprToken::OPERATOR: {
+      Operator* op = llvm::cast<Operator>(*it);
+      switch (op->arity()) {
+      case Operator::NULLARY: {
+        operandStack.push(op->eval(m_Module, m_Backend));
+        break;
+      }
+      case Operator::UNARY: {
+        Operand* opd = operandStack.top();
+        operandStack.pop();
+        op->appendOperand(opd);
+        operandStack.push(op->eval(m_Module, m_Backend));
+        break;
+      }
+      case Operator::BINARY: {
+        Operand* opd2 = operandStack.top();
+        operandStack.pop();
+        Operand* opd1 = operandStack.top();
+        operandStack.pop();
+        op->appendOperand(opd1);
+        op->appendOperand(opd2);
+        operandStack.push(op->eval(m_Module, m_Backend));
+        break;
+      }
+      case Operator::TERNARY: {
+        Operand* opd3 = operandStack.top();
+        operandStack.pop();
+        Operand* opd2 = operandStack.top();
+        operandStack.pop();
+        Operand* opd1 = operandStack.top();
+        operandStack.pop();
+        op->appendOperand(opd1);
+        op->appendOperand(opd2);
+        op->appendOperand(opd3);
+        operandStack.push(op->eval(m_Module, m_Backend));
+        break;
+      }
+      } // end of switch operator arity
+      break;
+    }
+
+    case ExprToken::OPERAND: {
+      Operand* opd = llvm::cast<Operand>(*it);
+      switch (opd->type()) {
+      case Operand::SYMBOL: {
+        // It's possible that there are no operators in an expression, so
+        // we set up symbol operand here.
+        if (!opd->isDot()) {
+          SymOperand* sym_opd = llvm::cast<SymOperand>(opd);
+          const LDSymbol* symbol =
+            m_Module.getNamePool().findSymbol(sym_opd->name());
+          if (symbol == NULL) {
+            fatal(diag::fail_sym_resolution) << __FILE__ << __LINE__
+                                             << "mclinker@googlegroups.com";
+          }
+          sym_opd->setValue(symbol->value());
+        }
+        operandStack.push(opd);
+        break;
+      }
+      default:
+        operandStack.push(opd);
+        break;
+      } // end of switch operand type
+      break;
+    }
+
+    } // end of switch
+  } // end of for
+
+  // stack top is result
+  assert(operandStack.top()->type() == Operand::SYMBOL ||
+         operandStack.top()->type() == Operand::INTEGER ||
+         operandStack.top()->type() == Operand::FRAGMENT);
+  pResult = operandStack.top()->value();
+  return true;
+}
+
diff --git a/lib/Script/RpnExpr.cpp b/lib/Script/RpnExpr.cpp
new file mode 100644
index 0000000..a9a4cae
--- /dev/null
+++ b/lib/Script/RpnExpr.cpp
@@ -0,0 +1,105 @@
+//===- RPNExpr.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/RpnExpr.h>
+#include <mcld/Script/ExprToken.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Script/Operator.h>
+#include <mcld/Support/GCFactory.h>
+#include <mcld/Support/raw_ostream.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/Casting.h>
+
+using namespace mcld;
+
+typedef GCFactory<RpnExpr, MCLD_SYMBOLS_PER_INPUT> ExprFactory;
+static llvm::ManagedStatic<ExprFactory> g_ExprFactory;
+
+//===----------------------------------------------------------------------===//
+// RpnExpr
+//===----------------------------------------------------------------------===//
+RpnExpr::RpnExpr()
+{
+}
+
+RpnExpr::~RpnExpr()
+{
+}
+
+bool RpnExpr::hasDot() const
+{
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+    if ((*it)->kind() == ExprToken::OPERAND &&
+        llvm::cast<Operand>(*it)->isDot())
+      return true;
+  }
+  return false;
+}
+
+void RpnExpr::dump() const
+{
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+    (*it)->dump();
+    mcld::outs() << " ";
+  }
+}
+
+void RpnExpr::push_back(ExprToken* pToken)
+{
+  m_TokenQueue.push_back(pToken);
+}
+
+RpnExpr* RpnExpr::create()
+{
+  RpnExpr* result = g_ExprFactory->allocate();
+  new (result) RpnExpr();
+  return result;
+}
+
+void RpnExpr::destroy(RpnExpr*& pRpnExpr)
+{
+  g_ExprFactory->destroy(pRpnExpr);
+  g_ExprFactory->deallocate(pRpnExpr);
+  pRpnExpr = NULL;
+}
+
+void RpnExpr::clear()
+{
+  g_ExprFactory->clear();
+}
+
+RpnExpr::iterator RpnExpr::insert(iterator pPosition, ExprToken* pToken)
+{
+  return m_TokenQueue.insert(pPosition, pToken);
+}
+
+void RpnExpr::erase(iterator pPosition)
+{
+  m_TokenQueue.erase(pPosition);
+}
+
+// buildHelperExpr - build the helper expr:
+//                   ADDR ( `output_sect' ) + SIZEOF ( `output_sect' )
+RpnExpr* RpnExpr::buildHelperExpr(SectionMap::iterator pIter)
+{
+  RpnExpr* expr = RpnExpr::create();
+  expr->push_back(SectDescOperand::create(*pIter));
+  expr->push_back(&Operator::create<Operator::ADDR>());
+  expr->push_back(SectDescOperand::create(*pIter));
+  expr->push_back(&Operator::create<Operator::SIZEOF>());
+  expr->push_back(&Operator::create<Operator::ADD>());
+  return expr;
+}
+
+// buildHelperExpr - build the helper expr: `fragment'
+RpnExpr* RpnExpr::buildHelperExpr(Fragment& pFrag)
+{
+  RpnExpr* expr = RpnExpr::create();
+  expr->push_back(FragOperand::create(pFrag));
+  return expr;
+}
diff --git a/lib/Script/ScriptCommand.cpp b/lib/Script/ScriptCommand.cpp
new file mode 100644
index 0000000..e360645
--- /dev/null
+++ b/lib/Script/ScriptCommand.cpp
@@ -0,0 +1,19 @@
+//===- ScriptCommand.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/ScriptCommand.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ScriptCommand
+//===----------------------------------------------------------------------===//
+ScriptCommand::~ScriptCommand()
+{
+}
+
diff --git a/lib/Script/ScriptFile.cpp b/lib/Script/ScriptFile.cpp
new file mode 100644
index 0000000..00a8056
--- /dev/null
+++ b/lib/Script/ScriptFile.cpp
@@ -0,0 +1,252 @@
+//===- ScriptFile.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/ScriptFile.h>
+#include <mcld/Script/StringList.h>
+#include <mcld/Script/ScriptCommand.h>
+#include <mcld/Script/EntryCmd.h>
+#include <mcld/Script/OutputFormatCmd.h>
+#include <mcld/Script/GroupCmd.h>
+#include <mcld/Script/OutputCmd.h>
+#include <mcld/Script/SearchDirCmd.h>
+#include <mcld/Script/OutputArchCmd.h>
+#include <mcld/Script/AssertCmd.h>
+#include <mcld/Script/SectionsCmd.h>
+#include <mcld/Script/RpnExpr.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Script/StrToken.h>
+#include <mcld/MC/Input.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/InputTree.h>
+#include <mcld/ADT/HashEntry.h>
+#include <mcld/ADT/HashTable.h>
+#include <mcld/ADT/StringHash.h>
+#include <llvm/Support/Casting.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <cassert>
+
+using namespace mcld;
+
+typedef HashEntry<std::string,
+                  void*,
+                  hash::StringCompare<std::string> > ParserStrEntry;
+typedef HashTable<ParserStrEntry,
+                  hash::StringHash<hash::DJB>,
+                  EntryFactory<ParserStrEntry> > ParserStrPool;
+static llvm::ManagedStatic<ParserStrPool> g_ParserStrPool;
+
+//===----------------------------------------------------------------------===//
+// ScriptFile
+//===----------------------------------------------------------------------===//
+ScriptFile::ScriptFile(Kind pKind, Input& pInput, InputBuilder& pBuilder)
+  : m_Kind(pKind),
+    m_Input(pInput),
+    m_Name(pInput.path().native()),
+    m_pInputTree(NULL),
+    m_Builder(pBuilder),
+    m_bHasSectionsCmd(false),
+    m_bInSectionsCmd(false),
+    m_bInOutputSectDesc(false),
+    m_pRpnExpr(NULL),
+    m_pStringList(NULL),
+    m_bAsNeeded(false)
+{
+  // FIXME: move creation of input tree out of ScriptFile.
+  m_pInputTree = new InputTree();
+}
+
+ScriptFile::~ScriptFile()
+{
+  for (iterator it = begin(), ie = end(); it != ie; ++it) {
+    if (*it != NULL)
+      delete *it;
+  }
+  if (NULL != m_pInputTree)
+    delete m_pInputTree;
+}
+
+void ScriptFile::dump() const
+{
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
+    (*it)->dump();
+}
+
+void ScriptFile::activate(Module& pModule)
+{
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
+    (*it)->activate(pModule);
+}
+
+void ScriptFile::addEntryPoint(const std::string& pSymbol)
+{
+  EntryCmd* entry = new EntryCmd(pSymbol);
+
+  if (m_bInSectionsCmd) {
+    assert(!m_CommandQueue.empty());
+    SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
+    sections->push_back(entry);
+  } else {
+    m_CommandQueue.push_back(entry);
+  }
+}
+
+void ScriptFile::addOutputFormatCmd(const std::string& pName)
+{
+  m_CommandQueue.push_back(new OutputFormatCmd(pName));
+}
+
+void ScriptFile::addOutputFormatCmd(const std::string& pDefault,
+                                    const std::string& pBig,
+                                    const std::string& pLittle)
+{
+  m_CommandQueue.push_back(new OutputFormatCmd(pDefault, pBig, pLittle));
+}
+
+void ScriptFile::addGroupCmd(StringList& pStringList,
+                             GroupReader& pGroupReader,
+                             const LinkerConfig& pConfig)
+{
+  m_CommandQueue.push_back(
+    new GroupCmd(pStringList, *m_pInputTree, m_Builder, pGroupReader, pConfig));
+}
+
+void ScriptFile::addOutputCmd(const std::string& pFileName)
+{
+  m_CommandQueue.push_back(new OutputCmd(pFileName));
+}
+
+void ScriptFile::addSearchDirCmd(const std::string& pPath)
+{
+  m_CommandQueue.push_back(new SearchDirCmd(pPath));
+}
+
+void ScriptFile::addOutputArchCmd(const std::string& pArch)
+{
+  m_CommandQueue.push_back(new OutputArchCmd(pArch));
+}
+
+void ScriptFile::addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage)
+{
+  m_CommandQueue.push_back(new AssertCmd(pRpnExpr, pMessage));
+}
+
+void ScriptFile::addAssignment(const std::string& pSymbolName,
+                               RpnExpr& pRpnExpr,
+                               Assignment::Type pType)
+{
+  if (m_bInSectionsCmd) {
+    assert(!m_CommandQueue.empty());
+    SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
+    if (m_bInOutputSectDesc) {
+      assert(!sections->empty());
+      OutputSectDesc* output_desc =
+        llvm::cast<OutputSectDesc>(sections->back());
+      output_desc->push_back(new Assignment(Assignment::INPUT_SECTION,
+                                            pType,
+                                            *(SymOperand::create(pSymbolName)),
+                                            pRpnExpr));
+    } else {
+      sections->push_back(new Assignment(Assignment::OUTPUT_SECTION,
+                                         pType,
+                                         *(SymOperand::create(pSymbolName)),
+                                         pRpnExpr));
+    }
+  } else {
+    m_CommandQueue.push_back(new Assignment(Assignment::OUTSIDE_SECTIONS,
+                                            pType,
+                                            *(SymOperand::create(pSymbolName)),
+                                            pRpnExpr));
+  }
+}
+
+bool ScriptFile::hasSectionsCmd() const
+{
+  return m_bHasSectionsCmd;
+}
+
+void ScriptFile::enterSectionsCmd()
+{
+  m_bHasSectionsCmd = true;
+  m_bInSectionsCmd = true;
+  m_CommandQueue.push_back(new SectionsCmd());
+}
+
+void ScriptFile::leaveSectionsCmd()
+{
+  m_bInSectionsCmd = false;
+}
+
+void ScriptFile::enterOutputSectDesc(const std::string& pName,
+                                     const OutputSectDesc::Prolog& pProlog)
+{
+  assert(!m_CommandQueue.empty());
+  assert(m_bInSectionsCmd);
+  SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
+  sections->push_back(new OutputSectDesc(pName, pProlog));
+
+  m_bInOutputSectDesc = true;
+}
+
+void ScriptFile::leaveOutputSectDesc(const OutputSectDesc::Epilog& pEpilog)
+{
+  assert(!m_CommandQueue.empty());
+  assert(m_bInSectionsCmd);
+  SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
+
+  assert(!sections->empty() && m_bInOutputSectDesc);
+  OutputSectDesc* output_desc = llvm::cast<OutputSectDesc>(sections->back());
+  output_desc->setEpilog(pEpilog);
+
+  m_bInOutputSectDesc = false;
+}
+
+void ScriptFile::addInputSectDesc(InputSectDesc::KeepPolicy pPolicy,
+                                  const InputSectDesc::Spec& pSpec)
+{
+  assert(!m_CommandQueue.empty());
+  assert(m_bInSectionsCmd);
+  SectionsCmd* sections = llvm::cast<SectionsCmd>(back());
+
+  assert(!sections->empty() && m_bInOutputSectDesc);
+  OutputSectDesc* output_sect = llvm::cast<OutputSectDesc>(sections->back());
+
+  output_sect->push_back(new InputSectDesc(pPolicy, pSpec, *output_sect));
+}
+
+RpnExpr* ScriptFile::createRpnExpr()
+{
+  m_pRpnExpr = RpnExpr::create();
+  return m_pRpnExpr;
+}
+
+StringList* ScriptFile::createStringList()
+{
+  m_pStringList = StringList::create();
+  return m_pStringList;
+}
+
+void ScriptFile::setAsNeeded(bool pEnable)
+{
+  m_bAsNeeded = pEnable;
+}
+
+const std::string& ScriptFile::createParserStr(const char* pText,
+                                               size_t pLength)
+{
+  bool exist = false;
+  ParserStrEntry* entry =
+    g_ParserStrPool->insert(std::string(pText, pLength), exist);
+  return entry->key();
+}
+
+void ScriptFile::clearParserStrPool()
+{
+  g_ParserStrPool->clear();
+}
+
diff --git a/lib/Script/ScriptParser.yy b/lib/Script/ScriptParser.yy
new file mode 100644
index 0000000..7b35e0e
--- /dev/null
+++ b/lib/Script/ScriptParser.yy
@@ -0,0 +1,936 @@
+/*===- ScriptParser.yy ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===*/
+
+%{
+/* C/C++ Declarations */
+#include <mcld/Script/ScriptReader.h>
+#include <mcld/Script/ScriptScanner.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Script/Operator.h>
+#include <mcld/Script/Assignment.h>
+#include <mcld/Script/RpnExpr.h>
+#include <mcld/Script/FileToken.h>
+#include <mcld/Script/NameSpec.h>
+#include <mcld/Script/WildcardPattern.h>
+#include <mcld/Support/MsgHandling.h>
+using namespace mcld;
+
+#undef yylex
+#define yylex m_ScriptScanner.lex
+%}
+
+%code requires {
+#include <mcld/Script/StrToken.h>
+#include <mcld/Script/StringList.h>
+#include <mcld/Script/OutputSectDesc.h>
+#include <mcld/Script/InputSectDesc.h>
+#include <llvm/Support/DataTypes.h>
+
+using namespace mcld;
+
+}
+
+%pure-parser
+%require "2.4"
+%skeleton "glr.cc"
+%defines "ScriptParser.h"
+%debug
+%error-verbose
+%define namespace "mcld"
+%define "parser_class_name" "ScriptParser"
+%parse-param { const class LinkerConfig& m_LDConfig }
+%parse-param { class ScriptFile& m_ScriptFile }
+%parse-param { class ScriptScanner& m_ScriptScanner }
+%parse-param { class GroupReader& m_GroupReader}
+%lex-param { const class ScriptFile& m_ScriptFile }
+
+%locations
+%initial-action
+{
+  /* Initialize the initial location. */
+  @$.begin.filename = @$.end.filename = &(m_ScriptFile.name());
+}
+
+%start script_file
+
+%union {
+  const std::string* string;
+  uint64_t integer;
+  RpnExpr* rpn_expr;
+  StrToken* str_token;
+  StringList* str_tokens;
+  OutputSectDesc::Prolog output_prolog;
+  OutputSectDesc::Type output_type;
+  OutputSectDesc::Constraint output_constraint;
+  OutputSectDesc::Epilog output_epilog;
+  WildcardPattern* wildcard;
+  InputSectDesc::Spec input_spec;
+}
+
+%token END 0 /* EOF */
+%token <string> STRING LNAMESPEC
+%token <integer> INTEGER
+
+/* Initial states */
+%token LINKER_SCRIPT DEFSYM VERSION_SCRIPT DYNAMIC_LIST
+
+/* Entry point */
+%token ENTRY
+/* File Commands */
+%token INCLUDE
+%token INPUT
+%token GROUP
+%token AS_NEEDED
+%token OUTPUT
+%token SEARCH_DIR
+%token STARTUP
+/* Format Commands */
+%token OUTPUT_FORMAT
+%token TARGET
+/* Misc Commands */
+%token ASSERT
+%token EXTERN
+%token FORCE_COMMON_ALLOCATION
+%token INHIBIT_COMMON_ALLOCATION
+%token INSERT
+%token NOCROSSREFS
+%token OUTPUT_ARCH
+%token LD_FEATURE
+/* Assignments */
+%token HIDDEN
+%token PROVIDE
+%token PROVIDE_HIDDEN
+/* SECTIONS Command */
+%token SECTIONS
+/* MEMORY Command */
+%token MEMORY
+/* PHDRS Command */
+%token PHDRS
+/* Builtin Functions */
+%token ABSOLUTE
+%token ADDR
+%token ALIGN
+%token ALIGNOF
+%token BLOCK
+%token DATA_SEGMENT_ALIGN
+%token DATA_SEGMENT_END
+%token DATA_SEGMENT_RELRO_END
+%token DEFINED
+%token LENGTH
+%token LOADADDR
+%token MAX
+%token MIN
+%token NEXT
+%token ORIGIN
+%token SEGMENT_START
+%token SIZEOF
+%token SIZEOF_HEADERS
+%token CONSTANT
+/* Symbolic Constants */
+%token MAXPAGESIZE
+%token COMMONPAGESIZE
+/* Input Section Description */
+%token EXCLUDE_FILE
+%token COMMON
+%token KEEP
+%token SORT_BY_NAME
+%token SORT_BY_ALIGNMENT
+%token SORT_NONE
+%token SORT_BY_INIT_PRIORITY
+/* Output Section Data */
+%token BYTE
+%token SHORT
+%token LONG
+%token QUAD
+%token SQUAD
+%token FILL
+/* Output Section Discarding */
+%token DISCARD
+/* Output Section Keywords */
+%token CREATE_OBJECT_SYMBOLS
+%token CONSTRUCTORS
+/* Output Section Attributes */
+/* Output Section Type */
+%token NOLOAD
+%token DSECT
+%token COPY
+%token INFO
+%token OVERLAY
+/* Output Section LMA */
+%token AT
+/* Forced Input Alignment */
+%token SUBALIGN
+/* Output Section Constraint */
+%token ONLY_IF_RO
+%token ONLY_IF_RW
+/* Operators are listed top to bottem, in ascending order */
+%left ','
+%right '=' ADD_ASSIGN SUB_ASSIGN MUL_ASSIGN DIV_ASSIGN AND_ASSIGN OR_ASSIGN LS_ASSIGN RS_ASSIGN
+%right '?' ':'
+%left LOGICAL_OR
+%left LOGICAL_AND
+%left '|'
+%left '^'
+%left '&'
+%left EQ NE
+%left '<' LE '>' GE
+%left LSHIFT RSHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY_PLUS UNARY_MINUS '!' '~'
+
+%type <integer> exp
+%type <string> string symbol opt_region opt_lma_region wildcard_pattern
+%type <rpn_expr> script_exp opt_lma opt_align opt_subalign opt_fill
+%type <str_token> input phdr
+%type <str_tokens> input_list opt_phdr opt_exclude_files input_sect_wildcard_patterns
+%type <output_prolog> output_desc_prolog opt_vma_and_type
+%type <output_type> opt_type type
+%type <output_constraint> opt_constraint
+%type <output_epilog> output_desc_epilog
+%type <wildcard> wildcard_file wildcard_section
+%type <input_spec> input_sect_spec
+
+%%
+
+script_file : LINKER_SCRIPT
+              { m_ScriptScanner.setLexState(ScriptFile::LDScript); }
+              linker_script
+              { m_ScriptScanner.popLexState(); }
+            ;
+
+linker_script : linker_script script_command
+              | /* Empty */
+              ;
+
+script_command : entry_command
+               | output_format_command
+               | group_command
+               | output_command
+               | search_dir_command
+               | output_arch_command
+               | assert_command
+               | symbol_assignment
+               | sections_command
+               | ';'
+               ;
+
+entry_command : ENTRY '(' STRING ')'
+                { m_ScriptFile.addEntryPoint(*$3); }
+              ;
+
+output_format_command : OUTPUT_FORMAT '(' STRING ')'
+                        { m_ScriptFile.addOutputFormatCmd(*$3); }
+                      | OUTPUT_FORMAT '(' STRING ',' STRING ',' STRING ')'
+                        { m_ScriptFile.addOutputFormatCmd(*$3, *$5, *$7); }
+                      ;
+
+group_command : GROUP '(' input_list ')'
+                { m_ScriptFile.addGroupCmd(*$3, m_GroupReader, m_LDConfig); }
+              ;
+
+search_dir_command : SEARCH_DIR '(' STRING ')'
+                     { m_ScriptFile.addSearchDirCmd(*$3); }
+                   ;
+
+output_command : OUTPUT '(' STRING ')'
+                 { m_ScriptFile.addOutputCmd(*$3); }
+               ;
+
+output_arch_command : OUTPUT_ARCH '(' STRING ')'
+                      { m_ScriptFile.addOutputArchCmd(*$3); }
+                    ;
+
+assert_command : ASSERT '(' script_exp ',' string ')'
+                 { m_ScriptFile.addAssertCmd(*$3, *$5); }
+               ;
+
+input_list : { m_ScriptFile.createStringList(); }
+             inputs
+             { $$ = m_ScriptFile.getCurrentStringList(); }
+           ;
+
+inputs : input
+         { m_ScriptFile.getCurrentStringList()->push_back($1); }
+       | inputs input
+         { m_ScriptFile.getCurrentStringList()->push_back($2); }
+       | inputs ',' input
+         { m_ScriptFile.getCurrentStringList()->push_back($3); }
+       | AS_NEEDED '('
+         { m_ScriptFile.setAsNeeded(true); }
+         inputs ')'
+         { m_ScriptFile.setAsNeeded(false); }
+       | inputs AS_NEEDED '('
+         { m_ScriptFile.setAsNeeded(true); }
+         inputs ')'
+         { m_ScriptFile.setAsNeeded(false); }
+       | inputs ',' AS_NEEDED '('
+         { m_ScriptFile.setAsNeeded(true); }
+         inputs ')'
+         { m_ScriptFile.setAsNeeded(false); }
+       ;
+
+input : string
+        { $$ = FileToken::create(*$1, m_ScriptFile.asNeeded()); }
+      | LNAMESPEC
+        { $$ = NameSpec::create(*$1, m_ScriptFile.asNeeded()); }
+      ;
+
+/*
+  SECTIONS
+  {
+    sections-command
+    sections-command
+    ...
+  }
+*/
+sections_command : SECTIONS
+                   { m_ScriptFile.enterSectionsCmd(); }
+                   '{' sect_commands '}'
+                   { m_ScriptFile.leaveSectionsCmd(); }
+                 ;
+
+sect_commands : sect_commands sect_cmd
+              | /* Empty */
+              ;
+
+/*
+Each sections-command may of be one of the following:
+
+an ENTRY command (see Entry command)
+a symbol assignment (see Assignments)
+an output section description
+an overlay description
+*/
+sect_cmd : entry_command
+         | symbol_assignment
+         | output_sect_desc
+         ;
+
+/*
+The full description of an output section looks like this:
+
+  section [address] [(type)] :
+    [AT(lma)]
+    [ALIGN(section_align)]
+    [SUBALIGN(subsection_align)]
+    [constraint]
+    {
+      output-section-command
+      output-section-command
+      ...
+    } [>region] [AT>lma_region] [:phdr :phdr ...] [=fillexp]
+*/
+output_sect_desc : string output_desc_prolog
+                   { m_ScriptFile.enterOutputSectDesc(*$1, $2); }
+                   '{'
+                       output_sect_commands
+                   '}' output_desc_epilog
+                   { m_ScriptFile.leaveOutputSectDesc($7); }
+                 ;
+
+output_desc_prolog : {
+                       m_ScriptScanner.setLexState(ScriptFile::Expression);
+                       /* create exp for vma */
+                       m_ScriptFile.createRpnExpr();
+                     }
+                     opt_vma_and_type
+                     { m_ScriptScanner.popLexState(); }
+                     ':'
+                     opt_lma opt_align opt_subalign opt_constraint
+                     {
+                       $$.m_pVMA       = $2.m_pVMA;
+                       $$.m_Type       = $2.m_Type;
+                       $$.m_pLMA       = $5;
+                       $$.m_pAlign     = $6;
+                       $$.m_pSubAlign  = $7;
+                       $$.m_Constraint = $8;
+                     }
+                   ;
+
+output_sect_commands : output_sect_commands output_sect_cmd
+                     | /* Empty */
+                     ;
+
+output_desc_epilog : opt_region opt_lma_region opt_phdr opt_fill
+                     {
+                        $$.m_pRegion    = $1;
+                        $$.m_pLMARegion = $2;
+                        $$.m_pPhdrs     = $3;
+                        $$.m_pFillExp   = $4;
+                     }
+                   ;
+
+/* Output Section Attributes */
+opt_vma_and_type : exp opt_type
+                   {
+                     $$.m_pVMA = m_ScriptFile.getCurrentRpnExpr();
+                     $$.m_Type = $2;
+                   }
+                 | opt_type
+                   {
+                     $$.m_pVMA = NULL;
+                     $$.m_Type = $1;
+                   }
+                 ;
+
+opt_type : '(' type ')'
+           { $$ = $2; }
+         | '(' ')'
+           { $$ = OutputSectDesc::LOAD; }
+         | /* Empty */
+           { $$ = OutputSectDesc::LOAD; }
+         ;
+
+type : NOLOAD
+       { $$ = OutputSectDesc::NOLOAD; }
+     | DSECT
+       { $$ = OutputSectDesc::DSECT; }
+     | COPY
+       { $$ = OutputSectDesc::COPY; }
+     | INFO
+       { $$ = OutputSectDesc::INFO; }
+     | OVERLAY
+       { $$ = OutputSectDesc::OVERLAY; }
+     ;
+
+opt_lma : AT '(' script_exp ')'
+          { $$ = $3; }
+        | /* Empty */
+          { $$ = NULL; }
+        ;
+
+/* Forced Output Alignment */
+opt_align : ALIGN '(' script_exp ')'
+            { $$ = $3; }
+          | /* Empty */
+            { $$ = NULL; }
+          ;
+
+/* Forced Input Alignment */
+opt_subalign : SUBALIGN '(' script_exp ')'
+               { $$ = $3; }
+             | /* Empty */
+               { $$ = NULL; }
+             ;
+
+opt_constraint : ONLY_IF_RO
+                 { $$ = OutputSectDesc::ONLY_IF_RO; }
+               | ONLY_IF_RW
+                 { $$ = OutputSectDesc::ONLY_IF_RW; }
+               | /* Empty */
+                 { $$ = OutputSectDesc::NO_CONSTRAINT; }
+               ;
+
+opt_region : '>' string
+             { $$ = $2; }
+           | /* Empty */
+             { $$ = NULL; }
+           ;
+
+opt_lma_region : AT '>' string
+                 { $$ = $3; }
+               | /* Empty */
+                 { $$ = NULL; }
+               ;
+
+opt_phdr : { m_ScriptFile.createStringList(); }
+           phdrs
+           { $$ = m_ScriptFile.getCurrentStringList(); }
+         ;
+
+phdrs : phdrs ':' phdr
+        { m_ScriptFile.getCurrentStringList()->push_back($3); }
+      | /* Empty */
+      ;
+
+phdr : string
+       { $$ = StrToken::create(*$1); }
+     ;
+
+opt_fill : '=' script_exp
+           { $$ = $2; }
+         | /* Empty */
+           { $$ = NULL; }
+         ;
+
+/*
+Each output-section-command may be one of the following:
+
+a symbol assignment (see Assignments)
+an input section description (see Input Section)
+data values to include directly (see Output Section Data)
+a special output section keyword (see Output Section Keywords)
+*/
+output_sect_cmd : symbol_assignment
+                | input_sect_desc
+                | output_sect_data
+                | output_sect_keyword
+                | ';'
+                ;
+
+input_sect_desc : input_sect_spec
+                  { m_ScriptFile.addInputSectDesc(InputSectDesc::NoKeep, $1); }
+                | KEEP '(' input_sect_spec ')'
+                  { m_ScriptFile.addInputSectDesc(InputSectDesc::Keep, $3); }
+                ;
+
+input_sect_spec : string
+                  {
+                    $$.m_pWildcardFile =
+                      WildcardPattern::create(*$1, WildcardPattern::SORT_NONE);
+                    $$.m_pExcludeFiles = NULL;
+                    $$.m_pWildcardSections = NULL;
+                  }
+                | wildcard_file '(' opt_exclude_files input_sect_wildcard_patterns ')'
+                  {
+                    $$.m_pWildcardFile = $1;
+                    $$.m_pExcludeFiles = $3;
+                    $$.m_pWildcardSections = $4;
+                  }
+                ;
+
+wildcard_file : wildcard_pattern
+                { $$ = WildcardPattern::create(*$1, WildcardPattern::SORT_NONE); }
+              | SORT_BY_NAME '(' wildcard_pattern ')'
+                { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_NAME); }
+              ;
+
+wildcard_pattern : string
+                   { $$ = $1; }
+                 | '*'
+                   { $$ = &m_ScriptFile.createParserStr("*", 1); }
+                 | '?'
+                   { $$ = &m_ScriptFile.createParserStr("?", 1); }
+                 ;
+
+opt_exclude_files : EXCLUDE_FILE '('
+                    { m_ScriptFile.createStringList(); }
+                    exclude_files ')'
+                    { $$ = m_ScriptFile.getCurrentStringList(); }
+                  | /* Empty */
+                    { $$ = NULL; }
+                  ;
+
+exclude_files : exclude_files wildcard_pattern
+                {
+                  m_ScriptFile.getCurrentStringList()->push_back(
+                    WildcardPattern::create(*$2, WildcardPattern::SORT_NONE));
+                }
+              | wildcard_pattern
+                {
+                  m_ScriptFile.getCurrentStringList()->push_back(
+                    WildcardPattern::create(*$1, WildcardPattern::SORT_NONE));
+                }
+              ;
+
+input_sect_wildcard_patterns : { m_ScriptFile.createStringList(); }
+                               wildcard_sections
+                               { $$ = m_ScriptFile.getCurrentStringList(); }
+                             ;
+
+wildcard_sections : wildcard_sections wildcard_section
+                    {
+                      m_ScriptFile.getCurrentStringList()->push_back($2);
+                    }
+                  | wildcard_section
+                    {
+                      m_ScriptFile.getCurrentStringList()->push_back($1);
+                    }
+                  ;
+
+wildcard_section : wildcard_pattern
+                   { $$ = WildcardPattern::create(*$1, WildcardPattern::SORT_NONE); }
+                 | SORT_NONE '(' wildcard_pattern ')'
+                   { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_NONE); }
+                 | SORT_BY_NAME '(' wildcard_pattern ')'
+                   { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_NAME); }
+                 | SORT_BY_ALIGNMENT '(' wildcard_pattern ')'
+                   { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_ALIGNMENT); }
+                 | SORT_BY_NAME '(' SORT_BY_ALIGNMENT '(' wildcard_pattern ')' ')'
+                   { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_NAME_ALIGNMENT); }
+                 | SORT_BY_ALIGNMENT '('SORT_BY_NAME '(' wildcard_pattern ')' ')'
+                   { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_ALIGNMENT_NAME); }
+                 | SORT_BY_NAME '(' SORT_BY_NAME '(' wildcard_pattern ')' ')'
+                   { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_NAME); }
+                 | SORT_BY_ALIGNMENT '(' SORT_BY_ALIGNMENT '(' wildcard_pattern ')' ')'
+                   { $$ = WildcardPattern::create(*$5, WildcardPattern::SORT_BY_ALIGNMENT); }
+                 | SORT_BY_INIT_PRIORITY '(' wildcard_pattern ')'
+                   { $$ = WildcardPattern::create(*$3, WildcardPattern::SORT_BY_INIT_PRIORITY); }
+                 ;
+
+output_sect_data : BYTE  '(' script_exp ')'
+                 | SHORT '(' script_exp ')'
+                 | LONG  '(' script_exp ')'
+                 | QUAD  '(' script_exp ')'
+                 | SQUAD '(' script_exp ')'
+                 ;
+
+output_sect_keyword : CREATE_OBJECT_SYMBOLS
+                    | CONSTRUCTORS
+                    | SORT_BY_NAME '(' CONSTRUCTORS ')'
+                    ;
+
+symbol_assignment : symbol '=' script_exp ';'
+                    { m_ScriptFile.addAssignment(*$1, *$3); }
+                  | symbol ADD_ASSIGN exp ';'
+                  | symbol SUB_ASSIGN exp ';'
+                  | symbol MUL_ASSIGN exp ';'
+                  | symbol DIV_ASSIGN exp ';'
+                  | symbol AND_ASSIGN exp ';'
+                  | symbol OR_ASSIGN exp ';'
+                  | symbol LS_ASSIGN exp ';'
+                  | symbol RS_ASSIGN exp ';'
+                  | HIDDEN '(' symbol '=' script_exp ')' ';'
+                    {
+                      m_ScriptFile.addAssignment(*$3, *$5,
+                                                 Assignment::HIDDEN);
+                    }
+                  | PROVIDE '(' symbol '=' script_exp ')' ';'
+                    {
+                      m_ScriptFile.addAssignment(*$3, *$5,
+                                                 Assignment::PROVIDE);
+                    }
+                  | PROVIDE_HIDDEN '(' symbol '=' script_exp ')' ';'
+                    {
+                      m_ScriptFile.addAssignment(*$3, *$5,
+                                                 Assignment::PROVIDE_HIDDEN);
+                    }
+                  ;
+
+script_exp : {
+               m_ScriptScanner.setLexState(ScriptFile::Expression);
+               m_ScriptFile.createRpnExpr();
+             }
+             exp
+             {
+               m_ScriptScanner.popLexState();
+               $$ = m_ScriptFile.getCurrentRpnExpr();
+             }
+           ;
+
+exp : '(' exp ')'
+      {
+        $$ = $2;
+      }
+    | '+' exp %prec UNARY_PLUS
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::UNARY_PLUS>());
+        $$ = $2 + 1;
+      }
+    | '-' exp %prec UNARY_MINUS
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::UNARY_MINUS>());
+        $$ = $2 + 1;
+      }
+    | '!' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::LOGICAL_NOT>());
+        $$ = $2 + 1;
+      }
+    | '~' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::BITWISE_NOT>());
+        $$ = $2 + 1;
+      }
+    | exp '*' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::MUL>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '/' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::DIV>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '%' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::MOD>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '+' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::ADD>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '-' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::SUB>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp LSHIFT exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::LSHIFT>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp RSHIFT exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::RSHIFT>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '<' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::LT>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp LE exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::LE>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '>' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::GT>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp GE exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::GE>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp EQ exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::EQ>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp NE exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::NE>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '&' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::BITWISE_AND>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '^' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::BITWISE_XOR>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '|' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::BITWISE_OR>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp LOGICAL_AND exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::LOGICAL_AND>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp LOGICAL_OR exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::LOGICAL_OR>());
+        $$ = $1 + $3 + 1;
+      }
+    | exp '?' exp ':' exp
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::TERNARY_IF>());
+        $$ = $1 + $3 + $5 + 1;
+      }
+    | ABSOLUTE '(' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::ABSOLUTE>());
+        $$ = $3 + 1;
+      }
+    | ADDR '(' string ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3));
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::ADDR>());
+        $$ = 2;
+      }
+    | ALIGN '(' exp ')'
+      {
+        RpnExpr::iterator pos = m_ScriptFile.getCurrentRpnExpr()->begin() +
+                                m_ScriptFile.getCurrentRpnExpr()->size() - $3;
+        m_ScriptFile.getCurrentRpnExpr()->insert(pos, SymOperand::create("."));
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::ALIGN>());
+        $$ = $3 + 2;
+      }
+    | ALIGN '(' exp ',' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::ALIGN>());
+        $$ = $3 + $5 + 1;
+      }
+    | ALIGNOF '(' string ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3));
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::ALIGNOF>());
+        $$ = 2;
+      }
+    | BLOCK '(' exp ')'
+      {
+        RpnExpr::iterator pos = m_ScriptFile.getCurrentRpnExpr()->begin() +
+                                m_ScriptFile.getCurrentRpnExpr()->size() - $3;
+        m_ScriptFile.getCurrentRpnExpr()->insert(pos, SymOperand::create("."));
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::ALIGN>());
+        $$ = $3 + 2;
+      }
+    | DATA_SEGMENT_ALIGN
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create("."));
+      }
+      '(' exp ',' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::DATA_SEGMENT_ALIGN>());
+        $$ = $4 + $6 + 2;
+      }
+    | DATA_SEGMENT_END '(' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::DATA_SEGMENT_END>());
+        $$ = $3 + 1;
+      }
+    | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::DATA_SEGMENT_RELRO_END>());
+        $$ = $3 + $5 + 1;
+      }
+    | DEFINED '(' symbol ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create(*$3));
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::DEFINED>());
+        $$ = 2;
+      }
+    | LENGTH '(' string ')'
+      {
+        /* TODO */
+      }
+    | LOADADDR '(' string ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3));
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::LOADADDR>());
+        $$ = 2;
+      }
+    | MAX '(' exp ',' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::MAX>());
+        $$ = $3 + $5 + 1;
+      }
+    | MIN '(' exp ',' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::MIN>());
+        $$ = $3 + $5 + 1;
+      }
+    | NEXT '(' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::NEXT>());
+        $$ = $3 + 1;
+      }
+    | ORIGIN '(' string ')'
+      {
+        /* TODO */
+      }
+    | SEGMENT_START '(' string
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3));
+      }
+      ',' exp ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::SEGMENT_START>());
+        $$ = $6 + 2;
+      }
+    | SIZEOF '(' string ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(SectOperand::create(*$3));
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::SIZEOF>());
+        $$ = 2;
+      }
+    | SIZEOF_HEADERS
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::SIZEOF_HEADERS>());
+        $$ = 1;
+      }
+    | CONSTANT '(' MAXPAGESIZE ')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::MAXPAGESIZE>());
+        $$ = 1;
+      }
+    | CONSTANT '(' COMMONPAGESIZE')'
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(
+          &Operator::create<Operator::COMMONPAGESIZE>());
+        $$ = 1;
+      }
+    | INTEGER
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(IntOperand::create($1));
+        $$ = 1;
+      }
+    | symbol
+      {
+        m_ScriptFile.getCurrentRpnExpr()->push_back(SymOperand::create(*$1));
+        $$ = 1;
+      }
+    ;
+
+symbol : STRING
+         { $$ = $1; }
+       ;
+
+string : STRING
+         { $$ = $1; }
+       | '"' STRING '"'
+         { $$ = $2; }
+       ;
+
+%%
+
+void mcld::ScriptParser::error(const mcld::ScriptParser::location_type& pLoc,
+                               const std::string &pMsg)
+{
+  position last = pLoc.end - 1;
+  std::string filename = "NaN";
+  if (last.filename != NULL)
+    filename = *last.filename;
+
+  mcld::error(diag::err_syntax_error)
+    << filename << last.line << last.column << pMsg;
+}
+
diff --git a/lib/Script/ScriptReader.cpp b/lib/Script/ScriptReader.cpp
new file mode 100644
index 0000000..37c3ce9
--- /dev/null
+++ b/lib/Script/ScriptReader.cpp
@@ -0,0 +1,58 @@
+//===- ScriptReader.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/ScriptReader.h>
+#include <mcld/Script/ScriptScanner.h>
+#include <mcld/Script/ScriptFile.h>
+#include <mcld/MC/Input.h>
+#include <mcld/Support/MemoryArea.h>
+
+#include <llvm/ADT/StringRef.h>
+
+#include <istream>
+#include <sstream>
+
+using namespace mcld;
+
+ScriptReader::ScriptReader(GroupReader& pGroupReader)
+  : m_GroupReader(pGroupReader)
+{
+}
+
+ScriptReader::~ScriptReader()
+{
+}
+
+/// isMyFormat
+bool ScriptReader::isMyFormat(Input& input, bool &doContinue) const
+{
+  doContinue = true;
+  // always return true now
+  return true;
+}
+
+bool ScriptReader::readScript(const LinkerConfig& pConfig,
+                              ScriptFile& pScriptFile)
+{
+  bool result = false;
+  Input& input = pScriptFile.input();
+  size_t size = input.memArea()->size();
+  llvm::StringRef region = input.memArea()->request(input.fileOffset(), size);
+  std::stringbuf buf(region.data());
+
+  std::istream in(&buf);
+  ScriptScanner scanner(&in);
+  ScriptParser parser(pConfig,
+                      pScriptFile,
+                      scanner,
+                      m_GroupReader);
+  result = (0 == parser.parse());;
+
+  return result;
+}
+
diff --git a/lib/Script/ScriptScanner.ll b/lib/Script/ScriptScanner.ll
new file mode 100644
index 0000000..f3fd921
--- /dev/null
+++ b/lib/Script/ScriptScanner.ll
@@ -0,0 +1,388 @@
+/*===- ScriptScanner.ll ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===*/
+
+%{
+/* C/C++ Declarations */
+
+#include <mcld/Script/ScriptScanner.h>
+#include <mcld/Script/ScriptFile.h>
+#include <mcld/Support/MsgHandling.h>
+#include <llvm/ADT/StringRef.h>
+#include <string>
+
+typedef mcld::ScriptParser::token token;
+typedef mcld::ScriptParser::token_type token_type;
+
+#define yyterminate() return token::END
+#define YY_NO_UNISTD_H
+%}
+
+/* Flex Declarations and Options */
+%option c++
+%option batch
+%option noyywrap
+%option nounput
+%option stack
+
+%{
+#define YY_USER_ACTION  yylloc->columns(yyleng);
+%}
+
+/* abbrev. of RE @ref binutils ld/ldlex.l */
+FILENAMECHAR1   [_a-zA-Z\/\.\\\$\_\~]
+SYMBOLCHARN     [_a-zA-Z\/\.\\\$\_\~0-9]
+NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\[\]\\\~]
+WILDCHAR        [_a-zA-Z0-9\/\.\-\_\+\$\[\]\\\,\~\?\*\^\!]
+WS [ \t\r]
+
+/* Start conditions */
+%s LDSCRIPT
+%s EXPRESSION
+
+%% /* Regular Expressions */
+
+ /* code to place at the beginning of yylex() */
+%{
+  /* reset location */
+  yylloc->step();
+
+  /* determine the initial parser state */
+  if (m_Kind == ScriptFile::Unknown) {
+    m_Kind = pScriptFile.getKind();
+    switch (pScriptFile.getKind()) {
+    case ScriptFile::LDScript:
+    case ScriptFile::Expression:
+      return token::LINKER_SCRIPT;
+    case ScriptFile::VersionScript:
+    case ScriptFile::DynamicList:
+    default:
+      assert(0 && "Unsupported script type!");
+      break;
+    }
+  }
+%}
+
+ /* Entry Point */
+<LDSCRIPT>"ENTRY"                      { return token::ENTRY; }
+ /* File Commands */
+<LDSCRIPT>"INCLUDE"                    { return token::INCLUDE; }
+<LDSCRIPT>"INPUT"                      { return token::INPUT; }
+<LDSCRIPT>"GROUP"                      { return token::GROUP; }
+<LDSCRIPT>"AS_NEEDED"                  { return token::AS_NEEDED; }
+<LDSCRIPT>"OUTPUT"                     { return token::OUTPUT; }
+<LDSCRIPT>"SEARCH_DIR"                 { return token::SEARCH_DIR; }
+<LDSCRIPT>"STARTUP"                    { return token::STARTUP; }
+ /* Format Commands */
+<LDSCRIPT>"OUTPUT_FORMAT"              { return token::OUTPUT_FORMAT; }
+<LDSCRIPT>"TARGET"                     { return token::TARGET; }
+ /* Misc Commands */
+<LDSCRIPT>"ASSERT"                     { return token::ASSERT; }
+<LDSCRIPT>"EXTERN"                     { return token::EXTERN; }
+<LDSCRIPT>"FORCE_COMMON_ALLOCATION"    { return token::FORCE_COMMON_ALLOCATION; }
+<LDSCRIPT>"INHIBIT_COMMON_ALLOCATION"  { return token::INHIBIT_COMMON_ALLOCATION; }
+<LDSCRIPT>"INSERT"                     { return token::INSERT; }
+<LDSCRIPT>"NOCROSSREFS"                { return token::NOCROSSREFS; }
+<LDSCRIPT>"OUTPUT_ARCH"                { return token::OUTPUT_ARCH; }
+<LDSCRIPT>"LD_FEATURE"                 { return token::LD_FEATURE; }
+ /* Assignemnts */
+<LDSCRIPT,EXPRESSION>"HIDDEN"          { return token::HIDDEN; }
+<LDSCRIPT,EXPRESSION>"PROVIDE"         { return token::PROVIDE; }
+<LDSCRIPT,EXPRESSION>"PROVIDE_HIDDEN"  { return token::PROVIDE_HIDDEN; }
+ /* SECTIONS Command */
+<LDSCRIPT>"SECTIONS"                   { return token::SECTIONS; }
+ /* MEMORY Command */
+<LDSCRIPT>"MEMORY"                     { return token::MEMORY; }
+ /* PHDRS Command */
+<LDSCRIPT>"PHDRS"                      { return token::PHDRS; }
+ /* Builtin Functions */
+<EXPRESSION>"ABSOLUTE"                 { return token::ABSOLUTE; }
+<EXPRESSION>"ADDR"                     { return token::ADDR; }
+<LDSCRIPT,EXPRESSION>"ALIGN"           { return token::ALIGN; }
+<EXPRESSION>"ALIGNOF"                  { return token::ALIGNOF; }
+<EXPRESSION>"BLOCK"                    { return token::BLOCK; }
+<EXPRESSION>"DATA_SEGMENT_ALIGN"       { return token::DATA_SEGMENT_ALIGN; }
+<EXPRESSION>"DATA_SEGMENT_END"         { return token::DATA_SEGMENT_END; }
+<EXPRESSION>"DATA_SEGMENT_RELRO_END"   { return token::DATA_SEGMENT_RELRO_END; }
+<EXPRESSION>"DEFINED"                  { return token::DEFINED; }
+<EXPRESSION>"LENGTH"                   { return token::LENGTH; }
+<EXPRESSION>"LOADADDR"                 { return token::LOADADDR; }
+<EXPRESSION>"MAX"                      { return token::MAX; }
+<EXPRESSION>"MIN"                      { return token::MIN; }
+<EXPRESSION>"NEXT"                     { return token::NEXT; }
+<EXPRESSION>"ORIGIN"                   { return token::ORIGIN; }
+<EXPRESSION>"SEGMENT_START"            { return token::SEGMENT_START; }
+<EXPRESSION>"SIZEOF"                   { return token::SIZEOF; }
+<EXPRESSION>"SIZEOF_HEADERS"           { return token::SIZEOF_HEADERS; }
+<EXPRESSION>"CONSTANT"                 { return token::CONSTANT; }
+ /* Symbolic Constants */
+<EXPRESSION>"MAXPAGESIZE"              { return token::MAXPAGESIZE; }
+<EXPRESSION>"COMMONPAGESIZE"           { return token::COMMONPAGESIZE; }
+ /* Input Section Description */
+<LDSCRIPT>"EXCLUDE_FILE"               { return token::EXCLUDE_FILE; }
+<LDSCRIPT>"KEEP"                       { return token::KEEP; }
+<LDSCRIPT>"SORT"                       { return token::SORT_BY_NAME; }
+<LDSCRIPT>"SORT_BY_NAME"               { return token::SORT_BY_NAME; }
+<LDSCRIPT>"SORT_BY_ALIGNMENT"          { return token::SORT_BY_ALIGNMENT; }
+<LDSCRIPT>"SORT_NONE"                  { return token::SORT_NONE; }
+<LDSCRIPT>"SORT_BY_INIT_PRIORITY"      { return token::SORT_BY_INIT_PRIORITY; }
+ /* Output Section Data */
+<LDSCRIPT>"BYTE"                       { return token::BYTE; }
+<LDSCRIPT>"SHORT"                      { return token::SHORT; }
+<LDSCRIPT>"LONG"                       { return token::LONG; }
+<LDSCRIPT>"QUAD"                       { return token::QUAD; }
+<LDSCRIPT>"SQUAD"                      { return token::SQUAD; }
+<LDSCRIPT>"FILL"                       { return token::FILL; }
+ /* Output Section Discarding */
+<LDSCRIPT>"DISCARD"                    { return token::DISCARD; }
+ /* Output Section Keywords */
+<LDSCRIPT>"CREATE_OBJECT_SYMBOLS"      { return token::CREATE_OBJECT_SYMBOLS; }
+<LDSCRIPT>"CONSTRUCTORS"               { return token::CONSTRUCTORS; }
+ /* Output Section Attributes */
+ /* Output Section Type */
+<LDSCRIPT,EXPRESSION>"NOLOAD"          { return token::NOLOAD; }
+<LDSCRIPT,EXPRESSION>"DSECT"           { return token::DSECT; }
+<LDSCRIPT,EXPRESSION>"COPY"            { return token::COPY; }
+<LDSCRIPT,EXPRESSION>"INFO"            { return token::INFO; }
+<LDSCRIPT,EXPRESSION>"OVERLAY"         { return token::OVERLAY; }
+ /* Output Section LMA */
+<LDSCRIPT>"AT"                         { return token::AT; }
+ /* Forced Input Alignment */
+<LDSCRIPT>"SUBALIGN"                   { return token::SUBALIGN; }
+ /* Output Section Constraint */
+<LDSCRIPT>"ONLY_IF_RO"                 { return token::ONLY_IF_RO; }
+<LDSCRIPT>"ONLY_IF_RW"                 { return token::ONLY_IF_RW; }
+ /* Operators */
+<LDSCRIPT,EXPRESSION>"<<"              { return token::LSHIFT; }
+<LDSCRIPT,EXPRESSION>">>"              { return token::RSHIFT; }
+<LDSCRIPT,EXPRESSION>"=="              { return token::EQ; }
+<LDSCRIPT,EXPRESSION>"!="              { return token::NE; }
+<LDSCRIPT,EXPRESSION>"<="              { return token::LE; }
+<LDSCRIPT,EXPRESSION>">="              { return token::GE; }
+<LDSCRIPT,EXPRESSION>"&&"              { return token::LOGICAL_AND; }
+<LDSCRIPT,EXPRESSION>"||"              { return token::LOGICAL_OR; }
+<LDSCRIPT,EXPRESSION>"+="              { return token::ADD_ASSIGN; }
+<LDSCRIPT,EXPRESSION>"-="              { return token::SUB_ASSIGN; }
+<LDSCRIPT,EXPRESSION>"*="              { return token::MUL_ASSIGN; }
+<LDSCRIPT,EXPRESSION>"/="              { return token::DIV_ASSIGN; }
+<LDSCRIPT,EXPRESSION>"&="              { return token::AND_ASSIGN; }
+<LDSCRIPT,EXPRESSION>"|="              { return token::OR_ASSIGN; }
+<LDSCRIPT,EXPRESSION>"<<="             { return token::LS_ASSIGN; }
+<LDSCRIPT,EXPRESSION>">>="             { return token::RS_ASSIGN; }
+<LDSCRIPT,EXPRESSION>","               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"="               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"?"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>":"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"|"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"^"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"&"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"<"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>">"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"+"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"-"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"*"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"/"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"%"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"!"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"~"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>";"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"("               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>")"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"{"               { return static_cast<token_type>(*yytext); }
+<LDSCRIPT,EXPRESSION>"}"               { return static_cast<token_type>(*yytext); }
+
+ /* Numbers */
+<LDSCRIPT,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? {
+  llvm::StringRef str(yytext, yyleng);
+  switch (str.back()) {
+  case 'k':
+  case 'K':
+    str.substr(0, yyleng - 1).getAsInteger(0, yylval->integer);
+    yylval->integer *= 1024;
+    break;
+  case 'm':
+  case 'M':
+    str.substr(0, yyleng - 1).getAsInteger(0, yylval->integer);
+    yylval->integer *= 1024 * 1024;
+    break;
+  default:
+    str.getAsInteger(0, yylval->integer);
+    break;
+  }
+  return token::INTEGER;
+}
+
+ /* Expression string */
+<EXPRESSION>{FILENAMECHAR1}{SYMBOLCHARN}* {
+  const std::string& str = pScriptFile.createParserStr(yytext, yyleng);
+  yylval->string = &str;
+  return token::STRING;
+}
+
+ /* String */
+<LDSCRIPT>{FILENAMECHAR1}{NOCFILENAMECHAR}* {
+  const std::string& str = pScriptFile.createParserStr(yytext, yyleng);
+  yylval->string = &str;
+  return token::STRING;
+}
+
+<LDSCRIPT,EXPRESSION>\"(\\.|[^\\"])*\" {
+  /*" c string literal */
+  const std::string& str = pScriptFile.createParserStr(yytext, yyleng);
+  yylval->string = &str;
+  return token::STRING;
+}
+
+ /* -l namespec */
+<LDSCRIPT>"-l"{FILENAMECHAR1}{NOCFILENAMECHAR}* {
+  const std::string& str = pScriptFile.createParserStr(yytext + 2, yyleng - 2);
+  yylval->string = &str;
+  return token::LNAMESPEC;
+}
+
+ /* WILDCHAR String */
+<LDSCRIPT>{WILDCHAR}* {
+  if (yytext[0] == '/' && yytext[1] == '*') {
+    yyless (2);
+    enterComments(*yylloc);
+  } else {
+    const std::string& str = pScriptFile.createParserStr(yytext, yyleng);
+    yylval->string = &str;
+    return token::STRING;
+  }
+}
+
+ /* gobble up C comments */
+<LDSCRIPT,EXPRESSION>"/*" {
+  enterComments(*yylloc);
+  yylloc->step();
+}
+
+ /* gobble up white-spaces */
+<LDSCRIPT,EXPRESSION>{WS}+ {
+  yylloc->step();
+}
+
+ /* gobble up end-of-lines */
+<LDSCRIPT,EXPRESSION>\n {
+  yylloc->lines(1);
+  yylloc->step();
+}
+
+%% /* Additional Code */
+
+namespace mcld {
+
+ScriptScanner::ScriptScanner(std::istream* yyin, std::ostream* yyout)
+  : yyFlexLexer(yyin, yyout), m_Kind(ScriptFile::Unknown)
+{
+}
+
+ScriptScanner::~ScriptScanner()
+{
+}
+
+void ScriptScanner::enterComments(ScriptParser::location_type& pLocation)
+{
+  const int start_line = pLocation.begin.line;
+  const int start_col  = pLocation.begin.column;
+
+  int ch = 0;
+
+  while (true) {
+    ch = yyinput();
+    pLocation.columns(1);
+
+    while (ch != '*' && ch != EOF) {
+      if (ch == '\n') {
+        pLocation.lines(1);
+      }
+
+      ch = yyinput();
+      pLocation.columns(1);
+    }
+
+    if (ch == '*') {
+      ch = yyinput();
+      pLocation.columns(1);
+
+      while (ch == '*') {
+        ch = yyinput();
+        pLocation.columns(1);
+      }
+
+      if (ch == '/')
+        break;
+    }
+
+    if (ch == '\n')
+      pLocation.lines(1);
+
+    if (ch == EOF) {
+      error(diag::err_unterminated_comment) << pLocation.begin.filename
+                                            << start_line
+                                            << start_col;
+      break;
+    }
+  }
+}
+
+void ScriptScanner::setLexState(ScriptFile::Kind pKind)
+{
+  /* push the state into the top of stach */
+  m_StateStack.push(pKind);
+
+  switch (pKind) {
+  case ScriptFile::LDScript:
+    BEGIN(LDSCRIPT);
+    break;
+  case ScriptFile::Expression:
+    BEGIN(EXPRESSION);
+    break;
+  case ScriptFile::VersionScript:
+  case ScriptFile::DynamicList:
+  default:
+    assert(0 && "Unsupported script type!");
+    break;
+  }
+}
+
+void ScriptScanner::popLexState()
+{
+  /* pop the last state */
+  m_StateStack.pop();
+
+  /* resume the appropriate state */
+  if (!m_StateStack.empty()) {
+    switch (m_StateStack.top()) {
+    case ScriptFile::LDScript:
+      BEGIN(LDSCRIPT);
+      break;
+    case ScriptFile::Expression:
+      BEGIN(EXPRESSION);
+      break;
+    case ScriptFile::VersionScript:
+    case ScriptFile::DynamicList:
+    default:
+      assert(0 && "Unsupported script type!");
+      break;
+    }
+  }
+}
+
+} /* namespace of mcld */
+
+#ifdef yylex
+#undef yylex
+#endif
+
+int yyFlexLexer::yylex()
+{
+  return 0;
+}
+
diff --git a/lib/Script/SearchDirCmd.cpp b/lib/Script/SearchDirCmd.cpp
new file mode 100644
index 0000000..dd9a56f
--- /dev/null
+++ b/lib/Script/SearchDirCmd.cpp
@@ -0,0 +1,38 @@
+//===- SearchDirCmd.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/SearchDirCmd.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/Module.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// SearchDirCmd
+//===----------------------------------------------------------------------===//
+SearchDirCmd::SearchDirCmd(const std::string& pPath)
+  : ScriptCommand(ScriptCommand::SEARCH_DIR),
+    m_Path(pPath)
+{
+}
+
+SearchDirCmd::~SearchDirCmd()
+{
+}
+
+void SearchDirCmd::dump() const
+{
+  mcld::outs() << "SEARCH_DIR ( " << m_Path << " )\n";
+}
+
+void SearchDirCmd::activate(Module& pModule)
+{
+  pModule.getScript().directories().insert(m_Path);
+}
+
diff --git a/lib/Script/SectionsCmd.cpp b/lib/Script/SectionsCmd.cpp
new file mode 100644
index 0000000..4ecc838
--- /dev/null
+++ b/lib/Script/SectionsCmd.cpp
@@ -0,0 +1,94 @@
+//===- SectionsCmd.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/SectionsCmd.h>
+#include <mcld/Support/raw_ostream.h>
+#include <cassert>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// SectionsCmd
+//===----------------------------------------------------------------------===//
+SectionsCmd::SectionsCmd()
+  : ScriptCommand(ScriptCommand::SECTIONS)
+{
+}
+
+SectionsCmd::~SectionsCmd()
+{
+  for (iterator it = begin(), ie = end(); it != ie; ++it) {
+    if (*it != NULL)
+      delete *it;
+  }
+}
+
+void SectionsCmd::dump() const
+{
+  mcld::outs() << "SECTIONS\n{\n";
+
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+    switch ((*it)->getKind()) {
+    case ScriptCommand::ENTRY:
+    case ScriptCommand::ASSIGNMENT:
+    case ScriptCommand::OUTPUT_SECT_DESC:
+      mcld::outs() << "\t";
+      (*it)->dump();
+      break;
+    default:
+      assert(0);
+      break;
+    }
+  }
+
+  mcld::outs() << "}\n";
+}
+
+void SectionsCmd::push_back(ScriptCommand* pCommand)
+{
+  switch (pCommand->getKind()) {
+  case ScriptCommand::ENTRY:
+  case ScriptCommand::ASSIGNMENT:
+  case ScriptCommand::OUTPUT_SECT_DESC:
+    m_SectionCommands.push_back(pCommand);
+    break;
+  default:
+    assert(0);
+    break;
+  }
+}
+
+void SectionsCmd::activate(Module& pModule)
+{
+  // Assignment between output sections
+  SectionCommands assignments;
+
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
+    switch ((*it)->getKind()) {
+    case ScriptCommand::ENTRY:
+      (*it)->activate(pModule);
+      break;
+    case ScriptCommand::ASSIGNMENT:
+      assignments.push_back(*it);
+      break;
+    case ScriptCommand::OUTPUT_SECT_DESC: {
+      (*it)->activate(pModule);
+
+      iterator assign, assignEnd = assignments.end();
+      for (assign = assignments.begin(); assign != assignEnd; ++assign)
+        (*assign)->activate(pModule);
+      assignments.clear();
+
+      break;
+    }
+    default:
+      assert(0);
+      break;
+    }
+  }
+}
diff --git a/lib/Script/StrToken.cpp b/lib/Script/StrToken.cpp
new file mode 100644
index 0000000..f886623
--- /dev/null
+++ b/lib/Script/StrToken.cpp
@@ -0,0 +1,52 @@
+//===- StrToken.cpp -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/StrToken.h>
+#include <mcld/Support/GCFactory.h>
+#include <llvm/Support/ManagedStatic.h>
+
+using namespace mcld;
+
+typedef GCFactory<StrToken, MCLD_SYMBOLS_PER_INPUT> StrTokenFactory;
+static llvm::ManagedStatic<StrTokenFactory> g_StrTokenFactory;
+
+//===----------------------------------------------------------------------===//
+// StrToken
+//===----------------------------------------------------------------------===//
+StrToken::StrToken()
+  : m_Kind(Unknown)
+{
+}
+
+StrToken::StrToken(Kind pKind, const std::string& pString)
+  : m_Kind(pKind), m_Name(pString)
+{
+}
+
+StrToken::~StrToken()
+{
+}
+
+StrToken* StrToken::create(const std::string& pString)
+{
+  StrToken* result = g_StrTokenFactory->allocate();
+  new (result) StrToken(String, pString);
+  return result;
+}
+
+void StrToken::destroy(StrToken*& pStrToken)
+{
+  g_StrTokenFactory->destroy(pStrToken);
+  g_StrTokenFactory->deallocate(pStrToken);
+  pStrToken = NULL;
+}
+
+void StrToken::clear()
+{
+  g_StrTokenFactory->clear();
+}
diff --git a/lib/Script/StringList.cpp b/lib/Script/StringList.cpp
new file mode 100644
index 0000000..e5637fb
--- /dev/null
+++ b/lib/Script/StringList.cpp
@@ -0,0 +1,60 @@
+//===- StringList.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/StringList.h>
+#include <mcld/Script/StrToken.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/GCFactory.h>
+#include <llvm/Support/ManagedStatic.h>
+
+using namespace mcld;
+
+typedef GCFactory<StringList, MCLD_SYMBOLS_PER_INPUT> StringListFactory;
+static llvm::ManagedStatic<StringListFactory> g_StringListFactory;
+
+//===----------------------------------------------------------------------===//
+// StringList
+//===----------------------------------------------------------------------===//
+StringList::StringList()
+{
+}
+
+StringList::~StringList()
+{
+}
+
+void StringList::push_back(StrToken* pToken)
+{
+  m_Tokens.push_back(pToken);
+}
+
+void StringList::dump() const
+{
+  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
+    mcld::outs() << (*it)->name() << "\t";
+  mcld::outs() << "\n";
+}
+
+StringList* StringList::create()
+{
+  StringList* result = g_StringListFactory->allocate();
+  new (result) StringList();
+  return result;
+}
+
+void StringList::destroy(StringList*& pStringList)
+{
+  g_StringListFactory->destroy(pStringList);
+  g_StringListFactory->deallocate(pStringList);
+  pStringList = NULL;
+}
+
+void StringList::clear()
+{
+  g_StringListFactory->clear();
+}
diff --git a/lib/Script/TernaryOp.cpp b/lib/Script/TernaryOp.cpp
new file mode 100644
index 0000000..131f460
--- /dev/null
+++ b/lib/Script/TernaryOp.cpp
@@ -0,0 +1,58 @@
+//===- TernaryOp.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/TernaryOp.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/ADT/SizeTraits.h>
+
+using namespace mcld;
+//===----------------------------------------------------------------------===//
+// TernaryOp
+//===----------------------------------------------------------------------===//
+template<>
+IntOperand*
+TernaryOp<Operator::TERNARY_IF>::eval(const Module& pModule,
+                                      const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  if (m_pOperand[0]->value())
+    res->setValue(m_pOperand[1]->value());
+  else
+    res->setValue(m_pOperand[2]->value());
+  return res;
+}
+
+/* DATA_SEGMENT_ALIGN(maxpagesize, commonpagesize) */
+template<>
+IntOperand*
+TernaryOp<Operator::DATA_SEGMENT_ALIGN>::eval(const Module& pModule,
+                                              const TargetLDBackend& pBackend)
+{
+  /* This is equivalent to either
+       (ALIGN(maxpagesize) + (. & (maxpagesize - 1)))
+     or
+       (ALIGN(maxpagesize) + (. & (maxpagesize - commonpagesize)))
+   */
+  IntOperand* res = result();
+  uint64_t dot = m_pOperand[0]->value();
+  uint64_t maxPageSize = m_pOperand[1]->value();
+  uint64_t commonPageSize = m_pOperand[2]->value();
+  uint64_t form1 = 0, form2 = 0;
+
+  alignAddress(dot, maxPageSize);
+
+  form1 = dot + (dot & (maxPageSize - 1));
+  form2 = dot + (dot & (maxPageSize - commonPageSize));
+
+  if (form1 <= form2)
+    res->setValue(form1);
+  else
+    res->setValue(form2);
+  return res;
+}
+
diff --git a/lib/Script/UnaryOp.cpp b/lib/Script/UnaryOp.cpp
new file mode 100644
index 0000000..866bbb2
--- /dev/null
+++ b/lib/Script/UnaryOp.cpp
@@ -0,0 +1,188 @@
+//===- UnaryOp.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/UnaryOp.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Object/SectionMap.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/Module.h>
+#include <llvm/Support/Casting.h>
+#include <cassert>
+
+using namespace mcld;
+//===----------------------------------------------------------------------===//
+// UnaryOp
+//===----------------------------------------------------------------------===//
+template<>
+IntOperand* UnaryOp<Operator::UNARY_PLUS>::eval(const Module& pModule,
+                                                const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(+ m_pOperand->value());
+  return res;
+}
+
+template<>
+IntOperand*
+UnaryOp<Operator::UNARY_MINUS>::eval(const Module& pModule,
+                                     const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(- m_pOperand->value());
+  return res;
+}
+
+template<>
+IntOperand*
+UnaryOp<Operator::LOGICAL_NOT>::eval(const Module& pModule,
+                                     const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(! m_pOperand->value());
+  return res;
+}
+
+template<>
+IntOperand*
+UnaryOp<Operator::BITWISE_NOT>::eval(const Module& pModule,
+                                     const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(~ m_pOperand->value());
+  return res;
+}
+
+template<>
+IntOperand* UnaryOp<Operator::ABSOLUTE>::eval(const Module& pModule,
+                                              const TargetLDBackend& pBackend)
+{
+  // TODO
+  assert(0);
+  return result();
+}
+
+template<>
+IntOperand* UnaryOp<Operator::ADDR>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  const LDSection* sect = NULL;
+  switch (m_pOperand->type()) {
+  case Operand::SECTION:
+    sect = pModule.getSection(llvm::cast<SectOperand>(m_pOperand)->name());
+    break;
+  case Operand::SECTION_DESC:
+    sect = llvm::cast<SectDescOperand>(m_pOperand)->outputDesc()->getSection();
+    break;
+  default:
+    assert(0);
+    break;
+  }
+  assert(sect != NULL);
+  res->setValue(sect->addr());
+  return res;
+}
+
+template<>
+IntOperand* UnaryOp<Operator::ALIGNOF>::eval(const Module& pModule,
+                                             const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  const LDSection* sect = NULL;
+  switch (m_pOperand->type()) {
+  case Operand::SECTION:
+    sect = pModule.getSection(llvm::cast<SectOperand>(m_pOperand)->name());
+    break;
+  case Operand::SECTION_DESC:
+    sect = llvm::cast<SectDescOperand>(m_pOperand)->outputDesc()->getSection();
+    break;
+  default:
+    assert(0);
+    break;
+  }
+  assert(sect != NULL);
+  res->setValue(sect->align());
+  return res;
+}
+
+template<>
+IntOperand*
+UnaryOp<Operator::DATA_SEGMENT_END>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  res->setValue(m_pOperand->value());
+  return res;
+}
+
+template<>
+IntOperand* UnaryOp<Operator::DEFINED>::eval(const Module& pModule,
+                                             const TargetLDBackend& pBackend)
+{
+  // TODO
+  assert(0);
+  return result();
+}
+
+template<>
+IntOperand* UnaryOp<Operator::LENGTH>::eval(const Module& pModule,
+                                            const TargetLDBackend& pBackend)
+{
+  // TODO
+  assert(0);
+  return result();
+}
+
+template<>
+IntOperand* UnaryOp<Operator::LOADADDR>::eval(const Module& pModule,
+                                              const TargetLDBackend& pBackend)
+{
+  // TODO
+  assert(0);
+  return result();
+}
+
+template<>
+IntOperand* UnaryOp<Operator::NEXT>::eval(const Module& pModule,
+                                          const TargetLDBackend& pBackend)
+{
+  // TODO
+  assert(0);
+  return result();
+}
+
+template<>
+IntOperand* UnaryOp<Operator::ORIGIN>::eval(const Module& pModule,
+                                            const TargetLDBackend& pBackend)
+{
+  // TODO
+  assert(0);
+  return result();
+}
+
+template<>
+IntOperand* UnaryOp<Operator::SIZEOF>::eval(const Module& pModule,
+                                            const TargetLDBackend& pBackend)
+{
+  IntOperand* res = result();
+  const LDSection* sect = NULL;
+  switch (m_pOperand->type()) {
+  case Operand::SECTION:
+    sect = pModule.getSection(llvm::cast<SectOperand>(m_pOperand)->name());
+    break;
+  case Operand::SECTION_DESC:
+    sect = llvm::cast<SectDescOperand>(m_pOperand)->outputDesc()->getSection();
+    break;
+  default:
+    assert(0);
+    break;
+  }
+  assert(sect != NULL);
+  res->setValue(sect->size());
+  return res;
+}
diff --git a/lib/Script/WildcardPattern.cpp b/lib/Script/WildcardPattern.cpp
new file mode 100644
index 0000000..035250e
--- /dev/null
+++ b/lib/Script/WildcardPattern.cpp
@@ -0,0 +1,69 @@
+//===- WildcardPattern.cpp ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Script/WildcardPattern.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/GCFactory.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <cassert>
+
+using namespace mcld;
+
+typedef GCFactory<WildcardPattern,
+                  MCLD_SYMBOLS_PER_INPUT> WildcardPatternFactory;
+static llvm::ManagedStatic<WildcardPatternFactory> g_WildcardPatternFactory;
+
+//===----------------------------------------------------------------------===//
+// WildcardPattern
+//===----------------------------------------------------------------------===//
+WildcardPattern::WildcardPattern()
+  : m_bIsPrefix(false)
+{
+}
+
+WildcardPattern::WildcardPattern(const std::string& pPattern,
+                                 SortPolicy pPolicy)
+  : StrToken(StrToken::Wildcard, pPattern), m_SortPolicy(pPolicy)
+{
+  if (pPattern.find_first_of('*') == (pPattern.size() - 1))
+    m_bIsPrefix = true;
+  else
+    m_bIsPrefix = false;
+}
+
+WildcardPattern::~WildcardPattern()
+{
+}
+
+llvm::StringRef WildcardPattern::prefix() const
+{
+  if (isPrefix())
+    return llvm::StringRef(name().c_str(), name().size() - 1);
+
+  return llvm::StringRef(name());
+}
+
+WildcardPattern* WildcardPattern::create(const std::string& pPattern,
+                                         SortPolicy pPolicy)
+{
+  WildcardPattern* result = g_WildcardPatternFactory->allocate();
+  new (result) WildcardPattern(pPattern, pPolicy);
+  return result;
+}
+
+void WildcardPattern::destroy(WildcardPattern*& pWildcardPattern)
+{
+  g_WildcardPatternFactory->destroy(pWildcardPattern);
+  g_WildcardPatternFactory->deallocate(pWildcardPattern);
+  pWildcardPattern = NULL;
+}
+
+void WildcardPattern::clear()
+{
+  g_WildcardPatternFactory->clear();
+}
diff --git a/lib/Support/Android.mk b/lib/Support/Android.mk
index ce9c6f1..36983ed 100644
--- a/lib/Support/Android.mk
+++ b/lib/Support/Android.mk
@@ -2,25 +2,21 @@
 
 mcld_support_SRC_FILES := \
   CommandLine.cpp \
-  DefSymParser.cpp \
   Directory.cpp \
-  FileHandle.cpp  \
-  FileSystem.cpp  \
-  HandleToArea.cpp  \
-  LEB128.cpp  \
-  MemoryArea.cpp  \
+  FileHandle.cpp \
+  FileOutputBuffer.cpp \
+  FileSystem.cpp \
+  LEB128.cpp \
+  MemoryArea.cpp \
   MemoryAreaFactory.cpp \
-  MemoryRegion.cpp  \
   MsgHandling.cpp \
-  Path.cpp  \
-  RealPath.cpp  \
-  RegionFactory.cpp \
-  Space.cpp \
+  Path.cpp \
+  raw_ostream.cpp \
+  RealPath.cpp \
   SystemUtils.cpp \
-  TargetRegistry.cpp  \
-  ToolOutputFile.cpp  \
-  raw_mem_ostream.cpp \
-  raw_ostream.cpp
+  Target.cpp \
+  TargetRegistry.cpp \
+  ToolOutputFile.cpp
 
 # For the host
 # =====================================================
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 96eb60b..033f88b 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -142,7 +142,8 @@
     long long unsigned size = 0;
     Arg.drop_front(17).getAsInteger(0, size);
     Val.setPageSize(static_cast<uint64_t>(size));
-  } else if (Arg.startswith("max-page-size=")) {
+  }
+  else if (Arg.startswith("max-page-size=")) {
     Val.setKind(ZOption::MaxPageSize);
     long long unsigned size = 0;
     Arg.drop_front(14).getAsInteger(0, size);
diff --git a/lib/Support/DefSymParser.cpp b/lib/Support/DefSymParser.cpp
deleted file mode 100644
index 424364d..0000000
--- a/lib/Support/DefSymParser.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-//===- DefSymParser.cpp ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/DefSymParser.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/LD/LDSymbol.h>
-
-using namespace llvm;
-using namespace mcld;
-
-DefSymParser::DefSymParser(const Module& pModule)
-  : m_Module(pModule) {
-}
-
-// passing a valid operator will return a number whose quantity relative
-// to other such obtained quantities will give the priority of the operator
-static inline int precedence(const char* x)
-{
-  switch (*x) {
-    case '-' :
-    case '+' : return 0;
-    case '/' :
-    case '*' : return 1;
-    default  : assert("Unsupported operator specified");
-  }
-  return 0;
-}
-
-bool DefSymParser::parse(StringRef pExpr, uint64_t& pSymVal)
-{
-  std::stack<const char*> operatorStack;
-  std::stack<unsigned long> operandStack;
-  unsigned long operand1 = 0,
-                operand2 = 0,
-                result = 0;
-  std::string token;
-  std::vector<std::string> postfixString;
-  std::vector<std::string>::iterator it;
-  llvm::StringRef::iterator si = pExpr.begin();
-
-  // Implement a modified Shunting Yard algorithm to form a RPN of the
-  // given expression
-  while (si != pExpr.end()) {
-    if (*si == '+' || *si == '-' || *si == '*' || *si == '/') {
-      if (token.empty() && (*si == '+' || *si == '-'))
-        // we have a case such as a++b or a+-b or a-+b
-        // pushing 0 when a token begins with a + or - operator
-        // solves unary operator problem
-        token = "0";
-      // An operator encountered means a token ended, push it to
-      // postfix string queue.
-      postfixString.push_back(token);
-      token.clear();
-
-      if (operatorStack.empty()) {
-        operatorStack.push(si);
-      }
-      else {
-        if (precedence(si) <= precedence(operatorStack.top())) {
-          // if the precedence of incoming operator is less or equal to
-          // top of stack, we clear stack till top is lower precedence
-          // or its empty
-          while (!operatorStack.empty()) {
-            if (precedence(si) <= precedence(operatorStack.top())) {
-            postfixString.push_back(std::string(operatorStack.top(),1));
-            operatorStack.pop();
-            }
-            else {
-              break;
-            }
-          }
-        }
-        operatorStack.push(si);
-      }
-      si++;
-      continue;
-    }
-    // keep reading the token when there is no operator encountered
-    token += *si;
-    si++;
-  }
-  postfixString.push_back(token);
-  // pop off any remaining operators from operator stack
-  while (!operatorStack.empty()) {
-    postfixString.push_back(std::string(operatorStack.top(),1));
-    operatorStack.pop();
-  }
-  //evaluate the postfix expression written above
-
-  for (it=postfixString.begin(); it != postfixString.end(); it++) {
-    switch (*((*it).c_str())) {
-      case '*':
-      case '-':
-      case '+':
-      case '/':
-        // when postfix string has an operator, pop first two operands from
-        // operand stack, use them in evaluate expression and push result
-        // back to stack
-        assert(!operandStack.empty() && "Invalid expression: extra operand");
-        operand2 = operandStack.top();
-        operandStack.pop();
-        operand1 = operandStack.top();
-        operandStack.pop();
-        if (*((*it).c_str()) == '*')
-          result = operand1 * operand2;
-        else if (*((*it).c_str()) == '/')
-          result = operand1 / operand2;
-        else if (*((*it).c_str()) == '-')
-          result = operand1 - operand2;
-        else
-          result = operand1 + operand2;
-        operandStack.push(result);
-        break;
-      default:
-        // if the string encountered in postfix queue is a string
-        // try converting it to integer.
-        llvm::StringRef stringOperand(*it);
-        if(stringOperand.getAsInteger(0,result)) {
-          // the integer conversion failed means the token is a symbol
-          // or its invalid if the NamePool has no such symbol;
-          const LDSymbol* symbol =
-                              m_Module.getNamePool().findSymbol(stringOperand);
-
-          if (!symbol)
-            fatal(diag::fail_sym_resolution)
-                  << __FILE__ << __LINE__
-                  << "mclinker@googlegroups.com" ;
-          result = symbol->value();
-        }
-        operandStack.push(result);
-    }
-  }
-  // once complete queue is processed, stack top is result
-  pSymVal = operandStack.top();
-  return true;
-}
diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp
new file mode 100644
index 0000000..ed8c898
--- /dev/null
+++ b/lib/Support/FileOutputBuffer.cpp
@@ -0,0 +1,59 @@
+//===- FileOutputBuffer.cpp ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/FileOutputBuffer.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/Path.h>
+
+using namespace mcld;
+using llvm::sys::fs::mapped_file_region;
+
+FileOutputBuffer::FileOutputBuffer(llvm::sys::fs::mapped_file_region* pRegion,
+                                   FileHandle& pFileHandle)
+  : m_pRegion(pRegion), m_FileHandle(pFileHandle)
+{
+}
+
+FileOutputBuffer::~FileOutputBuffer()
+{
+  // Unmap buffer, letting OS flush dirty pages to file on disk.
+  m_pRegion.reset(0);
+}
+
+llvm::error_code FileOutputBuffer::create(FileHandle& pFileHandle,
+    size_t pSize, llvm::OwningPtr<FileOutputBuffer>& pResult)
+{
+  llvm::error_code EC;
+  llvm::OwningPtr<mapped_file_region> mapped_file(new mapped_file_region(
+      pFileHandle.handler(),
+      false,
+      mapped_file_region::readwrite,
+      pSize,
+      0,
+      EC));
+
+  if (EC)
+    return EC;
+
+  pResult.reset(new FileOutputBuffer(mapped_file.get(), pFileHandle));
+  if (pResult)
+    mapped_file.take();
+  return llvm::error_code::success();
+}
+
+MemoryRegion FileOutputBuffer::request(size_t pOffset, size_t pLength)
+{
+  if (pOffset > getBufferSize() || (pOffset + pLength) > getBufferSize())
+    return MemoryRegion();
+  return MemoryRegion(getBufferStart() + pOffset, pLength);
+}
+
+llvm::StringRef FileOutputBuffer::getPath() const
+{
+  return m_FileHandle.path().native();
+}
diff --git a/lib/Support/HandleToArea.cpp b/lib/Support/HandleToArea.cpp
deleted file mode 100644
index 31a26c5..0000000
--- a/lib/Support/HandleToArea.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-//===- HandleToArea.cpp ----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/HandleToArea.h>
-#include <mcld/Support/MemoryArea.h>
-#include <llvm/ADT/StringRef.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// HandleToArea
-//===----------------------------------------------------------------------===//
-bool HandleToArea::push_back(FileHandle* pHandle, MemoryArea* pArea)
-{
-  if (NULL == pHandle || NULL == pArea)
-    return false;
-
-  Bucket bucket;
-  bucket.hash_value = HashFunction()(
-                              llvm::StringRef(pHandle->path().native().c_str(),
-                                              pHandle->path().native().size()));
-
-  bucket.handle = pHandle;
-  bucket.area = pArea;
-  m_AreaMap.push_back(bucket);
-  return true;
-}
-
-bool HandleToArea::erase(MemoryArea* pArea)
-{
-  if (NULL == pArea || NULL == pArea->handler())
-    return false;
-
-  return erase(pArea->handler()->path());
-}
-
-bool HandleToArea::erase(const sys::fs::Path& pPath)
-{
-  unsigned int hash_value = HashFunction()(
-                                  llvm::StringRef(pPath.native().c_str(),
-                                                  pPath.native().size()));
-
-  HandleToAreaMap::iterator bucket, bEnd = m_AreaMap.end();
-  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
-    if (bucket->hash_value == hash_value && bucket->handle->path() == pPath) {
-      // found
-      m_AreaMap.erase(bucket);
-      return true;
-    }
-  }
-
-  return false;
-}
-
-HandleToArea::Result HandleToArea::findFirst(const sys::fs::Path& pPath)
-{
-  unsigned int hash_value = HashFunction()(llvm::StringRef(pPath.native().c_str(),
-                                                         pPath.native().size()));
-
-  HandleToAreaMap::iterator bucket, bEnd = m_AreaMap.end();
-
-  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
-    if (bucket->hash_value == hash_value) {
-      if (bucket->handle->path() == pPath) {
-        return Result(bucket->handle, bucket->area);
-      }
-    }
-  }
-
-  return Result(NULL, NULL);
-}
-
-HandleToArea::ConstResult HandleToArea::findFirst(const sys::fs::Path& pPath) const
-{
-  unsigned int hash_value = HashFunction()(llvm::StringRef(pPath.native().c_str(),
-                                                         pPath.native().size()));
-
-  HandleToAreaMap::const_iterator bucket, bEnd = m_AreaMap.end();
-
-  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
-    if (bucket->hash_value == hash_value) {
-      if (bucket->handle->path() == pPath) {
-        return ConstResult(bucket->handle, bucket->area);
-      }
-    }
-  }
-
-  return ConstResult(NULL, NULL);
-}
-
diff --git a/lib/Support/MemoryArea.cpp b/lib/Support/MemoryArea.cpp
index c4015ea..862e6f1 100644
--- a/lib/Support/MemoryArea.cpp
+++ b/lib/Support/MemoryArea.cpp
@@ -7,161 +7,39 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/Space.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/MsgHandling.h>
+#include <llvm/Support/system_error.h>
+
+#include <cassert>
 
 using namespace mcld;
 
 //===--------------------------------------------------------------------===//
 // MemoryArea
 //===--------------------------------------------------------------------===//
-// MemoryArea - special constructor
-// This constructor is used for *SPECIAL* situation. I'm sorry I can not
-// reveal what is the special situation.
-MemoryArea::MemoryArea(Space& pUniverse)
-  : m_pFileHandle(NULL) {
-  m_SpaceMap.insert(std::make_pair(Key(pUniverse.start(), pUniverse.size()),
-                                   &pUniverse));
-}
-
-MemoryArea::MemoryArea(FileHandle& pFileHandle)
-  : m_pFileHandle(&pFileHandle) {
-}
-
-MemoryArea::~MemoryArea()
+MemoryArea::MemoryArea(llvm::StringRef pFilename)
 {
+  llvm::MemoryBuffer::getFile(pFilename,
+                              m_pMemoryBuffer,
+                              /*FileSize*/ -1,
+                              /*RequiresNullTerminator*/ false);
 }
 
-// The layout of MemorySpace in the virtual memory space
-//
-// |  : page boundary
-// [,]: MemoryRegion
-// -  : fillment
-// =  : data
-//
-// |---[=|====|====|==]--|
-// ^   ^              ^  ^
-// |   |              |  |
-// | r_start      +r_len |
-// space.data      +space.size
-//
-// space.file_offset is the offset of the mapped file segment from the start of
-// the file. if the MemorySpace's type is ALLOCATED_ARRAY, the distances of
-// (space.data, r_start) and (r_len, space.size) are zero.
-//
-MemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength)
+MemoryArea::MemoryArea(const char* pMemBuffer, size_t pSize)
 {
-  Space* space = find(pOffset, pLength);
-  if (NULL == space) {
-    // not found
-    if (NULL == m_pFileHandle) {
-      // if m_pFileHandle is NULL, clients delegate us an universal Space and
-      // we never remove it. In that way, space can not be NULL.
-      unreachable(diag::err_out_of_range_region) << pOffset << pLength;
-    }
-
-    space = Space::Create(*m_pFileHandle, pOffset, pLength);
-    m_SpaceMap.insert(std::make_pair(Key(space->start(), space->size()), space));
-  }
-
-  // adjust r_start
-  off_t distance = pOffset - space->start();
-  void* r_start = space->memory() + distance;
-
-  // now, we have a legal space to hold the new MemoryRegion
-  return MemoryRegion::Create(r_start, pLength, *space);
+  llvm::StringRef mem(pMemBuffer, pSize);
+  llvm::MemoryBuffer* buffer =
+      llvm::MemoryBuffer::getMemBuffer(mem, /*BufferName*/ "NaN",
+                                       /*RequiresNullTerminator*/ false);
+  assert(buffer != NULL);
+  m_pMemoryBuffer.reset(buffer);
 }
 
-// release - release a MemoryRegion
-void MemoryArea::release(MemoryRegion* pRegion)
+llvm::StringRef MemoryArea::request(size_t pOffset, size_t pLength)
 {
-  if (NULL == pRegion)
-    return;
-
-  Space *space = pRegion->parent();
-  MemoryRegion::Destroy(pRegion);
-
-  if (0 == space->numOfRegions()) {
-
-    if (NULL != m_pFileHandle) {
-      // if m_pFileHandle is NULL, clients delegate us an universal Space and
-      // we never remove it. Otherwise, we have to synchronize and release
-      // Space.
-      if (m_pFileHandle->isWritable()) {
-        // synchronize writable space before we release it.
-        Space::Sync(space, *m_pFileHandle);
-      }
-
-      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);
-    }
-  }
+  return llvm::StringRef(m_pMemoryBuffer->getBufferStart() + pOffset, pLength);
 }
 
-// clear - release all MemoryRegions
-void MemoryArea::clear()
+size_t MemoryArea::size() const
 {
-  if (NULL == m_pFileHandle)
-    return;
-
-  SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
-  if (m_pFileHandle->isWritable()) {
-    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 {
-    for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
-      Space::Release(space->second, *m_pFileHandle);
-      assert(NULL != space->second);
-      Space::Destroy(space->second);
-    }
-  }
-
-  m_SpaceMap.clear();
+  return m_pMemoryBuffer->getBufferSize();
 }
-
-//===--------------------------------------------------------------------===//
-// SpaceList methods
-//===--------------------------------------------------------------------===//
-Space* MemoryArea::find(size_t pOffset, size_t pLength)
-{
-  std::pair<SpaceMapType::iterator, SpaceMapType::iterator> range =
-    m_SpaceMap.equal_range(Key(pOffset, pLength));
-  SpaceMapType::iterator it;
-  for (it = range.first; it != range.second; ++it) {
-    if ((it->second->start() <= pOffset) &&
-        ((pOffset + pLength) <= (it->second->start() + it->second->size())))
-      return it->second;
-  }
-  return NULL;
-}
-
-const Space* MemoryArea::find(size_t pOffset, size_t pLength) const
-{
-  std::pair<SpaceMapType::const_iterator, SpaceMapType::const_iterator> range =
-    m_SpaceMap.equal_range(Key(pOffset, pLength));
-  SpaceMapType::const_iterator it;
-  for (it = range.first; it != range.second; ++it) {
-    if ((it->second->start() <= pOffset) &&
-        ((pOffset + pLength) <= (it->second->start() + it->second->size())))
-      return it->second;
-  }
-  return NULL;
-}
-
diff --git a/lib/Support/MemoryAreaFactory.cpp b/lib/Support/MemoryAreaFactory.cpp
index 224e0a6..655c525 100644
--- a/lib/Support/MemoryAreaFactory.cpp
+++ b/lib/Support/MemoryAreaFactory.cpp
@@ -9,7 +9,6 @@
 #include <mcld/Support/MemoryAreaFactory.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/SystemUtils.h>
-#include <mcld/Support/Space.h>
 
 using namespace mcld;
 
@@ -22,88 +21,59 @@
 
 MemoryAreaFactory::~MemoryAreaFactory()
 {
-  HandleToArea::iterator rec, rEnd = m_HandleToArea.end();
-  for (rec = m_HandleToArea.begin(); rec != rEnd; ++rec) {
-    if (rec->handle->isOpened()) {
-      rec->handle->close();
-    }
-    delete rec->handle;
-  }
 }
 
-MemoryArea*
-MemoryAreaFactory::produce(const sys::fs::Path& pPath,
-                           FileHandle::OpenMode pMode)
+MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath,
+                                       FileHandle::OpenMode pMode)
 {
-  HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
-  if (NULL == map_result.area) {
-    // can not found
-    FileHandle* handler = new FileHandle();
-    if (!handler->open(pPath, pMode)) {
-      error(diag::err_cannot_open_file) << pPath
-                                        << sys::strerror(handler->error());
-    }
-
+  llvm::StringRef name(pPath.native());
+  if (m_AreaMap.find(name) == m_AreaMap.end()) {
     MemoryArea* result = allocate();
-    new (result) MemoryArea(*handler);
-
-    m_HandleToArea.push_back(handler, result);
+    new (result) MemoryArea(name);
+    m_AreaMap[name] = result;
     return result;
   }
 
-  return map_result.area;
+  return m_AreaMap[name];
 }
 
-MemoryArea*
-MemoryAreaFactory::produce(const sys::fs::Path& pPath,
-                           FileHandle::OpenMode pMode,
-                           FileHandle::Permission pPerm)
+MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath,
+                                       FileHandle::OpenMode pMode,
+                                       FileHandle::Permission pPerm)
 {
-  HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
-  if (NULL == map_result.area) {
-    // can not found
-    FileHandle* handler = new FileHandle();
-    if (!handler->open(pPath, pMode, pPerm)) {
-      error(diag::err_cannot_open_file) << pPath
-                                        << sys::strerror(handler->error());
-    }
-
+  llvm::StringRef name(pPath.native());
+  if (m_AreaMap.find(name) == m_AreaMap.end()) {
     MemoryArea* result = allocate();
-    new (result) MemoryArea(*handler);
-
-    m_HandleToArea.push_back(handler, result);
+    new (result) MemoryArea(name);
+    m_AreaMap[name] = result;
     return result;
   }
 
-  return map_result.area;
+  return m_AreaMap[name];
 }
 
 MemoryArea* MemoryAreaFactory::produce(void* pMemBuffer, size_t pSize)
 {
-  Space* space = Space::Create(pMemBuffer, pSize);
-  MemoryArea* result = allocate();
-  new (result) MemoryArea(*space);
-  return result;
+  const char* base = reinterpret_cast<const char*>(pMemBuffer);
+  llvm::StringRef name(base, pSize);
+  if (m_AreaMap.find(name) == m_AreaMap.end()) {
+    MemoryArea* result = allocate();
+    new (result) MemoryArea(base, pSize);
+    m_AreaMap[name] = result;
+    return result;
+  }
+
+  return m_AreaMap[name];
 }
 
-MemoryArea*
-MemoryAreaFactory::produce(int pFD, FileHandle::OpenMode pMode)
+MemoryArea* MemoryAreaFactory::produce(int pFD, FileHandle::OpenMode pMode)
 {
-  FileHandle* handler = new FileHandle();
-  handler->delegate(pFD, pMode);
-  
-  MemoryArea* result = allocate();
-  new (result) MemoryArea(*handler);
-
-  return result;
+  // TODO
+  return NULL;
 }
 
 void MemoryAreaFactory::destruct(MemoryArea* pArea)
 {
-  m_HandleToArea.erase(pArea);
-  pArea->clear();
-  pArea->handler()->close();
   destroy(pArea);
   deallocate(pArea);
 }
-
diff --git a/lib/Support/MemoryRegion.cpp b/lib/Support/MemoryRegion.cpp
deleted file mode 100644
index 410500a..0000000
--- a/lib/Support/MemoryRegion.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- MemoryRegion.cpp ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/RegionFactory.h>
-
-#include <llvm/Support/ManagedStatic.h>
-
-using namespace mcld;
-
-static llvm::ManagedStatic<RegionFactory> g_RegionFactory;
-
-//===----------------------------------------------------------------------===//
-// MemoryRegion
-//===----------------------------------------------------------------------===//
-MemoryRegion::MemoryRegion()
-  : m_pParent(NULL), m_VMAStart(0), m_Length(0) {
-}
-
-MemoryRegion::MemoryRegion(MemoryRegion::Address pVMAStart, size_t pSize)
-  : m_pParent(NULL), m_VMAStart(pVMAStart), m_Length(pSize) {
-}
-
-MemoryRegion::~MemoryRegion()
-{
-}
-
-MemoryRegion* MemoryRegion::Create(void* pStart, size_t pSize)
-{
-  return g_RegionFactory->produce(static_cast<Address>(pStart), pSize);
-}
-
-MemoryRegion* MemoryRegion::Create(void* pStart, size_t pSize, Space& pSpace)
-{
-  MemoryRegion* result = g_RegionFactory->produce(static_cast<Address>(pStart),
-                                                  pSize);
-  result->setParent(pSpace);
-  pSpace.addRegion(*result);
-  return result;
-}
-
-void MemoryRegion::Destroy(MemoryRegion*& pRegion)
-{
-  if (NULL == pRegion)
-    return;
-
-  if (pRegion->hasParent())
-    pRegion->parent()->removeRegion(*pRegion);
-  g_RegionFactory->destruct(pRegion);
-  pRegion = NULL;
-}
-
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index 563fe1f..57d4bd8 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -197,9 +197,10 @@
 
 Path Path::extension() const
 {
-  size_t begin_pos = m_PathName.find_last_of('.');
-  Path result_path(m_PathName.substr(begin_pos));
-  return result_path;
+  size_t pos = m_PathName.find_last_of('.');
+  if (pos == StringType::npos)
+    return Path();
+  return Path(m_PathName.substr(pos));
 }
 
 //===--------------------------------------------------------------------===//
diff --git a/lib/Support/RegionFactory.cpp b/lib/Support/RegionFactory.cpp
deleted file mode 100644
index a52921b..0000000
--- a/lib/Support/RegionFactory.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===- RegionFactory.cpp --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/RegionFactory.h>
-#include <mcld/Support/Space.h>
-
-#include <new>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// RegionFactory
-//===----------------------------------------------------------------------===//
-MemoryRegion*
-RegionFactory::produce(Address pVMAStart, size_t pSize)
-{
-  MemoryRegion* result = Alloc::allocate();
-  new (result) MemoryRegion(pVMAStart, pSize);
-  return result;
-}
-
-void RegionFactory::destruct(MemoryRegion* pRegion)
-{
-  destroy(pRegion);
-  deallocate(pRegion);
-}
-
diff --git a/lib/Support/Space.cpp b/lib/Support/Space.cpp
deleted file mode 100644
index b9a306e..0000000
--- a/lib/Support/Space.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-//===- Space.cpp ----------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/Space.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/SystemUtils.h>
-#include <cstdlib>
-#include <unistd.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// constant data
-//===----------------------------------------------------------------------===//
-static const int PageSize = mcld::sys::GetPageSize();
-
-//===----------------------------------------------------------------------===//
-// Non-member functions
-//===----------------------------------------------------------------------===//
-//
-// low address      A page             high address
-// |--------------------|------------------|
-// ^ page_offset        ^ pFileOffset      ^ page_boundary
-//
-// Given a file offset, return the page offset.
-// return the first page boundary \b before pFileOffset
-inline static off_t page_offset(off_t pFileOffset)
-{ return pFileOffset & ~ (PageSize - 1); }
-
-// page_boundary - Given a file size, return the size to read integral pages.
-// return the first page boundary \b after pFileOffset
-inline static off_t page_boundary(off_t pFileOffset)
-{ return (pFileOffset + (PageSize - 1)) & ~ (PageSize - 1); }
-
-inline static Space::Type policy(off_t pOffset, size_t pLength)
-{
-#if defined(MCLD_ON_WIN32)
-  return Space::ALLOCATED_ARRAY;
-#endif
-  const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux
-  if (pLength < threshold)
-    return Space::ALLOCATED_ARRAY;
-  else
-    return Space::MMAPED;
-}
-
-//===----------------------------------------------------------------------===//
-// Space
-//===----------------------------------------------------------------------===//
-Space::Space()
-  : m_Data(NULL), m_StartOffset(0), m_Size(0),
-    m_RegionCount(0), m_Type(UNALLOCATED) {
-}
-
-Space::Space(Space::Type pType, void* pMemBuffer, size_t pSize)
-  : m_Data(static_cast<Address>(pMemBuffer)), m_StartOffset(0), m_Size(pSize),
-    m_RegionCount(0), m_Type(pType)
-{
-}
-
-Space::~Space()
-{
-  // do nothing. m_Data is deleted by @ref releaseSpace
-}
-
-Space* Space::Create(void* pMemBuffer, size_t pSize)
-{
-  Space* result = new Space(EXTERNAL, pMemBuffer, pSize);
-  return result;
-}
-
-Space* Space::Create(FileHandle& pHandler, size_t pStart, size_t pSize)
-{
-  Type type;
-  void* memory = NULL;
-  Space* result = NULL;
-  size_t start = 0, size = 0, total_offset = 0;
-  switch(type = policy(pStart, pSize)) {
-    case ALLOCATED_ARRAY: {
-      // adjust total_offset, start and size
-      total_offset = pStart + pSize;
-      start = pStart;
-      if (total_offset > pHandler.size()) {
-        if (pHandler.isWritable()) {
-          size = pSize;
-          pHandler.truncate(total_offset);
-        }
-        else if (pHandler.size() > start) {
-          // not writable -> shrink the size
-          size = pHandler.size() - start;
-        }
-        else {
-          // create a space out of a read-only file.
-          fatal(diag::err_cannot_read_small_file) << pHandler.path()
-                                                  << pHandler.size()
-                                                  << start << size;
-        }
-      }
-      else {
-        // within the space.
-        size = pSize;
-      }
-
-      // malloc
-      memory = (void*)malloc(size);
-      if (!pHandler.read(memory, start, size))
-        error(diag::err_cannot_read_file) << pHandler.path() << start << size;
-
-      break;
-    }
-    case MMAPED: {
-      // adjust total_offset, start and size
-      total_offset = page_boundary(pStart + pSize);
-      start = page_offset(pStart);
-      if (total_offset > pHandler.size()) {
-        if (pHandler.isWritable()) {
-          size = page_boundary((pStart - start) + pSize);
-          pHandler.truncate(total_offset);
-        }
-        else if (pHandler.size() > start)
-          size = pHandler.size() - start;
-        else {
-          // create a space out of a read-only file.
-          fatal(diag::err_cannot_read_small_file) << pHandler.path()
-                                                  << pHandler.size()
-                                                  << start << size;
-        }
-      }
-      else
-        size = page_boundary((pStart - start) + pSize);
-
-      // mmap
-      if (!pHandler.mmap(memory, start, size))
-        error(diag::err_cannot_mmap_file) << pHandler.path() << start << size;
-
-      break;
-    }
-    default:
-      break;
-  } // end of switch
-
-  result = new Space(type, memory, size);
-  result->setStart(start);
-  return result;
-}
-
-void Space::Destroy(Space*& pSpace)
-{
-  delete pSpace;
-  pSpace = NULL;
-}
-
-void Space::Release(Space* pSpace, FileHandle& pHandler)
-{
-  if (NULL == pSpace)
-    return;
-
-  switch(pSpace->type()) {
-    case ALLOCATED_ARRAY:
-      free(pSpace->memory());
-      break;
-    case MMAPED:
-      if (!pHandler.munmap(pSpace->memory(), pSpace->size()))
-        error(diag::err_cannot_munmap_file) << pHandler.path();
-      break;
-    default: // external and unallocated memory buffers
-      break;
-  } // end of switch
-}
-
-void Space::Sync(Space* pSpace, FileHandle& pHandler)
-{
-  if (NULL == pSpace || !pHandler.isWritable())
-    return;
-
-  switch(pSpace->type()) {
-    case Space::ALLOCATED_ARRAY: {
-      if (!pHandler.write(pSpace->memory(),
-                          pSpace->start(),
-                          pSpace->size())) {
-        error(diag::err_cannot_write_file) << pHandler.path()
-                                           << pSpace->start()
-                                           << pSpace->size();
-      }
-      return;
-    }
-    case Space::MMAPED:
-    default: {
-      // system will eventually write bakc the memory after
-      // calling ::munmap
-      return;
-    }
-  } // end of switch
-}
-
diff --git a/lib/Support/Target.cpp b/lib/Support/Target.cpp
new file mode 100644
index 0000000..d0e5f29
--- /dev/null
+++ b/lib/Support/Target.cpp
@@ -0,0 +1,81 @@
+//===- Target.cpp ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/Target.h>
+#include <llvm/ADT/Triple.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Target
+//===----------------------------------------------------------------------===//
+Target::Target()
+  : Name(NULL),
+    TripleMatchQualityFn(NULL),
+    TargetMachineCtorFn(NULL),
+    MCLinkerCtorFn(NULL),
+    TargetLDBackendCtorFn(NULL),
+    DiagnosticLineInfoCtorFn(NULL) {
+}
+
+unsigned int Target::getTripleQuality(const llvm::Triple& pTriple) const
+{
+  if (NULL == TripleMatchQualityFn)
+    return 0;
+  return TripleMatchQualityFn(pTriple);
+}
+
+MCLDTargetMachine*
+Target::createTargetMachine(const std::string& pTriple,
+                            const llvm::Target& pTarget,
+                            llvm::TargetMachine& pTM) const
+{
+  if (NULL == TargetMachineCtorFn)
+    return NULL;
+  return TargetMachineCtorFn(pTarget, *this, pTM, pTriple);
+}
+
+/// createMCLinker - create target-specific MCLinker
+MCLinker*
+Target::createMCLinker(const std::string &pTriple,
+                       LinkerConfig& pConfig,
+                       Module& pModule,
+                       FileHandle& pFileHandle) const
+{
+  if (NULL == MCLinkerCtorFn)
+    return NULL;
+  return MCLinkerCtorFn(pTriple, pConfig, pModule, pFileHandle);
+}
+
+/// emulate - given MCLinker default values for the other aspects of the
+/// target system.
+bool Target::emulate(LinkerScript& pScript, LinkerConfig& pConfig) const
+{
+  if (NULL == EmulationFn)
+    return false;
+  return EmulationFn(pScript, pConfig);
+}
+
+/// createLDBackend - create target-specific LDBackend
+TargetLDBackend* Target::createLDBackend(const LinkerConfig& pConfig) const
+{
+    if (NULL == TargetLDBackendCtorFn)
+      return NULL;
+    return TargetLDBackendCtorFn(pConfig);
+}
+
+/// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
+DiagnosticLineInfo*
+Target::createDiagnosticLineInfo(const mcld::Target& pTarget,
+                                 const std::string& pTriple) const
+{
+  if (NULL == DiagnosticLineInfoCtorFn)
+    return NULL;
+  return DiagnosticLineInfoCtorFn(pTarget, pTriple);
+}
+
diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index 38074d5..afffc5c 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/lib/Support/TargetRegistry.cpp
@@ -8,36 +8,98 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/Support/TargetRegistry.h>
 
+using namespace mcld;
 
-mcld::TargetRegistry::TargetListTy mcld::TargetRegistry::s_TargetList;
+TargetRegistry::TargetListTy mcld::TargetRegistry::s_TargetList;
 
-void mcld::TargetRegistry::RegisterTarget(mcld::Target &T)
+//===----------------------------------------------------------------------===//
+// TargetRegistry
+//===----------------------------------------------------------------------===//
+void TargetRegistry::RegisterTarget(Target& pTarget,
+                                    const char* pName,
+                                    Target::TripleMatchQualityFnTy pQualityFn)
 {
-  s_TargetList.push_back(&T);
+  pTarget.Name = pName;
+  pTarget.TripleMatchQualityFn = pQualityFn;
+
+  s_TargetList.push_back(&pTarget);
 }
 
-const mcld::Target*
-mcld::TargetRegistry::lookupTarget(const llvm::Target &pTarget)
+const Target* TargetRegistry::lookupTarget(const std::string &pTriple,
+                                           std::string &pError)
 {
-  mcld::Target *result = 0;
-  TargetListTy::const_iterator TIter, TEnd = s_TargetList.end();
-  for (TIter=s_TargetList.begin(); TIter!=TEnd; ++TIter) {
-    if ((*TIter)->get()==&pTarget) {
-      result = (*TIter);
-      break;
+  if (empty()) {
+    pError = "Unable to find target for this triple (no target are registered)";
+    return NULL;
+  }
+
+  llvm::Triple triple(pTriple);
+  Target* best = NULL, *ambiguity = NULL;
+  unsigned int highest = 0;
+
+  for (iterator target = begin(), ie = end(); target != ie; ++target) {
+    unsigned int quality = (*target)->getTripleQuality(triple);
+    if (quality > 0) {
+      if (NULL == best || highest < quality) {
+        highest = quality;
+        best = *target;
+        ambiguity = NULL;
+      }
+      else if (highest == quality) {
+        ambiguity = *target;
+      }
+    }
+  }
+
+  if (NULL == best) {
+    pError = "No availaible targets are compatible with this triple.";
+    return NULL;
+  }
+
+  if (NULL != ambiguity) {
+    pError = std::string("Ambiguous targets: \"") +
+             best->name() + "\" and \"" + ambiguity->name() + "\"";
+    return NULL;
+  }
+
+  return best;
+}
+
+const Target* TargetRegistry::lookupTarget(const std::string& pArchName,
+                                           llvm::Triple& pTriple,
+                                           std::string& pError)
+{
+  const Target* result = NULL;
+  if (!pArchName.empty()) {
+    for (mcld::TargetRegistry::iterator it = mcld::TargetRegistry::begin(),
+           ie = mcld::TargetRegistry::end(); it != ie; ++it) {
+      if (pArchName == (*it)->name()) {
+        result = *it;
+        break;
+      }
+    }
+
+    if (NULL == result) {
+      pError = std::string("invalid target '") + pArchName + "'.\n";
+      return NULL;
+    }
+
+    // Adjust the triple to match (if known), otherwise stick with the
+    // module/host triple.
+    llvm::Triple::ArchType type =
+                               llvm::Triple::getArchTypeForLLVMName(pArchName);
+    if (llvm::Triple::UnknownArch != type)
+      pTriple.setArch(type);
+  }
+  else {
+    std::string error;
+    result = lookupTarget(pTriple.getTriple(), error);
+    if (NULL == result) {
+      pError = std::string("unable to get target for `") +
+               pTriple.getTriple() + "'\n" +
+               "(Detail: " + error + ")\n";
+      return NULL;
     }
   }
   return result;
 }
-
-const mcld::Target*
-mcld::TargetRegistry::lookupTarget(const std::string &pTriple,
-                                   std::string &pError)
-{
-  const llvm::Target* target = llvm::TargetRegistry::lookupTarget(pTriple, pError);
-  if (!target)
-    return NULL;
-
-  return lookupTarget( *target );
-}
-
diff --git a/lib/Support/ToolOutputFile.cpp b/lib/Support/ToolOutputFile.cpp
index 0554398..1223d93 100644
--- a/lib/Support/ToolOutputFile.cpp
+++ b/lib/Support/ToolOutputFile.cpp
@@ -11,12 +11,12 @@
 #include <mcld/Support/Path.h>
 #include <mcld/Support/FileHandle.h>
 #include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/raw_mem_ostream.h>
 
 #include <mcld/Support/SystemUtils.h>
 #include <mcld/Support/MsgHandling.h>
 
 #include <llvm/Support/Signals.h>
+#include <llvm/Support/Path.h>
 #include <llvm/Support/FormattedStream.h>
 
 using namespace mcld;
@@ -24,56 +24,53 @@
 //===----------------------------------------------------------------------===//
 // CleanupInstaller
 //===----------------------------------------------------------------------===//
-ToolOutputFile::CleanupInstaller::CleanupInstaller(const std::string& pPath)
+ToolOutputFile::CleanupInstaller::CleanupInstaller(const sys::fs::Path& pPath)
   : Keep(false), m_Path(pPath) {
   // Arrange for the file to be deleted if the process is killed.
-  if ("-" != m_Path)
-    llvm::sys::RemoveFileOnSignal(m_Path);
+  if ("-" != m_Path.native())
+    llvm::sys::RemoveFileOnSignal(m_Path.native());
 }
 
 ToolOutputFile::CleanupInstaller::~CleanupInstaller()
 {
   // Delete the file if the client hasn't told us not to.
   // FIXME: In Windows, some path in CJK characters can not be removed by LLVM
-  // sys::fs::remove
-  if (!Keep && "_" != m_Path)
-    llvm::sys::fs::remove(m_Path);
+  // llvm::sys::Path
+  if (!Keep && "_" != m_Path.native()) {
+    bool Existed;
+    llvm::sys::fs::remove(m_Path.native(), Existed);
+  }
 
   // Ok, the file is successfully written and closed, or deleted. There's no
   // further need to clean it up on signals.
-  if ("_" != m_Path)
-    llvm::sys::DontRemoveFileOnSignal(m_Path);
+  if ("_" != m_Path.native())
+    llvm::sys::DontRemoveFileOnSignal(m_Path.native());
 }
 
 //===----------------------------------------------------------------------===//
 // ToolOutputFile
 //===----------------------------------------------------------------------===//
-ToolOutputFile::ToolOutputFile(const std::string& pPath,
+ToolOutputFile::ToolOutputFile(const sys::fs::Path& pPath,
                                FileHandle::OpenMode pMode,
                                FileHandle::Permission pPermission)
   : m_Installer(pPath),
-    m_pMemoryArea(NULL),
-    m_pOStream(NULL),
-    m_pFOStream(NULL) {
+    m_pFdOstream(NULL),
+    m_pFormattedOstream(NULL) {
 
   if (!m_FileHandle.open(pPath, pMode, pPermission)) {
     // If open fails, no clean-up is needed.
     m_Installer.Keep = true;
     fatal(diag::err_cannot_open_output_file)
-                                   << pPath
-                                   << sys::strerror(m_FileHandle.error());
+      << pPath
+      << sys::strerror(m_FileHandle.error());
     return;
   }
-
-  m_pMemoryArea = new MemoryArea(m_FileHandle);
-  m_pOStream = new raw_mem_ostream(*m_pMemoryArea);
 }
 
 ToolOutputFile::~ToolOutputFile()
 {
-  delete m_pFOStream;
-  delete m_pOStream;
-  delete m_pMemoryArea;
+  if (m_pFdOstream != NULL)
+    delete m_pFdOstream;
 }
 
 void ToolOutputFile::keep()
@@ -81,29 +78,24 @@
   m_Installer.Keep = true;
 }
 
-/// mem_os - Return the contained raw_mem_ostream.
-raw_mem_ostream& ToolOutputFile::mem_os()
+/// os - Return the containeed raw_fd_ostream.
+/// Since os is rarely used, we lazily initialize it.
+llvm::raw_fd_ostream& ToolOutputFile::os()
 {
-  assert(NULL != m_pOStream);
-  return *m_pOStream;
+  if (m_pFdOstream == NULL) {
+    assert(m_FileHandle.isOpened() &&
+           m_FileHandle.isGood() &&
+           m_FileHandle.isWritable());
+    m_pFdOstream = new llvm::raw_fd_ostream(m_FileHandle.handler(), false);
+  }
+  return *m_pFdOstream;
 }
 
-/// formatted_os - Return the containeed formatted_raw_ostream.
-/// Since formatted_os is rarely used, we lazily initialize it.
+/// formatted_os - Return the contained formatted_raw_ostream
 llvm::formatted_raw_ostream& ToolOutputFile::formatted_os()
 {
-  if (NULL == m_pFOStream) {
-    assert(NULL != m_pOStream);
-    m_pFOStream = new llvm::formatted_raw_ostream(*m_pOStream);
+  if (m_pFormattedOstream == NULL) {
+    m_pFormattedOstream = new llvm::formatted_raw_ostream(os());
   }
-
-  return *m_pFOStream;
+  return *m_pFormattedOstream;
 }
-
-/// memory - Return the contained MemoryArea.
-MemoryArea& ToolOutputFile::memory()
-{
-  assert(NULL != m_pOStream);
-  return m_pOStream->getMemoryArea();
-}
-
diff --git a/lib/Support/Unix/FileSystem.inc b/lib/Support/Unix/FileSystem.inc
index 7a727e9..811085e 100644
--- a/lib/Support/Unix/FileSystem.inc
+++ b/lib/Support/Unix/FileSystem.inc
@@ -15,6 +15,7 @@
 #include <fcntl.h>
 #include <mcld/Support/FileHandle.h>
 #include <mcld/Support/Directory.h>
+#include <llvm/Support/ErrorHandling.h>
 
 namespace mcld{
 namespace sys{
diff --git a/lib/Support/raw_mem_ostream.cpp b/lib/Support/raw_mem_ostream.cpp
deleted file mode 100644
index c3066dd..0000000
--- a/lib/Support/raw_mem_ostream.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- raw_mem_ostream.cpp ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/raw_mem_ostream.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/FileHandle.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// raw_mem_ostream
-//===----------------------------------------------------------------------===//
-raw_mem_ostream::raw_mem_ostream(MemoryArea &pMemoryArea)
-  : m_MemoryArea(pMemoryArea), m_Position(0) {
-  if (NULL == m_MemoryArea.handler() ||
-      !(m_MemoryArea.handler()->isGood() &&
-        m_MemoryArea.handler()->isWritable())) {
-    fatal(diag::fatal_unwritable_output) << m_MemoryArea.handler()->path();
-  }
-}
-
-raw_mem_ostream::~raw_mem_ostream()
-{
-  flush();
-  m_MemoryArea.clear();
-}
-
-void raw_mem_ostream::write_impl(const char *pPtr, size_t pSize)
-{
-  MemoryRegion* region = m_MemoryArea.request(m_Position, pSize);
-  memcpy(region->start(), pPtr, pSize);
-  m_Position += pSize;
-}
-
-uint64_t raw_mem_ostream::current_pos() const
-{
-  return m_Position;
-}
-
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h
index 53e4795..6fec04e 100644
--- a/lib/Target/ARM/ARM.h
+++ b/lib/Target/ARM/ARM.h
@@ -6,12 +6,17 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_ARM_H
-#define MCLD_ARM_H
+#ifndef MCLD_TARGET_ARM_H
+#define MCLD_TARGET_ARM_H
 #include <string>
-#include <mcld/Target/TargetMachine.h>
+
+namespace llvm {
+class Target;
+} // namespace of llvm
 
 namespace mcld {
+
+class Target;
 class TargetLDBackend;
 
 extern mcld::Target TheARMTarget;
diff --git a/lib/Target/ARM/ARMDiagnostic.cpp b/lib/Target/ARM/ARMDiagnostic.cpp
index b63a192..77cb87e 100644
--- a/lib/Target/ARM/ARMDiagnostic.cpp
+++ b/lib/Target/ARM/ARMDiagnostic.cpp
@@ -6,21 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/ADT/Triple.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/LD/DWARFLineInfo.h>
 #include "ARM.h"
 
 using namespace mcld;
 
-//===----------------------------------------------------------------------===//
-// ARMDiagnostic
-
-
 namespace mcld {
 //===----------------------------------------------------------------------===//
 // createARMDiagnostic - the help function to create corresponding ARMDiagnostic
-//
+//===----------------------------------------------------------------------===//
 DiagnosticLineInfo* createARMDiagLineInfo(const mcld::Target& pTarget,
                                           const std::string &pTriple)
 {
@@ -29,8 +24,9 @@
 
 } // namespace of mcld
 
-//==========================
+//===----------------------------------------------------------------------===//
 // InitializeARMDiagnostic
+//===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeARMDiagnosticLineInfo() {
   // Register the linker frontend
   mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheARMTarget, createARMDiagLineInfo);
diff --git a/lib/Target/ARM/ARMELFAttributeData.cpp b/lib/Target/ARM/ARMELFAttributeData.cpp
new file mode 100644
index 0000000..87ed1d3
--- /dev/null
+++ b/lib/Target/ARM/ARMELFAttributeData.cpp
@@ -0,0 +1,1074 @@
+//===- ARMELFAttributeData.h ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMELFAttributeData.h"
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/Input.h>
+#include <mcld/Support/LEB128.h>
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+const ELFAttributeValue *ARMELFAttributeData::getAttributeValue(TagType pTag) const
+{
+  if (pTag <= Tag_Max) {
+    const ELFAttributeValue &attr_value = m_Attrs[pTag];
+
+    if (attr_value.isInitialized()) {
+      return &attr_value;
+    } else {
+      // Don't return uninitialized attribute value.
+      return NULL;
+    }
+  } else {
+    UnknownAttrsMap::const_iterator attr_it = m_UnknownAttrs.find(pTag);
+
+    if (attr_it == m_UnknownAttrs.end()) {
+      return NULL;
+    } else {
+      return &attr_it->second;
+    }
+  }
+}
+
+std::pair<ELFAttributeValue*, bool>
+ARMELFAttributeData::getOrCreateAttributeValue(TagType pTag)
+{
+  ELFAttributeValue *attr_value = NULL;
+
+  if (pTag <= Tag_Max) {
+    attr_value = &m_Attrs[pTag];
+  } else {
+    // An unknown tag encounterred.
+    attr_value = &m_UnknownAttrs[pTag];
+  }
+
+  assert(attr_value != NULL);
+
+  // Setup the value type.
+  if (!attr_value->isUninitialized()) {
+    return std::make_pair(attr_value, false);
+  } else {
+    attr_value->setType(GetAttributeValueType(pTag));
+    return std::make_pair(attr_value, true);
+  }
+}
+
+unsigned int ARMELFAttributeData::GetAttributeValueType(TagType pTag)
+{
+  // See ARM [ABI-addenda], 2.2.6.
+  switch (pTag) {
+    case Tag_compatibility: {
+      return (ELFAttributeValue::Int | ELFAttributeValue::String);
+    }
+    case Tag_nodefaults: {
+      return (ELFAttributeValue::Int | ELFAttributeValue::NoDefault);
+    }
+    case Tag_CPU_raw_name:
+    case Tag_CPU_name: {
+      return ELFAttributeValue::String;
+    }
+    default: {
+      if (pTag < 32)
+        return ELFAttributeValue::Int;
+      else
+        return ((pTag & 1) ? ELFAttributeValue::String :
+                             ELFAttributeValue::Int);
+    }
+  }
+  // unreachable
+}
+
+//===--------------------------------------------------------------------===//
+// Helper Functions for merge()
+//===--------------------------------------------------------------------===//
+
+namespace {
+
+/*
+ * Helper function to decode value in Tag_also_compatible_with.
+ *
+ * @ref ARM [ABI-addenda], 2.3.7.3
+ */
+static int
+decode_secondary_compatibility_attribute(const ELFAttributeValue &pValue)
+{
+  // The encoding of Tag_also_compatible_with is:
+  //
+  // Tag_also_compatible_with (=65), NTSB: data
+  //
+  // The data can be either an ULEB128-encoded number followed by a NULL byte or
+  // a NULL-terminated string. Currently, only the following byte sequence in
+  // data are currently defined:
+  //
+  // Tag_CPU_arch (=6) [The arch] 0
+  assert((pValue.type() == ELFAttributeValue::String) &&
+         "Value of Tag_also_compatible_with must be a string!");
+
+  const std::string &data = pValue.getStringValue();
+
+  // Though the integer is in LEB128 format, but they occupy only 1 byte in
+  // currently defined value.
+  if (data.length() < 2)
+    // Must have a byte for Tag_CPU_arch (=6)
+    //           a byte for specifying the CPU architecture (CPU_Arch_ARM_*)
+    //
+    // Currently, the 2nd byte can only be v4T (=2) or v6-M (=11).
+    return -1;
+
+  if ((static_cast<uint8_t>(data[0]) == ARMELFAttributeData::Tag_CPU_arch) &&
+      ((data[1] == ARMELFAttributeData::CPU_Arch_ARM_V4T) ||
+       (data[1] == ARMELFAttributeData::CPU_Arch_ARM_V6_M)))
+    return static_cast<uint32_t>(data[1]);
+
+  // Tag_also_compatible_with can be safely ignored.
+  return -1;
+}
+
+/*
+ * This helper array keeps the ordering of the values in attributes such as
+ * Tag_ABI_align_needed which are sored as 1 > 2 > 0.
+ */
+static const int value_ordering_120[] = { 0, 2, 1 };
+
+} // anonymous namespace
+
+//===--------------------------------------------------------------------===//
+// End Helper Functions for merge()
+//===--------------------------------------------------------------------===//
+
+bool ARMELFAttributeData::merge(const LinkerConfig& pConfig,
+                                const Input &pInput, TagType pTag,
+                                const ELFAttributeValue& pInAttr)
+{
+  // Pre-condition
+  //  1. The out_attr must be initailized and has value of the same type as
+  //     pInAttr.
+  //  2. The value helf by out_attr and pInAttr must be different.
+  ELFAttributeValue &out_attr = m_Attrs[pTag];
+
+  // Attribute in the output must have value assigned.
+  assert(out_attr.isInitialized() && "No output attribute to be merged!");
+
+  switch (pTag) {
+    case Tag_CPU_arch: {
+      // Need value of Tag_also_compatible_with in the input for merge.
+      if (pInAttr.getIntValue() <= CPU_Arch_Max) {
+        m_CPUArch = pInAttr.getIntValue();
+      } else {
+        error(diag::error_unknown_cpu_arch) << pInput.name();
+        return false;
+      }
+      break;
+    }
+    case Tag_CPU_name: {
+      // need value of Tag_CPU_arch in the input for merge
+      m_CPUName = pInAttr.getStringValue();
+      break;
+    }
+    case Tag_CPU_raw_name: {
+      // need value of Tag_CPU_arch in the input for merge
+      m_CPURawName = pInAttr.getStringValue();
+      break;
+    }
+    case Tag_FP_arch: {
+      // need value of Tag_HardFP_use in the input for merge
+      m_FPArch = pInAttr.getIntValue();
+      break;
+    }
+    case Tag_ABI_HardFP_use: {
+      // need value of Tag_FP_arch in the input for merge
+      m_HardFPUse = pInAttr.getIntValue();
+      break;
+    }
+    case Tag_also_compatible_with: {
+      // need value of Tag_CPU_arch in the input for merge
+      m_SecondaryCPUArch = decode_secondary_compatibility_attribute(pInAttr);
+      break;
+    }
+    case Tag_ABI_VFP_args: {
+      // need value of Tag_ABI_FP_number_model in the input for merge
+      m_VFPArgs = pInAttr.getIntValue();
+      break;
+    }
+    // The value of these tags are integers and after merge, only the greatest
+    // value held by pInAttr and out_attr goes into output.
+    case Tag_ARM_ISA_use:
+    case Tag_THUMB_ISA_use:
+    case Tag_WMMX_arch:
+    case Tag_Advanced_SIMD_arch:
+    case Tag_ABI_FP_rounding:
+    case Tag_ABI_FP_exceptions:
+    case Tag_ABI_FP_user_exceptions:
+    case Tag_ABI_FP_number_model:
+    case Tag_FP_HP_extension:
+    case Tag_CPU_unaligned_access:
+    case Tag_T2EE_use: {
+      assert((out_attr.type() == ELFAttributeValue::Int) &&
+             (pInAttr.type() == ELFAttributeValue::Int) &&
+              "should have integer parameeter!");
+      if (pInAttr.getIntValue() > out_attr.getIntValue())
+        out_attr.setIntValue(pInAttr.getIntValue());
+      break;
+    }
+    // The value of these tags are integers and after merge, only the smallest
+    // value held by pInAttr and out_attr goes into output.
+    case Tag_ABI_align_preserved:
+    case Tag_ABI_PCS_RO_data: {
+      assert((out_attr.type() == ELFAttributeValue::Int) &&
+             (pInAttr.type() == ELFAttributeValue::Int) &&
+              "should have integer parameeter!");
+      if (pInAttr.getIntValue() < out_attr.getIntValue())
+        out_attr.setIntValue(pInAttr.getIntValue());
+      break;
+    }
+    // The values of these attributes are sorted as 1 > 2 > 0. And the greater
+    // value becomes output.
+    case Tag_ABI_align_needed:
+    case Tag_ABI_FP_denormal:
+    case Tag_ABI_PCS_GOT_use: {
+      const int in_val = pInAttr.getIntValue();
+      const int out_val = out_attr.getIntValue();
+
+      if (in_val <= 2) {
+        if (out_val <= 2) {
+          // Use value_ordering_120 to determine the ordering.
+          if (value_ordering_120[in_val] > value_ordering_120[out_val]) {
+            out_attr.setIntValue(in_val);
+          }
+        }
+      } else {
+        // input value > 2, for future-proofing
+        if (in_val > out_val) {
+          out_attr.setIntValue(in_val);
+        }
+      }
+      break;
+    }
+    // These tags use the first value ever seen.
+    case Tag_ABI_optimization_goals:
+    case Tag_ABI_FP_optimization_goals: {
+      break;
+    }
+    // Tag_CPU_arch_profile
+    case Tag_CPU_arch_profile: {
+      if (pInAttr.getIntValue() == Arch_Profile_None)
+        return true;
+
+      switch (out_attr.getIntValue()) {
+        case Arch_Profile_None: {
+          out_attr.setIntValue(pInAttr.getIntValue());
+          break;
+        }
+        case Arch_Profile_RealOrApp: {
+          if (pInAttr.getIntValue() != Arch_Profile_Microcontroller)
+            out_attr.setIntValue(pInAttr.getIntValue());
+          else
+            warning(diag::warn_mismatch_cpu_arch_profile)
+                << pInAttr.getIntValue() << pInput.name();
+          break;
+        }
+        default: {
+          // out_attr is Arch_Profile_Application or Arch_Profile_Realtime or
+          // Arch_Profile_Microcontroller.
+          if ((pInAttr.getIntValue() == Arch_Profile_RealOrApp) &&
+              (out_attr.getIntValue() != Arch_Profile_Microcontroller)) {
+            // do nothing
+          } else {
+            if (pConfig.options().warnMismatch())
+              warning(diag::warn_mismatch_cpu_arch_profile)
+                  << pInAttr.getIntValue() << pInput.name();
+          }
+          break;
+        }
+      }
+      break;
+    }
+    // Tag_MPextension_use and Tag_MPextension_use_legacy
+    case Tag_MPextension_use:
+    case Tag_MPextension_use_legacy: {
+      if (m_MPextensionUse < 0) {
+        m_MPextensionUse = pInAttr.getIntValue();
+      } else {
+        if (static_cast<unsigned>(m_MPextensionUse) != pInAttr.getIntValue()) {
+          warning(diag::error_mismatch_mpextension_use) << pInput.name();
+        }
+      }
+      break;
+    }
+    // Tag_DIV_use
+    case Tag_DIV_use: {
+      if (pInAttr.getIntValue() == 2) {
+        // 2 means the code was permitted to use SDIV/UDIV in anyway.
+        out_attr.setIntValue(2);
+      } else {
+        // Merge until settling down Tag_CPU_arch.
+        m_DIVUse = pInAttr.getIntValue();
+      }
+      break;
+    }
+    // Tag_ABI_enum_size
+    case Tag_ABI_enum_size: {
+      if ((out_attr.getIntValue() == Enum_Unused) ||
+          (out_attr.getIntValue() == Enum_Containerized_As_Possible))
+        out_attr.setIntValue(pInAttr.getIntValue());
+      else if (pInAttr.getIntValue() != Enum_Containerized_As_Possible &&
+               pConfig.options().warnMismatch())
+        warning(diag::warn_mismatch_enum_size)
+            << pInput.name() << pInAttr.getIntValue()
+            << out_attr.getIntValue();
+      break;
+    }
+    // Tag_ABI_FP_16bit_format
+    case Tag_ABI_FP_16bit_format: {
+      // 0: doesn't use any 16-bit FP number
+      // 1: use IEEE 754 format 16-bit FP number
+      // 2: use VFPv3/Advanced SIMD "alternative format" 16-bit FP number
+      if (pInAttr.getIntValue() != 0) {
+        if (out_attr.getIntValue() == 0) {
+          out_attr.setIntValue(pInAttr.getIntValue());
+        } else {
+          if (pConfig.options().warnMismatch())
+            warning(diag::warn_mismatch_fp16_format) << pInput.name();
+        }
+      }
+      break;
+    }
+    // Tag_nodefaults
+    case Tag_nodefaults: {
+      // There's nothing to do for this tag. It doesn't have an actual value.
+      break;
+    }
+    // Tag_conformance
+    case Tag_conformance: {
+      // Throw away the value if the attribute value doesn't match.
+      if (out_attr.getStringValue() != pInAttr.getStringValue())
+        out_attr.setStringValue("");
+      break;
+    }
+    // Tag_Virtualization_use
+    case Tag_Virtualization_use: {
+      // 0: No use of any virtualization extension
+      // 1: TrustZone
+      // 2: Virtualization extension such as HVC and ERET
+      // 3: TrustZone and virtualization extension are permitted
+      if (pInAttr.getIntValue() != 0) {
+        if (out_attr.getIntValue() == 0) {
+          out_attr.setIntValue(pInAttr.getIntValue());
+        } else {
+          if ((out_attr.getIntValue() <= 3) && (pInAttr.getIntValue() <= 3)) {
+            // Promote to 3
+            out_attr.setIntValue(3);
+          } else {
+            warning(diag::warn_unrecognized_virtualization_use)
+                << pInput.name() << pInAttr.getIntValue();
+          }
+        }
+      }
+      break;
+    }
+    // Tag_ABI_WMMX_args
+    case Tag_ABI_WMMX_args: {
+      // There's no way to merge this value (i.e., objects contain different
+      // value in this tag are definitely incompatible.)
+      if (pConfig.options().warnMismatch())
+        warning(diag::warn_mismatch_abi_wmmx_args) << pInput.name();
+      break;
+    }
+    // Tag_PCS_config
+    case Tag_PCS_config: {
+      // 0 means no standard configuration used or no information recorded.
+      if (pInAttr.getIntValue() != 0) {
+        if (out_attr.getIntValue() == 0)
+          out_attr.setIntValue(pInAttr.getIntValue());
+        else {
+          // Different values in these attribute are conflict
+          if (pConfig.options().warnMismatch())
+            warning(diag::warn_mismatch_pcs_config) << pInput.name();
+        }
+      }
+      break;
+    }
+    // Tag_ABI_PCS_R9_use
+    case Tag_ABI_PCS_R9_use: {
+      if (pInAttr.getIntValue() != R9_Unused) {
+        if (out_attr.getIntValue() == R9_Unused)
+          out_attr.setIntValue(pInAttr.getIntValue());
+        else {
+          if (pConfig.options().warnMismatch())
+            warning(diag::warn_mismatch_r9_use) << pInput.name();
+        }
+      }
+      break;
+    }
+    // Tag_ABI_PCS_RW_data
+    case Tag_ABI_PCS_RW_data: {
+      if (pInAttr.getIntValue() == RW_data_SB_Relative) {
+        // Require using R9 as SB (global Static Base register).
+        if ((out_attr.getIntValue() != R9_Unused) &&
+            (out_attr.getIntValue() != R9_SB) &&
+            pConfig.options().warnMismatch())
+          warning(diag::warn_mismatch_r9_use) << pInput.name();
+      }
+      // Choose the smaller value
+      if (pInAttr.getIntValue() < out_attr.getIntValue())
+        out_attr.setIntValue(pInAttr.getIntValue());
+      break;
+    }
+    // Tag_ABI_PCS_wchar_t
+    case Tag_ABI_PCS_wchar_t: {
+      // 0: no use of wchar_t
+      // 2: sizeof(wchar_t) = 2
+      // 4: sizeof(wchar_t) = 4
+      if (pInAttr.getIntValue() != 0) {
+        if (out_attr.getIntValue() == 0)
+          out_attr.setIntValue(pInAttr.getIntValue());
+        else {
+          if (pConfig.options().warnMismatch())
+            warning(diag::warn_mismatch_wchar_size)
+                << pInput.name() << pInAttr.getIntValue()
+                << out_attr.getIntValue();
+        }
+      }
+      break;
+    }
+    default: {
+      // Handle unknown attributes:
+      //
+      // Since we don't know how to merge the value of unknown attribute, we
+      // have to ignore it. There're two rules related to the processing (See
+      // ARM [ABI-addenda] 2.2.6, Coding extensibility and compatibility.):
+      //
+      // 1. For tag N where N >= 128, tag N has the same properties as
+      //    tag N % 128.
+      // 2. Tag 64-127 can be safely ignored.
+      // 3. Tag 0-63 must be comprehended, therefore we cannot ignore.
+      if (pConfig.options().warnMismatch()) {
+        if ((pTag & 127) < 64) {
+          warning(diag::warn_unknown_mandatory_attribute) << pTag
+                                                          << pInput.name();
+        } else {
+          warning(diag::warn_unknown_attribute) << pTag << pInput.name();
+        }
+      }
+      break;
+    }
+  }
+  return true;
+}
+
+//===--------------------------------------------------------------------===//
+// Helper Functions for postMerge()
+//===--------------------------------------------------------------------===//
+
+namespace {
+
+/*
+ * Helper function to encode value in Tag_also_compatible_with.
+ *
+ * @ref ARM [ABI-addenda], 2.3.7.3
+ */
+static void
+encode_secondary_compatibility_attribute(ELFAttributeValue &pValue, int pArch)
+{
+  if ((pArch < 0) || (pArch > ARMELFAttributeData::CPU_Arch_Max)) {
+    pValue.setStringValue("");
+  } else {
+    char new_value[] = {
+        ARMELFAttributeData::Tag_CPU_arch,
+        static_cast<char>(pArch),
+        0
+    };
+    pValue.setStringValue(std::string(new_value, sizeof(new_value)));
+  }
+  return;
+}
+
+/*
+ * Combine the main and secondary CPU arch value
+ */
+static int
+calculate_cpu_arch(int cpu_arch, int secondary_arch)
+{
+  // short-circuit
+  if ((secondary_arch < 0) ||
+      ((cpu_arch + secondary_arch) != (ARMELFAttributeData::CPU_Arch_ARM_V4T +
+                                       ARMELFAttributeData::CPU_Arch_ARM_V6_M)))
+    return cpu_arch;
+
+  if ((cpu_arch == ARMELFAttributeData::CPU_Arch_ARM_V4T) &&
+      (secondary_arch == ARMELFAttributeData::CPU_Arch_ARM_V6_M))
+    return ARMELFAttributeData::CPU_Arch_ARM_V4T_Plus_V6_M;
+  else if ((cpu_arch == ARMELFAttributeData::CPU_Arch_ARM_V6_M) &&
+           (secondary_arch == ARMELFAttributeData::CPU_Arch_ARM_V4T))
+    return ARMELFAttributeData::CPU_Arch_ARM_V4T_Plus_V6_M;
+  else
+    return cpu_arch;
+}
+
+/*
+ * Given a CPU arch X and a CPU arch Y in which Y is newer than X, the value in
+ * cpu_compatibility_table[X][Y] is the CPU arch required to run ISA both from X
+ * and Y. 0 in the table means unreachable and -1 means conflict architecture
+ * profile.
+ */
+#define CPU(C)  ARMELFAttributeData::CPU_Arch_ARM_ ## C
+static const int cpu_compatibility_table[][CPU(V4T_Plus_V6_M) + 1] =
+{
+  /* old\new          ARM v6T2    ARM v6K   ARM v7   ARM v6-M   ARM v6S-M   ARM v7E-M    ARMv8, ARM v4t + v6-M     */
+  /* Pre v4     */ { CPU(V6T2),  CPU(V6K), CPU(V7),        -1,         -1,         -1,      -1,       -1           },
+  /* ARM v4     */ { CPU(V6T2),  CPU(V6K), CPU(V7),        -1,         -1,         -1,      -1,       -1           },
+  /* ARM v4T    */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V4T)           },
+  /* ARM v5T    */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V5T)           },
+  /* ARM v5TE   */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V5TE)          },
+  /* ARM v5TEJ  */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V5TEJ)         },
+  /* ARM v6     */ { CPU(V6T2),  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V6)            },
+  /* ARM v6KZ   */ {   CPU(V7), CPU(V6KZ), CPU(V7), CPU(V6KZ),  CPU(V6KZ), CPU(V7E_M), CPU(V8), CPU(V6KZ)          },
+  /* ARM v6T2   */ { CPU(V6T2),   CPU(V7), CPU(V7),   CPU(V7),    CPU(V7), CPU(V7E_M), CPU(V8), CPU(V6T2)          },
+  /* ARM v6K    */ {         0,  CPU(V6K), CPU(V7),  CPU(V6K),   CPU(V6K), CPU(V7E_M), CPU(V8), CPU(V6K)           },
+  /* ARM v7     */ {         0,         0, CPU(V7),   CPU(V7),    CPU(V7), CPU(V7E_M), CPU(V8), CPU(V7)            },
+  /* ARM v6-M   */ {         0,         0,       0, CPU(V6_M), CPU(V6S_M), CPU(V7E_M), CPU(V8), CPU(V6_M)          },
+  /* ARM v6S-M  */ {         0,         0,       0,         0, CPU(V6S_M), CPU(V7E_M), CPU(V8), CPU(V6S_M)         },
+  /* ARM v7E-M  */ {         0,         0,       0,         0,          0, CPU(V7E_M), CPU(V8), CPU(V7E_M)         },
+  /* ARM v8     */ {         0,         0,       0,         0,          0,          0, CPU(V8), CPU(V8)            },
+  /* v4T + v6-M */ {         0,         0,       0,         0,          0,          0,       0, CPU(V4T_Plus_V6_M) }
+};
+
+/*
+ * Helper function to determine the merge of two different CPU arch.
+ */
+static int merge_cpu_arch(int out_cpu_arch, int in_cpu_arch)
+{
+  if (out_cpu_arch > CPU(V4T_Plus_V6_M))
+    return in_cpu_arch;
+
+  int new_cpu_arch, old_cpu_arch;
+  if (out_cpu_arch > in_cpu_arch) {
+    new_cpu_arch = out_cpu_arch;
+    old_cpu_arch = in_cpu_arch;
+  } else {
+    new_cpu_arch = in_cpu_arch;
+    old_cpu_arch = out_cpu_arch;
+  }
+
+  // No need to check the compatibility since the CPU architectures before
+  // V6KZ add features monotonically.
+  if (new_cpu_arch <= CPU(V6KZ))
+    return new_cpu_arch;
+
+  return cpu_compatibility_table[old_cpu_arch][new_cpu_arch - CPU(V6T2)];
+}
+#undef CPU
+
+/*
+ * Generic CPU name is used when Tag_CPU_name is unable to guess during the
+ * merge of Tag_CPU_arch.
+ */
+static const char* generic_cpu_name_table[] = {
+  /* Pre v4    */"Pre v4",
+  /* Pre v4    */"ARM v4",
+  /* ARM v4T   */"ARM v4T",
+  /* ARM v5T   */"ARM v5T",
+  /* ARM v5TE  */"ARM v5TE",
+  /* ARM v5TEJ */"ARM v5TEJ",
+  /* ARM v6    */"ARM v6",
+  /* ARM v6KZ  */"ARM v6KZ",
+  /* ARM v6T2  */"ARM v6T2",
+  /* ARM v6K   */"ARM v6K",
+  /* ARM v7    */"ARM v7",
+  /* ARM v6-M  */"ARM v6-M",
+  /* ARM v6S-M */"ARM v6S-M",
+  /* ARM v7E-M */"ARM v7E-M",
+  /* ARM v8    */"ARM v8",
+};
+
+static const char* get_generic_cpu_name(int cpu_arch) {
+  assert(cpu_arch < sizeof(generic_cpu_name_table) / sizeof(generic_cpu_name_table[0]));
+  return generic_cpu_name_table[cpu_arch];
+}
+
+/*
+ * Helper functions & data used in the merge of two different FP arch.
+ */
+static const struct fp_config_data {
+  int version;
+  int regs;
+} fp_configs[] = {
+  { 0, 0  },
+  { 1, 16 },
+  { 2, 16 },
+  { 3, 32 },
+  { 3, 16 },
+  { 4, 32 },
+  { 4, 16 },
+  { 8, 32 },
+  { 8, 16 },
+};
+
+static const size_t num_fp_configs =
+    sizeof(fp_configs) / sizeof(fp_config_data);
+
+// Given h(x, y) = (x * (y >> 4) + (y >> 5))
+//
+// fp_config_hash_table[ h(0, 0)  =  0 ] = 0
+// fp_config_hash_table[ h(1, 16) =  1 ] = 1
+// fp_config_hash_table[ h(2, 16) =  2 ] = 2
+// fp_config_hash_table[ h(3, 32) =  7 ] = 3
+// fp_config_hash_table[ h(3, 16) =  3 ] = 4
+// fp_config_hash_table[ h(4, 32) =  9 ] = 5
+// fp_config_hash_table[ h(4, 16) =  4 ] = 6
+// fp_config_hash_table[ h(8, 32) = 17 ] = 7
+// fp_config_hash_table[ h(8, 16) =  8 ] = 8
+//
+// h(0, 0) = 0
+static const uint8_t fp_config_hash_table[] =
+{
+#define UND static_cast<uint8_t>(-1)
+  /*  0 */0,
+  /*  1 */1,
+  /*  2 */2,
+  /*  3 */4,
+  /*  4 */6,
+  /*  5 */UND,
+  /*  6 */UND,
+  /*  7 */3,
+  /*  8 */8,
+  /*  9 */5,
+  /* 10 */UND,
+  /* 11 */UND,
+  /* 12 */UND,
+  /* 13 */UND,
+  /* 14 */UND,
+  /* 15 */UND,
+  /* 16 */UND,
+  /* 17 */7,
+#undef UND
+};
+
+static const size_t num_hash_table_entries =
+    sizeof(fp_config_hash_table) / sizeof(fp_config_hash_table[0]);
+
+static int calculate_fp_config_hash(const struct fp_config_data &pConfig)
+{
+  int x = pConfig.version;
+  int y = pConfig.regs;
+  return (x * (y >> 4) + (y >> 5));
+}
+
+static int get_fp_arch_of_config(const struct fp_config_data &pConfig)
+{
+  int hash = calculate_fp_config_hash(pConfig);
+  assert(hash < num_hash_table_entries);
+  return fp_config_hash_table[hash];
+}
+
+static bool is_allowed_use_of_div(int cpu_arch, int cpu_arch_profile,
+                                  int div_use) {
+  // 0: The code was permitted to use SDIV and UDIV in the Thumb ISA on v7-R or
+  //    v7-M.
+  // 1: The code was not permitted to use SDIV and UDIV.
+  // 2: The code was explicitly permitted to use SDIV and UDIV.
+  switch (div_use) {
+    case 0: {
+      if ((cpu_arch == ARMELFAttributeData::CPU_Arch_ARM_V7) &&
+          ((cpu_arch_profile == 'R') || (cpu_arch_profile == 'M'))) {
+        return true;
+      } else {
+        return (cpu_arch >= ARMELFAttributeData::CPU_Arch_ARM_V7E_M);
+      }
+    }
+    case 1: {
+      return false;
+    }
+    case 2:
+    // For future proofing
+    default: {
+      return true;
+    }
+  }
+}
+
+} // anonymous namespace
+
+//===--------------------------------------------------------------------===//
+// End Helper Functions for postMerge()
+//===--------------------------------------------------------------------===//
+
+bool ARMELFAttributeData::postMerge(const LinkerConfig& pConfig,
+                                    const Input &pInput)
+{
+  // Process Tag_CPU_arch, Tag_CPU_name, Tag_CPU_raw_name, and
+  // Tag_also_compatible_with.
+  ELFAttributeValue &out_cpu_arch_attr = m_Attrs[Tag_CPU_arch];
+  ELFAttributeValue &out_secondary_compatibility_attr =
+      m_Attrs[Tag_also_compatible_with];
+
+  if ((m_CurrentCPUArch < 0) && out_cpu_arch_attr.isInitialized()) {
+    // Current input initializes the value of Tag_CPU_arch. Validate it.
+    int out_cpu_arch = out_cpu_arch_attr.getIntValue();
+
+    if (out_cpu_arch > CPU_Arch_Max) {
+      error(diag::error_unknown_cpu_arch) << pInput.name();
+      return false;
+    }
+
+    // Initialize m_CurrentCPUArch.
+    int out_secondary_arch = -1;
+    if (out_secondary_compatibility_attr.isInitialized())
+      out_secondary_arch = decode_secondary_compatibility_attribute(
+                              out_secondary_compatibility_attr);
+
+    m_CurrentCPUArch = calculate_cpu_arch(out_cpu_arch, out_secondary_arch);
+  }
+
+  if (m_CPUArch >= 0) {
+    assert(out_cpu_arch_attr.isInitialized() && "CPU arch has never set!");
+    assert(m_CurrentCPUArch >= 0);
+
+    int in_cpu_arch = calculate_cpu_arch(m_CPUArch, m_SecondaryCPUArch);
+    int result_cpu_arch = merge_cpu_arch(m_CurrentCPUArch, in_cpu_arch);
+
+    if (result_cpu_arch < 0) {
+      warning(diag::warn_mismatch_cpu_arch_profile)
+          << in_cpu_arch << pInput.name();
+    } else {
+      if (result_cpu_arch != m_CurrentCPUArch) {
+        // Value of Tag_CPU_arch are going to changea.
+        m_CurrentCPUArch = result_cpu_arch;
+
+        // Write the result value to the output.
+        if (result_cpu_arch == CPU_Arch_ARM_V4T_Plus_V6_M) {
+          out_cpu_arch_attr.setIntValue(CPU_Arch_ARM_V4T);
+          encode_secondary_compatibility_attribute(
+              out_secondary_compatibility_attr, CPU_Arch_ARM_V6_M);
+        } else {
+          out_cpu_arch_attr.setIntValue(result_cpu_arch);
+          encode_secondary_compatibility_attribute(
+              out_secondary_compatibility_attr, -1);
+        }
+
+        ELFAttributeValue &out_cpu_name = m_Attrs[Tag_CPU_name];
+        ELFAttributeValue &out_cpu_raw_name = m_Attrs[Tag_CPU_raw_name];
+
+        if (m_CurrentCPUArch != in_cpu_arch) {
+          // Unable to guess the Tag_CPU_name. Use the generic name.
+          if (out_cpu_name.isInitialized()) {
+            out_cpu_name.setStringValue(get_generic_cpu_name(m_CurrentCPUArch));
+          }
+
+          // Tag_CPU_raw_name becomes unknown. Set to default value to disable
+          // it.
+          out_cpu_raw_name.setStringValue("");
+        } else {
+          // Use the value of Tag_CPU_name and Tag_CPU_raw_name from the input.
+          if (!m_CPUName.empty()) {
+            ELFAttributeValue &out_cpu_name = m_Attrs[Tag_CPU_name];
+            assert(out_cpu_name.isInitialized() && "CPU name has never set!");
+            out_cpu_name.setStringValue(m_CPUName);
+          }
+
+          if (!m_CPURawName.empty()) {
+            ELFAttributeValue &out_cpu_raw_name = m_Attrs[Tag_CPU_raw_name];
+            assert(out_cpu_raw_name.isInitialized() &&
+                   "CPU raw name has never set!");
+            out_cpu_raw_name.setStringValue(m_CPURawName);
+          }
+        }
+      }
+    }
+  } // (m_CPUArch >= 0)
+
+  // Process Tag_ABI_VFP_args.
+  if (m_VFPArgs >= 0) {
+    ELFAttributeValue &out_attr = m_Attrs[Tag_ABI_VFP_args];
+    ELFAttributeValue &out_float_number_model_attr =
+        m_Attrs[Tag_ABI_FP_number_model];
+
+    assert(out_attr.isInitialized() && "VFP args has never set!");
+
+    // If the output is not permitted to use floating number, this attribute
+    // is ignored (migrate the value from input directly.)
+    if (out_float_number_model_attr.isUninitialized() ||
+        (out_float_number_model_attr.getIntValue() == 0)) {
+      // Inherit requirement from input.
+      out_attr.setIntValue(m_VFPArgs);
+    } else {
+      if (pConfig.options().warnMismatch())
+        warning(diag::warn_mismatch_vfp_args) << pInput.name();
+    }
+  }
+
+  // Process Tag_FP_arch.
+  ELFAttributeValue &out_fp_arch_attr = m_Attrs[Tag_FP_arch];
+  if (m_FPArch >= 0) {
+    assert(out_fp_arch_attr.isInitialized() && "FP arch has never set!");
+
+    // Tag_FP_arch
+    //  0: instructions requiring FP hardware are not permitted
+    //  1: VFP1
+    //  2: VFP2
+    //  3: VFP3 D32
+    //  4: VFP3 D16
+    //  5: VFP4 D32
+    //  6: VFP4 D16
+    //  7: ARM v8-A D32
+    //  8: ARM v8-A D16
+    if (out_fp_arch_attr.getIntValue() == 0) {
+      // Output has no constraints on FP hardware. Copy the requirement from
+      // input.
+      out_fp_arch_attr.setIntValue(m_FPArch);
+    } else if (m_FPArch == 0) {
+      // Input has no constraints on FP hardware. Do nothing.
+    } else {
+      // If here, both output and input contain non-zero value of Tag_FP_arch.
+
+      // Version greater than num_fp_configs is not defined. Choose the greater
+      // one for future-proofing.
+      if (static_cast<unsigned>(m_FPArch) > num_fp_configs) {
+        if (static_cast<unsigned>(m_FPArch) > out_fp_arch_attr.getIntValue()) {
+          out_fp_arch_attr.setIntValue(m_FPArch);
+        }
+      } else {
+        if (out_fp_arch_attr.getIntValue() < num_fp_configs) {
+          const struct fp_config_data &input_fp_config = fp_configs[ m_FPArch ];
+
+          const struct fp_config_data &output_fp_config =
+              fp_configs[ out_fp_arch_attr.getIntValue() ];
+
+          const struct fp_config_data result_fp_config = {
+            /*version*/((output_fp_config.version > input_fp_config.version) ?
+                         output_fp_config.version : input_fp_config.version),
+            /* regs */((output_fp_config.regs > input_fp_config.regs) ?
+                        output_fp_config.regs : input_fp_config.regs),
+          };
+          // Find the attribute value corresponding the result_fp_config
+          out_fp_arch_attr.setIntValue(get_fp_arch_of_config(result_fp_config));
+        }
+      }
+    }
+  } // (m_FPArch >= 0)
+
+  // Process Tag_ABI_HardFP_use.
+  ELFAttributeValue &out_hardfp_use_attr = m_Attrs[Tag_ABI_HardFP_use];
+
+  if (!m_HardFPUseInitialized && out_hardfp_use_attr.isInitialized()) {
+    m_HardFPUse = out_hardfp_use_attr.getIntValue();
+    m_HardFPUseInitialized = true;
+  }
+
+  if (m_HardFPUse >= 0) {
+    // Tag_ABI_HardFP_use depends on the meaning of Tag_FP_arch when it's 0.
+    assert(out_hardfp_use_attr.isInitialized() && "HardFP use has never set!");
+
+    if (out_fp_arch_attr.isUninitialized() ||
+        (out_fp_arch_attr.getIntValue() == 0)) {
+      // Has no constraints on FP hardware.
+      out_hardfp_use_attr.setIntValue(m_HardFPUse);
+    } else {
+      // Both output and input contain non-zero value of Tag_FP_arch and we have
+      // different Tag_ABI_HaedFP_Use settings other than 0.
+      if ((out_fp_arch_attr.getIntValue() > 0) && (m_HardFPUse > 0))
+        // Promote to 3 (The user permitted this entity to use both SP and DP
+        // VFP instruction.)
+        out_hardfp_use_attr.setIntValue(3);
+    }
+  }
+
+  // Move the value of Tag_MPextension_use_legacy to Tag_MPextension_use.
+  ELFAttributeValue &out_mpextension_use_legacy =
+      m_Attrs[Tag_MPextension_use_legacy];
+
+  ELFAttributeValue &out_mpextension_use = m_Attrs[Tag_MPextension_use];
+
+  // If Tag_MPextension_use_legacy has value, it must be introduced by current
+  // input since it is reset every time after the merge completed.
+  if (out_mpextension_use_legacy.isInitialized()) {
+    if (out_mpextension_use.isInitialized()) {
+      if (m_MPextensionUse < 0) {
+        // The value of Tag_MPextension_use is introduced by the current input.
+        // Check whether it is consistent with the one set in legacy.
+        m_MPextensionUse = out_mpextension_use.getIntValue();
+      } else {
+        // Current input introduces value of Tag_MPextension_use in
+        // m_MPextensionUse.
+      }
+
+      // Check the consistency between m_MPextensionUse and the value of
+      // Tag_MPextension_use_legacy.
+      if (static_cast<unsigned>(m_MPextensionUse) !=
+              out_mpextension_use_legacy.getIntValue()) {
+        error(diag::error_mismatch_mpextension_use) << pInput.name();
+        return false;
+      }
+    } else {
+      if (m_MPextensionUse < 0) {
+        // Tag_MPextension_use is not set. Initialize it and move the value.
+        out_mpextension_use.setType(ELFAttributeValue::Int);
+        out_mpextension_use.setIntValue(out_mpextension_use.getIntValue());
+      } else {
+        // Unreachable case since the value to unitialized attribute is directly
+        // assigned in ELFAttribute::Subsection::merge().
+        assert(false && "Tag_MPextension_use is uninitialized but have value?");
+      }
+    }
+
+    // Reset the attribute to uninitialized so it won't be included in the
+    // output.
+    out_mpextension_use_legacy.setType(ELFAttributeValue::Uninitialized);
+  }
+
+  // Process Tag_MPextension_use.
+  if (m_MPextensionUse > 0) {
+    assert(out_mpextension_use.isInitialized());
+
+    if (static_cast<unsigned>(m_MPextensionUse) >
+            out_mpextension_use.getIntValue()) {
+      out_mpextension_use.setIntValue(m_MPextensionUse);
+    }
+  }
+
+  // Process Tag_DIV_use.
+  ELFAttributeValue &out_div_use_attr = m_Attrs[Tag_DIV_use];
+
+  if (!m_DIVUseInitialized && out_div_use_attr.isInitialized()) {
+    // Perform the merge by reverting value of Tag_DIV_use and setup m_DIVUse.
+    m_DIVUse = out_div_use_attr.getIntValue();
+    out_div_use_attr.setIntValue(0);
+    m_DIVUseInitialized = true;
+  }
+
+  if (m_DIVUse >= 0) {
+    assert(out_div_use_attr.isInitialized());
+
+    const ELFAttributeValue &out_cpu_arch_profile_attr =
+        m_Attrs[Tag_CPU_arch_profile];
+
+    int out_cpu_arch_profile = Arch_Profile_None;
+    if (out_cpu_arch_profile_attr.isInitialized()) {
+      out_cpu_arch_profile = out_cpu_arch_profile_attr.getIntValue();
+    }
+
+    if (m_DIVUse == 1) {
+      // Input (=1) was not permitted to use SDIV and UDIV. See whether current
+      // output was explicitly permitted the use.
+      if (!is_allowed_use_of_div(m_CurrentCPUArch, out_cpu_arch_profile,
+                                 out_div_use_attr.getIntValue())) {
+        out_div_use_attr.setIntValue(1);
+      }
+    } else {
+      if (out_div_use_attr.getIntValue() != 1) {
+        // Output does not explicitly forbid the use of SDIV/UDIV. See whether
+        // the input attribute can allow it under current CPU architecture
+        // profile.
+        if (is_allowed_use_of_div(m_CurrentCPUArch, out_cpu_arch_profile,
+                                  m_DIVUse)) {
+          out_div_use_attr.setIntValue(m_DIVUse);
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+size_t ARMELFAttributeData::sizeOutput() const {
+  size_t result = 0;
+
+  // Size contributed by known attributes
+  for (unsigned i = 0; i <= Tag_Max; ++i) {
+    TagType tag = static_cast<TagType>(i);
+    const ELFAttributeValue &value = m_Attrs[tag];
+
+    if (value.shouldEmit()) {
+      result += leb128::size(static_cast<uint32_t>(tag));
+      result += value.getSize();
+    }
+  }
+
+  // Size contributed by unknown attributes
+  for (UnknownAttrsMap::const_iterator unknown_attr_it = m_UnknownAttrs.begin(),
+          unknown_attr_end = m_UnknownAttrs.end();
+       unknown_attr_it != unknown_attr_end; ++unknown_attr_it) {
+    TagType tag = unknown_attr_it->first;
+    const ELFAttributeValue &value = unknown_attr_it->second;
+
+    if (value.shouldEmit()) {
+      result += leb128::size(static_cast<uint32_t>(tag));
+      result += value.getSize();
+    }
+  }
+
+  return result;
+}
+
+size_t ARMELFAttributeData::emit(char *pBuf) const {
+  char *buffer = pBuf;
+
+  // Tag_conformance "should be emitted first in a file-scope sub-subsection of
+  // the first public subsection of the attribute section."
+  //
+  // See ARM [ABI-addenda], 2.3.7.4 Conformance tag
+  const ELFAttributeValue &attr_conformance = m_Attrs[Tag_conformance];
+
+  if (attr_conformance.shouldEmit()) {
+    if (!ELFAttributeData::WriteAttribute(Tag_conformance,  attr_conformance,
+                                          buffer)) {
+      return 0;
+    }
+  }
+
+  // Tag_nodefaults "should be emitted before any other tag in an attribute
+  // subsection other that the conformance tag"
+  //
+  // See ARM [ABI-addenda], 2.3.7.5 No defaults tag
+  const ELFAttributeValue &attr_nodefaults = m_Attrs[Tag_nodefaults];
+
+  if (attr_nodefaults.shouldEmit()) {
+    if (!ELFAttributeData::WriteAttribute(Tag_nodefaults,  attr_nodefaults,
+                                          buffer)) {
+      return 0;
+    }
+  }
+
+  // Tag_conformance (=67)
+  // Tag_nodefaults (=64)
+  for (unsigned i = 0; i < Tag_nodefaults; ++i) {
+    TagType tag = static_cast<TagType>(i);
+    const ELFAttributeValue &value = m_Attrs[tag];
+
+    if (value.shouldEmit() &&
+        !ELFAttributeData::WriteAttribute(tag, value, buffer)) {
+      return 0;
+    }
+  }
+
+  for (unsigned i = (Tag_nodefaults + 1); i <= Tag_Max; ++i) {
+    TagType tag = static_cast<TagType>(i);
+    const ELFAttributeValue &value = m_Attrs[tag];
+
+    if (value.shouldEmit() && (i != Tag_conformance) &&
+        !ELFAttributeData::WriteAttribute(tag, value, buffer)) {
+      return 0;
+    }
+  }
+
+  for (UnknownAttrsMap::const_iterator unknown_attr_it = m_UnknownAttrs.begin(),
+          unknown_attr_end = m_UnknownAttrs.end();
+       unknown_attr_it != unknown_attr_end; ++unknown_attr_it) {
+    TagType tag = unknown_attr_it->first;
+    const ELFAttributeValue &value = unknown_attr_it->second;
+
+    if (value.shouldEmit() &&
+        !ELFAttributeData::WriteAttribute(tag, value, buffer)) {
+      return 0;
+    }
+  }
+
+  return (buffer - pBuf);
+}
diff --git a/lib/Target/ARM/ARMELFAttributeData.h b/lib/Target/ARM/ARMELFAttributeData.h
new file mode 100644
index 0000000..01e7816
--- /dev/null
+++ b/lib/Target/ARM/ARMELFAttributeData.h
@@ -0,0 +1,242 @@
+//===- ARMELFAttributeData.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_ATTRIBUTE_DATA_H
+#define MCLD_ARM_ELF_ATTRIBUTE_DATA_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/ELFAttributeData.h>
+#include <mcld/Target/ELFAttributeValue.h>
+
+#include <map>
+#include <string>
+
+namespace mcld {
+
+/** \class ARMELFAttributeData
+ *  \brief ARMELFAttributeData handles public ("aeabi") attributes subsection in
+ *  ARM ELF.
+ *
+ */
+class ARMELFAttributeData : public ELFAttributeData {
+public:
+  enum Tag {
+    // 0-3 are generic and are defined in ELFAttributeData.
+    Tag_CPU_raw_name                = 4,
+    Tag_CPU_name                    = 5,
+    Tag_CPU_arch                    = 6,
+    Tag_CPU_arch_profile            = 7,
+    Tag_ARM_ISA_use                 = 8,
+    Tag_THUMB_ISA_use               = 9,
+    Tag_FP_arch                     = 10,
+    Tag_WMMX_arch                   = 11,
+    Tag_Advanced_SIMD_arch          = 12,
+    Tag_PCS_config                  = 13,
+    Tag_ABI_PCS_R9_use              = 14,
+    Tag_ABI_PCS_RW_data             = 15,
+    Tag_ABI_PCS_RO_data             = 16,
+    Tag_ABI_PCS_GOT_use             = 17,
+    Tag_ABI_PCS_wchar_t             = 18,
+    Tag_ABI_FP_rounding             = 19,
+    Tag_ABI_FP_denormal             = 20,
+    Tag_ABI_FP_exceptions           = 21,
+    Tag_ABI_FP_user_exceptions      = 22,
+    Tag_ABI_FP_number_model         = 23,
+    Tag_ABI_align_needed            = 24,
+    Tag_ABI_align_preserved         = 25,
+    Tag_ABI_enum_size               = 26,
+    Tag_ABI_HardFP_use              = 27,
+    Tag_ABI_VFP_args                = 28,
+    Tag_ABI_WMMX_args               = 29,
+    Tag_ABI_optimization_goals      = 30,
+    Tag_ABI_FP_optimization_goals   = 31,
+    Tag_compatibility               = 32,
+
+    Tag_CPU_unaligned_access        = 34,
+
+    Tag_FP_HP_extension             = 36,
+
+    Tag_ABI_FP_16bit_format         = 38,
+
+    Tag_MPextension_use             = 42,
+
+    Tag_DIV_use                     = 44,
+
+    Tag_nodefaults                  = 64,
+    Tag_also_compatible_with        = 65,
+    Tag_T2EE_use                    = 66,
+    Tag_conformance                 = 67,
+    Tag_Virtualization_use          = 68,
+
+    Tag_MPextension_use_legacy      = 70,
+
+    Tag_Max = Tag_MPextension_use_legacy,
+
+    // Alias
+    Tag_VFP_arch                    = Tag_FP_arch,
+    Tag_ABI_align8_needed           = Tag_ABI_align_needed,
+    Tag_ABI_align8_preserved        = Tag_ABI_align_preserved,
+    Tag_VFP_HP_extension            = Tag_FP_HP_extension
+  };
+
+  // For Tag_CPU_arch
+  enum {
+    CPU_Arch_ARM_Pre_V4,
+    CPU_Arch_ARM_V4,    // e.g., SA110
+    CPU_Arch_ARM_V4T,   // e.g., ARM7TDMI
+    CPU_Arch_ARM_V5T,   // e.g., ARM9TDMI
+    CPU_Arch_ARM_V5TE,  // e.g., ARM946E-S
+    CPU_Arch_ARM_V5TEJ, // e.g., ARM926EJ-S
+    CPU_Arch_ARM_V6,    // e.g., ARM1136J-S
+    CPU_Arch_ARM_V6KZ,  // e.g., ARM1176JZ-S
+    CPU_Arch_ARM_V6T2,  // e.g., ARM1156T2F-S
+    CPU_Arch_ARM_V6K,   // e.g., ARM1136J-S
+    CPU_Arch_ARM_V7,    // e.g., Cortex A8, Cortex M3
+    CPU_Arch_ARM_V6_M,  // e.g., Cortex M1
+    CPU_Arch_ARM_V6S_M, // e.g., v6-M with the value of System extensions
+    CPU_Arch_ARM_V7E_M, // e.g., v7-M with DSP extensions
+    CPU_Arch_ARM_V8,
+
+    CPU_Arch_Max = CPU_Arch_ARM_V8,
+
+    // This is a pseudo-architecture to describe an architecture mixed with
+    // the subset of armv4t and armv6-m. This never appears in the value of
+    // Tag_CPU_arch.
+    CPU_Arch_ARM_V4T_Plus_V6_M = (CPU_Arch_Max + 1),
+
+    CPU_Arch_Plus_Pseudo_Max = CPU_Arch_ARM_V4T_Plus_V6_M,
+  };
+
+  // For Tag_CPU_arch_profile
+  enum {
+    Arch_Profile_None             = 0,
+    Arch_Profile_Application      = 'A',
+    Arch_Profile_Realtime         = 'R',
+    Arch_Profile_Microcontroller  = 'M',
+    Arch_Profile_RealOrApp        = 'S'
+  };
+
+  // For Tag_ABI_enum_size
+  enum {
+    Enum_Unused,
+    Enum_Smallest_Container,
+    Enum_32bit_Container,
+    Enum_Containerized_As_Possible
+  };
+
+  // For Tag_ABI_PCS_R9_use
+  enum {
+    R9_V6,
+    R9_SB,
+    R9_TLS,
+    R9_Unused
+  };
+
+  // For Tag_ABI_PCS_RW_data
+  enum {
+    RW_data_Absolute,
+    RW_data_PC_Relative,
+    RW_data_SB_Relative,
+    RW_data_unused
+  };
+
+public:
+  // ARM [ABI-addenda], 2.2.2: A public attributes subsection is named aeabi.
+  ARMELFAttributeData()
+    : ELFAttributeData("aeabi"), m_CurrentCPUArch(-1),
+      m_DIVUseInitialized(false), m_HardFPUseInitialized(false) { }
+
+public:
+  virtual const ELFAttributeValue *getAttributeValue(TagType pTag) const;
+
+  virtual std::pair<ELFAttributeValue*, bool>
+      getOrCreateAttributeValue(TagType pTag);
+
+  virtual bool preMerge(const Input &pInput)
+  {
+    // Reset states.
+    m_CPUArch = -1;
+    m_CPUName.clear();
+    m_CPURawName.clear();
+    m_SecondaryCPUArch = -1;
+    m_VFPArgs = -1;
+    m_FPArch = -1;
+    m_HardFPUse = -1;
+    m_MPextensionUse = -1;
+    m_DIVUse = -1;
+    return true;
+  }
+
+  virtual bool merge(const LinkerConfig& pConfig, const Input &pInput,
+                     TagType pTag, const ELFAttributeValue& pInAttr);
+
+  virtual bool postMerge(const LinkerConfig& pConfig, const Input &pInput);
+
+  virtual size_t sizeOutput() const;
+
+  virtual size_t emit(char *pBuf) const;
+
+private:
+  /// GetAttributeValueType - obtain the value type of the indicated tag.
+  static unsigned int GetAttributeValueType(TagType pTag);
+
+private:
+  // The storage for known tags which is indexed by the tag
+  ELFAttributeValue m_Attrs[Tag_Max + 1];
+
+  // The storage for unknown tags
+  typedef std::map<TagType, ELFAttributeValue> UnknownAttrsMap;
+  UnknownAttrsMap m_UnknownAttrs;
+
+  // This is a cache for the current output architecture calculate from of
+  // Tag_CPU_arch and Tag_also_compatible_with.
+  int m_CurrentCPUArch;
+
+  // Value of Tag_DIV_use and Tag_ABI_HardFP_use requires further examination
+  // for the every time adding to the output. These booleans are initialized to
+  // false and set to true until the corresponding attribute is initialized.
+  bool m_DIVUseInitialized;
+  bool m_HardFPUseInitialized;
+
+  // These attributes have dependency with each other. During the merge, we
+  // record their attribute values in the associated variables as follows and
+  // process them in postmerge() (when all other attributes are settled down.)
+
+  // Record the value of input Tag_CPU_arch.
+  int m_CPUArch;
+
+  // Record the value of input Tag_CPU_name.
+  std::string m_CPUName;
+
+  // Record the value of input Tag_CPU_raw_name.
+  std::string m_CPURawName;
+
+  // Record the value of input Tag_FP_arch.
+  int m_FPArch;
+
+  // Record the value of input Tag_ABI_HardFP_use.
+  int m_HardFPUse;
+
+  // Record the value of input Tag_also_compatible_with.
+  int m_SecondaryCPUArch;
+
+  // Record the value of input Tag_ABI_VFP_args.
+  int m_VFPArgs;
+
+  // Record the value of input Tag_MPextension_use and Tag_MPextension_use_legacy.
+  int m_MPextensionUse;
+
+  // Record the value of input Tag_DIV_use.
+  int m_DIVUse;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/ARMELFMCLinker.cpp b/lib/Target/ARM/ARMELFMCLinker.cpp
index daccc84..8e9a440 100644
--- a/lib/Target/ARM/ARMELFMCLinker.cpp
+++ b/lib/Target/ARM/ARMELFMCLinker.cpp
@@ -8,15 +8,12 @@
 //===----------------------------------------------------------------------===//
 #include "ARMELFMCLinker.h"
 
-#include <mcld/LinkerConfig.h>
-#include <mcld/Object/SectionMap.h>
-
 using namespace mcld;
 
 ARMELFMCLinker::ARMELFMCLinker(LinkerConfig& pConfig,
                                mcld::Module &pModule,
-                               MemoryArea& pOutput)
-  : ELFMCLinker(pConfig, pModule, pOutput) {
+                               FileHandle& pFileHandle)
+  : ELFMCLinker(pConfig, pModule, pFileHandle) {
 }
 
 ARMELFMCLinker::~ARMELFMCLinker()
diff --git a/lib/Target/ARM/ARMELFMCLinker.h b/lib/Target/ARM/ARMELFMCLinker.h
index 91f297f..1306bc9 100644
--- a/lib/Target/ARM/ARMELFMCLinker.h
+++ b/lib/Target/ARM/ARMELFMCLinker.h
@@ -16,7 +16,7 @@
 namespace mcld {
 
 class Module;
-class MemoryArea;
+class FileHandle;
 
 /** \class ARMELFMCLinker
  *  \brief ARMELFMCLinker sets up the environment for linking.
@@ -26,7 +26,7 @@
 public:
   ARMELFMCLinker(LinkerConfig& pConfig,
                  mcld::Module& pModule,
-                 MemoryArea& pOutput);
+                 FileHandle& pFileHandle);
 
   ~ARMELFMCLinker();
 };
diff --git a/lib/Target/ARM/ARMEmulation.cpp b/lib/Target/ARM/ARMEmulation.cpp
index 8b64f40..a890a87 100644
--- a/lib/Target/ARM/ARMEmulation.cpp
+++ b/lib/Target/ARM/ARMEmulation.cpp
@@ -34,11 +34,11 @@
   pConfig.attribute().predefined().setDynamic();
 
   // set up section map
-  if (pConfig.codeGenType() != LinkerConfig::Object) {
-    bool exist = false;
-    pScript.sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
-    pScript.sectionMap().append(".ARM.extab", ".ARM.extab", exist);
-    pScript.sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
+  if (pConfig.options().getScriptList().empty() &&
+      pConfig.codeGenType() != LinkerConfig::Object) {
+    pScript.sectionMap().insert(".ARM.exidx*", ".ARM.exidx");
+    pScript.sectionMap().insert(".ARM.extab*", ".ARM.extab");
+    pScript.sectionMap().insert(".ARM.attributes*", ".ARM.attributes");
   }
   return true;
 }
diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h
deleted file mode 100644
index f42b940..0000000
--- a/lib/Target/ARM/ARMFixupKinds.h
+++ /dev/null
@@ -1,98 +0,0 @@
-//===- ARMFixupKinds.h ----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LIB_TARGET_ARM_ARM_FIXUP_KINDS_H_
-#define MCLD_LIB_TARGET_ARM_ARM_FIXUP_KINDS_H_
-
-#include <llvm/MC/MCFixup.h>
-
-namespace mcld {
-namespace ARM {
-
-enum Fixups {
-  // fixup_arm_ldst_pcrel_12 - 12-bit PC relative relocation for symbol
-  // addresses
-  fixup_arm_ldst_pcrel_12 = FirstTargetFixupKind,
-
-  // fixup_t2_ldst_pcrel_12 - Equivalent to fixup_arm_ldst_pcrel_12, with
-  // the 16-bit halfwords reordered.
-  fixup_t2_ldst_pcrel_12,
-
-  // fixup_arm_pcrel_10 - 10-bit PC relative relocation for symbol addresses
-  // used in VFP instructions where the lower 2 bits are not encoded
-  // (so it's encoded as an 8-bit immediate).
-  fixup_arm_pcrel_10,
-  // fixup_t2_pcrel_10 - Equivalent to fixup_arm_pcrel_10, accounting for
-  // the short-swapped encoding of Thumb2 instructions.
-  fixup_t2_pcrel_10,
-  // fixup_thumb_adr_pcrel_10 - 10-bit PC relative relocation for symbol
-  // addresses where the lower 2 bits are not encoded (so it's encoded as an
-  // 8-bit immediate).
-  fixup_thumb_adr_pcrel_10,
-  // fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
-  // instruction.
-  fixup_arm_adr_pcrel_12,
-  // fixup_t2_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
-  // instruction.
-  fixup_t2_adr_pcrel_12,
-  // fixup_arm_condbranch - 24-bit PC relative relocation for conditional branch
-  // instructions. 
-  fixup_arm_condbranch,
-  // fixup_arm_uncondbranch - 24-bit PC relative relocation for 
-  // branch instructions. (unconditional)
-  fixup_arm_uncondbranch,
-  // fixup_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct
-  // unconditional branch instructions.
-  fixup_t2_condbranch,
-  // fixup_t2_uncondbranch - 20-bit PC relative relocation for Thumb2 direct
-  // branch unconditional branch instructions.
-  fixup_t2_uncondbranch,
-
-  // fixup_arm_thumb_br - 12-bit fixup for Thumb B instructions.
-  fixup_arm_thumb_br,
-
-  // fixup_arm_thumb_bl - Fixup for Thumb BL instructions.
-  fixup_arm_thumb_bl,
-
-  // fixup_arm_thumb_blx - Fixup for Thumb BLX instructions.
-  fixup_arm_thumb_blx,
-
-  // fixup_arm_thumb_cb - Fixup for Thumb branch instructions.
-  fixup_arm_thumb_cb,
-
-  // fixup_arm_thumb_cp - Fixup for Thumb load/store from constant pool instrs.
-  fixup_arm_thumb_cp,
-
-  // fixup_arm_thumb_bcc - Fixup for Thumb conditional branching instructions.
-  fixup_arm_thumb_bcc,
-
-  // The next two are for the movt/movw pair
-  // the 16bit imm field are split into imm{15-12} and imm{11-0}
-  fixup_arm_movt_hi16, // :upper16:
-  fixup_arm_movw_lo16, // :lower16:
-  fixup_t2_movt_hi16, // :upper16:
-  fixup_t2_movw_lo16, // :lower16:
-
-  // It is possible to create an "immediate" that happens to be pcrel.
-  // movw r0, :lower16:Foo-(Bar+8) and movt  r0, :upper16:Foo-(Bar+8)
-  // result in different reloc tags than the above two.
-  // Needed to support ELF::R_ARM_MOVT_PREL and ELF::R_ARM_MOVW_PREL_NC
-  fixup_arm_movt_hi16_pcrel, // :upper16:
-  fixup_arm_movw_lo16_pcrel, // :lower16:
-  fixup_t2_movt_hi16_pcrel, // :upper16:
-  fixup_t2_movw_lo16_pcrel, // :lower16:
-
-  // Marker
-  LastTargetFixupKind,
-  NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
-};
-
-} // namespace ARM
-} // namespace mcld
-
-#endif
diff --git a/lib/Target/ARM/ARMGNUInfo.h b/lib/Target/ARM/ARMGNUInfo.h
index ba51126..531a817 100644
--- a/lib/Target/ARM/ARMGNUInfo.h
+++ b/lib/Target/ARM/ARMGNUInfo.h
@@ -23,9 +23,7 @@
 
   uint64_t defaultTextSegmentAddr() const { return 0x8000; }
 
-  uint64_t flags() const
-  { return llvm::ELF::EF_ARM_EABI_VER5; }
-
+  uint64_t flags() const { return llvm::ELF::EF_ARM_EABI_VER5; }
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
index 1796635..3e9dc31 100644
--- a/lib/Target/ARM/ARMGOT.cpp
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -12,7 +12,6 @@
 
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/LDFileFormat.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 
 namespace {
@@ -24,15 +23,11 @@
 //===----------------------------------------------------------------------===//
 // ARMGOT
 ARMGOT::ARMGOT(LDSection& pSection)
-  : GOT(pSection), m_pLast(NULL)
+  : GOT(pSection), m_pGOTPLTFront(NULL), m_pGOTFront(NULL)
 {
-  // Create GOT0 entries.
-  reserve(ARMGOT0Num);
-
-  // Skip GOT0 entries.
-  for (unsigned int i = 0; i < ARMGOT0Num; ++i) {
-    consume();
-  }
+  // create GOT0, and put them into m_SectionData immediately
+  for (unsigned int i = 0; i < ARMGOT0Num; ++i)
+    new ARMGOTEntry(0, m_SectionData);
 }
 
 ARMGOT::~ARMGOT()
@@ -41,86 +36,64 @@
 
 bool ARMGOT::hasGOT1() const
 {
-  return (m_SectionData->size() > ARMGOT0Num);
+  return ((!m_GOT.empty()) || (!m_GOTPLT.empty()));
 }
 
-void ARMGOT::reserve(size_t pNum)
+ARMGOTEntry* ARMGOT::createGOT()
 {
-  for (size_t i = 0; i < pNum; i++) {
-    new ARMGOTEntry(0, m_SectionData);
-  }
+  ARMGOTEntry* entry = new ARMGOTEntry(0, NULL);
+  m_GOT.push_back(entry);
+  return entry;
 }
 
-ARMGOTEntry* ARMGOT::consume()
+ARMGOTEntry* ARMGOT::createGOTPLT()
 {
-  if (NULL == m_pLast) {
-    assert(!empty() && "Consume empty GOT entry!");
-    m_pLast = llvm::cast<ARMGOTEntry>(&m_SectionData->front());
-    return m_pLast;
+  ARMGOTEntry* entry = new ARMGOTEntry(0, NULL);
+  m_GOTPLT.push_back(entry);
+  return entry;
+}
+
+void ARMGOT::finalizeSectionSize()
+{
+  uint32_t offset = 0;
+  SectionData::FragmentListType& frag_list = m_SectionData->getFragmentList();
+  // setup GOT0 offset
+  SectionData::iterator frag, fragEnd = m_SectionData->end();
+  for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
+    frag->setOffset(offset);
+    offset += frag->size();
   }
 
-  m_pLast = llvm::cast<ARMGOTEntry>(m_pLast->getNextNode());
-  return m_pLast;
-}
-
-void ARMGOT::reserveGOTPLT()
-{
-  ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData);
-  if (NULL == m_GOTPLT.front) {
-    // GOTPLT is empty
-    if (NULL == m_GOT.front) {
-      // GOT part is also empty. Since entry is the last entry, we can assign
-      // it to GOTPLT directly.
-      m_GOTPLT.front = entry;
-    }
-    else {
-      // GOTn is not empty. Shift GOTn backward by one entry.
-      m_GOTPLT.front = m_GOT.front;
-      m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode());
+  // push GOTPLT into the SectionData and setup the offset
+  if (!m_GOTPLT.empty()) {
+    m_pGOTPLTFront = m_GOTPLT.front();
+    entry_iterator it, end = m_GOTPLT.end();
+    for (it = m_GOTPLT.begin(); it != end; ++it) {
+      ARMGOTEntry* entry = *it;
+      frag_list.push_back(entry);
+      entry->setParent(m_SectionData);
+      entry->setOffset(offset);
+      offset += entry->size();
     }
   }
-  else {
-    // GOTPLT is not empty
-    if (NULL != m_GOT.front)
-      m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode());
-  }
-}
+  m_GOTPLT.clear();
 
-void ARMGOT::reserveGOT()
-{
-  ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData);
-  if (NULL == m_GOT.front) {
-    // Entry must be the last entry. We can directly assign it to GOT part.
-    m_GOT.front = entry;
+  // push GOT into the SectionData and setup the offset
+  if (!m_GOT.empty()) {
+    m_pGOTFront = m_GOT.front();
+    entry_iterator it, end = m_GOT.end();
+    for (it = m_GOT.begin(); it != end; ++it) {
+      ARMGOTEntry* entry = *it;
+      frag_list.push_back(entry);
+      entry->setParent(m_SectionData);
+      entry->setOffset(offset);
+      offset += entry->size();
+    }
   }
-}
+  m_GOT.clear();
 
-ARMGOTEntry* ARMGOT::consumeGOTPLT()
-{
-  assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!");
-
-  if (NULL == m_GOTPLT.last_used) {
-    m_GOTPLT.last_used = m_GOTPLT.front;
-  }
-  else {
-    m_GOTPLT.last_used = llvm::cast<ARMGOTEntry>(m_GOTPLT.last_used->getNextNode());
-    assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!");
-  }
-  return m_GOTPLT.last_used;
-}
-
-ARMGOTEntry* ARMGOT::consumeGOT()
-{
-  assert(NULL != m_GOT.front && "Consuming empty GOT section!");
-
-  if (NULL == m_GOT.last_used) {
-    m_GOT.last_used = m_GOT.front;
-  }
-  else {
-    m_GOT.last_used = llvm::cast<ARMGOTEntry>(m_GOT.last_used->getNextNode());
-    assert(m_GOT.last_used != NULL && "No GOTn entry to consume!");
-  }
-  return m_GOT.last_used;
+  // set section size
+  m_Section.setSize(offset);
 }
 
 void ARMGOT::applyGOT0(uint64_t pAddress)
@@ -131,15 +104,15 @@
 
 void ARMGOT::applyGOTPLT(uint64_t pPLTBase)
 {
-  if (NULL == m_GOTPLT.front)
+  if (NULL == m_pGOTPLTFront)
     return;
 
-  SectionData::iterator entry(m_GOTPLT.front);
+  SectionData::iterator entry(m_pGOTPLTFront);
   SectionData::iterator e_end;
-  if (NULL == m_GOT.front)
+  if (NULL == m_pGOTFront)
     e_end = m_SectionData->end();
   else
-    e_end = SectionData::iterator(m_GOT.front);
+    e_end = SectionData::iterator(m_pGOTFront);
 
   while (entry != e_end) {
     llvm::cast<ARMGOTEntry>(entry)->setValue(pPLTBase);
@@ -149,7 +122,7 @@
 
 uint64_t ARMGOT::emit(MemoryRegion& pRegion)
 {
-  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
 
   ARMGOTEntry* got = NULL;
   uint64_t result = 0x0;
diff --git a/lib/Target/ARM/ARMGOT.h b/lib/Target/ARM/ARMGOT.h
index be22c67..dc85fb0 100644
--- a/lib/Target/ARM/ARMGOT.h
+++ b/lib/Target/ARM/ARMGOT.h
@@ -12,14 +12,14 @@
 #include <gtest.h>
 #endif
 
-#include <llvm/ADT/DenseMap.h>
-
 #include <mcld/Target/GOT.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <llvm/ADT/DenseMap.h>
+#include <vector>
 
 namespace mcld {
 
 class LDSection;
-class MemoryRegion;
 
 /** \class ARMGOTEntry
  *  \brief GOT Entry with size of 4 bytes
@@ -56,17 +56,10 @@
 
   ~ARMGOT();
 
-  void reserve(size_t pNum = 1);
+  ARMGOTEntry* createGOT();
+  ARMGOTEntry* createGOTPLT();
 
-  void reserveGOTPLT();
-
-  void reserveGOT();
-
-  ARMGOTEntry* consume();
-
-  ARMGOTEntry* consumeGOT();
-
-  ARMGOTEntry* consumeGOTPLT();
+  void finalizeSectionSize();
 
   uint64_t emit(MemoryRegion& pRegion);
 
@@ -77,20 +70,19 @@
   bool hasGOT1() const;
 
 private:
-  struct Part {
-  public:
-    Part() : front(NULL), last_used(NULL) { }
-
-  public:
-    ARMGOTEntry* front;
-    ARMGOTEntry* last_used;
-  };
+  typedef std::vector<ARMGOTEntry*> EntryListType;
+  typedef EntryListType::iterator entry_iterator;
+  typedef EntryListType::const_iterator const_entry_iterator;
 
 private:
-  Part m_GOTPLT;
-  Part m_GOT;
+  ARMGOTEntry* m_pGOTPLTFront;
+  ARMGOTEntry* m_pGOTFront;
 
-  ARMGOTEntry* m_pLast; ///< the last consumed entry
+  /// m_GOTPLTEntries - a list of gotplt entries
+  EntryListType m_GOTPLT;
+
+  /// m_GOTEntris - a list of got entries
+  EntryListType m_GOT;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index 8e45543..dfcfb0d 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include "ARM.h"
 #include "ARMGNUInfo.h"
+#include "ARMELFAttributeData.h"
 #include "ARMELFDynamic.h"
 #include "ARMLDBackend.h"
 #include "ARMRelocator.h"
@@ -28,17 +29,21 @@
 #include <mcld/Fragment/FillFragment.h>
 #include <mcld/Fragment/AlignFragment.h>
 #include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/Fragment/NullFragment.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
-#include <mcld/Fragment/Stub.h>
 #include <mcld/LD/BranchIslandFactory.h>
 #include <mcld/LD/StubFactory.h>
-#include <mcld/Object/ObjectBuilder.h>
-#include <mcld/Fragment/NullFragment.h>
 #include <mcld/LD/LDContext.h>
+#include <mcld/LD/ELFFileFormat.h>
+#include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/ELFSegment.h>
+#include <mcld/Target/ELFAttribute.h>
 #include <mcld/Target/GNUInfo.h>
+#include <mcld/Object/ObjectBuilder.h>
 
 using namespace mcld;
 
@@ -52,6 +57,7 @@
     m_pPLT(NULL),
     m_pRelDyn(NULL),
     m_pRelPLT(NULL),
+    m_pAttrData(NULL),
     m_pDynamic(NULL),
     m_pGOTSymbol(NULL),
     m_pEXIDXStart(NULL),
@@ -69,6 +75,7 @@
   delete m_pRelDyn;
   delete m_pRelPLT;
   delete m_pDynamic;
+  delete m_pAttrData;
 }
 
 void ARMGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
@@ -91,6 +98,10 @@
                                            0x0,
                                            0x1);
 
+  // initialize "aeabi" attributes subsection
+  m_pAttrData = new ARMELFAttributeData();
+  attribute().registerAttributeData(*m_pAttrData);
+
   if (LinkerConfig::Object != config().codeGenType()) {
     ELFFileFormat* file_format = getOutputFormat();
 
@@ -206,6 +217,9 @@
   if (!config().isCodeStatic() && NULL == m_pDynamic)
     m_pDynamic = new ARMELFDynamic(*this, config());
 
+  // set attribute section size
+  m_pAttributes->setSize(attribute().sizeOutput());
+
   // set .got size
   // when building shared object, the .got section is must
   if (LinkerConfig::Object != config().codeGenType()) {
@@ -316,77 +330,71 @@
 
   const ELFFileFormat* file_format = getOutputFormat();
 
-  if (&pSection == m_pAttributes ||
-      &pSection == m_pEXIDX ||
-      &pSection == m_pEXTAB) {
-    // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
-    // directly from the input file.
-    const SectionData* sect_data = pSection.getSectionData();
-    SectionData::const_iterator frag_iter, frag_end = sect_data->end();
-    uint8_t* out_offset = pRegion.start();
-    for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
-      size_t size = frag_iter->size();
-      switch(frag_iter->getKind()) {
-        case Fragment::Fillment: {
-          const FillFragment& fill_frag =
-            llvm::cast<FillFragment>(*frag_iter);
-          if (0 == fill_frag.getValueSize()) {
-            // virtual fillment, ignore it.
-            break;
-          }
-
-          memset(out_offset, fill_frag.getValue(), fill_frag.size());
-          break;
-        }
-        case Fragment::Region: {
-          const RegionFragment& region_frag =
-            llvm::cast<RegionFragment>(*frag_iter);
-          const uint8_t* start = region_frag.getRegion().start();
-          memcpy(out_offset, start, size);
-          break;
-        }
-        case Fragment::Alignment: {
-          const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
-          uint64_t count = size / align_frag.getValueSize();
-          switch (align_frag.getValueSize()) {
-            case 1u:
-              std::memset(out_offset, align_frag.getValue(), count);
-              break;
-            default:
-              llvm::report_fatal_error(
-                "unsupported value size for align fragment emission yet.\n");
-              break;
-          } // end switch
-          break;
-        }
-        case Fragment::Null: {
-          assert(0x0 == size);
-          break;
-        }
-        default:
-          llvm::report_fatal_error("unsupported fragment type.\n");
-          break;
-      } // end switch
-      out_offset += size;
-    } // end for
-    return pRegion.size();
-  } // end if
-
-  if (&pSection == &(file_format->getPLT())) {
-    assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
+  if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
     uint64_t result = m_pPLT->emit(pRegion);
     return result;
   }
 
-  if (&pSection == &(file_format->getGOT())) {
-    assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
+  if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
     uint64_t result = m_pGOT->emit(pRegion);
     return result;
   }
-  fatal(diag::unrecognized_output_sectoin)
-          << pSection.name()
-          << "mclinker@googlegroups.com";
-  return 0x0;
+
+  if (&pSection == m_pAttributes) {
+    return attribute().emit(pRegion);
+  }
+
+  // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
+  // directly from the input file.
+  const SectionData* sect_data = pSection.getSectionData();
+  SectionData::const_iterator frag_iter, frag_end = sect_data->end();
+  uint8_t* out_offset = pRegion.begin();
+  for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
+    size_t size = frag_iter->size();
+    switch(frag_iter->getKind()) {
+      case Fragment::Fillment: {
+        const FillFragment& fill_frag =
+          llvm::cast<FillFragment>(*frag_iter);
+        if (0 == fill_frag.getValueSize()) {
+          // virtual fillment, ignore it.
+          break;
+        }
+
+        memset(out_offset, fill_frag.getValue(), fill_frag.size());
+        break;
+      }
+      case Fragment::Region: {
+        const RegionFragment& region_frag =
+          llvm::cast<RegionFragment>(*frag_iter);
+        const char* start = region_frag.getRegion().begin();
+        memcpy(out_offset, start, size);
+        break;
+      }
+      case Fragment::Alignment: {
+        const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
+        uint64_t count = size / align_frag.getValueSize();
+        switch (align_frag.getValueSize()) {
+          case 1u:
+            std::memset(out_offset, align_frag.getValue(), count);
+            break;
+          default:
+            llvm::report_fatal_error(
+              "unsupported value size for align fragment emission yet.\n");
+            break;
+        } // end switch
+        break;
+      }
+      case Fragment::Null: {
+        assert(0x0 == size);
+        break;
+      }
+      default:
+        llvm::report_fatal_error("unsupported fragment type.\n");
+        break;
+    } // end switch
+    out_offset += size;
+  } // end for
+  return pRegion.size();
 }
 
 /// finalizeSymbol - finalize the symbol value
@@ -395,46 +403,110 @@
   return true;
 }
 
-bool ARMGNULDBackend::mergeSection(Module& pModule, LDSection& pSection)
+bool ARMGNULDBackend::mergeSection(Module& pModule,
+                                   const Input& pInput,
+                                   LDSection& pSection)
 {
   switch (pSection.type()) {
     case llvm::ELF::SHT_ARM_ATTRIBUTES: {
-      // FIXME: (Luba)
-      // Handle ARM attributes in the right way.
-      // 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.
-      if (0 != m_pAttributes->size())
-        return true;
-
-      // First time we meet a ARM attributes section.
-      SectionData* sd = IRBuilder::CreateSectionData(*m_pAttributes);
-      ObjectBuilder::MoveSectionData(*pSection.getSectionData(), *sd);
-      return true;
+      return attribute().merge(pInput, pSection);
     }
+    case llvm::ELF::SHT_ARM_EXIDX: {
+      assert(NULL != pSection.getLink());
+      if (LDFileFormat::Ignore == pSection.getLink()->kind()) {
+        // if the target section of the .ARM.exidx is Ignore, then it should be
+        // ignored as well
+        pSection.setKind(LDFileFormat::Ignore);
+        return true;
+      }
+    }
+    /** fall through **/
     default: {
       ObjectBuilder builder(config(), pModule);
-      return builder.MergeSection(pSection);
+      builder.MergeSection(pInput, pSection);
+      return true;
     }
   } // end of switch
   return true;
 }
 
+void ARMGNULDBackend::setUpReachedSectionsForGC(const Module& pModule,
+            GarbageCollection::SectionReachedListMap& pSectReachedListMap) const
+{
+  // traverse all the input relocations to find the relocation sections applying
+  // .ARM.exidx sections
+  Module::const_obj_iterator input, inEnd = pModule.obj_end();
+  for (input = pModule.obj_begin(); input != inEnd; ++input) {
+    LDContext::const_sect_iterator rs,
+                                   rsEnd = (*input)->context()->relocSectEnd();
+    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+      // bypass the discarded relocation section
+      // 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)
+      LDSection* reloc_sect = *rs;
+      LDSection* apply_sect = reloc_sect->getLink();
+      if ((LDFileFormat::Ignore == reloc_sect->kind()) ||
+          (!reloc_sect->hasRelocData()))
+        continue;
+
+      if (llvm::ELF::SHT_ARM_EXIDX == apply_sect->type()) {
+        // 1. set up the reference according to relocations
+        bool add_first = false;
+        GarbageCollection::SectionListTy* reached_sects = NULL;
+        RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end();
+        for (reloc_it = reloc_sect->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
+          // reference
+          if (NULL == sym)
+            continue;
+          if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
+            continue;
+
+          // only the target symbols defined in the concerned sections can make
+          // the reference
+          const LDSection* target_sect =
+                &sym->outSymbol()->fragRef()->frag()->getParent()->getSection();
+          if (target_sect->kind() != LDFileFormat::Regular &&
+              target_sect->kind() != LDFileFormat::BSS)
+            continue;
+
+          // setup the reached list, if we first add the element to reached list
+          // of this section, create an entry in ReachedSections map
+          if (!add_first) {
+            reached_sects = &pSectReachedListMap.getReachedList(*apply_sect);
+            add_first = true;
+          }
+          reached_sects->insert(target_sect);
+        }
+        reached_sects = NULL;
+        add_first = false;
+        // 2. set up the reference from XXX to .ARM.exidx.XXX
+        assert(apply_sect->getLink() != NULL);
+        pSectReachedListMap.addReference(*apply_sect->getLink(), *apply_sect);
+      }
+    }
+  }
+}
+
 bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD)
 {
   Fragment* frag = NULL;
   uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
   uint32_t size = pSD.getSection().size();
 
-  MemoryRegion* region = pInput.memArea()->request(offset, size);
-  if (NULL == region) {
+  llvm::StringRef region = pInput.memArea()->request(offset, size);
+  if (region.size() == 0) {
     // If the input section's size is zero, we got a NULL region.
     // use a virtual fill fragment
     frag = new FillFragment(0x0, 0, 0);
   }
   else {
-    frag = new RegionFragment(*region);
+    frag = new RegionFragment(region);
   }
 
   ObjectBuilder::AppendFragment(*frag, pSD);
@@ -489,18 +561,30 @@
   return *m_pRelPLT;
 }
 
+ARMELFAttributeData& ARMGNULDBackend::getAttributeData()
+{
+  assert(NULL != m_pAttrData && ".ARM.attributes section not exist");
+  return *m_pAttrData;
+}
+
+const ARMELFAttributeData& ARMGNULDBackend::getAttributeData() const
+{
+  assert(NULL != m_pAttrData && ".ARM.attributes section not exist");
+  return *m_pAttrData;
+}
+
 unsigned int
 ARMGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
 {
   const ELFFileFormat* file_format = getOutputFormat();
 
-  if (&pSectHdr == &file_format->getGOT()) {
+  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
     if (config().options().hasNow())
       return SHO_RELRO_LAST;
     return SHO_DATA;
   }
 
-  if (&pSectHdr == &file_format->getPLT())
+  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
     return SHO_PLT;
 
   if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) {
@@ -538,8 +622,7 @@
           case llvm::ELF::R_ARM_THM_CALL:
           case llvm::ELF::R_ARM_THM_XPC22:
           case llvm::ELF::R_ARM_THM_JUMP24:
-          case llvm::ELF::R_ARM_THM_JUMP19:
-          case llvm::ELF::R_ARM_V4BX: {
+          case llvm::ELF::R_ARM_THM_JUMP19: {
             // calculate the possible symbol value
             uint64_t sym_value = 0x0;
             LDSymbol* symbol = relocation->symInfo()->outSymbol();
@@ -561,23 +644,32 @@
                                                   pBuilder,
                                                   *getBRIslandFactory());
             if (NULL != stub) {
-              // a stub symbol should be local
-              assert(NULL != stub->symInfo() && stub->symInfo()->isLocal());
-              LDSection& symtab = file_format->getSymTab();
-              LDSection& strtab = file_format->getStrTab();
+              switch (config().options().getStripSymbolMode()) {
+                case GeneralOptions::StripAllSymbols:
+                case GeneralOptions::StripLocals:
+                  break;
+                default: {
+                  // 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);
-
+                  // 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);
+                }
+              } // end of switch
               isRelaxed = true;
             }
             break;
           }
+          case llvm::ELF::R_ARM_V4BX:
+            /* FIXME: bypass R_ARM_V4BX relocation now */
+            break;
           default:
             break;
         } // end of switch
@@ -639,7 +731,7 @@
      // make PT_ARM_EXIDX
      ELFSegment* exidx_seg = elfSegmentTable().produce(llvm::ELF::PT_ARM_EXIDX,
                                                        llvm::ELF::PF_R);
-     exidx_seg->addSection(m_pEXIDX);
+     exidx_seg->append(m_pEXIDX);
    }
 }
 
@@ -648,8 +740,7 @@
 //===----------------------------------------------------------------------===//
 /// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
 ///
-TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget,
-                                    const LinkerConfig& pConfig)
+TargetLDBackend* createARMLDBackend(const LinkerConfig& pConfig)
 {
   if (pConfig.targets().triple().isOSDarwin()) {
     assert(0 && "MachO linker is not supported yet");
diff --git a/lib/Target/ARM/ARMLDBackend.h b/lib/Target/ARM/ARMLDBackend.h
index 699fb78..5567293 100644
--- a/lib/Target/ARM/ARMLDBackend.h
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -18,9 +18,9 @@
 
 namespace mcld {
 
+class ARMELFAttributeData;
 class LinkerConfig;
 class GNUInfo;
-class SectionMap;
 
 //===----------------------------------------------------------------------===//
 /// ARMGNULDBackend - linker backend of ARM target of GNU ELF format
@@ -103,6 +103,9 @@
   OutputRelocSection& getRelPLT();
   const OutputRelocSection& getRelPLT() const;
 
+  ARMELFAttributeData& getAttributeData();
+  const ARMELFAttributeData& getAttributeData() const;
+
   LDSymbol* getGOTSymbol()             { return m_pGOTSymbol; }
   const LDSymbol* getGOTSymbol() const { return m_pGOTSymbol; }
 
@@ -113,7 +116,12 @@
   bool finalizeTargetSymbols();
 
   /// mergeSection - merge target dependent sections
-  bool mergeSection(Module& pModule, LDSection& pSection);
+  bool mergeSection(Module& pModule, const Input& pInput, LDSection& pSection);
+
+  /// setUpReachedSectionsForGC - set the reference from section XXX to
+  /// .ARM.exidx.XXX to make sure GC correctly handle section exidx
+  void setUpReachedSectionsForGC(const Module& pModule,
+           GarbageCollection::SectionReachedListMap& pSectReachedListMap) const;
 
   /// readSection - read target dependent sections
   bool readSection(Input& pInput, SectionData& pSD);
@@ -159,6 +167,9 @@
   /// m_RelPLT - dynamic relocation table of .rel.plt
   OutputRelocSection* m_pRelPLT;
 
+  /// m_pAttrData - attribute data in public ("aeabi") attribute subsection
+  ARMELFAttributeData* m_pAttrData;
+
   ARMELFDynamic* m_pDynamic;
   LDSymbol* m_pGOTSymbol;
   LDSymbol* m_pEXIDXStart;
diff --git a/lib/Target/ARM/ARMMCLinker.cpp b/lib/Target/ARM/ARMMCLinker.cpp
index cc9486e..dcee683 100644
--- a/lib/Target/ARM/ARMMCLinker.cpp
+++ b/lib/Target/ARM/ARMMCLinker.cpp
@@ -22,9 +22,9 @@
 MCLinker* createARMMCLinker(const std::string& pTriple,
                             LinkerConfig& pConfig,
                             mcld::Module& pModule,
-                            MemoryArea& pOutput)
+                            FileHandle& pFileHandle)
 {
-  Triple theTriple(pTriple);
+  llvm::Triple theTriple(pTriple);
   if (theTriple.isOSDarwin()) {
     assert(0 && "MachO linker has not supported yet");
     return NULL;
@@ -34,7 +34,7 @@
     return NULL;
   }
 
-  return new ARMELFMCLinker(pConfig, pModule, pOutput);
+  return new ARMELFMCLinker(pConfig, pModule, pFileHandle);
 }
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
index d7342ab..467bbeb 100644
--- a/lib/Target/ARM/ARMPLT.cpp
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -14,7 +14,6 @@
 #include <llvm/Support/Casting.h>
 
 #include <mcld/LD/LDSection.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
@@ -28,11 +27,9 @@
 //===----------------------------------------------------------------------===//
 // ARMPLT
 
-ARMPLT::ARMPLT(LDSection& pSection,
-               ARMGOT &pGOTPLT)
-  : PLT(pSection), m_GOT(pGOTPLT), m_PLTEntryIterator() {
+ARMPLT::ARMPLT(LDSection& pSection, ARMGOT &pGOTPLT)
+  : PLT(pSection), m_GOT(pGOTPLT) {
   new ARMPLT0(*m_SectionData);
-  m_PLTEntryIterator = m_SectionData->begin();
 }
 
 ARMPLT::~ARMPLT()
@@ -58,39 +55,12 @@
   }
 }
 
-void ARMPLT::reserveEntry(size_t pNum)
+ARMPLT1* ARMPLT::create()
 {
-  ARMPLT1* plt1_entry = 0;
-
-  for (size_t i = 0; i < pNum; ++i) {
-    plt1_entry = new (std::nothrow) ARMPLT1(*m_SectionData);
-
-    if (!plt1_entry)
-      fatal(diag::fail_allocate_memory_plt);
-
-    m_GOT.reserveGOTPLT();
-  }
-}
-
-ARMPLT1* ARMPLT::consume()
-{
-  ++m_PLTEntryIterator;
-  assert(m_PLTEntryIterator != m_SectionData->end() &&
-         "The number of PLT Entries and ResolveInfo doesn't match");
-
-  return llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
-}
-
-ARMPLT0* ARMPLT::getPLT0() const {
-
-  iterator first = m_SectionData->getFragmentList().begin();
-
-  assert(first != m_SectionData->getFragmentList().end() &&
-         "FragmentList is empty, getPLT0 failed!");
-
-  ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
-
-  return plt0;
+  ARMPLT1* plt1_entry = new (std::nothrow) ARMPLT1(*m_SectionData);
+  if (!plt1_entry)
+    fatal(diag::fail_allocate_memory_plt);
+  return plt1_entry;
 }
 
 void ARMPLT::applyPLT0() {
@@ -181,7 +151,7 @@
   uint64_t result = 0x0;
   iterator it = begin();
 
-  unsigned char* buffer = pRegion.getBuffer();
+  unsigned char* buffer = pRegion.begin();
   memcpy(buffer, llvm::cast<ARMPLT0>((*it)).getValue(), ARMPLT0::EntrySize);
   result += ARMPLT0::EntrySize;
   ++it;
diff --git a/lib/Target/ARM/ARMPLT.h b/lib/Target/ARM/ARMPLT.h
index 9554f0c..e1c8a74 100644
--- a/lib/Target/ARM/ARMPLT.h
+++ b/lib/Target/ARM/ARMPLT.h
@@ -11,6 +11,7 @@
 
 #include <mcld/Target/GOT.h>
 #include <mcld/Target/PLT.h>
+#include <mcld/Support/MemoryRegion.h>
 
 namespace {
 
@@ -33,7 +34,6 @@
 namespace mcld {
 
 class ARMGOT;
-class MemoryRegion;
 
 class ARMPLT0 : public PLT::Entry<sizeof(arm_plt0)>
 {
@@ -62,9 +62,7 @@
   // hasPLT1 - return if this plt section has any plt1 entry
   bool hasPLT1() const;
 
-  void reserveEntry(size_t pNum = 1) ;
-
-  ARMPLT1* consume();
+  ARMPLT1* create();
 
   ARMPLT0* getPLT0() const;
 
@@ -76,9 +74,6 @@
 
 private:
   ARMGOT& m_GOT;
-
-  // Used by getEntry() for mapping a ResolveInfo instance to a PLT1 Entry.
-  iterator m_PLTEntryIterator;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMRelocationFunctions.h b/lib/Target/ARM/ARMRelocationFunctions.h
index 94df077..790ed1f 100644
--- a/lib/Target/ARM/ARMRelocationFunctions.h
+++ b/lib/Target/ARM/ARMRelocationFunctions.h
@@ -33,6 +33,7 @@
 DECL_ARM_APPLY_RELOC_FUNC(got_prel)         \
 DECL_ARM_APPLY_RELOC_FUNC(tls)              \
 DECL_ARM_APPLY_RELOC_FUNC(thm_jump11)       \
+DECL_ARM_APPLY_RELOC_FUNC(thm_jump19)       \
 DECL_ARM_APPLY_RELOC_FUNC(unsupport)
 
 
@@ -77,7 +78,7 @@
   { &unsupport,         37, "R_ARM_ALU_SBREL_27_20_CK"},  \
   { &abs32,             38, "R_ARM_TARGET1"           },  \
   { &unsupport,         39, "R_ARM_SBREL31"           },  \
-  { &unsupport,         40, "R_ARM_V4BX"              },  \
+  { &none,              40, "R_ARM_V4BX"              },  \
   { &got_prel,          41, "R_ARM_TARGET2"           },  \
   { &prel31,            42, "R_ARM_PREL31"            },  \
   { &movw_abs_nc,       43, "R_ARM_MOVW_ABS_NC"       },  \
@@ -88,7 +89,7 @@
   { &thm_movt_abs,      48, "R_ARM_THM_MOVT_ABS"      },  \
   { &thm_movw_prel_nc,  49, "R_ARM_THM_MOVW_PREL_NC"  },  \
   { &thm_movt_prel,     50, "R_ARM_THM_MOVT_PREL"     },  \
-  { &unsupport,         51, "R_ARM_THM_JUMP19"        },  \
+  { &thm_jump19,        51, "R_ARM_THM_JUMP19"        },  \
   { &unsupport,         52, "R_ARM_THM_JUMP6"         },  \
   { &unsupport,         53, "R_ARM_THM_ALU_PREL_11_0" },  \
   { &unsupport,         54, "R_ARM_THM_PC12"          },  \
diff --git a/lib/Target/ARM/ARMRelocator.cpp b/lib/Target/ARM/ARMRelocator.cpp
index 02e4f14..415c36e 100644
--- a/lib/Target/ARM/ARMRelocator.cpp
+++ b/lib/Target/ARM/ARMRelocator.cpp
@@ -15,12 +15,304 @@
 #include <llvm/Support/Host.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/ELFFileFormat.h>
 #include <mcld/Object/ObjectBuilder.h>
 #include "ARMRelocator.h"
 #include "ARMRelocationFunctions.h"
 
 using namespace mcld;
 
+//=========================================//
+// Relocation helper function              //
+//=========================================//
+static Relocator::DWord getThumbBit(const Relocation& pReloc)
+{
+  // Set thumb bit if
+  // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
+  Relocator::DWord thumbBit =
+       ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
+        (pReloc.symInfo()->type() == ResolveInfo::Function) &&
+        ((pReloc.symValue() & 0x1) != 0))?
+        1:0;
+  return thumbBit;
+}
+
+// Using uint64_t to make sure those complicate operations won't cause
+// undefined behavior.
+static
+uint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width)
+{
+  assert(pOri_width <= 64);
+  if (pOri_width == 64)
+    return pVal;
+
+  uint64_t mask = (~((uint64_t)0)) >> (64 - pOri_width);
+  pVal &= mask;
+  // Reverse sign bit, then subtract sign bit.
+  uint64_t sign_bit = 1 << (pOri_width - 1);
+  return (pVal ^ sign_bit) - sign_bit;
+}
+
+static
+uint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask)
+{
+  return (pA & ~pMask) | (pB & pMask) ;
+}
+
+// Check if symbol can use relocation R_ARM_RELATIVE
+static bool
+helper_use_relative_reloc(const ResolveInfo& pSym,
+                          const ARMRelocator& pFactory)
+{
+  // if symbol is dynamic or undefine or preemptible
+  if (pSym.isDyn() ||
+      pSym.isUndef() ||
+      pFactory.getTarget().isSymbolPreemptible(pSym))
+    return false;
+  return true;
+}
+
+// Strip LSB (THUMB bit) if "S" is a THUMB target.
+static inline void helper_clear_thumb_bit(ARMRelocator::DWord& pValue)
+{
+  pValue &= (~0x1);
+}
+
+static
+ARMRelocator::Address helper_get_GOT_address(ResolveInfo& pSym,
+                                             ARMRelocator& pParent)
+{
+  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(pSym);
+  assert(NULL != got_entry);
+  return pParent.getTarget().getGOT().addr() + got_entry->getOffset();
+}
+
+static
+ARMGOTEntry& helper_GOT_init(Relocation& pReloc,
+                             bool pHasRel,
+                             ARMRelocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMGNULDBackend& ld_backend = pParent.getTarget();
+  assert(NULL == pParent.getSymGOTMap().lookUp(*rsym));
+
+  ARMGOTEntry* got_entry = ld_backend.getGOT().createGOT();
+  pParent.getSymGOTMap().record(*rsym, *got_entry);
+  // If we first get this GOT entry, we should initialize it.
+  if (!pHasRel) {
+    // No corresponding dynamic relocation, initialize to the symbol value.
+    got_entry->setValue(ARMRelocator::SymVal);
+  }
+  else {
+    // Initialize corresponding dynamic relocation.
+    Relocation& rel_entry = *ld_backend.getRelDyn().create();
+    if (rsym->isLocal() || helper_use_relative_reloc(*rsym, pParent)) {
+      // Initialize got entry to target symbol address
+      got_entry->setValue(ARMRelocator::SymVal);
+      rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
+      rel_entry.setSymInfo(NULL);
+    }
+    else {
+      // Initialize got entry to 0 for corresponding dynamic relocation.
+      got_entry->setValue(0);
+      rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
+      rel_entry.setSymInfo(rsym);
+    }
+    rel_entry.targetRef().assign(*got_entry);
+  }
+  return *got_entry;
+}
+
+static
+ARMRelocator::Address helper_GOT_ORG(ARMRelocator& pParent)
+{
+  return pParent.getTarget().getGOT().addr();
+}
+
+static
+ARMRelocator::Address helper_get_PLT_address(ResolveInfo& pSym,
+                                             ARMRelocator& pParent)
+{
+  ARMPLT1* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
+  assert(NULL != plt_entry);
+  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
+}
+
+static
+ARMPLT1& helper_PLT_init(Relocation& pReloc, ARMRelocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMGNULDBackend& ld_backend = pParent.getTarget();
+  assert(NULL == pParent.getSymPLTMap().lookUp(*rsym));
+
+  // initialize the plt and the corresponding gotplt and dyn relocation
+  ARMPLT1* plt_entry = ld_backend.getPLT().create();
+  pParent.getSymPLTMap().record(*rsym, *plt_entry);
+
+  assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) &&
+         "PLT entry not exist, but DynRel entry exist!");
+  ARMGOTEntry* gotplt_entry = ld_backend.getGOT().createGOTPLT();
+  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
+
+  Relocation& rel_entry = *ld_backend.getRelPLT().create();
+  rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
+  rel_entry.targetRef().assign(*gotplt_entry);
+  rel_entry.setSymInfo(rsym);
+
+  return *plt_entry;
+}
+
+// Get an relocation entry in .rel.dyn and set its type to pType,
+// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to
+// pReloc->symInfo()
+static
+void helper_DynRel_init(Relocation& pReloc,
+                        ARMRelocator::Type pType,
+                        ARMRelocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMGNULDBackend& ld_backend = pParent.getTarget();
+
+  Relocation& rel_entry = *ld_backend.getRelDyn().create();
+  rel_entry.setType(pType);
+  rel_entry.targetRef() = pReloc.targetRef();
+
+  if (pType == llvm::ELF::R_ARM_RELATIVE)
+    rel_entry.setSymInfo(NULL);
+  else
+    rel_entry.setSymInfo(rsym);
+}
+
+static ARMRelocator::DWord
+helper_extract_movw_movt_addend(ARMRelocator::DWord pTarget)
+{
+  // imm16: [19-16][11-0]
+  return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU),
+                            16);
+}
+
+static ARMRelocator::DWord
+helper_insert_val_movw_movt_inst(ARMRelocator::DWord pTarget,
+                                 ARMRelocator::DWord pImm)
+{
+  // imm16: [19-16][11-0]
+  pTarget &= 0xfff0f000U;
+  pTarget |= pImm & 0x0fffU;
+  pTarget |= (pImm & 0xf000U) << 4;
+  return pTarget;
+}
+
+static ARMRelocator::DWord
+helper_extract_thumb_movw_movt_addend(ARMRelocator::DWord pValue)
+{
+  // imm16: [19-16][26][14-12][7-0]
+  return helper_sign_extend((((pValue >> 4) & 0xf000U) |
+                             ((pValue >> 15) & 0x0800U) |
+                             ((pValue >> 4) & 0x0700U) |
+                             (pValue& 0x00ffU)),
+                            16);
+}
+
+static ARMRelocator::DWord
+helper_insert_val_thumb_movw_movt_inst(ARMRelocator::DWord pValue,
+                                       ARMRelocator::DWord pImm)
+{
+  // imm16: [19-16][26][14-12][7-0]
+  pValue &= 0xfbf08f00U;
+  pValue |= (pImm & 0xf000U) << 4;
+  pValue |= (pImm & 0x0800U) << 15;
+  pValue |= (pImm & 0x0700U) << 4;
+  pValue |= (pImm & 0x00ffU);
+  return pValue;
+}
+
+static ARMRelocator::DWord
+helper_thumb32_branch_offset(ARMRelocator::DWord pUpper16,
+                             ARMRelocator::DWord pLower16)
+{
+  ARMRelocator::DWord s = (pUpper16 & (1U << 10)) >> 10,        // 26 bit
+                           u  = pUpper16 & 0x3ffU,              // 25-16
+                           l  = pLower16 & 0x7ffU,              // 10-0
+                           j1 = (pLower16 & (1U << 13)) >> 13,  // 13
+                           j2 = (pLower16 & (1U << 11)) >> 11;  // 11
+  ARMRelocator::DWord i1 = j1 ^ s? 0: 1,
+                              i2 = j2 ^ s? 0: 1;
+
+  // [31-25][24][23][22][21-12][11-1][0]
+  //      0   s  i1  i2      u     l  0
+  return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) |
+                            (u << 12) | (l << 1),
+                            25);
+}
+
+static ARMRelocator::DWord
+helper_thumb32_branch_upper(ARMRelocator::DWord pUpper16,
+                            ARMRelocator::DWord pOffset)
+{
+  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
+  return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10);
+}
+
+static ARMRelocator::DWord
+helper_thumb32_branch_lower(ARMRelocator::DWord pLower16,
+                            ARMRelocator::DWord pOffset)
+{
+  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
+  return ((pLower16 & ~0x2fffU) |
+          ((((pOffset >> 23) & 1) ^ !sign) << 13) |
+          ((((pOffset >> 22) & 1) ^ !sign) << 11) |
+          ((pOffset >> 1) & 0x7ffU));
+}
+
+static ARMRelocator::DWord
+helper_thumb32_cond_branch_offset(ARMRelocator::DWord pUpper16,
+                                  ARMRelocator::DWord pLower16)
+{
+  uint32_t s = (pUpper16 & 0x0400U) >> 10;
+  uint32_t j1 = (pLower16 & 0x2000U) >> 13;
+  uint32_t j2 = (pLower16 & 0x0800U) >> 11;
+  uint32_t lower = (pLower16 & 0x07ffU);
+  uint32_t upper = (s << 8) | (j2 << 7) | (j1 << 6) | (pUpper16 & 0x003fU);
+  return helper_sign_extend((upper << 12) | (lower << 1), 21);
+}
+
+static ARMRelocator::DWord
+helper_thumb32_cond_branch_upper(ARMRelocator::DWord pUpper16,
+                                 ARMRelocator::DWord pOffset)
+{
+  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
+  return (pUpper16 & 0xfbc0U) | (sign << 10) | ((pOffset & 0x0003f000U) >> 12);
+}
+
+static ARMRelocator::DWord
+helper_thumb32_cond_branch_lower(ARMRelocator::DWord pLower16,
+                                 ARMRelocator::DWord pOffset)
+{
+  uint32_t j2 = (pOffset & 0x00080000U) >> 19;
+  uint32_t j1 = (pOffset & 0x00040000U) >> 18;
+  uint32_t lo = (pOffset & 0x00000ffeU) >> 1;
+  return (pLower16 & 0xd000U) | (j1 << 13) | (j2 << 11) | lo;
+}
+
+// Return true if overflow
+static bool
+helper_check_signed_overflow(ARMRelocator::DWord pValue,
+                             unsigned bits)
+{
+  int32_t signed_val = static_cast<int32_t>(pValue);
+  int32_t max = (1 << (bits - 1)) - 1;
+  int32_t min = -(1 << (bits - 1));
+  if (signed_val > max || signed_val < min) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+
 //===--------------------------------------------------------------------===//
 // Relocation Functions and Tables
 //===--------------------------------------------------------------------===//
@@ -79,7 +371,7 @@
 
 void ARMRelocator::addCopyReloc(ResolveInfo& pSym)
 {
-  Relocation& rel_entry = *getTarget().getRelDyn().consumeEntry();
+  Relocation& rel_entry = *getTarget().getRelDyn().create();
   rel_entry.setType(llvm::ELF::R_ARM_COPY);
   assert(pSym.outSymbol()->hasFragRef());
   rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
@@ -188,7 +480,7 @@
       // a dynamic relocations with RELATIVE type to this location is needed.
       // Reserve an entry in .rel.dyn
       if (config().isCodeIndep()) {
-        getTarget().getRelDyn().reserveEntry();
+        helper_DynRel_init(pReloc, llvm::ELF::R_ARM_RELATIVE, *this);
         // set Rel bit
         rsym->setReserved(rsym->reserved() | ReserveRel);
         getTarget().checkAndSetHasTextRel(*pSection.getLink());
@@ -227,21 +519,17 @@
     case llvm::ELF::R_ARM_GOT_PREL: {
       // A GOT entry is needed for these relocation type.
       // return if we already create GOT for this symbol
-      if (rsym->reserved() & (ReserveGOT | GOTRel))
+      if (rsym->reserved() & ReserveGOT)
         return;
-      getTarget().getGOT().reserveGOT();
+
       // If building PIC object, a dynamic relocation with
       // type RELATIVE is needed to relocate this GOT entry.
-      // Reserve an entry in .rel.dyn
-      if (config().isCodeIndep()) {
-        // create .rel.dyn section if not exist
-        getTarget().getRelDyn().reserveEntry();
-        // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | 0x4u);
-        return;
-      }
+      if (config().isCodeIndep())
+         helper_GOT_init(pReloc, true, *this);
+      else
+         helper_GOT_init(pReloc, false, *this);
       // set GOT bit
-      rsym->setReserved(rsym->reserved() | 0x2u);
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
     }
 
@@ -301,18 +589,15 @@
         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 ARMPLT->reserveEntry())
-          getTarget().getPLT().reserveEntry();
-          getTarget().getRelPLT().reserveEntry();
+          // in .got and .rel.plt.
+          helper_PLT_init(pReloc, *this);
           // set PLT bit
           rsym->setReserved(rsym->reserved() | ReservePLT);
         }
       }
 
-      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
-        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
-        getTarget().getRelDyn().reserveEntry();
+      if (getTarget().symbolNeedsDynRel(*rsym,
+                                       (rsym->reserved() & ReservePLT), true)) {
         if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
@@ -320,6 +605,10 @@
         else {
           checkValidReloc(pReloc);
           // set Rel bit
+          if (helper_use_relative_reloc(*rsym, *this))
+            helper_DynRel_init(pReloc, llvm::ELF::R_ARM_RELATIVE, *this);
+          else
+            helper_DynRel_init(pReloc, pReloc.type(), *this);
           rsym->setReserved(rsym->reserved() | ReserveRel);
           getTarget().checkAndSetHasTextRel(*pSection.getLink());
         }
@@ -385,9 +674,9 @@
     case llvm::ELF::R_ARM_MOVT_BREL:
     case llvm::ELF::R_ARM_MOVW_BREL: {
       // Relative addressing relocation, may needs dynamic relocation
-      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) {
+      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                                                                       false)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
-        getTarget().getRelDyn().reserveEntry();
         if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
@@ -395,6 +684,7 @@
         else {
           checkValidReloc(pReloc);
           // set Rel bit
+          //helper_DynRel_init(pReloc, pReloc.type(), *this);
           rsym->setReserved(rsym->reserved() | ReserveRel);
           getTarget().checkAndSetHasTextRel(*pSection.getLink());
         }
@@ -434,10 +724,8 @@
 
       // 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 ARMPLT->reserveEntry())
-      getTarget().getPLT().reserveEntry();
-      getTarget().getRelPLT().reserveEntry();
+      // in .got and .rel.plt.
+      helper_PLT_init(pReloc, *this);
       // set PLT bit
       rsym->setReserved(rsym->reserved() | ReservePLT);
       return;
@@ -453,17 +741,14 @@
     case llvm::ELF::R_ARM_GOT_PREL: {
       // Symbol needs GOT entry, reserve entry in .got
       // return if we already create GOT for this symbol
-      if (rsym->reserved() & (ReserveGOT | GOTRel))
+      if (rsym->reserved() & ReserveGOT)
         return;
-      getTarget().getGOT().reserveGOT();
       // if the symbol cannot be fully resolved at link time, then we need a
       // dynamic relocation
-      if (!getTarget().symbolFinalValueIsKnown(*rsym)) {
-        getTarget().getRelDyn().reserveEntry();
-        // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | GOTRel);
-        return;
-      }
+      if (!getTarget().symbolFinalValueIsKnown(*rsym))
+        helper_GOT_init(pReloc, true, *this);
+      else
+        helper_GOT_init(pReloc, false, *this);
       // set GOT bit
       rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
@@ -487,14 +772,14 @@
 void ARMRelocator::scanRelocation(Relocation& pReloc,
                                   IRBuilder& pBuilder,
                                   Module& pModule,
-                                  LDSection& pSection)
+                                  LDSection& pSection,
+                                  Input& pInput)
 {
   // 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;
@@ -514,293 +799,9 @@
   // 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();
+    issueUndefRef(pReloc, pSection, pInput);
 }
 
-//===--------------------------------------------------------------------===//
-// non-member functions
-//===--------------------------------------------------------------------===//
-static Relocator::DWord getThumbBit(const Relocation& pReloc)
-{
-  // Set thumb bit if
-  // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
-  Relocator::DWord thumbBit =
-       ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
-        (pReloc.symInfo()->type() == ResolveInfo::Function) &&
-        ((pReloc.symValue() & 0x1) != 0))?
-        1:0;
-  return thumbBit;
-}
-
-//=========================================//
-// Relocation helper function              //
-//=========================================//
-
-// Using uint64_t to make sure those complicate operations won't cause
-// undefined behavior.
-static
-uint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width)
-{
-  assert(pOri_width <= 64);
-  if (pOri_width == 64)
-    return pVal;
-  uint64_t mask = (~((uint64_t)0)) >> (64 - pOri_width);
-  pVal &= mask;
-  // Reverse sign bit, then subtract sign bit.
-  uint64_t sign_bit = 1 << (pOri_width - 1);
-  return (pVal ^ sign_bit) - sign_bit;
-}
-
-static
-uint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask)
-{
-  return (pA & ~pMask) | (pB & pMask) ;
-}
-
-// Check if symbol can use relocation R_ARM_RELATIVE
-static bool
-helper_use_relative_reloc(const ResolveInfo& pSym,
-                          const ARMRelocator& pFactory)
-{
-  // if symbol is dynamic or undefine or preemptible
-  if (pSym.isDyn() ||
-      pSym.isUndef() ||
-      pFactory.getTarget().isSymbolPreemptible(pSym))
-    return false;
-  return true;
-}
-
-// Strip LSB (THUMB bit) if "S" is a THUMB target.
-static inline void helper_clear_thumb_bit(ARMRelocator::DWord& pValue)
-{
-  pValue &= (~0x1);
-}
-
-static
-ARMGOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
-                                     ARMRelocator& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  ARMGNULDBackend& ld_backend = pParent.getTarget();
-
-  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
-  if (NULL == got_entry) {
-    got_entry = ld_backend.getGOT().consumeGOT();
-    pParent.getSymGOTMap().record(*rsym, *got_entry);
-    // If we first get this GOT entry, we should initialize it.
-    if (rsym->reserved() & ARMRelocator::ReserveGOT) {
-      // No corresponding dynamic relocation, initialize to the symbol value.
-      got_entry->setValue(pReloc.symValue());
-    }
-    else if (rsym->reserved() & ARMRelocator::GOTRel) {
-
-      // Initialize corresponding dynamic relocation.
-      Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
-      if ( rsym->isLocal() ||
-          helper_use_relative_reloc(*rsym, pParent)) {
-        // Initialize got entry to target symbol address
-        got_entry->setValue(pReloc.symValue());
-        rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
-        rel_entry.setSymInfo(0);
-      }
-      else {
-        // Initialize got entry to 0 for corresponding dynamic relocation.
-        got_entry->setValue(0);
-        rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
-        rel_entry.setSymInfo(rsym);
-      }
-      rel_entry.targetRef().assign(*got_entry);
-    }
-    else {
-      fatal(diag::reserve_entry_number_mismatch_got);
-    }
-  }
-  return *got_entry;
-}
-
-static
-ARMRelocator::Address helper_GOT_ORG(ARMRelocator& pParent)
-{
-  return pParent.getTarget().getGOT().addr();
-}
-
-
-static
-ARMRelocator::Address helper_GOT(Relocation& pReloc, ARMRelocator& pParent)
-{
-  ARMGOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
-  return helper_GOT_ORG(pParent) + got_entry.getOffset();
-}
-
-
-static
-ARMPLT1& helper_get_PLT_and_init(Relocation& pReloc, ARMRelocator& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  ARMGNULDBackend& ld_backend = pParent.getTarget();
-
-  ARMPLT1* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
-  if (NULL != plt_entry)
-    return *plt_entry;
-
-  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() & ARMRelocator::ReservePLT) {
-    ARMGOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
-    assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
-    gotplt_entry = ld_backend.getGOT().consumeGOTPLT();
-    pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
-
-    // Initialize corresponding dynamic relocation.
-    Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
-    rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
-    rel_entry.targetRef().assign(*gotplt_entry);
-    rel_entry.setSymInfo(rsym);
-  }
-  else {
-    fatal(diag::reserve_entry_number_mismatch_plt);
-  }
-
-  return *plt_entry;
-}
-
-static
-ARMRelocator::Address helper_PLT_ORG(ARMRelocator& pParent)
-{
-  return pParent.getTarget().getPLT().addr();
-}
-
-
-static
-ARMRelocator::Address helper_PLT(Relocation& pReloc, ARMRelocator& pParent)
-{
-  ARMPLT1& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
-  return helper_PLT_ORG(pParent) + plt_entry.getOffset();
-}
-
-// Get an relocation entry in .rel.dyn and set its type to pType,
-// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to
-// pReloc->symInfo()
-static
-void helper_DynRel(Relocation& pReloc,
-                   ARMRelocator::Type pType,
-                   ARMRelocator& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  ARMGNULDBackend& ld_backend = pParent.getTarget();
-
-  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
-  rel_entry.setType(pType);
-  rel_entry.targetRef() = pReloc.targetRef();
-
-  if (pType == llvm::ELF::R_ARM_RELATIVE)
-    rel_entry.setSymInfo(0);
-  else
-    rel_entry.setSymInfo(rsym);
-}
-
-static ARMRelocator::DWord
-helper_extract_movw_movt_addend(ARMRelocator::DWord pTarget)
-{
-  // imm16: [19-16][11-0]
-  return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU),
-                            16);
-}
-
-static ARMRelocator::DWord
-helper_insert_val_movw_movt_inst(ARMRelocator::DWord pTarget,
-                                 ARMRelocator::DWord pImm)
-{
-  // imm16: [19-16][11-0]
-  pTarget &= 0xfff0f000U;
-  pTarget |= pImm & 0x0fffU;
-  pTarget |= (pImm & 0xf000U) << 4;
-  return pTarget;
-}
-
-static ARMRelocator::DWord
-helper_extract_thumb_movw_movt_addend(ARMRelocator::DWord pValue)
-{
-  // imm16: [19-16][26][14-12][7-0]
-  return helper_sign_extend((((pValue >> 4) & 0xf000U) |
-                             ((pValue >> 15) & 0x0800U) |
-                             ((pValue >> 4) & 0x0700U) |
-                             (pValue& 0x00ffU)),
-                            16);
-}
-
-static ARMRelocator::DWord
-helper_insert_val_thumb_movw_movt_inst(ARMRelocator::DWord pValue,
-                                       ARMRelocator::DWord pImm)
-{
-  // imm16: [19-16][26][14-12][7-0]
-  pValue &= 0xfbf08f00U;
-  pValue |= (pImm & 0xf000U) << 4;
-  pValue |= (pImm & 0x0800U) << 15;
-  pValue |= (pImm & 0x0700U) << 4;
-  pValue |= (pImm & 0x00ffU);
-  return pValue;
-}
-
-static ARMRelocator::DWord
-helper_thumb32_branch_offset(ARMRelocator::DWord pUpper16,
-                             ARMRelocator::DWord pLower16)
-{
-  ARMRelocator::DWord s = (pUpper16 & (1U << 10)) >> 10,        // 26 bit
-                           u  = pUpper16 & 0x3ffU,              // 25-16
-                           l  = pLower16 & 0x7ffU,              // 10-0
-                           j1 = (pLower16 & (1U << 13)) >> 13,  // 13
-                           j2 = (pLower16 & (1U << 11)) >> 11;  // 11
-  ARMRelocator::DWord i1 = j1 ^ s? 0: 1,
-                              i2 = j2 ^ s? 0: 1;
-
-  // [31-25][24][23][22][21-12][11-1][0]
-  //      0   s  i1  i2      u     l  0
-  return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) |
-                            (u << 12) | (l << 1),
-                            25);
-}
-
-static ARMRelocator::DWord
-helper_thumb32_branch_upper(ARMRelocator::DWord pUpper16,
-                            ARMRelocator::DWord pOffset)
-{
-  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
-  return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10);
-}
-
-static ARMRelocator::DWord
-helper_thumb32_branch_lower(ARMRelocator::DWord pLower16,
-                            ARMRelocator::DWord pOffset)
-{
-  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
-  return ((pLower16 & ~0x2fffU) |
-          ((((pOffset >> 23) & 1) ^ !sign) << 13) |
-          ((((pOffset >> 22) & 1) ^ !sign) << 11) |
-          ((pOffset >> 1) & 0x7ffU));
-}
-
-// Return true if overflow
-static bool
-helper_check_signed_overflow(ARMRelocator::DWord pValue,
-                             unsigned bits)
-{
-  int32_t signed_val = static_cast<int32_t>(pValue);
-  int32_t max = (1 << (bits - 1)) - 1;
-  int32_t min = -(1 << (bits - 1));
-  if (signed_val > max || signed_val < min) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-
 //=========================================//
 // Each relocation function implementation //
 //=========================================//
@@ -821,43 +822,28 @@
   if (T != 0x0)
     helper_clear_thumb_bit(S);
 
-  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())) {
+  if (0x0 == (llvm::ELF::SHF_ALLOC &
+      pReloc.targetRef().frag()->getParent()->getSection().flag())) {
     pReloc.target() = (S + A) | T;
     return ARMRelocator::OK;
   }
 
-  // A local symbol may need REL Type dynamic relocation
-  if (rsym->isLocal() && (rsym->reserved() & ARMRelocator::ReserveRel)) {
-    helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
-    pReloc.target() = (S + A) | T ;
-    return ARMRelocator::OK;
-  }
-
   // An external symbol may need PLT and dynamic relocation
   if (!rsym->isLocal()) {
     if (rsym->reserved() & ARMRelocator::ReservePLT) {
-      S = helper_PLT(pReloc, pParent);
+      S = helper_get_PLT_address(*rsym, pParent);
       T = 0 ; // PLT is not thumb
     }
     // If we generate a dynamic relocation (except R_ARM_RELATIVE)
     // for a place, we should not perform static relocation on it
     // in order to keep the addend store in the place correct.
-    if (rsym->reserved() & ARMRelocator::ReserveRel) {
-      if (helper_use_relative_reloc(*rsym, pParent)) {
-        helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
-      }
-      else {
-        helper_DynRel(pReloc, pReloc.type(), pParent);
-        return ARMRelocator::OK;
-      }
-    }
+    if ((rsym->reserved() & ARMRelocator::ReserveRel) &&
+        (!helper_use_relative_reloc(*rsym, pParent)))
+      return ARMRelocator::OK;
   }
 
-
   // perform static relocation
   pReloc.target() = (S + A) | T;
   return ARMRelocator::OK;
@@ -870,17 +856,18 @@
   ARMRelocator::Address S = pReloc.symValue();
   ARMRelocator::DWord   T = getThumbBit(pReloc);
   ARMRelocator::DWord   A = pReloc.target() + pReloc.addend();
-  if (T != 0x0)
-    helper_clear_thumb_bit(S);
 
-  // An external symbol may need PLT (this reloc is from stub)
+  // An external symbol may need PLT (this reloc is from a stub/veneer)
   if (!pReloc.symInfo()->isLocal()) {
     if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
-      S = helper_PLT(pReloc, pParent);
+      S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
       T = 0;  // PLT is not thumb.
     }
   }
 
+  if (T != 0x0)
+    helper_clear_thumb_bit(S);
+
   // perform relocation
   pReloc.target() = ((S + A) | T) - pReloc.place();
 
@@ -913,31 +900,41 @@
 // R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
 ARMRelocator::Result got_brel(Relocation& pReloc, ARMRelocator& pParent)
 {
-  if (!(pReloc.symInfo()->reserved() &
-      (ARMRelocator::ReserveGOT | ARMRelocator::GOTRel))) {
+  if (!(pReloc.symInfo()->reserved() & ARMRelocator::ReserveGOT))
     return ARMRelocator::BadReloc;
-  }
-  ARMRelocator::Address GOT_S   = helper_GOT(pReloc, pParent);
+
+  ARMRelocator::Address GOT_S   = helper_get_GOT_address(*pReloc.symInfo(),
+                                                                       pParent);
   ARMRelocator::DWord   A       = pReloc.target() + pReloc.addend();
   ARMRelocator::Address GOT_ORG = helper_GOT_ORG(pParent);
   // Apply relocation.
   pReloc.target() = GOT_S + A - GOT_ORG;
+
+  // setup got entry value if needed
+  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
+  if (NULL != got_entry && ARMRelocator::SymVal == got_entry->getValue())
+    got_entry->setValue(pReloc.symValue());
   return ARMRelocator::OK;
 }
 
 // R_ARM_GOT_PREL: GOT(S) + A - P
 ARMRelocator::Result got_prel(Relocation& pReloc, ARMRelocator& pParent)
 {
-  if (!(pReloc.symInfo()->reserved() &
-      (ARMRelocator::ReserveGOT | ARMRelocator::GOTRel))) {
+  if (!(pReloc.symInfo()->reserved() & ARMRelocator::ReserveGOT)) {
     return ARMRelocator::BadReloc;
   }
-  ARMRelocator::Address GOT_S   = helper_GOT(pReloc, pParent);
+  ARMRelocator::Address GOT_S   = helper_get_GOT_address(*pReloc.symInfo(),
+                                                                       pParent);
   ARMRelocator::DWord   A       = pReloc.target() + pReloc.addend();
   ARMRelocator::Address P = pReloc.place();
 
   // Apply relocation.
   pReloc.target() = GOT_S + A - P;
+
+  // setup got entry value if needed
+  ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
+  if (NULL != got_entry && ARMRelocator::SymVal == got_entry->getValue())
+    got_entry->setValue(pReloc.symValue());
   return ARMRelocator::OK;
 }
 
@@ -951,7 +948,7 @@
   // S depends on PLT exists or not
   ARMRelocator::Address S = pReloc.symValue();
   if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT)
-    S = helper_PLT(pReloc, pParent);
+    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
 
   ARMRelocator::DWord X = S + A - P;
   if (helper_check_signed_overflow(X, 11))
@@ -961,6 +958,48 @@
   return ARMRelocator::OK;
 }
 
+// R_ARM_THM_JUMP19: ((S + A) | T) - P
+ARMRelocator::Result thm_jump19(Relocation& pReloc, ARMRelocator& pParent)
+{
+  // get lower and upper 16 bit instructions from relocation targetData
+  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
+
+  ARMRelocator::DWord T = getThumbBit(pReloc);
+  ARMRelocator::DWord A = helper_thumb32_cond_branch_offset(upper_inst,
+                                                                    lower_inst);
+  ARMRelocator::Address P = pReloc.place();
+  ARMRelocator::Address S;
+  // if symbol has plt
+  if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
+    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
+    T = 0;  // PLT is not thumb.
+  }
+  else {
+    S = pReloc.symValue();
+    if (T != 0x0)
+      helper_clear_thumb_bit(S);
+  }
+
+  if (0x0 == T) {
+    // FIXME: conditional branch to PLT in THUMB-2 not supported yet
+    error(diag::unsupport_cond_branch_reloc) << (int)pReloc.type();
+    return ARMRelocator::BadReloc;
+  }
+
+  ARMRelocator::DWord X = ((S + A) | T) - P;
+  if (helper_check_signed_overflow(X, 21))
+    return ARMRelocator::Overflow;
+
+  upper_inst = helper_thumb32_cond_branch_upper(upper_inst, X);
+  lower_inst = helper_thumb32_cond_branch_lower(lower_inst, X);
+
+  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
+  return ARMRelocator::OK;
+}
+
 // R_ARM_PC24: ((S + A) | T) - P
 // R_ARM_PLT32: ((S + A) | T) - P
 // R_ARM_JUMP24: ((S + A) | T) - P
@@ -990,7 +1029,7 @@
 
   // S depends on PLT exists or not
   if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
-    S = helper_PLT(pReloc, pParent);
+    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
     T = 0;  // PLT is not thumb.
   }
 
@@ -1039,14 +1078,13 @@
   uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
 
   ARMRelocator::DWord T = getThumbBit(pReloc);
-  ARMRelocator::DWord A = helper_thumb32_branch_offset(upper_inst,
-                                                               lower_inst);
+  ARMRelocator::DWord A = helper_thumb32_branch_offset(upper_inst, lower_inst);
   ARMRelocator::Address P = pReloc.place();
   ARMRelocator::Address S;
 
   // if symbol has plt
   if (pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
-    S = helper_PLT(pReloc, pParent);
+    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
     T = 0;  // PLT is not thumb.
   }
   else {
@@ -1111,7 +1149,7 @@
   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
     // use plt
     if (rsym->reserved() & ARMRelocator::ReservePLT) {
-      S = helper_PLT(pReloc, pParent);
+      S = helper_get_PLT_address(*rsym, pParent);
       T = 0 ; // PLT is not thumb
     }
   }
@@ -1158,7 +1196,7 @@
   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
     // use plt
     if (rsym->reserved() & ARMRelocator::ReservePLT) {
-      S = helper_PLT(pReloc, pParent);
+      S = helper_get_PLT_address(*rsym, pParent);
     }
   }
 
@@ -1205,7 +1243,7 @@
   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
     // use plt
     if (rsym->reserved() & ARMRelocator::ReservePLT) {
-      S = helper_PLT(pReloc, pParent);
+      S = helper_get_PLT_address(*rsym, pParent);
       T = 0; // PLT is not thumb
     }
   }
@@ -1287,7 +1325,7 @@
   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
     // use plt
     if (rsym->reserved() & ARMRelocator::ReservePLT) {
-      S = helper_PLT(pReloc, pParent);
+      S = helper_get_PLT_address(*rsym, pParent);
     }
   }
 
@@ -1340,7 +1378,7 @@
 
   // if symbol has plt
   if ( pReloc.symInfo()->reserved() & ARMRelocator::ReservePLT) {
-    S = helper_PLT(pReloc, pParent);
+    S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
     T = 0;  // PLT is not thumb.
   }
 
diff --git a/lib/Target/ARM/ARMRelocator.h b/lib/Target/ARM/ARMRelocator.h
index bf93380..f1c4643 100644
--- a/lib/Target/ARM/ARMRelocator.h
+++ b/lib/Target/ARM/ARMRelocator.h
@@ -14,7 +14,7 @@
 
 #include <mcld/LD/Relocator.h>
 #include <mcld/Target/GOT.h>
-#include <mcld/Target/SymbolEntryMap.h>
+#include <mcld/Target/KeyEntryMap.h>
 #include "ARMLDBackend.h"
 
 namespace mcld {
@@ -26,50 +26,42 @@
 class ARMRelocator : public Relocator
 {
 public:
-  typedef SymbolEntryMap<ARMGOTEntry> SymGOTMap;
-  typedef SymbolEntryMap<ARMPLT1> SymPLTMap;
+  typedef KeyEntryMap<ResolveInfo, ARMGOTEntry> SymGOTMap;
+  typedef KeyEntryMap<ResolveInfo, ARMPLT1> SymPLTMap;
 
   /** \enum ReservedEntryType
    *  \brief The reserved entry type of reserved space in ResolveInfo.
    *
    *  This is used for sacnRelocation to record what kinds of entries are
-   *  reserved for this resolved symbol
+   *  reserved for this resolved symbol In ARM, there are three kinds of
+   *  entries, GOT, PLT, and dynamic reloction.
    *
-   *  In ARM, there are three kinds of entries, GOT, PLT, and dynamic reloction.
-   *  GOT may needs a corresponding relocation to relocate itself, so we
-   *  separate GOT to two situations: GOT and GOTRel. Besides, for the same
-   *  symbol, there might be two kinds of entries reserved for different location.
-   *  For example, reference to the same symbol, one may use GOT and the other may
-   *  use dynamic relocation.
-   *
-   *  bit:  3       2      1     0
-   *   | PLT | GOTRel | GOT | Rel |
+   *  bit:  3     2     1     0
+   *   |    | PLT | GOT | Rel |
    *
    *  value    Name         - Description
    *
    *  0000     None         - no reserved entry
    *  0001     ReserveRel   - reserve an dynamic relocation entry
    *  0010     ReserveGOT   - reserve an GOT entry
-   *  0011     GOTandRel    - For different relocation, we've reserved GOT and
-   *                          Rel for different location.
-   *  0100     GOTRel       - reserve an GOT entry and the corresponding Dyncamic
-   *                          relocation entry which relocate this GOT entry
-   *  0101     GOTRelandRel - For different relocation, we've reserved GOTRel
-   *                          and relocation entry for different location.
-   *  1000     ReservePLT   - reserve an PLT entry and the corresponding GOT,
-   *                          Dynamic relocation entries
-   *  1001     PLTandRel    - For different relocation, we've reserved PLT and
-   *                          Rel for different location.
+   *  0100     ReservePLT   - reserve an PLT entry and the corresponding GOT,
+   *
    */
   enum ReservedEntryType {
     None         = 0,
     ReserveRel   = 1,
     ReserveGOT   = 2,
-    GOTandRel    = 3,
-    GOTRel       = 4,
-    GOTRelandRel = 5,
-    ReservePLT   = 8,
-    PLTandRel    = 9
+    ReservePLT   = 4,
+  };
+
+  /** \enum EntryValue
+   *  \brief The value of the entries. The symbol value will be decided at after
+   *  layout, so we mark the entry during scanRelocation and fill up the actual
+   *  value when applying relocations.
+   */
+  enum EntryValue {
+    Default = 0,
+    SymVal  = 1
   };
 
 public:
@@ -106,7 +98,8 @@
   void scanRelocation(Relocation& pReloc,
                       IRBuilder& pBuilder,
                       Module& pModule,
-                      LDSection& pSection);
+                      LDSection& pSection,
+                      Input& pInput);
 
 private:
   void scanLocalReloc(Relocation& pReloc, const LDSection& pSection);
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index 7062f31..25caa56 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -11,14 +11,13 @@
 
 #include <mcld/Support/TargetRegistry.h>
 
-mcld::ARMBaseTargetMachine::ARMBaseTargetMachine(llvm::TargetMachine& pPM,
-                                                 const mcld::Target &pTarget,
-                                                 const std::string& pTriple)
-  : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
-}
+using namespace mcld;
 
-mcld::ARMBaseTargetMachine::~ARMBaseTargetMachine()
-{
+ARMBaseTargetMachine::ARMBaseTargetMachine(llvm::TargetMachine& pPM,
+                                           const llvm::Target &pLLVMTarget,
+                                           const mcld::Target &pMCLDTarget,
+                                           const std::string& pTriple)
+  : MCLDTargetMachine(pPM, pLLVMTarget, pMCLDTarget, pTriple) {
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index 94a7866..375f7b2 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -10,18 +10,17 @@
 #define MCLD_ARM_TARGET_MACHINE_H
 
 #include "ARM.h"
-#include <mcld/Target/TargetMachine.h>
+#include <mcld/CodeGen/TargetMachine.h>
 
 namespace mcld {
 
 class ARMBaseTargetMachine : public MCLDTargetMachine
 {
 public:
-  ARMBaseTargetMachine(llvm::TargetMachine &pTM,
-                       const mcld::Target &pTarget,
-                       const std::string &pTriple);
-
-  virtual ~ARMBaseTargetMachine();
+  ARMBaseTargetMachine(llvm::TargetMachine& pTM,
+                       const llvm::Target& pLLVMTarget,
+                       const mcld::Target& pMCLDTarget,
+                       const std::string& pTriple);
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
index fd00641..de43662 100644
--- a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
+++ b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Target/TargetMachine.h"
-#include "mcld/Support/TargetRegistry.h"
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Support/Target.h>
 
 namespace mcld {
 
@@ -16,8 +16,8 @@
 
 extern "C" void MCLDInitializeARMLDTargetInfo() {
   // register into mcld::TargetRegistry
-  mcld::RegisterTarget X(TheARMTarget, "arm" );
-  mcld::RegisterTarget Y(TheThumbTarget, "thumb" );
+  mcld::RegisterTarget<llvm::Triple::arm> X(TheARMTarget, "arm");
+  mcld::RegisterTarget<llvm::Triple::thumb> Y(TheThumbTarget, "thumb");
 }
 
 } // namespace of mcld
diff --git a/lib/Target/Android.mk b/lib/Target/Android.mk
index 77ab932..e46a09f 100644
--- a/lib/Target/Android.mk
+++ b/lib/Target/Android.mk
@@ -1,15 +1,17 @@
 LOCAL_PATH:= $(call my-dir)
 
 mcld_target_SRC_FILES := \
-  ELFDynamic.cpp  \
-  ELFEmulation.cpp  \
-  ELFMCLinker.cpp  \
+  ELFAttribute.cpp \
+  ELFAttributeData.cpp \
+  ELFAttributeValue.cpp \
+  ELFDynamic.cpp \
+  ELFEmulation.cpp \
+  ELFMCLinker.cpp \
   GNUInfo.cpp \
-  GNULDBackend.cpp  \
+  GNULDBackend.cpp \
   GOT.cpp \
-  OutputRelocSection.cpp  \
+  OutputRelocSection.cpp \
   PLT.cpp \
-  Target.cpp  \
   TargetLDBackend.cpp
 
 # For the host
diff --git a/lib/Target/ELFAttribute.cpp b/lib/Target/ELFAttribute.cpp
new file mode 100644
index 0000000..76882d3
--- /dev/null
+++ b/lib/Target/ELFAttribute.cpp
@@ -0,0 +1,364 @@
+//===- ELFAttribute.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Target/ELFAttribute.h>
+
+#include <mcld/ADT/SizeTraits.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/Input.h>
+#include <mcld/Support/LEB128.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/ELFAttributeValue.h>
+#include <mcld/Target/GNULDBackend.h>
+
+#include <llvm/ADT/STLExtras.h>
+#include <llvm/Support/Host.h>
+
+#include <cstring>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ELFAttribute
+//===----------------------------------------------------------------------===//
+ELFAttribute::~ELFAttribute()
+{
+  llvm::DeleteContainerPointers(m_Subsections);
+  return;
+}
+
+bool ELFAttribute::merge(const Input &pInput, LDSection &pInputAttrSectHdr)
+{
+  // Skip corrupt subsection
+  if (pInputAttrSectHdr.size() < MinimalELFAttributeSectionSize)
+    return true;
+
+  // Obtain the region containing the attribute data. Expect exactly one
+  // RegionFragment in the section data.
+  const SectionData* sect_data = pInputAttrSectHdr.getSectionData();
+
+  // FIXME: Why is 2?
+  if ((sect_data->size() != 2) ||
+      (!llvm::isa<RegionFragment>(sect_data->front()))) {
+    return true;
+  }
+
+  const RegionFragment& region_frag =
+      llvm::cast<RegionFragment>(sect_data->front());
+
+  llvm::StringRef region = region_frag.getRegion();
+
+  // Parse the ELF attribute section header. ARM [ABI-addenda], 2.2.3.
+  //
+  // <format-version: ‘A’>
+  // [ <uint32: subsection-length> NTBS: vendor-name
+  //   <bytes: vendor-data>
+  // ]*
+  const char *attribute_data = region.begin();
+
+  // format-version
+  if (attribute_data[0] != FormatVersion) {
+    warning(diag::warn_unsupported_attribute_section_format)
+        << pInput.name() << attribute_data[0];
+    return true;
+  }
+
+  size_t subsection_offset = FormatVersionFieldSize;
+
+  // Iterate all subsections containing in this attribute section.
+  do {
+    const char *subsection_data = region.begin() + subsection_offset;
+
+    // subsection-length
+    uint32_t subsection_length =
+        *reinterpret_cast<const uint32_t*>(subsection_data);
+
+    if(llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian())
+      bswap32(subsection_length);
+
+    // vendor-name
+    const char* vendor_name = subsection_data + SubsectionLengthFieldSize;
+    const size_t vendor_name_length = ::strlen(vendor_name) + 1 /* '\0' */;
+
+    // Check the length.
+    if ((vendor_name_length <= 1) ||
+        (subsection_length <= (SubsectionLengthFieldSize + vendor_name_length)))
+      return true;
+
+    // Select the attribute subsection.
+    Subsection *subsection = getSubsection(vendor_name);
+
+    // Only process the subsections whose vendor can be recognized.
+    if (subsection == NULL) {
+      warning(diag::warn_unrecognized_vendor_subsection)
+          << vendor_name << pInput.name();
+    } else {
+      // vendor-data
+      size_t vendor_data_offset = subsection_offset +
+                                  SubsectionLengthFieldSize +
+                                  vendor_name_length;
+      size_t vendor_data_size = subsection_length - SubsectionLengthFieldSize -
+                                vendor_name_length;
+
+      ConstAddress vendor_data =
+          reinterpret_cast<ConstAddress>(region.begin()) + vendor_data_offset;
+
+      // Merge the vendor data in the subsection.
+      if (!subsection->merge(pInput, vendor_data, vendor_data_size))
+        return false;
+    }
+
+    subsection_offset += subsection_length;
+  } while ((subsection_offset + SubsectionLengthFieldSize) < pInputAttrSectHdr.size());
+
+  return true;
+}
+
+size_t ELFAttribute::sizeOutput() const
+{
+  size_t total_size = FormatVersionFieldSize;
+
+  for (llvm::SmallVectorImpl<Subsection*>::const_iterator
+          subsec_it = m_Subsections.begin(), subsec_end = m_Subsections.end();
+       subsec_it != subsec_end; ++subsec_it) {
+    total_size += (*subsec_it)->sizeOutput();
+  }
+  return total_size;
+}
+
+size_t ELFAttribute::emit(MemoryRegion &pRegion) const
+{
+  // ARM [ABI-addenda], 2.2.3
+  uint64_t total_size = 0;
+
+  // Write format-version.
+  char* buffer = reinterpret_cast<char*>(pRegion.begin());
+  buffer[0] = FormatVersion;
+  total_size += FormatVersionFieldSize;
+
+  for (llvm::SmallVectorImpl<Subsection*>::const_iterator
+          subsec_it = m_Subsections.begin(), subsec_end = m_Subsections.end();
+       subsec_it != subsec_end; ++subsec_it) {
+    // Write out subsection.
+    total_size += (*subsec_it)->emit(buffer + total_size);
+  }
+
+  return total_size;
+}
+
+void ELFAttribute::registerAttributeData(ELFAttributeData& pAttrData)
+{
+  assert((getSubsection(pAttrData.getVendorName()) == NULL) &&
+         "Multiple attribute data for a vendor!");
+  m_Subsections.push_back(new Subsection(*this, pAttrData));
+  return;
+}
+
+ELFAttribute::Subsection *
+ELFAttribute::getSubsection(llvm::StringRef pVendorName) const
+{
+  // Search m_Subsections linearly.
+  for (llvm::SmallVectorImpl<Subsection*>::const_iterator
+          subsec_it = m_Subsections.begin(), subsec_end = m_Subsections.end();
+       subsec_it != subsec_end; ++subsec_it) {
+    Subsection* const subsection = *subsec_it;
+    if (subsection->isMyAttribute(pVendorName)) {
+      return subsection;
+    }
+  }
+
+  // Not found
+  return NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// ELFAttribute::Subsection
+//===----------------------------------------------------------------------===//
+bool ELFAttribute::Subsection::merge(const Input &pInput,
+                                     ConstAddress pData,
+                                     size_t pSize)
+{
+  const bool need_swap = (llvm::sys::IsLittleEndianHost !=
+                              m_Parent.config().targets().isLittleEndian());
+  // Read attribute sub-subsection from vendor data.
+  //
+  // ARM [ABI-addenda], 2.2.4:
+  //
+  // [   Tag_File    (=1) <uint32: byte-size> <attribute>*
+  //   | Tag_Section (=2) <uint32: byte-size> <section number>* 0 <attribute>*
+  //   | Tag_symbol  (=3) <unit32: byte-size> <symbol number>* 0 <attribute>*
+  // ] +
+  const char *subsubsection_data = reinterpret_cast<const char*>(pData);
+  size_t remaining_size = pSize;
+
+  if (!m_AttrData.preMerge(pInput)) {
+    return false;
+  }
+
+  while (remaining_size > ELFAttribute::MinimalELFAttributeSubsectionSize) {
+    // The tag of sub-subsection is encoded in ULEB128.
+    size_t tag_size;
+    uint64_t tag = leb128::decode<uint64_t>(subsubsection_data, tag_size);
+
+    if ((tag_size + 4 /* byte-size */) >= remaining_size)
+      break;
+
+    size_t subsubsection_length =
+        *reinterpret_cast<const uint32_t*>(subsubsection_data + tag_size);
+
+    if (need_swap)
+      bswap32(subsubsection_length);
+
+    if (subsubsection_length > remaining_size) {
+      // The subsubsection is corrupted. Try our best to process it.
+      subsubsection_length = remaining_size;
+    }
+
+    switch (tag) {
+      case ELFAttributeData::Tag_File: {
+        ELFAttributeData::TagType tag;
+        ELFAttributeValue in_attr;
+        // The offset from the start of sub-subsection that <attribute> located
+        size_t attribute_offset = tag_size + 4 /* byte-size */;
+
+        const char* attr_buf = subsubsection_data + attribute_offset;
+        size_t attr_size = subsubsection_length - attribute_offset;
+
+        // Read attributes from the stream.
+        do {
+          if (!ELFAttributeData::ReadTag(tag, attr_buf, attr_size))
+            break;
+
+          ELFAttributeValue *out_attr;
+          bool is_newly_created;
+
+          llvm::tie(out_attr, is_newly_created) =
+              m_AttrData.getOrCreateAttributeValue(tag);
+
+          assert(out_attr != NULL);
+
+          if (is_newly_created) {
+            // Directly read the attribute value to the out_attr.
+            if (!ELFAttributeData::ReadValue(*out_attr, attr_buf, attr_size))
+              break;
+          } else {
+            // The attribute has been defined previously. Read the attribute
+            // to a temporary storage in_attr and perform the merge.
+            in_attr.reset();
+            in_attr.setType(out_attr->type());
+
+            // Read the attribute value.
+            if (!ELFAttributeData::ReadValue(in_attr, attr_buf, attr_size))
+              break;
+
+            // Merge if the read attribute value is different than current one
+            // in output.
+            if ((in_attr != *out_attr) &&
+                !m_AttrData.merge(m_Parent.config(), pInput, tag, in_attr)) {
+              // Fail to merge the attribute.
+              return false;
+            }
+          }
+        } while (attr_size > 0);
+
+        break;
+      }
+      // Skip sub-subsection tagged with Tag_Section and Tag_Symbol. They are
+      // deprecated since ARM [ABI-addenda] r2.09.
+      case ELFAttributeData::Tag_Section:
+      case ELFAttributeData::Tag_Symbol:
+      // Skip any unknown tags.
+      default: {
+        break;
+      }
+    }
+
+    // Update subsubsection_data and remaining_size for next.
+    subsubsection_data += subsubsection_length;
+    remaining_size -= subsubsection_length;
+  } // while (remaining_size > ELFAttribute::MinimalELFAttributeSubsectionSize)
+
+  return m_AttrData.postMerge(m_Parent.config(), pInput);
+}
+
+size_t ELFAttribute::Subsection::sizeOutput() const
+{
+  // ARM [ABI-addenda], 2.2.3 and 2.2.4
+  return ELFAttribute::SubsectionLengthFieldSize +
+            m_AttrData.getVendorName().length() /* vendor-name */ +
+            1 /* NULL-terminator for vendor-name */ +
+            1 /* Tag_File */ +
+            sizeof(uint32_t) /* length of sub-subsection */ +
+            m_AttrData.sizeOutput();
+}
+
+size_t ELFAttribute::Subsection::emit(char *pBuf) const
+{
+  // ARM [ABI-addenda], 2.2.3 and 2.2.4
+  const bool need_swap = (llvm::sys::IsLittleEndianHost !=
+                              m_Parent.config().targets().isLittleEndian());
+
+  char *buffer = pBuf;
+
+  // The subsection-length and byte-size field in sub-subsection will be patched
+  // later after writing out all attribute data.
+  char *subsection_length_hole = NULL;
+  char *subsubsection_length_hole = NULL;
+
+  // Reserve space for subsection-length.
+  subsection_length_hole = buffer;
+  buffer += 4;
+
+  // Write vendor-name.
+  const std::string &vendor_name = m_AttrData.getVendorName();
+  ::memcpy(buffer, vendor_name.c_str(), vendor_name.length());
+  buffer += vendor_name.length();
+
+  // Write NULL-terminator for vendor-name.
+  *buffer++ = '\0';
+
+  // Write Tag_File (0x01).
+  *buffer++ = '\x01';
+
+  // Reserve space for byte-size for sub-subsection.
+  subsubsection_length_hole = buffer;
+  buffer += sizeof(uint32_t);
+
+  // Write attribute data.
+  uint32_t subsubsection_length = m_AttrData.emit(buffer);
+
+  // Calculate value of subsection-length.
+  uint32_t subsection_length = (buffer - pBuf) + subsubsection_length;
+
+  // ARM [ABI-addenda] 2.2.4
+  //
+  // The byte-size in sub-subsection includes Tag_File (1-byte) and the size
+  // field of itself (4-byte).
+  subsubsection_length += 1 /* Tag_File */ + 4 /* size of byte-size */;
+
+  // Patch subsubsection_length_hole.
+  assert(subsubsection_length_hole != NULL);
+
+  if(need_swap)
+    bswap32(subsubsection_length);
+
+  ::memcpy(subsubsection_length_hole, &subsubsection_length, sizeof(uint32_t));
+
+  // Write subsection-length in subsection_length_hole.
+  if(need_swap)
+    bswap32(subsection_length);
+
+  assert(subsection_length_hole != NULL);
+  ::memcpy(subsection_length_hole, &subsection_length, sizeof(uint32_t));
+
+  return subsection_length;
+}
diff --git a/lib/Target/ELFAttributeData.cpp b/lib/Target/ELFAttributeData.cpp
new file mode 100644
index 0000000..c41918b
--- /dev/null
+++ b/lib/Target/ELFAttributeData.cpp
@@ -0,0 +1,88 @@
+//===- ELFAttributeData.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Target/ELFAttributeData.h>
+
+#include <mcld/Support/LEB128.h>
+#include <mcld/Target/ELFAttributeValue.h>
+#include <cstring>
+#include <cassert>
+
+using namespace mcld;
+
+bool ELFAttributeData::ReadTag(TagType& pTag, const char* &pBuf,
+                               size_t &pBufSize)
+{
+  size_t size = 0;
+
+  pTag = static_cast<ELFAttributeData::TagType>(
+            leb128::decode<uint64_t>(pBuf, size));
+
+  if (size > pBufSize)
+    return false;
+
+  pBuf += size;
+  pBufSize -= size;
+
+  return true;
+}
+
+bool ELFAttributeData::ReadValue(ELFAttributeValue& pValue, const char* &pBuf,
+                                 size_t &pBufSize)
+{
+  // An ULEB128-encoded value
+  if (pValue.isIntValue()) {
+    size_t size = 0;
+    uint64_t int_value = leb128::decode<uint64_t>(pBuf, size);
+    pValue.setIntValue(static_cast<unsigned int>(int_value));
+
+    if (size > pBufSize)
+      return false;
+
+    pBuf += size;
+    pBufSize -= size;
+  }
+
+  // A null-terminated byte string
+  if (pValue.isStringValue()) {
+    pValue.setStringValue(pBuf);
+
+    size_t size = pValue.getStringValue().length() + 1 /* '\0' */;
+    assert(size <= pBufSize);
+    pBuf += size;
+    pBufSize -= size;
+  }
+
+  return true;
+}
+
+bool ELFAttributeData::WriteAttribute(TagType pTag,
+                                      const ELFAttributeValue& pValue,
+                                      char* &pBuf)
+{
+  // Write the attribute tag.
+  leb128::encode<uint32_t>(pBuf, pTag);
+
+  // Write the attribute value.
+  if (pValue.isIntValue())
+    leb128::encode<uint32_t>(pBuf, pValue.getIntValue());
+
+  if (pValue.isStringValue()) {
+    // Write string data.
+    size_t str_val_len = pValue.getStringValue().length();
+
+    if (str_val_len > 0)
+      ::memcpy(pBuf, pValue.getStringValue().c_str(), str_val_len);
+    pBuf += str_val_len;
+
+    // Write NULL-terminator.
+    *pBuf++ = '\0';
+  }
+
+  return true;
+}
diff --git a/lib/Target/ELFAttributeValue.cpp b/lib/Target/ELFAttributeValue.cpp
new file mode 100644
index 0000000..0f99325
--- /dev/null
+++ b/lib/Target/ELFAttributeValue.cpp
@@ -0,0 +1,66 @@
+//===- ELFAttributeValue.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/Target/ELFAttributeValue.h>
+
+#include <llvm/Support/ErrorHandling.h>
+
+#include <mcld/Support/LEB128.h>
+
+using namespace mcld;
+
+size_t ELFAttributeValue::getSize() const
+{
+  size_t size = 0;
+
+  if (isIntValue())
+    size += leb128::size<uint32_t>(m_IntValue);
+
+  if (isStringValue())
+    size += m_StringValue.length() + 1 /* for NULL-terminator */;
+
+  if (size <= 0)
+    // unknown type of the value
+    llvm::report_fatal_error("Unknown type of attribtue value!");
+
+  return size;
+}
+
+bool ELFAttributeValue::isDefaultValue() const
+{
+  if (isUninitialized()) {
+    // Uninitialized attribute means default value
+    return true;
+  } else {
+    if (isIntValue() && (m_IntValue != 0))
+      return false;
+    if (isStringValue() && !m_StringValue.empty())
+      return false;
+
+    // The value hold in the storage is the "default value by default" (i.e., 0
+    // for int type, empty string for string type), but we need to check whether
+    // the "default value" is defined (that is, hasNoDefault() = false.)
+    return !hasNoDefault();
+  }
+  // unreachable
+}
+
+bool ELFAttributeValue::equals(const ELFAttributeValue& pValue) const
+{
+  if ((pValue.type() != m_Type) || isUninitialized())
+    return false;
+
+  if (isIntValue() && (m_IntValue != pValue.getIntValue()))
+    return false;
+
+  if (isStringValue() && (m_StringValue != pValue.getStringValue()))
+    return false;
+
+  return true;
+}
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
index aeccd92..25c56c1 100644
--- a/lib/Target/ELFDynamic.cpp
+++ b/lib/Target/ELFDynamic.cpp
@@ -12,7 +12,6 @@
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/LD/ELFFileFormat.h>
 #include <mcld/LinkerConfig.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
@@ -140,10 +139,8 @@
 
   reserveTargetEntries(pFormat); // DT_PLTGOT
 
-  if (pFormat.hasRelPlt() || pFormat.hasRelaPlt())
+  if (pFormat.hasRelPlt() || pFormat.hasRelaPlt()) {
     reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL
-
-  if (pFormat.hasPLT()) {
     reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL
     reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ
   }
@@ -343,7 +340,7 @@
                              llvm::Twine(" than the section's demaind.\n"));
   }
 
-  uint8_t* address = (uint8_t*)pRegion.start();
+  uint8_t* address = (uint8_t*)pRegion.begin();
   EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
   for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
     address += (*entry)->emit(address);
diff --git a/lib/Target/ELFEmulation.cpp b/lib/Target/ELFEmulation.cpp
index ff4a757..a68e485 100644
--- a/lib/Target/ELFEmulation.cpp
+++ b/lib/Target/ELFEmulation.cpp
@@ -9,6 +9,7 @@
 #include <mcld/Target/ELFEmulation.h>
 #include <mcld/LinkerScript.h>
 #include <mcld/LinkerConfig.h>
+#include <mcld/Script/InputSectDesc.h>
 
 #include <llvm/Support/Host.h>
 
@@ -17,63 +18,73 @@
 struct NameMap {
   const char* from; ///< the prefix of the input string. (match FROM*)
   const char* to;   ///< the output string.
+  InputSectDesc::KeepPolicy policy; /// mark whether the input is kept in GC
 };
 
 static const NameMap map[] =
 {
-  {".text", ".text"},
-  {".rodata", ".rodata"},
-  {".data.rel.ro.local", ".data.rel.ro.local"},
-  {".data.rel.ro", ".data.rel.ro"},
-  {".data", ".data"},
-  {".bss", ".bss"},
-  {".tdata", ".tdata"},
-  {".tbss", ".tbss"},
-  {".init_array", ".init_array"},
-  {".fini_array", ".fini_array"},
+  {".text*", ".text", InputSectDesc::NoKeep},
+  {".rodata*", ".rodata", InputSectDesc::NoKeep},
+  {".data.rel.ro.local*", ".data.rel.ro.local", InputSectDesc::NoKeep},
+  {".data.rel.ro*", ".data.rel.ro", InputSectDesc::NoKeep},
+  {".data*", ".data", InputSectDesc::NoKeep},
+  {".bss*", ".bss", InputSectDesc::NoKeep},
+  {".tdata*", ".tdata", InputSectDesc::NoKeep},
+  {".tbss*", ".tbss", InputSectDesc::NoKeep},
+  {".init", ".init", InputSectDesc::Keep},
+  {".fini", ".fini", InputSectDesc::Keep},
+  {".preinit_array*", ".preinit_array", InputSectDesc::Keep},
+  {".init_array*", ".init_array", InputSectDesc::Keep},
+  {".fini_array*", ".fini_array", InputSectDesc::Keep},
   // TODO: Support DT_INIT_ARRAY for all constructors?
-  {".ctors", ".ctors"},
-  {".dtors", ".dtors"},
+  {".ctors*", ".ctors", InputSectDesc::Keep},
+  {".dtors*", ".dtors", InputSectDesc::Keep},
+  {".jcr", ".jcr", InputSectDesc::Keep},
   // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
   // sections would be handled differently.
-  {".sdata2", ".sdata"},
-  {".sbss2", ".sbss"},
-  {".sdata", ".sdata"},
-  {".sbss", ".sbss"},
-  {".lrodata", ".lrodata"},
-  {".ldata", ".ldata"},
-  {".lbss", ".lbss"},
-  {".gcc_except_table", ".gcc_except_table"},
-  {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
-  {".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
-  {".gnu.linkonce.r", ".rodata"},
-  {".gnu.linkonce.d", ".data"},
-  {".gnu.linkonce.b", ".bss"},
-  {".gnu.linkonce.sb2", ".sbss"},
-  {".gnu.linkonce.sb", ".sbss"},
-  {".gnu.linkonce.s2", ".sdata"},
-  {".gnu.linkonce.s", ".sdata"},
-  {".gnu.linkonce.wi", ".debug_info"},
-  {".gnu.linkonce.td", ".tdata"},
-  {".gnu.linkonce.tb", ".tbss"},
-  {".gnu.linkonce.t", ".text"},
-  {".gnu.linkonce.lr", ".lrodata"},
-  {".gnu.linkonce.lb", ".lbss"},
-  {".gnu.linkonce.l", ".ldata"},
+  {".sdata2*", ".sdata", InputSectDesc::NoKeep},
+  {".sbss2*", ".sbss", InputSectDesc::NoKeep},
+  {".sdata*", ".sdata", InputSectDesc::NoKeep},
+  {".sbss*", ".sbss", InputSectDesc::NoKeep},
+  {".lrodata*", ".lrodata", InputSectDesc::NoKeep},
+  {".ldata*", ".ldata", InputSectDesc::NoKeep},
+  {".lbss*", ".lbss", InputSectDesc::NoKeep},
+  {".gcc_except_table*", ".gcc_except_table", InputSectDesc::Keep},
+  {".gnu.linkonce.d.rel.ro.local*", ".data.rel.ro.local", InputSectDesc::NoKeep},
+  {".gnu.linkonce.d.rel.ro*", ".data.rel.ro", InputSectDesc::NoKeep},
+  {".gnu.linkonce.r*", ".rodata", InputSectDesc::NoKeep},
+  {".gnu.linkonce.d*", ".data", InputSectDesc::NoKeep},
+  {".gnu.linkonce.b*", ".bss", InputSectDesc::NoKeep},
+  {".gnu.linkonce.sb2*", ".sbss", InputSectDesc::NoKeep},
+  {".gnu.linkonce.sb*", ".sbss", InputSectDesc::NoKeep},
+  {".gnu.linkonce.s2*", ".sdata", InputSectDesc::NoKeep},
+  {".gnu.linkonce.s*", ".sdata", InputSectDesc::NoKeep},
+  {".gnu.linkonce.wi*", ".debug_info", InputSectDesc::NoKeep},
+  {".gnu.linkonce.td*", ".tdata", InputSectDesc::NoKeep},
+  {".gnu.linkonce.tb*", ".tbss", InputSectDesc::NoKeep},
+  {".gnu.linkonce.t*", ".text", InputSectDesc::NoKeep},
+  {".gnu.linkonce.lr*", ".lrodata", InputSectDesc::NoKeep},
+  {".gnu.linkonce.lb*", ".lbss", InputSectDesc::NoKeep},
+  {".gnu.linkonce.l*", ".ldata", InputSectDesc::NoKeep},
 };
 
 bool mcld::MCLDEmulateELF(LinkerScript& pScript, LinkerConfig& pConfig)
 // FIXME: LinkerConfig& pConfig should be constant
 {
   // set up section map
-  if (pConfig.codeGenType() != LinkerConfig::Object) {
+  if (pConfig.options().getScriptList().empty() &&
+      pConfig.codeGenType() != LinkerConfig::Object) {
     const unsigned int map_size =  (sizeof(map) / sizeof(map[0]) );
     for (unsigned int i = 0; i < map_size; ++i) {
-      bool exist = false;
-      pScript.sectionMap().append(map[i].from, map[i].to, exist);
-      if (exist)
+      std::pair<SectionMap::mapping, bool> res =
+        pScript.sectionMap().insert(map[i].from, map[i].to, map[i].policy);
+      if (!res.second)
         return false;
     }
+  } else {
+    // FIXME: this is the hack to help assignment processing in current
+    // implementation.
+    pScript.sectionMap().insert("", "");
   }
 
   if (!pConfig.options().nostdlib()) {
diff --git a/lib/Target/ELFMCLinker.cpp b/lib/Target/ELFMCLinker.cpp
index 3fa9b90..fae5c8c 100644
--- a/lib/Target/ELFMCLinker.cpp
+++ b/lib/Target/ELFMCLinker.cpp
@@ -7,9 +7,6 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/Target/ELFMCLinker.h>
-#include <mcld/LinkerConfig.h>
-#include <mcld/Object/SectionMap.h>
-#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
@@ -18,8 +15,8 @@
 //===----------------------------------------------------------------------===//
 ELFMCLinker::ELFMCLinker(LinkerConfig& pConfig,
                          mcld::Module& pModule,
-                         MemoryArea& pOutput)
-  : MCLinker(pConfig, pModule, pOutput) {
+                         FileHandle& pFileHandle)
+  : MCLinker(pConfig, pModule, pFileHandle) {
 
 }
 
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
index c624f14..796c93e 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -17,25 +17,39 @@
 
 #include <mcld/Module.h>
 #include <mcld/LinkerConfig.h>
+#include <mcld/LinkerScript.h>
 #include <mcld/IRBuilder.h>
 #include <mcld/InputTree.h>
 #include <mcld/Config/Config.h>
 #include <mcld/ADT/SizeTraits.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/LDContext.h>
-#include <mcld/Fragment/FillFragment.h>
 #include <mcld/LD/EhFrame.h>
 #include <mcld/LD/EhFrameHdr.h>
 #include <mcld/LD/RelocData.h>
 #include <mcld/LD/RelocationFactory.h>
-#include <mcld/MC/Attribute.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/MemoryAreaFactory.h>
 #include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/ELFSegment.h>
 #include <mcld/LD/StubFactory.h>
+#include <mcld/LD/ELFFileFormat.h>
+#include <mcld/LD/ELFObjectFileFormat.h>
+#include <mcld/LD/ELFDynObjFileFormat.h>
+#include <mcld/LD/ELFExecFileFormat.h>
+#include <mcld/Target/ELFAttribute.h>
+#include <mcld/Target/ELFDynamic.h>
+#include <mcld/Target/GNUInfo.h>
+#include <mcld/Support/FileOutputBuffer.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Object/ObjectBuilder.h>
+#include <mcld/Object/SectionMap.h>
+#include <mcld/Script/RpnEvaluator.h>
+#include <mcld/Script/Operand.h>
+#include <mcld/Script/OutputSectDesc.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/MC/Attribute.h>
+
+#include <llvm/Support/Host.h>
 
 namespace {
 
@@ -69,10 +83,11 @@
     m_pExecFileFormat(NULL),
     m_pObjectFileFormat(NULL),
     m_pInfo(pInfo),
-    m_ELFSegmentTable(9), // magic number
+    m_pELFSegmentTable(NULL),
     m_pBRIslandFactory(NULL),
     m_pStubFactory(NULL),
     m_pEhFrameHdr(NULL),
+    m_pAttribute(NULL),
     m_bHasTextRel(false),
     m_bHasStaticTLS(false),
     f_pPreInitArrayStart(NULL),
@@ -94,17 +109,21 @@
     f_pBSSStart(NULL),
     f_pEnd(NULL),
     f_p_End(NULL) {
+  m_pELFSegmentTable = new ELFSegmentFactory();
   m_pSymIndexMap = new HashTableType(1024);
+  m_pAttribute = new ELFAttribute(*this, pConfig);
 }
 
 GNULDBackend::~GNULDBackend()
 {
+  delete m_pELFSegmentTable;
   delete m_pInfo;
   delete m_pDynObjFileFormat;
   delete m_pExecFileFormat;
   delete m_pObjectFileFormat;
   delete m_pSymIndexMap;
   delete m_pEhFrameHdr;
+  delete m_pAttribute;
   delete m_pBRIslandFactory;
   delete m_pStubFactory;
 }
@@ -117,10 +136,10 @@
   switch (config().targets().bitclass()) {
     case 32u:
       return sizeof(llvm::ELF::Elf32_Ehdr) +
-             numOfSegments() * sizeof(llvm::ELF::Elf32_Phdr);
+             elfSegmentTable().size() * sizeof(llvm::ELF::Elf32_Phdr);
     case 64u:
       return sizeof(llvm::ELF::Elf64_Ehdr) +
-             numOfSegments() * sizeof(llvm::ELF::Elf64_Phdr);
+             elfSegmentTable().size() * sizeof(llvm::ELF::Elf64_Phdr);
     default:
       fatal(diag::unsupported_bitclass) << config().targets().triple().str()
                                         << config().targets().bitclass();
@@ -160,7 +179,7 @@
 
 ELFBinaryReader* GNULDBackend::createBinaryReader(IRBuilder& pBuilder)
 {
-  return new ELFBinaryReader(*this, pBuilder, config());
+  return new ELFBinaryReader(pBuilder, config());
 }
 
 ELFObjectWriter* GNULDBackend::createWriter()
@@ -572,11 +591,12 @@
 
   // -----  segment symbols  ----- //
   if (NULL != f_pExecutableStart) {
-    ELFSegment* exec_start = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD, 0x0, 0x0);
-    if (NULL != exec_start) {
+    ELFSegmentFactory::const_iterator exec_start =
+      elfSegmentTable().find(llvm::ELF::PT_LOAD, 0x0, 0x0);
+    if (elfSegmentTable().end() != exec_start) {
       if (ResolveInfo::ThreadLocal != f_pExecutableStart->type()) {
         f_pExecutableStart->setValue(f_pExecutableStart->value() +
-                                     exec_start->vaddr());
+                                     (*exec_start)->vaddr());
       }
     }
     else
@@ -584,24 +604,25 @@
   }
 
   if (NULL != f_pEText || NULL != f_p_EText || NULL !=f_p__EText) {
-    ELFSegment* etext = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD,
-                                               llvm::ELF::PF_X,
-                                               llvm::ELF::PF_W);
-    if (NULL != etext) {
+    ELFSegmentFactory::const_iterator etext =
+      elfSegmentTable().find(llvm::ELF::PT_LOAD,
+                             llvm::ELF::PF_X,
+                             llvm::ELF::PF_W);
+    if (elfSegmentTable().end() != etext) {
       if (NULL != f_pEText && ResolveInfo::ThreadLocal != f_pEText->type()) {
         f_pEText->setValue(f_pEText->value() +
-                           etext->vaddr() +
-                           etext->memsz());
+                           (*etext)->vaddr() +
+                           (*etext)->memsz());
       }
       if (NULL != f_p_EText && ResolveInfo::ThreadLocal != f_p_EText->type()) {
         f_p_EText->setValue(f_p_EText->value() +
-                            etext->vaddr() +
-                            etext->memsz());
+                            (*etext)->vaddr() +
+                            (*etext)->memsz());
       }
       if (NULL != f_p__EText && ResolveInfo::ThreadLocal != f_p__EText->type()) {
         f_p__EText->setValue(f_p__EText->value() +
-                            etext->vaddr() +
-                            etext->memsz());
+                            (*etext)->vaddr() +
+                            (*etext)->memsz());
       }
     }
     else {
@@ -616,35 +637,34 @@
 
   if (NULL != f_pEData || NULL != f_p_EData || NULL != f_pBSSStart ||
       NULL != f_pEnd || NULL != f_p_End) {
-    ELFSegment* edata = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD,
-                                               llvm::ELF::PF_W,
-                                               0x0);
-    if (NULL != edata) {
+    ELFSegmentFactory::const_iterator edata =
+      elfSegmentTable().find(llvm::ELF::PT_LOAD, llvm::ELF::PF_W, 0x0);
+    if (elfSegmentTable().end() != edata) {
       if (NULL != f_pEData && ResolveInfo::ThreadLocal != f_pEData->type()) {
         f_pEData->setValue(f_pEData->value() +
-                            edata->vaddr() +
-                            edata->filesz());
+                           (*edata)->vaddr() +
+                           (*edata)->filesz());
       }
       if (NULL != f_p_EData && ResolveInfo::ThreadLocal != f_p_EData->type()) {
         f_p_EData->setValue(f_p_EData->value() +
-                            edata->vaddr() +
-                            edata->filesz());
+                            (*edata)->vaddr() +
+                            (*edata)->filesz());
       }
       if (NULL != f_pBSSStart && ResolveInfo::ThreadLocal != f_pBSSStart->type()) {
         f_pBSSStart->setValue(f_pBSSStart->value() +
-                              edata->vaddr() +
-                              edata->filesz());
+                              (*edata)->vaddr() +
+                              (*edata)->filesz());
       }
 
       if (NULL != f_pEnd && ResolveInfo::ThreadLocal != f_pEnd->type()) {
         f_pEnd->setValue(f_pEnd->value() +
-                         edata->vaddr() +
-                         edata->memsz());
+                         (*edata)->vaddr() +
+                         (*edata)->memsz());
       }
       if (NULL != f_p_End && ResolveInfo::ThreadLocal != f_p_End->type()) {
         f_p_End->setValue(f_p_End->value() +
-                          edata->vaddr() +
-                          edata->memsz());
+                          (*edata)->vaddr() +
+                          (*edata)->memsz());
       }
     }
     else {
@@ -672,11 +692,12 @@
     return true;
 
   // the value of a TLS symbol is the offset to the TLS segment
-  ELFSegment* tls_seg = m_ELFSegmentTable.find(llvm::ELF::PT_TLS,
-                                               llvm::ELF::PF_R, 0x0);
+  ELFSegmentFactory::iterator tls_seg =
+    elfSegmentTable().find(llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
+  assert(tls_seg != elfSegmentTable().end());
   uint64_t value = pSymbol.fragRef()->getOutputOffset();
   uint64_t addr  = pSymbol.fragRef()->frag()->getParent()->getSection().addr();
-  pSymbol.setValue(value + addr - tls_seg->vaddr());
+  pSymbol.setValue(value + addr - (*tls_seg)->vaddr());
   return true;
 }
 
@@ -718,6 +739,18 @@
   }
 }
 
+/// sizeShstrtab - compute the size of .shstrtab
+void GNULDBackend::sizeShstrtab(Module& pModule)
+{
+  size_t shstrtab = 0;
+  // compute the size of .shstrtab section.
+  Module::const_iterator sect, sectEnd = pModule.end();
+  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+    shstrtab += (*sect)->name().size() + 1;
+  } // end of for
+  getOutputFormat()->getShStrTab().setSize(shstrtab);
+}
+
 /// sizeNamePools - compute the size of regular name pools
 /// In ELF executable files, regular name pools are .symtab, .strtab,
 /// .dynsym, .dynstr, .hash and .shstrtab.
@@ -734,7 +767,6 @@
   // first byte
   size_t strtab   = 1;
   size_t dynstr   = config().isCodeStatic()? 0 : 1;
-  size_t shstrtab = 1;
   size_t hash     = 0;
   size_t gnuhash  = 0;
 
@@ -746,21 +778,34 @@
   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 (hasEntryInStrTab(**symbol))
-      strtab += (*symbol)->nameSize() + 1;
-  }
-  symtab_local_cnt = 1 + symbols.numOfFiles() + symbols.numOfLocals() +
-                     symbols.numOfLocalDyns();
+  /* TODO:
+       1. discard locals and temporary locals
+       2. check whether the symbol is used
+   */
+  switch (config().options().getStripSymbolMode()) {
+    case GeneralOptions::StripAllSymbols: {
+      symtab = strtab = 0;
+      break;
+    }
+    default: {
+      symEnd = symbols.end();
+      for (symbol = symbols.begin(); symbol != symEnd; ++symbol) {
+        ++symtab;
+        if (hasEntryInStrTab(**symbol))
+          strtab += (*symbol)->nameSize() + 1;
+      }
+      symtab_local_cnt = 1 + symbols.numOfFiles() + symbols.numOfLocals() +
+                         symbols.numOfLocalDyns();
+      break;
+    }
+  } // end of switch
 
   ELFFileFormat* file_format = getOutputFormat();
 
   switch(config().codeGenType()) {
     case LinkerConfig::DynObj: {
       // soname
-      dynstr += pModule.name().size() + 1;
+      dynstr += config().options().soname().size() + 1;
     }
     /** fall through **/
     case LinkerConfig::Exec:
@@ -857,38 +902,9 @@
       // index of the last local symbol
       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);
+      // The size of .shstrtab should be decided after output sections are all
+      // set, so we just set it to 1 here.
+      file_format->getShStrTab().setSize(0x1);
       break;
     }
     default:
@@ -948,32 +964,34 @@
 /// the size of these tables should be computed before layout
 /// layout should computes the start offset of these tables
 void GNULDBackend::emitRegNamePools(const Module& pModule,
-                                    MemoryArea& pOutput)
+                                    FileOutputBuffer& pOutput)
 {
   ELFFileFormat* file_format = getOutputFormat();
+  if (!file_format->hasSymTab())
+    return;
 
   LDSection& symtab_sect = file_format->getSymTab();
   LDSection& strtab_sect = file_format->getStrTab();
 
-  MemoryRegion* symtab_region = pOutput.request(symtab_sect.offset(),
-                                                symtab_sect.size());
-  MemoryRegion* strtab_region = pOutput.request(strtab_sect.offset(),
-                                                strtab_sect.size());
+  MemoryRegion symtab_region = pOutput.request(symtab_sect.offset(),
+                                               symtab_sect.size());
+  MemoryRegion strtab_region = pOutput.request(strtab_sect.offset(),
+                                               strtab_sect.size());
 
   // set up symtab_region
   llvm::ELF::Elf32_Sym* symtab32 = NULL;
   llvm::ELF::Elf64_Sym* symtab64 = NULL;
   if (config().targets().is32Bits())
-    symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
+    symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region.begin();
   else if (config().targets().is64Bits())
-    symtab64 = (llvm::ELF::Elf64_Sym*)symtab_region->start();
+    symtab64 = (llvm::ELF::Elf64_Sym*)symtab_region.begin();
   else {
     fatal(diag::unsupported_bitclass) << config().targets().triple().str()
                                       << config().targets().bitclass();
   }
 
   // set up strtab_region
-  char* strtab = (char*)strtab_region->start();
+  char* strtab = (char*)strtab_region.begin();
 
   // emit the first ELF symbol
   if (config().targets().is32Bits())
@@ -1014,7 +1032,7 @@
 ///
 /// the size of these tables should be computed before layout
 /// layout should computes the start offset of these tables
-void GNULDBackend::emitDynNamePools(Module& pModule, MemoryArea& pOutput)
+void GNULDBackend::emitDynNamePools(Module& pModule, FileOutputBuffer& pOutput)
 {
   ELFFileFormat* file_format = getOutputFormat();
   if (!file_format->hasDynSymTab() ||
@@ -1029,26 +1047,26 @@
   LDSection& strtab_sect = file_format->getDynStrTab();
   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* dyn_region    = pOutput.request(dyn_sect.offset(),
-                                                dyn_sect.size());
+  MemoryRegion symtab_region = pOutput.request(symtab_sect.offset(),
+                                               symtab_sect.size());
+  MemoryRegion strtab_region = pOutput.request(strtab_sect.offset(),
+                                               strtab_sect.size());
+  MemoryRegion dyn_region = pOutput.request(dyn_sect.offset(),
+                                            dyn_sect.size());
   // set up symtab_region
   llvm::ELF::Elf32_Sym* symtab32 = NULL;
   llvm::ELF::Elf64_Sym* symtab64 = NULL;
   if (config().targets().is32Bits())
-    symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
+    symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region.begin();
   else if (config().targets().is64Bits())
-    symtab64 = (llvm::ELF::Elf64_Sym*)symtab_region->start();
+    symtab64 = (llvm::ELF::Elf64_Sym*)symtab_region.begin();
   else {
     fatal(diag::unsupported_bitclass) << config().targets().triple().str()
                                       << config().targets().bitclass();
   }
 
   // set up strtab_region
-  char* strtab = (char*)strtab_region->start();
+  char* strtab = (char*)strtab_region.begin();
 
   // emit the first ELF symbol
   if (config().targets().is32Bits())
@@ -1121,28 +1139,28 @@
     dynamic().applySoname(strtabsize);
   }
   dynamic().applyEntries(*file_format);
-  dynamic().emit(dyn_sect, *dyn_region);
+  dynamic().emit(dyn_sect, dyn_region);
 
   // emit soname
   if (LinkerConfig::DynObj == config().codeGenType()) {
-    strcpy((strtab + strtabsize), pModule.name().c_str());
-    strtabsize += pModule.name().size() + 1;
+    strcpy((strtab + strtabsize), config().options().soname().c_str());
+    strtabsize += config().options().soname().size() + 1;
   }
 }
 
 /// emitELFHashTab - emit .hash
 void GNULDBackend::emitELFHashTab(const Module::SymbolTable& pSymtab,
-                                  MemoryArea& pOutput)
+                                  FileOutputBuffer& 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());
+  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* word_array = (uint32_t*)hash_region.begin();
   uint32_t& nbucket = word_array[0];
   uint32_t& nchain  = word_array[1];
 
@@ -1171,17 +1189,17 @@
 
 /// emitGNUHashTab - emit .gnu.hash
 void GNULDBackend::emitGNUHashTab(Module::SymbolTable& pSymtab,
-                                  MemoryArea& pOutput)
+                                  FileOutputBuffer& pOutput)
 {
   ELFFileFormat* file_format = getOutputFormat();
   if (!file_format->hasGNUHashTab())
     return;
 
-  MemoryRegion* gnuhash_region =
+  MemoryRegion gnuhash_region =
     pOutput.request(file_format->getGNUHashTab().offset(),
                     file_format->getGNUHashTab().size());
 
-  uint32_t* word_array = (uint32_t*)gnuhash_region->start();
+  uint32_t* word_array = (uint32_t*)gnuhash_region.begin();
   // fixed-length fields
   uint32_t& nbucket   = word_array[0];
   uint32_t& symidx    = word_array[1];
@@ -1309,18 +1327,18 @@
 }
 
 /// emitInterp - emit the .interp
-void GNULDBackend::emitInterp(MemoryArea& pOutput)
+void GNULDBackend::emitInterp(FileOutputBuffer& pOutput)
 {
   if (getOutputFormat()->hasInterp()) {
     const LDSection& interp = getOutputFormat()->getInterp();
-    MemoryRegion *region = pOutput.request(interp.offset(), interp.size());
+    MemoryRegion region = pOutput.request(interp.offset(), interp.size());
     const char* dyld_name;
     if (config().options().hasDyld())
       dyld_name = config().options().dyld().c_str();
     else
       dyld_name = m_pInfo->dyld();
 
-    std::memcpy(region->start(), dyld_name, interp.size());
+    std::memcpy(region.begin(), dyld_name, interp.size());
   }
 }
 
@@ -1349,7 +1367,7 @@
 
   // NULL section should be the "1st" section
   if (LDFileFormat::Null == pSectHdr.kind())
-    return 0;
+    return SHO_NULL;
 
   if (&pSectHdr == &file_format->getStrTab())
     return SHO_STRTAB;
@@ -1493,15 +1511,6 @@
   if (pSymbol.resolveInfo()->isUndef() || pSymbol.isDyn())
     return llvm::ELF::SHN_UNDEF;
 
-  if (pSymbol.resolveInfo()->isLocal() &&
-      LinkerConfig::Object != config().codeGenType()) {
-    switch (pSymbol.type()) {
-      case ResolveInfo::NoType:
-      case ResolveInfo::File:
-        return llvm::ELF::SHN_ABS;
-    }
-  }
-
   if (pSymbol.resolveInfo()->isDefine() && !pSymbol.hasFragRef())
     return llvm::ELF::SHN_ABS;
 
@@ -1598,18 +1607,19 @@
       // description here.
       (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
       Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
       if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
         // allocate TLS common symbol in tbss section
         tbss_offset += ObjectBuilder::AppendFragment(*frag,
                                                      *tbss_sect_data,
                                                      (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       }
       else {
         bss_offset += ObjectBuilder::AppendFragment(*frag,
                                                     *bss_sect_data,
                                                     (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       }
     }
   }
@@ -1624,18 +1634,19 @@
     // description here.
     (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
     Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
     if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
       // allocate TLS common symbol in tbss section
       tbss_offset += ObjectBuilder::AppendFragment(*frag,
                                                    *tbss_sect_data,
                                                    (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
     }
     else {
       bss_offset += ObjectBuilder::AppendFragment(*frag,
                                                   *bss_sect_data,
                                                   (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
     }
   }
 
@@ -1670,35 +1681,177 @@
   return true;
 }
 
+/// readRelocation - read ELF32_Rel entry
+bool GNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel,
+                                  Relocation::Type& pType,
+                                  uint32_t& pSymIdx,
+                                  uint32_t& pOffset) const
+{
+  uint32_t r_info = 0x0;
+  if (llvm::sys::IsLittleEndianHost) {
+    pOffset = pRel.r_offset;
+    r_info  = pRel.r_info;
+  }
+  else {
+    pOffset = mcld::bswap32(pRel.r_offset);
+    r_info  = mcld::bswap32(pRel.r_info);
+  }
+
+  pType = static_cast<unsigned char>(r_info);
+  pSymIdx = (r_info >> 8);
+  return true;
+}
+
+/// readRelocation - read ELF32_Rela entry
+bool GNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel,
+                                  Relocation::Type& pType,
+                                  uint32_t& pSymIdx,
+                                  uint32_t& pOffset,
+                                  int32_t& pAddend) const
+{
+  uint32_t r_info   = 0x0;
+  if (llvm::sys::IsLittleEndianHost) {
+    pOffset = pRel.r_offset;
+    r_info  = pRel.r_info;
+    pAddend = pRel.r_addend;
+  }
+  else {
+    pOffset = mcld::bswap32(pRel.r_offset);
+    r_info  = mcld::bswap32(pRel.r_info);
+    pAddend = mcld::bswap32(pRel.r_addend);
+  }
+
+  pType = static_cast<unsigned char>(r_info);
+  pSymIdx = (r_info >> 8);
+  return true;
+}
+
+/// readRelocation - read ELF64_Rel entry
+bool GNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel,
+                              Relocation::Type& pType,
+                              uint32_t& pSymIdx,
+                              uint64_t& pOffset) const
+{
+  uint64_t r_info = 0x0;
+  if (llvm::sys::IsLittleEndianHost) {
+    pOffset = pRel.r_offset;
+    r_info  = pRel.r_info;
+  }
+  else {
+    pOffset = mcld::bswap64(pRel.r_offset);
+    r_info  = mcld::bswap64(pRel.r_info);
+  }
+
+  pType = static_cast<uint32_t>(r_info);
+  pSymIdx = (r_info >> 32);
+  return true;
+}
+
+/// readRel - read ELF64_Rela entry
+bool GNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel,
+                              Relocation::Type& pType,
+                              uint32_t& pSymIdx,
+                              uint64_t& pOffset,
+                              int64_t& pAddend) const
+{
+  uint64_t r_info = 0x0;
+  if (llvm::sys::IsLittleEndianHost) {
+    pOffset = pRel.r_offset;
+    r_info  = pRel.r_info;
+    pAddend = pRel.r_addend;
+  }
+  else {
+    pOffset = mcld::bswap64(pRel.r_offset);
+    r_info  = mcld::bswap64(pRel.r_info);
+    pAddend = mcld::bswap64(pRel.r_addend);
+  }
+
+  pType = static_cast<uint32_t>(r_info);
+  pSymIdx = (r_info >> 32);
+  return true;
+}
+
+/// emitRelocation - write data to the ELF32_Rel entry
+void GNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel,
+                                  Relocation::Type pType,
+                                  uint32_t pSymIdx,
+                                  uint32_t pOffset) const
+{
+  pRel.r_offset = pOffset;
+  pRel.setSymbolAndType(pSymIdx, pType);
+}
+
+/// emitRelocation - write data to the ELF32_Rela entry
+void GNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel,
+                                  Relocation::Type pType,
+                                  uint32_t pSymIdx,
+                                  uint32_t pOffset,
+                                  int32_t pAddend) const
+{
+  pRel.r_offset = pOffset;
+  pRel.r_addend = pAddend;
+  pRel.setSymbolAndType(pSymIdx, pType);
+}
+
+/// emitRelocation - write data to the ELF64_Rel entry
+void GNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel,
+                                  Relocation::Type pType,
+                                  uint32_t pSymIdx,
+                                  uint64_t pOffset) const
+{
+  pRel.r_offset = pOffset;
+  pRel.setSymbolAndType(pSymIdx, pType);
+}
+
+/// emitRelocation - write data to the ELF64_Rela entry
+void GNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel,
+                                  Relocation::Type pType,
+                                  uint32_t pSymIdx,
+                                  uint64_t pOffset,
+                                  int64_t pAddend) const
+{
+  pRel.r_offset = pOffset;
+  pRel.r_addend = pAddend;
+  pRel.setSymbolAndType(pSymIdx, pType);
+}
+
 /// createProgramHdrs - base on output sections to create the program headers
 void GNULDBackend::createProgramHdrs(Module& pModule)
 {
   ELFFileFormat *file_format = getOutputFormat();
 
-  // make PT_PHDR
-  m_ELFSegmentTable.produce(llvm::ELF::PT_PHDR);
-
   // make PT_INTERP
   if (file_format->hasInterp()) {
-    ELFSegment* interp_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_INTERP);
-    interp_seg->addSection(&file_format->getInterp());
+    // make PT_PHDR
+    elfSegmentTable().produce(llvm::ELF::PT_PHDR);
+
+    ELFSegment* interp_seg = elfSegmentTable().produce(llvm::ELF::PT_INTERP);
+    interp_seg->append(&file_format->getInterp());
   }
 
-  uint32_t cur_flag, prev_flag = getSegmentFlag(0);
+  uint32_t cur_flag, prev_flag = 0x0;
   ELFSegment* load_seg = NULL;
   // make possible PT_LOAD segments
-  LinkerScript::AddressMap::iterator addrEnd
-                                      = pModule.getScript().addressMap().end();
-  Module::iterator sect, sect_end = pModule.end();
-  for (sect = pModule.begin(); sect != sect_end; ++sect) {
+  LinkerScript& ldscript = pModule.getScript();
+  LinkerScript::AddressMap::iterator addrEnd= ldscript.addressMap().end();
+  SectionMap::iterator out, prev, outBegin, outEnd;
+  outBegin = ldscript.sectionMap().begin();
+  outEnd = ldscript.sectionMap().end();
+  for (out = outBegin, prev = outEnd; out != outEnd; prev = out, ++out) {
+    LDSection* sect = (*out)->getSection();
 
-    if (0 == ((*sect)->flag() & llvm::ELF::SHF_ALLOC) &&
-        LDFileFormat::Null != (*sect)->kind())
+    if (0 == (sect->flag() & llvm::ELF::SHF_ALLOC) &&
+        LDFileFormat::Null != sect->kind())
+      break;
+
+    // bypass empty sections
+    if (!(*out)->hasContent() &&
+        (*out)->getSection()->kind() != LDFileFormat::Null)
       continue;
 
-    cur_flag = getSegmentFlag((*sect)->flag());
+    cur_flag = getSegmentFlag(sect->flag());
     bool createPT_LOAD = false;
-    if (LDFileFormat::Null == (*sect)->kind()) {
+    if (LDFileFormat::Null == sect->kind()) {
       // 1. create text segment
       createPT_LOAD = true;
     }
@@ -1707,31 +1860,35 @@
       // 2. create data segment if w/o omagic set
       createPT_LOAD = true;
     }
-    else if ((*sect)->kind() == LDFileFormat::BSS &&
+    else if (sect->kind() == LDFileFormat::BSS &&
              load_seg->isDataSegment() &&
-             addrEnd != pModule.getScript().addressMap().find(".bss")) {
+             addrEnd != ldscript.addressMap().find(".bss")) {
       // 3. create bss segment if w/ -Tbss and there is a data segment
       createPT_LOAD = true;
     }
-    else {
-      if ((*sect != &(file_format->getText())) &&
-          (*sect != &(file_format->getData())) &&
-          (*sect != &(file_format->getBSS())) &&
-          (addrEnd != pModule.getScript().addressMap().find((*sect)->name())))
-        // 4. create PT_LOAD for sections in address map except for text, data,
-        // and bss
-        createPT_LOAD = true;
+    else if ((sect != &(file_format->getText())) &&
+             (sect != &(file_format->getData())) &&
+             (sect != &(file_format->getBSS())) &&
+             (addrEnd != ldscript.addressMap().find(sect->name()))) {
+      // 4. create PT_LOAD for sections in address map except for text, data,
+      // and bss
+      createPT_LOAD = true;
+    }
+    else if (LDFileFormat::Null == (*prev)->getSection()->kind() &&
+             !config().options().getScriptList().empty()) {
+      // 5. create PT_LOAD to hold NULL section if there is a default ldscript
+      createPT_LOAD = true;
     }
 
     if (createPT_LOAD) {
       // create new PT_LOAD segment
-      load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD, cur_flag);
+      load_seg = elfSegmentTable().produce(llvm::ELF::PT_LOAD, cur_flag);
       if (!config().options().nmagic() && !config().options().omagic())
         load_seg->setAlign(abiPageSize());
     }
 
     assert(NULL != load_seg);
-    load_seg->addSection((*sect));
+    load_seg->append(sect);
     if (cur_flag != prev_flag)
       load_seg->updateFlag(cur_flag);
 
@@ -1740,27 +1897,27 @@
 
   // make PT_DYNAMIC
   if (file_format->hasDynamic()) {
-    ELFSegment* dyn_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_DYNAMIC,
+    ELFSegment* dyn_seg = elfSegmentTable().produce(llvm::ELF::PT_DYNAMIC,
                                                     llvm::ELF::PF_R |
                                                     llvm::ELF::PF_W);
-    dyn_seg->addSection(&file_format->getDynamic());
+    dyn_seg->append(&file_format->getDynamic());
   }
 
   if (config().options().hasRelro()) {
     // make PT_GNU_RELRO
-    ELFSegment* relro_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_RELRO);
+    ELFSegment* relro_seg = elfSegmentTable().produce(llvm::ELF::PT_GNU_RELRO);
     for (ELFSegmentFactory::iterator seg = elfSegmentTable().begin(),
-         segEnd = elfSegmentTable().end(); seg != segEnd; ++seg) {
-      if (llvm::ELF::PT_LOAD != (*seg).type())
+      segEnd = 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) {
+      for (ELFSegment::iterator sect = (*seg)->begin(),
+        sectEnd = (*seg)->end(); sect != sectEnd; ++sect) {
         unsigned int order = getSectionOrder(**sect);
         if (SHO_RELRO_LOCAL == order ||
             SHO_RELRO == order ||
             SHO_RELRO_LAST == order) {
-          relro_seg->addSection(*sect);
+          relro_seg->append(*sect);
         }
       }
     }
@@ -1768,22 +1925,22 @@
 
   // make PT_GNU_EH_FRAME
   if (file_format->hasEhFrameHdr()) {
-    ELFSegment* eh_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_EH_FRAME);
-    eh_seg->addSection(&file_format->getEhFrameHdr());
+    ELFSegment* eh_seg = elfSegmentTable().produce(llvm::ELF::PT_GNU_EH_FRAME);
+    eh_seg->append(&file_format->getEhFrameHdr());
   }
 
   // make PT_TLS
   if (file_format->hasTData() || file_format->hasTBSS()) {
-    ELFSegment* tls_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_TLS);
+    ELFSegment* tls_seg = elfSegmentTable().produce(llvm::ELF::PT_TLS);
     if (file_format->hasTData())
-      tls_seg->addSection(&file_format->getTData());
+      tls_seg->append(&file_format->getTData());
     if (file_format->hasTBSS())
-      tls_seg->addSection(&file_format->getTBSS());
+      tls_seg->append(&file_format->getTBSS());
   }
 
   // make PT_GNU_STACK
   if (file_format->hasStackNote()) {
-    m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_STACK,
+    elfSegmentTable().produce(llvm::ELF::PT_GNU_STACK,
                               llvm::ELF::PF_R |
                               llvm::ELF::PF_W |
                               getSegmentFlag(file_format->getStackNote().flag()));
@@ -1791,9 +1948,12 @@
 
   // make PT_NOTE
   ELFSegment *note_seg = NULL;
-  prev_flag = getSegmentFlag(0);
-  for (sect = pModule.begin(); sect != sect_end; ++sect) {
-    if ((*sect)->kind() != LDFileFormat::Note ||
+  prev_flag = 0x0;
+  Module::iterator sect, sectBegin, sectEnd;
+  sectBegin = pModule.begin();
+  sectEnd = pModule.end();
+  for (sect = sectBegin; sect != sectEnd; ++sect) {
+    if ((*sect)->type() != llvm::ELF::SHT_NOTE ||
         ((*sect)->flag() & llvm::ELF::SHF_ALLOC) == 0)
       continue;
 
@@ -1802,9 +1962,9 @@
     // 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 = elfSegmentTable().produce(llvm::ELF::PT_NOTE, cur_flag);
 
-    note_seg->addSection(*sect);
+    note_seg->append(*sect);
     prev_flag = cur_flag;
   }
 
@@ -1816,54 +1976,151 @@
 void GNULDBackend::setupProgramHdrs(const LinkerScript& pScript)
 {
   // update segment info
-  uint64_t seg_start_addr = getSegmentStartAddr(pScript);
-  ELFSegmentFactory::iterator seg, seg_end = m_ELFSegmentTable.end();
-  for (seg = m_ELFSegmentTable.begin(); seg != seg_end; ++seg) {
-    ELFSegment& segment = *seg;
+  for (ELFSegmentFactory::iterator seg = elfSegmentTable().begin(),
+    segEnd = elfSegmentTable().end(); seg != segEnd; ++seg) {
 
-    // update PT_PHDR
-    if (llvm::ELF::PT_PHDR == segment.type()) {
-      uint64_t offset = 0, phdr_size = 0;
+    // bypass if there is no section in this segment (e.g., PT_GNU_STACK)
+    if ((*seg)->size() == 0)
+      continue;
+
+    // bypass the PT_LOAD that only has NULL section now
+    if ((*seg)->type() == llvm::ELF::PT_LOAD &&
+        (*seg)->front()->kind() == LDFileFormat::Null &&
+        (*seg)->size() == 1)
+       continue;
+
+    (*seg)->setOffset((*seg)->front()->offset());
+    if ((*seg)->type() == llvm::ELF::PT_LOAD &&
+        (*seg)->front()->kind() == LDFileFormat::Null) {
+      const LDSection* second = *((*seg)->begin() + 1);
+      assert(second != NULL);
+      (*seg)->setVaddr(second->addr() - second->offset());
+    } else {
+      (*seg)->setVaddr((*seg)->front()->addr());
+    }
+    (*seg)->setPaddr((*seg)->vaddr());
+
+    ELFSegment::reverse_iterator sect, sectREnd = (*seg)->rend();
+    for (sect = (*seg)->rbegin(); sect != sectREnd; ++sect) {
+      if ((*sect)->kind() != LDFileFormat::BSS)
+        break;
+    }
+    if (sect != sectREnd) {
+      (*seg)->setFilesz((*sect)->offset() +
+                        (*sect)->size() -
+                        (*seg)->offset());
+    } else {
+      (*seg)->setFilesz(0x0);
+    }
+
+    (*seg)->setMemsz((*seg)->back()->addr() +
+                     (*seg)->back()->size() -
+                     (*seg)->vaddr());
+  } // end of for
+
+  // handle the case if text segment only has NULL section
+  LDSection* null_sect = &getOutputFormat()->getNULLSection();
+  ELFSegmentFactory::iterator null_seg =
+    elfSegmentTable().find(llvm::ELF::PT_LOAD, null_sect);
+
+  if ((*null_seg)->size() == 1) {
+    // find 2nd PT_LOAD
+    ELFSegmentFactory::iterator seg, segEnd = elfSegmentTable().end();
+    for (seg = null_seg + 1; seg != segEnd; ++seg) {
+      if ((*seg)->type() == llvm::ELF::PT_LOAD)
+        break;
+    }
+    if (seg != segEnd) {
+      uint64_t addr = (*seg)->front()->addr() - (*seg)->front()->offset();
+      uint64_t size = sectionStartOffset();
+      if (addr + size == (*seg)->front()->addr()) {
+        // if there is no space between the 2 segments, we can merge them.
+        (*seg)->setOffset(0x0);
+        (*seg)->setVaddr(addr);
+        (*seg)->setPaddr(addr);
+
+        ELFSegment::iterator sect, sectEnd = (*seg)->end();
+        for (sect = (*seg)->begin(); sect != sectEnd; ++sect) {
+          if ((*sect)->kind() == LDFileFormat::BSS) {
+            --sect;
+            break;
+          }
+        }
+        if (sect == sectEnd) {
+          (*seg)->setFilesz((*seg)->back()->offset() +
+                            (*seg)->back()->size() -
+                            (*seg)->offset());
+        } else if (*sect != (*seg)->front()) {
+          --sect;
+          (*seg)->setFilesz((*sect)->offset() +
+                            (*sect)->size() -
+                            (*seg)->offset());
+        } else {
+          (*seg)->setFilesz(0x0);
+        }
+
+        (*seg)->setMemsz((*seg)->back()->addr() +
+                         (*seg)->back()->size() -
+                         (*seg)->vaddr());
+
+        (*seg)->insert((*seg)->begin(), null_sect);
+        elfSegmentTable().erase(null_seg);
+
+      } else if (addr + size < (*seg)->vaddr()) {
+        (*null_seg)->setOffset(0x0);
+        (*null_seg)->setVaddr(addr);
+        (*null_seg)->setPaddr(addr);
+        (*null_seg)->setFilesz(size);
+        (*null_seg)->setMemsz(size);
+      } else {
+        // erase the non valid segment contains NULL.
+        elfSegmentTable().erase(null_seg);
+      }
+    }
+  }
+
+  // set up PT_PHDR
+  ELFSegmentFactory::iterator phdr =
+    elfSegmentTable().find(llvm::ELF::PT_PHDR, llvm::ELF::PF_R, 0x0);
+
+  if (phdr != elfSegmentTable().end()) {
+    ELFSegmentFactory::iterator null_seg =
+      elfSegmentTable().find(llvm::ELF::PT_LOAD, null_sect);
+    if (null_seg != elfSegmentTable().end()) {
+      uint64_t offset = 0x0, phdr_size = 0x0;
       if (config().targets().is32Bits()) {
         offset = sizeof(llvm::ELF::Elf32_Ehdr);
         phdr_size = sizeof(llvm::ELF::Elf32_Phdr);
-      }
-      else {
+      } else {
         offset = sizeof(llvm::ELF::Elf64_Ehdr);
         phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
       }
-      segment.setOffset(offset);
-      segment.setVaddr(seg_start_addr + offset);
-      segment.setPaddr(segment.vaddr());
-      segment.setFilesz(numOfSegments() * phdr_size);
-      segment.setMemsz(numOfSegments() * phdr_size);
-      segment.setAlign(config().targets().bitclass() / 8);
-      continue;
+      (*phdr)->setOffset(offset);
+      (*phdr)->setVaddr((*null_seg)->vaddr() + offset);
+      (*phdr)->setPaddr((*phdr)->vaddr());
+      (*phdr)->setFilesz(elfSegmentTable().size() * phdr_size);
+      (*phdr)->setMemsz(elfSegmentTable().size() * phdr_size);
+      (*phdr)->setAlign(config().targets().bitclass() / 8);
+    } else {
+      elfSegmentTable().erase(phdr);
     }
-
-    // bypass if there is no section in this segment (e.g., PT_GNU_STACK)
-    if (segment.numOfSections() == 0)
-      continue;
-
-    segment.setOffset(segment.front()->offset());
-    if (llvm::ELF::PT_LOAD == segment.type() &&
-        LDFileFormat::Null == segment.front()->kind())
-      segment.setVaddr(seg_start_addr);
-    else
-      segment.setVaddr(segment.front()->addr());
-    segment.setPaddr(segment.vaddr());
-
-    const LDSection* last_sect = segment.back();
-    assert(NULL != last_sect);
-    uint64_t file_size = last_sect->offset() - segment.offset();
-    if (LDFileFormat::BSS != last_sect->kind())
-      file_size += last_sect->size();
-    segment.setFilesz(file_size);
-
-    segment.setMemsz(last_sect->addr() - segment.vaddr() + last_sect->size());
   }
 }
 
+/// getSegmentFlag - give a section flag and return the corresponding segment
+/// flag
+uint32_t GNULDBackend::getSegmentFlag(const uint32_t pSectionFlag)
+{
+  uint32_t flag = 0x0;
+  if ((pSectionFlag & llvm::ELF::SHF_ALLOC) != 0x0)
+    flag |= llvm::ELF::PF_R;
+  if ((pSectionFlag & llvm::ELF::SHF_WRITE) != 0x0)
+    flag |= llvm::ELF::PF_W;
+  if ((pSectionFlag & llvm::ELF::SHF_EXECINSTR) != 0x0)
+    flag |= llvm::ELF::PF_X;
+  return flag;
+}
+
 /// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
 /// @ref gold linker: layout.cc:2608
 void GNULDBackend::setupGNUStackInfo(Module& pModule)
@@ -1910,203 +2167,249 @@
   }
 }
 
-/// setupRelro - setup the offset constraint of PT_RELRO
-void GNULDBackend::setupRelro(Module& pModule)
+/// setOutputSectionOffset - helper function to set output sections' offset.
+void GNULDBackend::setOutputSectionOffset(Module& pModule)
 {
-  assert(config().options().hasRelro());
-  // if -z relro is given, we need to adjust sections' offset again, and let
-  // PT_GNU_RELRO end on a common page boundary
-
-  Module::iterator sect = pModule.begin();
-  for (Module::iterator sect_end = pModule.end(); sect != sect_end; ++sect) {
-    // find the first non-relro section
-    if (getSectionOrder(**sect) > SHO_RELRO_LAST)
-      break;
-  }
-
-  // align the first non-relro section to page boundary
-  uint64_t offset = (*sect)->offset();
-  alignAddress(offset, commonPageSize());
-  (*sect)->setOffset(offset);
-
-  // It seems that compiler think .got and .got.plt are continuous (w/o any
-  // padding between). If .got is the last section in PT_RELRO and it's not
-  // continuous to its next section (i.e. .got.plt), we need to add padding
-  // in front of .got instead.
-  // FIXME: Maybe we can handle this in a more general way.
-  LDSection& got = getOutputFormat()->getGOT();
-  if ((getSectionOrder(got) == SHO_RELRO_LAST) &&
-      (got.offset() + got.size() != offset)) {
-    got.setOffset(offset - got.size());
-  }
-
-  // set up remaining section's offset
-  setOutputSectionOffset(pModule, ++sect, pModule.end());
-}
-
-/// setOutputSectionOffset - helper function to set a group of output sections'
-/// offset, and set pSectBegin to pStartOffset if pStartOffset is not -1U.
-void GNULDBackend::setOutputSectionOffset(Module& pModule,
-                                          Module::iterator pSectBegin,
-                                          Module::iterator pSectEnd,
-                                          uint64_t pStartOffset)
-{
-  if (pSectBegin == pModule.end())
-    return;
-
-  assert(pSectEnd == pModule.end() ||
-         (pSectEnd != pModule.end() &&
-          (*pSectBegin)->index() <= (*pSectEnd)->index()));
-
-  if (pStartOffset != -1U) {
-    (*pSectBegin)->setOffset(pStartOffset);
-    ++pSectBegin;
-  }
-
-  // set up the "cur" and "prev" iterator
-  Module::iterator cur = pSectBegin;
-  Module::iterator prev = pSectBegin;
-  if (cur != pModule.begin())
-    --prev;
-  else
-    ++cur;
-
-  for (; cur != pSectEnd; ++cur, ++prev) {
-    uint64_t offset = 0x0;
-    switch ((*prev)->kind()) {
-      case LDFileFormat::Null:
-        offset = sectionStartOffset();
-        break;
-      case LDFileFormat::BSS:
-        offset = (*prev)->offset();
-        break;
-      default:
-        offset = (*prev)->offset() + (*prev)->size();
-        break;
-    }
-
-    alignAddress(offset, (*cur)->align());
-    (*cur)->setOffset(offset);
-  }
-}
-
-/// setOutputSectionOffset - helper function to set output sections' address
-void GNULDBackend::setOutputSectionAddress(Module& pModule,
-                                           Module::iterator pSectBegin,
-                                           Module::iterator pSectEnd)
-{
-  if (pSectBegin == pModule.end())
-    return;
-
-  assert(pSectEnd == pModule.end() ||
-         (pSectEnd != pModule.end() &&
-          (*pSectBegin)->index() <= (*pSectEnd)->index()));
-
-  const LinkerScript& script = pModule.getScript();
-  uint64_t seg_start_addr = getSegmentStartAddr(script);
-  for (ELFSegmentFactory::iterator seg = elfSegmentTable().begin(),
-         segEnd = elfSegmentTable().end(), prev = elfSegmentTable().end();
-       seg != segEnd; prev = seg, ++seg) {
-    if (llvm::ELF::PT_LOAD != (*seg).type())
+  LinkerScript& script = pModule.getScript();
+  uint64_t offset = 0x0;
+  LDSection* cur = NULL;
+  LDSection* prev = NULL;
+  SectionMap::iterator out, outBegin, outEnd;
+  outBegin = script.sectionMap().begin();
+  outEnd = script.sectionMap().end();
+  for (out = outBegin; out != outEnd; ++out, prev = cur) {
+    cur = (*out)->getSection();
+    if (cur->kind() == LDFileFormat::Null) {
+      cur->setOffset(0x0);
       continue;
+    }
 
-    uint64_t start_addr = 0x0;
-    LinkerScript::AddressMap::const_iterator mapping;
-    if ((*seg).front()->kind() == LDFileFormat::Null)
-      mapping = script.addressMap().find(".text");
-    else if ((*seg).isDataSegment())
-      mapping = script.addressMap().find(".data");
-    else if ((*seg).isBssSegment())
-      mapping = script.addressMap().find(".bss");
-    else
-      mapping = script.addressMap().find((*seg).front()->name());
+    switch (prev->kind()) {
+    case LDFileFormat::Null:
+      offset = sectionStartOffset();
+      break;
+    case LDFileFormat::BSS:
+      offset = prev->offset();
+      break;
+    default:
+      offset = prev->offset() + prev->size();
+      break;
+    }
+    alignAddress(offset, cur->align());
+    cur->setOffset(offset);
+  }
+}
 
-    if (mapping != script.addressMap().end()) {
+/// setOutputSectionAddress - helper function to set output sections' address.
+void GNULDBackend::setOutputSectionAddress(Module& pModule)
+{
+  RpnEvaluator evaluator(pModule, *this);
+  LinkerScript& script = pModule.getScript();
+  uint64_t vma = 0x0, offset = 0x0;
+  LDSection* cur = NULL;
+  LDSection* prev = NULL;
+  LinkerScript::AddressMap::iterator addr, addrEnd = script.addressMap().end();
+  ELFSegmentFactory::iterator seg, segEnd = elfSegmentTable().end();
+  SectionMap::Output::dot_iterator dot;
+  SectionMap::iterator out, outBegin, outEnd;
+  outBegin = script.sectionMap().begin();
+  outEnd = script.sectionMap().end();
+  for (out = outBegin; out != outEnd; prev = cur, ++out) {
+    cur = (*out)->getSection();
+
+    if (cur->kind() == LDFileFormat::Null) {
+      cur->setOffset(0x0);
+      continue;
+    }
+
+    // process dot assignments between 2 output sections
+    for (SectionMap::Output::dot_iterator it = (*out)->dot_begin(),
+      ie = (*out)->dot_end(); it != ie; ++it) {
+      (*it).assign(evaluator);
+    }
+
+    seg = elfSegmentTable().find(llvm::ELF::PT_LOAD, cur);
+    if (seg != segEnd && cur == (*seg)->front()) {
+      if ((*seg)->isBssSegment())
+        addr = script.addressMap().find(".bss");
+      else if ((*seg)->isDataSegment())
+        addr = script.addressMap().find(".data");
+      else
+        addr = script.addressMap().find(cur->name());
+    } else
+      addr = addrEnd;
+
+    if (addr != addrEnd) {
       // use address mapping in script options
-      start_addr = mapping.getEntry()->value();
-    }
-    else {
-      if ((*seg).front()->kind() == LDFileFormat::Null) {
-        // 1st PT_LOAD
-        start_addr = seg_start_addr;
+      vma = addr.getEntry()->value();
+    } else if ((*out)->prolog().hasVMA()) {
+      // use address from output section description
+      evaluator.eval((*out)->prolog().vma(), vma);
+    } else if ((dot = (*out)->find_last_explicit_dot()) != (*out)->dot_end()) {
+      // assign address based on `.' symbol in ldscript
+      vma = (*dot).symbol().value();
+      alignAddress(vma, cur->align());
+    } else {
+      if ((*out)->prolog().type() == OutputSectDesc::NOLOAD) {
+        vma = prev->addr() + prev->size();
+      } else if ((cur->flag() & llvm::ELF::SHF_ALLOC) != 0) {
+        if (prev->kind() == LDFileFormat::Null) {
+          // Let SECTIONS starts at 0 if we have a default ldscript but don't
+          // have any initial value (VMA or `.').
+          if (!config().options().getScriptList().empty())
+            vma = 0x0;
+          else
+            vma = getSegmentStartAddr(script) + sectionStartOffset();
+        } else {
+          if ((prev->kind() == LDFileFormat::BSS))
+            vma = prev->addr();
+          else
+            vma = prev->addr() + prev->size();
+        }
+        alignAddress(vma, cur->align());
+        if (config().options().getScriptList().empty()) {
+          if (seg != segEnd && cur == (*seg)->front()) {
+            // 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(vma, (*seg)->align());
+          }
+        }
+      } else {
+        vma = 0x0;
       }
-      else if ((*prev).front()->kind() == LDFileFormat::Null) {
-        // prev segment is 1st PT_LOAD
-        start_addr = seg_start_addr + (*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());
     }
 
+    if (config().options().hasRelro()) {
+      // if -z relro is given, we need to adjust sections' offset again, and
+      // let PT_GNU_RELRO end on a abi page boundary
+
+      // check if current is the first non-relro section
+      SectionMap::iterator relro_last = out - 1;
+      if (relro_last != outEnd &&
+          (*relro_last)->order() <= SHO_RELRO_LAST &&
+          (*out)->order() > SHO_RELRO_LAST) {
+        // align the first non-relro section to page boundary
+        alignAddress(vma, abiPageSize());
+
+        // It seems that compiler think .got and .got.plt are continuous (w/o
+        // any padding between). If .got is the last section in PT_RELRO and
+        // it's not continuous to its next section (i.e. .got.plt), we need to
+        // add padding in front of .got instead.
+        // FIXME: Maybe we can handle this in a more general way.
+        LDSection& got = getOutputFormat()->getGOT();
+        if ((getSectionOrder(got) == SHO_RELRO_LAST) &&
+            (got.addr() + got.size() < vma)) {
+          uint64_t diff = vma - got.addr() - got.size();
+          got.setAddr(vma - got.size());
+          got.setOffset(got.offset() + diff);
+        }
+      }
+    } // end of if - for relro processing
+
+    cur->setAddr(vma);
+
+    switch (prev->kind()) {
+    case LDFileFormat::Null:
+      offset = sectionStartOffset();
+      break;
+    case LDFileFormat::BSS:
+      offset = prev->offset();
+      break;
+    default:
+      offset = prev->offset() + prev->size();
+      break;
+    }
+    alignAddress(offset, cur->align());
     // 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);
+    // FIXME: Now make all sh_addr and sh_offset are congruent, modulo the page
+    // size. Otherwise, old objcopy (e.g., binutils 2.17) may fail with our
+    // output!
+    if ((cur->flag() & llvm::ELF::SHF_ALLOC) != 0 &&
+        (vma & (abiPageSize() - 1)) != (offset & (abiPageSize() - 1))) {
+      uint64_t padding = abiPageSize() +
+                         (vma & (abiPageSize() - 1)) -
+                         (offset & (abiPageSize() - 1));
+      offset += padding;
     }
 
-    for (ELFSegment::sect_iterator sect = (*seg).begin(),
-           sectEnd = (*seg).end(); sect != sectEnd; ++sect) {
-      if ((*sect)->index() < (*pSectBegin)->index())
-        continue;
+    cur->setOffset(offset);
 
-      if (LDFileFormat::Null == (*sect)->kind())
-        continue;
+    // process dot assignments in the output section
+    bool changed = false;
+    Fragment* invalid = NULL;
+    for (SectionMap::Output::iterator in = (*out)->begin(),
+      inEnd = (*out)->end(); in != inEnd; ++in) {
 
-      if (sect == pSectEnd)
-        return;
+      if (invalid != NULL && !(*in)->dotAssignments().empty()) {
+        while (invalid != (*in)->dotAssignments().front().first) {
+          Fragment* prev = invalid->getPrevNode();
+          invalid->setOffset(prev->getOffset() + prev->size());
+          invalid = invalid->getNextNode();
+        }
+        invalid = NULL;
+      }
 
-      if (sect != (*seg).begin())
-        (*sect)->setAddr(start_addr + (*sect)->offset() -
-                         (*seg).front()->offset());
-      else
-        (*sect)->setAddr(start_addr);
+      for (SectionMap::Input::dot_iterator it = (*in)->dot_begin(),
+        ie = (*in)->dot_end(); it != ie; ++it) {
+        (*it).second.assign(evaluator);
+        if ((*it).first != NULL) {
+          uint64_t new_offset = (*it).second.symbol().value() - vma;
+          if (new_offset != (*it).first->getOffset()) {
+            (*it).first->setOffset(new_offset);
+            invalid = (*it).first->getNextNode();
+            changed = true;
+          }
+        }
+      } // for each dot assignment
+    } // for each input description
+
+    if (changed) {
+      while (invalid != NULL) {
+        Fragment* prev = invalid->getPrevNode();
+        invalid->setOffset(prev->getOffset() + prev->size());
+        invalid = invalid->getNextNode();
+      }
+
+      cur->setSize(cur->getSectionData()->back().getOffset() +
+                   cur->getSectionData()->back().size());
     }
-  }
+
+  } // for each output section description
 }
 
-/// layout - layout method
-void GNULDBackend::layout(Module& pModule)
+/// placeOutputSections - place output sections based on SectionMap
+void GNULDBackend::placeOutputSections(Module& pModule)
 {
-  std::vector<SHOEntry> output_list;
-  // 1. determine what sections will go into final output, and push the needed
-  // sections into output_list for later processing
+  typedef std::vector<LDSection*> Orphans;
+  Orphans orphans;
+  SectionMap& sectionMap = pModule.getScript().sectionMap();
+
   for (Module::iterator it = pModule.begin(), ie = pModule.end(); it != ie;
-       ++it) {
+    ++it) {
+    bool wanted = false;
+
     switch ((*it)->kind()) {
     // take NULL and StackNote directly
     case LDFileFormat::Null:
     case LDFileFormat::StackNote:
-      output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+      wanted = true;
       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)));
+        wanted = true;
       break;
     case LDFileFormat::Relocation:
       if (((*it)->size() != 0) ||
           ((*it)->hasRelocData() &&
            config().codeGenType() == LinkerConfig::Object))
-        output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+        wanted = true;
       break;
     case LDFileFormat::Regular:
     case LDFileFormat::Target:
@@ -2120,7 +2423,7 @@
       if (((*it)->size() != 0) ||
           ((*it)->hasSectionData() &&
            config().codeGenType() == LinkerConfig::Object))
-        output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+        wanted = true;
       break;
     case LDFileFormat::Group:
       if (LinkerConfig::Object == config().codeGenType()) {
@@ -2129,44 +2432,140 @@
       }
       break;
     case LDFileFormat::Version:
-      if (0 != (*it)->size()) {
-        output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+      if ((*it)->size() != 0) {
+        wanted = true;
         warning(diag::warn_unsupported_symbolic_versioning) << (*it)->name();
       }
       break;
     default:
-      if (0 != (*it)->size()) {
+      if ((*it)->size() != 0) {
         error(diag::err_unsupported_section) << (*it)->name() << (*it)->kind();
       }
       break;
+    } // end of switch
+
+    if (wanted) {
+      SectionMap::iterator out, outBegin, outEnd;
+      outBegin = sectionMap.begin();
+      outEnd = sectionMap.end();
+      for (out = outBegin; out != outEnd; ++out) {
+        bool matched = false;
+        if ((*it)->name().compare((*out)->name()) == 0) {
+          switch ((*out)->prolog().constraint()) {
+          case OutputSectDesc::NO_CONSTRAINT:
+            matched = true;
+            break;
+          case OutputSectDesc::ONLY_IF_RO:
+            matched = ((*it)->flag() & llvm::ELF::SHF_WRITE) == 0;
+            break;
+          case OutputSectDesc::ONLY_IF_RW:
+            matched = ((*it)->flag() & llvm::ELF::SHF_WRITE) != 0;
+            break;
+          } // end of switch
+
+          if (matched)
+            break;
+        }
+      } // for each output section description
+
+      if (out != outEnd) {
+        // set up the section
+        (*out)->setSection(*it);
+        (*out)->setOrder(getSectionOrder(**it));
+      } else {
+        orphans.push_back(*it);
+      }
     }
-  } // end of for
+  } // for each section in Module
 
-  // 2. sort output section orders
-  std::stable_sort(output_list.begin(), output_list.end(), SHOCompare());
+  // set up sections in SectionMap but do not exist at all.
+  uint32_t flag = 0x0;
+  unsigned int order = SHO_UNDEFINED;
+  OutputSectDesc::Type type = OutputSectDesc::LOAD;
+  for (SectionMap::reverse_iterator out = sectionMap.rbegin(),
+    outEnd = sectionMap.rend(); out != outEnd; ++out) {
+    if ((*out)->hasContent() ||
+        (*out)->getSection()->kind() == LDFileFormat::Null ||
+        (*out)->getSection()->kind() == LDFileFormat::StackNote) {
+      flag = (*out)->getSection()->flag();
+      order = (*out)->order();
+      type = (*out)->prolog().type();
+    } else {
+      (*out)->getSection()->setFlag(flag);
+      (*out)->setOrder(order);
+      (*out)->prolog().setType(type);
+    }
+  } // for each output section description
 
-  // 3. update output sections in Module
-  pModule.getSectionTable().clear();
-  for(size_t index = 0; index < output_list.size(); ++index) {
-    (output_list[index].first)->setIndex(index);
-    pModule.getSectionTable().push_back(output_list[index].first);
+  // place orphan sections
+  for (Orphans::iterator it = orphans.begin(), ie = orphans.end(); it != ie;
+    ++it) {
+    size_t order = getSectionOrder(**it);
+    SectionMap::iterator out, outBegin, outEnd;
+    outBegin = sectionMap.begin();
+    outEnd = sectionMap.end();
+
+    if ((*it)->kind() == LDFileFormat::Null)
+      out = sectionMap.insert(outBegin, *it);
+    else {
+      for (out = outBegin; out != outEnd; ++out) {
+        if ((*out)->order() > order)
+          break;
+      }
+      out = sectionMap.insert(out, *it);
+    }
+    (*out)->setOrder(order);
+  } // for each orphan section
+
+  // sort output section orders if there is no default ldscript
+  if (config().options().getScriptList().empty()) {
+    std::stable_sort(sectionMap.begin(),
+                     sectionMap.end(),
+                     SectionMap::SHOCompare());
   }
 
+  // when section ordering is fixed, now we can make sure dot assignments are
+  // all set appropriately
+  sectionMap.fixupDotSymbols();
+}
+
+/// layout - layout method
+void GNULDBackend::layout(Module& pModule)
+{
+  // 1. place output sections based on SectionMap from SECTIONS command
+  placeOutputSections(pModule);
+
+  // 2. update output sections in Module
+  SectionMap& sectionMap = pModule.getScript().sectionMap();
+  pModule.getSectionTable().clear();
+  for (SectionMap::iterator out = sectionMap.begin(), outEnd = sectionMap.end();
+    out != outEnd; ++out) {
+    if ((*out)->hasContent() ||
+        (*out)->getSection()->kind() == LDFileFormat::Null ||
+        (*out)->getSection()->kind() == LDFileFormat::StackNote ||
+        config().codeGenType() == LinkerConfig::Object) {
+      (*out)->getSection()->setIndex(pModule.size());
+      pModule.getSectionTable().push_back((*out)->getSection());
+    }
+  } // for each output section description
+
+  // 3. update the size of .shstrtab
+  sizeShstrtab(pModule);
+
   // 4. create program headers
   if (LinkerConfig::Object != config().codeGenType()) {
     createProgramHdrs(pModule);
   }
 
-  // 5. set output section offset
-  setOutputSectionOffset(pModule, pModule.begin(), pModule.end(), 0x0);
+  // 5. set output section address/offset
+  if (LinkerConfig::Object != config().codeGenType())
+    setOutputSectionAddress(pModule);
+  else
+    setOutputSectionOffset(pModule);
 }
 
-/// preLayout - Backend can do any needed modification before layout
-void GNULDBackend::preLayout(Module& pModule, IRBuilder& pBuilder)
+void GNULDBackend::createAndSizeEhFrameHdr(Module& pModule)
 {
-  // prelayout target first
-  doPreLayout(pBuilder);
-
   if (LinkerConfig::Object != config().codeGenType() &&
       config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
     // init EhFrameHdr and size the output section
@@ -2175,6 +2574,13 @@
                                    format->getEhFrame());
     m_pEhFrameHdr->sizeOutput();
   }
+}
+
+/// preLayout - Backend can do any needed modification before layout
+void GNULDBackend::preLayout(Module& pModule, IRBuilder& pBuilder)
+{
+  // prelayout target first
+  doPreLayout(pBuilder);
 
   // change .tbss and .tdata section symbol from Local to LocalDyn category
   if (NULL != f_pTDATA)
@@ -2248,28 +2654,17 @@
 /// postLayout - Backend can do any needed modification after layout
 void GNULDBackend::postLayout(Module& pModule, IRBuilder& pBuilder)
 {
-  // 1. set up section address and segment attributes
   if (LinkerConfig::Object != config().codeGenType()) {
-    if (config().options().hasRelro()) {
-      // 1.1 set up the offset constraint of PT_RELRO
-      setupRelro(pModule);
-    }
-
-    // 1.2 set up the output sections' address
-    setOutputSectionAddress(pModule, pModule.begin(), pModule.end());
-
-    // 1.3 do relaxation
+    // do relaxation
     relax(pModule, pBuilder);
-
-    // 1.4 set up the attributes of program headers
+    // set up the attributes of program headers
     setupProgramHdrs(pModule.getScript());
   }
 
-  // 2. target specific post layout
   doPostLayout(pModule, pBuilder);
 }
 
-void GNULDBackend::postProcessing(MemoryArea& pOutput)
+void GNULDBackend::postProcessing(FileOutputBuffer& pOutput)
 {
   if (LinkerConfig::Object != config().codeGenType() &&
       config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
@@ -2327,7 +2722,7 @@
 
 /// isDynamicSymbol
 /// @ref Google gold linker: symtab.cc:311
-bool GNULDBackend::isDynamicSymbol(const LDSymbol& pSymbol)
+bool GNULDBackend::isDynamicSymbol(const LDSymbol& pSymbol) const
 {
   // If a local symbol is in the LDContext's symbol table, it's a real local
   // symbol. We should not add it
@@ -2348,7 +2743,7 @@
 
 /// isDynamicSymbol
 /// @ref Google gold linker: symtab.cc:311
-bool GNULDBackend::isDynamicSymbol(const ResolveInfo& pResolveInfo)
+bool GNULDBackend::isDynamicSymbol(const ResolveInfo& pResolveInfo) const
 {
   // If a local symbol is in the LDContext's symbol table, it's a real local
   // symbol. We should not add it
@@ -2367,6 +2762,20 @@
   return false;
 }
 
+/// elfSegmentTable - return the reference of the elf segment table
+ELFSegmentFactory& GNULDBackend::elfSegmentTable()
+{
+  assert(m_pELFSegmentTable != NULL && "Do not create ELFSegmentTable!");
+  return *m_pELFSegmentTable;
+}
+
+/// elfSegmentTable - return the reference of the elf segment table
+const ELFSegmentFactory& GNULDBackend::elfSegmentTable() const
+{
+  assert(m_pELFSegmentTable != NULL && "Do not create ELFSegmentTable!");
+  return *m_pELFSegmentTable;
+}
+
 /// commonPageSize - the common page size of the target machine.
 /// @ref gold linker: target.h:135
 uint64_t GNULDBackend::commonPageSize() const
@@ -2553,6 +2962,14 @@
   return *f_pTBSS;
 }
 
+llvm::StringRef GNULDBackend::getEntry(const Module& pModule) const
+{
+  if (pModule.getScript().hasEntry())
+    return pModule.getScript().entry();
+  else
+    return getInfo().entry();
+}
+
 void GNULDBackend::checkAndSetHasTextRel(const LDSection& pSection)
 {
   if (m_bHasTextRel)
@@ -2567,6 +2984,28 @@
   return;
 }
 
+/// sortRelocation - sort the dynamic relocations to let dynamic linker
+/// process relocations more efficiently
+void GNULDBackend::sortRelocation(LDSection& pSection)
+{
+  if (!config().options().hasCombReloc())
+    return;
+
+  assert(pSection.kind() == LDFileFormat::Relocation);
+
+  switch (config().codeGenType()) {
+  case LinkerConfig::DynObj:
+  case LinkerConfig::Exec:
+    if (&pSection == &getOutputFormat()->getRelDyn() ||
+        &pSection == &getOutputFormat()->getRelaDyn()) {
+      if (pSection.hasRelocData())
+        pSection.getRelocData()->sort(RelocCompare(*this));
+    }
+  default:
+    return;
+  }
+}
+
 /// initBRIslandFactory - initialize the branch island factory for relaxation
 bool GNULDBackend::initBRIslandFactory()
 {
@@ -2590,21 +3029,12 @@
   if (!mayRelax())
     return true;
 
+  getBRIslandFactory()->group(pModule);
+
   bool finished = true;
   do {
     if (doRelax(pModule, pBuilder, finished)) {
-      // If the sections (e.g., .text) are relaxed, the layout is also changed
-      // We need to do the following:
-
-      // 1. set up the offset
-      setOutputSectionOffset(pModule, pModule.begin(), pModule.end());
-
-      // 2. set up the offset constraint of PT_RELRO
-      if (config().options().hasRelro())
-        setupRelro(pModule);
-
-      // 3. set up the output sections' address
-      setOutputSectionAddress(pModule, pModule.begin(), pModule.end());
+      setOutputSectionAddress(pModule);
     }
   } while (!finished);
 
@@ -2625,3 +3055,42 @@
   return !needGNUHash(*X) && needGNUHash(*Y);
 }
 
+bool GNULDBackend::RelocCompare::operator()(const Relocation* X,
+                                            const Relocation* Y) const
+{
+  // 1. compare if relocation is relative
+  if (X->symInfo() == NULL) {
+    if (Y->symInfo() != NULL)
+      return true;
+  } else if (Y->symInfo() == NULL) {
+    return false;
+  } else {
+    // 2. compare the symbol index
+    size_t symIdxX = m_Backend.getSymbolIdx(X->symInfo()->outSymbol());
+    size_t symIdxY = m_Backend.getSymbolIdx(Y->symInfo()->outSymbol());
+    if (symIdxX < symIdxY)
+      return true;
+    if (symIdxX > symIdxY)
+      return false;
+  }
+
+  // 3. compare the relocation address
+  if (X->place() < Y->place())
+    return true;
+  if (X->place() > Y->place())
+    return false;
+
+  // 4. compare the relocation type
+  if (X->type() < Y->type())
+    return true;
+  if (X->type() > Y->type())
+    return false;
+
+  // 5. compare the addend
+  if (X->addend() < Y->addend())
+    return true;
+  if (X->addend() > Y->addend())
+    return false;
+
+  return false;
+}
diff --git a/lib/Target/Hexagon/Hexagon.h b/lib/Target/Hexagon/Hexagon.h
index 5a286ef..731a878 100644
--- a/lib/Target/Hexagon/Hexagon.h
+++ b/lib/Target/Hexagon/Hexagon.h
@@ -6,19 +6,17 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_HEXAGON_H
-#define MCLD_HEXAGON_H
+#ifndef MCLD_TARGET_HEXAGON_H
+#define MCLD_TARGET_HEXAGON_H
 #include <string>
-#include <mcld/Target/TargetMachine.h>
 
 namespace llvm {
-
 class Target;
-
 } // namespace of llvm
 
 namespace mcld {
 
+class Target;
 class TargetLDBackend;
 
 extern mcld::Target TheHexagonTarget;
diff --git a/lib/Target/Hexagon/HexagonDiagnostic.cpp b/lib/Target/Hexagon/HexagonDiagnostic.cpp
index 01b8f9b..7fd58c0 100644
--- a/lib/Target/Hexagon/HexagonDiagnostic.cpp
+++ b/lib/Target/Hexagon/HexagonDiagnostic.cpp
@@ -6,18 +6,16 @@
 // 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)
 {
@@ -26,6 +24,8 @@
 
 } // namespace of mcld
 
+using namespace mcld;
+
 //===----------------------------------------------------------------------===//
 // InitializeHexagonDiagnostic
 //===----------------------------------------------------------------------===//
diff --git a/lib/Target/Hexagon/HexagonELFMCLinker.cpp b/lib/Target/Hexagon/HexagonELFMCLinker.cpp
index 6cc4a01..bf5f7d7 100644
--- a/lib/Target/Hexagon/HexagonELFMCLinker.cpp
+++ b/lib/Target/Hexagon/HexagonELFMCLinker.cpp
@@ -7,14 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 #include "HexagonELFMCLinker.h"
-#include <mcld/LinkerConfig.h>
 
 using namespace mcld;
 
 HexagonELFMCLinker::HexagonELFMCLinker(LinkerConfig& pConfig,
                                        mcld::Module& pModule,
-                                       MemoryArea& pOutput)
-  : ELFMCLinker(pConfig, pModule, pOutput) {
+                                       FileHandle& pFileHandle)
+  : ELFMCLinker(pConfig, pModule, pFileHandle) {
 }
 
 HexagonELFMCLinker::~HexagonELFMCLinker()
diff --git a/lib/Target/Hexagon/HexagonELFMCLinker.h b/lib/Target/Hexagon/HexagonELFMCLinker.h
index c588ddf..6bbfe26 100644
--- a/lib/Target/Hexagon/HexagonELFMCLinker.h
+++ b/lib/Target/Hexagon/HexagonELFMCLinker.h
@@ -16,7 +16,7 @@
 namespace mcld {
 
 class Module;
-class MemoryArea;
+class FileHandle;
 
 /** \class HexagonELFMCLinker
  *  \brief HexagonELFMCLinker sets up the environment for linking.
@@ -28,7 +28,7 @@
 public:
   HexagonELFMCLinker(LinkerConfig& pConfig,
                      mcld::Module& pModule,
-                     MemoryArea& pOutput);
+                     FileHandle& pFileHandle);
 
   ~HexagonELFMCLinker();
 };
diff --git a/lib/Target/Hexagon/HexagonGOT.cpp b/lib/Target/Hexagon/HexagonGOT.cpp
index 551b40f..637b078 100644
--- a/lib/Target/Hexagon/HexagonGOT.cpp
+++ b/lib/Target/Hexagon/HexagonGOT.cpp
@@ -27,22 +27,8 @@
 {
 }
 
-void HexagonGOT::reserve(size_t pNum)
+HexagonGOTEntry* HexagonGOT::create()
 {
-  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;
+  return new HexagonGOTEntry(0, m_SectionData);
 }
 
diff --git a/lib/Target/Hexagon/HexagonGOT.h b/lib/Target/Hexagon/HexagonGOT.h
index 4f9120c..c29239c 100644
--- a/lib/Target/Hexagon/HexagonGOT.h
+++ b/lib/Target/Hexagon/HexagonGOT.h
@@ -41,9 +41,7 @@
 
   ~HexagonGOT();
 
-  void reserve(size_t pNum = 1);
-
-  HexagonGOTEntry* consume();
+  HexagonGOTEntry* create();
 
 private:
   HexagonGOTEntry* m_pLast; ///< the last consumed entry
diff --git a/lib/Target/Hexagon/HexagonGOTPLT.cpp b/lib/Target/Hexagon/HexagonGOTPLT.cpp
index fee852f..cfceff5 100644
--- a/lib/Target/Hexagon/HexagonGOTPLT.cpp
+++ b/lib/Target/Hexagon/HexagonGOTPLT.cpp
@@ -23,12 +23,9 @@
 HexagonGOTPLT::HexagonGOTPLT(LDSection& pSection)
   : HexagonGOT(pSection)
 {
-  // Create GOT0 entries
-  reserve(HexagonGOTPLT0Num);
-
   // Skip GOT0 entries
   for (size_t i = 0; i < HexagonGOTPLT0Num; ++i) {
-    consume();
+    create();
   }
   pSection.setAlign(8);
 }
diff --git a/lib/Target/Hexagon/HexagonGOTPLT.h b/lib/Target/Hexagon/HexagonGOTPLT.h
index ad49992..9fc67cd 100644
--- a/lib/Target/Hexagon/HexagonGOTPLT.h
+++ b/lib/Target/Hexagon/HexagonGOTPLT.h
@@ -14,7 +14,6 @@
 
 #include <llvm/ADT/DenseMap.h>
 #include "HexagonGOT.h"
-#include <mcld/Support/MemoryRegion.h>
 
 namespace mcld {
 
diff --git a/lib/Target/Hexagon/HexagonLDBackend.cpp b/lib/Target/Hexagon/HexagonLDBackend.cpp
index fcf7fb3..5265c4b 100644
--- a/lib/Target/Hexagon/HexagonLDBackend.cpp
+++ b/lib/Target/Hexagon/HexagonLDBackend.cpp
@@ -21,7 +21,6 @@
 #include <mcld/Fragment/AlignFragment.h>
 #include <mcld/Fragment/FillFragment.h>
 #include <mcld/Fragment/RegionFragment.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
@@ -30,7 +29,9 @@
 #include <mcld/LD/BranchIslandFactory.h>
 #include <mcld/LD/StubFactory.h>
 #include <mcld/LD/LDContext.h>
-
+#include <mcld/LD/ELFFileFormat.h>
+#include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/ELFSegment.h>
 
 #include <cstring>
 
@@ -132,7 +133,7 @@
 }
 
 uint64_t HexagonLDBackend::emitSectionData(const LDSection& pSection,
-                                          MemoryRegion& pRegion) const
+                                           MemoryRegion& pRegion) const
 {
   if (!pRegion.size())
     return 0;
@@ -143,10 +144,9 @@
 
   if ((LinkerConfig::Object != config().codeGenType()) &&
       (!config().isCodeStatic())) {
-    if (&pSection == &(FileFormat->getPLT())) {
-      assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
+    if (FileFormat->hasPLT() && (&pSection == &(FileFormat->getPLT()))) {
 
-      unsigned char* buffer = pRegion.getBuffer();
+      unsigned char* buffer = pRegion.begin();
 
       m_pPLT->applyPLT0();
       m_pPLT->applyPLT1();
@@ -168,11 +168,12 @@
       }
       return RegionSize;
     }
-    else if (&pSection == &(FileFormat->getGOT())) {
+    else if (FileFormat->hasGOT() && (&pSection == &(FileFormat->getGOT()))) {
       RegionSize += emitGOTSectionData(pRegion);
       return RegionSize;
     }
-    else if (&pSection == &(FileFormat->getGOTPLT())) {
+    else if (FileFormat->hasGOTPLT() &&
+             (&pSection == &(FileFormat->getGOTPLT()))) {
       RegionSize += emitGOTPLTSectionData(pRegion, FileFormat);
       return RegionSize;
     }
@@ -180,7 +181,7 @@
 
   const SectionData* sect_data = pSection.getSectionData();
   SectionData::const_iterator frag_iter, frag_end = sect_data->end();
-  uint8_t* out_offset = pRegion.start();
+  uint8_t* out_offset = pRegion.begin();
   for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
     size_t size = frag_iter->size();
     switch(frag_iter->getKind()) {
@@ -197,7 +198,7 @@
       case Fragment::Region: {
         const RegionFragment& region_frag =
           llvm::cast<RegionFragment>(*frag_iter);
-        const uint8_t* start = region_frag.getRegion().start();
+        const char* start = region_frag.getRegion().begin();
         memcpy(out_offset, start, size);
         break;
       }
@@ -318,11 +319,12 @@
     m_pGOT->finalizeSectionSize();
 }
 
-uint64_t HexagonLDBackend::emitGOTSectionData(MemoryRegion& pRegion) const
+uint64_t
+HexagonLDBackend::emitGOTSectionData(MemoryRegion& pRegion) const
 {
   assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
 
-  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
 
   HexagonGOTEntry* got = 0;
   unsigned int EntrySize = HexagonGOTEntry::EntrySize;
@@ -367,13 +369,13 @@
 }
 
 uint64_t HexagonLDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion,
-                                         const ELFFileFormat* FileFormat) const
+    const ELFFileFormat* FileFormat) const
 {
   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());
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
 
   HexagonGOTEntry* got = 0;
   unsigned int EntrySize = HexagonGOTEntry::EntrySize;
@@ -395,19 +397,19 @@
   const ELFFileFormat* file_format = getOutputFormat();
 
   if (LinkerConfig::Object != config().codeGenType()) {
-    if (&pSectHdr == &file_format->getGOT()) {
+    if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
       if (config().options().hasNow())
         return SHO_RELRO;
       return SHO_RELRO_LAST;
     }
 
-    if (&pSectHdr == &file_format->getGOTPLT()) {
+    if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT())) {
       if (config().options().hasNow())
         return SHO_RELRO;
       return SHO_NON_RELRO_FIRST;
     }
 
-    if (&pSectHdr == &file_format->getPLT())
+    if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
       return SHO_PLT;
   }
 
@@ -658,33 +660,37 @@
   if (m_psdabase)
     m_psdabase->setValue(m_psdata->addr());
 
-  ELFSegment *edata = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD,
-                                             llvm::ELF::PF_W, llvm::ELF::PF_X);
-  if (NULL != edata) {
+  ELFSegmentFactory::const_iterator edata =
+    elfSegmentTable().find(llvm::ELF::PT_LOAD,
+                           llvm::ELF::PF_W,
+                           llvm::ELF::PF_X);
+  if (elfSegmentTable().end() != edata) {
     if (NULL != f_pEData && ResolveInfo::ThreadLocal != f_pEData->type()) {
-      f_pEData->setValue(edata->vaddr() + edata->filesz());
+      f_pEData->setValue((*edata)->vaddr() + (*edata)->filesz());
     }
     if (NULL != f_p_EData && ResolveInfo::ThreadLocal != f_p_EData->type()) {
-      f_p_EData->setValue(edata->vaddr() + edata->filesz());
+      f_p_EData->setValue((*edata)->vaddr() + (*edata)->filesz());
     }
     if (NULL != f_pBSSStart &&
         ResolveInfo::ThreadLocal != f_pBSSStart->type()) {
-      f_pBSSStart->setValue(edata->vaddr() + edata->filesz());
+      f_pBSSStart->setValue((*edata)->vaddr() + (*edata)->filesz());
     }
     if (NULL != f_pEnd && ResolveInfo::ThreadLocal != f_pEnd->type()) {
-      f_pEnd->setValue(((edata->vaddr() +
-                       edata->memsz()) + 7) & ~7);
+      f_pEnd->setValue((((*edata)->vaddr() +
+                       (*edata)->memsz()) + 7) & ~7);
     }
     if (NULL != f_p_End && ResolveInfo::ThreadLocal != f_p_End->type()) {
-      f_p_End->setValue(((edata->vaddr() +
-                       edata->memsz()) + 7) & ~7);
+      f_p_End->setValue((((*edata)->vaddr() +
+                        (*edata)->memsz()) + 7) & ~7);
     }
   }
   return true;
 }
 
 /// merge Input Sections
-bool HexagonLDBackend::mergeSection(Module& pModule, LDSection& pInputSection)
+bool HexagonLDBackend::mergeSection(Module& pModule,
+                                    const Input& pInputFile,
+                                    LDSection& pInputSection)
 {
   if ((pInputSection.flag() & llvm::ELF::SHF_HEX_GPREL) ||
       (pInputSection.kind() == LDFileFormat::LinkOnce) ||
@@ -699,7 +705,7 @@
   }
   else {
     ObjectBuilder builder(config(), pModule);
-    return builder.MergeSection(pInputSection);
+    builder.MergeSection(pInputFile, pInputSection);
   }
   return true;
 }
@@ -785,7 +791,6 @@
       // description here.
       (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
       Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
       switch((*com_sym)->size())  {
       case 1:
@@ -794,6 +799,7 @@
         ObjectBuilder::AppendFragment(*frag,
                                       *(m_pscommon_1->getSectionData()),
                                       (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
         continue;
       case 2:
         if (maxGPSize <= 1)
@@ -801,6 +807,7 @@
         ObjectBuilder::AppendFragment(*frag,
                                       *(m_pscommon_2->getSectionData()),
                                       (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
         continue;
       case 4:
         if (maxGPSize <= 3)
@@ -808,6 +815,7 @@
         ObjectBuilder::AppendFragment(*frag,
                                       *(m_pscommon_4->getSectionData()),
                                       (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
         continue;
       case 8:
         if (maxGPSize <= 7)
@@ -815,6 +823,7 @@
         ObjectBuilder::AppendFragment(*frag,
                                       *(m_pscommon_8->getSectionData()),
                                       (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
         continue;
       default:
         break;
@@ -825,12 +834,14 @@
         tbss_offset += ObjectBuilder::AppendFragment(*frag,
                                                      *tbss_sect_data,
                                                      (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       }
       // FIXME: how to identify small and large common symbols?
       else {
         bss_offset += ObjectBuilder::AppendFragment(*frag,
                                                     *bss_sect_data,
                                                     (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       }
     }
   }
@@ -845,7 +856,6 @@
     // description here.
     (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
     Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
     switch((*com_sym)->size())  {
     case 1:
@@ -854,6 +864,7 @@
       ObjectBuilder::AppendFragment(*frag,
                                     *(m_pscommon_1->getSectionData()),
                                     (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       continue;
     case 2:
       if (maxGPSize <= 1)
@@ -861,6 +872,7 @@
       ObjectBuilder::AppendFragment(*frag,
                                     *(m_pscommon_2->getSectionData()),
                                     (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       continue;
     case 4:
       if (maxGPSize <= 3)
@@ -868,6 +880,7 @@
       ObjectBuilder::AppendFragment(*frag,
                                     *(m_pscommon_4->getSectionData()),
                                     (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       continue;
     case 8:
       if (maxGPSize <= 7)
@@ -875,6 +888,7 @@
       ObjectBuilder::AppendFragment(*frag,
                                     *(m_pscommon_8->getSectionData()),
                                     (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       continue;
     default:
       break;
@@ -885,12 +899,14 @@
       tbss_offset += ObjectBuilder::AppendFragment(*frag,
                                                    *tbss_sect_data,
                                                    (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
     }
     // FIXME: how to identify small and large common symbols?
     else {
       bss_offset += ObjectBuilder::AppendFragment(*frag,
                                                   *bss_sect_data,
                                                   (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
     }
   }
 
@@ -954,14 +970,14 @@
     frag = new FillFragment(0x0, 1, size);
   }
   else {
-    MemoryRegion* region = pInput.memArea()->request(offset, size);
-    if (NULL == region) {
+    llvm::StringRef region = pInput.memArea()->request(offset, size);
+    if (region.size() == 0) {
       // If the input section's size is zero, we got a NULL region.
       // use a virtual fill fragment
       frag = new FillFragment(0x0, 0, 0);
     }
     else {
-      frag = new RegionFragment(*region);
+      frag = new RegionFragment(region);
     }
   }
 
@@ -1040,8 +1056,7 @@
 //===----------------------------------------------------------------------===//
 /// createHexagonLDBackend - the help funtion to create corresponding
 /// HexagonLDBackend
-TargetLDBackend* createHexagonLDBackend(const llvm::Target& pTarget,
-                                    const LinkerConfig& pConfig)
+TargetLDBackend* createHexagonLDBackend(const LinkerConfig& pConfig)
 {
   if (pConfig.targets().triple().isOSDarwin()) {
     assert(0 && "MachO linker is not supported yet");
diff --git a/lib/Target/Hexagon/HexagonLDBackend.h b/lib/Target/Hexagon/HexagonLDBackend.h
index 30a9f35..e2bc2bb 100644
--- a/lib/Target/Hexagon/HexagonLDBackend.h
+++ b/lib/Target/Hexagon/HexagonLDBackend.h
@@ -126,7 +126,7 @@
   bool finalizeTargetSymbols();
 
   /// mergeSection - merge target dependent sections
-  bool mergeSection(Module& pModule, LDSection& pSection);
+  bool mergeSection(Module& pModule, const Input& pInput, LDSection& pSection);
 
   /// readSection - read target dependent sections
   bool readSection(Input& pInput, SectionData& pSD);
diff --git a/lib/Target/Hexagon/HexagonMCLinker.cpp b/lib/Target/Hexagon/HexagonMCLinker.cpp
index 4f4f839..770ae94 100644
--- a/lib/Target/Hexagon/HexagonMCLinker.cpp
+++ b/lib/Target/Hexagon/HexagonMCLinker.cpp
@@ -21,9 +21,9 @@
 MCLinker* createHexagonMCLinker(const std::string &pTriple,
                                 LinkerConfig& pConfig,
                                 mcld::Module& pModule,
-                                MemoryArea& pOutput)
+                                FileHandle& pFileHandle)
 {
-  Triple theTriple(pTriple);
+  llvm::Triple theTriple(pTriple);
   if (theTriple.isOSDarwin()) {
     assert(0 && "MachO linker has not supported yet");
     return NULL;
@@ -34,7 +34,7 @@
   }
 
   if (theTriple.isArch32Bit())
-    return new HexagonELFMCLinker(pConfig, pModule, pOutput);
+    return new HexagonELFMCLinker(pConfig, pModule, pFileHandle);
 
   assert(0 && "Hexagon_64 has not supported yet");
   return NULL;
diff --git a/lib/Target/Hexagon/HexagonPLT.cpp b/lib/Target/Hexagon/HexagonPLT.cpp
index ceb8a58..6309408 100644
--- a/lib/Target/Hexagon/HexagonPLT.cpp
+++ b/lib/Target/Hexagon/HexagonPLT.cpp
@@ -49,7 +49,6 @@
   m_PLT0Size = sizeof (hexagon_plt0);
   // create PLT0
   new HexagonPLT0(*m_SectionData);
-  m_Last = m_SectionData->begin();
   pSection.setAlign(16);
 }
 
@@ -98,25 +97,9 @@
   return (m_SectionData->size() > 1);
 }
 
-void HexagonPLT::reserveEntry(size_t pNum)
+HexagonPLT1* HexagonPLT::create()
 {
-  PLTEntryBase* plt1_entry = NULL;
-
-  for (size_t i = 0; i < pNum; ++i) {
-    plt1_entry = new HexagonPLT1(*m_SectionData);
-
-    if (NULL == plt1_entry)
-      fatal(diag::fail_allocate_memory_plt);
-  }
-}
-
-HexagonPLT1* HexagonPLT::consume()
-{
-  ++m_Last;
-  assert(m_Last != m_SectionData->end() &&
-         "The number of PLT Entries and ResolveInfo doesn't match");
-
-  return llvm::cast<HexagonPLT1>(&(*m_Last));
+  return new HexagonPLT1(*m_SectionData);
 }
 
 void HexagonPLT::applyPLT0()
@@ -200,7 +183,7 @@
   uint64_t result = 0x0;
   iterator it = begin();
 
-  unsigned char* buffer = pRegion.getBuffer();
+  unsigned char* buffer = pRegion.begin();
   memcpy(buffer, llvm::cast<HexagonPLT0>((*it)).getValue(), HexagonPLT0::EntrySize);
   result += HexagonPLT0::EntrySize;
   ++it;
diff --git a/lib/Target/Hexagon/HexagonPLT.h b/lib/Target/Hexagon/HexagonPLT.h
index 8cf7e47..abdb4ea 100644
--- a/lib/Target/Hexagon/HexagonPLT.h
+++ b/lib/Target/Hexagon/HexagonPLT.h
@@ -13,6 +13,7 @@
 #include "HexagonGOTPLT.h"
 #include <mcld/Target/GOT.h>
 #include <mcld/Target/PLT.h>
+#include <mcld/Support/MemoryRegion.h>
 
 namespace {
 
@@ -44,7 +45,6 @@
 
 class GOTEntry;
 class LinkerConfig;
-class MemoryRegion;
 class HexagonPLT1;
 
 //===----------------------------------------------------------------------===//
@@ -76,9 +76,7 @@
   // hasPLT1 - return if this PLT has any PLT1 entry
   bool hasPLT1() const;
 
-  void reserveEntry(size_t pNum = 1) ;
-
-  HexagonPLT1* consume();
+  HexagonPLT1* create();
 
   void applyPLT0();
 
@@ -91,9 +89,6 @@
 private:
   HexagonGOTPLT& m_GOTPLT;
 
-  // the last consumed entry.
-  SectionData::iterator m_Last;
-
   const uint8_t *m_PLT0;
   unsigned int m_PLT0Size;
 
diff --git a/lib/Target/Hexagon/HexagonRelocationFunctions.h b/lib/Target/Hexagon/HexagonRelocationFunctions.h
index a5e6b87..6f9acad 100644
--- a/lib/Target/Hexagon/HexagonRelocationFunctions.h
+++ b/lib/Target/Hexagon/HexagonRelocationFunctions.h
@@ -39,84 +39,59 @@
 
 #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(relocB7PCREL)      \
-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(relocGPREL16_0)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocGPREL16_1)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocGPREL16_2)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocGPREL16_3)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocB13PCREL)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocB9PCREL)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocB32PCRELX)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(reloc32_6_X)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocB22PCRELX)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocB15PCRELX)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocB13PCRELX)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocB9PCRELX)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocB7PCRELX)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(reloc32PCREL)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocHexNX)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocHexGOTRELLO16)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocHexGOTRELHI16)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocHexGOTREL32)  \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocPCREL)     \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocGPREL)     \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocAbs)     \
 DECL_HEXAGON_APPLY_RELOC_FUNC(relocPLTB22PCREL)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocHex6PCRELX)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocHexGOT326X)  \
-DECL_HEXAGON_APPLY_RELOC_FUNC(relocHexGOT1611X)  \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocGOTREL)  \
+DECL_HEXAGON_APPLY_RELOC_FUNC(relocGOT)  \
 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"                   }, \
-  { &relocB7PCREL,        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"                           }, \
-  { &relocGPREL16_0,      9, "R_HEX_GPREL16_0"                   }, \
-  { &relocGPREL16_1,      10, "R_HEX_GPREL16_1"                  }, \
-  { &relocGPREL16_2,      11, "R_HEX_GPREL16_2"                  }, \
-  { &relocGPREL16_3,      12, "R_HEX_GPREL16_3"                  }, \
+  { &relocPCREL,          1, "R_HEX_B22_PCREL"                   }, \
+  { &relocPCREL,          2, "R_HEX_B15_PCREL"                   }, \
+  { &relocPCREL,          3, "R_HEX_B7_PCREL"                    }, \
+  { &relocAbs,            4, "R_HEX_LO16"                        }, \
+  { &relocAbs,            5, "R_HEX_HI16"                        }, \
+  { &relocAbs,            6, "R_HEX_32"                          }, \
+  { &relocAbs,            7, "R_HEX_16"                          }, \
+  { &relocAbs,            8, "R_HEX_8"                           }, \
+  { &relocGPREL,          9, "R_HEX_GPREL16_0"                   }, \
+  { &relocGPREL,          10, "R_HEX_GPREL16_1"                  }, \
+  { &relocGPREL,          11, "R_HEX_GPREL16_2"                  }, \
+  { &relocGPREL,          12, "R_HEX_GPREL16_3"                  }, \
   { &unsupport,           13, "R_HEX_HL16"                       }, \
-  { &relocB13PCREL,       14, "R_HEX_B13_PCREL"                  }, \
-  { &relocB9PCREL,        15, "R_HEX_B9_PCREL"                   }, \
-  { &relocB32PCRELX,      16, "R_HEX_B32_PCREL_X"                }, \
-  { &reloc32_6_X,         17, "R_HEX_32_6_X"                     }, \
-  { &relocB22PCRELX,      18, "R_HEX_B22_PCREL_X"                }, \
-  { &relocB15PCRELX,      19, "R_HEX_B15_PCREL_X"                }, \
-  { &relocB13PCRELX,      20, "R_HEX_B13_PCREL_X"                }, \
-  { &relocB9PCRELX,       21, "R_HEX_B9_PCREL_X"                 }, \
-  { &relocB7PCRELX,       22, "R_HEX_B7_PCREL_X"                 }, \
-  { &relocHexNX,          23, "R_HEX_16_X"                       }, \
-  { &relocHexNX,          24, "R_HEX_12_X"                       }, \
-  { &relocHexNX,          25, "R_HEX_11_X"                       }, \
-  { &relocHexNX,          26, "R_HEX_10_X"                       }, \
-  { &relocHexNX,          27, "R_HEX_9_X"                        }, \
-  { &relocHexNX,          28, "R_HEX_8_X"                        }, \
-  { &relocHexNX,          29, "R_HEX_7_X"                        }, \
-  { &relocHexNX,          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"                   }, \
+  { &relocPCREL,          14, "R_HEX_B13_PCREL"                  }, \
+  { &relocPCREL,          15, "R_HEX_B9_PCREL"                   }, \
+  { &relocPCREL,          16, "R_HEX_B32_PCREL_X"                }, \
+  { &relocAbs,            17, "R_HEX_32_6_X"                     }, \
+  { &relocPCREL,          18, "R_HEX_B22_PCREL_X"                }, \
+  { &relocPCREL,          19, "R_HEX_B15_PCREL_X"                }, \
+  { &relocPCREL,          20, "R_HEX_B13_PCREL_X"                }, \
+  { &relocPCREL,          21, "R_HEX_B9_PCREL_X"                 }, \
+  { &relocPCREL,          22, "R_HEX_B7_PCREL_X"                 }, \
+  { &relocAbs,            23, "R_HEX_16_X"                       }, \
+  { &relocAbs,            24, "R_HEX_12_X"                       }, \
+  { &relocAbs,            25, "R_HEX_11_X"                       }, \
+  { &relocAbs,            26, "R_HEX_10_X"                       }, \
+  { &relocAbs,            27, "R_HEX_9_X"                        }, \
+  { &relocAbs,            28, "R_HEX_8_X"                        }, \
+  { &relocAbs,            29, "R_HEX_7_X"                        }, \
+  { &relocAbs,            30, "R_HEX_6_X"                        }, \
+  { &relocPCREL,          31, "R_HEX_32_PCREL"                   }, \
+  { &none,                32, "R_HEX_COPY"                       }, \
+  { &none,                33, "R_HEX_GLOB_DAT"                   }, \
+  { &none,                34, "R_HEX_JMP_SLOT"                   }, \
+  { &none,                35, "R_HEX_RELATIVE"                   }, \
   { &relocPLTB22PCREL,    36, "R_HEX_PLT_B22_PCREL"              }, \
-  { &relocHexGOTRELLO16,  37, "R_HEX_GOTREL_LO16"                }, \
-  { &relocHexGOTRELHI16,  38, "R_HEX_GOTREL_HI16"                }, \
-  { &relocHexGOTREL32,    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"                     }, \
+  { &relocGOTREL,         37, "R_HEX_GOTREL_LO16"                }, \
+  { &relocGOTREL,         38, "R_HEX_GOTREL_HI16"                }, \
+  { &relocGOTREL,         39, "R_HEX_GOTREL_32"                  }, \
+  { &relocGOT,            40, "R_HEX_GOT_LO16"                   }, \
+  { &relocGOT,            41, "R_HEX_GOT_HI16"                   }, \
+  { &relocGOT,            42, "R_HEX_GOT_32"                     }, \
+  { &relocGOT,            43, "R_HEX_GOT_16"                     }, \
   { &unsupport,           44, "R_HEX_DTPMOD_32"                  }, \
   { &unsupport,           45, "R_HEX_DTPREL_LO16"                }, \
   { &unsupport,           46, "R_HEX_DTPREL_HI16"                }, \
@@ -138,13 +113,13 @@
   { &unsupport,           62, "R_HEX_TPREL_HI16"                 }, \
   { &unsupport,           63, "R_HEX_TPREL_32"                   }, \
   { &unsupport,           64, "R_HEX_TPREL_16"                   }, \
-  { &relocHex6PCRELX,     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"                }, \
-  { &relocHexGOT326X,     69, "R_HEX_GOT_32_6_X"                 }, \
-  { &relocHexGOT1611X,    70, "R_HEX_GOT_16_X"                   }, \
-  { &relocHexGOT1611X,    71, "R_HEX_GOT_11_X"                   }, \
+  { &relocPCREL,          65, "R_HEX_6_PCREL_X"                  }, \
+  { &relocGOTREL,         66, "R_HEX_GOTREL_32_6_X"              }, \
+  { &relocGOTREL,         67, "R_HEX_GOTREL_16_X"                }, \
+  { &relocGOTREL,         68, "R_HEX_GOTREL_11_X"                }, \
+  { &relocGOT,            69, "R_HEX_GOT_32_6_X"                 }, \
+  { &relocGOT,            70, "R_HEX_GOT_16_X"                   }, \
+  { &relocGOT,            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"                }, \
diff --git a/lib/Target/Hexagon/HexagonRelocator.cpp b/lib/Target/Hexagon/HexagonRelocator.cpp
index ba387cf..b82bbcd 100644
--- a/lib/Target/Hexagon/HexagonRelocator.cpp
+++ b/lib/Target/Hexagon/HexagonRelocator.cpp
@@ -6,34 +6,133 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#include <llvm/ADT/Twine.h>
-#include <mcld/LD/LDSymbol.h>
-#include <llvm/Support/DataTypes.h>
-#include <llvm/Support/ELF.h>
-#include <mcld/Support/MsgHandling.h>
-
 #include "HexagonRelocator.h"
 #include "HexagonRelocationFunctions.h"
 #include "HexagonEncodings.h"
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/ELF.h>
+
+#include <mcld/LD/ELFFileFormat.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
 //===--------------------------------------------------------------------===//
+// Relocation Helper Functions
+//===--------------------------------------------------------------------===//
+/// helper_DynRel - Get an relocation entry in .rela.dyn
+static Relocation &helper_DynRel_init(ResolveInfo *pSym,
+                                      Fragment &pFrag,
+                                      uint64_t pOffset,
+                                      HexagonRelocator::Type pType,
+                                      HexagonRelocator &pParent) {
+  HexagonLDBackend &ld_backend = pParent.getTarget();
+  Relocation &rela_entry = *ld_backend.getRelaDyn().create();
+  rela_entry.setType(pType);
+  rela_entry.targetRef().assign(pFrag, pOffset);
+  if (pType == llvm::ELF::R_HEX_RELATIVE || NULL == pSym)
+    rela_entry.setSymInfo(0);
+  else
+    rela_entry.setSymInfo(pSym);
+
+  return rela_entry;
+}
+
+/// helper_use_relative_reloc - Check if symbol can use relocation
+/// R_HEX_RELATIVE
+static bool helper_use_relative_reloc(const ResolveInfo &pSym,
+                                      const HexagonRelocator &pFactory) {
+  // if symbol is dynamic or undefine or preemptible
+  if (pSym.isDyn() || pSym.isUndef() ||
+      pFactory.getTarget().isSymbolPreemptible(pSym))
+    return false;
+  return true;
+}
+
+static HexagonGOTEntry &helper_GOT_init(Relocation &pReloc,
+                                        bool pHasRel,
+                                        HexagonRelocator &pParent) {
+  // rsym - The relocation target symbol
+  ResolveInfo *rsym = pReloc.symInfo();
+  HexagonLDBackend &ld_backend = pParent.getTarget();
+  assert(NULL == pParent.getSymGOTMap().lookUp(*rsym));
+
+  HexagonGOTEntry *got_entry = ld_backend.getGOT().create();
+  pParent.getSymGOTMap().record(*rsym, *got_entry);
+
+  if (!pHasRel) {
+    // No corresponding dynamic relocation, initialize to the symbol value.
+    got_entry->setValue(HexagonRelocator::SymVal);
+  }
+  else {
+    // Initialize got_entry content and the corresponding dynamic relocation.
+    if (helper_use_relative_reloc(*rsym, pParent)) {
+      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_RELATIVE,
+                                                                       pParent);
+      got_entry->setValue(HexagonRelocator::SymVal);
+    }
+    else {
+      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_GLOB_DAT,
+                                                                       pParent);
+      got_entry->setValue(0);
+    }
+  }
+  return *got_entry;
+}
+
+static HexagonRelocator::Address helper_get_GOT_address(ResolveInfo &pSym,
+                                                    HexagonRelocator &pParent) {
+  HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(pSym);
+  assert(NULL != got_entry);
+  return pParent.getTarget().getGOT().addr() + got_entry->getOffset();
+}
+
+static PLTEntryBase &helper_PLT_init(Relocation &pReloc,
+                                     HexagonRelocator &pParent) {
+  // rsym - The relocation target symbol
+  ResolveInfo *rsym = pReloc.symInfo();
+  HexagonLDBackend &ld_backend = pParent.getTarget();
+  assert(NULL == pParent.getSymPLTMap().lookUp(*rsym));
+
+  PLTEntryBase *plt_entry = ld_backend.getPLT().create();
+  pParent.getSymPLTMap().record(*rsym, *plt_entry);
+
+  assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) &&
+         "PLT entry not exist, but DynRel entry exist!");
+  HexagonGOTEntry *gotplt_entry = ld_backend.getGOTPLT().create();
+  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
+  // init the corresponding rel entry in .rela.plt
+  Relocation &rela_entry = *ld_backend.getRelaPLT().create();
+  rela_entry.setType(llvm::ELF::R_HEX_JMP_SLOT);
+  rela_entry.targetRef().assign(*gotplt_entry);
+  rela_entry.setSymInfo(rsym);
+
+  return *plt_entry;
+}
+
+static HexagonRelocator::Address helper_get_PLT_address(ResolveInfo& pSym,
+                                                    HexagonRelocator &pParent) {
+  PLTEntryBase *plt_entry = pParent.getSymPLTMap().lookUp(pSym);
+  assert(NULL != plt_entry);
+  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
+}
+
+//===--------------------------------------------------------------------===//
 // Relocation Functions and Tables
 //===--------------------------------------------------------------------===//
 DECL_HEXAGON_APPLY_RELOC_FUNCS
 
-/// the prototype of applying function
-typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
-                                               HexagonRelocator& pParent);
+    /// the prototype of applying function
+    typedef Relocator::Result (*ApplyFunctionType)(Relocation &pReloc,
+                                                   HexagonRelocator &pParent);
 
 // the table entry of applying functions
-struct ApplyFunctionTriple
-{
+struct ApplyFunctionTriple {
   ApplyFunctionType func;
   unsigned int type;
-  const char* name;
+  const char *name;
 };
 
 // declare the table of applying functions
@@ -41,8 +140,9 @@
   DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS
 };
 
-static uint32_t findBitMask(uint32_t insn, Instruction *encodings, int32_t numInsns) {
-  for (int32_t i = 0; i < numInsns ; i++) {
+static uint32_t findBitMask(uint32_t insn, Instruction *encodings,
+                            int32_t numInsns) {
+  for (int32_t i = 0; i < numInsns; i++) {
     if (((insn & 0xc000) == 0) && !(encodings[i].isDuplex))
       continue;
 
@@ -53,30 +153,25 @@
       return encodings[i].insnBitMask;
   }
   assert(0);
+  // Should not be here, but add a return for -Werror=return-type
+  // error: control reaches end of non-void function
+  return -1;
 }
 
-
-#define FINDBITMASK(INSN) \
-  findBitMask((uint32_t)INSN,\
-              insn_encodings,\
+#define FINDBITMASK(INSN)                                                      \
+  findBitMask((uint32_t) INSN, insn_encodings,                                 \
               sizeof(insn_encodings) / sizeof(Instruction))
 
 //===--------------------------------------------------------------------===//
 // HexagonRelocator
 //===--------------------------------------------------------------------===//
-HexagonRelocator::HexagonRelocator(HexagonLDBackend& pParent,
-                                   const LinkerConfig& pConfig)
-  : Relocator(pConfig),
-    m_Target(pParent) {
-}
+HexagonRelocator::HexagonRelocator(HexagonLDBackend &pParent,
+                                   const LinkerConfig &pConfig)
+    : Relocator(pConfig), m_Target(pParent) {}
 
-HexagonRelocator::~HexagonRelocator()
-{
-}
+HexagonRelocator::~HexagonRelocator() {}
 
-Relocator::Result
-HexagonRelocator::applyRelocation(Relocation& pRelocation)
-{
+Relocator::Result HexagonRelocator::applyRelocation(Relocation &pRelocation) {
   Relocation::Type type = pRelocation.type();
 
   if (type > 85) { // 86-255 relocs do not exists for Hexagon
@@ -87,30 +182,27 @@
   return ApplyFunctions[type].func(pRelocation, *this);
 }
 
-const char* HexagonRelocator::getName(Relocation::Type pType) const
-{
+const char *HexagonRelocator::getName(Relocation::Type pType) const {
   return ApplyFunctions[pType].name;
 }
 
-Relocator::Size HexagonRelocator::getSize(Relocation::Type pType) const
-{
+Relocator::Size HexagonRelocator::getSize(Relocation::Type pType) const {
   return 32;
 }
 
-void HexagonRelocator::scanRelocation(Relocation& pReloc,
-                                      IRBuilder& pLinker,
-                                      Module& pModule,
-                                      LDSection& pSection)
-{
+void HexagonRelocator::scanRelocation(Relocation &pReloc, IRBuilder &pLinker,
+                                      Module &pModule, LDSection &pSection, Input &pInput) {
   if (LinkerConfig::Object == config().codeGenType())
     return;
 
-  pReloc.updateAddend();
   // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
+  ResolveInfo *rsym = pReloc.symInfo();
   assert(NULL != rsym &&
          "ResolveInfo of relocation not set while scanRelocation");
 
+  if (config().isCodeStatic())
+    return;
+
   assert(NULL != pSection.getLink());
   if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC))
     return;
@@ -123,106 +215,179 @@
   // 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();
+    issueUndefRef(pReloc, pSection, pInput);
 }
 
-void HexagonRelocator::addCopyReloc(ResolveInfo& pSym,
-                                    HexagonLDBackend& pTarget)
-{
-  Relocation& rel_entry = *pTarget.getRelaDyn().consumeEntry();
+void HexagonRelocator::addCopyReloc(ResolveInfo &pSym,
+                                    HexagonLDBackend &pTarget) {
+  Relocation &rel_entry = *pTarget.getRelaDyn().create();
   rel_entry.setType(pTarget.getCopyRelType());
   assert(pSym.outSymbol()->hasFragRef());
   rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
   rel_entry.setSymInfo(&pSym);
 }
 
-void HexagonRelocator::scanLocalReloc(Relocation& pReloc,
-                                     IRBuilder& pBuilder,
-                                     Module& pModule,
-                                     LDSection& pSection)
-{
+void HexagonRelocator::scanLocalReloc(Relocation &pReloc, IRBuilder &pBuilder,
+                                      Module &pModule, LDSection &pSection) {
   // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
+  ResolveInfo *rsym = pReloc.symInfo();
 
-  switch(pReloc.type()){
+  switch (pReloc.type()) {
 
-    case llvm::ELF::R_HEX_32:
-    case llvm::ELF::R_HEX_16:
-    case llvm::ELF::R_HEX_8:
-      // 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 (config().isCodeIndep()) {
-        getTarget().getRelaDyn().reserveEntry();
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | ReserveRel);
-        getTarget().checkAndSetHasTextRel(*pSection.getLink());
-      }
-      return;
+  case llvm::ELF::R_HEX_LO16:
+  case llvm::ELF::R_HEX_HI16:
+  case llvm::ELF::R_HEX_16:
+  case llvm::ELF::R_HEX_8:
+  case llvm::ELF::R_HEX_32_6_X:
+  case llvm::ELF::R_HEX_16_X:
+  case llvm::ELF::R_HEX_12_X:
+  case llvm::ELF::R_HEX_11_X:
+  case llvm::ELF::R_HEX_10_X:
+  case llvm::ELF::R_HEX_9_X:
+  case llvm::ELF::R_HEX_8_X:
+  case llvm::ELF::R_HEX_7_X:
+  case llvm::ELF::R_HEX_6_X:
+    assert(!(rsym->reserved() & ReserveRel) &&
+           "Cannot apply this relocation for read only section");
+    return;
 
-    default:
-      break;
+  case llvm::ELF::R_HEX_32:
+    // 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 (config().isCodeIndep()) {
+      Relocation &reloc = helper_DynRel_init(rsym,
+                                             *pReloc.targetRef().frag(),
+                                             pReloc.targetRef().offset(),
+                                             llvm::ELF::R_HEX_RELATIVE,
+                                             *this);
+      // we need to set up the relocation addend at apply relocation, record the
+      // relocation
+      getRelRelMap().record(pReloc, reloc);
+
+      // set Rel bit
+      rsym->setReserved(rsym->reserved() | ReserveRel);
+      getTarget().checkAndSetHasTextRel(*pSection.getLink());
+    }
+    return;
+
+  default:
+    return;
   }
 }
 
-void HexagonRelocator::scanGlobalReloc(Relocation& pReloc,
-                                       IRBuilder& pBuilder,
-                                       Module& pModule,
-                                       LDSection& pSection)
-{
+void HexagonRelocator::scanGlobalReloc(Relocation &pReloc, IRBuilder &pBuilder,
+                                       Module &pModule, LDSection &pSection) {
   // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
+  ResolveInfo *rsym = pReloc.symInfo();
+  HexagonLDBackend &ld_backend = getTarget();
 
-  switch(pReloc.type()) {
-    case llvm::ELF::R_HEX_PLT_B22_PCREL:
-      // return if we already create plt for this symbol
-      if (rsym->reserved() & ReservePLT)
-        return;
+  switch (pReloc.type()) {
+  case llvm::ELF::R_HEX_LO16:
+  case llvm::ELF::R_HEX_HI16:
+  case llvm::ELF::R_HEX_16:
+  case llvm::ELF::R_HEX_8:
+  case llvm::ELF::R_HEX_32_6_X:
+  case llvm::ELF::R_HEX_16_X:
+  case llvm::ELF::R_HEX_12_X:
+  case llvm::ELF::R_HEX_11_X:
+  case llvm::ELF::R_HEX_10_X:
+  case llvm::ELF::R_HEX_9_X:
+  case llvm::ELF::R_HEX_8_X:
+  case llvm::ELF::R_HEX_7_X:
+  case llvm::ELF::R_HEX_6_X:
+    assert(!(rsym->reserved() & ReserveRel) &&
+           "Cannot apply this relocation for read only section");
+    return;
 
-      // Symbol needs PLT entry, we need to reserve a PLT entry
-      // and the corresponding GOT and dynamic relocation entry
-      // in .got.plt and .rela.plt.
-      getTarget().getPLT().reserveEntry();
-      getTarget().getGOTPLT().reserve();
-      getTarget().getRelaPLT().reserveEntry();
-      // set PLT bit
-      rsym->setReserved(rsym->reserved() | ReservePLT);
-      return;
-
-    case llvm::ELF::R_HEX_GOT_32_6_X:
-    case llvm::ELF::R_HEX_GOT_16_X:
-    case llvm::ELF::R_HEX_GOT_11_X:
-      // Symbol needs GOT entry, reserve entry in .got
-      // return if we already create GOT for this symbol
-      if (rsym->reserved() & (ReserveGOT | GOTRel))
-        return;
-      // FIXME: check STT_GNU_IFUNC symbol
-      getTarget().getGOT().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;
+  case llvm::ELF::R_HEX_32:
+    if (ld_backend.symbolNeedsPLT(*rsym)) {
+      //create PLT for this symbol if it does not have.
+      if (!(rsym->reserved() & ReservePLT)) {
+        helper_PLT_init(pReloc, *this);
+        rsym->setReserved(rsym->reserved() | ReservePLT);
       }
-      // 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
-      if (LinkerConfig::DynObj ==
-                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
-        getTarget().getRelaDyn().reserveEntry();
-        // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | GOTRel);
-        return;
-      }
-      // set GOT bit
-      rsym->setReserved(rsym->reserved() | ReserveGOT);
-      return;
-
-    default: {
-      break;
     }
-  } // end switch
+
+    if (ld_backend.symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                                     true)) {
+      if (ld_backend.symbolNeedsCopyReloc(pReloc, *rsym)) {
+        LDSymbol &cpy_sym =
+            defineSymbolforCopyReloc(pBuilder, *rsym, ld_backend);
+        addCopyReloc(*cpy_sym.resolveInfo(), ld_backend);
+      }
+      else {
+        Relocation &reloc = helper_DynRel_init(rsym,
+                                               *pReloc.targetRef().frag(),
+                                               pReloc.targetRef().offset(),
+                                               llvm::ELF::R_HEX_RELATIVE,
+                                               *this);
+        // we need to set up the relocation addend at apply relocation, record the
+        // relocation
+        getRelRelMap().record(pReloc, reloc);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+        ld_backend.checkAndSetHasTextRel(*pSection.getLink());
+      }
+    }
+    return;
+
+  case llvm::ELF::R_HEX_GOTREL_LO16:
+  case llvm::ELF::R_HEX_GOTREL_HI16:
+  case llvm::ELF::R_HEX_GOTREL_32:
+  case llvm::ELF::R_HEX_GOTREL_32_6_X:
+  case llvm::ELF::R_HEX_GOTREL_16_X:
+  case llvm::ELF::R_HEX_GOTREL_11_X:
+    // This assumes that GOT exists
+    return;
+
+  case llvm::ELF::R_HEX_GOT_LO16:
+  case llvm::ELF::R_HEX_GOT_HI16:
+  case llvm::ELF::R_HEX_GOT_32:
+  case llvm::ELF::R_HEX_GOT_16:
+  case llvm::ELF::R_HEX_GOT_32_6_X:
+  case llvm::ELF::R_HEX_GOT_16_X:
+  case llvm::ELF::R_HEX_GOT_11_X:
+    // Symbol needs GOT entry, reserve entry in .got
+    // return if we already create GOT for this symbol
+    if (rsym->reserved() & ReserveGOT)
+      return;
+    // If the GOT is used in statically linked binaries,
+    // the GOT entry is enough and no relocation is needed.
+    if (config().isCodeStatic())
+      helper_GOT_init(pReloc, false, *this);
+    else
+      helper_GOT_init(pReloc, true, *this);
+    // set GOT bit
+    rsym->setReserved(rsym->reserved() | ReserveGOT);
+    return;
+
+  case llvm::ELF::R_HEX_B22_PCREL:
+  case llvm::ELF::R_HEX_B15_PCREL:
+  case llvm::ELF::R_HEX_B7_PCREL:
+  case llvm::ELF::R_HEX_B13_PCREL:
+  case llvm::ELF::R_HEX_B9_PCREL:
+  case llvm::ELF::R_HEX_B32_PCREL_X:
+  case llvm::ELF::R_HEX_B22_PCREL_X:
+  case llvm::ELF::R_HEX_B15_PCREL_X:
+  case llvm::ELF::R_HEX_B13_PCREL_X:
+  case llvm::ELF::R_HEX_B9_PCREL_X:
+  case llvm::ELF::R_HEX_B7_PCREL_X:
+  case llvm::ELF::R_HEX_32_PCREL:
+  case llvm::ELF::R_HEX_6_PCREL_X:
+  case llvm::ELF::R_HEX_PLT_B22_PCREL:
+    if (rsym->reserved() & ReservePLT)
+      return;
+    if (ld_backend.symbolNeedsPLT(*rsym) ||
+        pReloc.type() == llvm::ELF::R_HEX_PLT_B22_PCREL) {
+      helper_PLT_init(pReloc, *this);
+      rsym->setReserved(rsym->reserved() | ReservePLT);
+    }
+    return;
+
+  default:
+    break;
+
+  } // end of switch
 }
 
 /// defineSymbolforCopyReloc
@@ -230,13 +395,11 @@
 /// section and all other reference to this symbol should refer to this
 /// copy.
 /// @note This is executed at `scan relocation' stage.
-LDSymbol& HexagonRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
-                                                 const ResolveInfo& pSym,
-                                                 HexagonLDBackend& pTarget)
-{
+LDSymbol &HexagonRelocator::defineSymbolforCopyReloc(
+    IRBuilder &pBuilder, const ResolveInfo &pSym, HexagonLDBackend &pTarget) {
   // get or create corresponding BSS LDSection
-  LDSection* bss_sect_hdr = NULL;
-  ELFFileFormat* file_format = pTarget.getOutputFormat();
+  LDSection *bss_sect_hdr = NULL;
+  ELFFileFormat *file_format = pTarget.getOutputFormat();
   if (ResolveInfo::ThreadLocal == pSym.type())
     bss_sect_hdr = &file_format->getTBSS();
   else
@@ -244,7 +407,7 @@
 
   // get or create corresponding BSS SectionData
   assert(NULL != bss_sect_hdr);
-  SectionData* bss_section = NULL;
+  SectionData *bss_section = NULL;
   if (bss_sect_hdr->hasSectionData())
     bss_section = bss_sect_hdr->getSectionData();
   else
@@ -255,45 +418,36 @@
   uint32_t addralign = config().targets().bitclass() / 8;
 
   // allocate space in BSS for the copy symbol
-  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
-  uint64_t size = ObjectBuilder::AppendFragment(*frag,
-                                                *bss_section,
-                                                addralign);
+  Fragment *frag = new FillFragment(0x0, 1, pSym.size());
+  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bss_section, addralign);
   bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
 
   // change symbol binding to Global if it's a weak symbol
-  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
+  ResolveInfo::Binding binding = (ResolveInfo::Binding) pSym.binding();
   if (binding == ResolveInfo::Weak)
     binding = ResolveInfo::Global;
 
   // Define the copy symbol in the bss section and resolve it
-  LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
-                      pSym.name(),
-                      (ResolveInfo::Type)pSym.type(),
-                      ResolveInfo::Define,
-                      binding,
-                      pSym.size(),  // size
-                      0x0,          // value
-                      FragmentRef::Create(*frag, 0x0),
-                      (ResolveInfo::Visibility)pSym.other());
+  LDSymbol *cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+      pSym.name(), (ResolveInfo::Type) pSym.type(), ResolveInfo::Define,
+      binding, pSym.size(), // size
+      0x0,                  // value
+      FragmentRef::Create(*frag, 0x0), (ResolveInfo::Visibility) pSym.other());
 
   // output all other alias symbols if any
   Module &pModule = pBuilder.getModule();
-  Module::AliasList* alias_list = pModule.getAliasList(pSym);
-  if (NULL!=alias_list) {
-    Module::alias_iterator it, it_e=alias_list->end();
-    for (it=alias_list->begin(); it!=it_e; ++it) {
-      const ResolveInfo* alias = *it;
-      if (alias!=&pSym && alias->isDyn()) {
+  Module::AliasList *alias_list = pModule.getAliasList(pSym);
+  if (NULL != alias_list) {
+    Module::alias_iterator it, it_e = alias_list->end();
+    for (it = alias_list->begin(); it != it_e; ++it) {
+      const ResolveInfo *alias = *it;
+      if (alias != &pSym && alias->isDyn()) {
         pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
-                           alias->name(),
-                           (ResolveInfo::Type)alias->type(),
-                           ResolveInfo::Define,
-                           binding,
-                           alias->size(),  // size
-                           0x0,          // value
-                           FragmentRef::Create(*frag, 0x0),
-                           (ResolveInfo::Visibility)alias->other());
+            alias->name(), (ResolveInfo::Type) alias->type(),
+            ResolveInfo::Define, binding, alias->size(), // size
+            0x0,                                         // value
+            FragmentRef::Create(*frag, 0x0),
+            (ResolveInfo::Visibility) alias->other());
       }
     }
   }
@@ -301,587 +455,359 @@
   return *cpy_sym;
 }
 
-void HexagonRelocator::partialScanRelocation(Relocation& pReloc,
-                                      Module& pModule,
-                                      const LDSection& pSection)
-{
+void HexagonRelocator::partialScanRelocation(Relocation &pReloc,
+                                             Module &pModule,
+                                             const LDSection &pSection) {
   pReloc.updateAddend();
   // if we meet a section symbol
   if (pReloc.symInfo()->type() == ResolveInfo::Section) {
-    LDSymbol* input_sym = pReloc.symInfo()->outSymbol();
+    LDSymbol *input_sym = pReloc.symInfo()->outSymbol();
 
     // 1. update the relocation target offset
     assert(input_sym->hasFragRef());
     // 2. get the output LDSection which the symbol defined in
-    const LDSection& out_sect =
-                        input_sym->fragRef()->frag()->getParent()->getSection();
-    ResolveInfo* sym_info =
-                     pModule.getSectionSymbolSet().get(out_sect)->resolveInfo();
+    const LDSection &out_sect =
+        input_sym->fragRef()->frag()->getParent()->getSection();
+    ResolveInfo *sym_info =
+        pModule.getSectionSymbolSet().get(out_sect)->resolveInfo();
     // set relocation target symbol to the output section symbol's resolveInfo
     pReloc.setSymInfo(sym_info);
   }
 }
 
-/// helper_DynRel - Get an relocation entry in .rela.dyn
-static
-Relocation& helper_DynRel(ResolveInfo* pSym,
-                          Fragment& pFrag,
-                          uint64_t pOffset,
-                          HexagonRelocator::Type pType,
-                          HexagonRelocator& pParent)
-{
-  HexagonLDBackend& ld_backend = pParent.getTarget();
-  Relocation& rela_entry = *ld_backend.getRelaDyn().consumeEntry();
-  rela_entry.setType(pType);
-  rela_entry.targetRef().assign(pFrag, pOffset);
-  if (pType == llvm::ELF::R_HEX_RELATIVE || NULL == pSym)
-    rela_entry.setSymInfo(0);
-  else
-    rela_entry.setSymInfo(pSym);
-
-  return rela_entry;
-}
-
-
-/// helper_use_relative_reloc - Check if symbol can use relocation
-/// R_HEX_RELATIVE
-static bool
-helper_use_relative_reloc(const ResolveInfo& pSym,
-                          const HexagonRelocator& pFactory)
-
-{
-  // if symbol is dynamic or undefine or preemptible
-  if (pSym.isDyn() ||
-      pSym.isUndef() ||
-      pFactory.getTarget().isSymbolPreemptible(pSym))
-    return false;
-  return true;
-}
-
-static
-HexagonGOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
-					HexagonRelocator& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  HexagonLDBackend& ld_backend = pParent.getTarget();
-
-  HexagonGOTEntry* 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() & HexagonRelocator::ReserveGOT) {
-    // No corresponding dynamic relocation, initialize to the symbol value.
-    got_entry->setValue(pReloc.symValue());
-  }
-  else if (rsym->reserved() & HexagonRelocator::GOTRel) {
-    // Initialize got_entry content and the corresponding dynamic relocation.
-    if (helper_use_relative_reloc(*rsym, pParent)) {
-      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_RELATIVE, pParent);
-      got_entry->setValue(pReloc.symValue());
-    }
-    else {
-      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_HEX_GLOB_DAT, pParent);
-      got_entry->setValue(0);
-    }
-  }
-  else {
-    fatal(diag::reserve_entry_number_mismatch_got);
-  }
-  return *got_entry;
-}
-
-static
-HexagonRelocator::Address helper_GOT_ORG(HexagonRelocator& pParent)
-{
-  return pParent.getTarget().getGOT().addr();
-}
-
-static
-HexagonRelocator::Address helper_GOT(Relocation& pReloc, HexagonRelocator& pParent)
-{
-  HexagonGOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
-  return helper_GOT_ORG(pParent) + got_entry.getOffset();
-}
-
-static
-PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc,
-				      HexagonRelocator& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  HexagonLDBackend& 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() & HexagonRelocator::ReservePLT) {
-    HexagonGOTEntry* 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& rela_entry = *ld_backend.getRelaPLT().consumeEntry();
-    rela_entry.setType(llvm::ELF::R_HEX_JMP_SLOT);
-    rela_entry.targetRef().assign(*gotplt_entry);
-    rela_entry.setSymInfo(rsym);
-  }
-  else {
-    fatal(diag::reserve_entry_number_mismatch_plt);
-  }
-
-  return *plt_entry;
-}
-
-static
-HexagonRelocator::Address helper_PLT_ORG(HexagonRelocator& pParent)
-{
-  return pParent.getTarget().getPLT().addr();
-}
-
-static
-HexagonRelocator::Address helper_PLT(Relocation& pReloc,
-                                     HexagonRelocator& pParent)
-{
-  PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
-  return helper_PLT_ORG(pParent) + plt_entry.getOffset();
-}
-
 //=========================================//
 // Each relocation function implementation //
 //=========================================//
 
 // R_HEX_NONE
-HexagonRelocator::Result none(Relocation& pReloc, HexagonRelocator& pParent)
-{
+HexagonRelocator::Result none(Relocation &pReloc, HexagonRelocator &pParent) {
   return HexagonRelocator::OK;
 }
 
-// R_HEX_B15_PCREL: Word32_B15 : 0x00df20fe  (S + A - P) >> 2 : Signed Verify
-HexagonRelocator::Result relocB15PCREL(Relocation& pReloc,
-                                       HexagonRelocator& pParent)
-{
+//R_HEX_32 and its class of relocations use only addend and symbol value
+// S + A : result is unsigned truncate.
+// Exception: R_HEX_32_6_X : unsigned verify
+HexagonRelocator::Result applyAbs(Relocation &pReloc) {
   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<int32_t>(0x00df20fe,result);
-    return HexagonRelocator::OK;
-  }
-  return HexagonRelocator::Overflow;
-}
-
-// 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;
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  if ( (result < range) && (result > -range)) {
-    pReloc.target() = pReloc.target() | ApplyMask<int32_t>(bitMask, 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<int32_t>(0x00001f18, result);
-    return HexagonRelocator::OK;
-  }
-  return HexagonRelocator::Overflow;
-}
-
-// 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();
-  ResolveInfo* rsym = pReloc.symInfo();
-  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
-                              *rsym,
-                              (rsym->reserved() & HexagonRelocator::ReservePLT),
-                              true);
+  uint32_t result = (uint32_t)(S + A);
+  uint32_t bitMask = 0;
+  uint32_t effectiveBits = 0;
+  uint32_t alignment = 1;
+  uint32_t shift = 0;
 
-  // A local symbol may need REL Type dynamic relocation
+  switch (pReloc.type()) {
+  case llvm::ELF::R_HEX_LO16:
+    bitMask = 0x00c03fff;
+    break;
+
+  case llvm::ELF::R_HEX_HI16:
+    shift = 16;
+    bitMask = 0x00c03fff;
+    break;
+
+  case llvm::ELF::R_HEX_32:
+    bitMask = 0xffffffff;
+    break;
+
+  case llvm::ELF::R_HEX_16:
+    bitMask = 0x0000ffff;
+    alignment = 2;
+    break;
+
+  case llvm::ELF::R_HEX_8:
+    bitMask = 0x000000ff;
+    alignment = 1;
+    break;
+
+  case llvm::ELF::R_HEX_12_X:
+    bitMask = 0x000007e0;
+    break;
+
+  case llvm::ELF::R_HEX_32_6_X:
+    bitMask = 0xfff3fff;
+    shift = 6;
+    effectiveBits = 26;
+    break;
+
+  case llvm::ELF::R_HEX_16_X:
+  case llvm::ELF::R_HEX_11_X:
+  case llvm::ELF::R_HEX_10_X:
+  case llvm::ELF::R_HEX_9_X:
+  case llvm::ELF::R_HEX_8_X:
+  case llvm::ELF::R_HEX_7_X:
+  case llvm::ELF::R_HEX_6_X:
+    bitMask = FINDBITMASK(pReloc.target());
+    break;
+
+  default:
+    // show proper error
+    fatal(diag::unsupported_relocation) << (int)
+        pReloc.type() << "mclinker@googlegroups.com";
+
+  }
+
+  if ((shift != 0) && (result % alignment != 0))
+    return HexagonRelocator::BadReloc;
+
+  result >>= shift;
+
+  if (effectiveBits) {
+    uint32_t range = 1 << effectiveBits;
+    if (result > (range - 1))
+      return HexagonRelocator::Overflow;
+  }
+
+  pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
+  return HexagonRelocator::OK;
+}
+
+//R_HEX_B22_PCREL and its class of relocations, use
+// S + A - P : result is signed verify.
+// Exception: R_HEX_B32_PCREL_X : signed truncate
+// Another Exception: R_HEX_6_PCREL_X is unsigned truncate
+HexagonRelocator::Result applyRel(Relocation &pReloc, int64_t pResult) {
+  uint32_t bitMask = 0;
+  uint32_t effectiveBits = 0;
+  uint32_t alignment = 1;
+  uint32_t result;
+  uint32_t shift = 0;
+
+  switch (pReloc.type()) {
+  case llvm::ELF::R_HEX_B22_PCREL:
+    bitMask = 0x01ff3ffe;
+    effectiveBits = 22;
+    alignment = 4;
+    shift = 2;
+    break;
+
+  case llvm::ELF::R_HEX_B15_PCREL:
+    bitMask = 0x00df20fe;
+    effectiveBits = 15;
+    alignment = 4;
+    shift = 2;
+    break;
+
+  case llvm::ELF::R_HEX_B7_PCREL:
+    bitMask = 0x00001f18;
+    effectiveBits = 7;
+    alignment = 4;
+    shift = 2;
+    break;
+
+  case llvm::ELF::R_HEX_B13_PCREL:
+    bitMask = 0x00202ffe;
+    effectiveBits = 13;
+    alignment = 4;
+    shift = 2;
+    break;
+
+  case llvm::ELF::R_HEX_B9_PCREL:
+    bitMask = 0x003000fe;
+    effectiveBits = 9;
+    alignment = 4;
+    shift = 2;
+    break;
+
+  case llvm::ELF::R_HEX_B32_PCREL_X:
+    bitMask = 0xfff3fff;
+    shift = 6;
+    break;
+
+  case llvm::ELF::R_HEX_B22_PCREL_X:
+    bitMask = 0x01ff3ffe;
+    effectiveBits = 22;
+    pResult &= 0x3f;
+    break;
+
+  case llvm::ELF::R_HEX_B15_PCREL_X:
+    bitMask = 0x00df20fe;
+    effectiveBits = 15;
+    pResult &= 0x3f;
+    break;
+
+  case llvm::ELF::R_HEX_B13_PCREL_X:
+    bitMask = 0x00202ffe;
+    effectiveBits = 13;
+    pResult &= 0x3f;
+    break;
+
+  case llvm::ELF::R_HEX_B9_PCREL_X:
+    bitMask = 0x003000fe;
+    effectiveBits = 9;
+    pResult &= 0x3f;
+    break;
+
+  case llvm::ELF::R_HEX_B7_PCREL_X:
+    bitMask = 0x00001f18;
+    effectiveBits = 7;
+    pResult &= 0x3f;
+    break;
+
+  case llvm::ELF::R_HEX_32_PCREL:
+    bitMask = 0xffffffff;
+    effectiveBits = 32;
+    break;
+
+  case llvm::ELF::R_HEX_6_PCREL_X:
+    // This is unique since it has a unsigned operand and its truncated
+    bitMask = FINDBITMASK(pReloc.target());
+    result = pReloc.addend() + pReloc.symValue() - pReloc.place();
+    pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
+    return HexagonRelocator::OK;
+
+  default:
+    // show proper error
+    fatal(diag::unsupported_relocation) << (int)
+        pReloc.type() << "mclinker@googlegroups.com";
+  }
+
+  if ((shift != 0) && (pResult % alignment != 0))
+    return HexagonRelocator::BadReloc;
+
+  pResult >>= shift;
+
+  if (effectiveBits) {
+    int64_t range = 1LL << (effectiveBits - 1);
+    if ((pResult > (range - 1)) || (pResult < -range))
+      return HexagonRelocator::Overflow;
+  }
+
+  pReloc.target() |= (uint32_t) ApplyMask<int32_t>(bitMask, pResult);
+  return HexagonRelocator::OK;
+}
+
+HexagonRelocator::Result relocAbs(Relocation &pReloc,
+                                  HexagonRelocator &pParent) {
+  ResolveInfo *rsym = pReloc.symInfo();
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord A = pReloc.addend();
+
+  Relocation* rel_entry = pParent.getRelRelMap().lookUp(pReloc);
+  bool has_dyn_rel = (NULL != rel_entry);
+
+  // if the flag of target section is not ALLOC, we eprform only static
+  // relocation.
+  if (0 == (llvm::ELF::SHF_ALLOC &
+            pReloc.targetRef().frag()->getParent()->getSection().flag())) {
+    return applyAbs(pReloc);
+  }
+
+  // a local symbol with .rela type relocation
   if (rsym->isLocal() && has_dyn_rel) {
-    FragmentRef &target_fragref = pReloc.targetRef();
-    Fragment *target_frag = target_fragref.frag();
-    HexagonRelocator::Type pType = llvm::ELF::R_HEX_RELATIVE;
-    Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
-        target_fragref.offset(), pType, pParent);
-    rel_entry.setAddend(S + A);
+    rel_entry->setAddend(S + A);
+    return HexagonRelocator::OK;
   }
 
-  uint32_t result = (uint32_t) (S + A);
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & HexagonRelocator::ReservePLT) {
+      S = helper_get_PLT_address(*rsym, pParent);
+    }
 
-  pReloc.target() = result | pReloc.target();
-  return HexagonRelocator::OK;
+    if (has_dyn_rel) {
+      if (llvm::ELF::R_HEX_32 == pReloc.type() &&
+          helper_use_relative_reloc(*rsym, pParent)) {
+        rel_entry->setAddend(S + A);
+      } else {
+        rel_entry->setAddend(A);
+        return HexagonRelocator::OK;
+      }
+    }
+  }
+
+  return applyAbs(pReloc);
 }
 
-// R_HEX_16: Word32 : 0xffff : (S + A) : Unsigned Truncate
-HexagonRelocator::Result reloc16(Relocation& pReloc,
-                                 HexagonRelocator& pParent)
-{
+HexagonRelocator::Result relocPCREL(Relocation &pReloc,
+                                    HexagonRelocator &pParent) {
+  ResolveInfo *rsym = pReloc.symInfo();
+  int64_t result;
+
+  HexagonRelocator::Address S = pReloc.symValue();
   HexagonRelocator::DWord A = pReloc.addend();
-  HexagonRelocator::DWord S = pReloc.symValue();
+  HexagonRelocator::DWord P = pReloc.place();
 
-  uint32_t result = (uint32_t) (S + A);
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(0x0000ffff, result);
+  FragmentRef &target_fragref = pReloc.targetRef();
+  Fragment *target_frag = target_fragref.frag();
+  LDSection &target_sect = target_frag->getParent()->getSection();
 
-  return HexagonRelocator::OK;
+  result = (int64_t)(S + A - P);
+
+  // for relocs inside non ALLOC, just apply
+  if (0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
+    return applyRel(pReloc, result);
+  }
+
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & HexagonRelocator::ReservePLT) {
+      S = helper_get_PLT_address(*rsym, pParent);
+      result = (int64_t)(S + A - P);
+      applyRel(pReloc, result);
+      return HexagonRelocator::OK;
+    }
+  }
+
+  return applyRel(pReloc, result);
 }
 
-// R_HEX_8: Word32 : 0xff : (S + A) : Unsigned Truncate
-HexagonRelocator::Result reloc8(Relocation& pReloc,
-                                HexagonRelocator& pParent)
-{
+// R_HEX_GPREL16_0 and its class : Unsigned Verify
+HexagonRelocator::Result relocGPREL(Relocation &pReloc,
+                                    HexagonRelocator &pParent) {
+  HexagonRelocator::Address S = pReloc.symValue();
   HexagonRelocator::DWord A = pReloc.addend();
-  HexagonRelocator::DWord S = pReloc.symValue();
+  HexagonRelocator::DWord GP = pParent.getTarget().getGP();
 
-  uint32_t result = (uint32_t) (S + A);
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(0x000000ff, result);
+  uint32_t result = (uint32_t)(S + A - GP);
+  uint32_t shift = 0;
+  uint32_t alignment = 1;
 
-  return HexagonRelocator::OK;
-}
+  switch (pReloc.type()) {
+  case llvm::ELF::R_HEX_GPREL16_0:
+    break;
 
-// 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();
+  case llvm::ELF::R_HEX_GPREL16_1:
+    shift = 1;
+    alignment = 2;
+    break;
 
-  uint32_t result = (uint32_t) (S + A);
-//  result = ((result & 0x3fff) | ((result << 6) & 0x00c00000));
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(0x00c03fff, result);
-  return HexagonRelocator::OK;
-}
+  case llvm::ELF::R_HEX_GPREL16_2:
+    shift = 2;
+    alignment = 4;
+    break;
 
-// 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();
+  case llvm::ELF::R_HEX_GPREL16_3:
+    shift = 3;
+    alignment = 8;
+    break;
 
-  uint32_t result = (uint32_t) ((S + A) >> 16);
-//  result = ((result & 0x3fff) | ((result << 6) & 0x00c00000));
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(0x00c03fff, result);
-  return HexagonRelocator::OK;
-}
-
-// R_HEX_GPREL16_0 : Word32_GP : 0x061f2ff  (S + A - GP) : Unsigned Verify
-HexagonRelocator::Result relocGPREL16_0(Relocation& pReloc,
-                                        HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-  HexagonLDBackend& ld_backend = pParent.getTarget();
-  HexagonRelocator::DWord   GP = ld_backend.getGP();
-
-  int64_t result = (int64_t) (S + A - GP);
-  int64_t range = 1ULL << 32;
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  if (result <= range) {
-    pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
-    return HexagonRelocator::OK;
-  }
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_GPREL16_1 : Word32_GP : 0x061f2ff  (S + A - GP)>>1 : Unsigned Verify
-HexagonRelocator::Result relocGPREL16_1(Relocation& pReloc,
-                                        HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-  HexagonLDBackend& ld_backend = pParent.getTarget();
-  HexagonRelocator::DWord   GP = ld_backend.getGP();
-
-  int64_t result = (int64_t) ((S + A - GP) >> 1);
-  int64_t range = 1LL << 32;
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  if (result <= range) {
-    pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
-    return HexagonRelocator::OK;
-  }
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_GPREL16_2 : Word32_GP : 0x061f2ff  (S + A - GP)>>2 : Unsigned Verify
-HexagonRelocator::Result relocGPREL16_2(Relocation& pReloc,
-                                        HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-  HexagonLDBackend& ld_backend = pParent.getTarget();
-  HexagonRelocator::DWord   GP = ld_backend.getGP();
-
-  int64_t result = (int64_t) ((S + A - GP) >> 2);
-  int64_t range = 1LL << 32;
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  if (result <= range) {
-    pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
-    return HexagonRelocator::OK;
-  }
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_GPREL16_3 : Word32_GP : 0x061f2ff  (S + A - GP)>>3 : Unsigned Verify
-HexagonRelocator::Result relocGPREL16_3(Relocation& pReloc,
-                                        HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-  HexagonLDBackend& ld_backend = pParent.getTarget();
-  HexagonRelocator::DWord   GP = ld_backend.getGP();
-
-  int64_t result = (int64_t) ((S + A - GP) >> 3);
-  int64_t range = 1LL << 32;
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  if (result <= range) {
-    pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
-    return HexagonRelocator::OK;
-  }
-  return HexagonRelocator::Overflow;
-}
-
-// 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<uint32_t>(0x00202ffe, result);
-    return HexagonRelocator::OK;
-  }
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_B9_PCREL : Word32_B9 : 0x00300ffe  (S + A - P)>>2 : Signed Verify
-HexagonRelocator::Result relocB9PCREL(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 << 8;
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  if (result < range && result > -range) {
-    pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
-    return HexagonRelocator::OK;
-  }
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_B32_PCREL_X : Word32_X26 : 0x0fff3fff  (S + A - P)>>6 : Truncate
-HexagonRelocator::Result relocB32PCRELX(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) >> 6);
-  pReloc.target() = pReloc.target() | ApplyMask<int32_t>(0xfff3fff, result);
-
-  return HexagonRelocator::OK;
-}
-
-// R_HEX_32_6_X : Word32_X26 : 0x0fff3fff  (S + A)>>6 : Unsigned Verify
-HexagonRelocator::Result reloc32_6_X(Relocation& pReloc,
-                                     HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-
-  int64_t result = ((S + A) >> 6);
-  int64_t range = 1LL << 32;
-
-  if (result > range)
-    return HexagonRelocator::Overflow;
-
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(0xfff3fff, result);
-
-  return HexagonRelocator::OK;
-}
-
-// R_HEX_B22_PCREL_X : Word32_B22 : 0x01ff3ffe
-// ((S + A - P) & 0x3f)>>2 : Signed Verify
-HexagonRelocator::Result relocB22PCRELX(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) & 0x3f);
-  int32_t range = 1 << 21;
-
-  if (result < range && result > -range)  {
-    pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(0x01ff3ffe, result);
-    return HexagonRelocator::OK;
+  default:
+    // show proper error
+    fatal(diag::unsupported_relocation) << (int)
+        pReloc.type() << "mclinker@googlegroups.com";
   }
 
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_B15_PCREL_X : Word32_B15 : 0x00df20fe
-// ((S + A - P) & 0x3f)>>2 : Signed Verify
-HexagonRelocator::Result relocB15PCRELX(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) & 0x3f);
-  int32_t range = 1 << 14;
-
-  if (result < range && result > -range)  {
-    pReloc.target() = pReloc.target() | ApplyMask<int32_t>(0x00df20fe, result);
-    return HexagonRelocator::OK;
-  }
-
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_B13_PCREL_X : Word32_B13 : 0x00202ffe
-// ((S + A - P) & 0x3f)>>2 : Signed Verify
-HexagonRelocator::Result relocB13PCRELX(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) & 0x3f);
-  int32_t range = 1 << 12;
-
-  if (result < range && result > -range)  {
-    pReloc.target() = pReloc.target() | ApplyMask<int32_t>(0x00202ffe, result);
-    return HexagonRelocator::OK;
-  }
-
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_B9_PCREL_X : Word32_B9 : 0x003000fe
-// ((S + A - P) & 0x3f)>>2 : Signed Verify
-HexagonRelocator::Result relocB9PCRELX(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) & 0x3f);
-  int32_t range = 1 << 8;
-
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  if (result < range && result > -range)  {
-    pReloc.target() = pReloc.target() | ApplyMask<int32_t>(bitMask, result);
-    return HexagonRelocator::OK;
-  }
-
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_B7_PCREL_X : Word32_B7 : 0x00001f18
-// ((S + A - P) & 0x3f)>>2 : Signed Verify
-HexagonRelocator::Result relocB7PCRELX(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) & 0x3f);
-  int32_t range = 1 << 6;
-
-  if (result < range && result > -range)  {
-    pReloc.target() = pReloc.target() | ApplyMask<int32_t>(0x00001f18, result);
-    return HexagonRelocator::OK;
-  }
-
-  return HexagonRelocator::Overflow;
-}
-
-// 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<int32_t>(0xffffffff, result);
-    return HexagonRelocator::OK;
-  }
-
-  return HexagonRelocator::Overflow;
-}
-
-// R_HEX_N_X : Word32_U6 : (S + A) : Unsigned Truncate
-HexagonRelocator::Result relocHexNX(Relocation& pReloc,
-                                    HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-  uint32_t result = (S + A);
+  uint32_t range = 1 << 16;
   uint32_t bitMask = FINDBITMASK(pReloc.target());
 
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
-  return HexagonRelocator::OK;
+  if ((shift != 0) && (result % alignment != 0))
+    return HexagonRelocator::BadReloc;
+
+  result >>= shift;
+
+  if (result < range - 1) {
+    pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
+    return HexagonRelocator::OK;
+  }
+  return HexagonRelocator::Overflow;
 }
 
 // R_HEX_PLT_B22_PCREL: PLT(S) + A - P
-HexagonRelocator::Result relocPLTB22PCREL(Relocation& pReloc, HexagonRelocator& pParent)
-{
+HexagonRelocator::Result relocPLTB22PCREL(Relocation &pReloc,
+                                          HexagonRelocator &pParent) {
   // PLT_S depends on if there is a PLT entry.
   HexagonRelocator::Address PLT_S;
   if ((pReloc.symInfo()->reserved() & HexagonRelocator::ReservePLT))
-    PLT_S = helper_PLT(pReloc, pParent);
+    PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
   else
     PLT_S = pReloc.symValue();
   HexagonRelocator::Address P = pReloc.place();
@@ -891,97 +817,142 @@
   return HexagonRelocator::OK;
 }
 
-// R_HEX_GOTREL_LO16: Word32_LO : 0x00c03fff  (S + A - GOT) : Unsigned Truncate
-HexagonRelocator::Result relocHexGOTRELLO16(Relocation& pReloc,
-                                            HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-  HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
-
-  uint32_t result = (uint32_t) (S + A - GOT);
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(0x00c03fff, result);
-  return HexagonRelocator::OK;
-}
-
-// R_HEX_GOTREL_HI16 : Word32_LO : 0x00c03fff  (S + A - GOT) >> 16 : Unsigned Truncate
-HexagonRelocator::Result relocHexGOTRELHI16(Relocation& pReloc,
-                                   HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-  HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
-
-  uint32_t result = (uint32_t) ((S + A - GOT) >> 16);
-
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(0x00c03fff, result);
-  return HexagonRelocator::OK;
-}
-
-// R_HEX_GOTREL_32 : Word32  (S + A - GOT) : Unsigned Truncate
-HexagonRelocator::Result relocHexGOTREL32(Relocation& pReloc,
-                                   HexagonRelocator& pParent)
-{
-  HexagonRelocator::Address S = pReloc.symValue();
-  HexagonRelocator::DWord   A = pReloc.addend();
-  HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
-
-  uint32_t result = (uint32_t) (S + A - GOT);
-
-  pReloc.target() = pReloc.target() | result;
-  return HexagonRelocator::OK;
-}
-
-// R_HEX_6_PCREL_X : (S + A - P)
-HexagonRelocator::Result relocHex6PCRELX(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);
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
-  return HexagonRelocator::OK;
-}
-
-// R_HEX_GOT_32_6_X : (G) >> 6
-HexagonRelocator::Result relocHexGOT326X(Relocation& pReloc,
-                                         HexagonRelocator& pParent)
-{
-  if (!(pReloc.symInfo()->reserved()
-       & (HexagonRelocator::ReserveGOT | HexagonRelocator::GOTRel))) {
+//R_HEX_GOT_LO16 and its class : (G) Signed Truncate
+//Exception: R_HEX_GOT_16(_X): signed verify
+// Exception: R_HEX_GOT_11_X : unsigned truncate
+HexagonRelocator::Result relocGOT(Relocation &pReloc,
+                                  HexagonRelocator &pParent) {
+  if (!(pReloc.symInfo()->reserved() & HexagonRelocator::ReserveGOT)) {
     return HexagonRelocator::BadReloc;
   }
-  HexagonRelocator::Address GOT_S   = helper_GOT(pReloc, pParent);
-  HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
-  int32_t result = (GOT_S - GOT) >> 6;
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
-  return HexagonRelocator::OK;
-}
 
-// R_HEX_GOT_16_X : (G)
-// R_HEX_GOT_11_X : (G)
-HexagonRelocator::Result relocHexGOT1611X(Relocation& pReloc,
-                                         HexagonRelocator& pParent)
-{
-  if (!(pReloc.symInfo()->reserved()
-       & (HexagonRelocator::ReserveGOT | HexagonRelocator::GOTRel))) {
-    return HexagonRelocator::BadReloc;
+  // set got entry value if needed
+  HexagonGOTEntry *got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
+  assert(NULL != got_entry);
+  if (HexagonRelocator::SymVal == got_entry->getValue())
+    got_entry->setValue(pReloc.symValue());
+
+  HexagonRelocator::Address GOT_S =
+                             helper_get_GOT_address(*pReloc.symInfo(), pParent);
+  HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
+  int32_t result = (int32_t)(GOT_S - GOT);
+  uint32_t effectiveBits = 0;
+  uint32_t alignment = 1;
+  uint32_t bitMask = 0;
+  uint32_t result_u;
+  uint32_t shift = 0;
+
+  switch (pReloc.type()) {
+  case llvm::ELF::R_HEX_GOT_LO16:
+    bitMask = 0x00c03fff;
+    break;
+
+  case llvm::ELF::R_HEX_GOT_HI16:
+    bitMask = 0x00c03fff;
+    shift = 16;
+    alignment = 4;
+    break;
+
+  case llvm::ELF::R_HEX_GOT_32:
+    bitMask = 0xffffffff;
+    break;
+
+  case llvm::ELF::R_HEX_GOT_16:
+    bitMask = FINDBITMASK(pReloc.target());
+    effectiveBits = 16;
+    break;
+
+  case llvm::ELF::R_HEX_GOT_32_6_X:
+    bitMask = 0xfff3fff;
+    shift = 6;
+    break;
+
+  case llvm::ELF::R_HEX_GOT_16_X:
+    bitMask = FINDBITMASK(pReloc.target());
+    effectiveBits = 6;
+    break;
+
+  case llvm::ELF::R_HEX_GOT_11_X:
+    bitMask = FINDBITMASK(pReloc.target());
+    result_u = GOT_S - GOT;
+    pReloc.target() |= ApplyMask<uint32_t>(bitMask, result_u);
+    return HexagonRelocator::OK;
+
+  default:
+    // show proper error
+    fatal(diag::unsupported_relocation) << (int)
+        pReloc.type() << "mclinker@googlegroups.com";
   }
-  HexagonRelocator::Address GOT_S   = helper_GOT(pReloc, pParent);
-  HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
-  int32_t result = (GOT_S - GOT);
-  uint32_t bitMask = FINDBITMASK(pReloc.target());
-  pReloc.target() = pReloc.target() | ApplyMask<uint32_t>(bitMask, result);
+
+  if ((shift != 0) && (result % alignment != 0))
+    return HexagonRelocator::BadReloc;
+
+  result >>= shift;
+
+  if (effectiveBits) {
+    int32_t range = 1 << (effectiveBits - 1);
+    if ((result > range - 1) || (result < -range))
+      return HexagonRelocator::Overflow;
+  }
+  pReloc.target() |= ApplyMask<int32_t>(bitMask, result);
   return HexagonRelocator::OK;
 }
 
-HexagonRelocator::Result unsupport(Relocation& pReloc,
-                                   HexagonRelocator& pParent)
-{
+// R_HEX_GOTREL_LO16: and its class of relocs
+// (S + A - GOT) : Signed Truncate
+HexagonRelocator::Result relocGOTREL(Relocation &pReloc,
+                                     HexagonRelocator &pParent) {
+  HexagonRelocator::Address S = pReloc.symValue();
+  HexagonRelocator::DWord A = pReloc.addend();
+  HexagonRelocator::Address GOT = pParent.getTarget().getGOTSymbolAddr();
+
+  uint32_t bitMask = 0;
+  uint32_t alignment = 1;
+  uint32_t shift = 0;
+
+  uint32_t result = (uint32_t)(S + A - GOT);
+
+  switch (pReloc.type()) {
+  case llvm::ELF::R_HEX_GOTREL_LO16:
+    bitMask = 0x00c03fff;
+    break;
+
+  case llvm::ELF::R_HEX_GOTREL_HI16:
+    bitMask = 0x00c03fff;
+    shift = 16;
+    alignment = 4;
+    break;
+
+  case llvm::ELF::R_HEX_GOTREL_32:
+    bitMask = 0xffffffff;
+    break;
+
+  case llvm::ELF::R_HEX_GOTREL_32_6_X:
+    bitMask = 0x0fff3fff;
+    shift = 6;
+    break;
+
+  case llvm::ELF::R_HEX_GOTREL_16_X:
+  case llvm::ELF::R_HEX_GOTREL_11_X:
+    bitMask = FINDBITMASK(pReloc.target());
+    break;
+
+  default:
+    // show proper error
+    fatal(diag::unsupported_relocation) << (int)
+        pReloc.type() << "mclinker@googlegroups.com";
+  }
+
+  if (result % alignment != 0)
+    return HexagonRelocator::BadReloc;
+
+  result >>= shift;
+
+  pReloc.target() |= ApplyMask<uint32_t>(bitMask, result);
+  return HexagonRelocator::OK;
+}
+
+HexagonRelocator::Result unsupport(Relocation &pReloc,
+                                   HexagonRelocator &pParent) {
   return HexagonRelocator::Unsupport;
 }
diff --git a/lib/Target/Hexagon/HexagonRelocator.h b/lib/Target/Hexagon/HexagonRelocator.h
index e65be9f..02e99c9 100644
--- a/lib/Target/Hexagon/HexagonRelocator.h
+++ b/lib/Target/Hexagon/HexagonRelocator.h
@@ -15,7 +15,7 @@
 #include <mcld/LD/Relocator.h>
 #include <mcld/Target/GOT.h>
 #include <mcld/Target/PLT.h>
-#include <mcld/Target/SymbolEntryMap.h>
+#include <mcld/Target/KeyEntryMap.h>
 #include "HexagonLDBackend.h"
 
 namespace mcld {
@@ -30,55 +30,45 @@
 class HexagonRelocator : public Relocator
 {
 public:
-  typedef SymbolEntryMap<PLTEntryBase> SymPLTMap;
-  typedef SymbolEntryMap<HexagonGOTEntry> SymGOTMap;
-  typedef SymbolEntryMap<HexagonGOTEntry> SymGOTPLTMap;
-
+  typedef KeyEntryMap<ResolveInfo, PLTEntryBase> SymPLTMap;
+  typedef KeyEntryMap<ResolveInfo, HexagonGOTEntry> SymGOTMap;
+  typedef KeyEntryMap<ResolveInfo, HexagonGOTEntry> SymGOTPLTMap;
+  typedef KeyEntryMap<Relocation, Relocation> RelRelMap;
 
 public:
   /** \enum ReservedEntryType
    *  \brief The reserved entry type of reserved space in ResolveInfo.
    *
    *  This is used for sacnRelocation to record what kinds of entries are
-   *  reserved for this resolved symbol
+   *  reserved for this resolved symbol. In Hexagon, there are three kinds
+   *  of entries, GOT, PLT, and dynamic relocation.
    *
-   *  In Hexagon, there are three kinds of entries, GOT, PLT, and dynamic
-   *  relocation.
-   *
-   *  GOT may needs a corresponding relocation to relocate itself, so we
-   *  separate GOT to two situations: GOT and GOTRel. Besides, for the same
-   *  symbol, there might be two kinds of entries reserved for different location.
-   *  For example, reference to the same symbol, one may use GOT and the other may
-   *  use dynamic relocation.
-   *
-   *  bit:  3       2      1     0
-   *   | PLT | GOTRel | GOT | Rel |
+   *  bit:  3     2     1     0
+   *   |    | PLT | GOT | Rel |
    *
    *  value    Name         - Description
    *
    *  0000     None         - no reserved entry
    *  0001     ReserveRel   - reserve an dynamic relocation entry
    *  0010     ReserveGOT   - reserve an GOT entry
-   *  0011     GOTandRel    - For different relocation, we've reserved GOT and
-   *                          Rel for different location.
-   *  0100     GOTRel       - reserve an GOT entry and the corresponding Dyncamic
-   *                          relocation entry which relocate this GOT entry
-   *  0101     GOTRelandRel - For different relocation, we've reserved GOTRel
-   *                          and relocation entry for different location.
-   *  1000     ReservePLT   - reserve an PLT entry and the corresponding GOT,
-   *                          Dynamic relocation entries
-   *  1001     PLTandRel    - For different relocation, we've reserved PLT and
-   *                          Rel for different location.
+   *  0100     ReservePLT   - reserve an PLT entry and the corresponding GOT,
+   *
    */
   enum ReservedEntryType {
     None         = 0,
     ReserveRel   = 1,
     ReserveGOT   = 2,
-    GOTandRel    = 3,
-    GOTRel       = 4,
-    GOTRelandRel = 5,
-    ReservePLT   = 8,
-    PLTandRel    = 9
+    ReservePLT   = 4,
+  };
+
+  /** \enum EntryValue
+   *  \brief The value of the entries. The symbol value will be decided at after
+   *  layout, so we mark the entry during scanRelocation and fill up the actual
+   *  value when applying relocations.
+   */
+  enum EntryValue {
+    Default = 0,
+    SymVal  = 1
   };
 
   HexagonRelocator(HexagonLDBackend& pParent, const LinkerConfig& pConfig);
@@ -95,7 +85,8 @@
   void scanRelocation(Relocation& pReloc,
                       IRBuilder& pBuilder,
                       Module& pModule,
-                      LDSection& pSection);
+                      LDSection& pSection,
+                      Input& pInput);
 
   // Handle partial linking
   void partialScanRelocation(Relocation& pReloc,
@@ -121,6 +112,9 @@
   const SymGOTPLTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
   SymGOTPLTMap&       getSymGOTPLTMap()       { return m_SymGOTPLTMap; }
 
+  const RelRelMap& getRelRelMap() const { return m_RelRelMap; }
+  RelRelMap&       getRelRelMap()       { return m_RelRelMap; }
+
 protected:
   /// addCopyReloc - add a copy relocation into .rela.dyn for pSym
   /// @param pSym - A resolved copy symbol that defined in BSS section
@@ -148,6 +142,7 @@
   SymPLTMap m_SymPLTMap;
   SymGOTMap m_SymGOTMap;
   SymGOTPLTMap m_SymGOTPLTMap;
+  RelRelMap m_RelRelMap;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Hexagon/HexagonTargetMachine.cpp b/lib/Target/Hexagon/HexagonTargetMachine.cpp
index 4e4f1c2..33067b9 100644
--- a/lib/Target/Hexagon/HexagonTargetMachine.cpp
+++ b/lib/Target/Hexagon/HexagonTargetMachine.cpp
@@ -8,7 +8,6 @@
 //===----------------------------------------------------------------------===//
 #include "HexagonTargetMachine.h"
 #include "Hexagon.h"
-#include <mcld/Target/TargetMachine.h>
 #include <mcld/Support/TargetRegistry.h>
 
 extern "C" void MCLDInitializeHexagonLDTarget() {
@@ -17,13 +16,14 @@
      X(mcld::TheHexagonTarget);
 }
 
-mcld::HexagonTargetMachine::HexagonTargetMachine(llvm::TargetMachine& pPM,
-                                                 const mcld::Target &pTarget,
-                                                 const std::string& pTriple)
-  : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
-}
+using namespace mcld;
 
-mcld::HexagonTargetMachine::~HexagonTargetMachine()
-{
+//===----------------------------------------------------------------------===//
+// HexagonTargetMachine
+//===----------------------------------------------------------------------===//
+HexagonTargetMachine::HexagonTargetMachine(llvm::TargetMachine& pPM,
+                                           const llvm::Target& pLLVMTarget,
+                                           const mcld::Target& pMCLDTarget,
+                                           const std::string& pTriple)
+  : MCLDTargetMachine(pPM, pLLVMTarget, pMCLDTarget, pTriple) {
 }
-
diff --git a/lib/Target/Hexagon/HexagonTargetMachine.h b/lib/Target/Hexagon/HexagonTargetMachine.h
index a374475..9b131c1 100644
--- a/lib/Target/Hexagon/HexagonTargetMachine.h
+++ b/lib/Target/Hexagon/HexagonTargetMachine.h
@@ -9,7 +9,7 @@
 #ifndef MCLD_HEXAGON_TARGET_MACHINE_H
 #define MCLD_HEXAGON_TARGET_MACHINE_H
 #include "Hexagon.h"
-#include <mcld/Target/TargetMachine.h>
+#include <mcld/CodeGen/TargetMachine.h>
 
 namespace mcld {
 
@@ -17,10 +17,9 @@
 {
 public:
   HexagonTargetMachine(llvm::TargetMachine &pTM,
-                       const mcld::Target &pTarget,
+                       const llvm::Target &pLLVMTarget,
+                       const mcld::Target &pMCLDTarget,
                        const std::string &pTriple);
-
-  virtual ~HexagonTargetMachine();
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp b/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp
index 0b113aa..e0d660b 100644
--- a/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp
+++ b/lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp
@@ -6,7 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/Target/TargetMachine.h>
+#include <mcld/Support/Target.h>
 #include <mcld/Support/TargetRegistry.h>
 
 namespace mcld {
@@ -15,7 +15,7 @@
 
 extern "C" void MCLDInitializeHexagonLDTargetInfo() {
   // register into mcld::TargetRegistry
-  mcld::RegisterTarget X(TheHexagonTarget, "hexagon");
+  mcld::RegisterTarget<llvm::Triple::hexagon> X(TheHexagonTarget, "hexagon");
 }
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h
index a63be45..35be4b4 100644
--- a/lib/Target/Mips/Mips.h
+++ b/lib/Target/Mips/Mips.h
@@ -9,11 +9,12 @@
 #ifndef MCLD_MIPS_H
 #define MCLD_MIPS_H
 
-#include "mcld/Support/TargetRegistry.h"
-
 namespace mcld {
 
-extern mcld::Target TheMipselTarget;
+class Target;
+
+extern Target TheMipselTarget;
+extern Target TheMips64elTarget;
 
 } // namespace of mcld
 
diff --git a/lib/Target/Mips/MipsDiagnostic.cpp b/lib/Target/Mips/MipsDiagnostic.cpp
index 2d5b7d9..e03ea3c 100644
--- a/lib/Target/Mips/MipsDiagnostic.cpp
+++ b/lib/Target/Mips/MipsDiagnostic.cpp
@@ -6,30 +6,30 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/ADT/Triple.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/LD/DWARFLineInfo.h>
 #include "Mips.h"
 
-using namespace mcld;
+namespace {
 
-
-namespace mcld {
 //===----------------------------------------------------------------------===//
 // createMipsDiagnostic - the help function to create corresponding
 // MipsDiagnostic
-DiagnosticLineInfo* createMipsDiagLineInfo(const mcld::Target& pTarget,
-                                           const std::string &pTriple)
+//===----------------------------------------------------------------------===//
+mcld::DiagnosticLineInfo* createMipsDiagLineInfo(const mcld::Target& pTarget,
+                                                 const std::string &pTriple)
 {
-  return new DWARFLineInfo();
+  return new mcld::DWARFLineInfo();
 }
 
 } // namespace of mcld
 
-//==========================
+//===----------------------------------------------------------------------===//
 // InitializeMipsDiagnostic
+//===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeMipsDiagnosticLineInfo() {
-  // Register the linker frontend
-  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheMipselTarget, createMipsDiagLineInfo);
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(mcld::TheMipselTarget,
+                                                   createMipsDiagLineInfo);
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(mcld::TheMips64elTarget,
+                                                   createMipsDiagLineInfo);
 }
-
diff --git a/lib/Target/Mips/MipsELFDynamic.cpp b/lib/Target/Mips/MipsELFDynamic.cpp
index e34d698..b532b03 100644
--- a/lib/Target/Mips/MipsELFDynamic.cpp
+++ b/lib/Target/Mips/MipsELFDynamic.cpp
@@ -6,61 +6,55 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "MipsELFDynamic.h"
-
-#include "MipsLDBackend.h"
+#include <llvm/Support/ELF.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/LD/ELFFileFormat.h>
+#include <mcld/LD/ELFSegment.h>
+#include <mcld/LD/ELFSegmentFactory.h>
 #include <mcld/Target/GNULDBackend.h>
+#include "MipsELFDynamic.h"
+#include "MipsLDBackend.h"
 
 using namespace mcld;
 
-// MIPS mandatory dynamic section entries
-enum {
-  MIPS_RLD_VERSION  = 0x70000001,
-  MIPS_FLAGS        = 0x70000005,
-  MIPS_BASE_ADDRESS = 0x70000006,
-  MIPS_LOCAL_GOTNO  = 0x7000000a,
-  MIPS_SYMTABNO     = 0x70000011,
-  MIPS_GOTSYM       = 0x70000013
-};
-
 MipsELFDynamic::MipsELFDynamic(const MipsGNULDBackend& pParent,
                                const LinkerConfig& pConfig)
   : ELFDynamic(pParent, pConfig),
-    m_pParent(pParent)
-{
-}
-
-MipsELFDynamic::~MipsELFDynamic()
+    m_pParent(pParent),
+    m_pConfig(pConfig)
 {
 }
 
 void MipsELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat)
 {
-  // reservePLTGOT
   if (pFormat.hasGOT())
     reserveOne(llvm::ELF::DT_PLTGOT);
 
-  reserveOne(MIPS_RLD_VERSION);
-  reserveOne(MIPS_FLAGS);
-  reserveOne(MIPS_BASE_ADDRESS);
-  reserveOne(MIPS_LOCAL_GOTNO);
-  reserveOne(MIPS_SYMTABNO);
-  reserveOne(MIPS_GOTSYM);
+  reserveOne(llvm::ELF::DT_MIPS_RLD_VERSION);
+  reserveOne(llvm::ELF::DT_MIPS_FLAGS);
+  reserveOne(llvm::ELF::DT_MIPS_BASE_ADDRESS);
+  reserveOne(llvm::ELF::DT_MIPS_LOCAL_GOTNO);
+  reserveOne(llvm::ELF::DT_MIPS_SYMTABNO);
+  reserveOne(llvm::ELF::DT_MIPS_GOTSYM);
+
+  if (pFormat.hasGOTPLT())
+    reserveOne(llvm::ELF::DT_MIPS_PLTGOT);
 }
 
 void MipsELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat)
 {
-  // applyPLTGOT
   if (pFormat.hasGOT())
     applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOT().addr());
 
-  applyOne(MIPS_RLD_VERSION, 1);
-  applyOne(MIPS_FLAGS, 0);
-  applyOne(MIPS_BASE_ADDRESS, 0);
-  applyOne(MIPS_LOCAL_GOTNO, getLocalGotNum(pFormat));
-  applyOne(MIPS_SYMTABNO, getSymTabNum(pFormat));
-  applyOne(MIPS_GOTSYM, getGotSym(pFormat));
+  applyOne(llvm::ELF::DT_MIPS_RLD_VERSION, 1);
+  applyOne(llvm::ELF::DT_MIPS_FLAGS, llvm::ELF::RHF_NOTPOT);
+  applyOne(llvm::ELF::DT_MIPS_BASE_ADDRESS, getBaseAddress());
+  applyOne(llvm::ELF::DT_MIPS_LOCAL_GOTNO, getLocalGotNum(pFormat));
+  applyOne(llvm::ELF::DT_MIPS_SYMTABNO, getSymTabNum(pFormat));
+  applyOne(llvm::ELF::DT_MIPS_GOTSYM, getGotSym(pFormat));
+
+  if (pFormat.hasGOTPLT())
+    applyOne(llvm::ELF::DT_MIPS_PLTGOT, pFormat.getGOTPLT().addr());
 }
 
 size_t MipsELFDynamic::getSymTabNum(const ELFFileFormat& pFormat) const
@@ -87,3 +81,14 @@
 
   return m_pParent.getGOT().getLocalNum();
 }
+
+uint64_t MipsELFDynamic::getBaseAddress()
+{
+  if (LinkerConfig::Exec != m_pConfig.codeGenType())
+    return 0;
+
+  ELFSegmentFactory::const_iterator baseSeg =
+    m_pParent.elfSegmentTable().find(llvm::ELF::PT_LOAD, 0x0, 0x0);
+
+  return m_pParent.elfSegmentTable().end() == baseSeg ? 0 : (*baseSeg)->vaddr();
+}
diff --git a/lib/Target/Mips/MipsELFDynamic.h b/lib/Target/Mips/MipsELFDynamic.h
index 6efbf71..bb7e579 100644
--- a/lib/Target/Mips/MipsELFDynamic.h
+++ b/lib/Target/Mips/MipsELFDynamic.h
@@ -22,10 +22,10 @@
 {
 public:
   MipsELFDynamic(const MipsGNULDBackend& pParent, const LinkerConfig& pConfig);
-  ~MipsELFDynamic();
 
 private:
   const MipsGNULDBackend& m_pParent;
+  const LinkerConfig& m_pConfig;
 
 private:
   void reserveTargetEntries(const ELFFileFormat& pFormat);
@@ -34,6 +34,7 @@
   size_t getSymTabNum(const ELFFileFormat& pFormat) const;
   size_t getGotSym(const ELFFileFormat& pFormat) const;
   size_t getLocalGotNum(const ELFFileFormat& pFormat) const;
+  uint64_t getBaseAddress();
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/MipsELFMCLinker.cpp b/lib/Target/Mips/MipsELFMCLinker.cpp
index 3964ee8..077177a 100644
--- a/lib/Target/Mips/MipsELFMCLinker.cpp
+++ b/lib/Target/Mips/MipsELFMCLinker.cpp
@@ -7,14 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 #include "MipsELFMCLinker.h"
-#include <mcld/LinkerConfig.h>
 
 using namespace mcld;
 
 MipsELFMCLinker::MipsELFMCLinker(LinkerConfig& pConfig,
                                  mcld::Module& pModule,
-                                 MemoryArea& pOutput)
-  : ELFMCLinker(pConfig, pModule, pOutput) {
+                                 FileHandle& pFileHandle)
+  : ELFMCLinker(pConfig, pModule, pFileHandle) {
 }
 
 MipsELFMCLinker::~MipsELFMCLinker()
diff --git a/lib/Target/Mips/MipsELFMCLinker.h b/lib/Target/Mips/MipsELFMCLinker.h
index 2c240ad..cdffdd5 100644
--- a/lib/Target/Mips/MipsELFMCLinker.h
+++ b/lib/Target/Mips/MipsELFMCLinker.h
@@ -16,7 +16,7 @@
 namespace mcld {
 
 class Module;
-class MemoryArea;
+class FileHandle;
 
 /** \class MipsELFMCLinker
  *  \brief MipsELFMCLinker sets up the environment for linking.
@@ -26,7 +26,7 @@
 public:
   MipsELFMCLinker(LinkerConfig& pConfig,
                   mcld::Module& pModule,
-                  MemoryArea& pOutput);
+                  FileHandle& pFileHandle);
 
   ~MipsELFMCLinker();
 };
diff --git a/lib/Target/Mips/MipsEmulation.cpp b/lib/Target/Mips/MipsEmulation.cpp
index bdb1783..5e5d192 100644
--- a/lib/Target/Mips/MipsEmulation.cpp
+++ b/lib/Target/Mips/MipsEmulation.cpp
@@ -21,7 +21,11 @@
 
   // set up bitclass and endian
   pConfig.targets().setEndian(TargetOptions::Little);
-  pConfig.targets().setBitClass(32);
+
+  llvm::Triple::ArchType arch = pConfig.targets().triple().getArch();
+  assert(arch == llvm::Triple::mipsel || arch == llvm::Triple::mips64el);
+  unsigned bitclass = arch == llvm::Triple::mipsel ? 32 : 64;
+  pConfig.targets().setBitClass(bitclass);
 
   // set up target-dependent constraints of attributes
   pConfig.attribute().constraint().enableWholeArchive();
@@ -58,7 +62,8 @@
 // MipsEmulation
 //===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeMipsEmulation() {
-  // Register the emulation
-  mcld::TargetRegistry::RegisterEmulation(mcld::TheMipselTarget, mcld::emulateMipsLD);
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheMipselTarget,
+                                          mcld::emulateMipsLD);
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheMips64elTarget,
+                                          mcld::emulateMipsLD);
 }
-
diff --git a/lib/Target/Mips/MipsGNUInfo.cpp b/lib/Target/Mips/MipsGNUInfo.cpp
new file mode 100644
index 0000000..521a800
--- /dev/null
+++ b/lib/Target/Mips/MipsGNUInfo.cpp
@@ -0,0 +1,77 @@
+//===- MipsGNUInfo.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "MipsGNUInfo.h"
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+// MipsGNUInfo
+//===----------------------------------------------------------------------===//
+MipsGNUInfo::MipsGNUInfo(const llvm::Triple& pTriple)
+  : GNUInfo(pTriple),
+    m_ABIVersion(0),
+    m_PICFlags(0)
+{}
+
+void MipsGNUInfo::setABIVersion(uint8_t ver)
+{
+  m_ABIVersion = ver;
+}
+
+void MipsGNUInfo::setPICFlags(uint64_t flags)
+{
+  m_PICFlags = flags;
+}
+
+uint32_t MipsGNUInfo::machine() const
+{
+  return llvm::ELF::EM_MIPS;
+}
+
+uint8_t MipsGNUInfo::ABIVersion() const
+{
+  return m_ABIVersion;
+}
+
+uint64_t MipsGNUInfo::defaultTextSegmentAddr() const
+{
+  if (m_Triple.isArch32Bit())
+    return 0x400000;
+  else
+    return 0x120000000ull;
+}
+
+uint64_t MipsGNUInfo::flags() const
+{
+  uint64_t val = llvm::ELF::EF_MIPS_NOREORDER | m_PICFlags;
+
+  if (m_Triple.isArch32Bit())
+    val |= llvm::ELF::EF_MIPS_ARCH_32R2 | llvm::ELF::EF_MIPS_ABI_O32;
+  else
+    val |= llvm::ELF::EF_MIPS_ARCH_64R2;
+
+  return val;
+}
+
+const char* MipsGNUInfo::entry() const
+{
+  return "__start";
+}
+
+const char* MipsGNUInfo::dyld() const
+{
+  return m_Triple.isArch32Bit() ? "/lib/ld.so.1" : "/lib64/ld.so.1";
+}
+
+uint64_t MipsGNUInfo::abiPageSize() const
+{
+  return 0x10000;
+}
+
+} // end mcld namespace
diff --git a/lib/Target/Mips/MipsGNUInfo.h b/lib/Target/Mips/MipsGNUInfo.h
index 9c829d5..2e43d80 100644
--- a/lib/Target/Mips/MipsGNUInfo.h
+++ b/lib/Target/Mips/MipsGNUInfo.h
@@ -8,52 +8,33 @@
 //===----------------------------------------------------------------------===//
 #ifndef MCLD_TARGET_MIPS_GNU_INFO_H
 #define MCLD_TARGET_MIPS_GNU_INFO_H
-#include <mcld/Target/GNUInfo.h>
-
 #include <llvm/Support/ELF.h>
+#include <mcld/Target/GNUInfo.h>
 
 namespace mcld {
 
 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
-  };
+  MipsGNUInfo(const llvm::Triple& pTriple);
 
-public:
-  MipsGNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
+  void setABIVersion(uint8_t ver);
+  void setPICFlags(uint64_t flags);
 
-  uint32_t machine() const { return llvm::ELF::EM_MIPS; }
+  // GNUInfo
+  uint32_t machine() const;
+  uint8_t ABIVersion() const;
+  uint64_t defaultTextSegmentAddr() const;
+  uint64_t flags() const;
+  const char* entry() const;
+  const char* dyld() const;
+  uint64_t abiPageSize() const;
 
-  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;
-  }
-
-  const char* entry() const { return "__start"; }
-
-  const char* dyld() const { return "/lib/ld.so.1"; }
-
-  uint64_t abiPageSize() const { return 0x10000; }
+private:
+  uint8_t m_ABIVersion;
+  uint64_t m_PICFlags;
 };
 
 } // namespace of mcld
 
 #endif
-
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
index 037e75a..dddf12b 100644
--- a/lib/Target/Mips/MipsGOT.cpp
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -11,7 +11,6 @@
 #include <llvm/Support/ELF.h>
 
 #include <mcld/LD/ResolveInfo.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Target/OutputRelocSection.h>
 
@@ -19,7 +18,9 @@
 #include "MipsRelocator.h"
 
 namespace {
-  const size_t MipsGOT0Num = 1;
+  const uint32_t Mips32ModulePtr = 1 << 31;
+  const uint64_t Mips64ModulePtr = 1ull << 63;
+  const size_t MipsGOT0Num = 2;
   const size_t MipsGOTGpOffset = 0x7FF0;
   const size_t MipsGOTSize = MipsGOTGpOffset + 0x7FFF;
 }
@@ -27,13 +28,6 @@
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// MipsGOTEntry
-//===----------------------------------------------------------------------===//
-MipsGOTEntry::MipsGOTEntry(uint64_t pContent, SectionData* pParent)
-   : GOT::Entry<4>(pContent, pParent)
-{}
-
-//===----------------------------------------------------------------------===//
 // MipsGOT::GOTMultipart
 //===----------------------------------------------------------------------===//
 MipsGOT::GOTMultipart::GOTMultipart(size_t local, size_t global)
@@ -57,7 +51,7 @@
   assert(m_ConsumedLocal < m_LocalNum &&
          "Consumed too many local GOT entries");
   ++m_ConsumedLocal;
-  m_pLastLocal = llvm::cast<MipsGOTEntry>(m_pLastLocal->getNextNode());
+  m_pLastLocal = m_pLastLocal->getNextNode();
 }
 
 void MipsGOT::GOTMultipart::consumeGlobal()
@@ -65,7 +59,29 @@
   assert(m_ConsumedGlobal < m_GlobalNum &&
          "Consumed too many global GOT entries");
   ++m_ConsumedGlobal;
-  m_pLastGlobal = llvm::cast<MipsGOTEntry>(m_pLastGlobal->getNextNode());
+  m_pLastGlobal = m_pLastGlobal->getNextNode();
+}
+
+//===----------------------------------------------------------------------===//
+// MipsGOT::LocalEntry
+//===----------------------------------------------------------------------===//
+MipsGOT::LocalEntry::LocalEntry(const ResolveInfo* pInfo,
+                                Relocation::DWord addend, bool isGot16)
+  : m_pInfo(pInfo),
+    m_Addend(addend),
+    m_IsGot16(isGot16)
+{
+}
+
+bool MipsGOT::LocalEntry::operator<(const LocalEntry &O) const
+{
+  if (m_pInfo != O.m_pInfo)
+    return m_pInfo < O.m_pInfo;
+
+  if (m_Addend != O.m_Addend)
+    return m_Addend < O.m_Addend;
+
+  return m_IsGot16 < O.m_IsGot16;
 }
 
 //===----------------------------------------------------------------------===//
@@ -78,16 +94,15 @@
 {
 }
 
-SizeTraits<32>::Address MipsGOT::getGPDispAddress() const
+uint64_t MipsGOT::getGPDispAddress() const
 {
   return addr() + MipsGOTGpOffset;
 }
 
 void MipsGOT::reserve(size_t pNum)
 {
-  for (size_t i = 0; i < pNum; i++) {
-    new MipsGOTEntry(0, m_SectionData);
-  }
+  for (size_t i = 0; i < pNum; i++)
+    createEntry(0, m_SectionData);
 }
 
 bool MipsGOT::hasGOT1() const
@@ -104,10 +119,10 @@
 {
   for (MultipartListType::iterator it = m_MultipartList.begin();
        it != m_MultipartList.end(); ++it) {
-    reserve(MipsGOT0Num);
-    it->m_pLastLocal = llvm::cast<MipsGOTEntry>(&m_SectionData->back());
+    reserveHeader();
+    it->m_pLastLocal = &m_SectionData->back();
     reserve(it->m_LocalNum);
-    it->m_pLastGlobal = llvm::cast<MipsGOTEntry>(&m_SectionData->back());
+    it->m_pLastGlobal = &m_SectionData->back();
     reserve(it->m_GlobalNum);
 
     if (it == m_MultipartList.begin())
@@ -137,20 +152,6 @@
   return itX == m_SymbolOrderMap.end() && itY != m_SymbolOrderMap.end();
 }
 
-uint64_t MipsGOT::emit(MemoryRegion& pRegion)
-{
-  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
-
-  uint64_t result = 0;
-  for (iterator it = begin(), ie = end();
-       it != ie; ++it, ++buffer) {
-    MipsGOTEntry* got = &(llvm::cast<MipsGOTEntry>((*it)));
-    *buffer = static_cast<uint32_t>(got->getValue());
-    result += got->size();
-  }
-  return result;
-}
-
 void MipsGOT::initGOTList()
 {
   m_SymbolOrderMap.clear();
@@ -170,8 +171,8 @@
 {
   m_MultipartList.back().m_Inputs.insert(m_pInput);
 
-  for (SymbolSetType::iterator it = m_InputLocalSymbols.begin(),
-                               end = m_InputLocalSymbols.end();
+  for (LocalSymbolSetType::iterator it = m_InputLocalSymbols.begin(),
+                                    end = m_InputLocalSymbols.end();
        it != end; ++it)
     m_MergedLocalSymbols.insert(*it);
 
@@ -193,7 +194,7 @@
 
   gotCount += 1;
 
-  return (gotCount * mcld::MipsGOTEntry::EntrySize) > MipsGOTSize;
+  return gotCount * getEntrySize() > MipsGOTSize;
 }
 
 void MipsGOT::split()
@@ -234,23 +235,27 @@
 {
 }
 
-bool MipsGOT::reserveLocalEntry(ResolveInfo& pInfo)
+bool MipsGOT::reserveLocalEntry(ResolveInfo& pInfo, int reloc,
+                                Relocation::DWord pAddend)
 {
-  if (pInfo.type() != ResolveInfo::Section) {
-    if (m_InputLocalSymbols.count(&pInfo))
-      return false;
+  LocalEntry entry(&pInfo, pAddend, reloc == llvm::ELF::R_MIPS_GOT16);
 
-    if (m_MergedLocalSymbols.count(&pInfo)) {
-      m_InputLocalSymbols.insert(&pInfo);
-      return false;
-    }
+  if (m_InputLocalSymbols.count(entry))
+    // Do nothing, if we have seen this symbol
+    // in the current input already.
+    return false;
+
+  if (m_MergedLocalSymbols.count(entry)) {
+    // We have seen this symbol in previous inputs.
+    // Remember that it exists in the current input too.
+    m_InputLocalSymbols.insert(entry);
+    return false;
   }
 
   if (isGOTFull())
     split();
 
-  if (pInfo.type() != ResolveInfo::Section)
-    m_InputLocalSymbols.insert(&pInfo);
+  m_InputLocalSymbols.insert(entry);
 
   ++m_MultipartList.back().m_LocalNum;
   return true;
@@ -285,7 +290,7 @@
   return m_CurrentGOTPart > 0;
 }
 
-MipsGOTEntry* MipsGOT::consumeLocal()
+Fragment* MipsGOT::consumeLocal()
 {
   assert(m_CurrentGOTPart < m_MultipartList.size() && "GOT number is out of range!");
 
@@ -297,7 +302,7 @@
   return m_MultipartList[m_CurrentGOTPart].m_pLastLocal;
 }
 
-MipsGOTEntry* MipsGOT::consumeGlobal()
+Fragment* MipsGOT::consumeGlobal()
 {
   assert(m_CurrentGOTPart < m_MultipartList.size() && "GOT number is out of range!");
 
@@ -309,7 +314,7 @@
   return m_MultipartList[m_CurrentGOTPart].m_pLastGlobal;
 }
 
-SizeTraits<32>::Address MipsGOT::getGPAddr(const Input& pInput) const
+uint64_t MipsGOT::getGPAddr(const Input& pInput) const
 {
   uint64_t gotSize = 0;
   for (MultipartListType::const_iterator it = m_MultipartList.begin();
@@ -322,32 +327,59 @@
       gotSize += getGlobalNum() - it->m_GlobalNum;
   }
 
-  return addr() + gotSize * MipsGOTEntry::EntrySize + MipsGOTGpOffset;
+  return addr() + gotSize * getEntrySize() + MipsGOTGpOffset;
 }
 
-SizeTraits<32>::Offset MipsGOT::getGPRelOffset(const Input& pInput,
-                                               const MipsGOTEntry& pEntry) const
+uint64_t MipsGOT::getGPRelOffset(const Input& pInput,
+                                 const Fragment& pEntry) const
 {
-  SizeTraits<32>::Address gpAddr = getGPAddr(pInput);
-  return addr() + pEntry.getOffset() - gpAddr;
+  return addr() + pEntry.getOffset() - getGPAddr(pInput);
 }
 
-void MipsGOT::recordEntry(const ResolveInfo* pInfo, MipsGOTEntry* pEntry)
+void MipsGOT::recordGlobalEntry(const ResolveInfo* pInfo, Fragment* pEntry)
 {
   GotEntryKey key;
   key.m_GOTPage = m_CurrentGOTPart;
   key.m_pInfo = pInfo;
-  m_GotEntriesMap[key] = pEntry;
+  key.m_Addend = 0;
+  m_GotGlobalEntriesMap[key] = pEntry;
 }
 
-MipsGOTEntry* MipsGOT::lookupEntry(const ResolveInfo* pInfo)
+Fragment* MipsGOT::lookupGlobalEntry(const ResolveInfo* pInfo)
 {
   GotEntryKey key;
   key.m_GOTPage= m_CurrentGOTPart;
   key.m_pInfo = pInfo;
-  GotEntryMapType::iterator it = m_GotEntriesMap.find(key);
+  key.m_Addend = 0;
+  GotEntryMapType::iterator it = m_GotGlobalEntriesMap.find(key);
 
-  if (it == m_GotEntriesMap.end())
+  if (it == m_GotGlobalEntriesMap.end())
+    return NULL;
+
+  return it->second;
+}
+
+void MipsGOT::recordLocalEntry(const ResolveInfo* pInfo,
+                               Relocation::DWord pAddend,
+                               Fragment* pEntry)
+{
+  GotEntryKey key;
+  key.m_GOTPage = m_CurrentGOTPart;
+  key.m_pInfo = pInfo;
+  key.m_Addend = pAddend;
+  m_GotLocalEntriesMap[key] = pEntry;
+}
+
+Fragment* MipsGOT::lookupLocalEntry(const ResolveInfo* pInfo,
+                                    Relocation::DWord pAddend)
+{
+  GotEntryKey key;
+  key.m_GOTPage= m_CurrentGOTPart;
+  key.m_pInfo = pInfo;
+  key.m_Addend = pAddend;
+  GotEntryMapType::iterator it = m_GotLocalEntriesMap.find(key);
+
+  if (it == m_GotLocalEntriesMap.end())
     return NULL;
 
   return it->second;
@@ -363,3 +395,85 @@
 {
   return m_SymbolOrderMap.size();
 }
+
+//===----------------------------------------------------------------------===//
+// Mips32GOT
+//===----------------------------------------------------------------------===//
+Mips32GOT::Mips32GOT(LDSection& pSection)
+  : MipsGOT(pSection)
+{}
+
+void Mips32GOT::setEntryValue(Fragment* entry, uint64_t pValue)
+{
+  llvm::cast<Mips32GOTEntry>(entry)->setValue(pValue);
+}
+
+uint64_t Mips32GOT::emit(MemoryRegion& pRegion)
+{
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
+
+  uint64_t result = 0;
+  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
+    Mips32GOTEntry* got = &(llvm::cast<Mips32GOTEntry>((*it)));
+    *buffer = static_cast<uint32_t>(got->getValue());
+    result += got->size();
+  }
+  return result;
+}
+
+Fragment* Mips32GOT::createEntry(uint64_t pValue, SectionData* pParent)
+{
+  return new Mips32GOTEntry(pValue, pParent);
+}
+
+size_t Mips32GOT::getEntrySize() const
+{
+  return Mips32GOTEntry::EntrySize;
+}
+
+void Mips32GOT::reserveHeader()
+{
+  createEntry(0, m_SectionData);
+  createEntry(Mips32ModulePtr, m_SectionData);
+}
+
+//===----------------------------------------------------------------------===//
+// Mips64GOT
+//===----------------------------------------------------------------------===//
+Mips64GOT::Mips64GOT(LDSection& pSection)
+  : MipsGOT(pSection)
+{}
+
+void Mips64GOT::setEntryValue(Fragment* entry, uint64_t pValue)
+{
+  llvm::cast<Mips64GOTEntry>(entry)->setValue(pValue);
+}
+
+uint64_t Mips64GOT::emit(MemoryRegion& pRegion)
+{
+  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
+
+  uint64_t result = 0;
+  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
+    Mips64GOTEntry* got = &(llvm::cast<Mips64GOTEntry>((*it)));
+    *buffer = static_cast<uint64_t>(got->getValue());
+    result += got->size();
+  }
+  return result;
+}
+
+Fragment* Mips64GOT::createEntry(uint64_t pValue, SectionData* pParent)
+{
+  return new Mips64GOTEntry(pValue, pParent);
+}
+
+size_t Mips64GOT::getEntrySize() const
+{
+  return Mips64GOTEntry::EntrySize;
+}
+
+void Mips64GOT::reserveHeader()
+{
+  createEntry(0, m_SectionData);
+  createEntry(Mips64ModulePtr, m_SectionData);
+}
diff --git a/lib/Target/Mips/MipsGOT.h b/lib/Target/Mips/MipsGOT.h
index 7f3051d..e3a9b9e 100644
--- a/lib/Target/Mips/MipsGOT.h
+++ b/lib/Target/Mips/MipsGOT.h
@@ -15,29 +15,21 @@
 #include <gtest.h>
 #endif
 
-#include <llvm/ADT/DenseMap.h>
-#include <llvm/ADT/DenseSet.h>
-
 #include <mcld/ADT/SizeTraits.h>
 #include <mcld/Target/GOT.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <llvm/ADT/DenseMap.h>
+#include <llvm/ADT/DenseSet.h>
+#include <set>
 
-namespace mcld
-{
+namespace mcld {
+
 class Input;
 class LDSection;
 class LDSymbol;
-class MemoryRegion;
 class OutputRelocSection;
 
-/** \class MipsGOTEntry
- *  \brief GOT Entry with size of 4 bytes
- */
-class MipsGOTEntry : public GOT::Entry<4>
-{
-public:
-  MipsGOTEntry(uint64_t pContent, SectionData* pParent);
-};
-
 /** \class MipsGOT
  *  \brief Mips Global Offset Table.
  */
@@ -46,15 +38,20 @@
 public:
   MipsGOT(LDSection& pSection);
 
-  /// Address of _gp_disp symbol.
-  SizeTraits<32>::Address getGPDispAddress() const;
+  /// Assign value to the GOT entry.
+  virtual void setEntryValue(Fragment* entry, uint64_t pValue) = 0;
 
-  uint64_t emit(MemoryRegion& pRegion);
+  /// Emit the global offset table.
+  virtual uint64_t emit(MemoryRegion& pRegion) = 0;
+
+  /// Address of _gp_disp symbol.
+  uint64_t getGPDispAddress() const;
 
   void initializeScan(const Input& pInput);
   void finalizeScan(const Input& pInput);
 
-  bool reserveLocalEntry(ResolveInfo& pInfo);
+  bool reserveLocalEntry(ResolveInfo& pInfo, int reloc,
+                         Relocation::DWord pAddend);
   bool reserveGlobalEntry(ResolveInfo& pInfo);
 
   size_t getLocalNum() const;   ///< number of local symbols in primary GOT
@@ -62,31 +59,20 @@
 
   bool isPrimaryGOTConsumed();
 
-  MipsGOTEntry* consumeLocal();
-  MipsGOTEntry* consumeGlobal();
+  Fragment* consumeLocal();
+  Fragment* consumeGlobal();
 
-  SizeTraits<32>::Address getGPAddr(const Input& pInput) const;
-  SizeTraits<32>::Offset getGPRelOffset(const Input& pInput,
-                                        const MipsGOTEntry& pEntry) const;
+  uint64_t getGPAddr(const Input& pInput) const;
+  uint64_t getGPRelOffset(const Input& pInput, const Fragment& pEntry) const;
 
-  void recordEntry(const ResolveInfo* pInfo, MipsGOTEntry* pEntry);
-  MipsGOTEntry* lookupEntry(const ResolveInfo* pInfo);
+  void recordGlobalEntry(const ResolveInfo* pInfo, Fragment* pEntry);
+  Fragment* lookupGlobalEntry(const ResolveInfo* pInfo);
 
-  void setLocal(const ResolveInfo* pInfo) {
-    m_GOTTypeMap[pInfo] = false;
-  }
-
-  void setGlobal(const ResolveInfo* pInfo) {
-    m_GOTTypeMap[pInfo] = true;
-  }
-
-  bool isLocal(const ResolveInfo* pInfo) {
-    return m_GOTTypeMap[pInfo] == false;
-  }
-
-  bool isGlobal(const ResolveInfo* pInfo) {
-    return m_GOTTypeMap[pInfo] == true;
-  }
+  void recordLocalEntry(const ResolveInfo* pInfo,
+                        Relocation::DWord pAddend,
+                        Fragment* pEntry);
+  Fragment* lookupLocalEntry(const ResolveInfo* pInfo,
+                             Relocation::DWord pAddend);
 
   /// hasGOT1 - return if this got section has any GOT1 entry
   bool hasGOT1() const;
@@ -99,6 +85,16 @@
   /// Compare two symbols to define order in the .dynsym.
   bool dynSymOrderCompare(const LDSymbol* pX, const LDSymbol* pY) const;
 
+protected:
+  /// Create GOT entry.
+  virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent) = 0;
+
+  /// Size of GOT entry.
+  virtual size_t getEntrySize() const = 0;
+
+  /// Reserve GOT header entries.
+  virtual void reserveHeader() = 0;
+
 private:
   /** \class GOTMultipart
    *  \brief GOTMultipart counts local and global entries in the GOT.
@@ -115,8 +111,8 @@
     size_t m_ConsumedLocal;       ///< consumed local entries
     size_t m_ConsumedGlobal;      ///< consumed global entries
 
-    MipsGOTEntry* m_pLastLocal;   ///< the last consumed local entry
-    MipsGOTEntry* m_pLastGlobal;  ///< the last consumed global entry
+    Fragment* m_pLastLocal;   ///< the last consumed local entry
+    Fragment* m_pLastGlobal;  ///< the last consumed global entry
 
     InputSetType m_Inputs;
 
@@ -126,17 +122,46 @@
     void consumeGlobal();
   };
 
+  /** \class LocalEntry
+   *  \brief LocalEntry local GOT entry descriptor.
+   */
+  struct LocalEntry
+  {
+    const ResolveInfo* m_pInfo;
+    Relocation::DWord  m_Addend;
+    bool               m_IsGot16;
+
+    LocalEntry(const ResolveInfo* pInfo,
+               Relocation::DWord addend, bool isGot16);
+
+    bool operator<(const LocalEntry &O) const;
+  };
+
   typedef std::vector<GOTMultipart> MultipartListType;
 
+  // Set of global symbols.
   typedef llvm::DenseSet<const ResolveInfo*> SymbolSetType;
+  // Map of symbols. If value is true, the symbol is referenced
+  // in the current input only. If value is false, the symbol
+  // is referenced in the other modules merged to the current GOT.
   typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolUniqueMapType;
 
+  // Set of local symbols.
+  typedef std::set<LocalEntry> LocalSymbolSetType;
+
   MultipartListType m_MultipartList;  ///< list of GOT's descriptors
   const Input* m_pInput;              ///< current input
-  SymbolSetType m_MergedGlobalSymbols; ///< merged global symbols from
-  SymbolUniqueMapType m_InputGlobalSymbols; ///< input global symbols
-  SymbolSetType m_MergedLocalSymbols;
-  SymbolSetType m_InputLocalSymbols;
+
+  // Global symbols merged to the current GOT
+  // except symbols from the current input.
+  SymbolSetType m_MergedGlobalSymbols;
+  // Global symbols from the current input.
+  SymbolUniqueMapType m_InputGlobalSymbols;
+  // Local symbols merged to the current GOT
+  // except symbols from the current input.
+  LocalSymbolSetType m_MergedLocalSymbols;
+  // Local symbols from the current input.
+  LocalSymbolSetType m_InputLocalSymbols;
 
   size_t m_CurrentGOTPart;
 
@@ -144,33 +169,72 @@
   SymbolOrderMapType m_SymbolOrderMap;
 
   void initGOTList();
+
   void changeInput();
   bool isGOTFull() const;
   void split();
   void reserve(size_t pNum);
 
 private:
-  typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolTypeMapType;
-
-  SymbolTypeMapType m_GOTTypeMap;
-
-private:
   struct GotEntryKey
   {
     size_t m_GOTPage;
     const ResolveInfo* m_pInfo;
+    Relocation::DWord m_Addend;
 
     bool operator<(const GotEntryKey& key) const
     {
-      if (m_GOTPage == key.m_GOTPage)
-        return m_pInfo < key.m_pInfo;
-      else
+      if (m_GOTPage != key.m_GOTPage)
         return m_GOTPage < key.m_GOTPage;
+
+      if (m_pInfo != key.m_pInfo)
+        return m_pInfo < key.m_pInfo;
+
+      return m_Addend < key.m_Addend;
     }
   };
 
-  typedef std::map<GotEntryKey, MipsGOTEntry*> GotEntryMapType;
-  GotEntryMapType m_GotEntriesMap;
+  typedef std::map<GotEntryKey, Fragment*> GotEntryMapType;
+  GotEntryMapType m_GotLocalEntriesMap;
+  GotEntryMapType m_GotGlobalEntriesMap;
+};
+
+/** \class Mips32GOT
+ *  \brief Mips 32-bit Global Offset Table.
+ */
+class Mips32GOT : public MipsGOT
+{
+public:
+  Mips32GOT(LDSection& pSection);
+
+private:
+  typedef GOT::Entry<4> Mips32GOTEntry;
+
+  // MipsGOT
+  virtual void setEntryValue(Fragment* entry, uint64_t pValue);
+  virtual uint64_t emit(MemoryRegion& pRegion);
+  virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent);
+  virtual size_t getEntrySize() const;
+  virtual void reserveHeader();
+};
+
+/** \class Mips64GOT
+ *  \brief Mips 64-bit Global Offset Table.
+ */
+class Mips64GOT : public MipsGOT
+{
+public:
+  Mips64GOT(LDSection& pSection);
+
+private:
+  typedef GOT::Entry<8> Mips64GOTEntry;
+
+  // MipsGOT
+  virtual void setEntryValue(Fragment* entry, uint64_t pValue);
+  virtual uint64_t emit(MemoryRegion& pRegion);
+  virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent);
+  virtual size_t getEntrySize() const;
+  virtual void reserveHeader();
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/MipsGOTPLT.cpp b/lib/Target/Mips/MipsGOTPLT.cpp
new file mode 100644
index 0000000..1f65490
--- /dev/null
+++ b/lib/Target/Mips/MipsGOTPLT.cpp
@@ -0,0 +1,79 @@
+//===- MipsGOTPLT.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/Support/Casting.h>
+#include "MipsGOTPLT.h"
+
+namespace {
+  typedef mcld::GOT::Entry<4> GOTPLTEntry;
+
+  const size_t MipsGOTPLT0Num = 2;
+}
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+// MipsGOTPLT
+//===----------------------------------------------------------------------===//
+MipsGOTPLT::MipsGOTPLT(LDSection& pSection)
+  : GOT(pSection)
+{
+  // Create header's entries.
+  new GOTPLTEntry(0, m_SectionData);
+  new GOTPLTEntry(0, m_SectionData);
+  m_Last = ++m_SectionData->begin();
+}
+
+void MipsGOTPLT::reserve(size_t pNum)
+{
+  for (size_t i = 0; i < pNum; i++)
+    new GOTPLTEntry(0, m_SectionData);
+}
+
+uint64_t MipsGOTPLT::emit(MemoryRegion& pRegion)
+{
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
+
+  uint64_t result = 0;
+  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
+    GOTPLTEntry* got = &(llvm::cast<GOTPLTEntry>((*it)));
+    *buffer = static_cast<uint32_t>(got->getValue());
+    result += got->size();
+  }
+  return result;
+}
+
+Fragment* MipsGOTPLT::consume()
+{
+  ++m_Last;
+  assert(m_Last != m_SectionData->end() &&
+         "There is no reserved GOTPLT entries");
+  return &(*m_Last);
+}
+
+bool MipsGOTPLT::hasGOT1() const
+{
+  return m_SectionData->size() > MipsGOTPLT0Num;
+}
+
+uint64_t MipsGOTPLT::getEntryAddr(size_t num) const
+{
+  return addr() + (MipsGOTPLT0Num + num) * GOTPLTEntry::EntrySize;
+}
+
+void MipsGOTPLT::applyAllGOTPLT(uint64_t pltAddr)
+{
+  iterator it = begin();
+  llvm::cast<GOTPLTEntry>(*it++).setValue(0); // PLT lazy resolver
+  llvm::cast<GOTPLTEntry>(*it++).setValue(0); // Module pointer
+
+  for (; it != end(); ++it)
+    llvm::cast<GOTPLTEntry>(*it).setValue(pltAddr);
+}
+
+} //end mcld namespace
diff --git a/lib/Target/Mips/MipsGOTPLT.h b/lib/Target/Mips/MipsGOTPLT.h
new file mode 100644
index 0000000..ccf521e
--- /dev/null
+++ b/lib/Target/Mips/MipsGOTPLT.h
@@ -0,0 +1,53 @@
+//===- MipsGOTPLT.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MIPS_GOTPLT_H
+#define MCLD_MIPS_GOTPLT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/GOT.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <llvm/ADT/DenseMap.h>
+
+namespace mcld {
+
+class LDSection;
+
+/** \class MipsGOTPLT
+ *  \brief Mips .got.plt section.
+ */
+class MipsGOTPLT : public GOT
+{
+public:
+  MipsGOTPLT(LDSection &pSection);
+
+  // hasGOT1 - return if this section has any GOT1 entry
+  bool hasGOT1() const;
+
+  uint64_t getEntryAddr(size_t num) const;
+
+  uint64_t emit(MemoryRegion& pRegion);
+
+  Fragment* consume();
+
+  void applyAllGOTPLT(uint64_t pltAddr);
+
+public:
+  // GOT
+  void reserve(size_t pNum = 1);
+
+private:
+  // the last consumed entry.
+  SectionData::iterator m_Last;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Mips/MipsLA25Stub.cpp b/lib/Target/Mips/MipsLA25Stub.cpp
new file mode 100644
index 0000000..fcbc011
--- /dev/null
+++ b/lib/Target/Mips/MipsLA25Stub.cpp
@@ -0,0 +1,109 @@
+//===- MipsLA25Stub.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/ResolveInfo.h>
+#include "MipsLA25Stub.h"
+#include "MipsLDBackend.h"
+
+namespace {
+
+const uint32_t STUB[] = {
+  0x3c190000,   // lui $25,%hi(func)
+  0x08000000,   // j func
+  0x27390000,   // add $25,$25,%lo(func)
+  0x00000000    // nop
+};
+
+enum {
+  // Fake relocations for patching LA25 stubs.
+  R_MIPS_LA25_LUI = 200,
+  R_MIPS_LA25_J   = 201,
+  R_MIPS_LA25_ADD = 202
+};
+
+}
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+// MipsLA25Stub
+//===----------------------------------------------------------------------===//
+
+MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget)
+ : m_Target(pTarget),
+   m_Name("MipsLA25_Prototype"),
+   m_pData(STUB),
+   m_Size(sizeof(STUB))
+{
+  addFixup(0, 0x0, R_MIPS_LA25_LUI);
+  addFixup(4, 0x0, R_MIPS_LA25_J);
+  addFixup(8, 0x0, R_MIPS_LA25_ADD);
+}
+
+MipsLA25Stub::MipsLA25Stub(const MipsGNULDBackend& pTarget,
+                           const uint32_t* pData,
+                           size_t pSize,
+                           const_fixup_iterator pBegin,
+                           const_fixup_iterator pEnd)
+ : m_Target(pTarget),
+   m_Name("pic"),
+   m_pData(pData),
+   m_Size(pSize)
+{
+  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+    addFixup(**it);
+}
+
+bool MipsLA25Stub::isMyDuty(const Relocation& pReloc,
+                            uint64_t pSource,
+                            uint64_t pTargetSymValue) const
+{
+  if (llvm::ELF::R_MIPS_26 != pReloc.type())
+    return false;
+
+  const ResolveInfo* rsym = pReloc.symInfo();
+
+  if (!rsym->isDefine())
+    return false;
+
+  if (rsym->isDyn() || rsym->isUndef())
+    return false;
+
+  if (!m_Target.hasNonPICBranch(rsym))
+    return false;
+
+  return true;
+}
+
+const std::string& MipsLA25Stub::name() const
+{
+  return m_Name;
+}
+
+const uint8_t* MipsLA25Stub::getContent() const
+{
+  return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t MipsLA25Stub::size() const
+{
+  return m_Size;
+}
+
+size_t MipsLA25Stub::alignment() const
+{
+  return 4;
+}
+
+Stub* MipsLA25Stub::doClone()
+{
+  return new MipsLA25Stub(m_Target, m_pData, m_Size,
+                          fixup_begin(), fixup_end());
+}
+
+} //end mcld namespace
diff --git a/lib/Target/Mips/MipsLA25Stub.h b/lib/Target/Mips/MipsLA25Stub.h
new file mode 100644
index 0000000..126cfd7
--- /dev/null
+++ b/lib/Target/Mips/MipsLA25Stub.h
@@ -0,0 +1,64 @@
+//===- MipsLA25Stub.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MIPS_LA25_STUB_H
+#define MCLD_MIPS_LA25_STUB_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Fragment/Stub.h>
+
+namespace mcld
+{
+
+class MipsGNULDBackend;
+class Relocation;
+
+//===----------------------------------------------------------------------===//
+// MipsLA25Stub
+//===----------------------------------------------------------------------===//
+/** \class MipsLA25Stub
+ *  \brief Mips stub for a non-PIC interface to a PIC function.
+ */
+class MipsLA25Stub : public Stub
+{
+public:
+  MipsLA25Stub(const MipsGNULDBackend& pTarget);
+
+private:
+  // Stub
+  Stub* doClone();
+  bool isMyDuty(const Relocation& pReloc,
+                uint64_t pSource,
+                uint64_t pTargetSymValue) const;
+  const std::string& name() const;
+  const uint8_t* getContent() const;
+  size_t size() const;
+  size_t alignment() const;
+
+private:
+  MipsLA25Stub(const MipsLA25Stub&);
+  MipsLA25Stub& operator=(const MipsLA25Stub&);
+
+  MipsLA25Stub(const MipsGNULDBackend& pTarget,
+               const uint32_t* pData,
+               size_t pSize,
+               const_fixup_iterator pBegin,
+               const_fixup_iterator pEnd);
+
+private:
+  const MipsGNULDBackend& m_Target;
+  const std::string m_Name;
+  const uint32_t* m_pData;
+  const size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
index e26a89e..a6fd40b 100644
--- a/lib/Target/Mips/MipsLDBackend.cpp
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -9,15 +9,22 @@
 #include "Mips.h"
 #include "MipsGNUInfo.h"
 #include "MipsELFDynamic.h"
+#include "MipsLA25Stub.h"
 #include "MipsLDBackend.h"
 #include "MipsRelocator.h"
 
 #include <llvm/ADT/Triple.h>
+#include <llvm/Support/Casting.h>
 #include <llvm/Support/ELF.h>
+#include <llvm/Support/Host.h>
 
 #include <mcld/Module.h>
 #include <mcld/LinkerConfig.h>
 #include <mcld/IRBuilder.h>
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/LD/StubFactory.h>
+#include <mcld/LD/ELFFileFormat.h>
 #include <mcld/MC/Attribute.h>
 #include <mcld/Fragment/FillFragment.h>
 #include <mcld/Support/MemoryRegion.h>
@@ -37,9 +44,14 @@
   : GNULDBackend(pConfig, pInfo),
     m_pRelocator(NULL),
     m_pGOT(NULL),
+    m_pPLT(NULL),
+    m_pGOTPLT(NULL),
+    m_pInfo(*pInfo),
+    m_pRelPlt(NULL),
     m_pRelDyn(NULL),
     m_pDynamic(NULL),
     m_pGOTSymbol(NULL),
+    m_pPLTSymbol(NULL),
     m_pGpDispSymbol(NULL)
 {
 }
@@ -47,24 +59,52 @@
 MipsGNULDBackend::~MipsGNULDBackend()
 {
   delete m_pRelocator;
-  delete m_pGOT;
+  delete m_pPLT;
+  delete m_pRelPlt;
   delete m_pRelDyn;
   delete m_pDynamic;
 }
 
-void MipsGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
+bool MipsGNULDBackend::needsLA25Stub(Relocation::Type pType,
+                                     const mcld::ResolveInfo* pSym)
 {
-  if (LinkerConfig::Object != config().codeGenType()) {
-    ELFFileFormat* file_format = getOutputFormat();
+  if (config().isCodeIndep())
+    return false;
 
-    // initialize .got
-    LDSection& got = file_format->getGOT();
-    m_pGOT = new MipsGOT(got);
+  if (llvm::ELF::R_MIPS_26 != pType)
+    return false;
 
-    // initialize .rel.dyn
-    LDSection& reldyn = file_format->getRelDyn();
-    m_pRelDyn = new OutputRelocSection(pModule, reldyn);
-  }
+  if (pSym->isLocal())
+    return false;
+
+  return true;
+}
+
+void MipsGNULDBackend::addNonPICBranchSym(ResolveInfo* rsym)
+{
+  m_HasNonPICBranchSyms.insert(rsym);
+}
+
+bool MipsGNULDBackend::hasNonPICBranch(const ResolveInfo* rsym) const
+{
+  return m_HasNonPICBranchSyms.count(rsym);
+}
+
+void MipsGNULDBackend::initTargetSections(Module& pModule,
+                                            ObjectBuilder& pBuilder)
+{
+  if (LinkerConfig::Object == config().codeGenType())
+    return;
+
+  ELFFileFormat* file_format = getOutputFormat();
+
+  // initialize .rel.plt
+  LDSection& relplt = file_format->getRelPlt();
+  m_pRelPlt = new OutputRelocSection(pModule, relplt);
+
+  // initialize .rel.dyn
+  LDSection& reldyn = file_format->getRelDyn();
+  m_pRelDyn = new OutputRelocSection(pModule, reldyn);
 }
 
 void MipsGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
@@ -81,6 +121,19 @@
                    FragmentRef::Null(), // FragRef
                    ResolveInfo::Hidden);
 
+  // Define the symbol _PROCEDURE_LINKAGE_TABLE_ if there is a symbol with the
+  // same name in input
+  m_pPLTSymbol =
+    pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
+                   "_PROCEDURE_LINKAGE_TABLE_",
+                   ResolveInfo::Object,
+                   ResolveInfo::Define,
+                   ResolveInfo::Local,
+                   0x0,  // size
+                   0x0,  // value
+                   FragmentRef::Null(), // FragRef
+                   ResolveInfo::Hidden);
+
   m_pGpDispSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
                    "_gp_disp",
                    ResolveInfo::Section,
@@ -90,18 +143,6 @@
                    0x0,  // value
                    FragmentRef::Null(), // FragRef
                    ResolveInfo::Default);
-
-  if (NULL != m_pGpDispSymbol) {
-    m_pGpDispSymbol->resolveInfo()->setReserved(MipsRelocator::ReserveGpDisp);
-  }
-}
-
-bool MipsGNULDBackend::initRelocator()
-{
-  if (NULL == m_pRelocator) {
-    m_pRelocator = new MipsRelocator(*this, config());
-  }
-  return true;
 }
 
 Relocator* MipsGNULDBackend::getRelocator()
@@ -128,7 +169,25 @@
       defineGOTSymbol(pBuilder);
     }
 
+    if (m_pGOTPLT->hasGOT1()) {
+      m_pGOTPLT->finalizeSectionSize();
+
+      defineGOTPLTSymbol(pBuilder);
+    }
+
+    if (m_pPLT->hasPLT1())
+      m_pPLT->finalizeSectionSize();
+
     ELFFileFormat* file_format = getOutputFormat();
+
+    // set .rel.plt size
+    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());
+    }
+
     // set .rel.dyn size
     if (!m_pRelDyn->empty()) {
       assert(!config().isCodeStatic() &&
@@ -141,6 +200,32 @@
 
 void MipsGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
 {
+  const ELFFileFormat *format = getOutputFormat();
+
+  if (format->hasGOTPLT()) {
+    assert(m_pGOTPLT && "doPostLayout failed, m_pGOTPLT is NULL!");
+    m_pGOTPLT->applyAllGOTPLT(m_pPLT->addr());
+  }
+
+  if (format->hasPLT()) {
+    assert(m_pPLT && "doPostLayout failed, m_pPLT is NULL!");
+    m_pPLT->applyAllPLT(*m_pGOTPLT);
+  }
+
+  m_pInfo.setABIVersion(m_pPLT && m_pPLT->hasPLT1() ? 1 : 0);
+
+  // FIXME: (simon) We need to iterate all input sections
+  // check that flags are consistent and merge them properly.
+  uint64_t picFlags = llvm::ELF::EF_MIPS_CPIC;
+  if (config().targets().triple().isArch64Bit()) {
+    picFlags |= llvm::ELF::EF_MIPS_PIC;
+  }
+  else {
+    if (LinkerConfig::DynObj == config().codeGenType())
+      picFlags |= llvm::ELF::EF_MIPS_PIC;
+  }
+
+  m_pInfo.setPICFlags(picFlags);
 }
 
 /// dynamic - the dynamic section of the target machine.
@@ -166,10 +251,16 @@
 
   const ELFFileFormat* file_format = getOutputFormat();
 
-  if (&pSection == &(file_format->getGOT())) {
-    assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
-    uint64_t result = m_pGOT->emit(pRegion);
-    return result;
+  if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
+    return m_pGOT->emit(pRegion);
+  }
+
+  if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
+    return m_pPLT->emit(pRegion);
+  }
+
+  if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
+    return m_pGOTPLT->emit(pRegion);
   }
 
   fatal(diag::unrecognized_output_sectoin)
@@ -218,6 +309,102 @@
                    DynsymGOTCompare(*m_pGOT));
 }
 
+namespace llvm {
+namespace ELF {
+// SHT_MIPS_OPTIONS section's block descriptor.
+struct Elf_Options {
+  unsigned char kind;     // Determines interpretation of variable
+                          // part of descriptor. See ODK_xxx enumeration.
+  unsigned char size;     // Byte size of descriptor, including this header.
+  Elf64_Half    section;  // Section header index of section affected,
+                          // or 0 for global options.
+  Elf64_Word    info;     // Kind-specific information.
+};
+
+// Type of SHT_MIPS_OPTIONS section's block.
+enum {
+  ODK_NULL       = 0, // Undefined.
+  ODK_REGINFO    = 1, // Register usage and GP value.
+  ODK_EXCEPTIONS = 2, // Exception processing information.
+  ODK_PAD        = 3, // Section padding information.
+  ODK_HWPATCH    = 4, // Hardware workarounds performed.
+  ODK_FILL       = 5, // Fill value used by the linker.
+  ODK_TAGS       = 6, // Reserved space for desktop tools.
+  ODK_HWAND      = 7, // Hardware workarounds, AND bits when merging.
+  ODK_HWOR       = 8, // Hardware workarounds, OR bits when merging.
+  ODK_GP_GROUP   = 9, // GP group to use for text/data sections.
+  ODK_IDENT      = 10 // ID information.
+};
+
+// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 32 bit ABI.
+struct Elf32_RegInfo {
+  Elf32_Word ri_gprmask;    // Mask of general purpose registers used.
+  Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used.
+  Elf32_Addr ri_gp_value;   // GP register value for this object file.
+};
+
+// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 64 bit ABI.
+struct Elf64_RegInfo {
+  Elf32_Word ri_gprmask;    // Mask of general purpose registers used.
+  Elf32_Word ri_pad;        // Padding.
+  Elf32_Word ri_cprmask[4]; // Mask of co-processor registers used.
+  Elf64_Addr ri_gp_value;   // GP register value for this object file.
+};
+
+}
+}
+
+bool MipsGNULDBackend::readSection(Input& pInput, SectionData& pSD)
+{
+  llvm::StringRef name(pSD.getSection().name());
+
+  if (name.startswith(".sdata")) {
+    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;
+  }
+
+  if (pSD.getSection().type() == llvm::ELF::SHT_MIPS_OPTIONS) {
+    uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
+    uint32_t size = pSD.getSection().size();
+
+    llvm::StringRef region = pInput.memArea()->request(offset, size);
+    if (region.size() > 0) {
+      const llvm::ELF::Elf_Options* optb =
+        reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin());
+      const llvm::ELF::Elf_Options* opte =
+        reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin() + size);
+
+      for (const llvm::ELF::Elf_Options* opt = optb; opt < opte; opt += opt->size) {
+        switch (opt->kind) {
+          default:
+            // Nothing to do.
+            break;
+          case llvm::ELF::ODK_REGINFO:
+            if (config().targets().triple().isArch32Bit()) {
+              const llvm::ELF::Elf32_RegInfo* reg =
+                reinterpret_cast<const llvm::ELF::Elf32_RegInfo*>(opt + 1);
+              m_GP0Map[&pInput] = reg->ri_gp_value;
+            }
+            else {
+              const llvm::ELF::Elf64_RegInfo* reg =
+                reinterpret_cast<const llvm::ELF::Elf64_RegInfo*>(opt + 1);
+              m_GP0Map[&pInput] = reg->ri_gp_value;
+            }
+            break;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  return GNULDBackend::readSection(pInput, pSD);
+}
+
 MipsGOT& MipsGNULDBackend::getGOT()
 {
   assert(NULL != m_pGOT);
@@ -230,6 +417,42 @@
   return *m_pGOT;
 }
 
+MipsPLT& MipsGNULDBackend::getPLT()
+{
+  assert(NULL != m_pPLT);
+  return *m_pPLT;
+}
+
+const MipsPLT& MipsGNULDBackend::getPLT() const
+{
+  assert(NULL != m_pPLT);
+  return *m_pPLT;
+}
+
+MipsGOTPLT& MipsGNULDBackend::getGOTPLT()
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
+const MipsGOTPLT& MipsGNULDBackend::getGOTPLT() const
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
+OutputRelocSection& MipsGNULDBackend::getRelPLT()
+{
+  assert(NULL != m_pRelPlt);
+  return *m_pRelPlt;
+}
+
+const OutputRelocSection& MipsGNULDBackend::getRelPLT() const
+{
+  assert(NULL != m_pRelPlt);
+  return *m_pRelPlt;
+}
+
 OutputRelocSection& MipsGNULDBackend::getRelDyn()
 {
   assert(NULL != m_pRelDyn);
@@ -247,9 +470,15 @@
 {
   const ELFFileFormat* file_format = getOutputFormat();
 
-  if (&pSectHdr == &file_format->getGOT())
+  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT()))
     return SHO_DATA;
 
+  if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
+    return SHO_DATA;
+
+  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
+    return SHO_PLT;
+
   return SHO_UNDEFINED;
 }
 
@@ -313,19 +542,20 @@
       // description here.
       (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
       Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
       if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
         // allocate TLS common symbol in tbss section
         tbss_offset += ObjectBuilder::AppendFragment(*frag,
                                                      *tbss_sect_data,
                                                      (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       }
       // FIXME: how to identify small and large common symbols?
       else {
         bss_offset += ObjectBuilder::AppendFragment(*frag,
                                                     *bss_sect_data,
                                                     (*com_sym)->value());
+        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
       }
     }
   }
@@ -340,19 +570,20 @@
     // description here.
     (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
     Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
     if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
       // allocate TLS common symbol in tbss section
       tbss_offset += ObjectBuilder::AppendFragment(*frag,
                                                    *tbss_sect_data,
                                                    (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
     }
     // FIXME: how to identify small and large common symbols?
     else {
       bss_offset += ObjectBuilder::AppendFragment(*frag,
                                                   *bss_sect_data,
                                                   (*com_sym)->value());
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
     }
   }
 
@@ -362,6 +593,11 @@
   return true;
 }
 
+uint64_t MipsGNULDBackend::getGP0(const Input& pInput) const
+{
+  return m_GP0Map.lookup(&pInput);
+}
+
 void MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
 {
   // If we do not reserve any GOT entries, we do not need to re-define GOT
@@ -394,6 +630,33 @@
   }
 }
 
+void MipsGNULDBackend::defineGOTPLTSymbol(IRBuilder& pBuilder)
+{
+  // define symbol _PROCEDURE_LINKAGE_TABLE_
+  if ( m_pPLTSymbol != NULL ) {
+    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
+                     "_PROCEDURE_LINKAGE_TABLE_",
+                     ResolveInfo::Object,
+                     ResolveInfo::Define,
+                     ResolveInfo::Local,
+                     0x0, // size
+                     0x0, // value
+                     FragmentRef::Create(*(m_pPLT->begin()), 0x0),
+                     ResolveInfo::Hidden);
+  }
+  else {
+    m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+                     "_PROCEDURE_LINKAGE_TABLE_",
+                     ResolveInfo::Object,
+                     ResolveInfo::Define,
+                     ResolveInfo::Local,
+                     0x0, // size
+                     0x0, // value
+                     FragmentRef::Create(*(m_pPLT->begin()), 0x0),
+                     ResolveInfo::Hidden);
+  }
+}
+
 /// doCreateProgramHdrs - backend can implement this function to create the
 /// target-dependent segments
 void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule)
@@ -401,27 +664,343 @@
   // TODO
 }
 
+bool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel)
+{
+  uint64_t sym_value = 0x0;
+
+  LDSymbol* symbol = pRel.symInfo()->outSymbol();
+  if (symbol->hasFragRef()) {
+    uint64_t value = symbol->fragRef()->getOutputOffset();
+    uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr();
+    sym_value = addr + value;
+  }
+
+  Stub* stub =
+    getStubFactory()->create(pRel, sym_value, pBuilder, *getBRIslandFactory());
+
+  if (NULL == stub)
+    return false;
+
+  assert(NULL != stub->symInfo());
+  // increase the size of .symtab and .strtab
+  LDSection& symtab = getOutputFormat()->getSymTab();
+  LDSection& strtab = getOutputFormat()->getStrTab();
+  symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
+  strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
+
+  return true;
+}
+
+bool MipsGNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder,
+                               bool& pFinished)
+{
+  assert(NULL != getStubFactory() && NULL != getBRIslandFactory());
+
+  bool isRelaxed = false;
+
+  for (Module::obj_iterator input = pModule.obj_begin();
+       input != pModule.obj_end(); ++input) {
+    LDContext* context = (*input)->context();
+
+    for (LDContext::sect_iterator rs = context->relocSectBegin();
+         rs != context->relocSectEnd(); ++rs) {
+      LDSection* sec = *rs;
+
+      if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData())
+        continue;
+
+      for (RelocData::iterator reloc = sec->getRelocData()->begin();
+           reloc != sec->getRelocData()->end(); ++reloc) {
+        if (llvm::ELF::R_MIPS_26 != reloc->type())
+          continue;
+
+        if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc)))
+          isRelaxed = true;
+      }
+    }
+  }
+
+  SectionData* textData = getOutputFormat()->getText().getSectionData();
+
+  // find the first fragment w/ invalid offset due to stub insertion
+  Fragment* invalid = NULL;
+  pFinished = true;
+  for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(),
+                                     ie = getBRIslandFactory()->end();
+       ii != ie; ++ii)
+  {
+    BranchIsland& island = *ii;
+    if (island.end() == textData->end())
+      break;
+
+    Fragment* exit = island.end();
+    if ((island.offset() + island.size()) > exit->getOffset()) {
+      invalid = exit;
+      pFinished = false;
+      break;
+    }
+  }
+
+  // reset the offset of invalid fragments
+  while (NULL != invalid) {
+    invalid->setOffset(invalid->getPrevNode()->getOffset() +
+                       invalid->getPrevNode()->size());
+    invalid = invalid->getNextNode();
+  }
+
+  // reset the size of .text
+  if (isRelaxed)
+    getOutputFormat()->getText().setSize(textData->back().getOffset() +
+                                         textData->back().size());
+
+  return isRelaxed;
+}
+
+bool MipsGNULDBackend::initTargetStubs()
+{
+  if (NULL == getStubFactory())
+    return false;
+
+  getStubFactory()->addPrototype(new MipsLA25Stub(*this));
+  return true;
+}
+
+bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel,
+                                      Relocation::Type& pType,
+                                      uint32_t& pSymIdx,
+                                      uint32_t& pOffset) const
+{
+  return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset);
+}
+
+bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel,
+                                      Relocation::Type& pType,
+                                      uint32_t& pSymIdx,
+                                      uint32_t& pOffset,
+                                      int32_t& pAddend) const
+{
+  return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
+}
+
+bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel,
+                                      Relocation::Type& pType,
+                                      uint32_t& pSymIdx,
+                                      uint64_t& pOffset) const
+{
+  uint64_t r_info = 0x0;
+  if (llvm::sys::IsLittleEndianHost) {
+    pOffset = pRel.r_offset;
+    r_info  = pRel.r_info;
+  }
+  else {
+    pOffset = mcld::bswap64(pRel.r_offset);
+    r_info  = mcld::bswap64(pRel.r_info);
+  }
+
+  // MIPS 64 little endian (we do not support big endian now)
+  // has a "special" encoding of r_info relocation
+  // field. Instead of one 64 bit little endian number, it is a little
+  // endian 32 bit number followed by a 32 bit big endian number.
+  pType = mcld::bswap32(r_info >> 32);
+  pSymIdx = r_info & 0xffffffff;
+  return true;
+}
+
+bool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel,
+                                      Relocation::Type& pType,
+                                      uint32_t& pSymIdx,
+                                      uint64_t& pOffset,
+                                      int64_t& pAddend) const
+{
+  uint64_t r_info = 0x0;
+  if (llvm::sys::IsLittleEndianHost) {
+    pOffset = pRel.r_offset;
+    r_info  = pRel.r_info;
+    pAddend = pRel.r_addend;
+  }
+  else {
+    pOffset = mcld::bswap64(pRel.r_offset);
+    r_info  = mcld::bswap64(pRel.r_info);
+    pAddend = mcld::bswap64(pRel.r_addend);
+  }
+
+  pType = mcld::bswap32(r_info >> 32);
+  pSymIdx = r_info & 0xffffffff;
+  return true;
+}
+
+void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel,
+                                      Relocation::Type pType,
+                                      uint32_t pSymIdx,
+                                      uint32_t pOffset) const
+{
+  GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset);
+}
+
+void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel,
+                                      Relocation::Type pType,
+                                      uint32_t pSymIdx,
+                                      uint32_t pOffset,
+                                      int32_t pAddend) const
+{
+  GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
+}
+
+void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel,
+                                      Relocation::Type pType,
+                                      uint32_t pSymIdx,
+                                      uint64_t pOffset) const
+{
+  uint64_t r_info = mcld::bswap32(pType);
+  r_info <<= 32;
+  r_info |= pSymIdx;
+
+  pRel.r_info = r_info;
+  pRel.r_offset = pOffset;
+}
+
+void MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel,
+                                      Relocation::Type pType,
+                                      uint32_t pSymIdx,
+                                      uint64_t pOffset,
+                                      int64_t pAddend) const
+{
+  uint64_t r_info = mcld::bswap32(pType);
+  r_info <<= 32;
+  r_info |= pSymIdx;
+
+  pRel.r_info = r_info;
+  pRel.r_offset = pOffset;
+  pRel.r_addend = pAddend;
+}
+
+//===----------------------------------------------------------------------===//
+// Mips32GNULDBackend
+//===----------------------------------------------------------------------===//
+Mips32GNULDBackend::Mips32GNULDBackend(const LinkerConfig& pConfig,
+                                       MipsGNUInfo* pInfo)
+  : MipsGNULDBackend(pConfig, pInfo)
+{}
+
+bool Mips32GNULDBackend::initRelocator()
+{
+  if (NULL == m_pRelocator)
+    m_pRelocator = new Mips32Relocator(*this, config());
+
+  return true;
+}
+
+void Mips32GNULDBackend::initTargetSections(Module& pModule,
+                                            ObjectBuilder& pBuilder)
+{
+  MipsGNULDBackend::initTargetSections(pModule, pBuilder);
+
+  if (LinkerConfig::Object == config().codeGenType())
+    return;
+
+  ELFFileFormat* fileFormat = getOutputFormat();
+
+  // initialize .got
+  LDSection& got = fileFormat->getGOT();
+  m_pGOT = new Mips32GOT(got);
+
+  // initialize .got.plt
+  LDSection& gotplt = fileFormat->getGOTPLT();
+  m_pGOTPLT = new MipsGOTPLT(gotplt);
+
+  // initialize .plt
+  LDSection& plt = fileFormat->getPLT();
+  m_pPLT = new MipsPLT(plt);
+}
+
+size_t Mips32GNULDBackend::getRelEntrySize()
+{
+  return 8;
+}
+
+size_t Mips32GNULDBackend::getRelaEntrySize()
+{
+  return 12;
+}
+
+//===----------------------------------------------------------------------===//
+// Mips64GNULDBackend
+//===----------------------------------------------------------------------===//
+Mips64GNULDBackend::Mips64GNULDBackend(const LinkerConfig& pConfig,
+                                       MipsGNUInfo* pInfo)
+  : MipsGNULDBackend(pConfig, pInfo)
+{}
+
+bool Mips64GNULDBackend::initRelocator()
+{
+  if (NULL == m_pRelocator)
+    m_pRelocator = new Mips64Relocator(*this, config());
+
+  return true;
+}
+
+void Mips64GNULDBackend::initTargetSections(Module& pModule,
+                                            ObjectBuilder& pBuilder)
+{
+  MipsGNULDBackend::initTargetSections(pModule, pBuilder);
+
+  if (LinkerConfig::Object == config().codeGenType())
+    return;
+
+  ELFFileFormat* fileFormat = getOutputFormat();
+
+  // initialize .got
+  LDSection& got = fileFormat->getGOT();
+  m_pGOT = new Mips64GOT(got);
+
+  // initialize .got.plt
+  LDSection& gotplt = fileFormat->getGOTPLT();
+  m_pGOTPLT = new MipsGOTPLT(gotplt);
+
+  // initialize .plt
+  LDSection& plt = fileFormat->getPLT();
+  m_pPLT = new MipsPLT(plt);
+}
+
+size_t Mips64GNULDBackend::getRelEntrySize()
+{
+  return 16;
+}
+
+size_t Mips64GNULDBackend::getRelaEntrySize()
+{
+  return 24;
+}
+
 //===----------------------------------------------------------------------===//
 /// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
 ///
-static TargetLDBackend* createMipsLDBackend(const llvm::Target& pTarget,
-                                            const LinkerConfig& pConfig)
+static TargetLDBackend* createMipsLDBackend(const LinkerConfig& pConfig)
 {
-  if (pConfig.targets().triple().isOSDarwin()) {
+  const llvm::Triple& triple = pConfig.targets().triple();
+
+  if (triple.isOSDarwin()) {
     assert(0 && "MachO linker is not supported yet");
   }
-  if (pConfig.targets().triple().isOSWindows()) {
+  if (triple.isOSWindows()) {
     assert(0 && "COFF linker is not supported yet");
   }
-  return new MipsGNULDBackend(pConfig, new MipsGNUInfo(pConfig.targets().triple()));
+
+  llvm::Triple::ArchType arch = triple.getArch();
+
+  if (llvm::Triple::mips64el == arch)
+    return new Mips64GNULDBackend(pConfig, new MipsGNUInfo(triple));
+
+  assert (arch == llvm::Triple::mipsel);
+  return new Mips32GNULDBackend(pConfig, new MipsGNUInfo(triple));
 }
 
 //===----------------------------------------------------------------------===//
 // Force static initialization.
 //===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeMipsLDBackend() {
-  // Register the linker backend
   mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
                                                 createMipsLDBackend);
+  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMips64elTarget,
+                                                createMipsLDBackend);
 }
-
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
index 831d830..5c4d12b 100644
--- a/lib/Target/Mips/MipsLDBackend.h
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -11,6 +11,8 @@
 #include <mcld/Target/GNULDBackend.h>
 #include "MipsELFDynamic.h"
 #include "MipsGOT.h"
+#include "MipsGOTPLT.h"
+#include "MipsPLT.h"
 
 namespace mcld {
 
@@ -20,9 +22,9 @@
 class MemoryArea;
 class MipsGNUInfo;
 
-//===----------------------------------------------------------------------===//
-/// MipsGNULDBackend - linker backend of Mips target of GNU ELF format
-///
+/** \class MipsGNULDBackend
+ *  \brief Base linker backend of Mips target of GNU ELF format.
+ */
 class MipsGNULDBackend : public GNULDBackend
 {
 public:
@@ -32,6 +34,11 @@
   MipsGNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
   ~MipsGNULDBackend();
 
+  bool needsLA25Stub(Relocation::Type pType, const mcld::ResolveInfo* pSym);
+
+  void addNonPICBranchSym(ResolveInfo* rsym);
+  bool hasNonPICBranch(const ResolveInfo* rsym) const;
+
 public:
   /// initTargetSections - initialize target dependent sections in output
   void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
@@ -39,9 +46,6 @@
   /// initTargetSymbols - initialize target dependent symbols in output.
   void initTargetSymbols(IRBuilder& pBuilder, Module& pModule);
 
-  /// initRelocator - create and initialize Relocator.
-  bool initRelocator();
-
   /// getRelocator - return relocator.
   Relocator* getRelocator();
 
@@ -82,14 +86,26 @@
   /// orderSymbolTable - order symbol table before emitting
   void orderSymbolTable(Module& pModule);
 
+  /// readSection - read a target dependent section.
+  bool readSection(Input& pInput, SectionData& pSD);
+
   MipsGOT& getGOT();
   const MipsGOT& getGOT() const;
 
+  MipsPLT& getPLT();
+  const MipsPLT& getPLT() const;
+
+  MipsGOTPLT& getGOTPLT();
+  const MipsGOTPLT& getGOTPLT() const;
+
+  OutputRelocSection& getRelPLT();
+  const OutputRelocSection& getRelPLT() const;
+
   OutputRelocSection& getRelDyn();
   const OutputRelocSection& getRelDyn() const;
 
-  LDSymbol*             getGOTSymbo()            { return m_pGOTSymbol;    }
-  const LDSymbol*       getGOTSymbo() const      { return m_pGOTSymbol;    }
+  LDSymbol*             getGOTSymbol()           { return m_pGOTSymbol;    }
+  const LDSymbol*       getGOTSymbol() const     { return m_pGOTSymbol;    }
 
   LDSymbol*             getGpDispSymbol()        { return m_pGpDispSymbol; }
   const LDSymbol*       getGpDispSymbol() const  { return m_pGpDispSymbol; }
@@ -107,8 +123,15 @@
   /// sections.
   bool allocateCommonSymbols(Module& pModule);
 
+  /// getGP0 - the gp value used to create the relocatable objects
+  /// in the specified input.
+  uint64_t getGP0(const Input& pInput) const;
+
 private:
   void defineGOTSymbol(IRBuilder& pBuilder);
+  void defineGOTPLTSymbol(IRBuilder& pBuilder);
+
+  bool relaxRelocation(IRBuilder& pBuilder, Relocation& pRel);
 
   /// emitSymbol32 - emit an ELF32 symbol, override parent's function
   void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32,
@@ -117,32 +140,134 @@
                     size_t pStrtabsize,
                     size_t pSymtabIdx);
 
-  /// 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;
+  /// mayRelax - Backends should override this function if they need relaxation
+  bool mayRelax() { return true; }
 
+  /// doRelax - Backend can orevride this function to add its relaxation
+  /// 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, IRBuilder& pBuilder, bool& pFinished);
+
+  /// initTargetStubs
+  bool initTargetStubs();
+
+  /// readRelocation - read ELF32_Rel entry
+  bool readRelocation(const llvm::ELF::Elf32_Rel& pRel,
+                      Relocation::Type& pType,
+                      uint32_t& pSymIdx,
+                      uint32_t& pOffset) const;
+
+  /// readRelocation - read ELF32_Rela entry
+  bool readRelocation(const llvm::ELF::Elf32_Rela& pRel,
+                      Relocation::Type& pType,
+                      uint32_t& pSymIdx,
+                      uint32_t& pOffset,
+                      int32_t& pAddend) const;
+
+  /// readRelocation - read ELF64_Rel entry
+  bool readRelocation(const llvm::ELF::Elf64_Rel& pRel,
+                      Relocation::Type& pType,
+                      uint32_t& pSymIdx,
+                      uint64_t& pOffset) const;
+
+  /// readRel - read ELF64_Rela entry
+  bool readRelocation(const llvm::ELF::Elf64_Rela& pRel,
+                      Relocation::Type& pType,
+                      uint32_t& pSymIdx,
+                      uint64_t& pOffset,
+                      int64_t& pAddend) const;
+
+  /// emitRelocation - write data to the ELF32_Rel entry
+  void emitRelocation(llvm::ELF::Elf32_Rel& pRel,
+                      Relocation::Type pType,
+                      uint32_t pSymIdx,
+                      uint32_t pOffset) const;
+
+  /// emitRelocation - write data to the ELF32_Rela entry
+  void emitRelocation(llvm::ELF::Elf32_Rela& pRel,
+                      Relocation::Type pType,
+                      uint32_t pSymIdx,
+                      uint32_t pOffset,
+                      int32_t pAddend) const;
+
+  /// emitRelocation - write data to the ELF64_Rel entry
+  void emitRelocation(llvm::ELF::Elf64_Rel& pRel,
+                      Relocation::Type pType,
+                      uint32_t pSymIdx,
+                      uint64_t pOffset) const;
+
+  /// emitRelocation - write data to the ELF64_Rela entry
+  void emitRelocation(llvm::ELF::Elf64_Rela& pRel,
+                      Relocation::Type pType,
+                      uint32_t pSymIdx,
+                      uint64_t pOffset,
+                      int64_t pAddend) const;
+
+private:
+  typedef llvm::DenseSet<const ResolveInfo*> ResolveInfoSetType;
+  typedef llvm::DenseMap<const Input*, llvm::ELF::Elf64_Addr> GP0MapType;
+
+protected:
+  Relocator* m_pRelocator;
   MipsGOT* m_pGOT;                      // .got
+  MipsPLT* m_pPLT;                      // .plt
+  MipsGOTPLT* m_pGOTPLT;                // .got.plt
+
+private:
+  MipsGNUInfo& m_pInfo;
+
+  OutputRelocSection* m_pRelPlt;        // .rel.plt
   OutputRelocSection* m_pRelDyn;        // .rel.dyn
 
   MipsELFDynamic* m_pDynamic;
   LDSymbol* m_pGOTSymbol;
+  LDSymbol* m_pPLTSymbol;
   LDSymbol* m_pGpDispSymbol;
 
   SymbolListType m_GlobalGOTSyms;
+  ResolveInfoSetType m_HasNonPICBranchSyms;
+  GP0MapType m_GP0Map;
+};
+
+/** \class Mips32GNULDBackend
+ *  \brief Base linker backend of Mips 32-bit target of GNU ELF format.
+ */
+class Mips32GNULDBackend : public MipsGNULDBackend
+{
+public:
+  Mips32GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
+
+private:
+  // MipsGNULDBackend
+
+  bool initRelocator();
+  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
+  size_t getRelEntrySize();
+  size_t getRelaEntrySize();
+};
+
+/** \class Mips64GNULDBackend
+ *  \brief Base linker backend of Mips 64-bit target of GNU ELF format.
+ */
+class Mips64GNULDBackend : public MipsGNULDBackend
+{
+public:
+  Mips64GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
+
+private:
+  // MipsGNULDBackend
+
+  bool initRelocator();
+  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
+  size_t getRelEntrySize();
+  size_t getRelaEntrySize();
 };
 
 } // namespace of mcld
 
 #endif
-
diff --git a/lib/Target/Mips/MipsMCLinker.cpp b/lib/Target/Mips/MipsMCLinker.cpp
index 5805f12..49940b7 100644
--- a/lib/Target/Mips/MipsMCLinker.cpp
+++ b/lib/Target/Mips/MipsMCLinker.cpp
@@ -6,25 +6,21 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "MipsELFMCLinker.h"
-
 #include "Mips.h"
+#include "MipsELFMCLinker.h"
 #include <llvm/ADT/Triple.h>
 #include <mcld/Module.h>
 #include <mcld/Support/TargetRegistry.h>
 
-using namespace mcld;
+namespace {
 
-namespace mcld {
 //===----------------------------------------------------------------------===//
-/// createMipsMCLinker - the help funtion to create
+/// createMipsMCLinker - the help funtion to create corresponding MipsMCLinker
 //===----------------------------------------------------------------------===//
-/// corresponding MipsMCLinker
-///
-MCLinker* createMipsMCLinker(const std::string &pTriple,
-                             LinkerConfig& pConfig,
-                             mcld::Module& pModule,
-                             MemoryArea& pOutput)
+mcld::MCLinker* createMipsMCLinker(const std::string &pTriple,
+                                   mcld::LinkerConfig& pConfig,
+                                   mcld::Module& pModule,
+                                   mcld::FileHandle& pFileHandle)
 {
   llvm::Triple theTriple(pTriple);
   if (theTriple.isOSDarwin()) {
@@ -36,7 +32,7 @@
     return NULL;
   }
 
-  return new MipsELFMCLinker(pConfig, pModule, pOutput);
+  return new mcld::MipsELFMCLinker(pConfig, pModule, pFileHandle);
 }
 
 } // namespace of mcld
@@ -45,6 +41,8 @@
 // MipsMCLinker
 //===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeMipsMCLinker() {
-  // Register the linker frontend
-  mcld::TargetRegistry::RegisterMCLinker(TheMipselTarget, createMipsMCLinker);
+  mcld::TargetRegistry::RegisterMCLinker(mcld::TheMipselTarget,
+                                         createMipsMCLinker);
+  mcld::TargetRegistry::RegisterMCLinker(mcld::TheMips64elTarget,
+                                         createMipsMCLinker);
 }
diff --git a/lib/Target/Mips/MipsPLT.cpp b/lib/Target/Mips/MipsPLT.cpp
new file mode 100644
index 0000000..a00b7c8
--- /dev/null
+++ b/lib/Target/Mips/MipsPLT.cpp
@@ -0,0 +1,169 @@
+//===- MipsPLT.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/Support/Casting.h>
+#include <llvm/Support/ELF.h>
+#include <mcld/Support/MsgHandling.h>
+#include "MipsGOTPLT.h"
+#include "MipsPLT.h"
+
+namespace {
+
+const uint32_t PLT0[] = {
+  0x3c1c0000,         // lui $28, %hi(&GOTPLT[0])
+  0x8f990000,         // lw $25, %lo(&GOTPLT[0])($28)
+  0x279c0000,         // addiu $28, $28, %lo(&GOTPLT[0])
+  0x031cc023,         // subu $24, $24, $28
+  0x03e07821,         // move $15, $31
+  0x0018c082,         // srl $24, $24, 2
+  0x0320f809,         // jalr $25
+  0x2718fffe          // subu $24, $24, 2
+};
+
+const uint32_t PLTA[] = {
+  0x3c0f0000,         // lui $15, %hi(.got.plt entry)
+  0x8df90000,         // l[wd] $25, %lo(.got.plt entry)($15)
+  0x03200008,         // jr $25
+  0x25f80000          // addiu $24, $15, %lo(.got.plt entry)
+};
+
+}
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+// MipsPLT0 Entry
+//===----------------------------------------------------------------------===//
+class MipsPLT0 : public PLT::Entry<sizeof(PLT0)>
+{
+public:
+  MipsPLT0(SectionData& pParent)
+    : PLT::Entry<sizeof(PLT0)>(pParent)
+  {}
+};
+
+//===----------------------------------------------------------------------===//
+// MipsPLTA Entry
+//===----------------------------------------------------------------------===//
+class MipsPLTA : public PLT::Entry<sizeof(PLTA)>
+{
+public:
+  MipsPLTA(SectionData& pParent)
+    : PLT::Entry<sizeof(PLTA)>(pParent)
+  {}
+};
+
+//===----------------------------------------------------------------------===//
+// MipsPLT
+//===----------------------------------------------------------------------===//
+MipsPLT::MipsPLT(LDSection& pSection)
+  : PLT(pSection)
+{
+  new MipsPLT0(*m_SectionData);
+  m_Last = m_SectionData->begin();
+}
+
+void MipsPLT::finalizeSectionSize()
+{
+  uint64_t size = sizeof(PLT0) +
+                  (m_SectionData->size() - 1) * sizeof(PLTA);
+  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();
+  }
+}
+
+bool MipsPLT::hasPLT1() const
+{
+  return m_SectionData->size() > 1;
+}
+
+uint64_t MipsPLT::emit(MemoryRegion& pRegion)
+{
+  uint64_t result = 0x0;
+  iterator it = begin();
+
+  unsigned char* buffer = pRegion.begin();
+  memcpy(buffer, llvm::cast<MipsPLT0>((*it)).getValue(), MipsPLT0::EntrySize);
+  result += MipsPLT0::EntrySize;
+  ++it;
+
+  MipsPLTA* plta = 0;
+  for (iterator ie = end(); it != ie; ++it) {
+    plta = &(llvm::cast<MipsPLTA>(*it));
+    memcpy(buffer + result, plta->getValue(), MipsPLTA::EntrySize);
+    result += MipsPLTA::EntrySize;
+  }
+  return result;
+}
+
+void MipsPLT::reserveEntry(size_t pNum)
+{
+  for (size_t i = 0; i < pNum; ++i) {
+    Fragment* entry = new (std::nothrow) MipsPLTA(*m_SectionData);
+
+    if (NULL == entry)
+      fatal(diag::fail_allocate_memory_plt);
+  }
+}
+
+Fragment* MipsPLT::consume()
+{
+  ++m_Last;
+  assert(m_Last != m_SectionData->end() &&
+         "The number of PLT Entries and ResolveInfo doesn't match");
+  return &(*m_Last);
+}
+
+void MipsPLT::applyAllPLT(MipsGOTPLT& pGOTPLT)
+{
+  assert(m_Section.addr() && ".plt base address is NULL!");
+
+  size_t count = 0;
+  for (iterator it = m_SectionData->begin(); it != m_SectionData->end(); ++it) {
+    PLTEntryBase* plt = &(llvm::cast<PLTEntryBase>(*it));
+
+    if (it == m_SectionData->begin()) {
+      uint32_t* data = static_cast<uint32_t*>(malloc(plt->size()));
+
+      if (!data)
+        fatal(diag::fail_allocate_memory_plt);
+
+      memcpy(data, PLT0, plt->size());
+
+      uint64_t gotAddr = pGOTPLT.addr();
+
+      data[0] |= ((gotAddr + 0x8000) >> 16) & 0xffff;
+      data[1] |= gotAddr & 0xffff;
+      data[2] |= gotAddr & 0xffff;
+
+      plt->setValue(reinterpret_cast<unsigned char*>(data));
+    } else {
+      uint32_t* data = static_cast<uint32_t*>(malloc(plt->size()));
+
+      if (!data)
+        fatal(diag::fail_allocate_memory_plt);
+
+      memcpy(data, PLTA, plt->size());
+
+      uint64_t gotEntryAddr = pGOTPLT.getEntryAddr(count++);
+
+      data[0] |= ((gotEntryAddr + 0x8000) >> 16) & 0xffff;
+      data[1] |= gotEntryAddr & 0xffff;
+      data[3] |= gotEntryAddr & 0xffff;
+
+      plt->setValue(reinterpret_cast<unsigned char*>(data));
+    }
+  }
+}
+
+} //end mcld namespace
diff --git a/lib/Target/Mips/MipsPLT.h b/lib/Target/Mips/MipsPLT.h
new file mode 100644
index 0000000..f2ad0c8
--- /dev/null
+++ b/lib/Target/Mips/MipsPLT.h
@@ -0,0 +1,51 @@
+//===- MipsPLT.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_MIPS_PLT_H
+#define MCLD_TARGET_MIPS_PLT_H
+
+#include <mcld/Target/PLT.h>
+#include <mcld/Support/MemoryRegion.h>
+
+namespace mcld {
+
+class MipsGOTPLT;
+
+//===----------------------------------------------------------------------===//
+// MipsPLT
+//===----------------------------------------------------------------------===//
+/** \class MipsPLT
+ *  \brief Mips Procedure Linkage Table
+ */
+class MipsPLT : public PLT
+{
+public:
+  MipsPLT(LDSection& pSection);
+
+  // hasPLT1 - return if this PLT has any PLTA/PLTB entries
+  bool hasPLT1() const;
+
+  uint64_t emit(MemoryRegion& pRegion);
+
+  Fragment* consume();
+
+  void applyAllPLT(MipsGOTPLT& pGOTPLT);
+
+public:
+  // PLT
+  void reserveEntry(size_t pNum = 1);
+  void finalizeSectionSize();
+
+private:
+  // the last consumed entry.
+  SectionData::iterator m_Last;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Mips/MipsRelocationFunctions.h b/lib/Target/Mips/MipsRelocationFunctions.h
index f1461a0..3634686 100644
--- a/lib/Target/Mips/MipsRelocationFunctions.h
+++ b/lib/Target/Mips/MipsRelocationFunctions.h
@@ -8,70 +8,285 @@
 //===----------------------------------------------------------------------===//
 
 #define DECL_MIPS_APPLY_RELOC_FUNC(Name) \
-static MipsRelocator::Result Name(Relocation& pEntry, \
+static MipsRelocator::Result Name(MipsRelocationInfo& pReloc, \
                                   MipsRelocator& pParent);
 
 #define DECL_MIPS_APPLY_RELOC_FUNCS \
 DECL_MIPS_APPLY_RELOC_FUNC(none) \
 DECL_MIPS_APPLY_RELOC_FUNC(abs32) \
+DECL_MIPS_APPLY_RELOC_FUNC(rel26) \
 DECL_MIPS_APPLY_RELOC_FUNC(hi16) \
 DECL_MIPS_APPLY_RELOC_FUNC(lo16) \
+DECL_MIPS_APPLY_RELOC_FUNC(gprel16) \
 DECL_MIPS_APPLY_RELOC_FUNC(got16) \
 DECL_MIPS_APPLY_RELOC_FUNC(call16) \
 DECL_MIPS_APPLY_RELOC_FUNC(gprel32) \
+DECL_MIPS_APPLY_RELOC_FUNC(abs64) \
+DECL_MIPS_APPLY_RELOC_FUNC(gotdisp) \
+DECL_MIPS_APPLY_RELOC_FUNC(gotoff) \
 DECL_MIPS_APPLY_RELOC_FUNC(gothi16) \
-DECL_MIPS_APPLY_RELOC_FUNC(gotlo16)
+DECL_MIPS_APPLY_RELOC_FUNC(gotlo16) \
+DECL_MIPS_APPLY_RELOC_FUNC(sub) \
+DECL_MIPS_APPLY_RELOC_FUNC(jalr) \
+DECL_MIPS_APPLY_RELOC_FUNC(la25lui) \
+DECL_MIPS_APPLY_RELOC_FUNC(la25j) \
+DECL_MIPS_APPLY_RELOC_FUNC(la25add) \
+DECL_MIPS_APPLY_RELOC_FUNC(pc32) \
+DECL_MIPS_APPLY_RELOC_FUNC(unsupport)
 
 #define DECL_MIPS_APPLY_RELOC_FUNC_PTRS \
-  { &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}
+  { &none,         0, "R_MIPS_NONE",                  0}, \
+  { &unsupport,    1, "R_MIPS_16",                   16}, \
+  { &abs32,        2, "R_MIPS_32",                   32}, \
+  { &unsupport,    3, "R_MIPS_REL32",                32}, \
+  { &rel26,        4, "R_MIPS_26",                   26}, \
+  { &hi16,         5, "R_MIPS_HI16",                 16}, \
+  { &lo16,         6, "R_MIPS_LO16",                 16}, \
+  { &gprel16,      7, "R_MIPS_GPREL16",              16}, \
+  { &unsupport,    8, "R_MIPS_LITERAL",              16}, \
+  { &got16,        9, "R_MIPS_GOT16",                16}, \
+  { &unsupport,   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}, \
+  { &unsupport,   16, "R_MIPS_SHIFT5",               32}, \
+  { &unsupport,   17, "R_MIPS_SHIFT6",               32}, \
+  { &abs64,       18, "R_MIPS_64",                   64}, \
+  { &gotdisp,     19, "R_MIPS_GOT_DISP",             16}, \
+  { &gotdisp,     20, "R_MIPS_GOT_PAGE",             16}, \
+  { &gotoff,      21, "R_MIPS_GOT_OFST",             16}, \
+  { &gothi16,     22, "R_MIPS_GOT_HI16",             16}, \
+  { &gotlo16,     23, "R_MIPS_GOT_LO16",             16}, \
+  { &sub,         24, "R_MIPS_SUB",                  64}, \
+  { &unsupport,   25, "R_MIPS_INSERT_A",              0}, \
+  { &unsupport,   26, "R_MIPS_INSERT_B",              0}, \
+  { &unsupport,   27, "R_MIPS_DELETE",                0}, \
+  { &unsupport,   28, "R_MIPS_HIGHER",               16}, \
+  { &unsupport,   29, "R_MIPS_HIGHEST",              16}, \
+  { &gothi16,     30, "R_MIPS_CALL_HI16",            16}, \
+  { &gotlo16,     31, "R_MIPS_CALL_LO16",            16}, \
+  { &unsupport,   32, "R_MIPS_SCN_DISP",             32}, \
+  { &unsupport,   33, "R_MIPS_REL16",                 0}, \
+  { &unsupport,   34, "R_MIPS_ADD_IMMEDIATE",         0}, \
+  { &unsupport,   35, "R_MIPS_PJUMP",                 0}, \
+  { &unsupport,   36, "R_MIPS_RELGOT",                0}, \
+  { &jalr,        37, "R_MIPS_JALR",                 32}, \
+  { &unsupport,   38, "R_MIPS_TLS_DTPMOD32",         32}, \
+  { &unsupport,   39, "R_MIPS_TLS_DTPREL32",         32}, \
+  { &unsupport,   40, "R_MIPS_TLS_DTPMOD64",          0}, \
+  { &unsupport,   41, "R_MIPS_TLS_DTPREL64",          0}, \
+  { &unsupport,   42, "R_MIPS_TLS_GD",               16}, \
+  { &unsupport,   43, "R_MIPS_TLS_LDM",              16}, \
+  { &unsupport,   44, "R_MIPS_TLS_DTPREL_HI16",      16}, \
+  { &unsupport,   45, "R_MIPS_TLS_DTPREL_LO16",      16}, \
+  { &unsupport,   46, "R_MIPS_TLS_GOTTPREL",         16}, \
+  { &unsupport,   47, "R_MIPS_TLS_TPREL32",          32}, \
+  { &unsupport,   48, "R_MIPS_TLS_TPREL64",           0}, \
+  { &unsupport,   49, "R_MIPS_TLS_TPREL_HI16",       16}, \
+  { &unsupport,   50, "R_MIPS_TLS_TPREL_LO16",       16}, \
+  { &unsupport,   51, "R_MIPS_GLOB_DAT",              0}, \
+  { &unsupport,   52, "",                             0}, \
+  { &unsupport,   53, "",                             0}, \
+  { &unsupport,   54, "",                             0}, \
+  { &unsupport,   55, "",                             0}, \
+  { &unsupport,   56, "",                             0}, \
+  { &unsupport,   57, "",                             0}, \
+  { &unsupport,   58, "",                             0}, \
+  { &unsupport,   59, "",                             0}, \
+  { &unsupport,   60, "",                             0}, \
+  { &unsupport,   61, "",                             0}, \
+  { &unsupport,   62, "",                             0}, \
+  { &unsupport,   63, "",                             0}, \
+  { &unsupport,   64, "",                             0}, \
+  { &unsupport,   65, "",                             0}, \
+  { &unsupport,   66, "",                             0}, \
+  { &unsupport,   67, "",                             0}, \
+  { &unsupport,   68, "",                             0}, \
+  { &unsupport,   69, "",                             0}, \
+  { &unsupport,   70, "",                             0}, \
+  { &unsupport,   71, "",                             0}, \
+  { &unsupport,   72, "",                             0}, \
+  { &unsupport,   73, "",                             0}, \
+  { &unsupport,   74, "",                             0}, \
+  { &unsupport,   75, "",                             0}, \
+  { &unsupport,   76, "",                             0}, \
+  { &unsupport,   77, "",                             0}, \
+  { &unsupport,   78, "",                             0}, \
+  { &unsupport,   79, "",                             0}, \
+  { &unsupport,   80, "",                             0}, \
+  { &unsupport,   81, "",                             0}, \
+  { &unsupport,   82, "",                             0}, \
+  { &unsupport,   83, "",                             0}, \
+  { &unsupport,   84, "",                             0}, \
+  { &unsupport,   85, "",                             0}, \
+  { &unsupport,   86, "",                             0}, \
+  { &unsupport,   87, "",                             0}, \
+  { &unsupport,   88, "",                             0}, \
+  { &unsupport,   89, "",                             0}, \
+  { &unsupport,   90, "",                             0}, \
+  { &unsupport,   91, "",                             0}, \
+  { &unsupport,   92, "",                             0}, \
+  { &unsupport,   93, "",                             0}, \
+  { &unsupport,   94, "",                             0}, \
+  { &unsupport,   95, "",                             0}, \
+  { &unsupport,   96, "",                             0}, \
+  { &unsupport,   97, "",                             0}, \
+  { &unsupport,   98, "",                             0}, \
+  { &unsupport,   99, "",                             0}, \
+  { &unsupport,  100, "R_MIPS16_26",                  0}, \
+  { &unsupport,  101, "R_MIPS16_GPREL",               0}, \
+  { &unsupport,  102, "R_MIPS16_GOT16",               0}, \
+  { &unsupport,  103, "R_MIPS16_CALL16",              0}, \
+  { &unsupport,  104, "R_MIPS16_HI16",                0}, \
+  { &unsupport,  105, "R_MIPS16_LO16",                0}, \
+  { &unsupport,  106, "R_MIPS16_TLS_GD",              0}, \
+  { &unsupport,  107, "R_MIPS16_TLS_LDM",             0}, \
+  { &unsupport,  108, "R_MIPS16_TLS_DTPREL_HI16",     0}, \
+  { &unsupport,  109, "R_MIPS16_TLS_DTPREL_LO16",     0}, \
+  { &unsupport,  110, "R_MIPS16_TLS_GOTTPREL",        0}, \
+  { &unsupport,  111, "R_MIPS16_TLS_TPREL_HI16",      0}, \
+  { &unsupport,  112, "R_MIPS16_TLS_TPREL_LO16",      0}, \
+  { &unsupport,  113, "",                             0}, \
+  { &unsupport,  114, "",                             0}, \
+  { &unsupport,  115, "",                             0}, \
+  { &unsupport,  116, "",                             0}, \
+  { &unsupport,  117, "",                             0}, \
+  { &unsupport,  118, "",                             0}, \
+  { &unsupport,  119, "",                             0}, \
+  { &unsupport,  120, "",                             0}, \
+  { &unsupport,  121, "",                             0}, \
+  { &unsupport,  122, "",                             0}, \
+  { &unsupport,  123, "",                             0}, \
+  { &unsupport,  124, "",                             0}, \
+  { &unsupport,  125, "",                             0}, \
+  { &unsupport,  126, "R_MIPS_COPY",                  0}, \
+  { &unsupport,  127, "R_MIPS_JUMP_SLOT",             0}, \
+  { &unsupport,  128, "",                             0}, \
+  { &unsupport,  129, "",                             0}, \
+  { &unsupport,  130, "",                             0}, \
+  { &unsupport,  131, "",                             0}, \
+  { &unsupport,  132, "",                             0}, \
+  { &unsupport,  133, "R_MICROMIPS_26_S1",            0}, \
+  { &unsupport,  134, "R_MICROMIPS_HI16",             0}, \
+  { &unsupport,  135, "R_MICROMIPS_LO16",             0}, \
+  { &unsupport,  136, "R_MICROMIPS_GPREL16",          0}, \
+  { &unsupport,  137, "R_MICROMIPS_LITERAL",          0}, \
+  { &unsupport,  138, "R_MICROMIPS_GOT16",            0}, \
+  { &unsupport,  139, "R_MICROMIPS_PC7_S1",           0}, \
+  { &unsupport,  140, "R_MICROMIPS_PC10_S1",          0}, \
+  { &unsupport,  141, "R_MICROMIPS_PC16_S1",          0}, \
+  { &unsupport,  142, "R_MICROMIPS_CALL16",           0}, \
+  { &unsupport,  143, "R_MICROMIPS_GOT_DISP",         0}, \
+  { &unsupport,  144, "R_MICROMIPS_GOT_PAGE",         0}, \
+  { &unsupport,  145, "R_MICROMIPS_GOT_OFST",         0}, \
+  { &unsupport,  146, "R_MICROMIPS_GOT_HI16",         0}, \
+  { &unsupport,  147, "R_MICROMIPS_GOT_LO16",         0}, \
+  { &unsupport,  148, "R_MICROMIPS_SUB",              0}, \
+  { &unsupport,  149, "R_MICROMIPS_HIGHER",           0}, \
+  { &unsupport,  150, "R_MICROMIPS_HIGHEST",          0}, \
+  { &unsupport,  151, "R_MICROMIPS_CALL_HI16",        0}, \
+  { &unsupport,  152, "R_MICROMIPS_CALL_LO16",        0}, \
+  { &unsupport,  153, "R_MICROMIPS_SCN_DISP",         0}, \
+  { &unsupport,  154, "R_MICROMIPS_JALR",             0}, \
+  { &unsupport,  155, "R_MICROMIPS_HI0_LO16",         0}, \
+  { &unsupport,  156, "",                             0}, \
+  { &unsupport,  157, "",                             0}, \
+  { &unsupport,  158, "",                             0}, \
+  { &unsupport,  159, "",                             0}, \
+  { &unsupport,  160, "",                             0}, \
+  { &unsupport,  161, "",                             0}, \
+  { &unsupport,  162, "R_MICROMIPS_TLS_GD",           0}, \
+  { &unsupport,  163, "R_MICROMIPS_TLS_LDM",          0}, \
+  { &unsupport,  164, "R_MICROMIPS_TLS_DTPREL_HI16",  0}, \
+  { &unsupport,  165, "R_MICROMIPS_TLS_DTPREL_LO16",  0}, \
+  { &unsupport,  166, "R_MICROMIPS_TLS_GOTTPREL",     0}, \
+  { &unsupport,  167, "",                             0}, \
+  { &unsupport,  168, "",                             0}, \
+  { &unsupport,  169, "R_MICROMIPS_TLS_TPREL_HI16",   0}, \
+  { &unsupport,  170, "R_MICROMIPS_TLS_TPREL_LO16",   0}, \
+  { &unsupport,  171, "",                             0}, \
+  { &unsupport,  172, "R_MICROMIPS_GPREL7_S2",        0}, \
+  { &unsupport,  173, "R_MICROMIPS_PC23_S2",          0}, \
+  { &unsupport,  174, "",                             0}, \
+  { &unsupport,  175, "",                             0}, \
+  { &unsupport,  176, "",                             0}, \
+  { &unsupport,  177, "",                             0}, \
+  { &unsupport,  178, "",                             0}, \
+  { &unsupport,  179, "",                             0}, \
+  { &unsupport,  180, "",                             0}, \
+  { &unsupport,  181, "",                             0}, \
+  { &unsupport,  182, "",                             0}, \
+  { &unsupport,  183, "",                             0}, \
+  { &unsupport,  184, "",                             0}, \
+  { &unsupport,  185, "",                             0}, \
+  { &unsupport,  186, "",                             0}, \
+  { &unsupport,  187, "",                             0}, \
+  { &unsupport,  188, "",                             0}, \
+  { &unsupport,  189, "",                             0}, \
+  { &unsupport,  190, "",                             0}, \
+  { &unsupport,  191, "",                             0}, \
+  { &unsupport,  192, "",                             0}, \
+  { &unsupport,  193, "",                             0}, \
+  { &unsupport,  194, "",                             0}, \
+  { &unsupport,  195, "",                             0}, \
+  { &unsupport,  196, "",                             0}, \
+  { &unsupport,  197, "",                             0}, \
+  { &unsupport,  198, "",                             0}, \
+  { &unsupport,  199, "",                             0}, \
+  { &la25lui,    200, "R_MIPS_LA25_LUI",             16}, \
+  { &la25j,      201, "R_MIPS_LA25_J",               26}, \
+  { &la25add,    202, "R_MIPS_LA25_ADD",             16}, \
+  { &unsupport,  203, "",                             0}, \
+  { &unsupport,  204, "",                             0}, \
+  { &unsupport,  205, "",                             0}, \
+  { &unsupport,  206, "",                             0}, \
+  { &unsupport,  207, "",                             0}, \
+  { &unsupport,  208, "",                             0}, \
+  { &unsupport,  209, "",                             0}, \
+  { &unsupport,  210, "",                             0}, \
+  { &unsupport,  211, "",                             0}, \
+  { &unsupport,  212, "",                             0}, \
+  { &unsupport,  213, "",                             0}, \
+  { &unsupport,  214, "",                             0}, \
+  { &unsupport,  215, "",                             0}, \
+  { &unsupport,  216, "",                             0}, \
+  { &unsupport,  217, "",                             0}, \
+  { &unsupport,  218, "",                             0}, \
+  { &unsupport,  219, "",                             0}, \
+  { &unsupport,  220, "",                             0}, \
+  { &unsupport,  221, "",                             0}, \
+  { &unsupport,  222, "",                             0}, \
+  { &unsupport,  223, "",                             0}, \
+  { &unsupport,  224, "",                             0}, \
+  { &unsupport,  225, "",                             0}, \
+  { &unsupport,  226, "",                             0}, \
+  { &unsupport,  227, "",                             0}, \
+  { &unsupport,  228, "",                             0}, \
+  { &unsupport,  229, "",                             0}, \
+  { &unsupport,  230, "",                             0}, \
+  { &unsupport,  231, "",                             0}, \
+  { &unsupport,  232, "",                             0}, \
+  { &unsupport,  233, "",                             0}, \
+  { &unsupport,  234, "",                             0}, \
+  { &unsupport,  235, "",                             0}, \
+  { &unsupport,  236, "",                             0}, \
+  { &unsupport,  237, "",                             0}, \
+  { &unsupport,  238, "",                             0}, \
+  { &unsupport,  239, "",                             0}, \
+  { &unsupport,  240, "",                             0}, \
+  { &unsupport,  241, "",                             0}, \
+  { &unsupport,  242, "",                             0}, \
+  { &unsupport,  243, "",                             0}, \
+  { &unsupport,  244, "",                             0}, \
+  { &unsupport,  245, "",                             0}, \
+  { &unsupport,  246, "",                             0}, \
+  { &unsupport,  247, "",                             0}, \
+  { &pc32,       248, "R_MIPS_PC32",                  0}, \
+  { &unsupport,  249, "",                             0}, \
+  { &unsupport,  250, "R_MIPS_GNU_REL16_S2",          0}, \
+  { &unsupport,  251, "",                             0}, \
+  { &unsupport,  252, "",                             0}, \
+  { &unsupport,  253, "R_MIPS_GNU_VTINHERIT",         0}, \
+  { &unsupport,  254, "R_MIPS_GNU_VTENTRY",           0}
diff --git a/lib/Target/Mips/MipsRelocator.cpp b/lib/Target/Mips/MipsRelocator.cpp
index 8f08862..314a6ad 100644
--- a/lib/Target/Mips/MipsRelocator.cpp
+++ b/lib/Target/Mips/MipsRelocator.cpp
@@ -6,26 +6,155 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#include <llvm/ADT/Twine.h>
-#include <llvm/Support/ELF.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Target/OutputRelocSection.h>
-#include <mcld/LinkerConfig.h>
-#include <mcld/IRBuilder.h>
-
 #include "MipsRelocator.h"
 #include "MipsRelocationFunctions.h"
 
+#include <mcld/IRBuilder.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Object/ObjectBuilder.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/OutputRelocSection.h>
+#include <mcld/LD/ELFFileFormat.h>
+
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/ELF.h>
+
+namespace llvm {
+namespace ELF {
+
+// FIXME: Consider upstream these relocation types to LLVM.
+enum {
+  R_MIPS_LA25_LUI = 200,
+  R_MIPS_LA25_J   = 201,
+  R_MIPS_LA25_ADD = 202,
+  R_MIPS_PC32     = 248,
+};
+
+} // end namespace ELF
+} // end namespace llvm
+
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
+// MipsRelocationInfo
+//===----------------------------------------------------------------------===//
+class mcld::MipsRelocationInfo
+{
+public:
+  static bool HasSubType(const Relocation& pParent, Relocation::Type pType)
+  {
+    if (llvm::ELF::R_MIPS_NONE == pType)
+      return true;
+
+    for (Relocation::Type type = pParent.type();
+         llvm::ELF::R_MIPS_NONE != (type & 0xff); type >>= 8) {
+      if ((type & 0xff) == pType)
+        return true;
+    }
+
+    return false;
+  }
+
+  MipsRelocationInfo(Relocation& pParent, bool pIsRel)
+    : m_Parent(&pParent),
+      m_Type(pParent.type()),
+      m_Addend(0),
+      m_Symbol(pParent.symValue()),
+      m_Result(pParent.target())
+  {
+    if (pIsRel && (type() < llvm::ELF::R_MIPS_LA25_LUI ||
+                   type() > llvm::ELF::R_MIPS_LA25_ADD))
+      m_Addend = pParent.target();
+    else
+      m_Addend = pParent.addend();
+  }
+
+  bool isNone() const
+  {
+    return llvm::ELF::R_MIPS_NONE == type();
+  }
+
+  bool isLast() const
+  {
+    return llvm::ELF::R_MIPS_NONE == (m_Type >> 8);
+  }
+
+  MipsRelocationInfo next() const
+  {
+    return MipsRelocationInfo(*m_Parent, m_Type >> 8, result(), result(), 0);
+  }
+
+  const Relocation& parent() const
+  {
+    return *m_Parent;
+  }
+
+  Relocation& parent()
+  {
+    return *m_Parent;
+  }
+
+  Relocation::Type type() const
+  {
+    return m_Type & 0xff;
+  }
+
+  Relocation::DWord A() const
+  {
+    return m_Addend;
+  }
+
+  Relocation::DWord S() const
+  {
+    return m_Symbol;
+  }
+
+  Relocation::DWord P() const
+  {
+    return parent().place();
+  }
+
+  Relocation::DWord result() const
+  {
+    return m_Result;
+  }
+
+  Relocation::DWord& result()
+  {
+    return m_Result;
+  }
+
+private:
+  Relocation* m_Parent;
+  Relocation::Type m_Type;
+  Relocation::DWord m_Addend;
+  Relocation::DWord m_Symbol;
+  Relocation::DWord m_Result;
+
+  MipsRelocationInfo(Relocation& pParent, Relocation::Type pType,
+                     Relocation::DWord pResult,
+                     Relocation::DWord pAddend, Relocation::DWord pSymbol)
+    : m_Parent(&pParent),
+      m_Type(pType),
+      m_Addend(pAddend),
+      m_Symbol(pSymbol),
+      m_Result(pResult)
+  {}
+
+  bool isFirst() const {
+    return m_Type == parent().type();
+  }
+};
+
+//===----------------------------------------------------------------------===//
 // Relocation Functions and Tables
 //===----------------------------------------------------------------------===//
 DECL_MIPS_APPLY_RELOC_FUNCS
 
 /// the prototype of applying function
-typedef Relocator::Result (*ApplyFunctionType)(Relocation&, MipsRelocator&);
+typedef Relocator::Result (*ApplyFunctionType)(MipsRelocationInfo&,
+                                               MipsRelocator& pParent);
+
 
 // the table entry of applying functions
 struct ApplyFunctionTriple
@@ -49,78 +178,102 @@
   : Relocator(pConfig),
     m_Target(pParent),
     m_pApplyingInput(NULL),
-    m_AHL(0)
+    m_CurrentLo16Reloc(NULL)
 {
 }
 
 Relocator::Result
-MipsRelocator::applyRelocation(Relocation& pRelocation)
+MipsRelocator::applyRelocation(Relocation& pReloc)
 {
-  Relocation::Type type = pRelocation.type();
-
-  if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) {
-    return Unknown;
+  // If m_CurrentLo16Reloc is not NULL we are processing
+  // postponed relocation. Otherwise check relocation type
+  // and postpone it for later handling.
+  if (NULL == m_CurrentLo16Reloc && isPostponed(pReloc)) {
+    postponeRelocation(pReloc);
+    return OK;
   }
 
-  // apply the relocation
-  return ApplyFunctions[type].func(pRelocation, *this);
+  for (MipsRelocationInfo info(pReloc, isRel());
+       !info.isNone(); info = info.next()) {
+    if (info.type() >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0]))
+      return Unknown;
+
+    const ApplyFunctionTriple & triple = ApplyFunctions[info.type()];
+
+    Result res = triple.func(info, *this);
+    if (OK != res)
+      return res;
+
+    if (info.isLast()) {
+      uint64_t mask = 0xFFFFFFFFFFFFFFFFULL >> (64 - triple.size);
+      pReloc.target() &= ~mask;
+      pReloc.target() |= info.result() & mask;
+    }
+  }
+
+  return OK;
 }
 
 const char* MipsRelocator::getName(Relocation::Type pType) const
 {
-  return ApplyFunctions[pType].name;
+  return ApplyFunctions[pType & 0xff].name;
 }
 
 Relocator::Size MipsRelocator::getSize(Relocation::Type pType) const
 {
-  return ApplyFunctions[pType].size;
+  return ApplyFunctions[pType & 0xff].size;
 }
 
 void MipsRelocator::scanRelocation(Relocation& pReloc,
                                    IRBuilder& pBuilder,
                                    Module& pModule,
-                                   LDSection& pSection)
+                                   LDSection& pSection,
+                                   Input& pInput)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
 
   // Skip relocation against _gp_disp
-  if (NULL != getTarget().getGpDispSymbol()) {
-    if (pReloc.symInfo() == getTarget().getGpDispSymbol()->resolveInfo())
-      return;
-  }
-
-  pReloc.updateAddend();
+  if (NULL != getTarget().getGpDispSymbol() &&
+      rsym == getTarget().getGpDispSymbol()->resolveInfo())
+    return;
 
   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
-  // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
-  // Don't put undef symbols into local entries.
-  if ((rsym->isLocal() || !getTarget().isDynamicSymbol(*rsym) ||
-      !rsym->isDyn()) && !rsym->isUndef())
-    scanLocalReloc(pReloc, pBuilder, pSection);
-  else
-    scanGlobalReloc(pReloc, pBuilder, pSection);
+  for (MipsRelocationInfo info(pReloc, isRel());
+       !info.isNone(); info = info.next()) {
+    // We test isLocal or if pInputSym is not a dynamic symbol
+    // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
+    // Don't put undef symbols into local entries.
+    if (isLocalReloc(*rsym))
+      scanLocalReloc(info, pBuilder, pSection);
+    else
+      scanGlobalReloc(info, pBuilder, pSection);
 
-  // check if we shoule issue undefined reference for the relocation target
-  // symbol
+    if (getTarget().needsLA25Stub(info.type(), info.parent().symInfo()))
+      getTarget().addNonPICBranchSym(pReloc.symInfo());
+  }
+
+  // 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();
+    issueUndefRef(pReloc, pSection, pInput);
 }
 
 bool MipsRelocator::initializeScan(Input& pInput)
 {
-  getTarget().getGOT().initializeScan(pInput);
+  if (LinkerConfig::Object != config().codeGenType())
+    getTarget().getGOT().initializeScan(pInput);
   return true;
 }
 
 bool MipsRelocator::finalizeScan(Input& pInput)
 {
-  getTarget().getGOT().finalizeScan(pInput);
+  if (LinkerConfig::Object != config().codeGenType())
+    getTarget().getGOT().finalizeScan(pInput);
   return true;
 }
 
@@ -136,17 +289,18 @@
   return true;
 }
 
-void MipsRelocator::scanLocalReloc(Relocation& pReloc,
+void MipsRelocator::scanLocalReloc(MipsRelocationInfo& pReloc,
                                    IRBuilder& pBuilder,
                                    const LDSection& pSection)
 {
-  ResolveInfo* rsym = pReloc.symInfo();
+  ResolveInfo* rsym = pReloc.parent().symInfo();
 
   switch (pReloc.type()){
     case llvm::ELF::R_MIPS_NONE:
     case llvm::ELF::R_MIPS_16:
       break;
     case llvm::ELF::R_MIPS_32:
+    case llvm::ELF::R_MIPS_64:
       if (LinkerConfig::DynObj == config().codeGenType()) {
         // TODO: (simon) The gold linker does not create an entry in .rel.dyn
         // section if the symbol section flags contains SHF_EXECINSTR.
@@ -155,10 +309,6 @@
         getTarget().getRelDyn().reserveEntry();
         rsym->setReserved(rsym->reserved() | ReserveRel);
         getTarget().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.
-        getTarget().getGOT().setLocal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_REL32:
@@ -168,9 +318,6 @@
     case llvm::ELF::R_MIPS_PC16:
     case llvm::ELF::R_MIPS_SHIFT5:
     case llvm::ELF::R_MIPS_SHIFT6:
-    case llvm::ELF::R_MIPS_64:
-    case llvm::ELF::R_MIPS_GOT_PAGE:
-    case llvm::ELF::R_MIPS_GOT_OFST:
     case llvm::ELF::R_MIPS_SUB:
     case llvm::ELF::R_MIPS_INSERT_A:
     case llvm::ELF::R_MIPS_INSERT_B:
@@ -193,17 +340,18 @@
     case llvm::ELF::R_MIPS_CALL_HI16:
     case llvm::ELF::R_MIPS_GOT_LO16:
     case llvm::ELF::R_MIPS_CALL_LO16:
-      if (getTarget().getGOT().reserveLocalEntry(*rsym)) {
+    case llvm::ELF::R_MIPS_GOT_DISP:
+    case llvm::ELF::R_MIPS_GOT_PAGE:
+    case llvm::ELF::R_MIPS_GOT_OFST:
+      if (getTarget().getGOT().reserveLocalEntry(*rsym,
+                                                 pReloc.type(), pReloc.A())) {
         if (getTarget().getGOT().hasMultipleGOT())
           getTarget().checkAndSetHasTextRel(*pSection.getLink());
-        // Remeber this rsym is a local GOT entry
-        getTarget().getGOT().setLocal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_GPREL32:
     case llvm::ELF::R_MIPS_GPREL16:
     case llvm::ELF::R_MIPS_LITERAL:
-    case llvm::ELF::R_MIPS_GOT_DISP:
       break;
     case llvm::ELF::R_MIPS_TLS_DTPMOD32:
     case llvm::ELF::R_MIPS_TLS_DTPREL32:
@@ -219,17 +367,18 @@
     case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
     case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
       break;
+    case llvm::ELF::R_MIPS_PC32:
+      break;
     default:
-      fatal(diag::unknown_relocation) << (int)pReloc.type()
-                                      << pReloc.symInfo()->name();
+      fatal(diag::unknown_relocation) << (int)pReloc.type() << rsym->name();
   }
 }
 
-void MipsRelocator::scanGlobalReloc(Relocation& pReloc,
+void MipsRelocator::scanGlobalReloc(MipsRelocationInfo& pReloc,
                                     IRBuilder& pBuilder,
                                     const LDSection& pSection)
 {
-  ResolveInfo* rsym = pReloc.symInfo();
+  ResolveInfo* rsym = pReloc.parent().symInfo();
 
   switch (pReloc.type()){
     case llvm::ELF::R_MIPS_NONE:
@@ -250,12 +399,15 @@
     case llvm::ELF::R_MIPS_LO16:
       if (getTarget().symbolNeedsDynRel(*rsym, false, true)) {
         getTarget().getRelDyn().reserveEntry();
-        rsym->setReserved(rsym->reserved() | ReserveRel);
-        getTarget().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.
-        getTarget().getGOT().setGlobal(rsym);
+        if (getTarget().symbolNeedsCopyReloc(pReloc.parent(), *rsym)) {
+          LDSymbol& cpySym = defineSymbolforCopyReloc(pBuilder, *rsym);
+          addCopyReloc(*cpySym.resolveInfo());
+        }
+        else {
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+          getTarget().checkAndSetHasTextRel(*pSection.getLink());
+        }
       }
       break;
     case llvm::ELF::R_MIPS_GOT16:
@@ -270,18 +422,25 @@
       if (getTarget().getGOT().reserveGlobalEntry(*rsym)) {
         if (getTarget().getGOT().hasMultipleGOT())
           getTarget().checkAndSetHasTextRel(*pSection.getLink());
-        // Remeber this rsym is a global GOT entry
-        getTarget().getGOT().setGlobal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_LITERAL:
     case llvm::ELF::R_MIPS_GPREL32:
       fatal(diag::invalid_global_relocation) << (int)pReloc.type()
-                                             << pReloc.symInfo()->name();
+                                             << rsym->name();
       break;
     case llvm::ELF::R_MIPS_GPREL16:
       break;
     case llvm::ELF::R_MIPS_26:
+      // Create a PLT entry if the symbol requires it and does not have it.
+      if (getTarget().symbolNeedsPLT(*rsym) &&
+          !(rsym->reserved() & ReservePLT)) {
+        getTarget().getPLT().reserveEntry();
+        getTarget().getGOTPLT().reserve();
+        getTarget().getRelPLT().reserveEntry();
+        rsym->setReserved(rsym->reserved() | ReservePLT);
+      }
+      break;
     case llvm::ELF::R_MIPS_PC16:
       break;
     case llvm::ELF::R_MIPS_16:
@@ -303,8 +462,8 @@
     case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
       break;
     case llvm::ELF::R_MIPS_REL32:
-      break;
     case llvm::ELF::R_MIPS_JALR:
+    case llvm::ELF::R_MIPS_PC32:
       break;
     case llvm::ELF::R_MIPS_COPY:
     case llvm::ELF::R_MIPS_GLOB_DAT:
@@ -312,156 +471,320 @@
       fatal(diag::dynamic_relocation) << (int)pReloc.type();
       break;
     default:
-      fatal(diag::unknown_relocation) << (int)pReloc.type()
-                                      << pReloc.symInfo()->name();
+      fatal(diag::unknown_relocation) << (int)pReloc.type() << rsym->name();
   }
 }
 
-//===----------------------------------------------------------------------===//
-// Relocation helper function
-//===----------------------------------------------------------------------===//
-static const char * const GP_DISP_NAME = "_gp_disp";
-
-// Find next R_MIPS_LO16 relocation paired to pReloc.
-static
-Relocation* helper_FindLo16Reloc(Relocation& pReloc)
+bool MipsRelocator::isPostponed(const Relocation& pReloc) const
 {
-  Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode());
-  while (NULL != reloc)
-  {
-    if (llvm::ELF::R_MIPS_LO16 == reloc->type() &&
-        reloc->symInfo() == pReloc.symInfo())
-      return reloc;
+  if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_HI16))
+    return true;
 
-    reloc = static_cast<Relocation*>(reloc->getNextNode());
+  if (MipsRelocationInfo::HasSubType(pReloc, llvm::ELF::R_MIPS_GOT16) &&
+      pReloc.symInfo()->isLocal())
+    return true;
+
+  return false;
+}
+
+void MipsRelocator::addCopyReloc(ResolveInfo& pSym)
+{
+  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
+  relEntry.setType(llvm::ELF::R_MIPS_COPY);
+  assert(pSym.outSymbol()->hasFragRef());
+  relEntry.targetRef().assign(*pSym.outSymbol()->fragRef());
+  relEntry.setSymInfo(&pSym);
+}
+
+LDSymbol& MipsRelocator::defineSymbolforCopyReloc(IRBuilder& pBuilder,
+                                                  const ResolveInfo& pSym)
+{
+  // Get or create corresponding BSS LDSection
+  ELFFileFormat* fileFormat = getTarget().getOutputFormat();
+  LDSection* bssSectHdr =
+    ResolveInfo::ThreadLocal == pSym.type() ? &fileFormat->getTBSS()
+                                            : &fileFormat->getBSS();
+
+  // Get or create corresponding BSS SectionData
+  SectionData* bssData =
+    bssSectHdr->hasSectionData() ? bssSectHdr->getSectionData()
+                                 : IRBuilder::CreateSectionData(*bssSectHdr);
+
+  // Determine the alignment by the symbol value
+  // FIXME: here we use the largest alignment
+  uint32_t addrAlign = config().targets().bitclass() / 8;
+
+  // Allocate space in BSS for the copy symbol
+  Fragment* frag = new FillFragment(0x0, 1, pSym.size());
+  uint64_t size = ObjectBuilder::AppendFragment(*frag, *bssData, addrAlign);
+  bssSectHdr->setSize(bssSectHdr->size() + size);
+
+  // Change symbol binding to Global if it's a weak symbol
+  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
+  if (binding == ResolveInfo::Weak)
+    binding = ResolveInfo::Global;
+
+  // Define the copy symbol in the bss section and resolve it
+  LDSymbol* cpySym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+                      pSym.name(),
+                      (ResolveInfo::Type)pSym.type(),
+                      ResolveInfo::Define,
+                      binding,
+                      pSym.size(),  // size
+                      0x0,          // value
+                      FragmentRef::Create(*frag, 0x0),
+                      (ResolveInfo::Visibility)pSym.other());
+
+  // Output all other alias symbols if any
+  Module::AliasList* alias_list = pBuilder.getModule().getAliasList(pSym);
+  if (NULL == alias_list)
+    return *cpySym;
+
+  for (Module::alias_iterator it = alias_list->begin(), ie = alias_list->end();
+       it != ie; ++it) {
+    const ResolveInfo* alias = *it;
+    if (alias == &pSym || !alias->isDyn())
+      continue;
+
+    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
+        alias->name(),
+        (ResolveInfo::Type)alias->type(),
+        ResolveInfo::Define,
+        binding,
+        alias->size(),  // size
+        0x0,            // value
+        FragmentRef::Create(*frag, 0x0),
+        (ResolveInfo::Visibility)alias->other());
   }
-  return NULL;
+
+  return *cpySym;
 }
 
-// Check the symbol is _gp_disp.
-static
-bool helper_isGpDisp(const Relocation& pReloc)
+void MipsRelocator::postponeRelocation(Relocation& pReloc)
 {
-  const ResolveInfo* rsym = pReloc.symInfo();
-  return 0 == strcmp(GP_DISP_NAME, rsym->name());
+  ResolveInfo* rsym = pReloc.symInfo();
+  m_PostponedRelocs[rsym].insert(&pReloc);
 }
 
-static
-Relocator::Address helper_GetGP(MipsRelocator& pParent)
+void MipsRelocator::applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc)
 {
-  return pParent.getTarget().getGOT().getGPAddr(pParent.getApplyingInput());
+  m_CurrentLo16Reloc = &pLo16Reloc;
+
+  ResolveInfo* rsym = pLo16Reloc.parent().symInfo();
+
+  RelocationSet & relocs = m_PostponedRelocs[rsym];
+  for (RelocationSet::iterator it = relocs.begin(); it != relocs.end(); ++it)
+    (*it)->apply(*this);
+
+  m_PostponedRelocs.erase(rsym);
+
+  m_CurrentLo16Reloc = NULL;
 }
 
-static
-void helper_SetupRelDynForGOTEntry(MipsGOTEntry& got_entry,
-                                   Relocation& pReloc,
-                                   ResolveInfo* rsym,
-                                   MipsRelocator& pParent)
+bool MipsRelocator::isGpDisp(const Relocation& pReloc) const
 {
-  MipsGNULDBackend& ld_backend = pParent.getTarget();
-
-  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
-  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
-  rel_entry.targetRef() = *FragmentRef::Create(got_entry, 0);
-  rel_entry.setSymInfo(rsym);
+  return 0 == strcmp("_gp_disp", pReloc.symInfo()->name());
 }
 
-static
-MipsGOTEntry& helper_GetGOTEntry(Relocation& pReloc, MipsRelocator& pParent)
+bool MipsRelocator::isRel() const
+{
+  return config().targets().is32Bits();
+}
+
+bool MipsRelocator::isLocalReloc(ResolveInfo& pSym) const
+{
+  if (pSym.isUndef())
+    return false;
+
+  return pSym.isLocal() ||
+         !getTarget().isDynamicSymbol(pSym) ||
+         !pSym.isDyn();
+}
+
+Relocator::Address MipsRelocator::getGPAddress()
+{
+  return getTarget().getGOT().getGPAddr(getApplyingInput());
+}
+
+Relocator::Address MipsRelocator::getGP0()
+{
+  return getTarget().getGP0(getApplyingInput());
+}
+
+Fragment& MipsRelocator::getLocalGOTEntry(MipsRelocationInfo& pReloc,
+                                          Relocation::DWord entryValue)
 {
   // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  MipsGNULDBackend& ld_backend = pParent.getTarget();
-  MipsGOT& got = ld_backend.getGOT();
-  MipsGOTEntry* got_entry;
+  ResolveInfo* rsym = pReloc.parent().symInfo();
+  MipsGOT& got = getTarget().getGOT();
 
-  if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) {
-    // Local section symbols consume local got entries.
-    got_entry = got.consumeLocal();
-    if (got.isPrimaryGOTConsumed())
-      helper_SetupRelDynForGOTEntry(*got_entry, pReloc, NULL, pParent);
+  assert(isLocalReloc(*rsym) &&
+         "Attempt to get a global GOT entry for the local relocation");
+
+  Fragment* got_entry = got.lookupLocalEntry(rsym, entryValue);
+
+  // Found a mapping, then return the mapped entry immediately.
+  if (NULL != got_entry)
     return *got_entry;
-  }
 
-  got_entry = got.lookupEntry(rsym);
-  if (NULL != got_entry) {
-    // found a mapping, then return the mapped entry immediately
-    return *got_entry;
-  }
-
-  // not found
-  if (got.isLocal(rsym))
-    got_entry = got.consumeLocal();
-  else
-    got_entry = got.consumeGlobal();
-
-  got.recordEntry(rsym, got_entry);
-
-  // If we first get this GOT entry, we should initialize it.
-  if (!got.isLocal(rsym) || ResolveInfo::Section != rsym->type()) {
-    if (!got.isPrimaryGOTConsumed())
-      got_entry->setValue(pReloc.symValue());
-  }
+  // Not found.
+  got_entry = got.consumeLocal();
 
   if (got.isPrimaryGOTConsumed())
-    helper_SetupRelDynForGOTEntry(*got_entry, pReloc,
-                                  got.isLocal(rsym) ? NULL : rsym, pParent);
+    setupRelDynEntry(*FragmentRef::Create(*got_entry, 0), NULL);
+  else
+    got.setEntryValue(got_entry, entryValue);
+
+  got.recordLocalEntry(rsym, entryValue, got_entry);
 
   return *got_entry;
 }
 
-static
-Relocator::Address helper_GetGOTOffset(Relocation& pReloc,
-                                       MipsRelocator& pParent)
+Fragment& MipsRelocator::getGlobalGOTEntry(MipsRelocationInfo& pReloc)
 {
-  MipsGNULDBackend& ld_backend = pParent.getTarget();
-  MipsGOT& got = ld_backend.getGOT();
-  MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
-  return got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.parent().symInfo();
+  MipsGOT& got = getTarget().getGOT();
+
+  assert(!isLocalReloc(*rsym) &&
+         "Attempt to get a local GOT entry for the global relocation");
+
+  Fragment* got_entry = got.lookupGlobalEntry(rsym);
+
+  // Found a mapping, then return the mapped entry immediately.
+  if (NULL != got_entry)
+    return *got_entry;
+
+  // Not found.
+  got_entry = got.consumeGlobal();
+
+  if (got.isPrimaryGOTConsumed())
+    setupRelDynEntry(*FragmentRef::Create(*got_entry, 0), rsym);
+  else
+    got.setEntryValue(got_entry, pReloc.parent().symValue());
+
+  got.recordGlobalEntry(rsym, got_entry);
+
+  return *got_entry;
 }
 
-static
-int32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc)
+Relocator::Address MipsRelocator::getGOTOffset(MipsRelocationInfo& pReloc)
 {
-  assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 ||
-          pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) &&
-         pLoReloc.type() == llvm::ELF::R_MIPS_LO16 &&
-         "Incorrect type of relocation for AHL calculation");
+  ResolveInfo* rsym = pReloc.parent().symInfo();
+  MipsGOT& got = getTarget().getGOT();
 
-  // Note the addend is section symbol offset here
-  assert (pHiReloc.addend() == pLoReloc.addend());
+  if (isLocalReloc(*rsym)) {
+    uint64_t value = pReloc.S();
 
-  int32_t AHI = pHiReloc.target();
-  int32_t ALO = pLoReloc.target();
-  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) +
-                 pLoReloc.addend();
+    if (ResolveInfo::Section == rsym->type())
+      value += pReloc.A();
+
+    return got.getGPRelOffset(getApplyingInput(),
+                              getLocalGOTEntry(pReloc, value));
+  }
+  else {
+    return got.getGPRelOffset(getApplyingInput(), getGlobalGOTEntry(pReloc));
+  }
+}
+
+void MipsRelocator::createDynRel(MipsRelocationInfo& pReloc)
+{
+  Relocator::DWord A = pReloc.A();
+  Relocator::DWord S = pReloc.S();
+
+  ResolveInfo* rsym = pReloc.parent().symInfo();
+
+  if (isLocalReloc(*rsym)) {
+    setupRelDynEntry(pReloc.parent().targetRef(), NULL);
+    pReloc.result() = A + S;
+  }
+  else {
+    setupRelDynEntry(pReloc.parent().targetRef(), rsym);
+    // Don't add symbol value that will be resolved by the dynamic linker.
+    pReloc.result() = A;
+  }
+}
+
+uint64_t MipsRelocator::calcAHL(const MipsRelocationInfo& pHiReloc)
+{
+  assert(NULL != m_CurrentLo16Reloc &&
+         "There is no saved R_MIPS_LO16 relocation");
+
+  uint64_t AHI = pHiReloc.A() & 0xFFFF;
+  uint64_t ALO = m_CurrentLo16Reloc->A() & 0xFFFF;
+  uint64_t AHL = (AHI << 16) + int16_t(ALO);
+
   return AHL;
 }
 
-static
-void helper_DynRel(Relocation& pReloc, MipsRelocator& pParent)
+bool MipsRelocator::isN64ABI() const
 {
-  ResolveInfo* rsym = pReloc.symInfo();
-  MipsGNULDBackend& ld_backend = pParent.getTarget();
-  MipsGOT& got = ld_backend.getGOT();
+  return config().targets().is64Bits();
+}
 
-  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
+uint64_t MipsRelocator::getPLTAddress(ResolveInfo& rsym)
+{
+  assert((rsym.reserved() & MipsRelocator::ReservePLT) &&
+         "Symbol does not require a PLT entry");
 
-  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
-  rel_entry.targetRef() = pReloc.targetRef();
+  SymPLTMap::const_iterator it = m_SymPLTMap.find(&rsym);
 
-  Relocator::DWord A = pReloc.target() + pReloc.addend();
-  Relocator::DWord S = pReloc.symValue();
+  Fragment* plt;
 
-  if (got.isLocal(rsym)) {
-    rel_entry.setSymInfo(NULL);
-    pReloc.target() = A + S;
+  if (it != m_SymPLTMap.end()) {
+    plt = it->second.first;
   }
   else {
-    rel_entry.setSymInfo(rsym);
-    // Don't add symbol value that will be resolved by the dynamic linker
-    pReloc.target() = A;
+    plt = getTarget().getPLT().consume();
+
+    Fragment* got = getTarget().getGOTPLT().consume();
+    Relocation* rel = getTarget().getRelPLT().consumeEntry();
+
+    rel->setType(llvm::ELF::R_MIPS_JUMP_SLOT);
+    rel->targetRef().assign(*got);
+    rel->setSymInfo(&rsym);
+
+    m_SymPLTMap[&rsym] = PLTDescriptor(plt, got);
   }
+
+  return getTarget().getPLT().addr() + plt->getOffset();
+}
+
+//===----------------------------------------------------------------------===//
+// Mips32Relocator
+//===----------------------------------------------------------------------===//
+Mips32Relocator::Mips32Relocator(Mips32GNULDBackend& pParent,
+                                 const LinkerConfig& pConfig)
+  : MipsRelocator(pParent, pConfig)
+{}
+
+void Mips32Relocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym)
+{
+  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
+  relEntry.setType(llvm::ELF::R_MIPS_REL32);
+  relEntry.targetRef() = pFragRef;
+  relEntry.setSymInfo(pSym);
+}
+
+//===----------------------------------------------------------------------===//
+// Mips64Relocator
+//===----------------------------------------------------------------------===//
+Mips64Relocator::Mips64Relocator(Mips64GNULDBackend& pParent,
+                                 const LinkerConfig& pConfig)
+  : MipsRelocator(pParent, pConfig)
+{}
+
+void Mips64Relocator::setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym)
+{
+  Relocation::Type type = llvm::ELF::R_MIPS_REL32 |
+                          llvm::ELF::R_MIPS_64 << 8;
+  // FIXME (simon): Fix dynamic relocations.
+  type = llvm::ELF::R_MIPS_NONE;
+
+  Relocation& relEntry = *getTarget().getRelDyn().consumeEntry();
+  relEntry.setType(type);
+  relEntry.targetRef() = pFragRef;
+  relEntry.setSymInfo(pSym);
 }
 
 //=========================================//
@@ -470,35 +793,60 @@
 
 // R_MIPS_NONE and those unsupported/deprecated relocation type
 static
-MipsRelocator::Result none(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result none(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
   return MipsRelocator::OK;
 }
 
 // R_MIPS_32: S + A
 static
-MipsRelocator::Result abs32(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result abs32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
-  ResolveInfo* rsym = pReloc.symInfo();
+  ResolveInfo* rsym = pReloc.parent().symInfo();
 
-  Relocator::DWord A = pReloc.target() + pReloc.addend();
-  Relocator::DWord S = pReloc.symValue();
+  Relocator::DWord A = pReloc.A();
+  Relocator::DWord S = pReloc.S();
 
-  LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
+  LDSection& target_sect =
+    pReloc.parent().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;
+    pReloc.result() = S + A;
     return MipsRelocator::OK;
   }
 
   if (rsym->reserved() & MipsRelocator::ReserveRel) {
-    helper_DynRel(pReloc, pParent);
-
+    pParent.createDynRel(pReloc);
     return MipsRelocator::OK;
   }
 
-  pReloc.target() = (S + A);
+  pReloc.result() = S + A;
+
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_26:
+//   local   : ((A | ((P + 4) & 0x3F000000)) + S) >> 2
+//   external: (sign–extend(A) + S) >> 2
+static
+MipsRelocator::Result rel26(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  ResolveInfo* rsym = pReloc.parent().symInfo();
+
+  int32_t A = ((pReloc.parent().target() & 0x03FFFFFF) << 2);
+  int32_t P = pReloc.P();
+  int32_t S = rsym->reserved() & MipsRelocator::ReservePLT
+                  ? pParent.getPLTAddress(*rsym)
+                  : pReloc.S();
+
+  if (rsym->isLocal())
+    pReloc.result() = A | ((P + 4) & 0x3F000000);
+  else
+    pReloc.result() = mcld::signExtend<28>(A);
+
+  pReloc.result() = (pReloc.result() + S) >> 2;
 
   return MipsRelocator::OK;
 }
@@ -507,29 +855,23 @@
 //   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
 //   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
 static
-MipsRelocator::Result hi16(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result hi16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
-  Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
-  assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16");
+  uint64_t AHL = pParent.calcAHL(pReloc);
 
-  int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
-  int32_t res = 0;
-
-  pParent.setAHL(AHL);
-
-  if (helper_isGpDisp(pReloc)) {
-    int32_t P = pReloc.place();
-    int32_t GP = helper_GetGP(pParent);
-    res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
+  if (pParent.isGpDisp(pReloc.parent())) {
+    int32_t P = pReloc.P();
+    int32_t GP = pParent.getGPAddress();
+    pReloc.result() = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
   }
   else {
-    int32_t S = pReloc.symValue();
-    res = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
+    int32_t S = pReloc.S();
+    if (pParent.isN64ABI())
+      pReloc.result() = (pReloc.A() + S + 0x8000ull) >> 16;
+    else
+      pReloc.result() = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
   }
 
-  pReloc.target() &= 0xFFFF0000;
-  pReloc.target() |= (res & 0xFFFF);
-
   return MipsRelocator::OK;
 }
 
@@ -537,27 +879,45 @@
 //   local/external: AHL + S
 //   _gp_disp      : AHL + GP - P + 4
 static
-MipsRelocator::Result lo16(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result lo16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
-  int32_t res = 0;
+  // AHL is a combination of HI16 and LO16 addends. But R_MIPS_LO16
+  // uses low 16 bits of the AHL. That is why we do not need R_MIPS_HI16
+  // addend here.
+  int32_t AHL = (pReloc.A() & 0xFFFF);
 
-  if (helper_isGpDisp(pReloc)) {
-    int32_t P = pReloc.place();
-    int32_t GP = helper_GetGP(pParent);
-    int32_t AHL = pParent.getAHL();
-    res = AHL + GP - P + 4;
+  if (pParent.isGpDisp(pReloc.parent())) {
+    int32_t P = pReloc.P();
+    int32_t GP = pParent.getGPAddress();
+    pReloc.result() = AHL + GP - P + 4;
   }
   else {
-    int32_t S = pReloc.symValue();
-    // The previous AHL may be for other hi/lo pairs.
-    // We need to calcuate the lo part now.  It is easy.
-    // Remember to add the section offset to ALO.
-    int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend();
-    res = ALO + S;
+    int32_t S = pReloc.S();
+    pReloc.result() = AHL + S;
   }
 
-  pReloc.target() &= 0xFFFF0000;
-  pReloc.target() |= (res & 0xFFFF);
+  pParent.applyPostponedRelocations(pReloc);
+
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_GPREL16:
+//   external: sign–extend(A) + S - GP
+//   local   : sign–extend(A) + S + GP0 – GP
+static
+MipsRelocator::Result gprel16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  // Remember to add the section offset to A.
+  uint64_t A = pReloc.A();
+  uint64_t S = pReloc.S();
+  uint64_t GP0 = pParent.getGP0();
+  uint64_t GP = pParent.getGPAddress();
+
+  ResolveInfo* rsym = pReloc.parent().symInfo();
+  if (rsym->isLocal())
+    pReloc.result() = A + S + GP0 - GP;
+  else
+    pReloc.result() = A + S - GP;
 
   return MipsRelocator::OK;
 }
@@ -566,52 +926,35 @@
 //   local   : G (calculate AHL and put high 16 bit to GOT)
 //   external: G
 static
-MipsRelocator::Result got16(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result got16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
-  MipsGNULDBackend& ld_backend = pParent.getTarget();
-  MipsGOT& got = ld_backend.getGOT();
-  ResolveInfo* rsym = pReloc.symInfo();
-  Relocator::Address G = 0;
-
-  if (rsym->isLocal()) {
-    Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
-    assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16");
-
-    int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
-    int32_t S = pReloc.symValue();
-
-    pParent.setAHL(AHL);
-
+  if (pReloc.parent().symInfo()->isLocal()) {
+    int32_t AHL = pParent.calcAHL(pReloc);
+    int32_t S = pReloc.S();
     int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
-    MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
 
-    got_entry.setValue(res);
-    G = got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
+    MipsGOT& got = pParent.getTarget().getGOT();
+
+    Fragment& got_entry = pParent.getLocalGOTEntry(pReloc, res);
+
+    pReloc.result() = got.getGPRelOffset(pParent.getApplyingInput(), got_entry);
   }
   else {
-    G = helper_GetGOTOffset(pReloc, pParent);
+    pReloc.result() = pParent.getGOTOffset(pReloc);
   }
 
-  pReloc.target() &= 0xFFFF0000;
-  pReloc.target() |= (G & 0xFFFF);
-
   return MipsRelocator::OK;
 }
 
 // R_MIPS_GOTHI16:
 //   external: (G - (short)G) >> 16 + A
 static
-MipsRelocator::Result gothi16(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result gothi16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
-  int32_t res = 0;
+  Relocator::Address G = pParent.getGOTOffset(pReloc);
+  int32_t A = pReloc.A();
 
-  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
-  int32_t A = pReloc.target() + pReloc.addend();
-
-  res = (G - (int16_t)G) >> (16 + A);
-
-  pReloc.target() &= 0xFFFF0000;
-  pReloc.target() |= (res & 0xFFFF);
+  pReloc.result() = (G - (int16_t)G) >> (16 + A);
 
   return MipsRelocator::OK;
 }
@@ -619,41 +962,145 @@
 // R_MIPS_GOTLO16:
 //   external: G & 0xffff
 static
-MipsRelocator::Result gotlo16(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result gotlo16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
-  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
+  pReloc.result() = pParent.getGOTOffset(pReloc) & 0xffff;
 
-  pReloc.target() &= 0xFFFF0000;
-  pReloc.target() |= (G & 0xFFFF);
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_SUB:
+//   external/local: S - A
+static
+MipsRelocator::Result sub(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  uint64_t S = pReloc.S();
+  uint64_t A = pReloc.A();
+
+  pReloc.result() = S - A;
 
   return MipsRelocator::OK;
 }
 
 // R_MIPS_CALL16: G
 static
-MipsRelocator::Result call16(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result call16(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
-  Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
-
-  pReloc.target() &= 0xFFFF0000;
-  pReloc.target() |= (G & 0xFFFF);
+  pReloc.result() = pParent.getGOTOffset(pReloc);
 
   return MipsRelocator::OK;
 }
 
 // R_MIPS_GPREL32: A + S + GP0 - GP
 static
-MipsRelocator::Result gprel32(Relocation& pReloc, MipsRelocator& pParent)
+MipsRelocator::Result gprel32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
 {
   // Remember to add the section offset to A.
-  int32_t A = pReloc.target() + pReloc.addend();
-  int32_t S = pReloc.symValue();
-  int32_t GP = helper_GetGP(pParent);
+  uint64_t A = pReloc.A();
+  uint64_t S = pReloc.S();
+  uint64_t GP0 = pParent.getGP0();
+  uint64_t GP = pParent.getGPAddress();
 
-  // llvm does not emits SHT_MIPS_REGINFO section.
-  // Assume that GP0 is zero.
-  pReloc.target() = (A + S - GP) & 0xFFFFFFFF;
+  pReloc.result() = A + S + GP0 - GP;
 
   return MipsRelocator::OK;
 }
 
+// R_MIPS_64: S + A
+static
+MipsRelocator::Result abs64(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  // FIXME (simon): Consider to merge with abs32() or use the same function
+  // but with another mask size.
+  ResolveInfo* rsym = pReloc.parent().symInfo();
+
+  Relocator::DWord A = pReloc.A();
+  Relocator::DWord S = pReloc.S();
+
+  LDSection& target_sect =
+    pReloc.parent().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.result() = S + A;
+    return MipsRelocator::OK;
+  }
+
+  if (rsym->reserved() & MipsRelocator::ReserveRel) {
+    pParent.createDynRel(pReloc);
+    return MipsRelocator::OK;
+  }
+
+  pReloc.result() = S + A;
+
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_GOT_DISP / R_MIPS_GOT_PAGE: G
+static
+MipsRelocator::Result gotdisp(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  pReloc.result() = pParent.getGOTOffset(pReloc);
+
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_GOT_OFST:
+static
+MipsRelocator::Result gotoff(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  // FIXME (simon): Needs to be implemented.
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_JALR:
+static
+MipsRelocator::Result jalr(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_LA25_LUI
+static
+MipsRelocator::Result la25lui(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  int32_t S = pReloc.S();
+
+  pReloc.result() = (S + 0x8000) >> 16;
+
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_LA25_J
+static
+MipsRelocator::Result la25j(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  int32_t S = pReloc.S();
+
+  pReloc.result() = S >> 2;
+
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_LA25_ADD
+static
+MipsRelocator::Result la25add(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  pReloc.result() = pReloc.S();
+
+  return MipsRelocator::OK;
+}
+
+// R_MIPS_PC32:
+static
+MipsRelocator::Result pc32(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  return MipsRelocator::OK;
+}
+
+static
+MipsRelocator::Result unsupport(MipsRelocationInfo& pReloc, MipsRelocator& pParent)
+{
+  return MipsRelocator::Unsupport;
+}
diff --git a/lib/Target/Mips/MipsRelocator.h b/lib/Target/Mips/MipsRelocator.h
index 96e73e2..4e24329 100644
--- a/lib/Target/Mips/MipsRelocator.h
+++ b/lib/Target/Mips/MipsRelocator.h
@@ -12,12 +12,15 @@
 #include <gtest.h>
 #endif
 
+#include <llvm/ADT/DenseMapInfo.h>
 #include <mcld/LD/Relocator.h>
 #include <mcld/Support/GCFactory.h>
 #include "MipsLDBackend.h"
 
 namespace mcld {
 
+class MipsRelocationInfo;
+
 /** \class MipsRelocator
  *  \brief MipsRelocator creates and destroys the Mips relocations.
  */
@@ -28,7 +31,7 @@
     None          = 0,  // no reserved entry
     ReserveRel    = 1,  // reserve a dynamic relocation entry
     ReserveGot    = 2,  // reserve a GOT entry
-    ReserveGpDisp = 8   // reserve _gp_disp symbol
+    ReservePLT    = 4   // reserve a PLT entry
   };
 
 public:
@@ -40,7 +43,8 @@
   void scanRelocation(Relocation& pReloc,
                       IRBuilder& pBuilder,
                       Module& pModule,
-                      LDSection& pSection);
+                      LDSection& pSection,
+                      Input& pInput);
 
   /// initializeScan - do initialization before scan relocations in pInput
   /// @return - return true for initialization success
@@ -58,7 +62,7 @@
   /// @return - return true for finalization success
   bool finalizeApply(Input& pInput);
 
-  Result applyRelocation(Relocation& pRelocation);
+  Result applyRelocation(Relocation& pReloc);
 
   const Input& getApplyingInput() const
   { return *m_pApplyingInput; }
@@ -69,31 +73,124 @@
   const MipsGNULDBackend& getTarget() const
   { return m_Target; }
 
-  // Get last calculated AHL.
-  int32_t getAHL() const
-  { return m_AHL; }
+  /// postponeRelocation - save R_MIPS_LO16 paired relocations
+  /// like R_MISP_HI16 and R_MIPS_GOT16 for a future processing.
+  void postponeRelocation(Relocation& pReloc);
 
-  // Set last calculated AHL.
-  void setAHL(int32_t pAHL)
-  { m_AHL = pAHL; }
+  /// applyPostponedRelocations - apply all postponed relocations
+  /// paired with the R_MIPS_LO16 one.
+  void applyPostponedRelocations(MipsRelocationInfo& pLo16Reloc);
+
+  /// isGpDisp - return true if relocation is against _gp_disp symbol.
+  bool isGpDisp(const Relocation& pReloc) const;
+
+  /// getGPAddress - return address of _gp symbol.
+  Address getGPAddress();
+
+  /// getGP0 - the gp value used to create the relocatable objects
+  /// in the processing input.
+  Address getGP0();
+
+  /// getLocalGOTEntry - initialize and return a local GOT entry
+  /// for this relocation.
+  Fragment& getLocalGOTEntry(MipsRelocationInfo& pReloc,
+                             Relocation::DWord entryValue);
+
+  /// getGlobalGOTEntry - initialize and return a global GOT entry
+  /// for this relocation.
+  Fragment& getGlobalGOTEntry(MipsRelocationInfo& pReloc);
+
+  /// getGOTOffset - return offset of corresponded GOT entry.
+  Address getGOTOffset(MipsRelocationInfo& pReloc);
+
+  /// createDynRel - initialize dynamic relocation for the relocation.
+  void createDynRel(MipsRelocationInfo& pReloc);
+
+  /// getPLTOffset - initialize PLT-related entries for the symbol
+  /// @return - return address of PLT entry
+  uint64_t getPLTAddress(ResolveInfo& rsym);
+
+  /// calcAHL - calculate combined addend used
+  /// by R_MIPS_HI16 and R_MIPS_GOT16 relocations.
+  uint64_t calcAHL(const MipsRelocationInfo& pHiReloc);
+
+  /// isN64ABI - check current ABI
+  bool isN64ABI() const;
 
   const char* getName(Relocation::Type pType) const;
 
   Size getSize(Relocation::Type pType) const;
 
-private:
-  void scanLocalReloc(Relocation& pReloc,
-                      IRBuilder& pBuilder,
-                      const LDSection& pSection);
+protected:
+  /// setupRelDynEntry - create dynamic relocation entry.
+  virtual void setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym) = 0;
 
-  void scanGlobalReloc(Relocation& pReloc,
-                       IRBuilder& pBuilder,
-                       const LDSection& pSection);
+  /// isLocalReloc - handle relocation as a local symbol
+  bool isLocalReloc(ResolveInfo& pSym) const;
+
+private:
+  typedef std::pair<Fragment*, Fragment*> PLTDescriptor;
+  typedef llvm::DenseMap<const ResolveInfo*, PLTDescriptor> SymPLTMap;
+  typedef llvm::DenseSet<Relocation*> RelocationSet;
+  typedef llvm::DenseMap<const ResolveInfo*, RelocationSet> SymRelocSetMap;
 
 private:
   MipsGNULDBackend& m_Target;
+  SymPLTMap m_SymPLTMap;
   Input* m_pApplyingInput;
-  int32_t m_AHL;
+  SymRelocSetMap m_PostponedRelocs;
+  MipsRelocationInfo* m_CurrentLo16Reloc;
+
+private:
+  void scanLocalReloc(MipsRelocationInfo& pReloc,
+                      IRBuilder& pBuilder,
+                      const LDSection& pSection);
+
+  void scanGlobalReloc(MipsRelocationInfo& pReloc,
+                       IRBuilder& pBuilder,
+                       const LDSection& pSection);
+
+  /// isPostponed - relocation applying needs to be postponed.
+  bool isPostponed(const Relocation& pReloc) const;
+
+  /// 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);
+
+  /// 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(IRBuilder& pBuilder,
+                                     const ResolveInfo& pSym);
+
+  /// isRel - returns true if REL relocation record format is expected
+  bool isRel() const;
+};
+
+/** \class Mips32Relocator
+ *  \brief Mips32Relocator creates and destroys the Mips 32-bit relocations.
+ */
+class Mips32Relocator : public MipsRelocator
+{
+public:
+  Mips32Relocator(Mips32GNULDBackend& pParent, const LinkerConfig& pConfig);
+
+private:
+  // MipsRelocator
+  void setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym);
+};
+
+/** \class Mips64Relocator
+ *  \brief Mips64Relocator creates and destroys the Mips 64-bit relocations.
+ */
+class Mips64Relocator : public MipsRelocator
+{
+public:
+  Mips64Relocator(Mips64GNULDBackend& pParent, const LinkerConfig& pConfig);
+
+private:
+  // MipsRelocator
+  void setupRelDynEntry(FragmentRef& pFragRef, ResolveInfo* pSym);
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 03db780..2e57868 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -7,23 +7,24 @@
 //
 //===----------------------------------------------------------------------===//
 #include "MipsTargetMachine.h"
-
 #include "Mips.h"
-#include <mcld/Target/TargetMachine.h>
 #include <mcld/Support/TargetRegistry.h>
 
+typedef mcld::RegisterTargetMachine<mcld::MipsBaseTargetMachine> RegMipsTarget;
+
 extern "C" void MCLDInitializeMipsLDTarget() {
-  // Register createTargetMachine function pointer to mcld::Target
-  mcld::RegisterTargetMachine<mcld::MipsBaseTargetMachine>
-        X(mcld::TheMipselTarget);
+  RegMipsTarget X1(mcld::TheMipselTarget);
+  RegMipsTarget X2(mcld::TheMips64elTarget);
 }
 
-mcld::MipsBaseTargetMachine::MipsBaseTargetMachine(llvm::TargetMachine& pPM,
-                                                   const mcld::Target &pTarget,
-                                                   const std::string& pTriple)
-  : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
-}
+using namespace mcld;
 
-mcld::MipsBaseTargetMachine::~MipsBaseTargetMachine()
-{
+//===----------------------------------------------------------------------===//
+// MipsBaseTargetMachine
+//===----------------------------------------------------------------------===//
+MipsBaseTargetMachine::MipsBaseTargetMachine(llvm::TargetMachine& pPM,
+                                             const llvm::Target &pLLVMTarget,
+                                             const mcld::Target &pMCLDTarget,
+                                             const std::string& pTriple)
+  : MCLDTargetMachine(pPM, pLLVMTarget, pMCLDTarget, pTriple) {
 }
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index 6cfae73..964a6d1 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -9,8 +9,7 @@
 #ifndef MIPS_TARGET_MACHINE_H
 #define MIPS_TARGET_MACHINE_H
 
-#include "Mips.h"
-#include <mcld/Target/TargetMachine.h>
+#include <mcld/CodeGen/TargetMachine.h>
 
 namespace mcld {
 
@@ -18,10 +17,9 @@
 {
 public:
   MipsBaseTargetMachine(llvm::TargetMachine &pTM,
-                        const mcld::Target &pTarget,
+                        const llvm::Target &pLLVMTarget,
+                        const mcld::Target &pMCLDTarget,
                         const std::string &pTriple);
-
-  virtual ~MipsBaseTargetMachine();
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
index 3991c45..4ae7a61 100644
--- a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
+++ b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
@@ -6,16 +6,19 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Target/TargetMachine.h"
-#include "mcld/Support/TargetRegistry.h"
+#include <mcld/Support/Target.h>
+#include <mcld/Support/TargetRegistry.h>
 
 namespace mcld {
 
 mcld::Target TheMipselTarget;
+mcld::Target TheMips64elTarget;
 
 extern "C" void MCLDInitializeMipsLDTargetInfo() {
-  // register into mcld::TargetRegistry
-  mcld::RegisterTarget X(TheMipselTarget, "mipsel");
+  mcld::RegisterTarget<llvm::Triple::mipsel>
+                       X1(TheMipselTarget, "mipsel");
+  mcld::RegisterTarget<llvm::Triple::mips64el>
+                       X2(TheMips64elTarget, "mips64el");
 }
 
 } // namespace of mcld
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
index 603350b..07670a3 100644
--- a/lib/Target/OutputRelocSection.cpp
+++ b/lib/Target/OutputRelocSection.cpp
@@ -34,6 +34,13 @@
 {
 }
 
+Relocation* OutputRelocSection::create()
+{
+  Relocation* reloc = Relocation::Create();
+  m_pRelocData->append(*reloc);
+  return reloc;
+}
+
 void OutputRelocSection::reserveEntry(size_t pNum)
 {
   for(size_t i=0; i<pNum; i++)
diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp
deleted file mode 100644
index ba69e03..0000000
--- a/lib/Target/Target.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- Target.cpp ---------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/TargetRegistry.h>
-#include <mcld/Target/TargetMachine.h>
-#include <llvm/Support/TargetRegistry.h>
-#include <llvm/Target/TargetMachine.h>
-
-using namespace llvm;
-
-mcld::Target::Target()
-  : TargetMachineCtorFn(NULL),
-    MCLinkerCtorFn(NULL),
-    TargetLDBackendCtorFn(NULL),
-    DiagnosticLineInfoCtorFn(NULL),
-    m_pT(NULL)
-{
-}
-
diff --git a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
index 3c02314..8e3a7c0 100644
--- a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
+++ b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Target/TargetMachine.h"
-#include "mcld/Support/TargetRegistry.h"
+#include <mcld/Support/Target.h>
+#include <mcld/Support/TargetRegistry.h>
 
 namespace mcld {
 
@@ -16,8 +16,10 @@
 
 extern "C" void MCLDInitializeX86LDTargetInfo() {
   // register into mcld::TargetRegistry
-  mcld::RegisterTarget X(TheX86_32Target, "x86");
-  mcld::RegisterTarget Y(TheX86_64Target, "x86-64");
+  mcld::RegisterTarget<llvm::Triple::x86>
+                       X(TheX86_32Target, "x86");
+  mcld::RegisterTarget<llvm::Triple::x86_64>
+                       Y(TheX86_64Target, "x86-64");
 }
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h
index 0f7d65d..5927f44 100644
--- a/lib/Target/X86/X86.h
+++ b/lib/Target/X86/X86.h
@@ -6,12 +6,17 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_X86_H
-#define MCLD_X86_H
+#ifndef MCLD_TARGET_X86_H
+#define MCLD_TARGET_X86_H
 #include <string>
-#include "mcld/Target/TargetMachine.h"
+
+namespace llvm {
+class Target;
+} // namespace of llvm
 
 namespace mcld {
+
+class Target;
 class TargetLDBackend;
 
 extern mcld::Target TheX86_32Target;
diff --git a/lib/Target/X86/X86Diagnostic.cpp b/lib/Target/X86/X86Diagnostic.cpp
index 9287ca7..9dab719 100644
--- a/lib/Target/X86/X86Diagnostic.cpp
+++ b/lib/Target/X86/X86Diagnostic.cpp
@@ -6,21 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/ADT/Triple.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/LD/DWARFLineInfo.h>
 #include "X86.h"
 
 using namespace mcld;
 
-//===----------------------------------------------------------------------===//
-// X86Diagnostic
-
-
 namespace mcld {
 //===----------------------------------------------------------------------===//
 // createX86Diagnostic - the help function to create corresponding X86Diagnostic
-//
+//===----------------------------------------------------------------------===//
 DiagnosticLineInfo* createX86DiagLineInfo(const mcld::Target& pTarget,
                                           const std::string &pTriple)
 {
@@ -29,8 +24,9 @@
 
 } // namespace of mcld
 
-//==========================
+//===----------------------------------------------------------------------===//
 // InitializeX86Diagnostic
+//===----------------------------------------------------------------------===//
 extern "C" void MCLDInitializeX86DiagnosticLineInfo() {
   // Register the linker frontend
   mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheX86_32Target, createX86DiagLineInfo);
diff --git a/lib/Target/X86/X86ELFMCLinker.cpp b/lib/Target/X86/X86ELFMCLinker.cpp
index 868d61c..a57fe37 100644
--- a/lib/Target/X86/X86ELFMCLinker.cpp
+++ b/lib/Target/X86/X86ELFMCLinker.cpp
@@ -7,14 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 #include "X86ELFMCLinker.h"
-#include <mcld/LinkerConfig.h>
 
 using namespace mcld;
 
 X86ELFMCLinker::X86ELFMCLinker(LinkerConfig& pConfig,
                                mcld::Module& pModule,
-                               MemoryArea& pOutput)
-  : ELFMCLinker(pConfig, pModule, pOutput) {
+                               FileHandle& pFileHandle)
+  : ELFMCLinker(pConfig, pModule, pFileHandle) {
 }
 
 X86ELFMCLinker::~X86ELFMCLinker()
diff --git a/lib/Target/X86/X86ELFMCLinker.h b/lib/Target/X86/X86ELFMCLinker.h
index 173f7dc..4b64d28 100644
--- a/lib/Target/X86/X86ELFMCLinker.h
+++ b/lib/Target/X86/X86ELFMCLinker.h
@@ -16,7 +16,7 @@
 namespace mcld {
 
 class Module;
-class MemoryArea;
+class FileHandle;
 
 /** \class X86ELFMCLinker
  *  \brief X86ELFMCLinker sets up the environment for linking.
@@ -28,7 +28,7 @@
 public:
   X86ELFMCLinker(LinkerConfig& pConfig,
                  mcld::Module& pModule,
-                 MemoryArea& pOutput);
+                 FileHandle& pFileHandle);
 
   ~X86ELFMCLinker();
 };
diff --git a/lib/Target/X86/X86Emulation.cpp b/lib/Target/X86/X86Emulation.cpp
index 99e15da..d91d46d 100644
--- a/lib/Target/X86/X86Emulation.cpp
+++ b/lib/Target/X86/X86Emulation.cpp
@@ -22,10 +22,10 @@
   // set up bitclass and endian
   pConfig.targets().setEndian(TargetOptions::Little);
   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) {
+  llvm::Triple::ArchType arch = pConfig.targets().triple().getArch();
+  assert (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64);
+  if (arch == llvm::Triple::x86 ||
+      pConfig.targets().triple().getEnvironment() == llvm::Triple::GNUX32) {
     bitclass = 32;
   }
   else {
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
index b77cfd3..bac4bee 100644
--- a/lib/Target/X86/X86GOT.cpp
+++ b/lib/Target/X86/X86GOT.cpp
@@ -19,7 +19,7 @@
 // X86_32GOT
 //===----------------------------------------------------------------------===//
 X86_32GOT::X86_32GOT(LDSection& pSection)
-  : GOT(pSection), m_pLast(NULL)
+  : GOT(pSection)
 {
 }
 
@@ -27,23 +27,9 @@
 {
 }
 
-void X86_32GOT::reserve(size_t pNum)
+X86_32GOTEntry* X86_32GOT::create()
 {
-  for (size_t i = 0; i < pNum; i++) {
-    new X86_32GOTEntry(0, m_SectionData);
-  }
-}
-
-X86_32GOTEntry* X86_32GOT::consume()
-{
-  if (NULL == m_pLast) {
-    assert(!empty() && "Consume empty GOT entry!");
-    m_pLast = llvm::cast<X86_32GOTEntry>(&m_SectionData->front());
-    return m_pLast;
-  }
-
-  m_pLast = llvm::cast<X86_32GOTEntry>(m_pLast->getNextNode());
-  return m_pLast;
+  return new X86_32GOTEntry(0, m_SectionData);
 }
 
 //===----------------------------------------------------------------------===//
@@ -58,22 +44,8 @@
 {
 }
 
-void X86_64GOT::reserve(size_t pNum)
+X86_64GOTEntry* X86_64GOT::create()
 {
-  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;
+  return new X86_64GOTEntry(0, m_SectionData);
 }
 
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
index df557f3..67c3163 100644
--- a/lib/Target/X86/X86GOT.h
+++ b/lib/Target/X86/X86GOT.h
@@ -41,12 +41,7 @@
 
   ~X86_32GOT();
 
-  void reserve(size_t pNum = 1);
-
-  X86_32GOTEntry* consume();
-
-private:
-  X86_32GOTEntry* m_pLast; ///< the last consumed entry
+  X86_32GOTEntry* create();
 };
 
 /** \class X86_64GOTEntry
@@ -71,9 +66,7 @@
 
   ~X86_64GOT();
 
-  void reserve(size_t pNum = 1);
-
-  X86_64GOTEntry* consume();
+  X86_64GOTEntry* create();
 
 private:
   X86_64GOTEntry* m_pLast; ///< the last consumed entry
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index 961e0dc..7baa5cb 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -23,13 +23,9 @@
 X86_32GOTPLT::X86_32GOTPLT(LDSection& pSection)
   : X86_32GOT(pSection)
 {
-  // Create GOT0 entries
-  reserve(X86GOTPLT0Num);
-
-  // Skip GOT0 entries
-  for (size_t i = 0; i < X86GOTPLT0Num; ++i) {
-    consume();
-  }
+  // create GOT0 entries
+  for (size_t i = 0; i < X86GOTPLT0Num; ++i)
+    create();
 }
 
 X86_32GOTPLT::~X86_32GOTPLT()
@@ -67,13 +63,8 @@
 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();
-  }
+  for (size_t i = 0; i < X86GOTPLT0Num; ++i)
+    create();
 }
 
 X86_64GOTPLT::~X86_64GOTPLT()
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index 87c1192..04e858c 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -12,18 +12,19 @@
 #include "X86Relocator.h"
 #include "X86GNUInfo.h"
 
+#include <llvm/ADT/StringRef.h>
 #include <llvm/ADT/Triple.h>
 #include <llvm/Support/Casting.h>
 
 #include <mcld/LinkerConfig.h>
 #include <mcld/IRBuilder.h>
+#include <mcld/LD/ELFFileFormat.h>
 #include <mcld/Fragment/FillFragment.h>
 #include <mcld/Fragment/RegionFragment.h>
-#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/Object/ObjectBuilder.h>
+#include <llvm/Support/Dwarf.h>
 
 #include <cstring>
 
@@ -44,13 +45,13 @@
     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) {
+  llvm::Triple::ArchType arch = pConfig.targets().triple().getArch();
+  assert (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64);
+  if (arch == llvm::Triple::x86 ||
+      pConfig.targets().triple().getEnvironment() == llvm::Triple::GNUX32) {
     m_RelEntrySize = 8;
     m_RelaEntrySize = 12;
-    if (arch == Triple::x86)
+    if (arch == llvm::Triple::x86)
       m_PointerRel = llvm::ELF::R_386_32;
     else
       m_PointerRel = llvm::ELF::R_X86_64_32;
@@ -105,6 +106,9 @@
       setRelPLTSize();
     }
   }
+
+  if (config().options().genUnwindInfo())
+    addEhFrameForPLT(pBuilder.getModule());
 }
 
 void X86GNULDBackend::doPostLayout(Module& pModule,
@@ -168,10 +172,8 @@
   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();
+  if (FileFormat->hasPLT() && (&pSection == &(FileFormat->getPLT()))) {
+    unsigned char* buffer = pRegion.begin();
 
     m_pPLT->applyPLT0();
     m_pPLT->applyPLT1();
@@ -192,15 +194,13 @@
       ++it;
     }
   }
-
-  else if (&pSection == &(FileFormat->getGOT())) {
+  else if (FileFormat->hasGOT() && (&pSection == &(FileFormat->getGOT()))) {
     RegionSize += emitGOTSectionData(pRegion);
   }
-
-  else if (&pSection == &(FileFormat->getGOTPLT())) {
+  else if (FileFormat->hasGOTPLT() &&
+           (&pSection == &(FileFormat->getGOTPLT()))) {
     RegionSize += emitGOTPLTSectionData(pRegion, FileFormat);
   }
-
   else {
     fatal(diag::unrecognized_output_sectoin)
             << pSection.name()
@@ -250,19 +250,19 @@
 {
   const ELFFileFormat* file_format = getOutputFormat();
 
-  if (&pSectHdr == &file_format->getGOT()) {
+  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
     if (config().options().hasNow())
       return SHO_RELRO;
     return SHO_RELRO_LAST;
   }
 
-  if (&pSectHdr == &file_format->getGOTPLT()) {
+  if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT())) {
     if (config().options().hasNow())
       return SHO_RELRO;
     return SHO_NON_RELRO_FIRST;
   }
 
-  if (&pSectHdr == &file_format->getPLT())
+  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
     return SHO_PLT;
 
   return SHO_UNDEFINED;
@@ -286,6 +286,51 @@
   }
 }
 
+void X86GNULDBackend::addEhFrameForPLT(Module& pModule)
+{
+  LDSection* plt_sect = pModule.getSection(".plt");
+  if (!plt_sect || plt_sect->size() == 0u)
+    return;
+
+  LDSection* eh_sect = pModule.getSection(".eh_frame");
+  if (!eh_sect || !eh_sect->hasEhFrame())
+    return;
+
+  EhFrame* eh_frame = eh_sect->getEhFrame();
+  SectionData::FragmentListType& frag_list =
+      eh_frame->getSectionData()->getFragmentList();
+  llvm::StringRef cie_region = createCIERegionForPLT();
+  llvm::StringRef fde_region = createFDERegionForPLT();
+  EhFrame::CIE* cie = new EhFrame::GeneratedCIE(cie_region);
+  EhFrame::FDE* fde = new EhFrame::GeneratedFDE(fde_region, *cie);
+  // Augmentation data only contains FDE encoding.
+  uint8_t aug_data = (uint8_t)(llvm::dwarf::DW_EH_PE_pcrel |
+                               llvm::dwarf::DW_EH_PE_sdata4);
+  cie->setFDEEncode(aug_data);
+  cie->setAugmentationData(std::string(1, aug_data));
+
+  EhFrame::cie_iterator i = eh_frame->cie_begin();
+  for (EhFrame::cie_iterator e = eh_frame->cie_end(); i != e; ++i) {
+    EhFrame::CIE& exist_cie = **i;
+    if (exist_cie == *cie) {
+      // Insert the FDE fragment
+      SectionData::iterator cur_iter(exist_cie);
+      frag_list.insertAfter(cur_iter, fde);
+      fde->setCIE(exist_cie);
+
+      // Cleanup the CIE we created
+      cie->clearFDEs();
+      delete cie;
+      break;
+    }
+  }
+  if (i == eh_frame->cie_end()) {
+    // Newly insert
+    eh_frame->addCIE(*cie);
+    eh_frame->addFDE(*fde);
+  }
+}
+
 /// finalizeSymbol - finalize the symbol value
 bool X86GNULDBackend::finalizeTargetSymbols()
 {
@@ -335,6 +380,7 @@
 
     // initialize .plt
     LDSection& plt = file_format->getPLT();
+    plt.setAlign(16u);
     m_pPLT = new X86_32PLT(plt,
 			   *m_pGOTPLT,
 			   config());
@@ -375,6 +421,59 @@
   return *m_pGOTPLT;
 }
 
+llvm::StringRef X86_32GNULDBackend::createCIERegionForPLT()
+{
+  using namespace llvm::dwarf;
+  static const uint8_t data[4+4+16] = {
+    0x14, 0, 0, 0, // length
+    0, 0, 0, 0, // ID
+    1,  // version
+    'z', 'R', '\0', // augmentation string
+    1,  // code alignment factor
+    0x7c, // data alignment factor
+    8,  // return address column
+    1,  // augmentation data size
+    DW_EH_PE_pcrel | DW_EH_PE_sdata4, // FDE encoding
+    DW_CFA_def_cfa, 4, 4,
+    DW_CFA_offset + 8, 1,
+    DW_CFA_nop,
+    DW_CFA_nop
+  };
+  return llvm::StringRef((const char*)data, 4+4+16);
+}
+
+llvm::StringRef X86_32GNULDBackend::createFDERegionForPLT()
+{
+  using namespace llvm::dwarf;
+  static const uint8_t data[4+4+32] = {
+    0x24, 0, 0, 0,  // length
+    0, 0, 0, 0,   // offset to CIE
+    0, 0, 0, 0,   // offset to PLT
+    0, 0, 0, 0,   // size of PLT
+    0,            // augmentation data size
+    DW_CFA_def_cfa_offset, 8,
+    DW_CFA_advance_loc + 6,
+    DW_CFA_def_cfa_offset, 12,
+    DW_CFA_advance_loc + 10,
+    DW_CFA_def_cfa_expression,
+    11,
+    DW_OP_breg4, 4,
+    DW_OP_breg8, 0,
+    DW_OP_lit15,
+    DW_OP_and,
+    DW_OP_lit11,
+    DW_OP_ge,
+    DW_OP_lit2,
+    DW_OP_shl,
+    DW_OP_plus,
+    DW_CFA_nop,
+    DW_CFA_nop,
+    DW_CFA_nop,
+    DW_CFA_nop
+  };
+  return llvm::StringRef((const char*)data, 4+4+32);
+}
+
 void X86_32GNULDBackend::setRelDynSize()
 {
   ELFFileFormat* file_format = getOutputFormat();
@@ -408,7 +507,7 @@
 {
   assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
 
-  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
 
   X86_32GOTEntry* got = 0;
   unsigned int EntrySize = X86_32GOTEntry::EntrySize;
@@ -431,7 +530,7 @@
   m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
   m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
 
-  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.begin());
 
   X86_32GOTEntry* got = 0;
   unsigned int EntrySize = X86_32GOTEntry::EntrySize;
@@ -492,6 +591,59 @@
   return *m_pGOTPLT;
 }
 
+llvm::StringRef X86_64GNULDBackend::createCIERegionForPLT()
+{
+  using namespace llvm::dwarf;
+  static const uint8_t data[4+4+16] = {
+    0x14, 0, 0, 0,  // length
+    0, 0, 0, 0,   // ID
+    1,          // CIE version
+    'z', 'R', '\0', // augmentation string
+    1,          // code alignment factor
+    0x78,       // data alignment factor
+    16,         // return address column
+    1,          // augmentation data size
+    DW_EH_PE_pcrel | DW_EH_PE_sdata4, // FDE encoding
+    DW_CFA_def_cfa, 7, 8,
+    DW_CFA_offset + 16, 1,
+    DW_CFA_nop,
+    DW_CFA_nop
+  };
+  return llvm::StringRef((const char*)data, 4+4+16);
+}
+
+llvm::StringRef X86_64GNULDBackend::createFDERegionForPLT()
+{
+  using namespace llvm::dwarf;
+  static const uint8_t data[4+4+32] = {
+    0x24, 0, 0, 0,  // length
+    0, 0, 0, 0,   // ID
+    0, 0, 0, 0,   // offset to PLT
+    0, 0, 0, 0,   // size of PLT
+    0,            // augmentation data size
+    DW_CFA_def_cfa_offset, 16,
+    DW_CFA_advance_loc + 6,
+    DW_CFA_def_cfa_offset, 24,
+    DW_CFA_advance_loc + 10,
+    DW_CFA_def_cfa_expression,
+    11,
+    DW_OP_breg7, 8,
+    DW_OP_breg16, 0,
+    DW_OP_lit15,
+    DW_OP_and,
+    DW_OP_lit11,
+    DW_OP_ge,
+    DW_OP_lit3,
+    DW_OP_shl,
+    DW_OP_plus,
+    DW_CFA_nop,
+    DW_CFA_nop,
+    DW_CFA_nop,
+    DW_CFA_nop
+  };
+  return llvm::StringRef((const char*)data, 4+4+32);
+}
+
 void X86_64GNULDBackend::setRelDynSize()
 {
   ELFFileFormat* file_format = getOutputFormat();
@@ -521,6 +673,7 @@
 
     // initialize .plt
     LDSection& plt = file_format->getPLT();
+    plt.setAlign(16u);
     m_pPLT = new X86_64PLT(plt,
 			   *m_pGOTPLT,
 			   config());
@@ -556,7 +709,7 @@
 {
   assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!");
 
-  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer());
+  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
 
   X86_64GOTEntry* got = 0;
   unsigned int EntrySize = X86_64GOTEntry::EntrySize;
@@ -579,7 +732,7 @@
   m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
   m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
 
-  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer());
+  uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.begin());
 
   X86_64GOTEntry* got = 0;
   unsigned int EntrySize = X86_64GOTEntry::EntrySize;
@@ -600,8 +753,7 @@
 //===----------------------------------------------------------------------===//
 /// createX86LDBackend - the help funtion to create corresponding X86LDBackend
 ///
-TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget,
-                                    const LinkerConfig& pConfig)
+TargetLDBackend* createX86LDBackend(const LinkerConfig& pConfig)
 {
   if (pConfig.targets().triple().isOSDarwin()) {
     assert(0 && "MachO linker is not supported yet");
@@ -619,11 +771,11 @@
                                createX86COFFObjectWriter);
     **/
   }
-  Triple::ArchType arch = pConfig.targets().triple().getArch();
-  if (arch == Triple::x86)
+  llvm::Triple::ArchType arch = pConfig.targets().triple().getArch();
+  if (arch == llvm::Triple::x86)
     return new X86_32GNULDBackend(pConfig,
 				  new X86_32GNUInfo(pConfig.targets().triple()));
-  assert (arch == Triple::x86_64);
+  assert (arch == llvm::Triple::x86_64);
   return new X86_64GNULDBackend(pConfig,
 				new X86_64GNUInfo(pConfig.targets().triple()));
 }
diff --git a/lib/Target/X86/X86LDBackend.h b/lib/Target/X86/X86LDBackend.h
index a3e8635..4ef5311 100644
--- a/lib/Target/X86/X86LDBackend.h
+++ b/lib/Target/X86/X86LDBackend.h
@@ -130,6 +130,10 @@
   virtual void setRelDynSize() = 0;
   virtual void setRelPLTSize() = 0;
 
+  void addEhFrameForPLT(Module& pModule);
+  virtual llvm::StringRef createCIERegionForPLT() = 0;
+  virtual llvm::StringRef createFDERegionForPLT() = 0;
+
 protected:
   Relocator* m_pRelocator;
   X86PLT* m_pPLT;
@@ -183,6 +187,9 @@
   void setRelDynSize();
   void setRelPLTSize();
 
+  llvm::StringRef createCIERegionForPLT();
+  llvm::StringRef createFDERegionForPLT();
+
 private:
   X86_32GOT* m_pGOT;
   X86_32GOTPLT* m_pGOTPLT;
@@ -223,6 +230,9 @@
   void setRelDynSize();
   void setRelPLTSize();
 
+  llvm::StringRef createCIERegionForPLT();
+  llvm::StringRef createFDERegionForPLT();
+
 private:
   X86_64GOT* m_pGOT;
   X86_64GOTPLT* m_pGOTPLT;
diff --git a/lib/Target/X86/X86MCLinker.cpp b/lib/Target/X86/X86MCLinker.cpp
index bad20a9..46d7bb5 100644
--- a/lib/Target/X86/X86MCLinker.cpp
+++ b/lib/Target/X86/X86MCLinker.cpp
@@ -22,9 +22,9 @@
 MCLinker* createX86MCLinker(const std::string &pTriple,
                             LinkerConfig& pConfig,
                             mcld::Module& pModule,
-                            MemoryArea& pOutput)
+                            FileHandle& pFileHandle)
 {
-  Triple theTriple(pTriple);
+  llvm::Triple theTriple(pTriple);
   if (theTriple.isOSDarwin()) {
     assert(0 && "MachO linker has not supported yet");
     return NULL;
@@ -34,7 +34,7 @@
     return NULL;
   }
 
-  return new X86ELFMCLinker(pConfig, pModule, pOutput);
+  return new X86ELFMCLinker(pConfig, pModule, pFileHandle);
 }
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index 669a047..d73693b 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -90,9 +90,7 @@
     m_PLT1Size = sizeof (x86_64_plt1);
     // create PLT0
     new X86_64PLT0(*m_SectionData);
-    m_Last = m_SectionData->begin();
   }
-  m_Last = m_SectionData->begin();
 }
 
 X86PLT::~X86PLT()
@@ -128,29 +126,12 @@
   return (m_SectionData->size() > 1);
 }
 
-void X86PLT::reserveEntry(size_t pNum)
+PLTEntryBase* X86PLT::create()
 {
-  PLTEntryBase* plt1_entry = NULL;
-
-  for (size_t i = 0; i < pNum; ++i) {
-
-    if (LinkerConfig::DynObj == m_Config.codeGenType())
-      plt1_entry = new X86_32DynPLT1(*m_SectionData);
-    else
-      plt1_entry = new X86_32ExecPLT1(*m_SectionData);
-
-    if (NULL == plt1_entry)
-      fatal(diag::fail_allocate_memory_plt);
-  }
-}
-
-PLTEntryBase* X86PLT::consume()
-{
-  // This will skip PLT0.
-  ++m_Last;
-  assert(m_Last != m_SectionData->end() &&
-         "The number of PLT Entries and ResolveInfo doesn't match");
-  return llvm::cast<PLTEntryBase>(&(*m_Last));
+  if (LinkerConfig::DynObj == m_Config.codeGenType())
+    return new X86_32DynPLT1(*m_SectionData);
+  else
+    return new X86_32ExecPLT1(*m_SectionData);
 }
 
 PLTEntryBase* X86PLT::getPLT0() const
diff --git a/lib/Target/X86/X86PLT.h b/lib/Target/X86/X86PLT.h
index 2f4176c..2578d67 100644
--- a/lib/Target/X86/X86PLT.h
+++ b/lib/Target/X86/X86PLT.h
@@ -119,9 +119,7 @@
   // hasPLT1 - return if this PLT has any PLT1 entry
   bool hasPLT1() const;
 
-  void reserveEntry(size_t pNum = 1) ;
-
-  PLTEntryBase* consume();
+  PLTEntryBase* create();
 
   virtual void applyPLT0() = 0;
 
@@ -134,9 +132,6 @@
   PLTEntryBase* getPLT0() const;
 
 protected:
-  // the last consumed entry.
-  SectionData::iterator m_Last;
-
   const uint8_t *m_PLT0;
   const uint8_t *m_PLT1;
   unsigned int m_PLT0Size;
diff --git a/lib/Target/X86/X86RelocationFunctions.h b/lib/Target/X86/X86RelocationFunctions.h
index 9209242..a4568bb 100644
--- a/lib/Target/X86/X86RelocationFunctions.h
+++ b/lib/Target/X86/X86RelocationFunctions.h
@@ -43,11 +43,11 @@
   { &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  },  \
+  { &tls_ie,            15, "R_386_TLS_IE",           32 },  \
+  { &tls_gotie,         16, "R_386_TLS_GOTIE",        32 },  \
+  { &tls_le,            17, "R_386_TLS_LE",           32 },  \
+  { &tls_gd,            18, "R_386_TLS_GD",           32 },  \
+  { &tls_ldm,           19, "R_386_TLS_LDM",          32 },  \
   { &abs,               20, "R_386_16",               16 },  \
   { &rel,               21, "R_386_PC16",             16 },  \
   { &abs,               22, "R_386_8",                8  },  \
@@ -60,7 +60,7 @@
   { &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  },  \
+  { &tls_ldo_32,        32, "R_386_TLS_LDO_32",       32 },  \
   { &unsupport,         33, "R_386_TLS_IE_32",        0  },  \
   { &unsupport,         34, "R_386_TLS_LE_32",        0  },  \
   { &unsupport,         35, "R_386_TLS_DTPMOD32",     0  },  \
@@ -72,7 +72,7 @@
   { &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  }
+  { &none,              44, "R_386_TLS_OPT",          32 }
 
 #define DECL_X86_64_APPLY_RELOC_FUNC(Name) \
 static X86Relocator::Result Name(Relocation& pEntry, X86_64Relocator& pParent);
diff --git a/lib/Target/X86/X86Relocator.cpp b/lib/Target/X86/X86Relocator.cpp
index af8c932..6e3234f 100644
--- a/lib/Target/X86/X86Relocator.cpp
+++ b/lib/Target/X86/X86Relocator.cpp
@@ -13,6 +13,9 @@
 #include <mcld/IRBuilder.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/ELFFileFormat.h>
+#include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/ELFSegment.h>
 #include <mcld/Object/ObjectBuilder.h>
 
 #include <llvm/ADT/Twine.h>
@@ -22,7 +25,126 @@
 using namespace mcld;
 
 //===--------------------------------------------------------------------===//
-// Relocation Functions and Tables
+// X86_32 Relocation helper function
+//===--------------------------------------------------------------------===//
+/// helper_DynRel - Get an relocation entry in .rel.dyn
+static
+Relocation& helper_DynRel_init(ResolveInfo* pSym,
+                               Fragment& pFrag,
+                               uint64_t pOffset,
+                               X86Relocator::Type pType,
+                               X86_32Relocator& pParent)
+{
+  X86_32GNULDBackend& ld_backend = pParent.getTarget();
+  Relocation& rel_entry = *ld_backend.getRelDyn().create();
+  rel_entry.setType(pType);
+  rel_entry.targetRef().assign(pFrag, pOffset);
+  if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym)
+    rel_entry.setSymInfo(NULL);
+  else
+    rel_entry.setSymInfo(pSym);
+
+  return rel_entry;
+}
+
+/// helper_use_relative_reloc - Check if symbol ceuse relocation
+/// R_386_RELATIVE
+static bool
+helper_use_relative_reloc(const ResolveInfo& pSym,
+                          const X86_32Relocator& pFactory)
+
+{
+  // if symbol is dynamic or undefine or preemptible
+  if (pSym.isDyn() ||
+      pSym.isUndef() ||
+      pFactory.getTarget().isSymbolPreemptible(pSym))
+    return false;
+  return true;
+}
+
+static
+X86_32GOTEntry& helper_GOT_init(Relocation& pReloc,
+                                bool pHasRel,
+					                      X86_32Relocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86_32GNULDBackend& ld_backend = pParent.getTarget();
+  assert(NULL == pParent.getSymGOTMap().lookUp(*rsym));
+
+  X86_32GOTEntry* got_entry = ld_backend.getGOT().create();
+  pParent.getSymGOTMap().record(*rsym, *got_entry);
+
+  if (!pHasRel) {
+    // No corresponding dynamic relocation, initialize to the symbol value.
+    got_entry->setValue(X86Relocator::SymVal);
+  }
+  else {
+    // Initialize got_entry content and the corresponding dynamic relocation.
+    if (helper_use_relative_reloc(*rsym, pParent)) {
+      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE,
+                                                                       pParent);
+      got_entry->setValue(X86Relocator::SymVal);
+    }
+    else {
+      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT,
+                                                                       pParent);
+      got_entry->setValue(0x0);
+    }
+  }
+  return *got_entry;
+}
+
+static
+X86Relocator::Address helper_GOT_ORG(X86_32Relocator& pParent)
+{
+  return pParent.getTarget().getGOTPLT().addr();
+}
+
+static
+X86Relocator::Address helper_get_GOT_address(Relocation& pReloc,
+                                             X86_32Relocator& pParent)
+{
+  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
+  assert(NULL != got_entry);
+  return pParent.getTarget().getGOT().addr() + got_entry->getOffset();
+}
+
+static
+PLTEntryBase& helper_PLT_init(Relocation& pReloc, X86_32Relocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86_32GNULDBackend& ld_backend = pParent.getTarget();
+  assert(NULL == pParent.getSymPLTMap().lookUp(*rsym));
+
+  PLTEntryBase* plt_entry = ld_backend.getPLT().create();
+  pParent.getSymPLTMap().record(*rsym, *plt_entry);
+
+  // initialize plt and the corresponding gotplt and dyn rel entry.
+  assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) &&
+         "PLT entry not exist, but GOTPLT entry exist!");
+  X86_32GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create();
+  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
+
+  // init the corresponding rel entry in .rel.plt
+  Relocation& rel_entry = *ld_backend.getRelPLT().create();
+  rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
+  rel_entry.targetRef().assign(*gotplt_entry);
+  rel_entry.setSymInfo(rsym);
+  return *plt_entry;
+}
+
+static
+X86Relocator::Address helper_get_PLT_address(ResolveInfo& pSym, X86_32Relocator& pParent)
+{
+  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
+  assert(NULL != plt_entry);
+  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
+}
+
+//===--------------------------------------------------------------------===//
+// X86_32 Relocation Functions and Tables
 //===--------------------------------------------------------------------===//
 DECL_X86_32_APPLY_RELOC_FUNCS
 
@@ -58,7 +180,8 @@
 void X86Relocator::scanRelocation(Relocation& pReloc,
                                   IRBuilder& pLinker,
                                   Module& pModule,
-                                  LDSection& pSection)
+                                  LDSection& pSection,
+                                  Input& pInput)
 {
   if (LinkerConfig::Object == config().codeGenType())
     return;
@@ -67,7 +190,6 @@
   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;
@@ -82,12 +204,12 @@
   // 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();
+    issueUndefRef(pReloc, pSection, pInput);
 }
 
 void X86Relocator::addCopyReloc(ResolveInfo& pSym, X86GNULDBackend& pTarget)
 {
-  Relocation& rel_entry = *pTarget.getRelDyn().consumeEntry();
+  Relocation& rel_entry = *pTarget.getRelDyn().create();
   rel_entry.setType(pTarget.getCopyRelType());
   assert(pSym.outSymbol()->hasFragRef());
   rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
@@ -202,9 +324,9 @@
 }
 
 void X86_32Relocator::scanLocalReloc(Relocation& pReloc,
-															     	 IRBuilder& pBuilder,
-																		 Module& pModule,
-																		 LDSection& pSection)
+                                     IRBuilder& pBuilder,
+                                     Module& pModule,
+                                     LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
@@ -212,13 +334,31 @@
   switch(pReloc.type()){
 
     case llvm::ELF::R_386_32:
+      // 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 (config().isCodeIndep()) {
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+        getTarget().checkAndSetHasTextRel(*pSection.getLink());
+        // set up the dyn rel directly
+        helper_DynRel_init(rsym,
+                           *pReloc.targetRef().frag(),
+                           pReloc.targetRef().offset(),
+                           llvm::ELF::R_386_RELATIVE,
+                           *this);
+      }
+      return;
+
     case llvm::ELF::R_386_16:
     case llvm::ELF::R_386_8:
       // 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 (config().isCodeIndep()) {
-        getTarget().getRelDyn().reserveEntry();
+        // set up the dyn rel directly
+        helper_DynRel_init(rsym, *pReloc.targetRef().frag(),
+                            pReloc.targetRef().offset(), pReloc.type(), *this);
         // set Rel bit
         rsym->setReserved(rsym->reserved() | ReserveRel);
         getTarget().checkAndSetHasTextRel(*pSection.getLink());
@@ -236,28 +376,25 @@
     case llvm::ELF::R_386_GOT32:
       // Symbol needs GOT entry, reserve entry in .got
       // return if we already create GOT for this symbol
-      if (rsym->reserved() & (ReserveGOT | GOTRel))
+      if (rsym->reserved() & ReserveGOT)
         return;
-      // FIXME: check STT_GNU_IFUNC symbol
-      getTarget().getGOT().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;
-      }
+      // FIXME: check STT_GNU_IFUNC symbol
+
       // 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
       if (LinkerConfig::DynObj ==
                    config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
-        getTarget().getRelDyn().reserveEntry();
-        // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | GOTRel);
+        helper_GOT_init(pReloc, true, *this);
+        // set GOT bit
+        rsym->setReserved(rsym->reserved() | ReserveGOT);
         return;
       }
-      // set GOT bit
+
+      // elsewhere if the GOT is used in statically linked binaries,
+      // the GOT entry is enough and no relocation is needed.
+      helper_GOT_init(pReloc, false, *this);
       rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
 
@@ -268,13 +405,9 @@
 
     case llvm::ELF::R_386_TLS_GD: {
       // FIXME: no linker optimization for TLS relocation
-      if (rsym->reserved() & GOTRel)
+      if (rsym->reserved() & ReserveGOT)
         return;
-      getTarget().getGOT().reserve(2);
-      // reserve an rel entry
-      getTarget().getRelDyn().reserveEntry();
-      // set GOTRel bit
-      rsym->setReserved(rsym->reserved() | GOTRel);
+
       // define the section symbol for .tdata or .tbss
       // the target symbol of the created dynamic relocation should be the
       // section symbol of the section which this symbol defined. so we
@@ -282,19 +415,40 @@
       ELFFileFormat* file_format = getTarget().getOutputFormat();
       const LDSection* sym_sect =
                &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
+      LDSymbol* sect_sym = NULL;
       if (&file_format->getTData() == sym_sect) {
-        if (!getTarget().hasTDATASymbol())
-          getTarget().setTDATASymbol(*pModule.getSectionSymbolSet().get(*sym_sect));
+        if (!getTarget().hasTDATASymbol()) {
+          sect_sym = pModule.getSectionSymbolSet().get(*sym_sect);
+          getTarget().setTDATASymbol(*sect_sym);
+        }
       }
       else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) {
-        if (!getTarget().hasTBSSSymbol())
-          getTarget().setTBSSSymbol(*pModule.getSectionSymbolSet().get(*sym_sect));
+        if (!getTarget().hasTBSSSymbol()) {
+          sect_sym = pModule.getSectionSymbolSet().get(*sym_sect);
+          getTarget().setTBSSSymbol(*sect_sym);
+        }
       }
       else
         error(diag::invalid_tls) << rsym->name() << sym_sect->name();
+
+      // set up a pair of got entries and a dyn rel
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
+      X86_32GOTEntry* got_entry1 = getTarget().getGOT().create();
+      X86_32GOTEntry* got_entry2 = getTarget().getGOT().create();
+      getSymGOTMap().record(*rsym, *got_entry1, *got_entry2);
+      // set up value of got entries, the value of got_entry2 should be the
+      // symbol value, which has to be set during apply relocation
+      got_entry1->setValue(0x0);
+
+      // setup dyn rel for got_entry1
+      Relocation& rel_entry1 = helper_DynRel_init(rsym, *got_entry1, 0x0,
+                                        llvm::ELF::R_386_TLS_DTPMOD32, *this);
+      // for local tls symbol, add rel entry against the section symbol this
+      // symbol belong to (.tdata or .tbss)
+      rel_entry1.setSymInfo(sect_sym->resolveInfo());
       return;
     }
-
     case llvm::ELF::R_386_TLS_LDM:
       getTLSModuleID();
       return;
@@ -302,46 +456,65 @@
     case llvm::ELF::R_386_TLS_LDO_32:
       return;
 
-    case llvm::ELF::R_386_TLS_IE:
+    case llvm::ELF::R_386_TLS_IE: {
       getTarget().setHasStaticTLS();
-      // if buildint shared object, a RELATIVE dynamic relocation is needed
+
+      // if building shared object, a RELATIVE dynamic relocation is needed
       if (LinkerConfig::DynObj == config().codeGenType()) {
-        getTarget().getRelDyn().reserveEntry();
+         helper_DynRel_init(rsym, *pReloc.targetRef().frag(),
+                                              pReloc.targetRef().offset(),
+                                              llvm::ELF::R_386_RELATIVE, *this);
         rsym->setReserved(rsym->reserved() | ReserveRel);
         getTarget().checkAndSetHasTextRel(*pSection.getLink());
-      } else {
+      }
+      else {
         // for local sym, we can convert ie to le if not building shared object
         convertTLSIEtoLE(pReloc, pSection);
         return;
       }
-      if (rsym->reserved() & GOTRel)
-        return;
-      // reserve got and dyn relocation entries for tp-relative offset
-      getTarget().getGOT().reserve();
-      getTarget().getRelDyn().reserveEntry();
-      // set GOTRel bit
-      rsym->setReserved(rsym->reserved() | GOTRel);
-      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
-      return;
 
-    case llvm::ELF::R_386_TLS_GOTIE:
-      getTarget().setHasStaticTLS();
-      if (rsym->reserved() & GOTRel)
+      if (rsym->reserved() & ReserveGOT)
         return;
-      // reserve got and dyn relocation entries for tp-relative offset
-      getTarget().getGOT().reserve();
-      getTarget().getRelDyn().reserveEntry();
-      // set GOTRel bit
-      rsym->setReserved(rsym->reserved() | GOTRel);
+
+      // set up the got and the corresponding rel entry
+      X86_32GOTEntry* got_entry = getTarget().getGOT().create();
+      getSymGOTMap().record(*rsym, *got_entry);
+      got_entry->setValue(0x0);
+      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF,
+                                                                         *this);
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
+      // add symbol to dyn sym table
       getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
       return;
+    }
+
+    case llvm::ELF::R_386_TLS_GOTIE: {
+      getTarget().setHasStaticTLS();
+      if (rsym->reserved() & ReserveGOT)
+        return;
+      // set up the got and the corresponding dyn rel
+      X86_32GOTEntry* got_entry = getTarget().getGOT().create();
+      getSymGOTMap().record(*rsym, *got_entry);
+      got_entry->setValue(0x0);
+      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF,
+                                                                        *this);
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
+      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
+      return;
+    }
 
     case llvm::ELF::R_386_TLS_LE:
     case llvm::ELF::R_386_TLS_LE_32:
       getTarget().setHasStaticTLS();
       // if buildint shared object, a dynamic relocation is needed
       if (LinkerConfig::DynObj == config().codeGenType()) {
-        getTarget().getRelDyn().reserveEntry();
+        helper_DynRel_init(rsym,
+                           *pReloc.targetRef().frag(),
+                           pReloc.targetRef().offset(),
+                           llvm::ELF::R_386_TLS_TPOFF,
+                           *this);
         rsym->setReserved(rsym->reserved() | ReserveRel);
         getTarget().checkAndSetHasTextRel(*pSection.getLink());
         // the target symbol of the dynamic relocation is rsym, so we need to
@@ -359,9 +532,9 @@
 }
 
 void X86_32Relocator::scanGlobalReloc(Relocation& pReloc,
-								 				 				 		  IRBuilder& pBuilder,
-								 				 				 		  Module& pModule,
-								 				 				 		  LDSection& pSection)
+                                      IRBuilder& pBuilder,
+                                      Module& pModule,
+                                      LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
@@ -375,29 +548,39 @@
       if (getTarget().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
+          // Symbol needs PLT entry, we need 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())
-          getTarget().getPLT().reserveEntry();
-          getTarget().getGOTPLT().reserve();
-          getTarget().getRelPLT().reserveEntry();
+          // in .got and .rel.plt.
+          helper_PLT_init(pReloc, *this);
           // set PLT bit
           rsym->setReserved(rsym->reserved() | ReservePLT);
         }
       }
 
-      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
-        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
-        getTarget().getRelDyn().reserveEntry();
+      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                                                                        true)) {
+        // symbol needs dynamic relocation entry, set up the dynrel entry
         if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
           addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
         }
         else {
-          // set Rel bit
+          // set Rel bit and the dyn rel
           rsym->setReserved(rsym->reserved() | ReserveRel);
-          getTarget().checkAndSetHasTextRel(pSection);
+          getTarget().checkAndSetHasTextRel(*pSection.getLink());
+          if (llvm::ELF::R_386_32 == pReloc.type() &&
+              helper_use_relative_reloc(*rsym, *this))
+            helper_DynRel_init(rsym,
+                               *pReloc.targetRef().frag(),
+                               pReloc.targetRef().offset(),
+                               llvm::ELF::R_386_RELATIVE,
+                               *this);
+          else
+            helper_DynRel_init(rsym,
+                               *pReloc.targetRef().frag(),
+                               pReloc.targetRef().offset(),
+                               pReloc.type(),
+                               *this);
         }
       }
       return;
@@ -422,17 +605,13 @@
       // if symbol is defined in the ouput file and it's not
       // preemptible, no need plt
       if (rsym->isDefine() && !rsym->isDyn() &&
-         !getTarget().isSymbolPreemptible(*rsym)) {
+          !getTarget().isSymbolPreemptible(*rsym))
         return;
-      }
 
-      // Symbol needs PLT entry, we need to reserve a PLT entry
+      // Symbol needs PLT entry, we need 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())
-      getTarget().getPLT().reserveEntry();
-      getTarget().getGOTPLT().reserve();
-      getTarget().getRelPLT().reserveEntry();
+      // in .got and .rel.plt
+      helper_PLT_init(pReloc, *this);
       // set PLT bit
       rsym->setReserved(rsym->reserved() | ReservePLT);
       return;
@@ -440,26 +619,16 @@
     case llvm::ELF::R_386_GOT32:
       // Symbol needs GOT entry, reserve entry in .got
       // return if we already create GOT for this symbol
-      if (rsym->reserved() & (ReserveGOT | GOTRel))
+      if (rsym->reserved() & ReserveGOT)
         return;
-      getTarget().getGOT().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
       if (LinkerConfig::DynObj ==
-                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
-        getTarget().getRelDyn().reserveEntry();
-        // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | GOTRel);
-        return;
-      }
+                   config().codeGenType() || rsym->isUndef() || rsym->isDyn())
+        helper_GOT_init(pReloc, true, *this);
+      else
+        helper_GOT_init(pReloc, false, *this);
       // set GOT bit
       rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
@@ -472,43 +641,65 @@
           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
+          // Symbol needs PLT entry, we need 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())
-          getTarget().getPLT().reserveEntry();
-          getTarget().getGOTPLT().reserve();
-          getTarget().getRelPLT().reserveEntry();
+          // in .got and .rel.plt.
           // set PLT bit
+          helper_PLT_init(pReloc, *this);
           rsym->setReserved(rsym->reserved() | ReservePLT);
         }
       }
 
-      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) {
-        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
-        getTarget().getRelDyn().reserveEntry();
+      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                                                                       false)) {
+        // symbol needs dynamic relocation entry, setup an entry in .rel.dyn
         if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
-          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym,
+                                                                   getTarget());
           addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
         }
         else {
-          // set Rel bit
+          // set Rel bit and the dyn rel
           rsym->setReserved(rsym->reserved() | ReserveRel);
-          getTarget().checkAndSetHasTextRel(pSection);
+          getTarget().checkAndSetHasTextRel(*pSection.getLink());
+          if (llvm::ELF::R_386_32 == pReloc.type() &&
+              helper_use_relative_reloc(*rsym, *this))
+            helper_DynRel_init(rsym,
+                               *pReloc.targetRef().frag(),
+                               pReloc.targetRef().offset(),
+                               llvm::ELF::R_386_RELATIVE,
+                               *this);
+          else
+            helper_DynRel_init(rsym,
+                               *pReloc.targetRef().frag(),
+                               pReloc.targetRef().offset(),
+                               pReloc.type(),
+                               *this);
         }
       }
       return;
 
     case llvm::ELF::R_386_TLS_GD: {
       // FIXME: no linker optimization for TLS relocation
-      if (rsym->reserved() & GOTRel)
+      if (rsym->reserved() & ReserveGOT)
         return;
-      // reserve two pairs of got entry and dynamic relocation
-      getTarget().getGOT().reserve(2);
-      getTarget().getRelDyn().reserveEntry(2);
+
+      // set up a pair of got entries and a pair of dyn rel
+      X86_32GOTEntry* got_entry1 = getTarget().getGOT().create();
+      X86_32GOTEntry* got_entry2 = getTarget().getGOT().create();
+      getSymGOTMap().record(*rsym, *got_entry1, *got_entry2);
+      got_entry1->setValue(0x0);
+      got_entry2->setValue(0x0);
+      // setup dyn rel for got entries against rsym
+      helper_DynRel_init(rsym, *got_entry1, 0x0,
+                                        llvm::ELF::R_386_TLS_DTPMOD32, *this);
+      helper_DynRel_init(rsym, *got_entry2, 0x0,
+                                        llvm::ELF::R_386_TLS_DTPOFF32, *this);
+
+      // add the rsym to dynamic symbol table
       getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
-      // set GOTRel bit
-      rsym->setReserved(rsym->reserved() | GOTRel);
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
     }
 
@@ -519,11 +710,13 @@
     case llvm::ELF::R_386_TLS_LDO_32:
       return;
 
-    case llvm::ELF::R_386_TLS_IE:
+    case llvm::ELF::R_386_TLS_IE: {
       getTarget().setHasStaticTLS();
       // if buildint shared object, a RELATIVE dynamic relocation is needed
       if (LinkerConfig::DynObj == config().codeGenType()) {
-        getTarget().getRelDyn().reserveEntry();
+        helper_DynRel_init(rsym, *pReloc.targetRef().frag(),
+                                               pReloc.targetRef().offset(),
+                                               llvm::ELF::R_386_RELATIVE, *this);
         rsym->setReserved(rsym->reserved() | ReserveRel);
         getTarget().checkAndSetHasTextRel(*pSection.getLink());
       } else {
@@ -533,34 +726,45 @@
           return;
         }
       }
-      if (rsym->reserved() & GOTRel)
+      if (rsym->reserved() & ReserveGOT)
         return;
-      // reserve got and dyn relocation entries for tp-relative offset
-      getTarget().getGOT().reserve();
-      getTarget().getRelDyn().reserveEntry();
-      getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
-      // set GOTRel bit
-      rsym->setReserved(rsym->reserved() | GOTRel);
+      // set up the got and the corresponding rel entry
+      X86_32GOTEntry* got_entry = getTarget().getGOT().create();
+      getSymGOTMap().record(*rsym, *got_entry);
+      got_entry->setValue(0x0);
+      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF,
+                                                                         *this);
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
+    }
 
-    case llvm::ELF::R_386_TLS_GOTIE:
+    case llvm::ELF::R_386_TLS_GOTIE: {
       getTarget().setHasStaticTLS();
-      if (rsym->reserved() & GOTRel)
+      if (rsym->reserved() & ReserveGOT)
         return;
-      // reserve got and dyn relocation entries for tp-relative offset
-      getTarget().getGOT().reserve();
-      getTarget().getRelDyn().reserveEntry();
+      // set up the got and the corresponding dyn rel
+      X86_32GOTEntry* got_entry = getTarget().getGOT().create();
+      getSymGOTMap().record(*rsym, *got_entry);
+      got_entry->setValue(0x0);
+      helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_386_TLS_TPOFF,
+                                                                        *this);
       getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
-      // set GOTRel bit
-      rsym->setReserved(rsym->reserved() | GOTRel);
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
+    }
 
     case llvm::ELF::R_386_TLS_LE:
     case llvm::ELF::R_386_TLS_LE_32:
       getTarget().setHasStaticTLS();
       // if buildint shared object, a dynamic relocation is needed
       if (LinkerConfig::DynObj == config().codeGenType()) {
-        getTarget().getRelDyn().reserveEntry();
+        helper_DynRel_init(rsym,
+                           *pReloc.targetRef().frag(),
+                           pReloc.targetRef().offset(),
+                           llvm::ELF::R_386_TLS_TPOFF,
+                           *this);
         getTarget().getRelDyn().addSymbolToDynSym(*rsym->outSymbol());
         rsym->setReserved(rsym->reserved() | ReserveRel);
         getTarget().checkAndSetHasTextRel(*pSection.getLink());
@@ -583,16 +787,11 @@
     return *got_entry;
 
   // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
-  getTarget().getGOT().reserve(2);
-  got_entry = getTarget().getGOT().consume();
-  getTarget().getGOT().consume()->setValue(0x0);
+  got_entry = getTarget().getGOT().create();
+  getTarget().getGOT().create()->setValue(0x0);
 
-  getTarget().getRelDyn().reserveEntry();
-  Relocation* rel_entry = getTarget().getRelDyn().consumeEntry();
-  rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32);
-  rel_entry->targetRef().assign(*got_entry, 0x0);
-  rel_entry->setSymInfo(NULL);
-
+  helper_DynRel_init(NULL, *got_entry, 0x0, llvm::ELF::R_386_TLS_DTPMOD32,
+                                                                          *this);
   return *got_entry;
 }
 
@@ -611,10 +810,11 @@
     off = 0;
 
   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);
+  // FIXME: should we create a special symbol for the tls opt instead?
+  reloc->setSymInfo(pReloc.symInfo());
 
   // 2. modify the opcodes to the appropriate ones
   uint8_t* op =  (reinterpret_cast<uint8_t*>(&reloc->target()));
@@ -647,154 +847,9 @@
   pReloc.setType(llvm::ELF::R_386_TLS_LE);
 }
 
-//===--------------------------------------------------------------------===//
-// Relocation helper function
-//===--------------------------------------------------------------------===//
-
-/// helper_DynRel - Get an relocation entry in .rel.dyn
-static
-Relocation& helper_DynRel(ResolveInfo* pSym,
-                          Fragment& pFrag,
-                          uint64_t pOffset,
-                          X86Relocator::Type pType,
-                          X86_32Relocator& pParent)
-{
-  X86_32GNULDBackend& 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_386_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_386_RELATIVE
-static bool
-helper_use_relative_reloc(const ResolveInfo& pSym,
-                          const X86_32Relocator& pFactory)
-
-{
-  // if symbol is dynamic or undefine or preemptible
-  if (pSym.isDyn() ||
-      pSym.isUndef() ||
-      pFactory.getTarget().isSymbolPreemptible(pSym))
-    return false;
-  return true;
-}
-
-static
-X86_32GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
-					X86_32Relocator& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  X86_32GNULDBackend& ld_backend = pParent.getTarget();
-
-  X86_32GOTEntry* 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() & X86Relocator::ReserveGOT) {
-    // No corresponding dynamic relocation, initialize to the symbol value.
-    got_entry->setValue(pReloc.symValue());
-  }
-  else if (rsym->reserved() & X86Relocator::GOTRel) {
-    // Initialize got_entry content and the corresponding dynamic relocation.
-    if (helper_use_relative_reloc(*rsym, pParent)) {
-      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent);
-      got_entry->setValue(pReloc.symValue());
-    }
-    else {
-      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_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_32Relocator& pParent)
-{
-  return pParent.getTarget().getGOTPLT().addr();
-}
-
-
-static
-X86Relocator::Address helper_GOT(Relocation& pReloc, X86_32Relocator& 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,
-				      X86_32Relocator& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  X86_32GNULDBackend& 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() & X86Relocator::ReservePLT) {
-    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);
-    // init the corresponding rel entry in .rel.plt
-    Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
-    rel_entry.setType(llvm::ELF::R_386_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_32Relocator& pParent)
-{
-  return pParent.getTarget().getPLT().addr();
-}
-
-
-static
-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();
-}
-
-
-//=========================================//
-// Each relocation function implementation //
-//=========================================//
+//================================================//
+// X86_32 Each relocation function implementation //
+//================================================//
 
 // R_386_NONE
 X86Relocator::Result none(Relocation& pReloc, X86_32Relocator& pParent)
@@ -811,13 +866,12 @@
   Relocator::DWord A = pReloc.target() + pReloc.addend();
   Relocator::DWord S = pReloc.symValue();
   bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
-                              *rsym,
-                              (rsym->reserved() & X86Relocator::ReservePLT),
-                              true);
-  FragmentRef &target_fragref = pReloc.targetRef();
-  Fragment *target_frag = target_fragref.frag();
+                                  *rsym,
+                                  (rsym->reserved() & X86Relocator::ReservePLT),
+                                  true);
 
-  LDSection& target_sect = target_frag->getParent()->getSection();
+
+  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())) {
@@ -825,36 +879,18 @@
     return X86Relocator::OK;
   }
 
-  // A local symbol may need REL Type dynamic relocation
-  if (rsym->isLocal() && has_dyn_rel) {
-    X86Relocator::Type pType = pReloc.type();
-    if (llvm::ELF::R_386_32 == pType)
-      pType = llvm::ELF::R_386_RELATIVE;
-    helper_DynRel(rsym, *target_frag, target_fragref.offset(), pType, pParent);
-    pReloc.target() = S + A;
-    return X86Relocator::OK;
-  }
-
   // An external symbol may need PLT and dynamic relocation
   if (!rsym->isLocal()) {
     if (rsym->reserved() & X86Relocator::ReservePLT) {
-      S = helper_PLT(pReloc, pParent);
+      S = helper_get_PLT_address(*rsym, pParent);
     }
     // If we generate a dynamic relocation (except R_386_RELATIVE)
     // for a place, we should not perform static relocation on it
     // in order to keep the addend store in the place correct.
-    if (has_dyn_rel) {
-      if (llvm::ELF::R_386_32 == pReloc.type() &&
-          helper_use_relative_reloc(*rsym, pParent)) {
-        helper_DynRel(rsym, *target_frag, target_fragref.offset(),
-              llvm::ELF::R_386_RELATIVE, pParent);
-      }
-      else {
-        helper_DynRel(rsym, *target_frag, target_fragref.offset(),
-                      pReloc.type(), pParent);
+    if (has_dyn_rel)
+      if (llvm::ELF::R_386_32 != pReloc.type() ||
+          (!helper_use_relative_reloc(*rsym, pParent)))
         return X86Relocator::OK;
-      }
-    }
   }
 
   // perform static relocation
@@ -871,6 +907,10 @@
   Relocator::DWord A = pReloc.target() + pReloc.addend();
   Relocator::DWord S = pReloc.symValue();
   Relocator::DWord P = pReloc.place();
+  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
+                                  *rsym,
+                                  (rsym->reserved() & X86Relocator::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
@@ -883,23 +923,12 @@
   // An external symbol may need PLT and dynamic relocation
   if (!rsym->isLocal()) {
     if (rsym->reserved() & X86Relocator::ReservePLT) {
-       S = helper_PLT(pReloc, pParent);
-       pReloc.target() = S + A - P;
+      S = helper_get_PLT_address(*rsym, pParent);
+      pReloc.target() = S + A - P;
     }
-    if (pParent.getTarget().symbolNeedsDynRel(
-                              *rsym,
-                              (rsym->reserved() & X86Relocator::ReservePLT),
-                              false)) {
-      if (helper_use_relative_reloc(*rsym, pParent) ) {
-        helper_DynRel(rsym, *pReloc.targetRef().frag(),
-              pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
-      }
-      else {
-        helper_DynRel(rsym, *pReloc.targetRef().frag(),
-                          pReloc.targetRef().offset(), pReloc.type(), pParent);
-          return X86Relocator::OK;
-      }
-    }
+    if (has_dyn_rel)
+      if (!helper_use_relative_reloc(*rsym, pParent))
+        return X86Relocator::OK;
   }
 
    // perform static relocation
@@ -931,11 +960,18 @@
 // R_386_GOT32: GOT(S) + A - GOT_ORG
 X86Relocator::Result got32(Relocation& pReloc, X86_32Relocator& pParent)
 {
-  if (!(pReloc.symInfo()->reserved()
-       & (X86Relocator::ReserveGOT | X86Relocator::GOTRel))) {
+  ResolveInfo* rsym = pReloc.symInfo();
+  if (!(rsym->reserved() & (X86Relocator::ReserveGOT)))
     return X86Relocator::BadReloc;
-  }
-  X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
+
+  // set up got entry value if the got has no dyn rel or
+  // the dyn rel is RELATIVE
+  X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
+  assert(NULL != got_entry);
+  if (got_entry->getValue() == X86Relocator::SymVal)
+    got_entry->setValue(pReloc.symValue());
+
+  X86Relocator::Address GOT_S   = helper_get_GOT_address(pReloc, pParent);
   Relocator::DWord      A       = pReloc.target() + pReloc.addend();
   X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
   // Apply relocation.
@@ -949,7 +985,7 @@
   // PLT_S depends on if there is a PLT entry.
   X86Relocator::Address PLT_S;
   if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT))
-    PLT_S = helper_PLT(pReloc, pParent);
+    PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
   else
     PLT_S = pReloc.symValue();
   Relocator::DWord      A = pReloc.target() + pReloc.addend();
@@ -964,50 +1000,19 @@
   // global-dynamic
   ResolveInfo* rsym = pReloc.symInfo();
   // must reserve two pairs of got and dynamic relocation
-  if (!(rsym->reserved() & X86Relocator::GOTRel)) {
-     return X86Relocator::BadReloc;
-  }
+  if (!(rsym->reserved() & X86Relocator::ReserveGOT))
+    return X86Relocator::BadReloc;
 
-  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
-  X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
+  X86_32GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUpFirstEntry(*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);
-    X86_32GOTEntry* got_entry2 = ld_backend.getGOT().consume();
-    got_entry1->setValue(0x0);
-    got_entry2->setValue(0x0);
-    // setup dyn rel for get_entry1
-    Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0,
-                                        llvm::ELF::R_386_TLS_DTPMOD32, pParent);
-    if (rsym->isLocal()) {
-      // for local symbol, set got_entry2 to symbol value
-      got_entry2->setValue(pReloc.symValue());
-
-      // for local tls symbol, add rel entry against the section symbol this
-      // symbol belong to (.tdata or .tbss)
-      const LDSection* sym_sect =
-         &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
-      ResolveInfo* sect_sym = NULL;
-      if (&file_format->getTData() == sym_sect)
-        sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo();
-      else
-        sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo();
-      rel_entry1.setSymInfo(sect_sym);
-    }
-    else {
-      // for non-local symbol, add a pair of rel entries against this symbol
-      // for those two got entries
-      helper_DynRel(rsym, *got_entry2, 0x0,
-                                        llvm::ELF::R_386_TLS_DTPOFF32, pParent);
-    }
-  }
+  // set the got_entry2 value to symbol value
+  if (rsym->isLocal())
+     pParent.getSymGOTMap().lookUpSecondEntry(*rsym)->setValue(pReloc.symValue());
 
   // perform relocation to the first got entry
   Relocator::DWord A = pReloc.target() + pReloc.addend();
@@ -1051,31 +1056,13 @@
 X86Relocator::Result tls_ie(Relocation& pReloc, X86_32Relocator& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
-  if (!(rsym->reserved() & X86Relocator::GOTRel)) {
+  if (!(rsym->reserved() & X86Relocator::ReserveGOT)) {
      return X86Relocator::BadReloc;
   }
 
-  if (rsym->reserved() & X86Relocator::ReserveRel) {
-    // when building shared object, set up a RELATIVE dynamic relocation
-    helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(),
-                                            llvm::ELF::R_386_RELATIVE, pParent);
-  }
-
   // set up the got and dynamic relocation entries if not exist
   X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
-  if (NULL == got_entry) {
-    // set got entry
-    X86_32GNULDBackend& ld_backend = pParent.getTarget();
-    got_entry = ld_backend.getGOT().consume();
-    pParent.getSymGOTMap().record(*rsym, *got_entry);
-    got_entry->setValue(0x0);
-    // set relocation entry
-    Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
-    rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
-    rel_entry.setSymInfo(rsym);
-    rel_entry.targetRef().assign(*got_entry);
-  }
-
+  assert(NULL != got_entry);
   // perform relocation to the absolute address of got_entry
   X86Relocator::Address GOT_S =
                  pParent.getTarget().getGOT().addr() + got_entry->getOffset();
@@ -1090,24 +1077,13 @@
 X86Relocator::Result tls_gotie(Relocation& pReloc, X86_32Relocator& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
-  if (!(rsym->reserved() & X86Relocator::GOTRel)) {
+  if (!(rsym->reserved() & X86Relocator::ReserveGOT)) {
      return X86Relocator::BadReloc;
   }
 
   // set up the got and dynamic relocation entries if not exist
   X86_32GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
-  if (NULL == got_entry) {
-    // set got entry
-    X86_32GNULDBackend& ld_backend = pParent.getTarget();
-    got_entry = ld_backend.getGOT().consume();
-    pParent.getSymGOTMap().record(*rsym, *got_entry);
-    got_entry->setValue(0x0);
-    // set relocation entry
-    Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
-    rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
-    rel_entry.setSymInfo(rsym);
-    rel_entry.targetRef().assign(*got_entry);
-  }
+  assert(NULL != got_entry);
 
   // All GOT offsets are relative to the end of the GOT.
   X86Relocator::SWord GOT_S = got_entry->getOffset() -
@@ -1121,23 +1097,19 @@
 // R_X86_TLS_LE
 X86Relocator::Result tls_le(Relocation& pReloc, X86_32Relocator& pParent)
 {
-  ResolveInfo* rsym = pReloc.symInfo();
-  if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel) {
-    helper_DynRel(rsym,
-                  *pReloc.targetRef().frag(),
-                  pReloc.targetRef().offset(),
-                  llvm::ELF::R_386_TLS_TPOFF,
-                  pParent);
+  if (pReloc.symInfo()->reserved() & X86Relocator::ReserveRel)
     return X86Relocator::OK;
-  }
 
   // perform static relocation
   // get TLS segment
-  ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find(
-                                       llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
+  ELFSegmentFactory::const_iterator tls_seg =
+    pParent.getTarget().elfSegmentTable().find(llvm::ELF::PT_TLS,
+                                               llvm::ELF::PF_R,
+                                               0x0);
+  assert(tls_seg != pParent.getTarget().elfSegmentTable().end());
   Relocator::DWord A = pReloc.target() + pReloc.addend();
   X86Relocator::Address S = pReloc.symValue();
-  pReloc.target() = S + A - tls_seg->memsz();
+  pReloc.target() = S + A - (*tls_seg)->memsz();
   return X86Relocator::OK;
 }
 
@@ -1147,7 +1119,130 @@
 }
 
 //===--------------------------------------------------------------------===//
-// Relocation Functions and Tables
+// X86_64 Relocation helper function
+//===--------------------------------------------------------------------===//
+/// helper_DynRel - Get an relocation entry in .rela.dyn
+static
+Relocation& helper_DynRel_init(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().create();
+  rel_entry.setType(pType);
+  rel_entry.targetRef().assign(pFrag, pOffset);
+  if (pType == llvm::ELF::R_X86_64_RELATIVE || NULL == pSym)
+    rel_entry.setSymInfo(NULL);
+  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_GOT_init(Relocation& pReloc,
+                                bool pHasRel,
+                                X86_64Relocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86_64GNULDBackend& ld_backend = pParent.getTarget();
+  assert(NULL == pParent.getSymGOTMap().lookUp(*rsym));
+
+  X86_64GOTEntry* got_entry = ld_backend.getGOT().create();
+  pParent.getSymGOTMap().record(*rsym, *got_entry);
+
+  // If we first get this GOT entry, we should initialize it.
+  if (!pHasRel) {
+    // No corresponding dynamic relocation, initialize to the symbol value.
+    got_entry->setValue(X86Relocator::SymVal);
+  }
+  else {
+    // Initialize got_entry content and the corresponding dynamic relocation.
+    if (helper_use_relative_reloc(*rsym, pParent)) {
+       Relocation& rel_entry = helper_DynRel_init(rsym, *got_entry, 0x0,
+                                         llvm::ELF::R_X86_64_RELATIVE, pParent);
+       rel_entry.setAddend(X86Relocator::SymVal);
+       pParent.getRelRelMap().record(pReloc, rel_entry);
+    }
+    else {
+       helper_DynRel_init(rsym, *got_entry, 0x0, llvm::ELF::R_X86_64_GLOB_DAT,
+                                                                       pParent);
+    }
+    got_entry->setValue(0);
+  }
+  return *got_entry;
+}
+
+static
+X86Relocator::Address helper_GOT_ORG(X86_64Relocator& pParent)
+{
+  return pParent.getTarget().getGOT().addr();
+}
+
+static
+X86Relocator::Address helper_get_GOT_address(Relocation& pReloc,
+                                             X86_64Relocator& pParent)
+{
+  X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
+  assert(NULL != got_entry);
+  return got_entry->getOffset();
+}
+
+static
+X86Relocator::Address helper_get_PLT_address(ResolveInfo& pSym,
+                                             X86_64Relocator& pParent)
+{
+  PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym);
+  assert(NULL != plt_entry);
+  return pParent.getTarget().getPLT().addr() + plt_entry->getOffset();
+}
+
+static
+PLTEntryBase& helper_PLT_init(Relocation& pReloc, X86_64Relocator& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86_64GNULDBackend& ld_backend = pParent.getTarget();
+  assert(NULL == pParent.getSymPLTMap().lookUp(*rsym));
+
+  PLTEntryBase* plt_entry = ld_backend.getPLT().create();
+  pParent.getSymPLTMap().record(*rsym, *plt_entry);
+
+  // initialize plt and the corresponding gotplt and dyn rel entry.
+  assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) &&
+         "PLT entry not exist, but DynRel entry exist!");
+  X86_64GOTEntry* gotplt_entry = ld_backend.getGOTPLT().create();
+  pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
+
+  // init the corresponding rel entry in .rel.plt
+  Relocation& rel_entry = *ld_backend.getRelPLT().create();
+  rel_entry.setType(llvm::ELF::R_X86_64_JUMP_SLOT);
+  rel_entry.targetRef().assign(*gotplt_entry);
+  rel_entry.setSymInfo(rsym);
+  return *plt_entry;
+}
+
+//===--------------------------------------------------------------------===//
+// X86_64 Relocation Functions and Tables
 //===--------------------------------------------------------------------===//
 DECL_X86_64_APPLY_RELOC_FUNCS
 
@@ -1210,6 +1305,22 @@
 
   switch(pReloc.type()){
     case llvm::ELF::R_X86_64_64:
+      // 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()) {
+        Relocation& reloc = helper_DynRel_init(rsym,
+                                               *pReloc.targetRef().frag(),
+                                               pReloc.targetRef().offset(),
+                                               llvm::ELF::R_X86_64_RELATIVE,
+                                               *this);
+        getRelRelMap().record(pReloc, reloc);
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+        getTarget().checkAndSetHasTextRel(*pSection.getLink());
+      }
+      return;
+
     case llvm::ELF::R_X86_64_32:
     case llvm::ELF::R_X86_64_16:
     case llvm::ELF::R_X86_64_8:
@@ -1218,7 +1329,12 @@
       // a dynamic relocations with RELATIVE type to this location is needed.
       // Reserve an entry in .rela.dyn
       if (config().isCodeIndep()) {
-        getTarget().getRelDyn().reserveEntry();
+        Relocation& reloc = helper_DynRel_init(rsym,
+                                               *pReloc.targetRef().frag(),
+                                               pReloc.targetRef().offset(),
+                                               pReloc.type(),
+                                               *this);
+        getRelRelMap().record(pReloc, reloc);
         // set Rel bit
         rsym->setReserved(rsym->reserved() | ReserveRel);
         getTarget().checkAndSetHasTextRel(*pSection.getLink());
@@ -1233,27 +1349,17 @@
     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))
+      if (rsym->reserved() & ReserveGOT)
         return;
-      getTarget().getGOT().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()) {
-        getTarget().getRelDyn().reserveEntry();
-        // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | GOTRel);
-        return;
-      }
-      // set GOT bit
+                   config().codeGenType() || rsym->isUndef() || rsym->isDyn())
+        helper_GOT_init(pReloc, true, *this);
+      else
+        helper_GOT_init(pReloc, false, *this);
       rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
 
@@ -1285,26 +1391,41 @@
         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())
-          getTarget().getPLT().reserveEntry();
-          getTarget().getGOTPLT().reserve();
-          getTarget().getRelPLT().reserveEntry();
+          // in .got and .rela.plt.
+          helper_PLT_init(pReloc, *this);
           // set PLT bit
           rsym->setReserved(rsym->reserved() | ReservePLT);
         }
       }
 
-      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) {
-        // symbol needs dynamic relocation entry, reserve an entry in .rela.dyn
-        getTarget().getRelDyn().reserveEntry();
+      if (getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                                                                        true)) {
+        // symbol needs dynamic relocation entry, set up the dynrel entry
         if (getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
           addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
         }
         else {
-          // set Rel bit
+          // set Rel bit and the dyn rel
           rsym->setReserved(rsym->reserved() | ReserveRel);
+          getTarget().checkAndSetHasTextRel(*pSection.getLink());
+          if (llvm::ELF::R_386_32 == pReloc.type() &&
+              helper_use_relative_reloc(*rsym, *this)) {
+            Relocation& reloc = helper_DynRel_init(rsym,
+                                                   *pReloc.targetRef().frag(),
+                                                   pReloc.targetRef().offset(),
+                                                   llvm::ELF::R_X86_64_RELATIVE,
+                                                   *this);
+            getRelRelMap().record(pReloc, reloc);
+          }
+          else {
+            Relocation& reloc = helper_DynRel_init(rsym,
+                                                   *pReloc.targetRef().frag(),
+                                                   pReloc.targetRef().offset(),
+                                                   pReloc.type(),
+                                                   *this);
+            getRelRelMap().record(pReloc, reloc);
+          }
 	        getTarget().checkAndSetHasTextRel(*pSection.getLink());
         }
       }
@@ -1313,26 +1434,17 @@
     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))
+      if (rsym->reserved() & ReserveGOT)
         return;
-      getTarget().getGOT().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()) {
-        getTarget().getRelDyn().reserveEntry();
-        // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | GOTRel);
-        return;
-      }
+                   config().codeGenType() || rsym->isUndef() || rsym->isDyn())
+        helper_GOT_init(pReloc, true, *this);
+      else
+        helper_GOT_init(pReloc, false, *this);
       // set GOT bit
       rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
@@ -1355,13 +1467,10 @@
         return;
       }
 
-      // Symbol needs PLT entry, we need to reserve a PLT entry
+      // Symbol needs PLT entry, we need 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())
-      getTarget().getPLT().reserveEntry();
-      getTarget().getGOTPLT().reserve();
-      getTarget().getRelPLT().reserveEntry();
+      // in .got and .rel.plt.
+      helper_PLT_init(pReloc, *this);
       // set PLT bit
       rsym->setReserved(rsym->reserved() | ReservePLT);
       return;
@@ -1373,13 +1482,10 @@
           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
+          // Symbol needs PLT entry, we need 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())
-          getTarget().getPLT().reserveEntry();
-          getTarget().getGOTPLT().reserve();
-          getTarget().getRelPLT().reserveEntry();
+          // in .got and .rel.plt.
+          helper_PLT_init(pReloc, *this);
           // set PLT bit
           rsym->setReserved(rsym->reserved() | ReservePLT);
         }
@@ -1391,11 +1497,12 @@
       // All other dynamic relocations may lead to run-time relocation
       // overflow.
       if (getTarget().isDynamicSymbol(*rsym) &&
-	  getTarget().symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false) &&
-	  getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
-        getTarget().getRelDyn().reserveEntry();
-   	LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
-	  addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
+	        getTarget().symbolNeedsDynRel(*rsym,
+                                        (rsym->reserved() & ReservePLT),
+                                        false) &&
+	        getTarget().symbolNeedsCopyReloc(pReloc, *rsym)) {
+   	    LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, getTarget());
+	      addCopyReloc(*cpy_sym.resolveInfo(), getTarget());
       }
       return;
 
@@ -1406,147 +1513,9 @@
   } // end switch
 }
 
-//===--------------------------------------------------------------------===//
-// Relocation helper function
-//===--------------------------------------------------------------------===//
-/// 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() & X86Relocator::ReserveGOT) {
-    // No corresponding dynamic relocation, initialize to the symbol value.
-    got_entry->setValue(pReloc.symValue());
-  }
-  else if (rsym->reserved() & X86Relocator::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() & X86Relocator::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)
 {
@@ -1562,15 +1531,10 @@
   ResolveInfo* rsym = pReloc.symInfo();
   Relocator::DWord A = pReloc.target() + pReloc.addend();
   Relocator::DWord S = pReloc.symValue();
-  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
-                              *rsym,
-                              (rsym->reserved() & X86Relocator::ReservePLT),
-                              true);
+  Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc);
+  bool has_dyn_rel = (NULL != dyn_rel);
 
-  FragmentRef &target_fragref = pReloc.targetRef();
-  Fragment *target_frag = target_fragref.frag();
-
-  LDSection& target_sect = target_frag->getParent()->getSection();
+  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())) {
@@ -1580,19 +1544,14 @@
 
   // A local symbol may need RELA Type dynamic relocation
   if (rsym->isLocal() && has_dyn_rel) {
-    X86Relocator::Type pType = pReloc.type();
-    if (llvm::ELF::R_X86_64_64 == pType)
-      pType = llvm::ELF::R_X86_64_RELATIVE;
-    Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
-        target_fragref.offset(), pType, pParent);
-    rel_entry.setAddend(S + A);
+    dyn_rel->setAddend(S + A);
     return X86Relocator::OK;
   }
 
   // An external symbol may need PLT and dynamic relocation
   if (!rsym->isLocal()) {
     if (rsym->reserved() & X86Relocator::ReservePLT) {
-      S = helper_PLT(pReloc, pParent);
+      S = helper_get_PLT_address(*rsym, pParent);
     }
     // If we generate a dynamic relocation (except R_X86_64_RELATIVE)
     // for a place, we should not perform static relocation on it
@@ -1600,14 +1559,10 @@
     if (has_dyn_rel) {
       if (llvm::ELF::R_X86_64_64 == pReloc.type() &&
           helper_use_relative_reloc(*rsym, pParent)) {
-        Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
-            target_fragref.offset(), llvm::ELF::R_X86_64_RELATIVE, pParent);
-        rel_entry.setAddend(S + A);
+        dyn_rel->setAddend(S + A);
       }
       else {
-        Relocation& rel_entry = helper_DynRel(rsym, *target_frag,
-            target_fragref.offset(), pReloc.type(), pParent);
-        rel_entry.setAddend(A);
+        dyn_rel->setAddend(A);
         return X86Relocator::OK;
       }
     }
@@ -1624,13 +1579,9 @@
   ResolveInfo* rsym = pReloc.symInfo();
   Relocator::DWord A = pReloc.target() + pReloc.addend();
   Relocator::DWord S = pReloc.symValue();
-  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
-                              *rsym,
-                              (rsym->reserved() & X86Relocator::ReservePLT),
-                              true);
 
   // There should be no dynamic relocations for R_X86_64_32S.
-  if (has_dyn_rel)
+  if (NULL != pParent.getRelRelMap().lookUp(pReloc))
     return X86Relocator::BadReloc;
 
   LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
@@ -1639,7 +1590,7 @@
   // An external symbol may need PLT and dynamic relocation
   if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag()) &&
       !rsym->isLocal() && rsym->reserved() & X86Relocator::ReservePLT)
-    S = helper_PLT(pReloc, pParent);
+    S = helper_get_PLT_address(*rsym, pParent);
 
 #if notyet
   // Check 32-bit signed overflow.
@@ -1656,11 +1607,22 @@
 // R_X86_64_GOTPCREL: GOT(S) + GOT_ORG + A - P
 X86Relocator::Result gotpcrel(Relocation& pReloc, X86_64Relocator& pParent)
 {
-  if (!(pReloc.symInfo()->reserved()
-       & (X86Relocator::ReserveGOT | X86Relocator::GOTRel))) {
+  if (!(pReloc.symInfo()->reserved() & X86Relocator::ReserveGOT)) {
     return X86Relocator::BadReloc;
   }
-  X86Relocator::Address GOT_S   = helper_GOT(pReloc, pParent);
+
+  // set symbol value of the got entry if needed
+  X86_64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*pReloc.symInfo());
+  if (X86Relocator::SymVal == got_entry->getValue())
+    got_entry->setValue(pReloc.symValue());
+
+  // setup relocation addend if needed
+  Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc);
+  if ((NULL != dyn_rel) && (X86Relocator::SymVal == dyn_rel->addend())) {
+    dyn_rel->setAddend(pReloc.symValue());
+  }
+
+  X86Relocator::Address GOT_S   = helper_get_GOT_address(pReloc, pParent);
   Relocator::DWord      A       = pReloc.target() + pReloc.addend();
   X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
   // Apply relocation.
@@ -1674,7 +1636,7 @@
   // PLT_S depends on if there is a PLT entry.
   X86Relocator::Address PLT_S;
   if ((pReloc.symInfo()->reserved() & X86Relocator::ReservePLT))
-    PLT_S = helper_PLT(pReloc, pParent);
+    PLT_S = helper_get_PLT_address(*pReloc.symInfo(), pParent);
   else
     PLT_S = pReloc.symValue();
   Relocator::DWord      A = pReloc.target() + pReloc.addend();
@@ -1701,17 +1663,22 @@
     return X86Relocator::OK;
   }
 
+  // setup relocation addend if needed
+  Relocation* dyn_rel = pParent.getRelRelMap().lookUp(pReloc);
+  if ((NULL != dyn_rel) && (X86Relocator::SymVal == dyn_rel->addend())) {
+    dyn_rel->setAddend(S);
+  }
+
   // An external symbol may need PLT and dynamic relocation
   if (!rsym->isLocal()) {
     if (rsym->reserved() & X86Relocator::ReservePLT) {
-       S = helper_PLT(pReloc, pParent);
-       pReloc.target() = S + A - P;
+       S = helper_get_PLT_address(*rsym, pParent);
     }
     if (pParent.getTarget().symbolNeedsDynRel(
                               *rsym,
                               (rsym->reserved() & X86Relocator::ReservePLT),
                               false)) {
-          return X86Relocator::Overflow;
+      return X86Relocator::Overflow;
     }
   }
 
diff --git a/lib/Target/X86/X86Relocator.h b/lib/Target/X86/X86Relocator.h
index d6e97ed..da67464 100644
--- a/lib/Target/X86/X86Relocator.h
+++ b/lib/Target/X86/X86Relocator.h
@@ -15,7 +15,7 @@
 #include <mcld/LD/Relocator.h>
 #include <mcld/Target/GOT.h>
 #include <mcld/Target/PLT.h>
-#include <mcld/Target/SymbolEntryMap.h>
+#include <mcld/Target/KeyEntryMap.h>
 #include "X86LDBackend.h"
 
 namespace mcld {
@@ -30,49 +30,41 @@
 class X86Relocator : public Relocator
 {
 public:
-  typedef SymbolEntryMap<PLTEntryBase> SymPLTMap;
+  typedef KeyEntryMap<ResolveInfo, PLTEntryBase> SymPLTMap;
 
   /** \enum ReservedEntryType
    *  \brief The reserved entry type of reserved space in ResolveInfo.
    *
    *  This is used for sacnRelocation to record what kinds of entries are
-   *  reserved for this resolved symbol
+   *  reserved for this resolved symbol. In X86, there are three kinds of
+   *  entries, GOT, PLT, and dynamic reloction.
    *
-   *  In X86, there are three kinds of entries, GOT, PLT, and dynamic reloction.
-   *  GOT may needs a corresponding relocation to relocate itself, so we
-   *  separate GOT to two situations: GOT and GOTRel. Besides, for the same
-   *  symbol, there might be two kinds of entries reserved for different location.
-   *  For example, reference to the same symbol, one may use GOT and the other may
-   *  use dynamic relocation.
-   *
-   *  bit:  3       2      1     0
-   *   | PLT | GOTRel | GOT | Rel |
+   *  bit:  3     2     1     0
+   *   |    | PLT | GOT | Rel |
    *
    *  value    Name         - Description
    *
    *  0000     None         - no reserved entry
    *  0001     ReserveRel   - reserve an dynamic relocation entry
    *  0010     ReserveGOT   - reserve an GOT entry
-   *  0011     GOTandRel    - For different relocation, we've reserved GOT and
-   *                          Rel for different location.
-   *  0100     GOTRel       - reserve an GOT entry and the corresponding Dyncamic
-   *                          relocation entry which relocate this GOT entry
-   *  0101     GOTRelandRel - For different relocation, we've reserved GOTRel
-   *                          and relocation entry for different location.
-   *  1000     ReservePLT   - reserve an PLT entry and the corresponding GOT,
-   *                          Dynamic relocation entries
-   *  1001     PLTandRel    - For different relocation, we've reserved PLT and
-   *                          Rel for different location.
+   *  0100     ReservePLT   - reserve an PLT entry and the corresponding GOT,
+   *
    */
   enum ReservedEntryType {
     None         = 0,
     ReserveRel   = 1,
     ReserveGOT   = 2,
-    GOTandRel    = 3,
-    GOTRel       = 4,
-    GOTRelandRel = 5,
-    ReservePLT   = 8,
-    PLTandRel    = 9
+    ReservePLT   = 4,
+  };
+
+  /** \enum EntryValue
+   *  \brief The value of the entries. The symbol value will be decided at after
+   *  layout, so we mark the entry during scanRelocation and fill up the actual
+   *  value when applying relocations.
+   */
+  enum EntryValue {
+    Default = 0,
+    SymVal  = 1
   };
 
 public:
@@ -95,7 +87,8 @@
   void scanRelocation(Relocation& pReloc,
                       IRBuilder& pBuilder,
                       Module& pModule,
-                      LDSection& pSection);
+                      LDSection& pSection,
+                      Input& pInput);
 
 protected:
   /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
@@ -131,8 +124,8 @@
 class X86_32Relocator : public X86Relocator
 {
 public:
-  typedef SymbolEntryMap<X86_32GOTEntry> SymGOTMap;
-  typedef SymbolEntryMap<X86_32GOTEntry> SymGOTPLTMap;
+  typedef KeyEntryMap<ResolveInfo, X86_32GOTEntry> SymGOTMap;
+  typedef KeyEntryMap<ResolveInfo, X86_32GOTEntry> SymGOTPLTMap;
 
   enum {
     R_386_TLS_OPT = 44 // mcld internal relocation type
@@ -189,8 +182,9 @@
 class X86_64Relocator : public X86Relocator
 {
 public:
-  typedef SymbolEntryMap<X86_64GOTEntry> SymGOTMap;
-  typedef SymbolEntryMap<X86_64GOTEntry> SymGOTPLTMap;
+  typedef KeyEntryMap<ResolveInfo, X86_64GOTEntry> SymGOTMap;
+  typedef KeyEntryMap<ResolveInfo, X86_64GOTEntry> SymGOTPLTMap;
+  typedef KeyEntryMap<Relocation, Relocation> RelRelMap;
 
 public:
   X86_64Relocator(X86_64GNULDBackend& pParent, const LinkerConfig& pConfig);
@@ -213,6 +207,9 @@
   const SymGOTPLTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
   SymGOTPLTMap&       getSymGOTPLTMap()       { return m_SymGOTPLTMap; }
 
+  const RelRelMap& getRelRelMap() const { return m_RelRelMap; }
+  RelRelMap&       getRelRelMap()       { return m_RelRelMap; }
+
 private:
   void scanLocalReloc(Relocation& pReloc,
                       IRBuilder& pBuilder,
@@ -228,6 +225,7 @@
   X86_64GNULDBackend& m_Target;
   SymGOTMap m_SymGOTMap;
   SymGOTPLTMap m_SymGOTPLTMap;
+  RelRelMap m_RelRelMap;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index b419fd1..82fea93 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -9,7 +9,6 @@
 #include "X86TargetMachine.h"
 
 #include "X86.h"
-#include <mcld/Target/TargetMachine.h>
 #include <mcld/Support/TargetRegistry.h>
 
 extern "C" void MCLDInitializeX86LDTarget() {
@@ -18,13 +17,15 @@
   mcld::RegisterTargetMachine<mcld::X86TargetMachine> Y(mcld::TheX86_64Target);
 }
 
-mcld::X86TargetMachine::X86TargetMachine(llvm::TargetMachine& pPM,
-                                         const mcld::Target &pTarget,
-                                         const std::string& pTriple)
-  : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
-}
+using namespace mcld;
 
-mcld::X86TargetMachine::~X86TargetMachine()
-{
+//===----------------------------------------------------------------------===//
+// X86TargetMachine
+//===----------------------------------------------------------------------===//
+X86TargetMachine::X86TargetMachine(llvm::TargetMachine& pPM,
+                                   const llvm::Target& pLLVMTarget,
+                                   const mcld::Target& pMCLDTarget,
+                                   const std::string& pTriple)
+  : MCLDTargetMachine(pPM, pLLVMTarget, pMCLDTarget, pTriple) {
 }
 
diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h
index 9034741..b9d78e1 100644
--- a/lib/Target/X86/X86TargetMachine.h
+++ b/lib/Target/X86/X86TargetMachine.h
@@ -9,18 +9,17 @@
 #ifndef MCLD_X86_TARGET_MACHINE_H
 #define MCLD_X86_TARGET_MACHINE_H
 #include "X86.h"
-#include <mcld/Target/TargetMachine.h>
+#include <mcld/CodeGen/TargetMachine.h>
 
 namespace mcld {
 
 class X86TargetMachine : public MCLDTargetMachine
 {
 public:
-  X86TargetMachine(llvm::TargetMachine &pTM,
-                   const mcld::Target &pTarget,
-                   const std::string &pTriple);
-
-  virtual ~X86TargetMachine();
+  X86TargetMachine(llvm::TargetMachine& pTM,
+                   const llvm::Target& pLLVMTarget,
+                   const mcld::Target& pMCLDTarget,
+                   const std::string& pTriple);
 };
 
 } // namespace of mcld
diff --git a/templates/header.h b/templates/header.h
new file mode 100644
index 0000000..2b9acf7
--- /dev/null
+++ b/templates/header.h
@@ -0,0 +1,29 @@
+//===- header.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_${CLASS_NAME}_H
+#define MCLD_${CLASS_NAME}_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld
+{
+
+/** \class ${class_name}
+ *  \brief ${brief}
+ */
+class ${class_name}
+{
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/templates/headerTest.h b/templates/headerTest.h
new file mode 100644
index 0000000..d36bda1
--- /dev/null
+++ b/templates/headerTest.h
@@ -0,0 +1,40 @@
+//===- headerTest.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_${CLASS_NAME}_TEST_H
+#define MCLD_${CLASS_NAME}_TEST_H
+
+#include <gtest.h>
+
+namespace mcld {
+
+class ${class_name};
+
+namespace test {
+
+class ${class_name}Test : public ::testing::Test
+{
+public:
+  // Constructor can do set-up work for all test here.
+  ${class_name}Test();
+
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~${class_name}Test();
+
+  // SetUp() will be called immediately before each test.
+  virtual void SetUp();
+
+  // TearDown() will be called immediately after each test.
+  virtual void TearDown();
+};
+
+} // namespace of test
+} // namespace of mcld
+
+#endif
+
diff --git a/templates/impl.cpp b/templates/impl.cpp
new file mode 100644
index 0000000..fe468d8
--- /dev/null
+++ b/templates/impl.cpp
@@ -0,0 +1,16 @@
+//===- impl.cpp -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/${deployment}/${class_name}.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ${class_name}
+//===----------------------------------------------------------------------===//
+
diff --git a/templates/implTest.cpp b/templates/implTest.cpp
new file mode 100644
index 0000000..fbfdf05
--- /dev/null
+++ b/templates/implTest.cpp
@@ -0,0 +1,44 @@
+//===- implTest.cpp -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/${deployment}/${class_name}.h>
+#include "${class_name}Test.h"
+
+using namespace mcld;
+using namespace mcld::test;
+
+
+// Constructor can do set-up work for all test here.
+${class_name}Test::${class_name}Test()
+{
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+${class_name}Test::~${class_name}Test()
+{
+}
+
+// SetUp() will be called immediately before each test.
+void ${class_name}Test::SetUp()
+{
+}
+
+// TearDown() will be called immediately after each test.
+void ${class_name}Test::TearDown()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Testcases
+//===----------------------------------------------------------------------===//
+/** 
+TEST_F( ${class_name}Test, name of  the testcase for ${class_name} ) {
+	Write you exercise here
+}
+**/
+
diff --git a/tools/mcld/include/alone/Config/Config.h.in b/tools/mcld/include/alone/Config/Config.h.in
deleted file mode 100644
index 6618b08..0000000
--- a/tools/mcld/include/alone/Config/Config.h.in
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef ALONE_CONFIG_CONFIG_H
-#define ALONE_CONFIG_CONFIG_H
-
-#if defined(TARGET_BUILD)
-  #define PROVIDE_@PROVIDE_ALONE_TARGET@_CODEGEN
-  #define DEFAULT_@DEFAULT_ALONE_TARGET@_CODEGEN
-#else
-  #define PROVIDE_ARM_CODEGEN
-  #define PROVIDE_X86_CODEGEN
-  #define PROVIDE_MIPS_CODEGEN
-  #define DEFAULT_@DEFAULT_ALONE_TARGET@_CODEGEN
-#endif
-
-#define DEFAULT_ARM_TRIPLE_STRING "armv7-none-linux-gnueabi"
-#define DEFAULT_X86_TRIPLE_STRING "i686-unknown-linux"
-#define DEFAULT_MIPS_TRIPLE_STRING "mipsel-none-linux-gnueabi"
-#define DEFAULT_X86_64_TRIPLE_STRING "x86_64-unknown-linux"
-
-#define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_@DEFAULT_ALONE_TARGET@_TRIPLE_STRING
-
-#endif // ALONE_CONFIG_CONFIG_H
diff --git a/tools/mcld/include/alone/Linker.h b/tools/mcld/include/alone/Linker.h
deleted file mode 100644
index 987b36a..0000000
--- a/tools/mcld/include/alone/Linker.h
+++ /dev/null
@@ -1,94 +0,0 @@
-//===- Linker.h -----------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALONE_LINKER_H
-#define ALONE_LINKER_H
-
-#include <string>
-
-namespace mcld {
-
-class Module;
-class IRBuilder;
-class LinkerConfig;
-class Linker;
-class Input;
-class MemoryArea;
-
-namespace sys { namespace fs {
-
-class Path;
-
-} } // end namespace sys::fs
-
-} // end namespace mcld
-
-namespace alone {
-
-class LinkerConfig;
-
-class Linker {
-public:
-  enum ErrorCode {
-    kSuccess,
-    kDoubleConfig,
-    kDelegateLDInfo,
-    kFindNameSpec,
-    kOpenObjectFile,
-    kOpenMemory,
-    kNotConfig,
-    kNotSetUpOutput,
-    kOpenOutput,
-    kReadSections,
-    kReadSymbols,
-    kAddAdditionalSymbols,
-    kMaxErrorCode
-  };
-
-  static const char *GetErrorString(enum ErrorCode pErrCode);
-
-private:
-  const mcld::LinkerConfig *mLDConfig;
-  mcld::Module *mModule;
-  mcld::Linker *mLinker;
-  mcld::IRBuilder *mBuilder;
-  std::string mSOName;
-  std::string mOutputPath;
-  int mOutputHandler;
-
-public:
-  Linker();
-
-  Linker(const LinkerConfig& pConfig);
-
-  ~Linker();
-
-  enum ErrorCode config(const LinkerConfig& pConfig);
-
-  enum ErrorCode addNameSpec(const std::string &pNameSpec);
-
-  enum ErrorCode addObject(const std::string &pObjectPath);
-
-  enum ErrorCode addObject(void* pMemory, size_t pSize);
-
-  enum ErrorCode addCode(void* pMemory, size_t pSize);
-
-  enum ErrorCode setOutput(const std::string &pPath);
-
-  enum ErrorCode setOutput(int pFileHandler);
-
-  enum ErrorCode link();
-
-private:
-  enum ErrorCode extractFiles(const LinkerConfig& pConfig);
-};
-
-} // end namespace alone
-
-#endif // ALONE_LINKER_H
diff --git a/tools/mcld/include/alone/Support/Initialization.h b/tools/mcld/include/alone/Support/Initialization.h
deleted file mode 100644
index 9af994e..0000000
--- a/tools/mcld/include/alone/Support/Initialization.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- Initialization.h ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALONE_SUPPORT_INITIALIZATION_H
-#define ALONE_SUPPORT_INITIALIZATION_H
-
-namespace alone {
-
-namespace init {
-
-void Initialize();
-
-} // end namespace init
-
-} // end namespace alone
-
-#endif // ALONE_SUPPORT_INITIALIZATION_H
diff --git a/tools/mcld/include/alone/Support/LinkerConfig.h b/tools/mcld/include/alone/Support/LinkerConfig.h
deleted file mode 100644
index 8f36ec5..0000000
--- a/tools/mcld/include/alone/Support/LinkerConfig.h
+++ /dev/null
@@ -1,123 +0,0 @@
-//===- Linker.h -----------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALONE_SUPPORT_LINKER_CONFIG_H
-#define ALONE_SUPPORT_LINKER_CONFIG_H
-
-#include <string>
-
-#include <mcld/LinkerConfig.h>
-#include <mcld/LinkerScript.h>
-#include <mcld/Support/TargetRegistry.h>
-#include <mcld/LD/DiagnosticLineInfo.h>
-#include <mcld/LD/DiagnosticPrinter.h>
-
-namespace alone {
-
-class LinkerConfig {
-private:
-  //===--------------------------------------------------------------------===//
-  // Available Configurations
-  //===--------------------------------------------------------------------===//
-  const std::string mTriple;
-  std::string mSOName;
-
-private:
-  //===--------------------------------------------------------------------===//
-  // These are generated by LinkerConfig during initialize().
-  //===--------------------------------------------------------------------===//
-  const mcld::Target *mTarget;
-  bool initializeTarget();
-
-  mcld::LinkerConfig *mLDConfig;
-  bool initializeLDInfo();
-
-  mcld::LinkerScript *mLDScript;
-  bool initializeLDScript();
-
-  mcld::DiagnosticLineInfo *mDiagLineInfo;
-  mcld::DiagnosticPrinter *mDiagPrinter;
-  bool initializeDiagnostic();
-
-public:
-  enum ZOptionEnum {
-    kCombReloc     = 1 << 0,  ///< [on] -z combreloc, [off] -z nocombreloc
-    kDefs          = 1 << 1,  ///< -z defs
-    kExecStack     = 1 << 2,  ///< [on] -z execstack, [off] -z noexecstack
-    kInitFirst     = 1 << 3,  ///< -z initfirst
-    kInterPose     = 1 << 4,  ///< -z interpose
-    kLoadFltr      = 1 << 5,  ///< -z loadfltr
-    kMulDefs       = 1 << 6,  ///< -z muldefs
-    kNoCopyReloc   = 1 << 7,  ///< -z nocopyreloc
-    kNoDefaultLib  = 1 << 8,  ///< -z nodefaultlib
-    kNoDelete      = 1 << 9,  ///< -z nodelete
-    kNoDLOpen      = 1 << 10, ///< -z nodlopen
-    kNoDump        = 1 << 11, ///< -z nodump
-    kRelro         = 1 << 12, ///< [on] -z relro, [off] -z norelro
-    kLazy          = 1 << 13, ///< [on] -z lazy, [off] -z now
-    kOrigin        = 1 << 14, ///< -z origin
-    kZOptionMask   = 0xFFFF
-  };
-
-public:
-  //===--------------------------------------------------------------------===//
-  // Getters
-  //===--------------------------------------------------------------------===//
-  inline const std::string &getTriple() const
-  { return mTriple; }
-
-  inline const mcld::Target *getTarget() const
-  { return mTarget; }
-
-  inline mcld::LinkerConfig* getLDConfig()
-  { return mLDConfig; }
-
-  inline const mcld::LinkerConfig* getLDConfig() const
-  { return mLDConfig; }
-
-  inline mcld::LinkerScript* getLDScript()
-  { return mLDScript; }
-
-  inline const mcld::LinkerScript* getLDScript() const
-  { return mLDScript; }
-
-  bool isShared() const;
-
-  inline std::string getSOName() const
-  { return mSOName; }
-
-  void setShared(bool pEnable = true);
-
-  void setBsymbolic(bool pEnable = true);
-
-  void setDefineCommon(bool pEnable = true);
-
-  void setSOName(const std::string &pSOName);
-
-  void setDyld(const std::string &pDyld);
-
-  void setSysRoot(const std::string &pSysRoot);
-
-  void setZOption(unsigned int pOptions);
-
-  void addWrap(const std::string &pWrapSymbol);
-
-  void addPortable(const std::string &pPortableSymbol);
-
-  void addSearchDir(const std::string &pDir);
-
-public:
-  LinkerConfig(const std::string& pTriple);
-
-  virtual ~LinkerConfig();
-};
-
-} // end namespace alone
-
-#endif // ALONE_SUPPORT_LINKER_CONFIG_H
diff --git a/tools/mcld/include/alone/Support/Log.h b/tools/mcld/include/alone/Support/Log.h
deleted file mode 100644
index e3c80d1..0000000
--- a/tools/mcld/include/alone/Support/Log.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//===- Log.h --------------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALONE_SUPPORT_LOG_H
-#define ALONE_SUPPORT_LOG_H
-
-#include <cstdio>
-
-#define ALOGE(fmt, args...) \
-printf("%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, args)
-
-#endif // ALONE_SUPPORT_LOG_H
diff --git a/tools/mcld/include/alone/Support/TargetLinkerConfigs.h b/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
deleted file mode 100644
index 3bb6b7b..0000000
--- a/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
+++ /dev/null
@@ -1,89 +0,0 @@
-//===- TargetLinkerConfig.h -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALONE_SUPPORT_TARGET_LINKER_CONFIGS_H
-#define ALONE_SUPPORT_TARGET_LINKER_CONFIGS_H
-
-#include <string>
-
-#include "alone/Config/Config.h"
-#include "alone/Support/LinkerConfig.h"
-
-namespace alone {
-
-//===----------------------------------------------------------------------===//
-// ARM
-//===----------------------------------------------------------------------===//
-#if defined(PROVIDE_ARM_CODEGEN)
-class ARMLinkerConfig : public LinkerConfig {
-public:
-  ARMLinkerConfig();
-};
-#endif // defined(PROVIDE_ARM_CODEGEN)
-
-//===----------------------------------------------------------------------===//
-// MIPS
-//===----------------------------------------------------------------------===//
-#if defined(PROVIDE_MIPS_CODEGEN)
-class MipsLinkerConfig : public LinkerConfig {
-public:
-  MipsLinkerConfig();
-};
-#endif // defined(PROVIDE_MIPS_CODEGEN)
-
-//===----------------------------------------------------------------------===//
-// X86 and X86_64
-//===----------------------------------------------------------------------===//
-#if defined(PROVIDE_X86_CODEGEN)
-class X86FamilyLinkerConfigBase : public LinkerConfig {
-public:
-  X86FamilyLinkerConfigBase(const std::string& pTriple);
-};
-
-class X86_32LinkerConfig : public X86FamilyLinkerConfigBase {
-public:
-  X86_32LinkerConfig();
-};
-
-class X86_64LinkerConfig : public X86FamilyLinkerConfigBase {
-public:
-  X86_64LinkerConfig();
-};
-#endif // defined(PROVIDE_X86_CODEGEN)
-
-//===----------------------------------------------------------------------===//
-// Default target
-//===----------------------------------------------------------------------===//
-class DefaultLinkerConfig : public
-#if defined (DEFAULT_ARM_CODEGEN)
-  ARMLinkerConfig
-#elif defined (DEFAULT_MIPS_CODEGEN)
-  MipsLinkerConfig
-#elif defined (DEFAULT_X86_CODEGEN)
-  X86_32LinkerConfig
-#elif defined (DEFAULT_X86_64_CODEGEN)
-  X86_64LinkerConfig
-#else
-#  error "Unsupported Default Target!"
-#endif
-{ };
-
-#if !defined(TARGET_BUILD)
-//===----------------------------------------------------------------------===//
-// General target
-//===----------------------------------------------------------------------===//
-class GeneralLinkerConfig : public LinkerConfig {
-public:
-  GeneralLinkerConfig(const std::string& pTriple);
-};
-#endif // !defined(TARGET_BUILD)
-
-} // end namespace alone
-
-#endif // ALONE_SUPPORT_LINKER_CONFIG_H
diff --git a/tools/mcld/lib/Core/Linker.cpp b/tools/mcld/lib/Core/Linker.cpp
deleted file mode 100644
index 99d658c..0000000
--- a/tools/mcld/lib/Core/Linker.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-//===- Linker.cpp ---------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "alone/Linker.h"
-#include "alone/Support/LinkerConfig.h"
-#include "alone/Support/Log.h"
-
-#include <llvm/Support/ELF.h>
-
-#include <mcld/Module.h>
-#include <mcld/IRBuilder.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/Linker.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/Support/Path.h>
-
-using namespace alone;
-
-const char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode) {
-  static const char* ErrorString[] = {
-    /* kSuccess */
-    "Successfully compiled.",
-    /* kDoubleConfig */
-    "Configure Linker twice.",
-    /* kDelegateLDInfo */
-    "Cannot get linker information",
-    /* kFindNameSpec */
-    "Cannot find -lnamespec",
-    /* kOpenObjectFile */
-    "Cannot open object file",
-    /* kNotConfig */
-    "Linker::config() is not called",
-    /* kNotSetUpOutput */
-    "Linker::setOutput() is not called before add input files",
-    /* kOpenOutput */
-    "Cannot open output file",
-    /* kReadSections */
-    "Cannot read sections",
-    /* kReadSymbols */
-    "Cannot read symbols",
-    /* kAddAdditionalSymbols */
-    "Cannot add standard and target symbols",
-    /* kMaxErrorCode */
-    "(Unknown error code)"
-  };
-
-  if (pErrCode > kMaxErrorCode) {
-    pErrCode = kMaxErrorCode;
-  }
-
-  return ErrorString[ static_cast<size_t>(pErrCode) ];
-}
-
-//===----------------------------------------------------------------------===//
-// Linker
-//===----------------------------------------------------------------------===//
-Linker::Linker()
-  : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
-    mOutputHandler(-1) {
-}
-
-Linker::Linker(const LinkerConfig& pConfig)
-  : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
-    mOutputHandler(-1) {
-
-  const std::string &triple = pConfig.getTriple();
-
-  enum ErrorCode err = config(pConfig);
-  if (kSuccess != err) {
-    ALOGE("%s (%s)", GetErrorString(err), triple.c_str());
-    return;
-  }
-
-  return;
-}
-
-Linker::~Linker() {
-  delete mModule;
-  delete mLinker;
-  delete mBuilder;
-}
-
-enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
-  mLDConfig = pConfig.getLDConfig();
-  if (mLDConfig == NULL) {
-    return kDelegateLDInfo;
-  }
-  return kSuccess;
-}
-
-enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
-  if (mLDConfig != NULL) {
-    return kDoubleConfig;
-  }
-
-  extractFiles(pConfig);
-
-  mModule = new mcld::Module(mLDConfig->options().soname(),
-                   const_cast<mcld::LinkerScript&>(*pConfig.getLDScript()));
-
-  mBuilder = new mcld::IRBuilder(*mModule, *mLDConfig);
-
-  mLinker = new mcld::Linker();
-
-  mLinker->emulate(const_cast<mcld::LinkerScript&>(*pConfig.getLDScript()),
-                   const_cast<mcld::LinkerConfig&>(*mLDConfig));
-
-  return kSuccess;
-}
-
-enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
-  mcld::Input* input = mBuilder->ReadInput(pNameSpec);
-  if (NULL == input)
-    return kFindNameSpec;
-  return kSuccess;
-}
-
-/// addObject - Add a object file by the filename.
-enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
-  mcld::Input* input = mBuilder->ReadInput(pObjectPath, pObjectPath);
-  if (NULL == input)
-    return kOpenObjectFile;
-  return kSuccess;
-}
-
-/// addObject - Add a piece of memory. The memory is of ELF format.
-enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
-  mcld::Input* input = mBuilder->ReadInput("NAN", pMemory, pSize);
-  if (NULL == input)
-    return kOpenMemory;
-  return kSuccess;
-}
-
-enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
-  mcld::Input* input = mBuilder->CreateInput("NAN", "NAN", mcld::Input::Object);
-  mcld::LDSection* sect = mBuilder->CreateELFHeader(*input, ".text",
-                                llvm::ELF::SHT_PROGBITS,
-                                llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
-                                0x1);
-  mcld::SectionData* data = mBuilder->CreateSectionData(*sect);
-  mcld::Fragment* frag = mBuilder->CreateRegion(pMemory, pSize);
-  mBuilder->AppendFragment(*frag, *data);
-  return kSuccess;
-}
-
-enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
-  mOutputPath = pPath;
-  return kSuccess;
-}
-
-enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
-  mOutputHandler = pFileHandler;
-  return kSuccess;
-}
-
-enum Linker::ErrorCode Linker::link() {
-  mLinker->link(*mModule, *mBuilder);
-  if (!mOutputPath.empty()) {
-    mLinker->emit(mOutputPath);
-    return kSuccess;
-  }
-
-  if (-1 != mOutputHandler) {
-    mLinker->emit(mOutputHandler);
-    return kSuccess;
-  }
-  return kNotSetUpOutput;
-}
-
diff --git a/tools/mcld/lib/Support/Initialization.cpp b/tools/mcld/lib/Support/Initialization.cpp
deleted file mode 100644
index 71bd57d..0000000
--- a/tools/mcld/lib/Support/Initialization.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-//===- Initialization.cpp -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "alone/Support/Initialization.h"
-
-#include <cstdlib>
-
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/Support/TargetSelect.h>
-
-#include <mcld/Support/TargetSelect.h>
-#include <mcld/Support/TargetRegistry.h>
-
-#include "alone/Config/Config.h"
-#include "alone/Support/Log.h"
-
-namespace {
-
-void llvm_error_handler(void *pUserData, const std::string &pMessage) {
-  ALOGE("%s", pMessage.c_str());
-  ::exit(1);
-}
-
-} // end anonymous namespace
-
-void alone::init::Initialize() {
-  static bool is_initialized = false;
-
-  if (is_initialized) {
-    return;
-  }
-
-  // Setup error handler for LLVM.
-  llvm::remove_fatal_error_handler();
-  llvm::install_fatal_error_handler(llvm_error_handler, NULL);
-
-#if defined(PROVIDE_ARM_CODEGEN)
-  LLVMInitializeARMAsmPrinter();
-# if USE_DISASSEMBLER
-  LLVMInitializeARMDisassembler();
-# endif
-  LLVMInitializeARMTargetMC();
-  LLVMInitializeARMTargetInfo();
-  LLVMInitializeARMTarget();
-  MCLDInitializeARMLDTargetInfo();
-  MCLDInitializeARMLDTarget();
-  MCLDInitializeARMLDBackend();
-  MCLDInitializeARMDiagnosticLineInfo();
-#endif
-
-#if defined(PROVIDE_MIPS_CODEGEN)
-  LLVMInitializeMipsAsmPrinter();
-# if USE_DISASSEMBLER
-  LLVMInitializeMipsDisassembler();
-# endif
-  LLVMInitializeMipsTargetMC();
-  LLVMInitializeMipsTargetInfo();
-  LLVMInitializeMipsTarget();
-  MCLDInitializeMipsLDTargetInfo();
-  MCLDInitializeMipsLDTarget();
-  MCLDInitializeMipsLDBackend();
-  MCLDInitializeMipsDiagnosticLineInfo();
-#endif
-
-#if defined(PROVIDE_X86_CODEGEN)
-  LLVMInitializeX86AsmPrinter();
-# if USE_DISASSEMBLER
-  LLVMInitializeX86Disassembler();
-# endif
-  LLVMInitializeX86TargetMC();
-  LLVMInitializeX86TargetInfo();
-  LLVMInitializeX86Target();
-  MCLDInitializeX86LDTargetInfo();
-  MCLDInitializeX86LDTarget();
-  MCLDInitializeX86LDBackend();
-  MCLDInitializeX86DiagnosticLineInfo();
-#endif
-
-  is_initialized = true;
-
-  return;
-}
diff --git a/tools/mcld/lib/Support/LinkerConfig.cpp b/tools/mcld/lib/Support/LinkerConfig.cpp
deleted file mode 100644
index e968cc1..0000000
--- a/tools/mcld/lib/Support/LinkerConfig.cpp
+++ /dev/null
@@ -1,340 +0,0 @@
-//===- LinkerConfig.cpp ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "alone/Support/LinkerConfig.h"
-#include "alone/Support/Log.h"
-
-#include <llvm/Support/Signals.h>
-
-#include <mcld/MC/MCLDDirectory.h>
-#include <mcld/MC/ZOption.h>
-#include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/Support/Path.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/raw_ostream.h>
-
-using namespace alone;
-
-LinkerConfig::LinkerConfig(const std::string &pTriple)
-  : mTriple(pTriple), mSOName(), mTarget(NULL), mLDConfig(NULL),
-    mLDScript(NULL), mDiagLineInfo(NULL), mDiagPrinter(NULL) {
-
-  initializeTarget();
-  initializeLDScript();
-  initializeLDInfo();
-  initializeDiagnostic();
-}
-
-LinkerConfig::~LinkerConfig() {
-  delete mLDConfig;
-
-  if (mDiagPrinter->getNumErrors() != 0) {
-    // If here, the program failed ungracefully. Run the interrupt handlers to
-    // ensure any other cleanups (e.g., files that registered by
-    // RemoveFileOnSignal(...)) getting done before exit.
-    llvm::sys::RunInterruptHandlers();
-  }
-  mDiagPrinter->finish();
-
-  delete mLDScript;
-  delete mDiagLineInfo;
-  delete mDiagPrinter;
-}
-
-bool LinkerConfig::initializeTarget() {
-  std::string error;
-  mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error);
-  if (NULL != mTarget) {
-    return true;
-  } else {
-    ALOGE("Cannot initialize mcld::Target for given triple '%s'! (%s)\n",
-          mTriple.c_str(), error.c_str());
-    return false;
-  }
-}
-
-bool LinkerConfig::initializeLDInfo() {
-  if (NULL != mLDConfig) {
-    ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
-          mTriple.c_str());
-    return false;
-  }
-
-  mLDConfig = new mcld::LinkerConfig(getTriple());
-  mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
-
-  struct NameMap {
-    const char* from;
-    const char* to;
-  };
-
-  static const NameMap map[] =
-  {
-    {".text", ".text"},
-    {".rodata", ".rodata"},
-    {".data.rel.ro.local", ".data.rel.ro.local"},
-    {".data.rel.ro", ".data.rel.ro"},
-    {".data", ".data"},
-    {".bss", ".bss"},
-    {".tdata", ".tdata"},
-    {".tbss", ".tbss"},
-    {".init_array", ".init_array"},
-    {".fini_array", ".fini_array"},
-    // TODO: Support DT_INIT_ARRAY for all constructors?
-    {".ctors", ".ctors"},
-    {".dtors", ".dtors"},
-    // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
-    // sections would be handled differently.
-    {".sdata2", ".sdata"},
-    {".sbss2", ".sbss"},
-    {".sdata", ".sdata"},
-    {".sbss", ".sbss"},
-    {".lrodata", ".lrodata"},
-    {".ldata", ".ldata"},
-    {".lbss", ".lbss"},
-    {".gcc_except_table", ".gcc_except_table"},
-    {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
-    {".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
-    {".gnu.linkonce.r", ".rodata"},
-    {".gnu.linkonce.d", ".data"},
-    {".gnu.linkonce.b", ".bss"},
-    {".gnu.linkonce.sb2", ".sbss"},
-    {".gnu.linkonce.sb", ".sbss"},
-    {".gnu.linkonce.s2", ".sdata"},
-    {".gnu.linkonce.s", ".sdata"},
-    {".gnu.linkonce.wi", ".debug_info"},
-    {".gnu.linkonce.td", ".tdata"},
-    {".gnu.linkonce.tb", ".tbss"},
-    {".gnu.linkonce.t", ".text"},
-    {".gnu.linkonce.lr", ".lrodata"},
-    {".gnu.linkonce.lb", ".lbss"},
-    {".gnu.linkonce.l", ".ldata"},
-  };
-
-  if (mLDConfig->codeGenType() != mcld::LinkerConfig::Object) {
-    const unsigned int map_size =  (sizeof(map) / sizeof(map[0]) );
-    for (unsigned int i = 0; i < map_size; ++i) {
-      bool exist = false;
-      mLDScript->sectionMap().append(map[i].from,
-                                               map[i].to,
-                                               exist);
-    }
-  }
-  return true;
-}
-
-bool LinkerConfig::initializeLDScript() {
-  mLDScript = new mcld::LinkerScript();
-  return true;
-}
-
-bool LinkerConfig::initializeDiagnostic() {
-  // Set up MsgHandler.
-  mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDConfig);
-
-  mcld::InitializeDiagnosticEngine(*mLDConfig, mDiagPrinter);
-
-  mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
-
-  mcld::getDiagnosticEngine().setLineInfo(*mDiagLineInfo);
-  return true;
-}
-
-bool LinkerConfig::isShared() const {
-  return (mcld::LinkerConfig::DynObj == mLDConfig->codeGenType());
-}
-
-void LinkerConfig::setShared(bool pEnable) {
-  if (pEnable)
-    mLDConfig->setCodeGenType(mcld::LinkerConfig::DynObj);
-  else
-    mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
-  return;
-}
-
-void LinkerConfig::setBsymbolic(bool pEnable) {
-  mLDConfig->options().setBsymbolic(pEnable);
-  return;
-}
-
-void LinkerConfig::setDefineCommon(bool pEnable) {
-  mLDConfig->options().setDefineCommon(pEnable);
-  return;
-}
-
-void LinkerConfig::setSOName(const std::string &pSOName) {
-  mLDConfig->options().setSOName(pSOName);
-  return;
-}
-
-void LinkerConfig::setDyld(const std::string &pDyld) {
-  mLDConfig->options().setDyld(pDyld);
-  return;
-}
-
-void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
-  mLDScript->setSysroot(mcld::sys::fs::Path(pSysRoot));
-  return;
-}
-
-void LinkerConfig::setZOption(unsigned int pOptions) {
-  mcld::ZOption option;
-  if (pOptions & kCombReloc) {
-    option.setKind(mcld::ZOption::CombReloc);
-    mLDConfig->options().addZOption(option);
-  }
-  else {
-    option.setKind(mcld::ZOption::NoCombReloc);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kDefs) {
-    option.setKind(mcld::ZOption::Defs);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kExecStack) {
-    option.setKind(mcld::ZOption::ExecStack);
-    mLDConfig->options().addZOption(option);
-  }
-  else {
-    option.setKind(mcld::ZOption::NoExecStack);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kInitFirst) {
-    option.setKind(mcld::ZOption::InitFirst);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kInterPose) {
-    option.setKind(mcld::ZOption::InterPose);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kLoadFltr) {
-    option.setKind(mcld::ZOption::LoadFltr);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kMulDefs) {
-    option.setKind(mcld::ZOption::MulDefs);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kNoCopyReloc) {
-    option.setKind(mcld::ZOption::NoCopyReloc);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kNoDefaultLib) {
-    option.setKind(mcld::ZOption::NoDefaultLib);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kNoDelete) {
-    option.setKind(mcld::ZOption::NoDelete);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kNoDLOpen) {
-    option.setKind(mcld::ZOption::NoDLOpen);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kNoDump) {
-    option.setKind(mcld::ZOption::NoDump);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kRelro) {
-    option.setKind(mcld::ZOption::Relro);
-    mLDConfig->options().addZOption(option);
-  }
-  else {
-    option.setKind(mcld::ZOption::NoRelro);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kLazy) {
-    option.setKind(mcld::ZOption::Lazy);
-    mLDConfig->options().addZOption(option);
-  }
-  else {
-    option.setKind(mcld::ZOption::Now);
-    mLDConfig->options().addZOption(option);
-  }
-
-  if (pOptions & kOrigin) {
-    option.setKind(mcld::ZOption::Origin);
-    mLDConfig->options().addZOption(option);
-  }
-}
-
-void LinkerConfig::addWrap(const std::string &pWrapSymbol) {
-  bool exist = false;
-
-  // Add wname -> __wrap_wname.
-  mcld::StringEntry<llvm::StringRef>* to_wrap =
-               mLDScript->renameMap().insert(pWrapSymbol, exist);
-
-  std::string to_wrap_str = "__wrap_" + pWrapSymbol;
-  to_wrap->setValue(to_wrap_str);
-
-  if (exist) {
-    mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str;
-  }
-
-  // Add __real_wname -> wname.
-  std::string from_real_str = "__real_" + pWrapSymbol;
-  mcld::StringEntry<llvm::StringRef>* from_real =
-             mLDScript->renameMap().insert(from_real_str, exist);
-  from_real->setValue(pWrapSymbol);
-
-  if (exist) {
-    mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str;
-  }
-
-  return;
-}
-
-void LinkerConfig::addPortable(const std::string &pPortableSymbol) {
-  bool exist = false;
-
-  // Add pname -> pname_portable.
-  mcld::StringEntry<llvm::StringRef>* to_port =
-                mLDScript->renameMap().insert(pPortableSymbol, exist);
-
-  std::string to_port_str = pPortableSymbol + "_portable";
-  to_port->setValue(to_port_str);
-
-  if (exist) {
-    mcld::warning(mcld::diag::rewrap) << pPortableSymbol << to_port_str;
-}
-
-  // Add __real_pname -> pname.
-  std::string from_real_str = "__real_" + pPortableSymbol;
-  mcld::StringEntry<llvm::StringRef>* from_real =
-           mLDScript->renameMap().insert(from_real_str, exist);
-
-  from_real->setValue(pPortableSymbol);
-
-  if (exist) {
-    mcld::warning(mcld::diag::rewrap) << pPortableSymbol << from_real_str;
-  }
-
-  return;
-}
-
-void LinkerConfig::addSearchDir(const std::string &pDirPath) {
-  // SearchDirs will remove the created MCLDDirectory.
-  if (!mLDScript->directories().insert(pDirPath)) {
-    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
-  }
-}
diff --git a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
deleted file mode 100644
index d8722f6..0000000
--- a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-//===- TargetLinkerConfigs.cpp --------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "alone/Config/Config.h"
-#include "alone/Support/TargetLinkerConfigs.h"
-
-#include <mcld/TargetOptions.h>
-#include <mcld/MC/InputFactory.h>
-#include <mcld/Fragment/Relocation.h>
-
-using namespace alone;
-
-#ifdef TARGET_BUILD
-static const char* gDefaultDyld = "/system/bin/linker";
-static const char* gDefaultSysroot = "/system";
-#else
-static const char* gDefaultDyld = "/usr/lib/ld.so.1";
-static const char* gDefaultSysroot = "/";
-#endif
-
-//===----------------------------------------------------------------------===//
-// ARM
-//===----------------------------------------------------------------------===//
-#if defined(PROVIDE_ARM_CODEGEN)
-ARMLinkerConfig::ARMLinkerConfig() : LinkerConfig(DEFAULT_ARM_TRIPLE_STRING) {
-
-  // set up target-dependent options
-  getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
-  getLDConfig()->targets().setBitClass(32);
-
-  // set up target-dependent constraints of attributes
-  getLDConfig()->attribute().constraint().enableWholeArchive();
-  getLDConfig()->attribute().constraint().disableAsNeeded();
-  getLDConfig()->attribute().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  getLDConfig()->attribute().predefined().unsetWholeArchive();
-  getLDConfig()->attribute().predefined().setDynamic();
-
-  // set up target dependent options
-  if (getLDScript()->sysroot().empty()) {
-    getLDScript()->setSysroot(gDefaultSysroot);
-  }
-
-  if (!getLDConfig()->options().hasDyld()) {
-    getLDConfig()->options().setDyld(gDefaultDyld);
-  }
-
-  // set up section map
-  if (getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
-    bool exist = false;
-    getLDScript()->sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
-    getLDScript()->sectionMap().append(".ARM.extab", ".ARM.extab", exist);
-    getLDScript()->sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
-  }
-
-  // set up relocation factory
-  mcld::Relocation::SetUp(*getLDConfig());
-}
-#endif // defined(PROVIDE_ARM_CODEGEN)
-
-//===----------------------------------------------------------------------===//
-// Mips
-//===----------------------------------------------------------------------===//
-#if defined(PROVIDE_MIPS_CODEGEN)
-MipsLinkerConfig::MipsLinkerConfig()
-  : LinkerConfig(DEFAULT_MIPS_TRIPLE_STRING) {
-
-  // set up target-dependent options
-  getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
-  getLDConfig()->targets().setBitClass(32);
-
-  // set up target-dependent constraints of attibutes
-  getLDConfig()->attribute().constraint().enableWholeArchive();
-  getLDConfig()->attribute().constraint().disableAsNeeded();
-  getLDConfig()->attribute().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  getLDConfig()->attribute().predefined().unsetWholeArchive();
-  getLDConfig()->attribute().predefined().setDynamic();
-
-  // set up target dependent options
-  if (getLDScript()->sysroot().empty()) {
-    getLDScript()->setSysroot(gDefaultSysroot);
-  }
-
-  if (!getLDConfig()->options().hasDyld()) {
-    getLDConfig()->options().setDyld(gDefaultDyld);
-  }
-
-  // set up relocation factory
-  mcld::Relocation::SetUp(*getLDConfig());
-}
-#endif // defined(PROVIDE_MIPS_CODEGEN)
-
-//===----------------------------------------------------------------------===//
-// X86 and X86_64
-//===----------------------------------------------------------------------===//
-#if defined(PROVIDE_X86_CODEGEN)
-X86FamilyLinkerConfigBase::X86FamilyLinkerConfigBase(const std::string& pTriple)
-  : LinkerConfig(pTriple) {
-  // set up target-dependent options
-  getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
-  getLDConfig()->targets().setBitClass(32);
-
-  // set up target-dependent constraints of attibutes
-  getLDConfig()->attribute().constraint().enableWholeArchive();
-  getLDConfig()->attribute().constraint().disableAsNeeded();
-  getLDConfig()->attribute().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  getLDConfig()->attribute().predefined().unsetWholeArchive();
-  getLDConfig()->attribute().predefined().setDynamic();
-
-  // set up target dependent options
-  if (getLDScript()->sysroot().empty()) {
-    getLDScript()->setSysroot(gDefaultSysroot);
-  }
-
-  if (!getLDConfig()->options().hasDyld()) {
-    getLDConfig()->options().setDyld(gDefaultDyld);
-  }
-
-  // set up relocation factory
-  mcld::Relocation::SetUp(*getLDConfig());
-}
-
-X86_32LinkerConfig::X86_32LinkerConfig()
-  : X86FamilyLinkerConfigBase(DEFAULT_X86_TRIPLE_STRING) {
-}
-
-X86_64LinkerConfig::X86_64LinkerConfig()
-  : X86FamilyLinkerConfigBase(DEFAULT_X86_64_TRIPLE_STRING) {
-}
-#endif // defined(PROVIDE_X86_CODEGEN)
-
-#if !defined(TARGET_BUILD)
-//===----------------------------------------------------------------------===//
-// General
-//===----------------------------------------------------------------------===//
-GeneralLinkerConfig::GeneralLinkerConfig(const std::string& pTriple)
-  : LinkerConfig(pTriple) {
-
-  // set up target-dependent options
-  getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
-  getLDConfig()->targets().setBitClass(32);
-
-  // set up target-dependent constraints of attributes
-  getLDConfig()->attribute().constraint().enableWholeArchive();
-  getLDConfig()->attribute().constraint().disableAsNeeded();
-  getLDConfig()->attribute().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  getLDConfig()->attribute().predefined().unsetWholeArchive();
-  getLDConfig()->attribute().predefined().setDynamic();
-
-  // set up section map
-  if (llvm::Triple::arm == getLDConfig()->targets().triple().getArch() &&
-      getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
-    bool exist = false;
-    getLDScript()->sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
-    getLDScript()->sectionMap().append(".ARM.extab", ".ARM.extab", exist);
-    getLDScript()->sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
-  }
-
-  // set up relocation factory
-  mcld::Relocation::SetUp(*getLDConfig());
-}
-#endif // defined(TARGET_BUILD)
diff --git a/tools/mcld/main.cpp b/tools/mcld/main.cpp
index 968c5e6..dcb8140 100644
--- a/tools/mcld/main.cpp
+++ b/tools/mcld/main.cpp
@@ -1,4 +1,4 @@
-//===- mcld.cpp -----------------------------------------------------------===//
+//===- llvm-mcld.cpp ------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,367 +6,1552 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/CodeGen/TargetMachine.h>
+#include <mcld/Support/TargetSelect.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Support/CommandLine.h>
+#include <mcld/Support/Path.h>
+#include <mcld/Support/RealPath.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/SystemUtils.h>
+#include <mcld/Support/ToolOutputFile.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/LD/TextDiagnosticPrinter.h>
 
-#include <stdlib.h>
-#include <string>
-
-#include <llvm/ADT/SmallString.h>
+#include <llvm/PassManager.h>
+#include <llvm/Pass.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IRReader/IRReader.h>
+#include <llvm/ADT/Triple.h>
+#include <llvm/ADT/StringSwitch.h>
+#include <llvm/MC/SubtargetFeature.h>
 #include <llvm/Support/CommandLine.h>
-#include <llvm/Support/FileSystem.h>
-#include <llvm/Support/Path.h>
-#include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/system_error.h>
+#include <llvm/Support/Debug.h>
+#include <llvm/Support/FormattedStream.h>
+#include <llvm/Support/Host.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/Signals.h>
+#include <llvm/Support/SourceMgr.h>
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/Support/TargetRegistry.h>
+#include <llvm/Support/Process.h>
+#include <llvm/Target/TargetMachine.h>
 
-#include <mcld/Config/Config.h>
+#include <iostream>
 
-#include <alone/Config/Config.h>
-#include <alone/Support/LinkerConfig.h>
-#include <alone/Support/Initialization.h>
-#include <alone/Support/TargetLinkerConfigs.h>
-#include <alone/Linker.h>
+using namespace std;
 
-using namespace alone;
-
-//===----------------------------------------------------------------------===//
-// Compiler Options
-//===----------------------------------------------------------------------===//
-#ifdef TARGET_BUILD
-static const std::string OptTargetTriple(DEFAULT_TARGET_TRIPLE_STRING);
-#else
-static llvm::cl::opt<std::string>
-OptTargetTriple("mtriple",
-                llvm::cl::desc("Specify the target triple (default: "
-                                DEFAULT_TARGET_TRIPLE_STRING ")"),
-                llvm::cl::init(DEFAULT_TARGET_TRIPLE_STRING),
-                llvm::cl::value_desc("triple"));
-
-static llvm::cl::alias OptTargetTripleC("C", llvm::cl::NotHidden,
-                                        llvm::cl::desc("Alias for -mtriple"),
-                                        llvm::cl::aliasopt(OptTargetTriple));
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
 #endif
 
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#include <io.h>
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+#endif
+
+using namespace llvm;
+
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+
+static cl::opt<bool>
+UnitTest("unittest",  cl::desc("do unit test") );
+
+int unit_test( int argc, char* argv[] )
+{
+  testing::InitGoogleTest( &argc, argv );
+  return RUN_ALL_TESTS();
+}
+
+#endif
+
+// General options for llc.  Other pass-specific options are specified
+// within the corresponding llc passes, and target-specific options
+// and back-end code generation options are specified with the target machine.
+//
+// Determine optimization level.
+static cl::opt<char>
+OptLevel("O",
+         cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+                  "(default = '-O2')"),
+         cl::Prefix,
+         cl::ZeroOrMore,
+         cl::init(' '));
+
+static cl::opt<std::string>
+TargetTriple("mtriple", cl::desc("Override target triple for module"));
+
+static cl::opt<std::string>
+MArch("march", cl::desc("Architecture to generate code for (see --version)"));
+
+static cl::opt<std::string>
+MCPU("mcpu",
+  cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+  cl::value_desc("cpu-name"),
+  cl::init(""));
+
+static cl::list<std::string>
+MAttrs("mattr",
+  cl::CommaSeparated,
+  cl::desc("Target specific attributes (-mattr=help for details)"),
+  cl::value_desc("a1,+a2,-a3,..."));
+
+static cl::opt<llvm::CodeModel::Model>
+CMModel("code-model",
+        cl::desc("Choose code model"),
+        cl::init(CodeModel::Default),
+        cl::values(clEnumValN(CodeModel::Default, "default",
+                              "Target default code model"),
+                   clEnumValN(CodeModel::Small, "small",
+                              "Small code model"),
+                   clEnumValN(CodeModel::Kernel, "kernel",
+                              "Kernel code model"),
+                   clEnumValN(CodeModel::Medium, "medium",
+                              "Medium code model"),
+                   clEnumValN(CodeModel::Large, "large",
+                              "Large code model"),
+                   clEnumValEnd));
+
+cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
+                       cl::desc("Do not verify input module"));
+
+static cl::opt<bool>
+EnableFPMAD("enable-fp-mad",
+  cl::desc("Enable less precise MAD instructions to be generated"),
+  cl::init(false));
+
+static cl::opt<bool>
+DisableFPElim("disable-fp-elim",
+  cl::desc("Disable frame pointer elimination optimization"),
+  cl::init(false));
+
+static cl::opt<llvm::FPOpFusion::FPOpFusionMode>
+FuseFPOps("fuse-fp-ops",
+  cl::desc("Enable aggresive formation of fused FP ops"),
+  cl::init(FPOpFusion::Standard),
+  cl::values(
+    clEnumValN(FPOpFusion::Fast, "fast",
+               "Fuse FP ops whenever profitable"),
+    clEnumValN(FPOpFusion::Standard, "standard",
+               "Only fuse 'blessed' FP ops."),
+    clEnumValN(FPOpFusion::Strict, "strict",
+               "Only fuse FP ops when the result won't be effected."),
+    clEnumValEnd));
+
+static cl::opt<bool>
+EnableUnsafeFPMath("enable-unsafe-fp-math",
+  cl::desc("Enable optimizations that may decrease FP precision"),
+  cl::init(false));
+
+static cl::opt<bool>
+EnableNoInfsFPMath("enable-no-infs-fp-math",
+  cl::desc("Enable FP math optimizations that assume no +-Infs"),
+  cl::init(false));
+
+static cl::opt<bool>
+EnableNoNaNsFPMath("enable-no-nans-fp-math",
+  cl::desc("Enable FP math optimizations that assume no NaNs"),
+  cl::init(false));
+
+static cl::opt<bool>
+EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math",
+  cl::Hidden,
+  cl::desc("Force codegen to assume rounding mode can change dynamically"),
+  cl::init(false));
+
+static cl::opt<bool>
+GenerateSoftFloatCalls("soft-float",
+  cl::desc("Generate software floating point library calls"),
+  cl::init(false));
+
+static cl::opt<llvm::FloatABI::ABIType>
+FloatABIForCalls("float-abi",
+  cl::desc("Choose float ABI type"),
+  cl::init(FloatABI::Default),
+  cl::values(
+    clEnumValN(FloatABI::Default, "default",
+               "Target default float ABI type"),
+    clEnumValN(FloatABI::Soft, "soft",
+               "Soft float ABI (implied by -soft-float)"),
+    clEnumValN(FloatABI::Hard, "hard",
+               "Hard float ABI (uses FP registers)"),
+    clEnumValEnd));
+
+static cl::opt<bool>
+DontPlaceZerosInBSS("nozero-initialized-in-bss",
+  cl::desc("Don't place zero-initialized symbols into bss section"),
+  cl::init(false));
+
+// In debug builds, make this default to true.
+#ifdef NDEBUG
+#define EMIT_DEBUG false
+#else
+#define EMIT_DEBUG true
+#endif
+static cl::opt<bool>
+EmitJitDebugInfo("jit-emit-debug",
+  cl::desc("Emit debug information to debugger"),
+  cl::init(EMIT_DEBUG));
+#undef EMIT_DEBUG
+
+static cl::opt<bool>
+EmitJitDebugInfoToDisk("jit-emit-debug-to-disk",
+  cl::Hidden,
+  cl::desc("Emit debug info objfiles to disk"),
+  cl::init(false));
+
+static cl::opt<bool>
+EnableGuaranteedTailCallOpt("tailcallopt",
+  cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."),
+  cl::init(false));
+
+static cl::opt<unsigned>
+OverrideStackAlignment("stack-alignment",
+  cl::desc("Override default stack alignment"),
+  cl::init(0));
+
+// --script is an alias, but cl::alias doesn't work correctly with cl::list.
+static cl::list<std::string>
+ArgLinkerScript("T",
+             cl::ZeroOrMore,
+             cl::desc("Linker script"),
+             cl::value_desc("file"));
+
+static cl::opt<std::string>
+TrapFuncName("trap-func", cl::Hidden,
+  cl::desc("Emit a call to trap function rather than a trap instruction"),
+  cl::init(""));
+
+static cl::opt<bool>
+SegmentedStacks("segmented-stacks",
+  cl::desc("Use segmented stacks if possible."),
+  cl::init(false));
+
 //===----------------------------------------------------------------------===//
 // Command Line Options
 // There are four kinds of command line options:
-//   1. input, (may be a file, such as -m and /tmp/XXXX.o.)
-//   2. scripting options, (represent a subset of link scripting language, such
-//      as --defsym.)
-//   3. and general options. (the rest of options)
+//   1. Bitcode option. Used to represent a bitcode.
+//   2. Attribute options. Attributes describes the input file after them. For
+//      example, --as-needed affects the input file after this option. Attribute
+//      options are not attributes. Attribute options are the options that is
+//      used to define a legal attribute.
+//   3. Scripting options, Used to represent a subset of link scripting
+//      language, such as --defsym.
+//   4. General options. (the rest of options)
+//===----------------------------------------------------------------------===//
+// Bitcode Options
+//===----------------------------------------------------------------------===//
+static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
+ArgBitcodeFilename("dB",
+              cl::desc("set default bitcode"),
+              cl::value_desc("bitcode"));
+
 //===----------------------------------------------------------------------===//
 // General Options
 //===----------------------------------------------------------------------===//
-static llvm::cl::opt<std::string>
-OptOutputFilename("o",
-                  llvm::cl::desc("Output filename"),
-                  llvm::cl::value_desc("filename"));
+static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
+ArgOutputFilename("o",
+               cl::desc("Output filename"),
+               cl::value_desc("filename"));
 
-static llvm::cl::opt<std::string>
-OptSysRoot("sysroot", llvm::cl::desc("Use directory as the location of the "
-                                     "sysroot, overriding the configure-time "
-                                     "default."),
-           llvm::cl::value_desc("directory"),
-           llvm::cl::ValueRequired);
+static cl::alias
+AliasOutputFilename("output",
+                    cl::desc("alias for -o"),
+                    cl::aliasopt(ArgOutputFilename));
 
-static llvm::cl::list<std::string>
-OptSearchDirList("L",
-                 llvm::cl::ZeroOrMore,
-                 llvm::cl::desc("Add path searchdir to the list of paths that "
-                                "mcld will search for archive libraries and "
-                                "mcld control scripts."),
-                 llvm::cl::value_desc("searchdir"),
-                 llvm::cl::Prefix);
+static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
+ArgSysRoot("sysroot",
+           cl::desc("Use directory as the location of the sysroot, overriding the configure-time default."),
+           cl::value_desc("directory"),
+           cl::ValueRequired);
 
-static llvm::cl::opt<std::string>
-OptSOName("soname",
-          llvm::cl::desc("Set internal name of shared library"),
-          llvm::cl::value_desc("name"));
+static cl::list<std::string, bool, llvm::cl::SearchDirParser>
+ArgSearchDirList("L",
+                 cl::ZeroOrMore,
+                 cl::desc("Add path searchdir to the list of paths that ld will search for archive libraries and ld control scripts."),
+                 cl::value_desc("searchdir"),
+                 cl::Prefix);
+
+static cl::alias
+ArgSearchDirListAlias("library-path",
+                      cl::desc("alias for -L"),
+                      cl::aliasopt(ArgSearchDirList));
+
+static cl::opt<bool>
+ArgTrace("t",
+         cl::desc("Print the names of the input files as ld processes them."));
+
+static cl::alias
+ArgTraceAlias("trace",
+              cl::desc("alias for -t"),
+              cl::aliasopt(ArgTrace));
+
+static cl::opt<int>
+ArgVerbose("verbose",
+           cl::init(-1),
+           cl::desc("Display the version number for ld and list the linker emulations supported."));
+
+static cl::opt<bool>
+ArgVersion("V",
+           cl::init(false),
+           cl::desc("Display the version number for MCLinker."));
+
+static cl::opt<int>
+ArgMaxErrorNum("error-limit",
+               cl::init(-1),
+               cl::desc("limits the maximum number of erros."));
+
+static cl::opt<int>
+ArgMaxWarnNum("warning-limit",
+               cl::init(-1),
+               cl::desc("limits the maximum number of warnings."));
+
+static cl::opt<std::string>
+ArgEntry("e",
+         cl::desc("Use entry as the explicit symbol for beginning execution of your program."),
+         cl::value_desc("entry"),
+         cl::ValueRequired);
+
+static cl::alias
+ArgEntryAlias("entry",
+              cl::desc("alias for -e"),
+              cl::aliasopt(ArgEntry));
+
+static cl::opt<bool>
+ArgBsymbolic("Bsymbolic",
+             cl::desc("Bind references within the shared library."),
+             cl::init(false));
+
+static cl::opt<bool>
+ArgBgroup("Bgroup",
+          cl::desc("Info the dynamic linker to perform lookups only inside the group."),
+          cl::init(false));
+
+static cl::opt<std::string>
+ArgSOName("soname",
+          cl::desc("Set internal name of shared library"),
+          cl::value_desc("name"));
+
+static cl::opt<bool>
+ArgNoUndefined("no-undefined",
+               cl::desc("Do not allow unresolved references"),
+               cl::init(false));
+
+static cl::opt<bool>
+ArgAllowMulDefs("allow-multiple-definition",
+                cl::desc("Allow multiple definition"),
+                cl::init(false));
+
+static cl::opt<bool>
+ArgEhFrameHdr("eh-frame-hdr",
+              cl::ZeroOrMore,
+              cl::desc("Request creation of \".eh_frame_hdr\" section and ELF \"PT_GNU_EH_FRAME\" segment header."),
+              cl::init(false));
+
+static cl::list<mcld::ZOption, bool, llvm::cl::parser<mcld::ZOption> >
+ArgZOptionList("z",
+               cl::ZeroOrMore,
+               cl::desc("The -z options for GNU ld compatibility."),
+               cl::value_desc("keyword"),
+               cl::Prefix);
+
+cl::opt<mcld::CodeGenFileType>
+ArgFileType("filetype", cl::init(mcld::CGFT_EXEFile),
+  cl::desc("Choose a file type (not all types are supported by all targets):"),
+  cl::values(
+       clEnumValN(mcld::CGFT_ASMFile, "asm",
+                  "Emit an assembly ('.s') file"),
+       clEnumValN(mcld::CGFT_OBJFile, "obj",
+                  "Emit a relocatable object ('.o') file"),
+       clEnumValN(mcld::CGFT_DSOFile, "dso",
+                  "Emit an dynamic shared object ('.so') file"),
+       clEnumValN(mcld::CGFT_EXEFile, "exe",
+                  "Emit a executable ('.exe') file"),
+       clEnumValN(mcld::CGFT_NULLFile, "null",
+                  "Emit nothing, for performance testing"),
+       clEnumValEnd));
+
+static cl::opt<bool>
+ArgShared("shared",
+          cl::desc("Create a shared library."),
+          cl::init(false));
+
+static cl::alias
+ArgSharedAlias("Bshareable",
+               cl::desc("alias for -shared"),
+               cl::aliasopt(ArgShared));
+
+static cl::opt<bool>
+ArgPIE("pie",
+       cl::desc("Emit a position-independent executable file"),
+       cl::init(false));
+
+static cl::opt<bool>
+ArgRelocatable("relocatable",
+               cl::desc("Generate relocatable output"),
+               cl::init(false));
+
+static cl::alias
+ArgRelocatableAlias("r",
+                    cl::desc("alias for --relocatable"),
+                    cl::aliasopt(ArgRelocatable));
+
+static cl::opt<Reloc::Model>
+ArgRelocModel("relocation-model",
+             cl::desc("Choose relocation model"),
+             cl::init(Reloc::Default),
+             cl::values(
+               clEnumValN(Reloc::Default, "default",
+                       "Target default relocation model"),
+               clEnumValN(Reloc::Static, "static",
+                       "Non-relocatable code"),
+               clEnumValN(Reloc::PIC_, "pic",
+                       "Fully relocatable, position independent code"),
+               clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+                       "Relocatable external references, non-relocatable code"),
+               clEnumValEnd));
+
+static cl::opt<bool>
+ArgFPIC("fPIC",
+        cl::desc("Set relocation model to pic. The same as -relocation-model=pic."),
+        cl::init(false));
+
+static cl::opt<std::string>
+ArgDyld("dynamic-linker",
+        cl::ZeroOrMore,
+        cl::desc("Set the name of the dynamic linker."),
+        cl::value_desc("Program"));
+
+namespace color {
+enum Color {
+  Never,
+  Always,
+  Auto
+};
+} // namespace of color
+
+static cl::opt<color::Color>
+ArgColor("color",
+  cl::value_desc("WHEN"),
+  cl::desc("Surround the result strings with the marker"),
+  cl::init(color::Auto),
+  cl::values(
+    clEnumValN(color::Never, "never",
+      "do not surround result strings"),
+    clEnumValN(color::Always, "always",
+      "always surround result strings, even the output is a plain file"),
+    clEnumValN(color::Auto, "auto",
+      "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));
 
 
-static llvm::cl::opt<bool>
-OptShared("shared",
-          llvm::cl::desc("Create a shared library."),
-          llvm::cl::init(false));
+static cl::opt<int>
+ArgGPSize("G",
+          cl::desc("Set the maximum size of objects to be optimized using GP"),
+          cl::init(8));
 
-static llvm::cl::opt<bool>
-OptBsymbolic("Bsymbolic",
-             llvm::cl::desc("Bind references within the shared library."),
-             llvm::cl::init(true));
+static bool ArgGenUnwindInfo;
 
-static llvm::cl::opt<std::string>
-OptDyld("dynamic-linker",
-        llvm::cl::desc("Set the name of the dynamic linker."),
-        llvm::cl::value_desc("Program"));
+static cl::opt<bool, true, cl::FalseParser>
+ArgNoGenUnwindInfoFlag("no-ld-generated-unwind-info",
+                       cl::ZeroOrMore, cl::location(ArgGenUnwindInfo),
+                       cl::desc("Don't create unwind info for linker generated"
+                                " sections to save size"),
+                       cl::init(false),
+                       cl::ValueDisallowed);
+static cl::opt<bool, true>
+ArgGenUnwindInfoFlag("ld-generated-unwind-info",
+                     cl::ZeroOrMore, cl::location(ArgGenUnwindInfo),
+                     cl::desc("Request creation of unwind info for linker"
+                              " generated code sections like PLT."),
+                     cl::init(true),
+                     cl::ValueDisallowed);
+/// @{
+/// @{
+/// @name FIXME: begin of unsupported options
+/// @}
+static cl::opt<bool>
+ArgGCSections("gc-sections",
+              cl::ZeroOrMore,
+              cl::desc("Enable garbage collection of unused input sections."),
+              cl::init(false));
 
-static llvm::cl::opt<bool>
-OptRelocatable("relocatable",
-               llvm::cl::desc("Generate relocatable output"),
-               llvm::cl::init(false));
+static cl::opt<bool>
+ArgNoGCSections("no-gc-sections",
+                cl::ZeroOrMore,
+                cl::desc("disable garbage collection of unused input sections."),
+                cl::init(false));
 
-static llvm::cl::alias
-OptRelocatableAlias("r",
-                    llvm::cl::desc("alias for --relocatable"),
-                    llvm::cl::aliasopt(OptRelocatable));
+namespace icf {
+enum Mode {
+  None,
+  All,
+  Safe
+};
+} // namespace of icf
 
-static llvm::cl::opt<bool>
-OptDefineCommon("d",
-                llvm::cl::ZeroOrMore,
-                llvm::cl::desc("Define common symbol"),
-                llvm::cl::init(false));
+static cl::opt<icf::Mode>
+ArgICF("icf",
+       cl::ZeroOrMore,
+       cl::desc("Identical Code Folding"),
+       cl::init(icf::None),
+       cl::values(
+         clEnumValN(icf::None, "none",
+           "do not perform cold folding"),
+         clEnumValN(icf::All, "all",
+           "always preform cold folding"),
+         clEnumValN(icf::Safe, "safe",
+           "Folds ctors, dtors and functions whose pointers are definitely not taken."),
+         clEnumValEnd));
 
-static llvm::cl::alias
-OptDefineCommonAlias1("dc",
-                      llvm::cl::desc("alias for -d"),
-                      llvm::cl::aliasopt(OptDefineCommon));
+// FIXME: add this to target options?
+static cl::opt<bool>
+ArgFIXCA8("fix-cortex-a8",
+          cl::desc("Enable Cortex-A8 Thumb-2 branch erratum fix"),
+          cl::init(false));
 
-static llvm::cl::alias
-OptDefineCommonAlias2("dp",
-                      llvm::cl::desc("alias for -d"),
-                      llvm::cl::aliasopt(OptDefineCommon));
+static cl::opt<bool>
+ArgExportDynamic("export-dynamic",
+                 cl::desc("Export all dynamic symbols"),
+                 cl::init(false));
 
+static cl::alias
+ArgExportDynamicAlias("E",
+                      cl::desc("alias for --export-dynamic"),
+                      cl::aliasopt(ArgExportDynamic));
 
-//===----------------------------------------------------------------------===//
-// Inputs
-//===----------------------------------------------------------------------===//
-static llvm::cl::list<std::string>
-OptInputObjectFiles(llvm::cl::Positional,
-                    llvm::cl::desc("[input object files]"),
-                    llvm::cl::OneOrMore);
+static cl::opt<std::string>
+ArgEmulation("m",
+             cl::ZeroOrMore,
+             cl::desc("Set GNU linker emulation"),
+             cl::value_desc("emulation"),
+             cl::Prefix);
 
-static llvm::cl::list<std::string>
-OptNameSpecList("l",
-                llvm::cl::ZeroOrMore,
-                llvm::cl::desc("Add the archive or object file specified by "
-                               "namespec to the list of files to link."),
-                llvm::cl::value_desc("namespec"),
-                llvm::cl::Prefix);
+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"));
+
+static cl::list<std::string>
+ArgExcludeLIBS("exclude-libs",
+               cl::CommaSeparated,
+               cl::desc("Exclude libraries from automatic export"),
+               cl::value_desc("lib1,lib2,..."));
+
+static cl::opt<std::string>
+ArgBuildID("build-id",
+           cl::desc("Request creation of \".note.gnu.build-id\" ELF note section."),
+           cl::value_desc("style"),
+           cl::ValueOptional);
+
+static cl::opt<std::string>
+ArgForceUndefined("u",
+                  cl::desc("Force symbol to be undefined in the output file"),
+                  cl::value_desc("symbol"));
+
+static cl::alias
+ArgForceUndefinedAlias("undefined",
+                       cl::desc("alias for -u"),
+                       cl::aliasopt(ArgForceUndefined));
+
+static cl::opt<std::string>
+ArgVersionScript("version-script",
+                 cl::desc("Version script."),
+                 cl::value_desc("Version script"));
+
+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>
+ArgUseGold("use-gold",
+          cl::desc("GCC/collect2 compatibility: uses ld.gold.  Ignored"),
+          cl::init(false));
+
+static cl::opt<bool>
+ArgUseMCLD("use-mcld",
+          cl::desc("GCC/collect2 compatibility: uses ld.mcld.  Ignored"),
+          cl::init(false));
+
+static cl::opt<bool>
+ArgUseLD("use-ld",
+          cl::desc("GCC/collect2 compatibility: uses ld.bfd.  Ignored"),
+          cl::init(false));
+
+static cl::opt<bool>
+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));
+
+static cl::list<std::string>
+ArgPlugin("plugin",
+          cl::desc("Load a plugin library."),
+          cl::value_desc("plugin"));
+
+static cl::list<std::string>
+ArgPluginOpt("plugin-opt",
+             cl::desc("	Pass an option to the plugin."),
+             cl::value_desc("option"));
+
+static cl::opt<bool>
+ArgSVR4Compatibility("Qy",
+                    cl::desc("This option is ignored for SVR4 compatibility"),
+                    cl::init(false));
+
+static cl::list<std::string>
+ArgY("Y",
+     cl::desc("Add path to the default library search path"),
+     cl::value_desc("default-search-path"));
+
+static cl::opt<bool>
+ArgARMCompatibility("p",
+                    cl::desc("Ignore for ARM backward compatibility"),
+                    cl::init(false));
+
+/// @{
+/// @name FIXME: end of unsupported options
+/// @}
+
+static cl::opt<bool>
+ArgNoWarnMismatch("no-warn-mismatch",
+                  cl::desc("Allow linking together mismatched input files."),
+                  cl::init(false));
+
+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));
+
+static cl::opt<bool>
+ArgPrintMap("M",
+            cl::desc("Print a link map to the standard output."),
+            cl::init(false));
+
+static cl::alias
+ArgPrintMapAlias("print-map",
+                 cl::desc("alias for -M"),
+                 cl::aliasopt(ArgPrintMap));
+
+static bool ArgFatalWarnings;
+
+static cl::opt<bool, true, cl::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>
+ArgFatalWarningsFlag("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));
+
+namespace format {
+enum Format {
+  Binary,
+  Unknown // decided by triple
+};
+} // namespace of format
+
+static cl::opt<format::Format>
+ArgFormat("b",
+  cl::value_desc("Format"),
+  cl::desc("set input format"),
+  cl::init(format::Unknown),
+  cl::values(
+    clEnumValN(format::Binary, "binary",
+      "read in binary machine code."),
+    clEnumValEnd));
+
+static cl::alias
+ArgFormatAlias("format",
+               cl::desc("alias for -b"),
+               cl::aliasopt(ArgFormat));
+
+static cl::opt<format::Format>
+ArgOFormat("oformat",
+  cl::value_desc("Format"),
+  cl::desc("set output format"),
+  cl::init(format::Unknown),
+  cl::values(
+    clEnumValN(format::Binary, "binary",
+      "generate binary machine code."),
+    clEnumValEnd));
+
+static cl::opt<bool>
+ArgDefineCommon("d",
+                cl::ZeroOrMore,
+                cl::desc("Define common symbol"),
+                cl::init(false));
+
+static cl::alias
+ArgDefineCommonAlias1("dc",
+                      cl::ZeroOrMore,
+                      cl::desc("alias for -d"),
+                      cl::aliasopt(ArgDefineCommon));
+
+static cl::alias
+ArgDefineCommonAlias2("dp",
+                      cl::ZeroOrMore,
+                      cl::desc("alias for -d"),
+                      cl::aliasopt(ArgDefineCommon));
 
 //===----------------------------------------------------------------------===//
 // Scripting Options
 //===----------------------------------------------------------------------===//
-static llvm::cl::list<std::string>
-OptWrapList("wrap",
-            llvm::cl::ZeroOrMore,
-            llvm::cl::desc("Use a wrap function fo symbol."),
-            llvm::cl::value_desc("symbol"));
+static cl::list<std::string>
+ArgWrapList("wrap",
+            cl::ZeroOrMore,
+            cl::desc("Use a wrap function fo symbol."),
+            cl::value_desc("symbol"));
 
-static llvm::cl::list<std::string>
-OptPortableList("portable",
-                llvm::cl::ZeroOrMore,
-                llvm::cl::desc("Use a portable function to symbol."),
-                llvm::cl::value_desc("symbol"));
+static cl::list<std::string>
+ArgPortList("portable",
+            cl::ZeroOrMore,
+            cl::desc("Use a portable function fo symbol."),
+            cl::value_desc("symbol"));
+
+static cl::list<std::string>
+ArgAddressMapList("section-start",
+                  cl::ZeroOrMore,
+                  cl::desc("Locate a output section at the given absolute address"),
+                  cl::value_desc("Set address of section"),
+                  cl::Prefix);
+
+static cl::opt<unsigned long long>
+ArgBssSegAddr("Tbss",
+              cl::desc("Set the address of the bss segment"),
+              cl::init(-1U));
+
+static cl::opt<unsigned long long>
+ArgDataSegAddr("Tdata",
+               cl::desc("Set the address of the data segment"),
+               cl::init(-1U));
+
+static cl::opt<unsigned long long>
+ArgTextSegAddr("Ttext",
+               cl::desc("Set the address of the text segment"),
+               cl::init(-1U));
+
+static cl::alias
+ArgTextSegAddrAlias("Ttext-segment",
+                    cl::desc("alias for -Ttext"),
+                    cl::aliasopt(ArgTextSegAddr));
 
 //===----------------------------------------------------------------------===//
-// Helper Functions
+// non-member functions
 //===----------------------------------------------------------------------===//
-// Override "mcld -version"
-static void MCLDVersionPrinter() {
-  llvm::raw_ostream &os = llvm::outs();
-  os << "mcld (The MCLinker Project, http://mclinker.googlecode.com/):\n"
-     << "  version: " MCLD_VERSION "\n"
-     << "  Default target: " << DEFAULT_TARGET_TRIPLE_STRING << "\n";
+/// GetOutputStream - get the output stream.
+static mcld::ToolOutputFile *GetOutputStream(const char* pTargetName,
+                                             Triple::OSType pOSType,
+                                             mcld::CodeGenFileType pFileType,
+                                             const mcld::sys::fs::Path& pInputFilename,
+                                             mcld::sys::fs::Path& pOutputFilename)
+{
+  if (pOutputFilename.empty()) {
+    if (0 == pInputFilename.native().compare("-"))
+      pOutputFilename.assign("-");
+    else {
+      switch(pFileType) {
+      case mcld::CGFT_ASMFile: {
+        if (0 == pInputFilename.native().compare("-"))
+          pOutputFilename.assign("_out");
+        else
+          pOutputFilename.assign(pInputFilename.stem().native());
 
-  os << "\n";
+        if (0 == strcmp(pTargetName, "c"))
+          pOutputFilename.native() += ".cbe.c";
+        else if (0 == strcmp(pTargetName, "cpp"))
+          pOutputFilename.native() += ".cpp";
+        else
+          pOutputFilename.native() += ".s";
+      }
+      break;
 
-  os << "LLVM (http://llvm.org/):\n";
+      case mcld::CGFT_OBJFile: {
+        if (0 == pInputFilename.native().compare("-"))
+          pOutputFilename.assign("_out");
+        else
+          pOutputFilename.assign(pInputFilename.stem().native());
 
-  return;
+        if (pOSType == Triple::Win32)
+          pOutputFilename.native() += ".obj";
+        else
+          pOutputFilename.native() += ".o";
+      }
+      break;
+
+      case mcld::CGFT_PARTIAL: {
+        if (Triple::Win32 == pOSType) {
+          if (0 == pInputFilename.native().compare("-"))
+            pOutputFilename.assign("_out");
+          else
+            pOutputFilename.assign(pInputFilename.stem().native());
+          pOutputFilename.native() += ".obj";
+        }
+        else
+          pOutputFilename.assign("a.out");
+      }
+      break;
+
+      case mcld::CGFT_DSOFile: {
+        if (Triple::Win32 == pOSType) {
+          if (0 == pInputFilename.native().compare("-"))
+            pOutputFilename.assign("_out");
+          else
+            pOutputFilename.assign(pInputFilename.stem().native());
+          pOutputFilename.native() += ".dll";
+        }
+        else
+          pOutputFilename.assign("a.out");
+      }
+      break;
+
+      case mcld::CGFT_EXEFile: {
+        if (Triple::Win32 == pOSType) {
+          if (0 == pInputFilename.native().compare("-"))
+            pOutputFilename.assign("_out");
+          else
+            pOutputFilename.assign(pInputFilename.stem().native());
+          pOutputFilename.native() += ".exe";
+        }
+        else
+          pOutputFilename.assign("a.out");
+      }
+      break;
+
+      case mcld::CGFT_NULLFile:
+        break;
+      default:
+        llvm::report_fatal_error("Unknown output file type.\n");
+      } // end of switch
+    } // end of ! pInputFilename == "-"
+  } // end of if empty pOutputFilename
+
+  mcld::FileHandle::Permission permission;
+  switch (pFileType) {
+  default: assert(0 && "Unknown file type");
+  case mcld::CGFT_ASMFile:
+  case mcld::CGFT_OBJFile:
+  case mcld::CGFT_PARTIAL:
+    permission = mcld::FileHandle::Permission(0x644);
+    break;
+  case mcld::CGFT_DSOFile:
+  case mcld::CGFT_EXEFile:
+  case mcld::CGFT_BINARY:
+  case mcld::CGFT_NULLFile:
+    permission = mcld::FileHandle::Permission(0x755);
+    break;
+  }
+
+  // Open the file.
+  mcld::ToolOutputFile* result_output =
+    new mcld::ToolOutputFile(pOutputFilename,
+                             mcld::FileHandle::ReadWrite |
+                               mcld::FileHandle::Create |
+                               mcld::FileHandle::Truncate,
+                             permission);
+
+  return result_output;
 }
 
-#define DEFAULT_OUTPUT_PATH "a.out"
-static inline
-std::string DetermineOutputFilename(const std::string &pOutputPath) {
-  if (!pOutputPath.empty()) {
-    return pOutputPath;
+/// ParseProgName - Parse program name
+/// This function simplifies cross-compiling by reading triple from the program
+/// name. For example, if the program name is `arm-linux-eabi-ld.mcld', we can
+/// get the triple is arm-linux-eabi by the program name.
+static std::string ParseProgName(const char *progname)
+{
+  static const char *suffixes[] = {
+    "ld",
+    "ld.mcld",
+  };
+
+  std::string ProgName(mcld::sys::fs::Path(progname).stem().native());
+
+  for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
+    if (ProgName == suffixes[i])
+      return std::string();
   }
 
-  // User does't specify the value to -o
-  if (OptInputObjectFiles.size() > 1) {
-    llvm::errs() << "Use " DEFAULT_OUTPUT_PATH " for output file!\n";
-    return DEFAULT_OUTPUT_PATH;
+  StringRef ProgNameRef(ProgName);
+  StringRef Prefix;
+
+  for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
+    if (!ProgNameRef.endswith(suffixes[i]))
+      continue;
+
+    StringRef::size_type LastComponent = ProgNameRef.rfind('-',
+      ProgNameRef.size() - strlen(suffixes[i]));
+    if (LastComponent == StringRef::npos)
+      continue;
+    StringRef Prefix = ProgNameRef.slice(0, LastComponent);
+    std::string IgnoredError;
+    if (!mcld::TargetRegistry::lookupTarget(Prefix, IgnoredError))
+      continue;
+    return Prefix.str();
   }
-
-  // There's only one input file
-  const std::string &input_path = OptInputObjectFiles[0];
-  llvm::SmallString<200> output_path(input_path);
-
-  llvm::error_code err = llvm::sys::fs::make_absolute(output_path);
-  if (llvm::errc::success != err) {
-    llvm::errs() << "Failed to determine the absolute path of `" << input_path
-                 << "'! (detail: " << err.message() << ")\n";
-    return "";
-  }
-
-  llvm::sys::path::remove_filename(output_path);
-  llvm::sys::path::append(output_path, "a.out");
-
-  return output_path.c_str();
+  return std::string();
 }
 
-static inline
-bool ConfigLinker(Linker &pLinker, const std::string &pOutputFilename) {
-  LinkerConfig* config = NULL;
+static Triple ParseEmulation(const std::string& pEmulation)
+{
+  Triple result = StringSwitch<Triple>(pEmulation)
+    .Case("armelf_linux_eabi", Triple("arm", "", "linux", "gnueabi"))
+    .Case("elf_i386",          Triple("i386", "", "", "gnu"))
+    .Case("elf_x86_64",        Triple("x86_64", "", "", "gnu"))
+    .Case("elf32_x86_64",      Triple("x86_64", "", "", "gnux32"))
+    .Case("elf_i386_fbsd",     Triple("i386", "", "freebsd", "gnu"))
+    .Case("elf_x86_64_fbsd",   Triple("x86_64", "", "freebsd", "gnu"))
+    .Case("elf32ltsmip",       Triple("mipsel", "", "", "gnu"))
+    .Default(Triple());
 
-#ifdef TARGET_BUILD
-  config = new (std::nothrow) DefaultLinkerConfig();
-#else
-  config = new (std::nothrow) GeneralLinkerConfig(OptTargetTriple);
+  if (result.getArch()        == Triple::UnknownArch &&
+      result.getOS()          == Triple::UnknownOS &&
+      result.getEnvironment() == Triple::UnknownEnvironment)
+    mcld::error(mcld::diag::err_invalid_emulation) << pEmulation << "\n";
+
+  return result;
+}
+
+static bool ShouldColorize()
+{
+   const char* term = getenv("TERM");
+   return term && (0 != strcmp(term, "dumb"));
+}
+
+static bool ProcessLinkerOptionsFromCommand(mcld::LinkerScript& pScript,
+                                            mcld::LinkerConfig& pConfig)
+{
+  // -----  Set up General Options  ----- //
+  // set up colorize
+  switch (ArgColor) {
+    case color::Never:
+      pConfig.options().setColor(false);
+    break;
+    case color::Always:
+      pConfig.options().setColor(true);
+    break;
+    case color::Auto:
+      bool color_option = ShouldColorize() &&
+                 llvm::sys::Process::FileDescriptorIsDisplayed(STDOUT_FILENO);
+      pConfig.options().setColor(color_option);
+    break;
+  }
+
+  mcld::outs().setColor(pConfig.options().color());
+  mcld::errs().setColor(pConfig.options().color());
+
+  // 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);
+  }
+
+  // add all linker scripts
+  cl::list<std::string>::iterator sp;
+  cl::list<std::string>::iterator spEnd = ArgLinkerScript.end();
+  for (sp = ArgLinkerScript.begin(); sp != spEnd; ++sp) {
+    pConfig.options().getScriptList().push_back(*sp);
+  }
+
+  pConfig.options().setGenUnwindInfo(ArgGenUnwindInfo);
+
+  // --fatal-warnings
+  // pConfig.options().setFatalWarnings(ArgFatalWarnings);
+
+  // -shared or -pie
+  if (true == ArgShared || true == ArgPIE) {
+    ArgFileType = mcld::CGFT_DSOFile;
+  }
+  else if (true == ArgRelocatable) {
+    ArgFileType = mcld::CGFT_PARTIAL;
+  }
+  else if (format::Binary == ArgOFormat) {
+    ArgFileType = mcld::CGFT_BINARY;
+  }
+
+  // -b [input-format], --format=[input-format]
+  if (format::Binary == ArgFormat)
+    pConfig.options().setBinaryInput();
+
+  // -V
+  if (ArgVersion) {
+    mcld::outs() << "MCLinker - "
+                 << mcld::LinkerConfig::version()
+                 << "\n";
+  }
+
+  // set up sysroot
+  if (!ArgSysRoot.empty()) {
+    if (exists(ArgSysRoot) && is_directory(ArgSysRoot))
+      pScript.setSysroot(ArgSysRoot);
+  }
+
+  // add all search directories
+  cl::list<std::string>::iterator sd;
+  cl::list<std::string>::iterator sdEnd = ArgSearchDirList.end();
+  for (sd=ArgSearchDirList.begin(); sd!=sdEnd; ++sd) {
+    if (!pScript.directories().insert(*sd)) {
+      // FIXME: need a warning function
+      errs() << "WARNING: can not open search directory `-L"
+             << *sd
+             << "'.\n";
+    }
+  }
+
+  pConfig.options().setPIE(ArgPIE);
+  pConfig.options().setTrace(ArgTrace);
+  pConfig.options().setVerbose(ArgVerbose);
+  pConfig.options().setMaxErrorNum(ArgMaxErrorNum);
+  pConfig.options().setMaxWarnNum(ArgMaxWarnNum);
+  pConfig.options().setBsymbolic(ArgBsymbolic);
+  pConfig.options().setBgroup(ArgBgroup);
+  pConfig.options().setDyld(ArgDyld);
+  pConfig.options().setNoUndefined(ArgNoUndefined);
+  pConfig.options().setMulDefs(ArgAllowMulDefs);
+  pConfig.options().setEhFrameHdr(ArgEhFrameHdr);
+  pConfig.options().setNMagic(ArgNMagic);
+  pConfig.options().setOMagic(ArgOMagic);
+  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);
+  pConfig.options().setPrintMap(ArgPrintMap);
+  pConfig.options().setGCSections(ArgGCSections);
+  pConfig.options().setGPSize(ArgGPSize);
+  if (ArgNoWarnMismatch)
+    pConfig.options().setWarnMismatch(false);
+  else
+    pConfig.options().setWarnMismatch(true);
+
+  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 entry point from -e
+  pScript.setEntry(ArgEntry);
+
+  // set up rename map, for --wrap
+  cl::list<std::string>::iterator wname;
+  cl::list<std::string>::iterator wnameEnd = ArgWrapList.end();
+  for (wname = ArgWrapList.begin(); wname != wnameEnd; ++wname) {
+    bool exist = false;
+
+    // add wname -> __wrap_wname
+    mcld::StringEntry<llvm::StringRef>* to_wrap =
+                                     pScript.renameMap().insert(*wname, exist);
+
+    std::string to_wrap_str = "__wrap_" + *wname;
+    to_wrap->setValue(to_wrap_str);
+
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *wname << to_wrap_str;
+
+    // add __real_wname -> wname
+    std::string from_real_str = "__real_" + *wname;
+    mcld::StringEntry<llvm::StringRef>* from_real =
+                              pScript.renameMap().insert(from_real_str, exist);
+    from_real->setValue(*wname);
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
+  } // end of for
+
+  // set up rename map, for --portable
+  cl::list<std::string>::iterator pname;
+  cl::list<std::string>::iterator pnameEnd = ArgPortList.end();
+  for (pname = ArgPortList.begin(); pname != pnameEnd; ++pname) {
+    bool exist = false;
+
+    // add pname -> pname_portable
+    mcld::StringEntry<llvm::StringRef>* to_port =
+                                     pScript.renameMap().insert(*pname, exist);
+
+    std::string to_port_str = *pname + "_portable";
+    to_port->setValue(to_port_str);
+
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *pname << to_port_str;
+
+    // add __real_pname -> pname
+    std::string from_real_str = "__real_" + *pname;
+    mcld::StringEntry<llvm::StringRef>* from_real =
+                              pScript.renameMap().insert(from_real_str, exist);
+
+    from_real->setValue(*pname);
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *pname << from_real_str;
+  } // end of for
+
+  // add -z options
+  cl::list<mcld::ZOption>::iterator zOpt;
+  cl::list<mcld::ZOption>::iterator zOptEnd = ArgZOptionList.end();
+  for (zOpt = ArgZOptionList.begin(); zOpt != zOptEnd; ++zOpt) {
+    pConfig.options().addZOption(*zOpt);
+  }
+
+  // set up icf mode
+  switch (ArgICF) {
+    case icf::None:
+      break;
+    case icf::All:
+    case icf::Safe:
+    default:
+      mcld::warning(mcld::diag::warn_unsupported_option) << ArgICF.ArgStr;
+      break;
+  }
+
+  if (ArgFIXCA8) {
+    mcld::warning(mcld::diag::warn_unsupported_option) << ArgFIXCA8.ArgStr;
+  }
+
+  // add address mappings
+  // -Ttext
+  if (-1U != ArgTextSegAddr) {
+    bool exist = false;
+    mcld::StringEntry<uint64_t>* text_mapping =
+                                   pScript.addressMap().insert(".text", exist);
+    text_mapping->setValue(ArgTextSegAddr);
+  }
+  // -Tdata
+  if (-1U != ArgDataSegAddr) {
+    bool exist = false;
+    mcld::StringEntry<uint64_t>* data_mapping =
+                                   pScript.addressMap().insert(".data", exist);
+    data_mapping->setValue(ArgDataSegAddr);
+  }
+  // -Tbss
+  if (-1U != ArgBssSegAddr) {
+    bool exist = false;
+    mcld::StringEntry<uint64_t>* bss_mapping =
+                                    pScript.addressMap().insert(".bss", exist);
+    bss_mapping->setValue(ArgBssSegAddr);
+  }
+  // --section-start SECTION=ADDRESS
+  for (cl::list<std::string>::iterator
+       it = ArgAddressMapList.begin(), ie = ArgAddressMapList.end();
+       it != ie; ++it) {
+    // FIXME: Add a cl::parser
+    size_t pos = (*it).find_last_of('=');
+    llvm::StringRef script(*it);
+    uint64_t address = 0x0;
+    script.substr(pos + 1).getAsInteger(0, address);
+    bool exist = false;
+    mcld::StringEntry<uint64_t>* addr_mapping =
+                     pScript.addressMap().insert(script.substr(0, pos), exist);
+    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;
+}
+
+int main(int argc, char* argv[])
+{
+  sys::PrintStackTraceOnErrorSignal();
+
+  LLVMContext &Context = getGlobalContext();
+  llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
+
+  // Initialize targets first, so that --version shows registered targets.
+  InitializeAllTargets();
+  InitializeAllAsmPrinters();
+  InitializeAllAsmParsers();
+  InitializeAllTargetMCs();
+  mcld::InitializeAllTargets();
+  mcld::InitializeAllLinkers();
+  mcld::InitializeAllEmulations();
+  mcld::InitializeAllDiagnostics();
+
+  cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
+
+#ifdef ENABLE_UNITTEST
+  if (UnitTest) {
+    return unit_test( argc, argv );
+  }
 #endif
-  if (config == NULL) {
-    llvm::errs() << "Out of memory when create the linker configuration!\n";
-    return false;
+
+  // Load the module to be compiled...
+  std::auto_ptr<llvm::Module> M;
+
+  // Load the module to be linked...
+  mcld::LinkerScript LDScript;
+  mcld::Module LDIRModule(LDScript);
+  mcld::LinkerConfig LDConfig;
+
+  // Process the linker input from the command line
+  if (!ProcessLinkerOptionsFromCommand(LDScript, LDConfig)) {
+    errs() << argv[0] << ": failed to process linker options from command line!\n";
+    return 1;
   }
 
-  // Setup the configuration accroding to the command line options.
+  if (ArgBitcodeFilename.empty() &&
+      (mcld::CGFT_DSOFile != ArgFileType &&
+       mcld::CGFT_EXEFile != ArgFileType &&
+       mcld::CGFT_PARTIAL != ArgFileType &&
+       mcld::CGFT_BINARY  != ArgFileType)) {
+    // If the file is not given, forcefully read from stdin
+    if (ArgVerbose >= 0) {
+      errs() << "** The bitcode/llvm asm file is not given. Read from stdin.\n"
+             << "** Specify input bitcode/llvm asm file by\n\n"
+             << "          llvm-mcld -dB [the bitcode/llvm asm]\n\n";
+    }
 
-  // 1. Set up soname.
-  if (!OptSOName.empty()) {
-    config->setSOName(OptSOName);
+    ArgBitcodeFilename.assign("-");
+  }
+
+  if (!ArgBitcodeFilename.empty()) {
+    SMDiagnostic Err;
+    M.reset(ParseIRFile(ArgBitcodeFilename.native(), Err, Context));
+
+    if (M.get() == 0) {
+      Err.print(argv[0], errs());
+      errs() << "** Failed to to the given bitcode/llvm asm file '"
+             << ArgBitcodeFilename.native() << "'. **\n";
+      return 1;
+    }
+  }
+  else {
+    // If here, output must be dynamic shared object (mcld::CGFT_DSOFile) and
+    // executable file (mcld::CGFT_EXEFile).
+    M.reset(new Module("Empty Module", Context));
+  }
+  Module &mod = *M.get();
+
+  // If we are supposed to override the target triple, do so now.
+  Triple TheTriple;
+  if (!TargetTriple.empty()) {
+    // 1. Use the triple from command.
+    TheTriple.setTriple(TargetTriple);
+    mod.setTargetTriple(TargetTriple);
+  } else if (!mod.getTargetTriple().empty()) {
+    // 2. Use the triple in the input Module.
+    TheTriple.setTriple(mod.getTargetTriple());
   } else {
-    config->setSOName(pOutputFilename);
-  }
-
-  // 2. If given, set up sysroot.
-  if (!OptSysRoot.empty()) {
-    config->setSysRoot(OptSysRoot);
-  }
-
-  // 3. If given, set up dynamic linker path.
-  if (!OptDyld.empty()) {
-    config->setDyld(OptDyld);
-  }
-
-  // 4. If given, set up wrapped symbols.
-  llvm::cl::list<std::string>::iterator wrap, wrap_end = OptWrapList.end();
-  for (wrap = OptWrapList.begin(); wrap != wrap_end; ++wrap) {
-    config->addWrap(*wrap);
-  }
-
-  // 5. If given, set up portable symbols.
-  llvm::cl::list<std::string>::iterator portable, portable_end = OptPortableList.end();
-  for (portable = OptPortableList.begin(); portable != portable_end; ++portable) {
-    config->addPortable(*portable);
-  }
-
-  // 6. if given, set up search directories.
-  llvm::cl::list<std::string>::iterator sdir, sdir_end = OptSearchDirList.end();
-  for (sdir = OptSearchDirList.begin(); sdir != sdir_end; ++sdir) {
-    config->addSearchDir(*sdir);
-  }
-
-  // 7. Set up output's type.
-  config->setShared(OptShared);
-
-  // 8. Set up -Bsymbolic.
-  config->setBsymbolic(OptBsymbolic);
-
-  // 9. Set up -d (define common symbols)
-  config->setDefineCommon(OptDefineCommon);
-
-  Linker::ErrorCode result = pLinker.config(*config);
-  if (Linker::kSuccess != result) {
-    llvm::errs() << "Failed to configure the linker! (detail: "
-                 << Linker::GetErrorString(result) << ")\n";
-    return false;
-  }
-
-  return true;
-}
-
-static inline
-bool PrepareInputOutput(Linker &pLinker, const std::string &pOutputPath) {
-  // -----  Set output  ----- //
-
-  // FIXME: Current MCLinker requires one to set up output before inputs. The
-  // constraint will be relaxed in the furture.
-  Linker::ErrorCode result = pLinker.setOutput(pOutputPath);
-
-  if (Linker::kSuccess != result) {
-    llvm::errs() << "Failed to open the output file! (detail: "
-                 << pOutputPath << ": "
-                 << Linker::GetErrorString(result) << ")\n";
-    return false;
-  }
-
-  // -----  Set inputs  ----- //
-  llvm::cl::list<std::string>::iterator file_it = OptInputObjectFiles.begin();
-  llvm::cl::list<std::string>::iterator lib_it  = OptNameSpecList.begin();
-
-  llvm::cl::list<std::string>::iterator file_begin = OptInputObjectFiles.begin();
-  llvm::cl::list<std::string>::iterator lib_begin = OptNameSpecList.begin();
-  llvm::cl::list<std::string>::iterator file_end = OptInputObjectFiles.end();
-  llvm::cl::list<std::string>::iterator lib_end = OptNameSpecList.end();
-
-  unsigned lib_pos = 0, file_pos = 0;
-  while (true) {
-    if (lib_it != lib_end) {
-      lib_pos = OptNameSpecList.getPosition(lib_it - lib_begin);
+    std::string ProgNameTriple = ParseProgName(argv[0]);
+    if (!ProgNameTriple.empty()) {
+      // 3. Use the triple from the program name prefix.
+      TheTriple.setTriple(ProgNameTriple);
+      mod.setTargetTriple(ProgNameTriple);
     } else {
-      lib_pos = 0;
-    }
-
-    if (file_it != file_end) {
-      file_pos = OptInputObjectFiles.getPosition(file_it - file_begin);
-    } else {
-      file_pos = 0;
-    }
-
-    if ((file_pos != 0) && ((lib_pos == 0) || (file_pos < lib_pos))) {
-      result = pLinker.addObject(*file_it);
-      if (Linker::kSuccess != result) {
-        llvm::errs() << "Failed to open the input file! (detail: " << *file_it
-                     << ": " << Linker::GetErrorString(result) << ")\n";
-        return false;
-      }
-      ++file_it;
-    } else if ((lib_pos != 0) && ((file_pos == 0) || (lib_pos < file_pos))) {
-      result = pLinker.addNameSpec(*lib_it);
-      if (Linker::kSuccess != result) {
-        llvm::errs() << "Failed to open the namespec! (detail: " << *lib_it
-                     << ": " << Linker::GetErrorString(result) << ")\n";
-        return false;
-      }
-      ++lib_it;
-    } else {
-      break; // we're done with the list
+      // 4. Use the default target triple.
+      TheTriple.setTriple(mcld::sys::getDefaultTargetTriple());
     }
   }
 
-  return true;
+  // If a specific emulation was requested, apply it now.
+  if (!ArgEmulation.empty()) {
+    Triple EmulationTriple = ParseEmulation(ArgEmulation);
+    if (EmulationTriple.getArch() != Triple::UnknownArch)
+      TheTriple.setArch(EmulationTriple.getArch());
+    if (EmulationTriple.getOS() != Triple::UnknownOS)
+      TheTriple.setOS(EmulationTriple.getOS());
+    if (EmulationTriple.getEnvironment() != Triple::UnknownEnvironment)
+      TheTriple.setEnvironment(EmulationTriple.getEnvironment());
+  }
+
+  // Get the target specific parser.
+  std::string error;
+  const llvm::Target *LLVMTarget = llvm::TargetRegistry::lookupTarget(MArch,
+                                                                      TheTriple,
+                                                                      error);
+  if (NULL == LLVMTarget) {
+    errs() << argv[0] << ": " << error;
+    return 1;
+  }
+
+  // Allocate target machine.  First, check whether the user has explicitly
+  // specified an architecture to compile for. If so we have to look it up by
+  // name, because it might be a backend that has no mapping to a target triple.
+  const mcld::Target *MCLDTarget = mcld::TargetRegistry::lookupTarget(MArch,
+                                                                     TheTriple,
+                                                                     error);
+  if (NULL == MCLDTarget) {
+    errs() << argv[0] << ": " << error;
+    return 1;
+  }
+
+
+  LDConfig.targets().setTriple(TheTriple);
+
+  // Package up features to be passed to target/subtarget
+  std::string FeaturesStr;
+  if (MAttrs.size()) {
+    SubtargetFeatures Features;
+    for (unsigned i = 0; i != MAttrs.size(); ++i)
+      Features.AddFeature(MAttrs[i]);
+    FeaturesStr = Features.getString();
+  }
+
+  CodeGenOpt::Level OLvl = CodeGenOpt::Default;
+  switch (OptLevel) {
+  default:
+    errs() << argv[0] << ": invalid optimization level.\n";
+    return 1;
+  case ' ': break;
+  case '0': OLvl = CodeGenOpt::None; break;
+  case '1': OLvl = CodeGenOpt::Less; break;
+  case '2': OLvl = CodeGenOpt::Default; break;
+  case '3': OLvl = CodeGenOpt::Aggressive; break;
+  }
+
+  // set -fPIC
+  if (ArgFPIC)
+    ArgRelocModel = Reloc::PIC_;
+
+  TargetOptions Options;
+  Options.LessPreciseFPMADOption = EnableFPMAD;
+  Options.NoFramePointerElim = DisableFPElim;
+  Options.AllowFPOpFusion = FuseFPOps;
+  Options.UnsafeFPMath = EnableUnsafeFPMath;
+  Options.NoInfsFPMath = EnableNoInfsFPMath;
+  Options.NoNaNsFPMath = EnableNoNaNsFPMath;
+  Options.HonorSignDependentRoundingFPMathOption =
+      EnableHonorSignDependentRoundingFPMath;
+  Options.UseSoftFloat = GenerateSoftFloatCalls;
+  if (FloatABIForCalls != FloatABI::Default)
+    Options.FloatABIType = FloatABIForCalls;
+  Options.NoZerosInBSS = DontPlaceZerosInBSS;
+  Options.JITEmitDebugInfo = EmitJitDebugInfo;
+  Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk;
+  Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
+  Options.StackAlignmentOverride = OverrideStackAlignment;
+  Options.TrapFuncName = TrapFuncName;
+  Options.EnableSegmentedStacks = SegmentedStacks;
+
+  OwningPtr<llvm::TargetMachine>
+    TM(LLVMTarget->createTargetMachine(TheTriple.getTriple(),
+                                       MCPU, FeaturesStr, Options,
+                                       ArgRelocModel, CMModel, OLvl));
+
+  std::auto_ptr<mcld::MCLDTargetMachine> target_machine(
+          MCLDTarget->createTargetMachine(TheTriple.getTriple(),
+                                        *LLVMTarget,
+                                        *TM.get()));
+
+  assert(target_machine.get() && "Could not allocate target machine!");
+  mcld::MCLDTargetMachine &TheTargetMachine = *target_machine.get();
+
+  LDConfig.targets().setTargetCPU(MCPU);
+  LDConfig.targets().setTargetFeatureString(FeaturesStr);
+
+  TheTargetMachine.getTM().setMCUseLoc(false);
+  TheTargetMachine.getTM().setMCUseCFI(false);
+
+  // FIXME: Move the initialization of LineInfo to mcld::Linker when we
+  // finish LineInfo's implementation.
+  OwningPtr<mcld::DiagnosticLineInfo>
+    diag_line_info(MCLDTarget->createDiagnosticLineInfo(*MCLDTarget,
+                                                       TheTriple.getTriple()));
+
+  mcld::getDiagnosticEngine().setLineInfo(*diag_line_info.take());
+
+  // Figure out where we are going to send the output...
+  OwningPtr<mcld::ToolOutputFile>
+  Out(GetOutputStream(MCLDTarget->name(),
+                      TheTriple.getOS(),
+                      ArgFileType,
+                      ArgBitcodeFilename,
+                      ArgOutputFilename));
+  if (!Out) {
+    // FIXME: show some error message pls.
+    return 1;
+  }
+
+  // Build up all of the passes that we want to do to the module.
+  PassManager PM;
+
+  // Add the data layout from the target machine, if it exists, or the module.
+  if (const DataLayout *DL = TheTargetMachine.getTM().getDataLayout())
+    PM.add(new DataLayout(*DL));
+   else
+    PM.add(new DataLayout(&mod));
+
+  // Override default to generate verbose assembly.
+  TheTargetMachine.getTM().setAsmVerbosityDefault(true);
+
+  {
+    // Ask the target to add backend passes as necessary.
+    if(TheTargetMachine.addPassesToEmitFile(PM,
+                                            *Out,
+                                            ArgFileType,
+                                            OLvl,
+                                            LDIRModule,
+                                            LDConfig,
+                                            NoVerify)) {
+      errs() << argv[0] << ": target does not support generation of this"
+             << " file type!\n";
+      return 1;
+    }
+
+    // Before executing passes, print the final values of the LLVM options.
+    cl::PrintOptionValues();
+
+    PM.run(mod);
+  }
+
+  if (mcld::getDiagnosticEngine().getPrinter()->getNumErrors())
+    return 1;
+
+  // Declare success.
+  Out->keep();
+  return 0;
 }
-
-static inline bool LinkFiles(Linker &pLinker) {
-  Linker::ErrorCode result = pLinker.link();
-  if (Linker::kSuccess != result) {
-    llvm::errs() << "Failed to linking! (detail: "
-                 << Linker::GetErrorString(result) << "\n";
-    return false;
-  }
-  return true;
-}
-
-int main(int argc, char** argv) {
-  llvm::cl::SetVersionPrinter(MCLDVersionPrinter);
-  llvm::cl::ParseCommandLineOptions(argc, argv);
-  init::Initialize();
-
-  std::string OutputFilename = DetermineOutputFilename(OptOutputFilename);
-  if (OutputFilename.empty()) {
-    return EXIT_FAILURE;
-  }
-
-  Linker linker;
-  if (!ConfigLinker(linker, OutputFilename)) {
-    return EXIT_FAILURE;
-  }
-
-  if (!PrepareInputOutput(linker, OutputFilename)) {
-    return EXIT_FAILURE;
-  }
-
-  if (!LinkFiles(linker)) {
-    return EXIT_FAILURE;
-  }
-
-  return EXIT_SUCCESS;
-}
-
diff --git a/unittests/BinTreeTest.cpp b/unittests/BinTreeTest.cpp
index 5d2cd0a..e436752 100644
--- a/unittests/BinTreeTest.cpp
+++ b/unittests/BinTreeTest.cpp
@@ -124,47 +124,46 @@
 
 TEST_F( BinTreeTest, DFSIterator_BasicTraversal)
 {
-  int a = 111;
+  int a = 111, b = 10, c = 9, d = 8, e = 7;
   BinaryTree<int>::iterator pos = m_pTestee->root();
 
   m_pTestee->join<InputTree::Inclusive>(pos,a);
   pos.move<InputTree::Inclusive>();
-  m_pTestee->join<InputTree::Positional>(pos,10);
-  m_pTestee->join<InputTree::Inclusive>(pos,9);
+  m_pTestee->join<InputTree::Positional>(pos,b);
+  m_pTestee->join<InputTree::Inclusive>(pos,c);
   pos.move<InputTree::Inclusive>();
-  m_pTestee->join<InputTree::Positional>(pos,8);
-  m_pTestee->join<InputTree::Inclusive>(pos,7);
+  m_pTestee->join<InputTree::Positional>(pos,d);
+  m_pTestee->join<InputTree::Inclusive>(pos,e);
 
   BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
   BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
 
   ASSERT_EQ(111, **dfs_it);
   ++dfs_it;
-  ASSERT_EQ(9, **dfs_it);
+  EXPECT_EQ(9, **dfs_it);
   ++dfs_it;
-  ASSERT_EQ(7, **dfs_it);
+  EXPECT_EQ(7, **dfs_it);
   ++dfs_it;
-  ASSERT_EQ(8, **dfs_it);
+  EXPECT_EQ(8, **dfs_it);
   ++dfs_it;
-  ASSERT_EQ(10, **dfs_it);
+  EXPECT_EQ(10, **dfs_it);
   ++dfs_it;
-  ASSERT_TRUE( dfs_it ==  dfs_end);
-  BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
-  BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
+  EXPECT_TRUE( dfs_it ==  dfs_end);
 }
 
 TEST_F( BinTreeTest, DFSIterator_RightMostTree)
 {
+  int a = 0, b = 1, c = 2, d = 3, e = 4;
   BinaryTree<int>::iterator pos = m_pTestee->root();
-  m_pTestee->join<InputTree::Inclusive>(pos,0);
+  m_pTestee->join<InputTree::Inclusive>(pos,a);
   pos.move<InputTree::Inclusive>();
-  m_pTestee->join<InputTree::Positional>(pos,1);
+  m_pTestee->join<InputTree::Positional>(pos,b);
   pos.move<InputTree::Positional>();
-  m_pTestee->join<InputTree::Positional>(pos,2);
+  m_pTestee->join<InputTree::Positional>(pos,c);
   pos.move<InputTree::Positional>();
-  m_pTestee->join<InputTree::Positional>(pos,3);
+  m_pTestee->join<InputTree::Positional>(pos,d);
   pos.move<InputTree::Positional>();
-  m_pTestee->join<InputTree::Positional>(pos,4);
+  m_pTestee->join<InputTree::Positional>(pos,e);
 
   BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
   BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
@@ -199,16 +198,16 @@
 
 TEST_F( BinTreeTest, BFSIterator_BasicTraversal)
 {
-  int a = 111;
+  int a = 111, b = 10, c = 9, d = 8, e = 7;
   BinaryTree<int>::iterator pos = m_pTestee->root();
 
   m_pTestee->join<InputTree::Inclusive>(pos,a);
   pos.move<InputTree::Inclusive>();
-  m_pTestee->join<InputTree::Positional>(pos,10);
-  m_pTestee->join<InputTree::Inclusive>(pos,9);
+  m_pTestee->join<InputTree::Positional>(pos,b);
+  m_pTestee->join<InputTree::Inclusive>(pos,c);
   pos.move<InputTree::Inclusive>();
-  m_pTestee->join<InputTree::Positional>(pos,8);
-  m_pTestee->join<InputTree::Inclusive>(pos,7);
+  m_pTestee->join<InputTree::Positional>(pos,d);
+  m_pTestee->join<InputTree::Inclusive>(pos,e);
 
   BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
   BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
@@ -230,16 +229,17 @@
 
 TEST_F( BinTreeTest, BFSIterator_RightMostTree)
 {
+  int a = 0, b = 1, c = 2, d = 3, e = 4;
   BinaryTree<int>::iterator pos = m_pTestee->root();
-  m_pTestee->join<InputTree::Inclusive>(pos,0);
+  m_pTestee->join<InputTree::Inclusive>(pos,a);
   pos.move<InputTree::Inclusive>();
-  m_pTestee->join<InputTree::Positional>(pos,1);
+  m_pTestee->join<InputTree::Positional>(pos,b);
   pos.move<InputTree::Positional>();
-  m_pTestee->join<InputTree::Positional>(pos,2);
+  m_pTestee->join<InputTree::Positional>(pos,c);
   pos.move<InputTree::Positional>();
-  m_pTestee->join<InputTree::Positional>(pos,3);
+  m_pTestee->join<InputTree::Positional>(pos,d);
   pos.move<InputTree::Positional>();
-  m_pTestee->join<InputTree::Positional>(pos,4);
+  m_pTestee->join<InputTree::Positional>(pos,e);
 
   BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
   BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
@@ -274,17 +274,18 @@
 
 TEST_F( BinTreeTest, TreeIterator)
 {
+  int a = 0, b = 1, c = 2, d = 3, e = 4, f = 5;
   BinaryTree<int>::iterator pos = m_pTestee->root();
-  m_pTestee->join<InputTree::Inclusive>(pos,0);
+  m_pTestee->join<InputTree::Inclusive>(pos,a);
   pos.move<InputTree::Inclusive>();
-  m_pTestee->join<InputTree::Positional>(pos,1);
+  m_pTestee->join<InputTree::Positional>(pos,b);
   pos.move<InputTree::Positional>();
-  m_pTestee->join<InputTree::Inclusive>(pos,2);
-  m_pTestee->join<InputTree::Positional>(pos,5);
+  m_pTestee->join<InputTree::Inclusive>(pos,c);
+  m_pTestee->join<InputTree::Positional>(pos,f);
   pos.move<InputTree::Inclusive>();
-  m_pTestee->join<InputTree::Positional>(pos,3);
+  m_pTestee->join<InputTree::Positional>(pos,d);
   pos.move<InputTree::Positional>();
-  m_pTestee->join<InputTree::Positional>(pos,4);
+  m_pTestee->join<InputTree::Positional>(pos,e);
 
   BinaryTree<int>::iterator it = m_pTestee->begin();
   BinaryTree<int>::iterator end = m_pTestee->end();
diff --git a/unittests/DirIteratorTest.cpp b/unittests/DirIteratorTest.cpp
index f319172..13472ac 100644
--- a/unittests/DirIteratorTest.cpp
+++ b/unittests/DirIteratorTest.cpp
@@ -6,9 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/Directory.h"
+#include <mcld/Support/Directory.h>
 #include "DirIteratorTest.h"
-#include "errno.h"
+#include <errno.h>
 
 using namespace mcld;
 using namespace mcld::sys::fs;
diff --git a/unittests/ELFBinaryReaderTest.cpp b/unittests/ELFBinaryReaderTest.cpp
new file mode 100644
index 0000000..7792717
--- /dev/null
+++ b/unittests/ELFBinaryReaderTest.cpp
@@ -0,0 +1,64 @@
+//===- ELFBinaryReaderTest.cpp --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFBinaryReader.h>
+#include <mcld/Module.h>
+#include <mcld/LinkerScript.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/GeneralOptions.h>
+#include <mcld/MC/Input.h>
+
+#include "ELFBinaryReaderTest.h"
+
+using namespace mcld;
+using namespace mcld::test;
+
+
+// Constructor can do set-up work for all test here.
+ELFBinaryReaderTest::ELFBinaryReaderTest()
+{
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+ELFBinaryReaderTest::~ELFBinaryReaderTest()
+{
+}
+
+// SetUp() will be called immediately before each test.
+void ELFBinaryReaderTest::SetUp()
+{
+}
+
+// TearDown() will be called immediately after each test.
+void ELFBinaryReaderTest::TearDown()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Testcases
+//===----------------------------------------------------------------------===//
+TEST_F( ELFBinaryReaderTest, is_myformat) {
+  LinkerScript script;
+  Module module("test", script);
+  LinkerConfig config;
+  IRBuilder builder(module, config);
+  ELFBinaryReader *reader = new ELFBinaryReader(builder, config);
+
+  Input input("test.bin");
+
+  bool doContinue = false;
+  config.options().setBinaryInput();
+  ASSERT_TRUE(reader->isMyFormat(input, doContinue));
+
+  config.options().setBinaryInput(false);
+  ASSERT_FALSE(reader->isMyFormat(input, doContinue));
+
+  delete reader;
+}
+
diff --git a/unittests/ELFBinaryReaderTest.h b/unittests/ELFBinaryReaderTest.h
new file mode 100644
index 0000000..a9ea042
--- /dev/null
+++ b/unittests/ELFBinaryReaderTest.h
@@ -0,0 +1,39 @@
+//===- ELFBinaryReaderTest.h ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELFBINARYREADER_TEST_H
+#define MCLD_ELFBINARYREADER_TEST_H
+
+#include <gtest.h>
+
+namespace mcld {
+class ELFBinaryReader;
+
+namespace test {
+
+class ELFBinaryReaderTest : public ::testing::Test
+{
+public:
+  // Constructor can do set-up work for all test here.
+  ELFBinaryReaderTest();
+
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~ELFBinaryReaderTest();
+
+  // SetUp() will be called immediately before each test.
+  virtual void SetUp();
+
+  // TearDown() will be called immediately after each test.
+  virtual void TearDown();
+};
+
+} // namespace of test
+} // namespace of mcld
+
+#endif
+
diff --git a/unittests/ELFReaderTest.cpp b/unittests/ELFReaderTest.cpp
index ddbc6d5..1ff2a31 100644
--- a/unittests/ELFReaderTest.cpp
+++ b/unittests/ELFReaderTest.cpp
@@ -8,12 +8,14 @@
 //===----------------------------------------------------------------------===//
 #include <cstdio>
 
+#include <llvm/ADT/StringRef.h>
 #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/MC/Input.h>
 #include <mcld/Support/Path.h>
+#include <mcld/Support/MemoryArea.h>
 #include <../lib/Target/X86/X86LDBackend.h>
 #include <../lib/Target/X86/X86GNUInfo.h>
 
@@ -66,11 +68,10 @@
 
   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();
+  llvm::StringRef region = m_pInput->memArea()->request(m_pInput->fileOffset(),
+                                                        hdr_size);
+  const char* ELF_hdr = region.begin();
   bool shdr_result = m_pELFReader->readSectionHeaders(*m_pInput, ELF_hdr);
-  m_pInput->memArea()->release(region);
   ASSERT_TRUE(shdr_result);
 }
 
@@ -109,22 +110,18 @@
   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());
+  llvm::StringRef 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());
+  llvm::StringRef strtab_region = m_pInput->memArea()->request(
+      m_pInput->fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
+  const char* strtab = strtab_region.begin();
   bool result = m_pELFReader->readSymbols(*m_pInput, *m_pIRBuilder,
-                                          *symtab_region, strtab);
+                                          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();
@@ -134,12 +131,11 @@
 
   uint64_t offset = m_pInput->fileOffset() + (*rs)->offset();
   uint64_t size = (*rs)->size();
-  MemoryRegion* region = mem->request(offset, size);
+  llvm::StringRef 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);
+  ASSERT_TRUE(m_pELFReader->readRela(*m_pInput, **rs, region));
 
   const RelocData::RelocationListType &rRelocs =
                           (*rs)->getRelocData()->getRelocationList();
@@ -158,7 +154,8 @@
 }
 
 TEST_F( ELFReaderTest, is_my_format ) {
-  ASSERT_TRUE( m_pELFObjReader->isMyFormat(*m_pInput) );
+  bool doContinue;
+  ASSERT_TRUE( m_pELFObjReader->isMyFormat(*m_pInput, doContinue) );
 }
 
 
diff --git a/unittests/ELFReaderTest.h b/unittests/ELFReaderTest.h
index 58ec470..abe99b1 100644
--- a/unittests/ELFReaderTest.h
+++ b/unittests/ELFReaderTest.h
@@ -19,7 +19,7 @@
 #include <mcld/MC/InputBuilder.h>
 
 namespace mcld {
-  class ELFReader<64, true>;
+  template<> class ELFReader<64, true>;
 } // namespace for mcld
 
 namespace mcldtest
diff --git a/unittests/FragmentRefTest.cpp b/unittests/FragmentRefTest.cpp
index 599289d..881cdb8 100644
--- a/unittests/FragmentRefTest.cpp
+++ b/unittests/FragmentRefTest.cpp
@@ -14,6 +14,7 @@
 #include <mcld/Support/FileHandle.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/Path.h>
+#include <llvm/ADT/StringRef.h>
 
 using namespace mcld;
 using namespace mcld::sys::fs;
@@ -48,18 +49,18 @@
   MemoryAreaFactory* areaFactory = new MemoryAreaFactory(1);
   MemoryArea* area = areaFactory->produce(path, FileHandle::ReadWrite);
 
-  MemoryRegion* region = area->request(0, 4096);
-  RegionFragment *frag = new RegionFragment(*region);
+  llvm::StringRef region = area->request(0, 4096);
+  RegionFragment *frag = new RegionFragment(region);
   FragmentRef *ref = FragmentRef::Create(*frag, 0x0);
 
-  ASSERT_EQ('H', region->getBuffer()[0]);
-  ASSERT_TRUE(4096 == region->size());
-  ASSERT_EQ('H', frag->getRegion().getBuffer()[0]);
+  ASSERT_EQ('H', region.data()[0]);
+  ASSERT_TRUE(4096 == region.size());
+  ASSERT_EQ('H', frag->getRegion().data()[0]);
   ASSERT_TRUE(4096 == frag->getRegion().size());
   ASSERT_EQ(frag, ref->frag());
-  ASSERT_EQ('H', static_cast<RegionFragment*>(ref->frag())->getRegion().getBuffer()[0]);
+  ASSERT_EQ('H', static_cast<RegionFragment*>(ref->frag())->getRegion().data()[0]);
   ASSERT_TRUE(4096 == static_cast<RegionFragment*>(ref->frag())->getRegion().size());
-  ASSERT_EQ('H', ref->deref()[0]);
+  //ASSERT_EQ('H', ref->deref()[0]);
 
   ASSERT_TRUE(RegionFragment::classof(frag));
 
diff --git a/unittests/GraphTest.cpp b/unittests/GraphTest.cpp
new file mode 100644
index 0000000..38fc0d4
--- /dev/null
+++ b/unittests/GraphTest.cpp
@@ -0,0 +1,340 @@
+//===- GraphTest.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "GraphTest.h"
+#include <mcld/ADT/GraphLite/Digraph.h>
+#include <mcld/ADT/GraphLite/ListDigraph.h>
+
+using namespace mcld;
+using namespace mcld::test;
+using namespace mcld::graph;
+
+// Constructor can do set-up work for all test here.
+GraphTest::GraphTest()
+{
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+GraphTest::~GraphTest()
+{
+}
+
+// SetUp() will be called immediately before each test.
+void GraphTest::SetUp()
+{
+}
+
+// TearDown() will be called immediately after each test.
+void GraphTest::TearDown()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Testcases
+//===----------------------------------------------------------------------===//
+TEST_F(GraphTest, list_digraph_add_n_erase_nodes_1)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ASSERT_TRUE(NULL == u1->first_in);
+  ASSERT_TRUE(NULL == u1->first_out);
+  ASSERT_TRUE(u2   == u1->prev);
+  ASSERT_TRUE(NULL == u1->next);
+
+  ASSERT_TRUE(NULL == u2->first_in);
+  ASSERT_TRUE(NULL == u2->first_out);
+  ASSERT_TRUE(u3   == u2->prev);
+  ASSERT_TRUE(u1   == u2->next);
+
+  ASSERT_TRUE(NULL == u3->first_in);
+  ASSERT_TRUE(NULL == u3->first_out);
+  ASSERT_TRUE(u2   == u3->next);
+  ASSERT_TRUE(NULL == u3->prev);
+
+  ListDigraph::Node* head = NULL;
+  graph.getHead(head);
+  ASSERT_TRUE(head == u3);
+
+  graph.erase(*u2);
+
+  ASSERT_TRUE(NULL == u1->first_in);
+  ASSERT_TRUE(NULL == u1->first_out);
+  ASSERT_TRUE(u3   == u1->prev);
+  ASSERT_TRUE(NULL == u1->next);
+
+  ASSERT_TRUE(NULL == u3->first_in);
+  ASSERT_TRUE(NULL == u3->first_out);
+  ASSERT_TRUE(u1   == u3->next);
+  ASSERT_TRUE(NULL == u3->prev);
+
+  ASSERT_TRUE(NULL == u2->first_in);
+  ASSERT_TRUE(NULL == u2->first_out);
+  ASSERT_TRUE(NULL == u2->prev);
+  ASSERT_TRUE(NULL == u2->next);
+
+  graph.getHead(head);
+  ASSERT_TRUE(head == u3);
+}
+
+TEST_F(GraphTest, list_digraph_add_n_erase_nodes_2)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ASSERT_TRUE(NULL == u1->first_in);
+  ASSERT_TRUE(NULL == u1->first_out);
+  ASSERT_TRUE(u2   == u1->prev);
+  ASSERT_TRUE(NULL == u1->next);
+
+  ASSERT_TRUE(NULL == u2->first_in);
+  ASSERT_TRUE(NULL == u2->first_out);
+  ASSERT_TRUE(u3   == u2->prev);
+  ASSERT_TRUE(u1   == u2->next);
+
+  ASSERT_TRUE(NULL == u3->first_in);
+  ASSERT_TRUE(NULL == u3->first_out);
+  ASSERT_TRUE(u2   == u3->next);
+  ASSERT_TRUE(NULL == u3->prev);
+
+  ListDigraph::Node* head = NULL;
+  graph.getHead(head);
+  ASSERT_TRUE(head == u3);
+
+  graph.erase(*u1);
+
+  ASSERT_TRUE(NULL == u1->first_in);
+  ASSERT_TRUE(NULL == u1->first_out);
+  ASSERT_TRUE(NULL == u1->prev);
+  ASSERT_TRUE(NULL == u1->next);
+
+  ASSERT_TRUE(NULL == u2->first_in);
+  ASSERT_TRUE(NULL == u2->first_out);
+  ASSERT_TRUE(u3   == u2->prev);
+  ASSERT_TRUE(NULL == u2->next);
+
+  ASSERT_TRUE(NULL == u3->first_in);
+  ASSERT_TRUE(NULL == u3->first_out);
+  ASSERT_TRUE(u2   == u3->next);
+  ASSERT_TRUE(NULL == u3->prev);
+
+  graph.getHead(head);
+  ASSERT_TRUE(head == u3);
+}
+
+TEST_F(GraphTest, list_digraph_add_n_erase_nodes_3)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ASSERT_TRUE(NULL == u1->first_in);
+  ASSERT_TRUE(NULL == u1->first_out);
+  ASSERT_TRUE(u2   == u1->prev);
+  ASSERT_TRUE(NULL == u1->next);
+
+  ASSERT_TRUE(NULL == u2->first_in);
+  ASSERT_TRUE(NULL == u2->first_out);
+  ASSERT_TRUE(u3   == u2->prev);
+  ASSERT_TRUE(u1   == u2->next);
+
+  ASSERT_TRUE(NULL == u3->first_in);
+  ASSERT_TRUE(NULL == u3->first_out);
+  ASSERT_TRUE(u2   == u3->next);
+  ASSERT_TRUE(NULL == u3->prev);
+
+  ListDigraph::Node* head = NULL;
+  graph.getHead(head);
+  ASSERT_TRUE(head == u3);
+
+  graph.erase(*u3);
+
+  ASSERT_TRUE(NULL == u3->first_in);
+  ASSERT_TRUE(NULL == u3->first_out);
+  ASSERT_TRUE(NULL == u3->prev);
+  ASSERT_TRUE(NULL == u3->next);
+
+  ASSERT_TRUE(NULL == u1->first_in);
+  ASSERT_TRUE(NULL == u1->first_out);
+  ASSERT_TRUE(u2   == u1->prev);
+  ASSERT_TRUE(NULL == u1->next);
+
+  ASSERT_TRUE(NULL == u2->first_in);
+  ASSERT_TRUE(NULL == u2->first_out);
+  ASSERT_TRUE(u1   == u2->next);
+  ASSERT_TRUE(NULL == u2->prev);
+
+  graph.getHead(head);
+  ASSERT_TRUE(head == u2);
+
+}
+
+TEST_F(GraphTest, list_digraph_add_arcs_1)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ListDigraph::Arc* a1 = graph.addArc(*u1, *u2);
+  ListDigraph::Arc* a2 = graph.addArc(*u2, *u3);
+  ListDigraph::Arc* a3 = graph.addArc(*u3, *u1);
+
+  ASSERT_TRUE(u1 == a1->source && u2 == a1->target);
+  ASSERT_TRUE(u2 == a2->source && u3 == a2->target);
+  ASSERT_TRUE(u3 == a3->source && u1 == a3->target);
+
+  ASSERT_TRUE(u1->first_in == a3 && u1->first_out == a1);
+  ASSERT_TRUE(u2->first_in == a1 && u2->first_out == a2);
+  ASSERT_TRUE(u3->first_in == a2 && u3->first_out == a3);
+}
+
+TEST_F(GraphTest, list_digraph_add_arcs_2)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ListDigraph::Arc* a1 = graph.addArc(*u1, *u1);
+  ListDigraph::Arc* a2 = graph.addArc(*u1, *u2);
+  ListDigraph::Arc* a3 = graph.addArc(*u1, *u3);
+
+  ASSERT_TRUE(u1 == a1->source && u1 == a1->target);
+  ASSERT_TRUE(u1 == a2->source && u2 == a2->target);
+  ASSERT_TRUE(u1 == a3->source && u3 == a3->target);
+
+  ASSERT_TRUE(u1->first_in == a1 && u1->first_out == a3);
+  ASSERT_TRUE(u2->first_in == a2 && u2->first_out == NULL);
+  ASSERT_TRUE(u3->first_in == a3 && u3->first_out == NULL);
+}
+
+TEST_F(GraphTest, list_digraph_add_n_erase_arcs_1)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ListDigraph::Arc* a1 = graph.addArc(*u1, *u2);
+  ListDigraph::Arc* a2 = graph.addArc(*u2, *u3);
+  ListDigraph::Arc* a3 = graph.addArc(*u3, *u1);
+
+  graph.erase(*a2);
+  
+  ASSERT_TRUE(u1 == a1->source && u2 == a1->target);
+  ASSERT_TRUE(u3 == a3->source && u1 == a3->target);
+
+  // remove from the fan-out list
+  ASSERT_TRUE(u2->first_in == a1 && u2->first_out == NULL);
+
+  // remove from the fan-in list
+  ASSERT_TRUE(u3->first_in == NULL && u3->first_out == a3);
+
+  // put into free list
+  ASSERT_TRUE(NULL == a2->next_in);
+}
+
+
+TEST_F(GraphTest, list_digraph_add_n_erase_arcs_2)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ListDigraph::Arc* a1 = graph.addArc(*u1, *u2);
+  ListDigraph::Arc* a2 = graph.addArc(*u2, *u3);
+  ListDigraph::Arc* a3 = graph.addArc(*u3, *u1);
+
+  graph.erase(*a1);
+  
+  ASSERT_TRUE(u2 == a2->source && u3 == a2->target);
+  ASSERT_TRUE(u3 == a3->source && u1 == a3->target);
+
+  // remove from the fan-out list
+  ASSERT_TRUE(u1->first_in == a3 && u1->first_out == NULL);
+
+  // remove from the fan-in list
+  ASSERT_TRUE(u2->first_in == NULL && u2->first_out == a2);
+
+  // put into free list
+  ASSERT_TRUE(NULL == a1->next_in);
+}
+
+TEST_F(GraphTest, list_digraph_add_n_erase_arcs_3)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ListDigraph::Arc* a1 = graph.addArc(*u1, *u2);
+  ListDigraph::Arc* a2 = graph.addArc(*u2, *u3);
+  ListDigraph::Arc* a3 = graph.addArc(*u3, *u1);
+
+  graph.erase(*a3);
+  
+  ASSERT_TRUE(u1 == a1->source && u2 == a1->target);
+  ASSERT_TRUE(u2 == a2->source && u3 == a2->target);
+
+  // remove from the fan-out list
+  ASSERT_TRUE(u1->first_in == NULL && u1->first_out == a1);
+
+  // remove from the fan-in list
+  ASSERT_TRUE(u3->first_in == a2 && u3->first_out == NULL);
+
+  // put into free list
+  ASSERT_TRUE(NULL == a3->next_in);
+}
+
+TEST_F(GraphTest, list_digraph_add_n_erase_arcs_4)
+{
+  ListDigraph graph;
+
+  ListDigraph::Node* u1 = graph.addNode();
+  ListDigraph::Node* u2 = graph.addNode();
+  ListDigraph::Node* u3 = graph.addNode();
+
+  ListDigraph::Arc* a1 = graph.addArc(*u1, *u1);
+  graph.addArc(*u1, *u2);
+  graph.addArc(*u1, *u3);
+
+  graph.erase(*u1);
+
+  ASSERT_TRUE(u2->first_in == NULL);
+  ASSERT_TRUE(u3->first_in == NULL);
+  ASSERT_TRUE(a1->next_in == NULL);
+
+}
+
+TEST_F(GraphTest, api_test)
+{
+  Digraph graph;
+
+  Digraph::Node node = graph.addNode();
+  graph.addNode();
+  graph.addNode();
+  graph.addNode();
+
+  ASSERT_EQ(4, graph.numOfNodes());
+  ASSERT_EQ(0, graph.numOfArcs());
+}
diff --git a/unittests/GraphTest.h b/unittests/GraphTest.h
new file mode 100644
index 0000000..a71276b
--- /dev/null
+++ b/unittests/GraphTest.h
@@ -0,0 +1,38 @@
+//===- GraphTest.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_GRAPH_TEST_H
+#define MCLD_GRAPH_TEST_H
+
+#include <gtest.h>
+
+
+namespace mcld {
+namespace test {
+
+class GraphTest : public ::testing::Test
+{
+public:
+  // Constructor can do set-up work for all test here.
+  GraphTest();
+
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~GraphTest();
+
+  // SetUp() will be called immediately before each test.
+  virtual void SetUp();
+
+  // TearDown() will be called immediately after each test.
+  virtual void TearDown();
+};
+
+} // namespace of test
+} // namespace of mcld
+
+#endif
+
diff --git a/unittests/HashTableTest.cpp b/unittests/HashTableTest.cpp
index 532c307..fe67e95 100644
--- a/unittests/HashTableTest.cpp
+++ b/unittests/HashTableTest.cpp
@@ -8,8 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "HashTableTest.h"
-#include "mcld/ADT/HashEntry.h"
-#include "mcld/ADT/HashTable.h"
+#include <mcld/ADT/HashEntry.h>
+#include <mcld/ADT/HashTable.h>
 #include <cstdlib>
 
 using namespace std;
diff --git a/unittests/LDSymbolTest.cpp b/unittests/LDSymbolTest.cpp
index c414fa0..e0e681d 100644
--- a/unittests/LDSymbolTest.cpp
+++ b/unittests/LDSymbolTest.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "mcld/LD/LDSymbol.h"
+#include <mcld/LD/LDSymbol.h>
 #include "LDSymbolTest.h"
 
 using namespace mcld;
diff --git a/unittests/LinearAllocatorTest.cpp b/unittests/LinearAllocatorTest.cpp
index fea135f..d38684a 100644
--- a/unittests/LinearAllocatorTest.cpp
+++ b/unittests/LinearAllocatorTest.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "LinearAllocatorTest.h"
-#include "mcld/Support/Allocators.h"
+#include <mcld/Support/Allocators.h>
 
 using namespace mcld;
 using namespace mcldtest;
diff --git a/unittests/LinkerTest.cpp b/unittests/LinkerTest.cpp
index 16c6448..479bbb9 100644
--- a/unittests/LinkerTest.cpp
+++ b/unittests/LinkerTest.cpp
@@ -14,6 +14,7 @@
 #include <mcld/IRBuilder.h>
 #include <mcld/Linker.h>
 #include <mcld/LinkerConfig.h>
+#include <mcld/LinkerScript.h>
 
 #include <mcld/Support/Path.h>
 
@@ -63,7 +64,7 @@
   //   builder.CreateInput("./test.o");
 
   if (linker.link(module, builder))
-    linker.emit("./test.so");
+    linker.emit(module, "./test.so");
 
   Finalize();
 }
@@ -123,7 +124,7 @@
   builder.ReadInput("crtend", crtend);
 
   if (linker.link(module, builder)) {
-    linker.emit("libplasma.so"); ///< -o libplasma.so
+    linker.emit(module, "libplasma.so"); ///< -o libplasma.so
   }
 
   Finalize();
@@ -181,7 +182,7 @@
   builder1.ReadInput("crtend", crtend);
 
   if (linker.link(module1, builder1)) {
-    linker.emit("libplasma.once.so"); ///< -o libplasma.so
+    linker.emit(module1, "libplasma.once.so"); ///< -o libplasma.so
   }
 
   Finalize();
@@ -224,7 +225,7 @@
   builder2.ReadInput("crtend", crtend);
 
   if (linker.link(module2, builder2)) {
-    linker.emit("libplasma.twice.so"); ///< -o libplasma.exe
+    linker.emit(module2, "libplasma.twice.so"); ///< -o libplasma.exe
   }
 
   Finalize();
@@ -278,7 +279,7 @@
   builder1->ReadInput("crtend", crtend);
 
   if (linker.link(module1, *builder1)) {
-    linker.emit("libplasma.once.so"); ///< -o libplasma.so
+    linker.emit(module1, "libplasma.once.so"); ///< -o libplasma.so
   }
 
   // Can not delete builder until emit the output. Dynamic string table
@@ -326,7 +327,7 @@
   builder2->ReadInput("crtend", crtend);
 
   if (linker.link(module2, *builder2)) {
-    linker.emit("libplasma.twice.so"); ///< -o libplasma.exe
+    linker.emit(module2, "libplasma.twice.so"); ///< -o libplasma.exe
   }
 
   delete builder2;
@@ -467,7 +468,7 @@
  builder.AddRelocation(*rel_text, llvm::ELF::R_ARM_PLT32, *z1gv, 0x4);
 
   if (linker.link(module, builder)) {
-    linker.emit("libgotplt.so"); ///< -o libgotplt.so
+    linker.emit(module, "libgotplt.so"); ///< -o libgotplt.so
   }
 
   Finalize();
diff --git a/unittests/MCRegionFragmentTest.cpp b/unittests/MCRegionFragmentTest.cpp
index 842ddf9..7d6c3b9 100644
--- a/unittests/MCRegionFragmentTest.cpp
+++ b/unittests/MCRegionFragmentTest.cpp
@@ -9,9 +9,9 @@
 
 #include "MCRegionFragmentTest.h"
 
-#include "mcld/MC/MCRegionFragment.h"
-#include "mcld/Support/MemoryAreaFactory.h"
-#include "mcld/Support/Path.h"
+#include <mcld/MC/MCRegionFragment.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/Path.h>
 
 using namespace mcld;
 using namespace mcldtest;
diff --git a/unittests/MemoryAreaTest.cpp b/unittests/MemoryAreaTest.cpp
deleted file mode 100644
index 0499a0d..0000000
--- a/unittests/MemoryAreaTest.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-//===- MemoryAreaTest.cpp -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Support/Path.h>
-
-#include "MemoryAreaTest.h"
-#include <fcntl.h>
-#include <cstdio>
-
-using namespace mcld;
-using namespace mcld::sys::fs;
-using namespace mcldtest;
-
-
-// Constructor can do set-up work for all test here.
-MemoryAreaTest::MemoryAreaTest()
-{
-}
-
-// Destructor can do clean-up work that doesn't throw exceptions here.
-MemoryAreaTest::~MemoryAreaTest()
-{
-}
-
-// SetUp() will be called immediately before each test.
-void MemoryAreaTest::SetUp()
-{
-}
-
-// TearDown() will be called immediately after each test.
-void MemoryAreaTest::TearDown()
-{
-}
-
-//==========================================================================//
-// Testcases
-//
-TEST_F( MemoryAreaTest, read_by_malloc )
-{
-	Path path(TOPDIR);
-	path.append("unittests/test3.txt");
-
-	MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1);
-	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadOnly);
-	MemoryRegion* region = area->request(3, 2);
-	ASSERT_EQ('L', region->getBuffer()[0]);
-	ASSERT_EQ('O', region->getBuffer()[1]);
-	area->release(region);
-	AreaFactory->destruct(area);
-	//delete AreaFactory;;
-}
-
-TEST_F( MemoryAreaTest, write_by_malloc )
-{
-	Path path(TOPDIR);
-	path.append("unittests/test2.txt");
-	MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1);
-	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadOnly);
-        ASSERT_TRUE(area->handler()->isOpened());
-        ASSERT_TRUE(area->handler()->isGood());
-	MemoryRegion* region = area->request(3, 4);
-	region->getBuffer()[0] = 'L';
-	region->getBuffer()[1] = 'i';
-	region->getBuffer()[2] = 'n';
-	region->getBuffer()[3] = 'k';
-	area->release(region);
-	area->clear();
-	area->handler()->close();
-
-        area->handler()->open(path, FileHandle::ReadOnly);
-        ASSERT_TRUE(area->handler()->isOpened());
-        ASSERT_TRUE(area->handler()->isGood());
-        region = area->request(5, 2);
-        ASSERT_EQ('n', region->getBuffer()[0]);
-        ASSERT_EQ('k', region->getBuffer()[1]);
-	area->release(region);
-	AreaFactory->destruct(area);
-	//delete AreaFactory;;
-}
-
-TEST_F( MemoryAreaTest, read_one_page )
-{
-        Path path(TOPDIR) ;
-	path.append("unittests/test3.txt") ;
-	MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1) ;
-	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadOnly) ;
-	ASSERT_TRUE(area->handler()->isOpened()) ;
-	ASSERT_TRUE(area->handler()->isGood()) ;
-	MemoryRegion* region = area->request(0, 4096);
-	ASSERT_EQ('H', region->getBuffer()[0]);
-	ASSERT_EQ('E', region->getBuffer()[1]);
-	area->release(region);
-	AreaFactory->destruct(area);
-	//delete AreaFactory; ;
-}
-
-TEST_F( MemoryAreaTest, write_one_page )
-{
-        Path path(TOPDIR) ;
-	path.append("unittests/test2.txt") ;
-        MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1) ;
-	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadWrite);
-	ASSERT_TRUE(area->handler()->isOpened()) ;
-	ASSERT_TRUE(area->handler()->isGood()) ;
-	MemoryRegion* region = area->request(0, 4096) ;
-	region->getBuffer()[4000] = 'K' ;
-	region->getBuffer()[4001] = 'R' ;
-	ASSERT_EQ('K', region->getBuffer()[4000]);
-	ASSERT_EQ('R', region->getBuffer()[4001]);
-	area->release(region);
-	area->clear() ;
-	area->handler()->close();
-
-	area->handler()->open(path, FileHandle::ReadOnly);
-	region = area->request(4000, 4);
-	ASSERT_EQ('K', region->getBuffer()[0]);
-	ASSERT_EQ('R', region->getBuffer()[1]);
-	region->getBuffer()[0] = 'O' ;
-	region->getBuffer()[1] = 'H' ;
-        area->clear() ;
-	AreaFactory->destruct(area);
-	//delete AreaFactory; ;
-}
-
-TEST_F( MemoryAreaTest, write_sync )
-{
-        Path path(TOPDIR) ;
-	path.append("unittests/test2.txt") ;
-	MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1) ;
-	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadWrite) ;
-	ASSERT_TRUE(area->handler()->isOpened()) ;
-	ASSERT_TRUE(area->handler()->isGood()) ;
-	MemoryRegion* region1 = area->request(0, 4096) ;
-	MemoryRegion* region2 = area->request(512, 1024) ;
-	region1->getBuffer()[1000] = 'L' ;
-	region1->getBuffer()[1001] = 'L' ;
-	region2->getBuffer()[488] = 'V' ;
-	region2->getBuffer()[489] = 'M' ;
-	area->release(region1);
-	area->release(region2);
-	area->clear();
-	area->handler()->close();
-	area->handler()->open(path, FileHandle::ReadWrite);
-	region1 = area->request(0, 1024) ;
-	EXPECT_EQ('V', region1->getBuffer()[1000]) ;
-	EXPECT_EQ('M', region1->getBuffer()[1001]) ;
-	region1->getBuffer()[1000] = '@' ;
-	region1->getBuffer()[1001] = '@' ;
-	area->release(region1);
-	area->clear();
-	AreaFactory->destruct(area);
-	//delete AreaFactory; ;
-}
-
-
diff --git a/unittests/MemoryAreaTest.h b/unittests/MemoryAreaTest.h
deleted file mode 100644
index 86a5da0..0000000
--- a/unittests/MemoryAreaTest.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//===- MemoryAreaTest.h ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MEMORYAREA_TEST_H
-#define MEMORYAREA_TEST_H
-
-#include <gtest.h>
-
-namespace mcld
-{
-class MemoryArea;
-
-} // namespace for mcld
-
-namespace mcldtest
-{
-
-/** \class MemoryAreaTest
- *  \brief 
- *
- *  \see MemoryArea 
- */
-class MemoryAreaTest : public ::testing::Test
-{
-public:
-	// Constructor can do set-up work for all test here.
-	MemoryAreaTest();
-
-	// Destructor can do clean-up work that doesn't throw exceptions here.
-	virtual ~MemoryAreaTest();
-
-	// SetUp() will be called immediately before each test.
-	virtual void SetUp();
-
-	// TearDown() will be called immediately after each test.
-	virtual void TearDown();
-
-protected:
-	mcld::MemoryArea* m_pTestee;
-};
-
-} // namespace of mcldtest
-
-#endif
-
diff --git a/unittests/PathTest.cpp b/unittests/PathTest.cpp
index 1a73de2..73e62cc 100644
--- a/unittests/PathTest.cpp
+++ b/unittests/PathTest.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "PathTest.h"
-#include "mcld/Support/FileSystem.h"
+#include <mcld/Support/FileSystem.h>
 #include <string>
 
 //
diff --git a/unittests/RTLinearAllocatorTest.cpp b/unittests/RTLinearAllocatorTest.cpp
index 7ed5dac..1e07f4a 100644
--- a/unittests/RTLinearAllocatorTest.cpp
+++ b/unittests/RTLinearAllocatorTest.cpp
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/Allocators.h"
-#include <RTLinearAllocatorTest.h>
+#include <mcld/Support/Allocators.h>
+#include "RTLinearAllocatorTest.h"
 
 using namespace mcld;
 using namespace mcldtest;
diff --git a/unittests/StaticResolverTest.cpp b/unittests/StaticResolverTest.cpp
index bd40cd5..eb3accc 100644
--- a/unittests/StaticResolverTest.cpp
+++ b/unittests/StaticResolverTest.cpp
@@ -59,7 +59,7 @@
   ASSERT_TRUE( mcld::ResolveInfo::define_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::define_flag == old_sym->info());
   bool override = true;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
 }
@@ -85,7 +85,7 @@
   ASSERT_TRUE( mcld::ResolveInfo::Define    == old_sym->desc());
 
   bool override = false;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_TRUE(1 == old_sym->size());
@@ -112,7 +112,7 @@
   ASSERT_TRUE( mcld::ResolveInfo::Define == old_sym->desc());
 
   bool override = false;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_TRUE(1 == old_sym->size());
@@ -139,7 +139,7 @@
   ASSERT_TRUE( mcld::ResolveInfo::Undefined ==  old_sym->desc());
 
   bool override = false;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_TRUE(1 == old_sym->size());
@@ -161,7 +161,7 @@
   ASSERT_TRUE( mcld::ResolveInfo::global_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::weak_flag == old_sym->info());
   bool override = false;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_TRUE( override );
   ASSERT_TRUE(0 == old_sym->size());
@@ -190,7 +190,7 @@
   ASSERT_TRUE( mcld::ResolveInfo::Define == new_sym->desc());
 
   bool override = false;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_TRUE(1 == old_sym->size());
@@ -212,7 +212,7 @@
   ASSERT_TRUE( mcld::ResolveInfo::common_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::common_flag == old_sym->info());
   bool override = true;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_TRUE(999 == old_sym->size());
@@ -237,7 +237,7 @@
   ASSERT_TRUE( (ResolveInfo::weak_flag | ResolveInfo::common_flag) == old_sym->info());
 
   bool override = false;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_TRUE( override );
   ASSERT_TRUE(999 == old_sym->size());
@@ -261,7 +261,7 @@
   ASSERT_TRUE( ResolveInfo::common_flag == old_sym->info());
 
   bool override = false;
-  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override, 0x0);
   ASSERT_TRUE(result);
   ASSERT_TRUE( override );
   ASSERT_TRUE(999 == old_sym->size());
diff --git a/unittests/SymbolTableTest.cpp b/unittests/SymbolTableTest.cpp
index 5b665f0..2dc5143 100644
--- a/unittests/SymbolTableTest.cpp
+++ b/unittests/SymbolTableTest.cpp
@@ -6,7 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/LD/SymbolTable.h"
+#include <mcld/LD/SymbolTable.h>
 #include "SymbolTableTest.h"
 
 using namespace mcld;
diff --git a/unittests/TargetMachineTest.cpp b/unittests/TargetMachineTest.cpp
index 6258906..85950a9 100644
--- a/unittests/TargetMachineTest.cpp
+++ b/unittests/TargetMachineTest.cpp
@@ -6,7 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <TargetMachineTest.h>
+#include "TargetMachineTest.h"
 
 using namespace mcld;
 using namespace mcldTEST;