MCLinker upstream commit 0459e386785c.

Change-Id: Ide6790f5a354b7fcc03d812d6c8cf43b1e309ba3
diff --git a/Android.mk b/Android.mk
index c094c8d..79c6d5b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,8 +10,11 @@
 subdirs := \
   lib/ADT \
   lib/CodeGen \
+  lib/Core \
+  lib/Fragment \
   lib/LD \
   lib/MC \
+  lib/Object \
   lib/Support \
   lib/Target
 
diff --git a/include/mcld/ADT/Flags.h b/include/mcld/ADT/Flags.h
index 0091cea..d38d941 100644
--- a/include/mcld/ADT/Flags.h
+++ b/include/mcld/ADT/Flags.h
@@ -28,10 +28,10 @@
   Flags(Enum pFlag)
   : m_Data(pFlag) {}
 
-  Flags(int pFlag = 0x0)
+  Flags(unsigned int pFlag = 0x0)
   : m_Data(pFlag) {}
 
-  operator int () const
+  operator unsigned int () const
   { return m_Data; }
 
   bool operator! () const
@@ -46,11 +46,6 @@
   Flags operator& (Enum pMask ) const
   { return Flags(m_Data & pMask); }
 
-  Flags& operator&= (int pMask ) {
-    m_Data &= pMask;
-    return *this;
-  }
-
   Flags& operator&= (unsigned int pMask ) {
     m_Data &= pMask;
     return *this;
@@ -97,7 +92,7 @@
   { return Flags(~m_Data); }
 
 private:
-  int m_Data;
+  unsigned int m_Data;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/ADT/HashBase.h b/include/mcld/ADT/HashBase.h
index 76410ab..896f5b8 100644
--- a/include/mcld/ADT/HashBase.h
+++ b/include/mcld/ADT/HashBase.h
@@ -103,6 +103,8 @@
   /// initialize the hash table.
   void init(unsigned int pInitSize);
 
+  void clear();
+
   /// lookUpBucketFor - search the index of bucket whose key is p>ey
   //  @return the index of the found bucket
   unsigned int lookUpBucketFor(const key_type& pKey);
diff --git a/include/mcld/ADT/HashBase.tcc b/include/mcld/ADT/HashBase.tcc
index 62d92b1..165f4ae 100644
--- a/include/mcld/ADT/HashBase.tcc
+++ b/include/mcld/ADT/HashBase.tcc
@@ -80,7 +80,7 @@
          typename HashFunctionTy>
 HashTableImpl<HashEntryTy, HashFunctionTy>::~HashTableImpl()
 {
-  free(m_Buckets);
+  clear();
 }
 
 /// empty - check if the hash table is empty
@@ -105,6 +105,19 @@
   m_Buckets = (bucket_type*)calloc(m_NumOfBuckets, sizeof(bucket_type));
 }
 
+/// clear - clear the hash table.
+template<typename HashEntryTy,
+         typename HashFunctionTy>
+void HashTableImpl<HashEntryTy, HashFunctionTy>::clear()
+{
+  free(m_Buckets);
+
+  m_Buckets = 0;
+  m_NumOfBuckets = 0;
+  m_NumOfEntries = 0;
+  m_NumOfTombstones = 0;
+}
+
 /// lookUpBucketFor - look up the bucket whose key is pKey
 template<typename HashEntryTy,
          typename HashFunctionTy>
diff --git a/include/mcld/ADT/HashEntryFactory.h b/include/mcld/ADT/HashEntryFactory.h
new file mode 100644
index 0000000..42aa5e7
--- /dev/null
+++ b/include/mcld/ADT/HashEntryFactory.h
@@ -0,0 +1,36 @@
+//===- HashEntryFactory.h --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_HASH_ENTRY_FACTORY_H
+#define MCLD_HASH_ENTRY_FACTORY_H
+
+namespace mcld {
+
+/** \class HashEntryFactory
+ *  \brief HashEntryFactoy is a factory wrapper for those entries who have
+ *  factory methods.
+ */
+template<typename HashEntryTy>
+class HashEntryFactory
+{
+public:
+  typedef HashEntryTy           entry_type;
+  typedef typename HashEntryTy::key_type key_type;
+
+public:
+  entry_type* produce(const key_type& pKey)
+  { return HashEntryTy::Create(pKey); }
+
+  void destroy(entry_type*& pEntry)
+  { HashEntryTy::Destroy(pEntry); }
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/HashIterator.h b/include/mcld/ADT/HashIterator.h
index e25df77..078b20a 100644
--- a/include/mcld/ADT/HashIterator.h
+++ b/include/mcld/ADT/HashIterator.h
@@ -30,7 +30,7 @@
 
 public:
   ChainIteratorBase()
-  : m_pHashTable(0), m_HashValue(0), m_Index(0), m_EndIndex(0)
+  : m_pHashTable(0), m_Index(0), m_HashValue(0), m_EndIndex(0)
   { }
 
   ChainIteratorBase(HashTableImplTy* pTable, const key_type& pKey)
@@ -64,15 +64,15 @@
   ChainIteratorBase(const ChainIteratorBase& pCopy)
   : m_pHashTable(pCopy.m_pHashTable),
     m_Index(pCopy.m_Index),
-    m_EndIndex(pCopy.m_EndIndex),
-    m_HashValue(pCopy.m_HashValue)
+    m_HashValue(pCopy.m_HashValue),
+    m_EndIndex(pCopy.m_EndIndex)
   { }
 
   ChainIteratorBase& assign(const ChainIteratorBase& pCopy) {
     m_pHashTable = pCopy.m_pHashTable;
     m_Index = pCopy.m_Index;
-    m_EndIndex = pCopy.m_EndIndex;
     m_HashValue = pCopy.m_HashValue;
+    m_EndIndex = pCopy.m_EndIndex;
     return *this;
   }
 
diff --git a/include/mcld/ADT/HashTable.h b/include/mcld/ADT/HashTable.h
index dfc2f5a..0b6757e 100644
--- a/include/mcld/ADT/HashTable.h
+++ b/include/mcld/ADT/HashTable.h
@@ -6,22 +6,21 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #ifndef MCLD_HASH_TABLE_H
 #define MCLD_HASH_TABLE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
-#include "mcld/ADT/HashBase.h"
-#include "mcld/ADT/HashIterator.h"
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/ADT/TypeTraits.h"
-#include "mcld/Support/Allocators.h"
+#include <mcld/ADT/HashBase.h>
+#include <mcld/ADT/HashIterator.h>
+#include <mcld/ADT/HashEntryFactory.h>
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/ADT/TypeTraits.h>
+#include <mcld/Support/Allocators.h>
 #include <utility>
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class HashTable
  *  \brief HashTable is a hash table which follows boost::unordered_map, but it
@@ -33,7 +32,7 @@
  */
 template<typename HashEntryTy,
          typename HashFunctionTy,
-         typename EntryFactoryTy>
+         typename EntryFactoryTy = HashEntryFactory<HashEntryTy> >
 class HashTable : public HashTableImpl<HashEntryTy, HashFunctionTy>,
                   private Uncopyable
 {
diff --git a/include/mcld/ADT/HashTable.tcc b/include/mcld/ADT/HashTable.tcc
index 7439982..d0040ae 100644
--- a/include/mcld/ADT/HashTable.tcc
+++ b/include/mcld/ADT/HashTable.tcc
@@ -51,8 +51,8 @@
       BaseTy::m_Buckets[i].Entry = bucket_type::getEmptyBucket();
     }
   }
-  BaseTy::m_NumOfEntries = 0;
-  BaseTy::m_NumOfTombstones = 0;
+
+  BaseTy::clear();
 }
 
 /// insert - insert a new element to the container. If the element already
diff --git a/include/mcld/ADT/StringEntry.h b/include/mcld/ADT/StringEntry.h
index 09c8dfe..e6d1c20 100644
--- a/include/mcld/ADT/StringEntry.h
+++ b/include/mcld/ADT/StringEntry.h
@@ -69,7 +69,7 @@
 private:
   DataType m_Value;
   uint16_t m_KeyLen;
-  char m_Key[0];
+  char m_Key[];
 
   friend class StringEntryFactory<DataType>;
 };
@@ -123,7 +123,7 @@
 private:
   llvm::StringRef m_Value;
   uint16_t m_KeyLen;
-  char m_Key[0];
+  char m_Key[];
 
   friend class StringEntryFactory<llvm::StringRef>;
 };
diff --git a/include/mcld/ADT/StringHash.h b/include/mcld/ADT/StringHash.h
index f100a49..757287c 100644
--- a/include/mcld/ADT/StringHash.h
+++ b/include/mcld/ADT/StringHash.h
@@ -13,7 +13,9 @@
 #include <gtest.h>
 #endif
 #include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
 #include <llvm/Support/ErrorHandling.h>
+#include <cctype>
 #include <functional>
 
 namespace mcld
@@ -31,16 +33,17 @@
   DEK,
   BP,
   FNV,
-  AP
+  AP,
+  ES
 };
 
-/** \class template<size_t TYPE> StringHash
+/** \class template<uint32_t TYPE> StringHash
  *  \brief the template StringHash class, for specification
  */
-template<size_t TYPE>
-struct StringHash : public std::unary_function<const llvm::StringRef&, size_t>
+template<uint32_t TYPE>
+struct StringHash : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
     llvm::report_fatal_error("Undefined StringHash function.\n");
   }
@@ -50,13 +53,13 @@
  *  \brief RS StringHash funciton
  */
 template<>
-struct StringHash<RS> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<RS> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
     const unsigned int b = 378551;
-    size_t a = 63689;
-    size_t hash_val = 0;
+    uint32_t a = 63689;
+    uint32_t hash_val = 0;
 
     for(unsigned int i = 0; i < pKey.size(); ++i) {
       hash_val = hash_val * a + pKey[i];
@@ -70,11 +73,11 @@
  *  \brief JS hash funciton
  */
 template<>
-struct StringHash<JS> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<JS> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    size_t hash_val = 1315423911;
+    uint32_t hash_val = 1315423911;
 
     for(unsigned int i = 0; i < pKey.size(); ++i) {
        hash_val ^= ((hash_val << 5) + pKey[i] + (hash_val >> 2));
@@ -87,16 +90,16 @@
  *  \brief P.J. Weinberger hash function
  */
 template<>
-struct StringHash<PJW> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<PJW> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
     const unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
     const unsigned int ThreeQuarters     = (unsigned int)((BitsInUnsignedInt  * 3) / 4);
     const unsigned int OneEighth         = (unsigned int)(BitsInUnsignedInt / 8);
     const unsigned int HighBits          = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
-    size_t hash_val = 0;
-    size_t test = 0;
+    uint32_t hash_val = 0;
+    uint32_t test = 0;
 
     for(unsigned int i = 0; i < pKey.size(); ++i) {
       hash_val = (hash_val << OneEighth) + pKey[i];
@@ -113,12 +116,12 @@
  *  \brief ELF hash function.
  */
 template<>
-struct StringHash<ELF> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<ELF> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    size_t hash_val = 0;
-    size_t x = 0;
+    uint32_t hash_val = 0;
+    uint32_t x = 0;
 
     for (unsigned int i = 0; i < pKey.size(); ++i) {
       hash_val = (hash_val << 4) + pKey[i];
@@ -134,14 +137,14 @@
  *  \brief BKDR hash function
  */
 template<>
-struct StringHash<BKDR> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<BKDR> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    const size_t seed = 131;
-    size_t hash_val = 0;
+    const uint32_t seed = 131;
+    uint32_t hash_val = 0;
       
-    for(size_t i = 0; i < pKey.size(); ++i)
+    for(uint32_t i = 0; i < pKey.size(); ++i)
       hash_val = (hash_val * seed) + pKey[i];
     return hash_val;
   }
@@ -153,13 +156,13 @@
  *  0.049s in 100000 test
  */
 template<>
-struct StringHash<SDBM> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<SDBM> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    size_t hash_val = 0;
+    uint32_t hash_val = 0;
 
-    for(size_t i = 0; i < pKey.size(); ++i)
+    for(uint32_t i = 0; i < pKey.size(); ++i)
       hash_val = pKey[i] + (hash_val << 6) + (hash_val << 16) - hash_val;
     return hash_val;
   }
@@ -170,13 +173,13 @@
  *  0.057s in 100000 test
  */
 template<>
-struct StringHash<DJB> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<DJB> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    size_t hash_val = 5381;
+    uint32_t hash_val = 5381;
 
-    for(size_t i = 0; i < pKey.size(); ++i)
+    for(uint32_t i = 0; i < pKey.size(); ++i)
       hash_val = ((hash_val << 5) + hash_val) + pKey[i];
 
     return hash_val;
@@ -188,13 +191,13 @@
  *  0.60s
  */
 template<>
-struct StringHash<DEK> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<DEK> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    size_t hash_val = pKey.size();
+    uint32_t hash_val = pKey.size();
 
-    for(size_t i = 0; i < pKey.size(); ++i)
+    for(uint32_t i = 0; i < pKey.size(); ++i)
       hash_val = ((hash_val << 5) ^ (hash_val >> 27)) ^ pKey[i];
 
     return hash_val;
@@ -206,12 +209,12 @@
  *  0.057s
  */
 template<>
-struct StringHash<BP> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<BP> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    size_t hash_val = 0;
-    for(size_t i = 0; i < pKey.size(); ++i)
+    uint32_t hash_val = 0;
+    for(uint32_t i = 0; i < pKey.size(); ++i)
       hash_val = hash_val << 7 ^ pKey[i];
 
     return hash_val;
@@ -223,13 +226,13 @@
  *  0.058s
  */
 template<>
-struct StringHash<FNV> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<FNV> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
-    const size_t fnv_prime = 0x811C9DC5;
-    size_t hash_val = 0;
-    for(size_t i = 0; i < pKey.size(); ++i) {
+    const uint32_t fnv_prime = 0x811C9DC5;
+    uint32_t hash_val = 0;
+    for(uint32_t i = 0; i < pKey.size(); ++i) {
       hash_val *= fnv_prime;
       hash_val ^= pKey[i];
     }
@@ -243,13 +246,13 @@
  *  0.060s
  */
 template<>
-struct StringHash<AP> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<AP> : public std::unary_function<const llvm::StringRef&, uint32_t>
 {
-  size_t operator()(const llvm::StringRef& pKey) const
+  uint32_t operator()(const llvm::StringRef& pKey) const
   {
     unsigned int hash_val = 0xAAAAAAAA;
    
-    for(size_t i = 0; i < pKey.size(); ++i) {  
+    for(uint32_t i = 0; i < pKey.size(); ++i) {  
       hash_val ^= ((i & 1) == 0)?
                           ((hash_val <<  7) ^ pKey[i] * (hash_val >> 3)):
                           (~((hash_val << 11) + (pKey[i] ^ (hash_val >> 5))));
@@ -259,7 +262,83 @@
   }
 };
 
-/** \class template<size_t TYPE> StringCompare
+/** \class StringHash<ES>
+ *  \brief This is a revision of Edward Sayers' string characteristic function.
+ *
+ *  31-28  27  26  25   -   0
+ *  +----+---+---+------------+
+ *  | .  | N | - | a/A  ~ z/Z |
+ *  +----+---+---+------------+
+ *
+ *  . (bit 31~28) - The number of '.' characters
+ *  N (bit 27)    - Are there any numbers in the string
+ *  - (bit 26)    - Does the string have '-' character
+ *  bit 25~0      - Bit 25 is set only if the string contains a 'a' or 'A', and
+ *                  Bit 24 is set only if ...                   'b' or 'B', ...
+ */
+template<>
+struct StringHash<ES> : public std::unary_function<const llvm::StringRef&, uint32_t>
+{
+  uint32_t operator()(const llvm::StringRef& pString) const
+  {
+    uint32_t result = 0x0;
+    unsigned int dot = 0;
+    std::string::size_type idx;
+    for (idx = 0; idx < pString.size(); ++idx) {
+      int cur_char = pString[idx];
+
+      if ('.' == cur_char) {
+        ++dot;
+        continue;
+      }
+
+      if (isdigit(cur_char)) {
+        result |= (1 << 27);
+        continue;
+      }
+
+      if ('_' == cur_char) {
+        result |= (1 << 26);
+        continue;
+      }
+
+      if (isupper(cur_char)) {
+        result |= (1 << (cur_char - 'A'));
+        continue;
+      }
+
+      if (islower(cur_char)) {
+        result |= (1 << (cur_char - 'a'));
+        continue;
+      }
+    }
+    result |= (dot << 28);
+    return result;
+  }
+
+
+  /** \func may_include
+   *  \brief is it possible that pRule is a sub-string of pInString
+   */
+  static bool may_include(uint32_t pRule, uint32_t pInString)
+  {
+    uint32_t in_c = pInString << 4;
+    uint32_t r_c  = pRule << 4;
+
+    uint32_t res = (in_c ^ r_c) & r_c;
+    if (0 != res)
+      return false;
+
+    uint32_t in_dot = pInString >> 28;
+    uint32_t r_dot  = pRule >> 28;
+    if (r_dot > in_dot)
+      return false;
+
+    return true;
+  }
+};
+
+/** \class template<uint32_t TYPE> StringCompare
  *  \brief the template StringCompare class, for specification
  */
 template<typename STRING_TYPE>
diff --git a/include/mcld/ADT/TreeBase.h b/include/mcld/ADT/TreeBase.h
index 10e0892..6fb3bf6 100644
--- a/include/mcld/ADT/TreeBase.h
+++ b/include/mcld/ADT/TreeBase.h
@@ -12,8 +12,7 @@
 
 #include <cstddef>
 
-namespace mcld
-{
+namespace mcld {
 
 class NodeBase
 {
@@ -39,7 +38,7 @@
 
 } // namespace of template proxy
 
-struct TreeIteratorBase
+class TreeIteratorBase
 {
 public:
   enum Direct {
diff --git a/include/mcld/AttributeOption.h b/include/mcld/AttributeOption.h
new file mode 100644
index 0000000..18d7278
--- /dev/null
+++ b/include/mcld/AttributeOption.h
@@ -0,0 +1,38 @@
+//===- AttributeOption.h --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ATTRIBUTE_OPTIONS_H
+#define MCLD_ATTRIBUTE_OPTIONS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/MC/Attribute.h>
+
+namespace mcld {
+
+class AttributeOption
+{
+public:
+  AttributeOption();
+  ~AttributeOption();
+
+  const Attribute& predefined() const { return m_Predefined; }
+  Attribute&       predefined()       { return m_Predefined; }
+
+  const AttrConstraint& constraint() const { return m_Constraint; }
+  AttrConstraint&       constraint()       { return m_Constraint; }
+
+private:
+  Attribute m_Predefined;
+  AttrConstraint m_Constraint;
+};
+
+} // namespace mcld
+
+#endif
+
diff --git a/include/mcld/BitcodeOption.h b/include/mcld/BitcodeOption.h
new file mode 100644
index 0000000..4e9a5e1
--- /dev/null
+++ b/include/mcld/BitcodeOption.h
@@ -0,0 +1,49 @@
+//===- BitcodeOption.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_BITCODE_OPTIONS_H
+#define MCLD_BITCODE_OPTIONS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/Path.h>
+
+namespace mcld {
+
+/** \class BitcodeOption
+ *  \brief BitcodeOption represents the options of bitcode on the command line.
+ */
+class BitcodeOption
+{
+public:
+  BitcodeOption();
+
+  ~BitcodeOption();
+
+  void setPosition(unsigned int pPosition) { m_Position = pPosition; }
+
+  unsigned int getPosition() const { return m_Position; }
+
+  void setPath(const sys::fs::Path& pPath) { m_Path = pPath; }
+
+  const sys::fs::Path& getPath() const { return m_Path; }
+
+  bool hasDefined() const;
+
+private:
+  int m_Position;
+
+  sys::fs::Path m_Path;
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/CodeGen/MCLinker.h b/include/mcld/CodeGen/MCLinker.h
new file mode 100644
index 0000000..34ddcb7
--- /dev/null
+++ b/include/mcld/CodeGen/MCLinker.h
@@ -0,0 +1,85 @@
+//===- MCLinker.h ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// MCLinker is a base class inherited by target specific linker.
+// This class primarily handles common functionality used by all linkers.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_CODEGEN_MCLINKER_H
+#define MCLD_CODEGEN_MCLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/CodeGen/MachineFunctionPass.h>
+
+namespace llvm {
+
+class Module;
+class MachineFunction;
+
+} // namespace of llvm
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+class IRBuilder;
+class LinkerConfig;
+class Linker;
+
+/** \class MCLinker
+*  \brief MCLinker provides a linking pass for standard compilation flow
+*
+*  MCLinker is responded for
+*  - provide an interface for target-specific linker
+*  - set up environment for ObjectLinker
+*  - perform linking
+*
+*  @see MachineFunctionPass ObjectLinker
+*/
+class MCLinker : public llvm::MachineFunctionPass
+{
+protected:
+  // Constructor. Although MCLinker has only two arguments,
+  // TargetMCLinker should handle
+  // - enabled attributes
+  // - the default attribute
+  // - the default link script
+  // - the standard symbols
+  MCLinker(LinkerConfig& pConfig,
+           mcld::Module& pModule,
+           MemoryArea& pOutput);
+
+public:
+  virtual ~MCLinker();
+
+  virtual bool doInitialization(llvm::Module &pM);
+
+  virtual bool doFinalization(llvm::Module &pM);
+
+  virtual bool runOnMachineFunction(llvm::MachineFunction& pMFn);
+
+protected:
+  void initializeInputTree(IRBuilder& pBuilder);
+
+protected:
+  LinkerConfig& m_Config;
+  mcld::Module& m_Module;
+  MemoryArea& m_Output;
+  IRBuilder* m_pBuilder;
+  Linker* m_pLinker;
+
+private:
+  static char m_ID;
+};
+
+} // namespace of MC Linker
+
+#endif
+
diff --git a/include/mcld/CodeGen/SectLinker.h b/include/mcld/CodeGen/SectLinker.h
deleted file mode 100644
index 4ed2907..0000000
--- a/include/mcld/CodeGen/SectLinker.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===- SectLinker.h -------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//SectLinker is a base class inherited by target specific linker.
-//This class primarily handles common functionality used by all linkers.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTION_LINKER_H
-#define MCLD_SECTION_LINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/CodeGen/MachineFunctionPass.h>
-#include <mcld/Support/PositionDependentOption.h>
-#include <vector>
-
-namespace llvm
-{
-class Module;
-class MachineFunction;
-} // namespace of llvm
-
-namespace mcld
-{
-class MCLDInfo;
-class MCLDFile;
-class MCLDDriver;
-class TargetLDBackend;
-class AttributeFactory;
-class SectLinkerOption;
-class MemoryAreaFactory;
-
-/** \class SectLinker
-*  \brief SectLinker provides a linking pass for standard compilation flow
-*
-*  SectLinker is responded for
-*  - provide an interface for target-specific SectLinekr
-*  - set up environment for MCLDDriver
-*  - control AsmPrinter, make sure AsmPrinter has already prepared
-*    all SectionDatas for linking
-*
-*  SectLinker resolves the absolue paths of input arguments.
-*
-*  @see MachineFunctionPass MCLDDriver
-*/
-class SectLinker : public llvm::MachineFunctionPass
-{
-protected:
-  // Constructor. Although SectLinker has only two arguments,
-  // TargetSectLinker should handle
-  // - enabled attributes
-  // - the default attribute
-  // - the default link script
-  // - the standard symbols
-  SectLinker(SectLinkerOption &pOption,
-             TargetLDBackend &pLDBackend);
-
-public:
-  virtual ~SectLinker();
-
-  /// doInitialization - Read all parameters and set up the AsmPrinter.
-  /// If your pass overrides this, it must make sure to explicitly call
-  /// this implementation.
-  virtual bool doInitialization(llvm::Module &pM);
-
-  /// doFinalization - Shut down the AsmPrinter, and do really linking.
-  /// If you override this in your pass, you must make sure to call it
-  /// explicitly.
-  virtual bool doFinalization(llvm::Module &pM);
-
-  /// runOnMachineFunction
-  /// redirect to AsmPrinter
-  virtual bool runOnMachineFunction(llvm::MachineFunction& pMFn);
-
-protected:
-  void initializeInputTree(const PositionDependentOptions &pOptions) const;
-
-  void initializeInputOutput(MCLDInfo& pLDInfo);
-
-  MemoryAreaFactory* memAreaFactory()
-  { return m_pMemAreaFactory; }
-
-private:
-  SectLinkerOption *m_pOption;
-
-protected:
-  TargetLDBackend *m_pLDBackend;
-  MCLDDriver *m_pLDDriver;
-  MemoryAreaFactory *m_pMemAreaFactory;
-
-private:
-  static char m_ID;
-};
-
-} // namespace of MC Linker
-
-#endif
-
diff --git a/include/mcld/CodeGen/SectLinkerOption.h b/include/mcld/CodeGen/SectLinkerOption.h
deleted file mode 100644
index 78c8f53..0000000
--- a/include/mcld/CodeGen/SectLinkerOption.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- SectLinkerOption.h ---------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTLINKERDATA_H
-#define MCLD_SECTLINKERDATA_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/Support/PositionDependentOption.h>
-
-#include <string>
-
-namespace mcld
-{
-  class PositionDependentOption;
-
-  /** \class SectLinkerOption
-   *  \brief This file collects inputs to linker.
-   */
-  class SectLinkerOption
-  {
-  public:
-    // Constructor.
-    SectLinkerOption(MCLDInfo &pLDInfo);
-
-    // -----  Position-dependent Options  ----- //
-    inline void appendOption(PositionDependentOption *pOption)
-    { m_PosDepOptions.push_back(pOption); }
-
-    inline void prependOption(PositionDependentOption *pOption)
-    { m_PosDepOptions.insert(m_PosDepOptions.begin(), pOption); }
-
-    inline const PositionDependentOptions &pos_dep_options() const
-    { return m_PosDepOptions; }
-    inline PositionDependentOptions &pos_dep_options()
-    { return m_PosDepOptions; }
-
-    inline const MCLDInfo &info() const { return *m_pLDInfo; }
-    inline MCLDInfo &info() { return *m_pLDInfo; }
-
-    ~SectLinkerOption();
-
-  private:
-    MCLDInfo *m_pLDInfo;
-    PositionDependentOptions m_PosDepOptions;
-  };
-
-} // namespace of mcld
-
-#endif
diff --git a/include/mcld/Config/Config.h b/include/mcld/Config/Config.h
index 8daa109..f604109 100644
--- a/include/mcld/Config/Config.h
+++ b/include/mcld/Config/Config.h
@@ -23,7 +23,12 @@
 # define MCLD_ON_WIN32 1
 #endif
 
-#define MCLD_VERSION "Phoenix - 1.4.0"
+#define MCLD_VERSION "RockBull - 2.0.0"
+
+#define MCLD_REGION_CHUNK_SIZE 32
+#define MCLD_NUM_OF_INPUTS 32
+#define MCLD_SECTIONS_PER_INPUT 16
+#define MCLD_SYMBOLS_PER_INPUT 128
 
 #endif
 
diff --git a/include/mcld/Config/Config.h.in b/include/mcld/Config/Config.h.in
index c0e7e0a..f025393 100644
--- a/include/mcld/Config/Config.h.in
+++ b/include/mcld/Config/Config.h.in
@@ -11,6 +11,10 @@
 
 #define @MCLD_ON_PLATFORM@ 1
 #define MCLD_VERSION "@MCLD_VERSION@"
+#define MCLD_REGION_CHUNK_SIZE 32
+#define MCLD_NUM_OF_INPUTS 32
+#define MCLD_SECTIONS_PER_INPUT 16
+#define MCLD_SYMBOLS_PER_INPUT 128
 
 #endif
 
diff --git a/include/mcld/Config/Linkers.def b/include/mcld/Config/Linkers.def
index 2781461..c0a852f 100644
--- a/include/mcld/Config/Linkers.def
+++ b/include/mcld/Config/Linkers.def
@@ -1,4 +1,4 @@
-//===- llvm/Config/Linkers.def - LLVM Linkers -------------------*- C++ -*-===//
+//===- llvm/Config/Linkers.def - MCLinkers ----------------------*- C++ -*-===//
 //
 //                     The MCLinker Project
 //
@@ -7,13 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file enumerates all of the linkers supported by this build of LLVM.
-// Clients of this file should define the LLVM_LINKER macro to be a function-like
+// This file enumerates all of the linkers supported by this build of MCLinker.
+// Clients of this file should define the MCLD_LINKER macro to be a function-like
 // macro with a single parameter (the name of the target whose exe/dso can be
 // generated); including this file will then enumerate all of the targets with
 // linkers.
 //
-// The set of targets supported by LLVM is generated at configuration
+// The set of targets supported by MCLD is generated at configuration
 // time, at which point this header is generated. Do not modify this
 // header directly.
 //
@@ -23,11 +23,12 @@
 // Hand-coded for Android build
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LINKER
-#  error Please define the macro LLVM_LINKER(TargetName)
+#ifndef MCLD_LINKER
+#  error Please define the macro MCLD_LINKER(TargetName)
 #endif
 
-#define LLVM_TARGET LLVM_LINKER
+#define LLVM_TARGET MCLD_LINKER
 #include <llvm/Config/Targets.def>
+#undef LLVM_TARGET
 
-#undef LLVM_LINKER
+#undef MCLD_LINKER
diff --git a/include/mcld/Config/Linkers.def.in b/include/mcld/Config/Linkers.def.in
index 0e09040..e8b870b 100644
--- a/include/mcld/Config/Linkers.def.in
+++ b/include/mcld/Config/Linkers.def.in
@@ -1,4 +1,4 @@
-//===- llvm/Config/Linkers.def - LLVM Linkers -------------------*- C++ -*-===//
+//===- llvm/Config/Linkers.def - MCLinkers ----------------------*- C++ -*-===//
 //
 //                     The MCLinker Project
 //
@@ -7,22 +7,22 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file enumerates all of the linkers supported by this build of LLVM. 
-// Clients of this file should define the LLVM_LINKER macro to be a function-like 
+// This file enumerates all of the linkers supported by this build of MCLinker. 
+// Clients of this file should define the MCLD_LINKER macro to be a function-like 
 // macro with a single parameter (the name of the target whose exe/dso can be
 // generated); including this file will then enumerate all of the targets with
 // linkers.
 //
-// The set of targets supported by LLVM is generated at configuration
+// The set of targets supported by MCLD is generated at configuration
 // time, at which point this header is generated. Do not modify this
 // header directly.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LINKER
-#  error Please define the macro LLVM_LINKER(TargetName)
+#ifndef MCLD_LINKER
+#  error Please define the macro MCLD_LINKER(TargetName)
 #endif
 
-@LLVM_ENUM_LINKERS@
+@MCLD_ENUM_LINKERS@
 
-#undef LLVM_LINKER
+#undef MCLD_LINKER
diff --git a/include/mcld/Config/Targets.def b/include/mcld/Config/Targets.def
index a0981d6..db05cce 100644
--- a/include/mcld/Config/Targets.def
+++ b/include/mcld/Config/Targets.def
@@ -1,6 +1,6 @@
-/*===- llvm/Config/Targets.def - LLVM Target Architectures ------*- C++ -*-===*\
+/*===- llvm/Config/Targets.def - MCLD Target Architectures ------*- C++ -*-===*\
 |*                                                                            *|
-|*                     The MCLinker Project                       *|
+|*                     The MCLinker Project                                   *|
 |*                                                                            *|
 |* This file is distributed under the University of Illinois Open Source      *|
 |* License. See LICENSE.TXT for details.                                      *|
@@ -8,12 +8,12 @@
 |*===----------------------------------------------------------------------===*|
 |*                                                                            *|
 |* This file enumerates all of the target architectures supported by          *|
-|* this build of LLVM. Clients of this file should define the                 *|
-|* LLVM_TARGET macro to be a function-like macro with a single                *|
+|* this build of MCLD. Clients of this file should define the                 *|
+|* MCLD_TARGET macro to be a function-like macro with a single                *|
 |* parameter (the name of the target); including this file will then          *|
 |* enumerate all of the targets.                                              *|
 |*                                                                            *|
-|* The set of targets supported by LLVM is generated at configuration         *|
+|* The set of targets supported by MCLD is generated at configuration         *|
 |* time, at which point this header is generated. Do not modify this          *|
 |* header directly.                                                           *|
 |*                                                                            *|
@@ -23,10 +23,12 @@
 // Hand-coded for Android build
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TARGET
-#  error Please define the macro LLVM_TARGET(TargetName)
+#ifndef MCLD_TARGET
+#  error Please define the macro MCLD_TARGET(TargetName)
 #endif
 
+#define LLVM_TARGET MCLD_TARGET
 #include <llvm/Config/Targets.def>
-
 #undef LLVM_TARGET
+
+#undef MCLD_TARGET
diff --git a/include/mcld/Config/Targets.def.in b/include/mcld/Config/Targets.def.in
index a73b9b7..7423904 100644
--- a/include/mcld/Config/Targets.def.in
+++ b/include/mcld/Config/Targets.def.in
@@ -1,6 +1,6 @@
-/*===- llvm/Config/Targets.def - LLVM Target Architectures ------*- C++ -*-===*\
+/*===- llvm/Config/Targets.def - MCLD Target Architectures ------*- C++ -*-===*\
 |*                                                                            *|
-|*                     The MCLinker Project                       *|
+|*                     The MCLinker Project                                   *|
 |*                                                                            *|
 |* This file is distributed under the University of Illinois Open Source      *|
 |* License. See LICENSE.TXT for details.                                      *|
@@ -8,21 +8,21 @@
 |*===----------------------------------------------------------------------===*|
 |*                                                                            *|
 |* This file enumerates all of the target architectures supported by          *|
-|* this build of LLVM. Clients of this file should define the                 *|
-|* LLVM_TARGET macro to be a function-like macro with a single                *|
+|* this build of MCLD. Clients of this file should define the                 *|
+|* MCLD_TARGET macro to be a function-like macro with a single                *|
 |* parameter (the name of the target); including this file will then          *|
 |* enumerate all of the targets.                                              *|
 |*                                                                            *|
-|* The set of targets supported by LLVM is generated at configuration         *|
+|* The set of targets supported by MCLD is generated at configuration         *|
 |* time, at which point this header is generated. Do not modify this          *|
 |* header directly.                                                           *|
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#ifndef LLVM_TARGET
-#  error Please define the macro LLVM_TARGET(TargetName)
+#ifndef MCLD_TARGET
+#  error Please define the macro MCLD_TARGET(TargetName)
 #endif
 
-@LLVM_ENUM_TARGETS@
+@MCLD_ENUM_TARGETS@
 
-#undef LLVM_TARGET
+#undef MCLD_TARGET
diff --git a/include/mcld/Environment.h b/include/mcld/Environment.h
new file mode 100644
index 0000000..d543566
--- /dev/null
+++ b/include/mcld/Environment.h
@@ -0,0 +1,23 @@
+//===- Environment.h ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ENVIRONMENT_H
+#define MCLD_ENVIRONMENT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld {
+
+void Initialize();
+
+void Finalize();
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/LD/AlignFragment.h b/include/mcld/Fragment/AlignFragment.h
similarity index 91%
rename from include/mcld/LD/AlignFragment.h
rename to include/mcld/Fragment/AlignFragment.h
index 4c5582c..14d0051 100644
--- a/include/mcld/LD/AlignFragment.h
+++ b/include/mcld/Fragment/AlignFragment.h
@@ -12,10 +12,9 @@
 #include <gtest.h>
 #endif
 
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class SectionData;
 
@@ -37,11 +36,12 @@
 
   void setEmitNops(bool pValue) { m_bEmitNops = pValue; }
 
-  static bool classof(const Fragment *F) {
-    return F->getKind() == Fragment::Alignment;
-  }
+  static bool classof(const Fragment *F)
+  { return F->getKind() == Fragment::Alignment; }
   static bool classof(const AlignFragment *) { return true; }
 
+  size_t size() const;
+
 private:
   /// Alignment - The alignment to ensure, in bytes.
   unsigned int m_Alignment;
diff --git a/include/mcld/LD/FillFragment.h b/include/mcld/Fragment/FillFragment.h
similarity index 92%
rename from include/mcld/LD/FillFragment.h
rename to include/mcld/Fragment/FillFragment.h
index db29111..af78237 100644
--- a/include/mcld/LD/FillFragment.h
+++ b/include/mcld/Fragment/FillFragment.h
@@ -14,10 +14,9 @@
 
 #include <llvm/Support/DataTypes.h>
 
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class SectionData;
 
@@ -31,13 +30,13 @@
 
   unsigned getValueSize() const { return m_ValueSize; }
 
-  uint64_t getSize() const { return m_Size; }
-
   static bool classof(const Fragment *F)
   { return F->getKind() == Fragment::Fillment; }
 
   static bool classof(const FillFragment *) { return true; }
 
+  size_t size() const { return m_Size; }
+
 private:
   /// m_Value - Value used for filling bytes
   int64_t m_Value;
diff --git a/include/mcld/LD/Fragment.h b/include/mcld/Fragment/Fragment.h
similarity index 81%
rename from include/mcld/LD/Fragment.h
rename to include/mcld/Fragment/Fragment.h
index 1baa8df..b3d072d 100644
--- a/include/mcld/LD/Fragment.h
+++ b/include/mcld/Fragment/Fragment.h
@@ -6,19 +6,20 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_FRAGMENT_H
-#define MCLD_FRAGMENT_H
+#ifndef MCLD_FRAGMENT_FRAGMENT_H
+#define MCLD_FRAGMENT_FRAGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
 #include <llvm/ADT/ilist_node.h>
+
 #include <llvm/Support/DataTypes.h>
 
 #include <cstddef>
+#include <cassert>
 
-namespace mcld
-{
+namespace mcld {
 
 class SectionData;
 
@@ -33,7 +34,9 @@
     Fillment,
     Region,
     Relocation,
-    Target
+    Target,
+    Stub,
+    Null
   };
 
 public:
@@ -49,16 +52,19 @@
 
   void setParent(SectionData *pValue) { m_pParent = pValue; }
 
-  uint64_t getOffset() const { return m_Offset; }
+  uint64_t getOffset() const;
 
   void setOffset(uint64_t pOffset) { m_Offset = pOffset; }
 
-  unsigned int getLayoutOrder() const { return m_LayoutOrder; }
-
-  void setLayoutOrder(unsigned int pValue) { m_LayoutOrder = pValue; }
+  bool hasOffset() const;
 
   static bool classof(const Fragment *O) { return true; }
 
+  virtual size_t size() const {
+    assert(false && "Can not call abstract Fragment::size()!");
+    return 0;
+  }
+
 private:
   Fragment(const Fragment& );            // DO NOT IMPLEMENT
   Fragment& operator=(const Fragment& ); // DO NOT IMPLEMENT
@@ -68,7 +74,6 @@
   SectionData* m_pParent;
 
   uint64_t m_Offset;
-  unsigned int m_LayoutOrder;
 
 };
 
diff --git a/include/mcld/MC/MCLinker.h b/include/mcld/Fragment/FragmentLinker.h
similarity index 63%
rename from include/mcld/MC/MCLinker.h
rename to include/mcld/Fragment/FragmentLinker.h
index 9fe78d8..9fd70d0 100644
--- a/include/mcld/MC/MCLinker.h
+++ b/include/mcld/Fragment/FragmentLinker.h
@@ -1,4 +1,4 @@
-//===- MCLinker.h -------------------------------------------------------===//
+//===- FragmentLinker.h ---------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -11,45 +11,38 @@
 // These APIs do the things which a linker should do.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MCLINKER_H
-#define MCLD_MCLINKER_H
+#ifndef MCLD_FRAGMENT_FRAGMENT_LINKER_H
+#define MCLD_FRAGMENT_FRAGMENT_LINKER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
-#include <set>
 #include <string>
 
-#include <llvm/ADT/ilist.h>
-
-#include <mcld/LD/StaticResolver.h>
-#include <mcld/LD/LDSectionFactory.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/LD/LDFileFormat.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/Relocation.h>
-#include <mcld/LD/SectionMerger.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
 #include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/SymbolCategory.h>
-#include <mcld/Support/GCFactory.h>
-#include <mcld/Support/GCFactoryListTraits.h>
 
 namespace mcld {
 
+class Module;
 class TargetLDBackend;
-class MCLDInfo;
+class LinkerConfig;
 class LDSection;
 class LDSectionFactory;
 class SectionData;
-class SectionMap;
 class Output;
 class EhFrame;
 class EhFrameHdr;
+class MemoryArea;
+class RelocData;
 
-/** \class MCLinker
- *  \brief MCLinker provides a pass to link object files.
+/** \class FragmentLinker
+ *  \brief FragmentLinker provides a pass to link object files.
  */
-class MCLinker
+class FragmentLinker
 {
 public:
   enum DefinePolicy
@@ -65,11 +58,11 @@
   };
 
 public:
-  MCLinker(TargetLDBackend& pBackend,
-           MCLDInfo& pLDInfo,
-           SectionMap& pSectionMap);
+  FragmentLinker(const LinkerConfig& pConfig,
+                 Module& pModule,
+                 TargetLDBackend& pBackend);
 
-  ~MCLinker();
+  ~FragmentLinker();
 
   // ----- about symbols  ----- //
   /// addDynSymbol - add a symbol and resolve it immediately
@@ -115,52 +108,18 @@
 
   bool finalizeSymbols();
 
-  // -----  sections  ----- //
-  /// getSectionMap - getSectionMap to change the behavior of SectionMerger
-  /// SectionMap& getSectionMap()
-  /// { return m_SectionMap; }
-
-  /// createSectHdr - for reader and standard/target format to create a section
-  /// header. This function will create a new LDSection and return it. If the
-  /// output has no related LDSection, this function will also create one and
-  /// push into the output.
-  LDSection& createSectHdr(const std::string& pName,
-                           LDFileFormat::Kind pKind,
-                           uint32_t pType,
-                           uint32_t pFlag);
-
-  /// getOrCreateOutputSectHdr - for reader and standard/target format to get
-  /// or create the output's section header
-  LDSection& getOrCreateOutputSectHdr(const std::string& pName,
-                                      LDFileFormat::Kind pKind,
-                                      uint32_t pType,
-                                      uint32_t pFlag,
-                                      uint32_t pAlign = 0x0);
-
-  /// getOrCreateSectData - for reader to map and perform section merging immediately
-  SectionData& getOrCreateSectData(LDSection& pSection);
-
-  // -----  eh_frame sections  ----- //
-  /// addEhFrame - add an exception handling section
-  /// @param pInput - the Input contains this section
-  /// @param pSection - the input section
-  /// @param pArea - the memory area which pSection is within.
-  uint64_t addEhFrame(const Input& pInput,
-                      LDSection& pSection,
-                      MemoryArea& pArea);
-
   // -----  relocations  ----- //
-  /// addRelocation - add a relocation entry in MCLinker (only for object file)
+  /// addRelocation - add a relocation entry in FragmentLinker (only for object file)
   /// @param pType - the type of the relocation
-  /// @param pResolveInfo - the symbol should be the symbol in the input file. MCLinker
+  /// @param pSym  - the symbol should be the symbol in the input file. FragmentLinker
   ///                  computes the real applied address by the output symbol.
-  /// @param pFragmentRef - the fragment reference of the applied address.
+  /// @param pSection - the input relocation section
+  /// @param pOffset - the offset of target section.
   /// @param pAddend - the addend value for applying relocation
   Relocation* addRelocation(Relocation::Type pType,
-                            const LDSymbol& pSym,
-                            ResolveInfo& pResolveInfo,
-                            FragmentRef& pFragmentRef,
-                            const LDSection& pSection,
+                            LDSymbol& pSym,
+                            LDSection& pSection,
+                            uint32_t pOffset,
                             Relocation::Address pAddend = 0);
 
   /// applyRelocations - apply all relocation enties.
@@ -168,32 +127,17 @@
 
   /// syncRelocationResult - After applying relocation, write back relocation target
   /// data to output file.
-  void syncRelocationResult();
-
-  // -----  layout  ----- //
-  void initSectionMap();
-
-  Layout& getLayout()
-  { return m_Layout; }
-
-  const Layout& getLayout() const
-  { return m_Layout; }
-
-  bool layout();
-
-  // -----  output symbols  ----- //
-  SymbolCategory& getOutputSymbols()
-  { return m_OutputSymbols; }
-
-  const SymbolCategory& getOutputSymbols() const
-  { return m_OutputSymbols; }
+  void syncRelocationResult(MemoryArea& pOutput);
 
   // -----  capacity  ----- //
-  MCLDInfo& getLDInfo()
-  { return m_LDInfo; }
+  const LinkerConfig& getLDInfo() const { return m_Config; }
 
-  const MCLDInfo& getLDInfo() const
-  { return m_LDInfo; }
+  // ----- output attribute ----- //
+  /// isOutputPIC - return whether the output is position-independent
+  bool isOutputPIC() const;
+
+  /// isStaticLink - return whether we're doing static link
+  bool isStaticLink() const;
 
 private:
   LDSymbol* defineSymbolForcefully(const llvm::StringRef& pName,
@@ -255,28 +199,34 @@
                                 LDSymbol::ValueType pValue,
                                 FragmentRef* pFragmentRef,
                                 ResolveInfo::Visibility pVisibility);
-private:
-  typedef GCFactory<LDSymbol, 0> LDSymbolFactory;
-  typedef GCFactory<SectionData, 0> LDSectionDataFactory;
-  typedef llvm::iplist<Fragment,
-                       GCFactoryListTraits<Fragment> > RelocationListType;
-  typedef std::set<LDSymbol*> ForceLocalSymbolTable;
-  typedef std::vector<LDSymbol*> OutputSymbolTable;
+
+  /// checkIsOutputPIC - return whether the output is position-independent,
+  /// called by isOutputPIC()
+  bool checkIsOutputPIC() const;
+
+  /// checkIsStaticLink - return whether we're doing static link, called by
+  /// isStaticLink()
+  bool checkIsStaticLink() const;
+
+  /// normalSyncRelocationResult - sync relocation result when producing shared
+  /// objects or executables
+  void normalSyncRelocationResult(MemoryArea& pOutput);
+
+  /// 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;
-  MCLDInfo& m_LDInfo;
-  SectionMap& m_SectionMap;
-  LDSymbolFactory m_LDSymbolFactory;
-  LDSectionFactory m_LDSectHdrFactory;
-  LDSectionDataFactory m_LDSectDataFactory;
-  SectionMerger* m_pSectionMerger;
-  Layout m_Layout;
-  RelocationListType m_RelocationList;
-  SymbolCategory m_OutputSymbols;
 };
 
-#include "MCLinker.tcc"
+#include "FragmentLinker.tcc"
 
 } // namespace of mcld
 
diff --git a/include/mcld/MC/MCLinker.tcc b/include/mcld/Fragment/FragmentLinker.tcc
similarity index 67%
rename from include/mcld/MC/MCLinker.tcc
rename to include/mcld/Fragment/FragmentLinker.tcc
index b13e48d..884a597 100644
--- a/include/mcld/MC/MCLinker.tcc
+++ b/include/mcld/Fragment/FragmentLinker.tcc
@@ -1,4 +1,4 @@
-//===- MCLinker.tcc -------------------------------------------------------===//
+//===- FragmentLinker.tcc --------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -9,21 +9,21 @@
 
 /// addSymbol - add a symbol and resolve it immediately
 template<Input::Type FROM>
-LDSymbol* MCLinker::addSymbol(const llvm::StringRef& pName,
-                              ResolveInfo::Type pType,
-                              ResolveInfo::Desc pDesc,
-                              ResolveInfo::Binding pBinding,
-                              ResolveInfo::SizeType pSize,
-                              LDSymbol::ValueType pValue,
-                              FragmentRef* pFragmentRef,
-                              ResolveInfo::Visibility pVisibility)
+LDSymbol* FragmentLinker::addSymbol(const llvm::StringRef& pName,
+                                    ResolveInfo::Type pType,
+                                    ResolveInfo::Desc pDesc,
+                                    ResolveInfo::Binding pBinding,
+                                    ResolveInfo::SizeType pSize,
+                                    LDSymbol::ValueType pValue,
+                                    FragmentRef* pFragmentRef,
+                                    ResolveInfo::Visibility pVisibility)
 {
   llvm::StringRef symbol_name = pName;
   if (!getLDInfo().scripts().renameMap().empty() &&
       ResolveInfo::Undefined == pDesc) {
     // If the renameMap is not empty, some symbols should be renamed.
     // --wrap and --portable defines the symbol rename map.
-    ScriptOptions::SymbolRenameMap::iterator renameSym
+    ScriptOptions::SymbolRenameMap::const_iterator renameSym
                                 = getLDInfo().scripts().renameMap().find(pName);
     if (renameSym != getLDInfo().scripts().renameMap().end())
       symbol_name = renameSym.getEntry()->value();
@@ -54,20 +54,21 @@
 }
 
 // defineSymbol - define a new symbol
-template<MCLinker::DefinePolicy POLICY, MCLinker::ResolvePolicy RESOLVE>
-LDSymbol* MCLinker::defineSymbol(const llvm::StringRef& pName,
-                                 bool pIsDyn,
-                                 ResolveInfo::Type pType,
-                                 ResolveInfo::Desc pDesc,
-                                 ResolveInfo::Binding pBinding,
-                                 ResolveInfo::SizeType pSize,
-                                 LDSymbol::ValueType pValue,
-                                 FragmentRef* pFragmentRef,
-                                 ResolveInfo::Visibility pVisibility)
+template<FragmentLinker::DefinePolicy POLICY,
+         FragmentLinker::ResolvePolicy RESOLVE>
+LDSymbol* FragmentLinker::defineSymbol(const llvm::StringRef& pName,
+                                       bool pIsDyn,
+                                       ResolveInfo::Type pType,
+                                       ResolveInfo::Desc pDesc,
+                                       ResolveInfo::Binding pBinding,
+                                       ResolveInfo::SizeType pSize,
+                                       LDSymbol::ValueType pValue,
+                                       FragmentRef* pFragmentRef,
+                                       ResolveInfo::Visibility pVisibility)
 {
   // These if/return should be optimized by compiler.
   // This function is defined for clarity.
-  if (MCLinker::Force == POLICY && MCLinker::Unresolve == RESOLVE)
+  if (FragmentLinker::Force == POLICY && FragmentLinker::Unresolve == RESOLVE)
     return defineSymbolForcefully(pName,
                                   pIsDyn,
                                   pType,
@@ -78,7 +79,7 @@
                                   pFragmentRef,
                                   pVisibility);
 
-  if (MCLinker::AsRefered == POLICY && MCLinker::Unresolve == RESOLVE)
+  if (FragmentLinker::AsRefered == POLICY && FragmentLinker::Unresolve == RESOLVE)
     return defineSymbolAsRefered(pName,
                                  pIsDyn,
                                  pType,
@@ -89,7 +90,7 @@
                                  pFragmentRef,
                                  pVisibility);
 
-  if (MCLinker::Force == POLICY && MCLinker::Resolve == RESOLVE)
+  if (FragmentLinker::Force == POLICY && FragmentLinker::Resolve == RESOLVE)
     return defineAndResolveSymbolForcefully(pName,
                                             pIsDyn,
                                             pType,
@@ -100,7 +101,7 @@
                                             pFragmentRef,
                                             pVisibility);
 
-  if (MCLinker::AsRefered == POLICY && MCLinker::Resolve == RESOLVE)
+  if (FragmentLinker::AsRefered == POLICY && FragmentLinker::Resolve == RESOLVE)
     return defineAndResolveSymbolAsRefered(pName,
                                            pIsDyn,
                                            pType,
diff --git a/include/mcld/LD/FragmentRef.h b/include/mcld/Fragment/FragmentRef.h
similarity index 62%
rename from include/mcld/LD/FragmentRef.h
rename to include/mcld/Fragment/FragmentRef.h
index 20b94c2..3fce7c9 100644
--- a/include/mcld/LD/FragmentRef.h
+++ b/include/mcld/Fragment/FragmentRef.h
@@ -6,25 +6,23 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_FRAGMENT_REFERENCE_H
-#define MCLD_LD_FRAGMENT_REFERENCE_H
+#ifndef MCLD_FRAGMENT_FRAGMENT_REFERENCE_H
+#define MCLD_FRAGMENT_FRAGMENT_REFERENCE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
+#include <mcld/Config/Config.h>
 #include <mcld/ADT/SizeTraits.h>
 #include <mcld/ADT/TypeTraits.h>
-#include <mcld/LD/Fragment.h>
+#include <mcld/Support/Allocators.h>
 
-namespace mcld
-{
+namespace mcld {
 
+class Fragment;
+class LDSection;
 class Layout;
 
-/// compunteFragmentSize - compute the specific Fragment size
-uint64_t computeFragmentSize(const Layout& pLayout,
-                             const Fragment& pFrag);
-
 /** \class FragmentRef
  *  \brief FragmentRef is a reference of a Fragment's contetnt.
  *
@@ -37,9 +35,21 @@
   typedef ConstTraits<unsigned char>::pointer ConstAddress;
 
 public:
-  FragmentRef();
-  FragmentRef(Fragment& pFrag, Offset pOffset = 0);
-  ~FragmentRef();
+  /// Create - create a fragment reference for a given fragment.
+  ///
+  /// @param pFrag - the given fragment
+  /// @param pOffset - the offset, can be larger than the fragment, but can not
+  ///                  be larger than the section size.
+  /// @return if the offset is legal, return the fragment reference. Otherwise,
+  /// return NULL.
+  static FragmentRef* Create(Fragment& pFrag, uint64_t pOffset);
+
+  static FragmentRef* Create(LDSection& pSection, uint64_t pOffset);
+
+  /// Clear - clear all generated FragmentRef in the system.
+  static void Clear();
+
+  static FragmentRef* Null();
 
   // -----  modifiers  ----- //
   FragmentRef& assign(const FragmentRef& pCopy);
@@ -55,6 +65,8 @@
   void memcpy(void* pDest, size_t pNBytes, Offset pOffset = 0) const;
 
   // -----  observers  ----- //
+  bool isNull() const { return (this == Null()); }
+
   Fragment* frag()
   { return m_pFragment; }
 
@@ -64,6 +76,8 @@
   Offset offset() const
   { return m_Offset; }
 
+  Offset getOutputOffset() const;
+
   // -----  dereference  ----- //
   Address deref();
 
@@ -74,10 +88,22 @@
 
   ConstAddress operator*() const
   { return deref(); }
+
+private:
+  friend FragmentRef& NullFragmentRef();
+  friend class Chunk<FragmentRef, MCLD_SECTIONS_PER_INPUT>;
+  friend class Relocation;
+
+  FragmentRef();
+
+  FragmentRef(Fragment& pFrag, Offset pOffset = 0);
   
 private:
   Fragment* m_pFragment;
   Offset m_Offset;
+
+  static FragmentRef g_NullFragmentRef;
+
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Fragment/NullFragment.h b/include/mcld/Fragment/NullFragment.h
new file mode 100644
index 0000000..1c84fae
--- /dev/null
+++ b/include/mcld/Fragment/NullFragment.h
@@ -0,0 +1,43 @@
+//===- NullFragment.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LD_NULL_FRAGMENT_H
+#define MCLD_LD_NULL_FRAGMENT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Fragment/Fragment.h>
+
+namespace mcld {
+
+class SectionData;
+
+/** \class NullFragment
+ *  \brief NullFragment is a kind of MCFragment that presents the "end fragment"
+ *         referenced by some special symbols
+ */
+class NullFragment : public Fragment
+{
+public:
+  NullFragment(SectionData* pSD = NULL);
+
+  /// size -
+  size_t size() const { return 0x0; }
+
+  static bool classof(const Fragment *F)
+  { return F->getKind() == Fragment::Null; }
+
+  static bool classof(const NullFragment *)
+  { return true; }
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/RegionFragment.h b/include/mcld/Fragment/RegionFragment.h
similarity index 80%
rename from include/mcld/LD/RegionFragment.h
rename to include/mcld/Fragment/RegionFragment.h
index 8aba1ef..e077264 100644
--- a/include/mcld/LD/RegionFragment.h
+++ b/include/mcld/Fragment/RegionFragment.h
@@ -6,18 +6,17 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #ifndef MCLD_LD_REGION_FRAGMENT_H
 #define MCLD_LD_REGION_FRAGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
-#include <mcld/LD/Fragment.h>
-#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Fragment/Fragment.h>
 
-namespace mcld
-{
+namespace mcld {
+
+class MemoryRegion;
 
 /** \class RegionFragment
  *  \brief RegionFragment is a kind of Fragment containing mcld::MemoryRegion
@@ -29,11 +28,8 @@
 
   ~RegionFragment();
 
-  MemoryRegion& getRegion()
-  { return m_Region; }
-
-  const MemoryRegion& getRegion() const
-  { return m_Region; }
+  const MemoryRegion& getRegion() const { return m_Region; }
+  MemoryRegion&       getRegion()       { return m_Region; }
 
   static bool classof(const Fragment *F)
   { return F->getKind() == Fragment::Region; }
@@ -41,6 +37,8 @@
   static bool classof(const RegionFragment *)
   { return true; }
 
+  size_t size() const;
+
 private:
   MemoryRegion& m_Region;
 };
diff --git a/include/mcld/LD/Relocation.h b/include/mcld/Fragment/Relocation.h
similarity index 68%
rename from include/mcld/LD/Relocation.h
rename to include/mcld/Fragment/Relocation.h
index fa77e64..c6584c4 100644
--- a/include/mcld/LD/Relocation.h
+++ b/include/mcld/Fragment/Relocation.h
@@ -6,25 +6,21 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_RELOCATION_H
-#define MCLD_LD_RELOCATION_H
+#ifndef MCLD_FRAGMENT_RELOCATION_H
+#define MCLD_FRAGMENT_RELOCATION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <llvm/ADT/ilist_node.h>
 #include <llvm/Support/DataTypes.h>
 
-#include <mcld/LD/Fragment.h>
-#include <mcld/LD/FragmentRef.h>
-#include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/FragmentRef.h>
 
+namespace mcld {
 
-namespace mcld
-{
-class Layout;
+class ResolveInfo;
 class RelocationFactory;
-class MCLDInfo;
+class LinkerConfig;
 
 class Relocation : public Fragment
 {
@@ -33,6 +29,7 @@
 public:
   typedef uint64_t Address; // FIXME: use SizeTrait<T>::Address instead
   typedef uint64_t DWord; // FIXME: use SizeTrait<T>::Word instead
+  typedef int64_t SWord; // FIXME: use SizeTrait<T>::SWord instead
   typedef uint8_t Type;
 
 private:
@@ -56,31 +53,26 @@
   { return m_Addend; }
 
   /// place - P value - address of the place being relocated
-  Address place(const Layout& pLayout) const;
+  Address place() const;
 
   /// symbol info - binding, type
-  const ResolveInfo* symInfo() const
-  { return m_pSymInfo; }
-
-  /// symbol info - binding, type
-  ResolveInfo* symInfo()
-  { return m_pSymInfo; }
+  const ResolveInfo* symInfo() const { return m_pSymInfo; }
+  ResolveInfo*       symInfo()       { return m_pSymInfo; }
 
   /// target - the target data to relocate
-  DWord& target();
-
-  /// target - the target data to relocate
-  const DWord& target() const;
+  const DWord& target() const { return m_TargetData; }
+  DWord&       target()       { return m_TargetData; }
 
   /// targetRef - the reference of the target data
-  FragmentRef& targetRef()
-  { return m_TargetAddress; }
+  const FragmentRef& targetRef() const { return m_TargetAddress; }
+  FragmentRef&       targetRef()       { return m_TargetAddress; }
 
-  /// targetRef - the reference of the target data
-  const FragmentRef& targetRef() const
-  { return m_TargetAddress; }
 
-  void apply(RelocationFactory& pRelocFactory, const MCLDInfo& pLDInfo);
+  void apply(RelocationFactory& pRelocFactory);
+
+  /// updateAddend - A relocation with a section symbol must update addend
+  /// before reading its value.
+  void updateAddend();
 
   /// ----- modifiers ----- ///
   void setType(Type pType);
@@ -92,7 +84,11 @@
   // Relocation is a kind of Fragment with type of FT_Reloc
   static bool classof(const Fragment *F)
   { return F->getKind() == Fragment::Relocation; }
-  static bool classof(const Relocation *) { return true; }
+
+  static bool classof(const Relocation *)
+  { return true; }
+
+  size_t size() const;
 
 private:
   /// m_Type - the type of the relocation entries
diff --git a/include/mcld/Fragment/Stub.h b/include/mcld/Fragment/Stub.h
new file mode 100644
index 0000000..11a1db4
--- /dev/null
+++ b/include/mcld/Fragment/Stub.h
@@ -0,0 +1,134 @@
+//===- Stub.h -------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_FRAGMENT_STUB_H
+#define MCLD_FRAGMENT_STUB_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/Relocation.h>
+#include <vector>
+#include <string>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+class Stub: public Fragment
+{
+public:
+  typedef Relocation::DWord DWord;
+  typedef Relocation::SWord SWord;
+  typedef Relocation::Type  Type;
+
+  class Fixup
+  {
+  public:
+    Fixup(DWord pOffset, SWord pAddend, Type pType)
+     : m_Offset(pOffset), m_Addend(pAddend), m_Type(pType)
+    { }
+
+    ~Fixup()
+    { }
+
+    DWord offset() const { return m_Offset; }
+
+    SWord addend() const { return m_Addend; }
+
+    Type  type() const   { return m_Type; }
+
+  private:
+    DWord m_Offset;
+    SWord m_Addend;
+    Type  m_Type;
+  };
+
+public:
+  typedef std::vector<Fixup*> FixupListType;
+  typedef FixupListType::iterator fixup_iterator;
+  typedef FixupListType::const_iterator const_fixup_iterator;
+
+public:
+  Stub();
+
+  virtual ~Stub();
+
+  /// clone - clone function for stub factory to create the corresponding stub
+  Stub* clone() { return doClone(); }
+
+  /// isMyDuty - return true when the pReloc is problematic and the stub is able
+  /// to fix it!
+  virtual bool isMyDuty(const class Relocation& pReloc,
+                        uint64_t pSource,
+                        uint64_t pTargetSymValue) const = 0;
+
+  /// name - name of this stub
+  virtual const std::string& name() const = 0;
+
+  /// getContent - content of the stub
+  virtual const uint8_t* getContent() const = 0;
+
+  /// size - size of the stub
+  virtual size_t size() const = 0;
+
+  /// alignment - alignment of the stub
+  virtual size_t alignment() const = 0;
+
+  /// symInfo - ResolveInfo of this Stub
+  ResolveInfo* symInfo()             { return m_pSymInfo; }
+
+  const ResolveInfo* symInfo() const { return m_pSymInfo; }
+
+  /// symValue - initial value for stub's symbol
+  virtual uint64_t initSymValue() const  { return 0x0; }
+
+  ///  -----  Fixup  -----  ///
+  fixup_iterator       fixup_begin()       { return m_FixupList.begin(); }
+
+  const_fixup_iterator fixup_begin() const { return m_FixupList.begin(); }
+
+  fixup_iterator       fixup_end()         { return m_FixupList.end();   }
+
+  const_fixup_iterator fixup_end()   const { return m_FixupList.end();   }
+
+  /// ----- modifiers ----- ///
+  void setSymInfo(ResolveInfo* pSymInfo);
+
+  // Stub is a kind of Fragment with type of Stub
+  static bool classof(const Fragment *F)
+  { return F->getKind() == Fragment::Stub; }
+
+  static bool classof(const Stub *)
+  { return true; }
+
+protected:
+  /// addFixup - add a fixup for this stub to build a relocation
+  void addFixup(DWord pOffset, SWord pAddend, Type pType);
+
+  /// addFixup - add a fixup from a existing fixup of the prototype
+  void addFixup(const Fixup& pFixup);
+
+private:
+  /// doClone - when adding a backend stub, we should implement this function
+  virtual Stub* doClone() = 0;
+
+private:
+  ResolveInfo* m_pSymInfo;
+  FixupListType m_FixupList;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/TargetFragment.h b/include/mcld/Fragment/TargetFragment.h
similarity index 90%
rename from include/mcld/LD/TargetFragment.h
rename to include/mcld/Fragment/TargetFragment.h
index 92af5a0..665fcea 100644
--- a/include/mcld/LD/TargetFragment.h
+++ b/include/mcld/Fragment/TargetFragment.h
@@ -6,17 +6,15 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #ifndef MCLD_LD_TARGET_FRAGMENT_H
 #define MCLD_LD_TARGET_FRAGMENT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class SectionData;
 
@@ -33,9 +31,6 @@
 public:
   virtual ~TargetFragment() {}
 
-  virtual size_t getSize() const = 0;
-
-public:
   static bool classof(const Fragment *F)
   { return F->getKind() == Fragment::Target; }
 
diff --git a/include/mcld/MC/MCLDOptions.h b/include/mcld/GeneralOptions.h
similarity index 78%
rename from include/mcld/MC/MCLDOptions.h
rename to include/mcld/GeneralOptions.h
index ad857cb..0b5c7a9 100644
--- a/include/mcld/MC/MCLDOptions.h
+++ b/include/mcld/GeneralOptions.h
@@ -1,4 +1,4 @@
-//===- MCLDOptions.h ------------------------------------------------------===//
+//===- GeneralOptions.h ---------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,48 +6,21 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_OPTIONS_H
-#define MCLD_OPTIONS_H
+#ifndef MCLD_GENERAL_OPTIONS_H
+#define MCLD_GENERAL_OPTIONS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <string>
-#include <llvm/ADT/StringRef.h>
-#include <mcld/ADT/StringEntry.h>
-#include <mcld/ADT/HashTable.h>
 #include <mcld/Support/RealPath.h>
 #include <mcld/Support/FileSystem.h>
 #include <mcld/MC/SearchDirs.h>
 #include <mcld/MC/ZOption.h>
 
-namespace mcld
-{
+namespace mcld {
+
 class Input;
 
-/** \class ScriptOptions
- *
- */
-class ScriptOptions
-{
-public:
-  typedef HashTable<StringEntry<llvm::StringRef>,
-                    StringHash<ELF>,
-                    StringEntryFactory<llvm::StringRef> > SymbolRenameMap;
-
-public:
-  ScriptOptions();
-  ~ScriptOptions();
-
-  SymbolRenameMap& renameMap()
-  { return m_SymbolRenames; }
-
-  const SymbolRenameMap& renameMap() const
-  { return m_SymbolRenames; }
-
-private:
-  SymbolRenameMap m_SymbolRenames;
-};
-
 /** \class GeneralOptions
  *  \brief GeneralOptions collects the options that not be one of the
  *     - input files
@@ -66,8 +39,7 @@
   void setDefaultLDScript(const std::string& pFilename);
 
   /// sysroot
-  const sys::fs::Path& sysroot() const
-  { return m_Sysroot; }
+  const sys::fs::Path& sysroot() const;
 
   void setSysroot(const sys::fs::Path &pPath);
 
@@ -85,7 +57,7 @@
   bool trace() const
   { return m_bTrace; }
 
-  void setBsymbolic(bool pBsymbolic = false)
+  void setBsymbolic(bool pBsymbolic = true)
   { m_Bsymbolic = pBsymbolic; }
 
   bool Bsymbolic() const
@@ -97,7 +69,7 @@
   bool isPIE() const
   { return m_bPIE; }
 
-  void setBgroup(bool pBgroup = false)
+  void setBgroup(bool pBgroup = true)
   { m_Bgroup = pBgroup; }
 
   bool Bgroup() const
@@ -121,6 +93,11 @@
   bool hasDyld() const
   { return !m_Dyld.empty(); }
 
+  void setSOName(const std::string& pName);
+
+  const std::string& soname() const
+  { return m_SOName; }
+
   void setAllowShlibUndefined(bool pEnabled = true)
   { m_bAllowShlibUndefined = pEnabled; }
 
@@ -151,10 +128,10 @@
   bool color() const
   { return m_bColor; }
 
-  void setNoUndefined(bool pEnable = false)
+  void setNoUndefined(bool pEnable = true)
   { m_bNoUndefined = pEnable; }
 
-  void setMulDefs(bool pEnable = false)
+  void setMulDefs(bool pEnable = true)
   { m_bMulDefs = pEnable; }
 
   void setEhFrameHdr(bool pEnable = true)
@@ -220,6 +197,41 @@
   bool hasEhFrameHdr() const
   { return m_bCreateEhFrameHdr; }
 
+  // -n, --nmagic
+  void setNMagic(bool pMagic = true)
+  { m_NMagic = pMagic; }
+
+  bool nnagic() const
+  { return m_NMagic; }
+
+  // -N, --omagic
+  void setOMagic(bool pMagic = true)
+  { m_OMagic = pMagic; }
+
+  bool omagic() const
+  { return m_OMagic; }
+
+  // -S, --strip-debug
+  void setStripDebug(bool pStripDebug = true)
+  { m_StripDebug = pStripDebug; }
+
+  bool stripDebug() const
+  { return m_StripDebug; }
+
+  // -E, --export-dynamic
+  void setExportDynamic(bool pExportDynamic = true)
+  { m_ExportDynamic = pExportDynamic; }
+
+  bool exportDynamic() const
+  { return m_ExportDynamic; }
+
+  // --warn-shared-textrel
+  void setWarnSharedTextrel(bool pWarnSharedTextrel = true)
+  { m_WarnSharedTextrel = pWarnSharedTextrel; }
+
+  bool warnSharedTextrel() const
+  { return m_WarnSharedTextrel; }
+
 private:
   enum status {
     YES,
@@ -230,10 +242,10 @@
 private:
   Input* m_pDefaultBitcode;
   std::string m_DefaultLDScript;
-  sys::fs::RealPath m_Sysroot;
   SearchDirs m_SearchDirs;
   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
@@ -261,6 +273,11 @@
   bool m_bColor         : 1;   // --color[=true,false,auto]
   bool m_bAllowShlibUndefined : 1; // --[no-]allow-shlib-undefined and
   bool m_bCreateEhFrameHdr : 1;    // --eh-frame-hdr
+  bool m_NMagic; // -n, --nmagic
+  bool m_OMagic; // -N, --omagic
+  bool m_StripDebug; // -S, --strip-debug
+  bool m_ExportDynamic; //-E, --export-dynamic
+  bool m_WarnSharedTextrel; // --warn-shared-textrel
 };
 
 } // namespace of mcld
diff --git a/include/mcld/IRBuilder.h b/include/mcld/IRBuilder.h
new file mode 100644
index 0000000..1ebd153
--- /dev/null
+++ b/include/mcld/IRBuilder.h
@@ -0,0 +1,372 @@
+//===- IRBuilder.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// IRBuilder is a class used as a convenient way to create MCLinker sections
+// with a consistent and simplified interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_IRBUILDER_H
+#define MCLD_IRBUILDER_H
+
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/InputBuilder.h>
+
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/EhFrame.h>
+
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/FillFragment.h>
+
+#include <mcld/Support/Path.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/raw_mem_ostream.h>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+class InputTree;
+
+/** \class IRBuilder
+ *  \brief IRBuilder provides an uniform API for creating sections and
+ *  inserting them into a input file.
+ *
+ *  Ahead-of-time virtual machines (VM) usually compiles an intermediate
+ *  language into a system-dependent binary.  IRBuilder helps such kind of VMs
+ *  to emit binaries in native object format, such as ELF or MachO.
+ */
+class IRBuilder
+{
+public:
+  enum ObjectFormat {
+    ELF,
+    MachO,
+    COFF
+  };
+
+public:
+  IRBuilder(Module& pModule, const LinkerConfig& pConfig);
+
+  ~IRBuilder();
+
+  const InputBuilder& getInputBuilder() const { return m_InputBuilder; }
+  InputBuilder&       getInputBuilder()       { return m_InputBuilder; }
+
+/// @}
+/// @name Input Files On The Command Line
+/// @{
+
+  /// CreateInput - To create an input file and append it to the input tree.
+  /// This function is like to add an input file in the command line.
+  ///
+  /// There are four types of the input files:
+  ///   - relocatable objects,
+  ///   - shared objects,
+  ///   - archives,
+  ///   - and user-defined objects.
+  ///
+  /// If Input::Unknown type is given, MCLinker will automatically
+  /// open and read the input file, and create sections of the input. Otherwise,
+  /// users need to manually create sections by IRBuilder.
+  ///
+  /// @see mcld::Input
+  ///
+  /// @param pName [in] The name of the input file.
+  /// @param pPath [in] The path of the input file.
+  /// @param pType [in] The type of the input file. MCLinker will parse the
+  ///                   input file to create sections only if pType is
+  ///                   Input::Unknown.
+  /// @return the created mcld::Input.
+  Input* CreateInput(const std::string& pName,
+                     const sys::fs::Path& pPath,
+                     Input::Type pType);
+
+  /// ReadInput - To read an input file and append it to the input tree.
+  /// This function is like to add an input file in the command line.
+  ///
+  /// This funciton is equal to call
+  ///   @ref IRBuilder::CreateInput(pName, pPath, Input::Unknown);
+  ///
+  /// MCLinker will automatically open and read the input file, and create
+  /// sections of the input.
+  ///
+  /// @see mcld::Input
+  ///
+  /// @param pName [in] The name of the input file.
+  /// @param pPath [in] The path of the input file.
+  /// @return the created mcld::Input.
+  Input* ReadInput(const std::string& pName, const sys::fs::Path& pPath);
+
+  /// ReadInput - To read an input file and append it to the input tree.
+  ///
+  /// This function is equal to -l option. This function tells MCLinker to
+  /// search for lib[pNameSpec].so or lib[pNameSpec].a in the search path.
+  ///
+  /// @param pNameSpec [in] The namespec of the input file.
+  /// @return the created mcld::Input.
+  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);
+
+  /// 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.
+  ///
+  /// This function tells MCLinker to read pRawMemory as an image of an object
+  /// file. So far, MCLinekr only supports ELF object format, but it will
+  /// support various object formats in the future. MCLinker relies triple to
+  /// know the object format of pRawMemory.
+  /// @param [in] pName      The name of the input file
+  /// @param [in] pRawMemory An image of object file
+  /// @param [in] pSize      The size of the memory
+  /// @return The created mcld::Input
+  Input* ReadInput(const std::string& pName, void* pRawMemory, size_t pSize);
+
+  /// StartGroup - Add an opening tag of group.
+  ///
+  /// This function is equal to --start-group option. This function tells
+  /// MCLinker to create a new archive group and to add the following archives
+  /// in the created group. The archives in a group are searched repeatedly
+  /// until no new undefined references are created.
+  bool StartGroup();
+
+  /// EndGroup - Add a closing tag of group.
+  ///
+  /// This function is equal to --end-group option. This function tells
+  /// MCLinker to stop adding following archives in the created group.
+  bool EndGroup();
+
+/// @}
+/// @name Positional Options On The Command Line
+/// @{
+
+  /// WholeArchive - Append a --whole-archive option on the command line
+  ///
+  /// This function is equal to --whole-archive option. This function tells
+  /// MCLinker to include every object files in the following archives.
+  void WholeArchive();
+
+  /// NoWholeArchive - Append a --no-whole-archive option on the command line.
+  ///
+  /// This function is equal to --no-whole-archive option. This function tells
+  /// MCLinker to stop including every object files in the following archives.
+  /// Only used object files in the following archives are included.
+  void NoWholeArchive();
+
+  /// AsNeeded - Append a --as-needed option on the command line.
+  ///
+  /// This function is equal to --as-needed option. This function tells
+  /// MCLinker to not add a DT_NEEDED tag in .dynamic sections for the
+  /// following shared objects that are not really used. MCLinker will add tags
+  //  only for the following shared objects which is really used.
+  void AsNeeded();
+
+  /// NoAsNeeded - Append a --no-as-needed option on the command line.
+  ///
+  /// This function is equal to --no-as-needed option. This function tells
+  /// MCLinker to add a DT_NEEDED tag in .dynamic section for every shared
+  /// objects that is created after this option.
+  void NoAsNeeded();
+
+  /// CopyDTNeeded - Append a --add-needed option on the command line.
+  ///
+  /// This function is equal to --add-needed option. This function tells
+  /// NCLinker to copy all DT_NEEDED tags of every following shared objects
+  /// to the output file.
+  void CopyDTNeeded();
+
+  /// NoCopyDTNeeded - Append a --no-add-needed option on the command line.
+  ///
+  /// This function is equal to --no-add-needed option. This function tells
+  /// MCLinker to stop copying all DT_NEEDS tags in the following shared
+  /// objects to the output file.
+  void NoCopyDTNeeded();
+
+  /// AgainstShared - Append a -Bdynamic option on the command line.
+  ///
+  /// This function is equal to -Bdynamic option. This function tells MCLinker
+  /// to search shared objects before archives for the following namespec.
+  void AgainstShared();
+
+  /// AgainstStatic - Append a -static option on the command line.
+  ///
+  /// This function is equal to -static option. This function tells MCLinker to
+  /// search archives before shared objects for the following namespec.
+  void AgainstStatic();
+
+/// @}
+/// @name Input Methods
+/// @{
+
+  /// CreateELFHeader - To create and append a section header in the input file
+  ///
+  /// @param OF     [in]      The file format. @see ObjectFormat
+  /// @param pInput [in, out] The input file.
+  /// @param pName  [in]      The name of the section.
+  /// @param pType  [in]      The meaning of the content in the section. The
+  ///                         value is format-dependent. In ELF, the value is
+  ///                         SHT_* in normal.
+  /// @param pFlag  [in]      The format-dependent flag. In ELF, the value is
+  ///                         SHF_* in normal.
+  /// @param pAlign [in]      The alignment constraint of the section
+  /// @return The created section header.
+  static LDSection* CreateELFHeader(Input& pInput,
+                                    const std::string& pName,
+                                    uint32_t pType,
+                                    uint32_t pFlag,
+                                    uint32_t pAlign);
+
+  /// CreateSectionData - To create a section data for given pSection.
+  /// @param [in, out] pSection The given LDSection. It can be in either an
+  ///         input or the output.
+  ///         pSection.getSectionData() is set to a valid section data.
+  /// @return The created section data. If the pSection already has section
+  ///         data, or if the pSection's type should not have a section data
+  ///         (.eh_frame or relocation data), then an assertion occurs.
+  static SectionData* CreateSectionData(LDSection& pSection);
+
+  /// CreateRelocData - To create a relocation data for given pSection.
+  /// @param [in, out] pSection The given LDSection. It can be in either an
+  ///         input or the output.
+  ///         pSection.getRelocData() is set to a valid relocation data.
+  /// @return The created relocation data. If the pSection already has
+  ///         relocation data, or if the pSection's type is not
+  ///         LDFileFormat::Relocation, then an assertion occurs.
+  static RelocData* CreateRelocData(LDSection &pSection);
+
+  /// CreateEhFrame - To create a eh_frame for given pSection
+  /// @param [in, out] pSection The given LDSection. It can be in either an
+  ///         input or the output.
+  ///         pSection.getEhFrame() is set to a valid eh_frame.
+  /// @return The created eh_frame. If the pSection already has eh_frame data,
+  ///         or if the pSection's type is not LDFileFormat::EhFrame, then an
+  ///         assertion occurs.
+  static EhFrame* CreateEhFrame(LDSection& pSection);
+
+  /// CreateBSS - To create a bss section for given pSection
+  /// @param [in, out] pSection The given LDSection. It can be in either an
+  ///         input or the output.
+  ///         pSection.getSectionData() is set to a valid section data and
+  ///         contains a fillment fragment whose size is pSection.size().
+  /// @return The create section data. It the pSection already has a section
+  ///         data, or if the pSection's type is not LDFileFormat::BSS, then
+  ///         an assertion occurs.
+  static SectionData* CreateBSS(LDSection& pSection);
+
+  /// CreateRegion - To create a region fragment in the input file.
+  /// This function tells MCLinker to read a piece of data from the input
+  /// file, and to create a region fragment that carries the data. The data
+  /// will be deallocated automatically when pInput is destroyed.
+  ///
+  /// @param pInput  [in, out] The input file.
+  /// @param pOffset [in]      The starting file offset of the data
+  /// @param pLength [in]      The number of bytes of the data
+  /// @return If pLength is zero or failing to request a region, return a
+  ///         FillFragment.
+  static Fragment* CreateRegion(Input& pInput, size_t pOffset, size_t pLength);
+
+  /// CreateRegion - To create a region fragment wrapping the given memory.
+  /// This function tells MCLinker to create a region fragment by the data
+  /// directly. Since the data is given from outside, not read from the input
+  /// file, users should deallocated the data manually.
+  ///
+  /// @param pMemory [in] The start address of the given data
+  /// @param pLength [in] The number of bytes of the data
+  /// @return If pLength is zero or failing to request a region, return a
+  ///         FillFragment.
+  static Fragment* CreateRegion(void* pMemory, size_t pLength);
+
+  /// AppendFragment - To append pFrag to the given SectionData pSD.
+  /// This function tells MCLinker to append a fragment to section data, and
+  /// update size of the section header.
+  ///
+  /// @note In order to keep the alignment of pFrag, This function inserts an
+  /// AlignFragment before pFrag if the section header's alignment is larger
+  /// than 1.
+  /// @note This function does not update offset of section headers.
+  ///
+  /// @param pFrag [in, out] The appended fragment. Its offset is set as the
+  ///                        section offset in pSD.
+  /// @param pSD   [in, out] The section data. Size of the header is also
+  ///                        updated.
+  /// @return Total size of the inserted fragments.
+  static uint64_t AppendFragment(Fragment& pFrag, SectionData& pSD);
+
+  /// AppendRelocation - To append a relocation to a relocation data.
+  /// This function tells MCLinker to add a general relocation to the
+  /// relocation data. This function does not update offset and size of section
+  /// headers.
+  ///
+  /// @param pReloc [in]      The appended relocation.
+  /// @param pRD    [in, out] The relocation data being appended.
+  static void AppendRelocation(Relocation& pRelocation, RelocData& pRD);
+
+  /// AppendEhFrame - To append a fragment to a EhFrame.
+  /// @note In order to keep the alignment of pFrag, This function inserts an
+  /// AlignFragment before pFrag if the section header's alignment is larger
+  /// than 1.
+  /// @note This function also update size of the section header, but does not
+  /// update header's offset.
+  ///
+  /// @param pFrag    [in, out] The appended fragment.
+  /// @param pEhFrame [in, out] The EhFrame.
+  /// @return Total size of the inserted fragments.
+  static uint64_t AppendEhFrame(Fragment& pFrag, EhFrame& pEhFrame);
+
+  /// AppendEhFrame - To append a FDE to the given EhFrame pEhFram.
+  /// @note In order to keep the alignment of pFrag, This function inserts an
+  /// AlignFragment before pFrag if the section header's alignment is larger
+  /// than 1.
+  /// @note This function also update size of the section header, but does not
+  /// update header's offset.
+  ///
+  /// @param [in, out] pFDE The appended FDE entry.
+  /// @param [in, out] pEhFrame The eh_frame being appended.
+  /// @return Total size of the inserted fragments.
+  static uint64_t AppendEhFrame(EhFrame::FDE& pFDE, EhFrame& pEhFrame);
+
+  /// AppendEhFrame - To append a CIE to the given EhFrame pEhFram.
+  /// @note In order to keep the alignment of pFrag, This function inserts an
+  /// AlignFragment before pFrag if the section header's alignment is larger
+  /// than 1.
+  /// @note This function also update size of the section header, but does not
+  /// update header's offset.
+  ///
+  /// @param [in, out] pCIE The appended CIE entry.
+  /// @param [in, out] pEhFrame The eh_frame being appended.
+  /// @return Total size of the inserted fragments.
+  static uint64_t AppendEhFrame(EhFrame::CIE& pCIE, EhFrame& pEhFrame);
+
+private:
+  Module& m_Module;
+  const LinkerConfig& m_Config;
+
+  InputBuilder m_InputBuilder;
+};
+
+} // end of namespace mcld
+
+#endif
diff --git a/include/mcld/MC/InputTree.h b/include/mcld/InputTree.h
similarity index 70%
rename from include/mcld/MC/InputTree.h
rename to include/mcld/InputTree.h
index 5916916..2981ebe 100644
--- a/include/mcld/MC/InputTree.h
+++ b/include/mcld/InputTree.h
@@ -6,23 +6,21 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_INPUT_TREE_H
-#define MCLD_INPUT_TREE_H
+#ifndef MCLD_MC_INPUT_TREE_H
+#define MCLD_MC_INPUT_TREE_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/InputFactory.h"
-#include "mcld/Support/FileSystem.h"
+#include <mcld/ADT/BinTree.h>
+#include <mcld/ADT/TypeTraits.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/Path.h>
 
 #include <string>
 
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input>
  *  \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator
@@ -49,11 +47,12 @@
   virtual ~PolicyIterator() {}
 
   bool isGroup() const
-  { return !Base::hasData(); }
+  { return !Base::hasData() && !Base::isRoot(); }
 
   Self& operator++() {
     IteratorType::advance();
-    if (isGroup())
+    // skip the Group node
+    while (isGroup())
       IteratorType::advance();
     return *this;
   }
@@ -61,7 +60,8 @@
   Self operator++(int) {
     Self tmp(*this);
     IteratorType::advance();
-    if (isGroup())
+    // skip the Group node
+    while (isGroup())
       IteratorType::advance();
     return tmp;
   }
@@ -137,54 +137,25 @@
 
   using BinTreeTy::merge;
 
-  InputTree(InputFactory& pInputFactory);
-  ~InputTree();
-
   // -----  modify  ----- //
-  /// insert - create a leaf node and merge it in the tree.
-  //  This version of join determines the direction at run time.
-  //  @param pRoot  position the parent node
-  //  @param pMover the direction of the connecting edge of the parent node.
-  template<size_t DIRECT>
-  InputTree& insert(TreeIteratorBase pRoot,
-                    const std::string& pNamespec,
-                    const sys::fs::Path& pPath,
-                    unsigned int pType = Input::Unknown);
-
   template<size_t DIRECT>
   InputTree& enterGroup(TreeIteratorBase pRoot);
 
   template<size_t DIRECT>
   InputTree& insert(TreeIteratorBase pRoot,
-                    const Input& pInput);
+                    Input& pInput);
 
-  InputTree& merge(TreeIteratorBase pRoot, 
+  InputTree& merge(TreeIteratorBase pRoot,
                    const Mover& pMover,
                    InputTree& pTree);
 
   InputTree& insert(TreeIteratorBase pRoot,
                     const Mover& pMover,
-                    const std::string& pNamespec,
-                    const sys::fs::Path& pPath,
-                    unsigned int pType = Input::Unknown);
-
-  InputTree& insert(TreeIteratorBase pRoot,
-                    const Mover& pMover,
-                    const Input& pInput);
+                    Input& pInput);
 
   InputTree& enterGroup(TreeIteratorBase pRoot,
                         const Mover& pMover);
 
-  // -----  observers  ----- //
-  unsigned int numOfInputs() const
-  { return m_FileFactory.size(); }
-
-  bool hasInput() const
-  { return !m_FileFactory.empty(); }
-
-private:
-  InputFactory& m_FileFactory;
-
 };
 
 bool isGroup(const InputTree::iterator& pos);
@@ -198,29 +169,12 @@
 
 //===----------------------------------------------------------------------===//
 // template member functions
-template<size_t DIRECT>
-mcld::InputTree&
-mcld::InputTree::insert(mcld::TreeIteratorBase pRoot,
-                        const std::string& pNamespec,
-                        const mcld::sys::fs::Path& pPath,
-                        unsigned int pType)
-{
-  BinTreeTy::node_type* node = createNode();
-  node->data = m_FileFactory.produce(pNamespec, pPath, pType); 
-  if (pRoot.isRoot())
-    proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
-        const_cast<const node_type*>(node));
-  else
-    proxy::hook<DIRECT>(pRoot.m_pNode,
-        const_cast<const node_type*>(node));
-  return *this;
-}
-
+//===----------------------------------------------------------------------===//
 template<size_t DIRECT>
 mcld::InputTree&
 mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot)
 {
-  BinTreeTy::node_type* node = createNode(); 
+  BinTreeTy::node_type* node = createNode();
   if (pRoot.isRoot())
     proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
         const_cast<const node_type*>(node));
@@ -232,10 +186,10 @@
 
 template<size_t DIRECT>
 mcld::InputTree& mcld::InputTree::insert(mcld::TreeIteratorBase pRoot,
-	                                 const mcld::Input& pInput)
+	                                 mcld::Input& pInput)
 {
   BinTreeTy::node_type* node = createNode();
-  node->data = const_cast<mcld::Input*>(&pInput);
+  node->data = &pInput;
   if (pRoot.isRoot())
     proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
                                          const_cast<const node_type*>(node));
diff --git a/include/mcld/LD/Archive.h b/include/mcld/LD/Archive.h
index 12b574c..53cf2a5 100644
--- a/include/mcld/LD/Archive.h
+++ b/include/mcld/LD/Archive.h
@@ -12,19 +12,23 @@
 #include <gtest.h>
 #endif
 
+#include <mcld/InputTree.h>
 #include <mcld/ADT/HashEntry.h>
 #include <mcld/ADT/HashTable.h>
 #include <mcld/ADT/StringHash.h>
 #include <mcld/Support/GCFactory.h>
-#include <mcld/MC/InputTree.h>
 
 #include <vector>
 #include <string>
 
-namespace mcld
-{
-class InputTree;
+namespace mcld {
+
 class Input;
+class InputFactory;
+class InputBuilder;
+class AttributeFactory;
+class ContextFactory;
+class MemoryAreaFactory;
 
 /** \class Archive
  *  \brief This class define the interfacee to Archive files
@@ -63,13 +67,12 @@
   {
     size_t operator()(uint32_t pKey) const
     {
-      size_t h;
-      h ^= h >> 16;
-      h *= 0x85ebca6b;
-      h ^= h >> 13;
-      h *= 0xc2b2ae35;
-      h ^= h >> 16;
-      return h;
+      pKey ^= pKey >> 16;
+      pKey *= 0x85ebca6b;
+      pKey ^= pKey >> 13;
+      pKey *= 0xc2b2ae35;
+      pKey ^= pKey >> 16;
+      return pKey;
     }
   };
 
@@ -126,7 +129,7 @@
   typedef std::vector<Symbol*> SymTabType;
 
 public:
-  Archive(Input& pInputFile, InputFactory& pInputFactory);
+  Archive(Input& pInputFile, InputBuilder& pBuilder);
 
   ~Archive();
 
@@ -223,6 +226,21 @@
   /// getStrTable - get the extended name table
   const std::string& getStrTable() const;
 
+  /// hasStrTable - return true if this archive has extended name table
+  bool hasStrTable() const;
+
+  /// getMemberFile       - get the member file in an archive member
+  /// @param pArchiveFile - Input reference of the archive member
+  /// @param pIsThinAR    - denote the archive menber is a Thin Archive or not
+  /// @param pName        - the name of the member file we want to get
+  /// @param pPath        - the path of the member file
+  /// @param pFileOffset  - the file offset of the member file in a regular AR
+  Input* getMemberFile(Input& pArchiveFile,
+                       bool isThinAR,
+                       const std::string& pName,
+                       const sys::fs::Path& pPath,
+                       off_t pFileOffset = 0);
+
 private:
   typedef GCFactory<Symbol, 0> SymbolFactory;
 
@@ -235,6 +253,7 @@
   SymTabType m_SymTab;
   size_t m_SymTabSize;
   std::string m_StrTab;
+  InputBuilder& m_Builder;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/BranchIsland.h b/include/mcld/LD/BranchIsland.h
index 8e5cf9c..9de1380 100644
--- a/include/mcld/LD/BranchIsland.h
+++ b/include/mcld/LD/BranchIsland.h
@@ -6,22 +6,163 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef BRANCHISLAND_H
-#define BRANCHISLAND_H
+#ifndef MCLD_LD_BRANCH_ISLAND_H
+#define MCLD_LD_BRANCH_ISLAND_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
+#include <llvm/Support/DataTypes.h>
+#include <llvm/ADT/StringRef.h>
+#include <mcld/ADT/HashEntry.h>
+#include <mcld/ADT/HashTable.h>
+#include <mcld/ADT/StringHash.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+
 namespace mcld
 {
 
+class Stub;
+class Relocation;
+
 /** \class BranchIsland
  *  \brief BranchIsland is a collection of stubs
  *
  */
 class BranchIsland
 {
+public:
+  typedef SectionData::iterator iterator;
+  typedef SectionData::const_iterator const_iterator;
 
+  typedef std::vector<Relocation*> RelocationListType;
+  typedef RelocationListType::iterator reloc_iterator;
+  typedef RelocationListType::const_iterator const_reloc_iterator;
+
+public:
+  /*
+   *               ----------
+   *  --- Entry -> | Island | -> Exit ---
+   *               ----------
+   */
+
+  /// BranchIsland - constructor
+  /// @param pEntryFrag - the entry fragment to the island
+  /// @param pMaxSize   - the max size the island can be
+  /// @param pIndex     - the inedx in the island factory
+  BranchIsland(Fragment& pEntryFrag, size_t pMaxSize, size_t pIndex);
+
+  ~BranchIsland();
+
+  /// fragment iterators of the island
+  iterator begin();
+
+  const_iterator begin() const;
+
+  iterator end();
+
+  const_iterator end() const;
+
+  /// relocation iterators of the island
+  reloc_iterator reloc_begin()
+  { return m_Relocations.begin(); }
+
+  const_reloc_iterator reloc_begin() const
+  { return m_Relocations.begin(); }
+
+  reloc_iterator reloc_end()
+  { return m_Relocations.end(); }
+
+  const_reloc_iterator reloc_end() const
+  { return m_Relocations.end(); }
+
+  /// observers
+  uint64_t offset() const;
+
+  size_t size() const;
+
+  size_t maxSize() const;
+
+  const std::string& name() const;
+
+  size_t numOfStubs() const;
+
+  /// findStub - return true if there is a stub built from the given prototype
+  ///            for the given relocation
+  Stub* findStub(const Stub* pPrototype, const Relocation& pReloc);
+
+  /// addStub - add a stub into the island
+  bool addStub(const Stub* pPrototype, const Relocation& pReloc, Stub& pStub);
+
+  /// addRelocation - add a relocation into island
+  bool addRelocation(Relocation& pReloc);
+
+private:
+  /** \class Key
+   *  \brief Key to recognize a stub in the island.
+   *
+   */
+  class Key
+  {
+  public:
+    Key(const Stub* pPrototype, const LDSymbol* pSymbol, Stub::SWord pAddend)
+    : m_pPrototype(pPrototype), m_pSymbol(pSymbol), m_Addend(pAddend)
+    { }
+
+    ~Key()
+    { }
+
+    const Stub*  prototype() const { return m_pPrototype; }
+
+    const LDSymbol* symbol() const { return m_pSymbol; }
+
+    Stub::SWord     addend() const { return m_Addend; }
+
+    struct Hash
+    {
+      size_t operator() (const Key& KEY) const
+      {
+        llvm::StringRef sym_name(KEY.symbol()->name());
+        StringHash<ELF> str_hasher;
+        return (size_t((uintptr_t)KEY.prototype())) ^
+               str_hasher(sym_name) ^
+               KEY.addend();
+      }
+    };
+
+    struct Compare
+    {
+      bool operator() (const Key& KEY1, const Key& KEY2) const
+      {
+        return (KEY1.prototype() == KEY2.prototype()) &&
+               (KEY1.symbol() == KEY2.symbol()) &&
+               (KEY1.addend() == KEY2.addend());
+      }
+    };
+
+  private:
+    const Stub* m_pPrototype;
+    const LDSymbol* m_pSymbol;
+    Stub::SWord m_Addend;
+  };
+
+  typedef HashEntry<Key, Stub*, Key::Compare> StubEntryType;
+
+  typedef HashTable<StubEntryType,
+                    Key::Hash,
+                    EntryFactory<StubEntryType> > StubMapType;
+private:
+  Fragment& m_Entry; // entry fragment of the island
+  Fragment* m_pExit; // exit fragment of the island
+  Fragment* m_pRear; // rear fragment of the island
+  size_t m_MaxSize;
+  std::string m_Name;
+  StubMapType m_StubMap;
+  /// m_Relocations - list of relocations created for stubs in this island
+  RelocationListType m_Relocations;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/BranchIslandFactory.h b/include/mcld/LD/BranchIslandFactory.h
new file mode 100644
index 0000000..755cc31
--- /dev/null
+++ b/include/mcld/LD/BranchIslandFactory.h
@@ -0,0 +1,56 @@
+//===- BranchIslandFactory.h ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LD_BRANCH_ISLAND_FACTORY_H
+#define MCLD_LD_BRANCH_ISLAND_FACTORY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Support/GCFactory.h>
+#include <mcld/LD/BranchIsland.h>
+
+namespace mcld
+{
+
+class Fragment;
+
+/** \class BranchIslandFactory
+ *  \brief
+ *
+ */
+class BranchIslandFactory : public GCFactory<BranchIsland, 0>
+{
+public:
+  /// ctor
+  /// @param pMaxBranchRange - the max branch range of the target backend
+  /// @param pMaxIslandSize - a predifned value (64KB here) to decide the max
+  ///                         size of the island
+  BranchIslandFactory(uint64_t pMaxBranchRange,
+                      uint64_t pMaxIslandSize = 65536U);
+
+  ~BranchIslandFactory();
+
+  /// produce - produce a island for the given fragment
+  /// @param pFragment - the fragment needs a branch island
+  BranchIsland* produce(Fragment& pFragment);
+
+  /// find - find a island for the given fragment
+  /// @param pFragment - the fragment needs a branch isladn
+  BranchIsland* find(const Fragment& pFragment);
+
+private:
+  uint64_t m_MaxBranchRange;
+  uint64_t m_MaxIslandSize;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/CIE.h b/include/mcld/LD/CIE.h
deleted file mode 100644
index 23dfa22..0000000
--- a/include/mcld/LD/CIE.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- CIE.h --------------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_COMMON_INFORMATION_ENTRY_H
-#define MCLD_COMMON_INFORMATION_ENTRY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/Support/DataTypes.h>
-#include <mcld/LD/RegionFragment.h>
-
-namespace mcld
-{
-
-/** \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
-{
-public:
-  explicit CIE(MemoryRegion& pRegion, uint8_t pFDEEncode);
-  ~CIE();
-
-  // ----- observers ----- //
-  /// getFDEEncoding - get the FDE encoding from Augmentation Data if 'R'
-  /// is present in Augmentaion String
-  uint8_t getFDEEncode() const
-  { return m_FDEEncoding; }
-
-private:
-  uint8_t m_FDEEncoding;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/DiagCommonKinds.inc b/include/mcld/LD/DiagCommonKinds.inc
index 835e1d4..08850e7 100644
--- a/include/mcld/LD/DiagCommonKinds.inc
+++ b/include/mcld/LD/DiagCommonKinds.inc
@@ -41,3 +41,8 @@
 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_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.")
+DIAG(fatal_illegal_codegen_type, DiagnosticEngine::Fatal, "illegal output format of output %0", "illegal output format of output %0")
diff --git a/include/mcld/LD/DiagLayouts.inc b/include/mcld/LD/DiagLayouts.inc
index af6bc96..fac7a32 100644
--- a/include/mcld/LD/DiagLayouts.inc
+++ b/include/mcld/LD/DiagLayouts.inc
@@ -1,3 +1,6 @@
 DIAG(warn_unsupported_exception, DiagnosticEngine::Warning, "Exception handling has not been fully supported yet.\nsection `%0'.", "Exception handling has not been fully supported yet.\nsection `%0'.")
 DIAG(warn_unsupported_symbolic_versioning, DiagnosticEngine::Warning, "Symbolic versioning has not been fully supported yet.\nsection `%0'.", "Symbolic versioning has not been fully supported yet.\nsection `%0'")
 DIAG(err_section_not_laid_out, DiagnosticEngine::Unreachable, "section %0 has not been laid out. Developers may use an output LDSection in Layout::getFragmentRef", "section %0 has not been laid out. Developers may use an output LDSection in Layout::getFragmentRef")
+DIAG(warn_duplicate_std_sectmap, DiagnosticEngine::Warning, "Duplicated definition of section map \"from %0 to %0\".", "Duplicated definition of section map \"from %0 to %0\".")
+DIAG(warn_rules_check_failed, DiagnosticEngine::Warning, "Illegal section mapping rule: %0 -> %1. (conflict with %2 -> %3)", "Illegal section mapping rule: %0 -> %1. (conflict with %2 -> %3)")
+DIAG(err_cannot_merge_section, DiagnosticEngine::Error, "Cannot merge section %0 of %1", "Cannot merge section %0 of %1")
diff --git a/include/mcld/LD/DiagReaders.inc b/include/mcld/LD/DiagReaders.inc
index 8ba28c2..3f08a21 100644
--- a/include/mcld/LD/DiagReaders.inc
+++ b/include/mcld/LD/DiagReaders.inc
@@ -1 +1,4 @@
 DIAG(archive_magic_mismatch, DiagnosticEngine::Error, "magic number is mismatched in `%0'", "magic number is mismatched in `%0'")
+DIAG(debug_cannot_parse_eh, DiagnosticEngine::Debug, "cannot parse .eh_frame section in input %0", "cannot parse .eh_frame section in input %0.")
+DIAG(debug_cannot_scan_eh, DiagnosticEngine::Debug, "cannot scan .eh_frame section in input %0", "cannot scan .eh_frame section in input %0.")
+DIAG(fatal_cannot_read_input, DiagnosticEngine::Fatal, "cannot read input input %0", "cannot read input %0")
diff --git a/include/mcld/LD/DiagRelocations.inc b/include/mcld/LD/DiagRelocations.inc
index e115fd8..5d52dd8 100644
--- a/include/mcld/LD/DiagRelocations.inc
+++ b/include/mcld/LD/DiagRelocations.inc
@@ -1,9 +1,11 @@
 DIAG(undefined_reference, DiagnosticEngine::Fatal, "undefined reference to `%0'", "In %1:%2, variable %0 must be defined")
 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, "enexpected relocation type `%0' in object file", "unexpected relocation type `%0' in object file")
+DIAG(dynamic_relocation, DiagnosticEngine::Fatal, "unexpected relocation type `%0' in object file", "unexpected relocation type `%0' in object file")
 DIAG(unsupported_relocation, DiagnosticEngine::Unreachable, "encounter unsupported relocation type `%0'\nPlease report to %1", "encounter unsupported relocation type `%0'\nPlease report to %1")
 DIAG(unknown_relocation, DiagnosticEngine::Fatal, "encounter unknown relocation type `%0' for symbol `%1'", "encounter unknown relocation type `%0' for symbol `%1'")
 DIAG(invalid_global_relocation, DiagnosticEngine::Unreachable, "relocation type `%0' is invalid for global symbol `%1'", "relocation type `%0' is invalid for global symbol `%1'")
 DIAG(result_overflow, DiagnosticEngine::Error, "applying relocation `%0' causes overflow on symbol `%1'","applying relocation `%0' causes overflow on symbol `%1'")
 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'")
diff --git a/include/mcld/LD/DiagnosticEngine.h b/include/mcld/LD/DiagnosticEngine.h
index 77666ab..9d24c7a 100644
--- a/include/mcld/LD/DiagnosticEngine.h
+++ b/include/mcld/LD/DiagnosticEngine.h
@@ -18,7 +18,7 @@
 namespace mcld {
 
 class Input;
-class MCLDInfo;
+class LinkerConfig;
 class MsgHandler;
 class DiagnosticPrinter;
 class DiagnosticLineInfo;
@@ -61,17 +61,15 @@
 
   ~DiagnosticEngine();
 
-  void reset(const MCLDInfo& pLDInfo);
+  void reset(const LinkerConfig& pConfig);
 
   void setLineInfo(DiagnosticLineInfo& pLineInfo);
 
   void setPrinter(DiagnosticPrinter& pPrinter, bool pShouldOwnPrinter = true);
 
-  DiagnosticPrinter* getPrinter()
-  { return m_pPrinter; }
+  const DiagnosticPrinter* getPrinter() const { return m_pPrinter; }
+  DiagnosticPrinter*       getPrinter()       { return m_pPrinter; }
 
-  const DiagnosticPrinter* getPrinter() const
-  { return m_pPrinter; }
 
   DiagnosticPrinter* takePrinter() {
     m_OwnPrinter = false;
@@ -95,7 +93,7 @@
   enum {
     /// MaxArguments - The maximum number of arguments we can hold. We currently
     /// only support up to 10 arguments (%0-%9).
-    MaxArguments = 10,
+    MaxArguments = 10
   };
 
   struct State
@@ -139,7 +137,7 @@
   }
 
 private:
-  const MCLDInfo* m_pLDInfo;
+  const LinkerConfig* m_pConfig;
   DiagnosticLineInfo* m_pLineInfo;
   DiagnosticPrinter* m_pPrinter;
   DiagnosticInfos* m_pInfoMap;
diff --git a/include/mcld/LD/DiagnosticInfos.h b/include/mcld/LD/DiagnosticInfos.h
index 66f7fc0..cb9bdbd 100644
--- a/include/mcld/LD/DiagnosticInfos.h
+++ b/include/mcld/LD/DiagnosticInfos.h
@@ -29,7 +29,7 @@
   };
 } // namespace of diag
 
-class MCLDInfo;
+class LinkerConfig;
 class DiagnosticEngine;
 
 /** \class DiagnosticInfos
@@ -38,7 +38,7 @@
 class DiagnosticInfos
 {
 public:
-  DiagnosticInfos(const MCLDInfo& pLDInfo);
+  DiagnosticInfos(const LinkerConfig& pConfig);
 
   ~DiagnosticInfos();
 
@@ -47,7 +47,7 @@
   bool process(DiagnosticEngine& pEngine) const;
 
 private:
-  const MCLDInfo& m_LDInfo;
+  const LinkerConfig& m_Config;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/DiagnosticPrinter.h b/include/mcld/LD/DiagnosticPrinter.h
index 13911f5..b3617a7 100644
--- a/include/mcld/LD/DiagnosticPrinter.h
+++ b/include/mcld/LD/DiagnosticPrinter.h
@@ -28,7 +28,7 @@
 
   virtual ~DiagnosticPrinter();
 
-  virtual void beginInput(const Input& pInput, const MCLDInfo& pLDInfo) {}
+  virtual void beginInput(const Input& pInput, const LinkerConfig& pConfig) {}
 
   virtual void endInput() {}
 
@@ -42,11 +42,8 @@
   virtual void handleDiagnostic(DiagnosticEngine::Severity pSeverity,
                                 const Diagnostic& pInfo);
 
-  unsigned int getNumErrors() const
-  { return m_NumErrors; }
-
-  unsigned int getNumWarnings() const
-  { return m_NumWarnings; }
+  unsigned int getNumErrors() const { return m_NumErrors; }
+  unsigned int getNumWarnings() const { return m_NumWarnings; }
 
 protected:
   unsigned int m_NumErrors;
diff --git a/include/mcld/LD/DynObjReader.h b/include/mcld/LD/DynObjReader.h
index 0900109..ddc9500 100644
--- a/include/mcld/LD/DynObjReader.h
+++ b/include/mcld/LD/DynObjReader.h
@@ -14,8 +14,7 @@
 #include "mcld/LD/LDReader.h"
 #include <llvm/Support/system_error.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class TargetLDBackend;
 class Input;
@@ -33,7 +32,7 @@
 public:
   virtual ~DynObjReader() { }
 
-  virtual bool readDSO(Input& pFile) = 0;
+  virtual bool readHeader(Input& pFile) = 0;
 
   virtual bool readSymbols(Input& pFile) = 0;
 
diff --git a/include/mcld/LD/DynObjWriter.h b/include/mcld/LD/DynObjWriter.h
index 1c77bd4..89d9765 100644
--- a/include/mcld/LD/DynObjWriter.h
+++ b/include/mcld/LD/DynObjWriter.h
@@ -11,12 +11,14 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <mcld/MC/MCLDOutput.h>
 #include <mcld/LD/LDWriter.h>
 #include <llvm/Support/system_error.h>
 
-namespace mcld
-{
+namespace mcld {
+
+class Module;
+class MemoryArea;
+class TargetLDBackend;
 
 /** \class DynObjWriter
  *  \brief DynObjWriter provides an common interface for different object
@@ -32,7 +34,8 @@
 public:
   virtual ~DynObjWriter() { }
 
-  virtual llvm::error_code writeDynObj(Output& pOutput) = 0;
+  virtual llvm::error_code writeDynObj(Module& pModule,
+                                       MemoryArea& pOutput) = 0;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFDynObjFileFormat.h b/include/mcld/LD/ELFDynObjFileFormat.h
index 9b77e91..2ee97a6 100644
--- a/include/mcld/LD/ELFDynObjFileFormat.h
+++ b/include/mcld/LD/ELFDynObjFileFormat.h
@@ -13,23 +13,18 @@
 #endif
 #include <mcld/LD/ELFFileFormat.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class GNULDBackend;
-class MCLinker;
+class ObjectBuilder;
 
 /** \class ELFDynObjFileFormat
  *  \brief ELFDynObjFileFormat describes the format for ELF dynamic objects.
  */
 class ELFDynObjFileFormat : public ELFFileFormat
 {
-public:
-  ELFDynObjFileFormat(GNULDBackend& pBackend) : ELFFileFormat(pBackend)
-  {}
-
-  void initObjectType(MCLinker& pLinker);
-
+  /// initObjectFormat - initialize sections that are dependent on shared
+  /// objects.
+  void initObjectFormat(ObjectBuilder& pBuilder, unsigned int pBitClass);
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFDynObjReader.h b/include/mcld/LD/ELFDynObjReader.h
index 72a3336..b5d59a3 100644
--- a/include/mcld/LD/ELFDynObjReader.h
+++ b/include/mcld/LD/ELFDynObjReader.h
@@ -18,7 +18,7 @@
 {
 
 class Input;
-class MCLinker;
+class FragmentLinker;
 class GNULDBackend;
 class ELFReaderIF;
 
@@ -29,20 +29,20 @@
 class ELFDynObjReader : public DynObjReader
 {
 public:
-  ELFDynObjReader(GNULDBackend& pBackend, MCLinker& pLinker);
+  ELFDynObjReader(GNULDBackend& pBackend, FragmentLinker& pLinker);
   ~ELFDynObjReader();
 
   // -----  observers  ----- //
   bool isMyFormat(Input &pFile) const;
 
   // -----  readers  ----- //
-  bool readDSO(Input& pFile);
+  bool readHeader(Input& pFile);
 
   bool readSymbols(Input& pInput);
 
 private:
   ELFReaderIF *m_pELFReader;
-  MCLinker& m_Linker;
+  FragmentLinker& m_Linker;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFDynObjWriter.h b/include/mcld/LD/ELFDynObjWriter.h
index dc0e37b..b5dd390 100644
--- a/include/mcld/LD/ELFDynObjWriter.h
+++ b/include/mcld/LD/ELFDynObjWriter.h
@@ -11,22 +11,15 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <llvm/ADT/DenseMap.h>
-#include <llvm/Support/ELF.h>
 #include <mcld/LD/DynObjWriter.h>
 #include <mcld/LD/ELFWriter.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/Support/MemoryArea.h>
-#include <vector>
-#include <utility>
 
+namespace mcld {
 
-namespace mcld
-{
-
+class Module;
+class MemoryArea;
 class GNULDBackend;
-class MCLinker;
+class FragmentLinker;
 
 /** \class ELFDynObjWriter
  *  \brief ELFDynObjWriter writes the dynamic sections.
@@ -37,14 +30,13 @@
   typedef ELFWriter::FileOffset FileOffset;
 
 public:
-  ELFDynObjWriter(GNULDBackend& pBackend, MCLinker& pLinker);
+  ELFDynObjWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
   ~ELFDynObjWriter();
 
-  llvm::error_code writeDynObj(Output& pOutput);
+  llvm::error_code writeDynObj(Module& pModule, MemoryArea& pOutput);
 
 private:
-  GNULDBackend& m_Backend;
-  MCLinker& m_Linker;
+  FragmentLinker& m_Linker;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFExecFileFormat.h b/include/mcld/LD/ELFExecFileFormat.h
index 3c0d8bd..d888c93 100644
--- a/include/mcld/LD/ELFExecFileFormat.h
+++ b/include/mcld/LD/ELFExecFileFormat.h
@@ -13,22 +13,18 @@
 #endif
 #include <mcld/LD/ELFFileFormat.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class GNULDBackend;
-class MCLinker;
+class ObjectBuilder;
 
 /** \class ELFExecFileFormat
  *  \brief ELFExecFileFormat describes the format for ELF dynamic objects.
  */
 class ELFExecFileFormat : public ELFFileFormat
 {
-public:
-  ELFExecFileFormat(GNULDBackend& pBackend) : ELFFileFormat(pBackend)
-  {}
-
-  void initObjectType(MCLinker& pLinker);
+  /// initObjectFormat - initialize sections that are dependent on executable
+  /// objects.
+  void initObjectFormat(ObjectBuilder& pBuilder, unsigned int pBitClass);
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFExecWriter.h b/include/mcld/LD/ELFExecWriter.h
index 09709f7..dc731b9 100644
--- a/include/mcld/LD/ELFExecWriter.h
+++ b/include/mcld/LD/ELFExecWriter.h
@@ -11,22 +11,15 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <llvm/ADT/DenseMap.h>
-#include <llvm/Support/ELF.h>
 #include <mcld/LD/ExecWriter.h>
 #include <mcld/LD/ELFWriter.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/Support/MemoryArea.h>
-#include <vector>
-#include <utility>
 
+namespace mcld {
 
-namespace mcld
-{
-
+class Module;
+class MemoryArea;
 class GNULDBackend;
-class MCLinker;
+class FragmentLinker;
 
 /** \class ELFDynObjWriter
  *  \brief ELFDynObjWriter writes the dynamic sections.
@@ -37,14 +30,13 @@
   typedef ELFWriter::FileOffset FileOffset;
 
 public:
-  ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker);
+  ELFExecWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
   ~ELFExecWriter();
 
-  llvm::error_code writeExecutable(Output& pOutput);
+  llvm::error_code writeExecutable(Module& pModule, MemoryArea& pOutput);
 
 private:
-  GNULDBackend& m_Backend;
-  MCLinker& m_Linker;
+  FragmentLinker& m_Linker;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFFileFormat.h b/include/mcld/LD/ELFFileFormat.h
index f7a0c68..e52a813 100644
--- a/include/mcld/LD/ELFFileFormat.h
+++ b/include/mcld/LD/ELFFileFormat.h
@@ -14,11 +14,9 @@
 #include <mcld/LD/LDFileFormat.h>
 #include <mcld/LD/LDSection.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class GNULDBackend;
-class MCLinker;
+class ObjectBuilder;
 
 /** \class ELFFileFormat
  *  \brief ELFFileFormat describes the common file formats in ELF.
@@ -32,14 +30,16 @@
  */
 class ELFFileFormat : public LDFileFormat
 {
+private:
+  /// initObjectFormat - initialize sections that are dependent on object
+  /// formats. (executable, shared objects or relocatable objects).
+  virtual void
+  initObjectFormat(ObjectBuilder& pBuilder, unsigned int pBitClass) = 0;
+
 public:
-  ELFFileFormat(GNULDBackend& pBackend);
+  ELFFileFormat();
 
-  virtual ~ELFFileFormat();
-
-  virtual void initObjectFormat(MCLinker& pLinker);
-
-  virtual void initObjectType(MCLinker& pLinker) = 0;
+  void initStdSections(ObjectBuilder& pBuilder, unsigned int pBitClass);
 
   // -----  capacity  ----- //
   /// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
@@ -174,6 +174,12 @@
   bool hasStack() const
   { return (NULL != f_pStack) && (0 != f_pStack->size()); }
 
+  bool hasStackNote() const
+  { return (NULL != f_pStackNote); }
+
+  bool hasDataRelRoLocal() const
+  { return (NULL != f_pDataRelRoLocal) && (0 != f_pDataRelRoLocal->size()); }
+
   // -----  access functions  ----- //
   /// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
   LDSection& getNULLSection() {
@@ -607,9 +613,28 @@
     assert(NULL != f_pStack);
     return *f_pStack;
   }
-protected:
-  GNULDBackend& f_Backend;
 
+  LDSection& getStackNote() {
+    assert(NULL != f_pStackNote);
+    return *f_pStackNote;
+  }
+
+  const LDSection& getStackNote() const {
+    assert(NULL != f_pStackNote);
+    return *f_pStackNote;
+  }
+
+  LDSection& getDataRelRoLocal() {
+    assert(NULL != f_pDataRelRoLocal);
+    return *f_pDataRelRoLocal;
+  }
+
+  const LDSection& getDataRelRoLocal() const {
+    assert(NULL != f_pDataRelRoLocal);
+    return *f_pDataRelRoLocal;
+  }
+
+protected:
   //         variable name         :  ELF
   /// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
   LDSection* f_pNULLSection;
@@ -661,6 +686,8 @@
 
   /// practical
   LDSection* f_pStack;             // .stack
+  LDSection* f_pStackNote;         // .note.GNU-stack
+  LDSection* f_pDataRelRoLocal;    // .data.rel.ro.local
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFObjectFileFormat.h b/include/mcld/LD/ELFObjectFileFormat.h
new file mode 100644
index 0000000..e2430db
--- /dev/null
+++ b/include/mcld/LD/ELFObjectFileFormat.h
@@ -0,0 +1,34 @@
+//===- ELFObjectFileFormat.h ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELF_OBJECT_FILE_FROMAT_H
+#define MCLD_ELF_OBJECT_FILE_FROMAT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/LD/ELFFileFormat.h>
+
+namespace mcld {
+
+class ObjectBuilder;
+
+/** \class ELFObjectFileFormat
+ *  \brief ELFObjectFileFormat describes the format for ELF dynamic objects.
+ */
+class ELFObjectFileFormat : public ELFFileFormat
+{
+  void initObjectFormat(ObjectBuilder& pBuilder, unsigned int pBitClass) {
+    // do nothing
+    return;
+  }
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ELFObjectReader.h b/include/mcld/LD/ELFObjectReader.h
index ac11261..c1463fa 100644
--- a/include/mcld/LD/ELFObjectReader.h
+++ b/include/mcld/LD/ELFObjectReader.h
@@ -13,15 +13,16 @@
 #endif
 
 #include <mcld/LD/ObjectReader.h>
-#include <llvm/Support/system_error.h>
+#include <mcld/ADT/Flags.h>
 
-namespace mcld
-{
+namespace mcld {
 
+class Module;
 class Input;
-class MCLinker;
+class FragmentLinker;
 class GNULDBackend;
 class ELFReaderIF;
+class EhFrameReader;
 
 /** \lclass ELFObjectReader
  *  \brief ELFObjectReader reads target-independent parts of ELF object file
@@ -29,7 +30,15 @@
 class ELFObjectReader : public ObjectReader
 {
 public:
-  ELFObjectReader(GNULDBackend& pBackend, MCLinker& pLinker);
+  enum ReadFlagType {
+    ParseEhFrame    = 0x1, ///< parse .eh_frame section if the bit is set.
+    NumOfReadFlags  = 1
+  };
+
+  typedef Flags<ReadFlagType> ReadFlag;
+
+public:
+  ELFObjectReader(GNULDBackend& pBackend, FragmentLinker& pLinker);
 
   ~ELFObjectReader();
 
@@ -37,7 +46,7 @@
   bool isMyFormat(Input &pFile) const;
 
   // -----  readers  ----- //
-  bool readObject(Input& pFile);
+  bool readHeader(Input& pFile);
 
   virtual bool readSections(Input& pFile);
 
@@ -50,7 +59,10 @@
 
 private:
   ELFReaderIF* m_pELFReader;
-  MCLinker& m_Linker;
+  EhFrameReader* m_pEhFrameReader;
+  FragmentLinker& m_Linker;
+  ReadFlag m_ReadFlag;
+  GNULDBackend& m_Backend;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFObjectWriter.h b/include/mcld/LD/ELFObjectWriter.h
index a6b9a87..31f7b12 100644
--- a/include/mcld/LD/ELFObjectWriter.h
+++ b/include/mcld/LD/ELFObjectWriter.h
@@ -15,11 +15,11 @@
 #include <mcld/LD/ObjectWriter.h>
 #include <mcld/LD/ELFWriter.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class Input;
-class MCLinker;
+class Module;
+class MemoryArea;
+class FragmentLinker;
 class GNULDBackend;
 
 /** \class ELFObjectWriter
@@ -30,15 +30,14 @@
 class ELFObjectWriter : public ObjectWriter, protected ELFWriter
 {
 public:
-  ELFObjectWriter(GNULDBackend& pBackend, MCLinker& pLinker);
+  ELFObjectWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
 
   ~ELFObjectWriter();
 
-  llvm::error_code writeObject(Output& pOutput)
-  { return llvm::make_error_code(llvm::errc::not_supported); }
+  llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput);
 
 private:
-  MCLinker& m_Linker;
+  FragmentLinker& m_Linker;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ELFReader.h b/include/mcld/LD/ELFReader.h
index f893be5..941c8cd 100644
--- a/include/mcld/LD/ELFReader.h
+++ b/include/mcld/LD/ELFReader.h
@@ -16,21 +16,23 @@
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Host.h>
 
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/Fragment.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/LD/RegionFragment.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/LDContext.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MsgHandling.h>
 
-namespace mcld
-{
+namespace mcld {
+
+class Module;
+class FragmentRef;
+class FragmentLinker;
+class SectionData;
+class LDSection;
 
 /** \class ELFReaderIF
  *  \brief ELFReaderIF provides common interface for all kind of ELF readers.
@@ -57,60 +59,43 @@
   virtual bool isMyMachine(void* pELFHeader) const = 0;
 
   /// fileType - the file type of this file
-  virtual MCLDFile::Type fileType(void* pELFHeader) const = 0;
+  virtual Input::Type fileType(void* pELFHeader) const = 0;
 
   /// target - the target backend
-  GNULDBackend& target()
-  { return m_Backend; }
+  const GNULDBackend& target() const { return m_Backend; }
+  GNULDBackend&       target()       { return m_Backend; }
 
-  /// target - the target backend
-  const GNULDBackend& target() const
-  { return m_Backend; }
 
   /// readSectionHeaders - read ELF section header table and create LDSections
-  virtual bool readSectionHeaders(Input& pInput,
-                                  MCLinker& pLinker,
-                                  void* pELFHeader) const = 0;
+  virtual bool readSectionHeaders(Input& pInput, void* pELFHeader) const = 0;
 
   /// readRegularSection - read a regular section and create fragments.
-  virtual bool readRegularSection(Input& pInput,
-                                  MCLinker& pLinker,
-                                  LDSection& pSectHdr) const = 0;
-
-  /// readRegularSection - read a target section and create fragments.
-  virtual bool readTargetSection(Input& pInput,
-                                 MCLinker& pLinker,
-                                 LDSection& pSectHdr) = 0;
+  virtual bool readRegularSection(Input& pInput, SectionData& pSD) const = 0;
 
   /// readSymbols - read ELF symbols and create LDSymbol
   virtual bool readSymbols(Input& pInput,
-                           MCLinker& pLinker,
+                           FragmentLinker& pLinker,
                            const MemoryRegion& pRegion,
                            const char* StrTab) const = 0;
 
-  /// readSymbol - read a symbol from the given Input and index in symtab
+  /// readSignature - read a symbol from the given Input and index in symtab
   /// This is used to get the signature of a group section.
-  virtual ResolveInfo* readSymbol(Input& pInput,
-                                  LDSection& pSymTab,
-                                  MCLDInfo& pLDInfo,
-                                  uint32_t pSymIdx) const = 0;
+  virtual ResolveInfo* readSignature(Input& pInput,
+                                     LDSection& pSymTab,
+                                     uint32_t pSymIdx) const = 0;
 
   /// readRela - read ELF rela and create Relocation
   virtual bool readRela(Input& pInput,
-                        MCLinker& pLinker,
+                        FragmentLinker& pLinker,
                         LDSection& pSection,
                         const MemoryRegion& pRegion) const = 0;
 
   /// readRel - read ELF rel and create Relocation
   virtual bool readRel(Input& pInput,
-                       MCLinker& pLinker,
+                       FragmentLinker& pLinker,
                        LDSection& pSection,
                        const MemoryRegion& pRegion) const = 0;
 
-  bool readEhFrame(Input& pInput,
-                   MCLinker& pLinker,
-                   LDSection& pSection) const;
-
   /// readDynamic - read ELF .dynamic in input dynobj
   virtual bool readDynamic(Input& pInput) const = 0;
 
@@ -125,8 +110,6 @@
   typedef std::vector<LinkInfo> LinkInfoList;
 
 protected:
-  LDFileFormat::Kind getLDSectionKind(uint32_t pType, const char* pName) const;
-
   ResolveInfo::Type getSymType(uint8_t pInfo, uint16_t pShndx) const;
 
   ResolveInfo::Desc getSymDesc(uint16_t pShndx, const Input& pInput) const;
@@ -140,13 +123,12 @@
                        const Input& pInput) const;
 
   FragmentRef* getSymFragmentRef(Input& pInput,
-                                 MCLinker& pLinker,
                                  uint16_t pShndx,
                                  uint32_t pOffset) const;
 
   ResolveInfo::Visibility getSymVisibility(uint8_t pVis) const;
 
-private:
+protected:
   GNULDBackend& m_Backend;
 };
 
@@ -171,72 +153,60 @@
   typedef llvm::ELF::Elf32_Rela Rela;
 
 public:
-  inline ELFReader(GNULDBackend& pBackend);
+  ELFReader(GNULDBackend& pBackend);
 
-  inline ~ELFReader();
+  ~ELFReader();
 
   /// ELFHeaderSize - return the size of the ELFHeader
-  inline size_t getELFHeaderSize() const
+  size_t getELFHeaderSize() const
   { return sizeof(ELFHeader); }
 
   /// isELF - is this a ELF file
-  inline bool isELF(void* pELFHeader) const;
+  bool isELF(void* pELFHeader) const;
 
   /// isMyEndian - is this ELF file in the same endian to me?
-  inline bool isMyEndian(void* pELFHeader) const;
+  bool isMyEndian(void* pELFHeader) const;
 
   /// isMyMachine - is this ELF file generated for the same machine.
-  inline bool isMyMachine(void* pELFHeader) const;
+  bool isMyMachine(void* pELFHeader) const;
 
   /// fileType - the file type of this file
-  inline MCLDFile::Type fileType(void* pELFHeader) const;
+  Input::Type fileType(void* pELFHeader) const;
 
   /// readSectionHeaders - read ELF section header table and create LDSections
-  inline bool readSectionHeaders(Input& pInput,
-                          MCLinker& pLinker,
-                          void* pELFHeader) const;
+  bool readSectionHeaders(Input& pInput, void* pELFHeader) const;
 
   /// readRegularSection - read a regular section and create fragments.
-  inline bool readRegularSection(Input& pInput,
-                                 MCLinker& pLinker,
-                                 LDSection& pInputSectHdr) const;
-
-  /// readRegularSection - read a target section and create fragments.
-  inline bool readTargetSection(Input& pInput,
-                                MCLinker& pLinker,
-                                LDSection& pInputSectHdr);
+  bool readRegularSection(Input& pInput, SectionData& pSD) const;
 
   /// readSymbols - read ELF symbols and create LDSymbol
-  inline bool readSymbols(Input& pInput,
-                          MCLinker& pLinker,
+  bool readSymbols(Input& pInput,
+                          FragmentLinker& pLinker,
                           const MemoryRegion& pRegion,
                           const char* StrTab) const;
 
-  /// readSymbol - read a symbol from the given Input and index in symtab
+  /// readSignature - read a symbol from the given Input and index in symtab
   /// This is used to get the signature of a group section.
-  inline ResolveInfo* readSymbol(Input& pInput,
-                                 LDSection& pSymTab,
-                                 MCLDInfo& pLDInfo,
-                                 uint32_t pSymIdx) const;
+  ResolveInfo* readSignature(Input& pInput,
+                                    LDSection& pSymTab,
+                                    uint32_t pSymIdx) const;
 
   /// readRela - read ELF rela and create Relocation
-  inline bool readRela(Input& pInput,
-                       MCLinker& pLinker,
-                       LDSection& pSection,
-                       const MemoryRegion& pRegion) const;
+  bool readRela(Input& pInput,
+                FragmentLinker& pLinker,
+                LDSection& pSection,
+                const MemoryRegion& pRegion) const;
 
   /// readRel - read ELF rel and create Relocation
-  inline bool readRel(Input& pInput,
-                      MCLinker& pLinker,
-                      LDSection& pSection,
-                      const MemoryRegion& pRegion) const;
+  bool readRel(Input& pInput,
+               FragmentLinker& pLinker,
+               LDSection& pSection,
+               const MemoryRegion& pRegion) const;
 
   /// readDynamic - read ELF .dynamic in input dynobj
-  inline bool readDynamic(Input& pInput) const;
+  bool readDynamic(Input& pInput) const;
 };
 
-#include "ELFReader.tcc"
-
 } // namespace of mcld
 
 #endif
diff --git a/include/mcld/LD/ELFReader.tcc b/include/mcld/LD/ELFReader.tcc
deleted file mode 100644
index 7c3f6d4..0000000
--- a/include/mcld/LD/ELFReader.tcc
+++ /dev/null
@@ -1,596 +0,0 @@
-//===- ELFReader.tcc ------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  This file is the template implemenation of ELFReaders
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// ELFReader<32, true>
-#include <cstring>
-#include <vector>
-
-/// constructor
-ELFReader<32, true>::ELFReader(GNULDBackend& pBackend)
-  : ELFReaderIF(pBackend) {
-}
-
-/// destructor
-ELFReader<32, true>::~ELFReader()
-{
-}
-
-/// isELF - is this a ELF file
-bool ELFReader<32, true>::isELF(void* pELFHeader) const
-{
-  llvm::ELF::Elf32_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
-  if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
-    return true;
-  return false;
-}
-
-/// isMyEndian - is this ELF file in the same endian to me?
-bool ELFReader<32, true>::isMyEndian(void* pELFHeader) const
-{
-  llvm::ELF::Elf32_Ehdr* hdr =
-                          reinterpret_cast<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
-{
-  llvm::ELF::Elf32_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
-
-  if (llvm::sys::isLittleEndianHost())
-    return (hdr->e_machine == target().machine());
-  return (bswap16(hdr->e_machine) == target().machine());
-}
-
-/// fileType - return the file type
-MCLDFile::Type ELFReader<32, true>::fileType(void* pELFHeader) const
-{
-  llvm::ELF::Elf32_Ehdr* hdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
-  uint32_t type = 0x0;
-  if (llvm::sys::isLittleEndianHost())
-    type = hdr->e_type;
-  else
-    type = bswap16(hdr->e_type);
-
-  switch(type) {
-  case llvm::ELF::ET_REL:
-    return MCLDFile::Object;
-  case llvm::ELF::ET_EXEC:
-    return MCLDFile::Exec;
-  case llvm::ELF::ET_DYN:
-    return MCLDFile::DynObj;
-  case llvm::ELF::ET_CORE:
-    return MCLDFile::CoreFile;
-  case llvm::ELF::ET_NONE:
-  default:
-    return MCLDFile::Unknown;
-  }
-}
-
-/// readSectionHeaders - read ELF section header table and create LDSections
-bool ELFReader<32, true>::readSectionHeaders(Input& pInput,
-                                             MCLinker& pLinker,
-                                             void* pELFHeader) const
-{
-  llvm::ELF::Elf32_Ehdr* ehdr =
-                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
-
-  uint32_t shoff     = 0x0;
-  uint16_t shentsize = 0x0;
-  uint16_t shnum     = 0x0;
-  uint16_t shstrtab  = 0x0;
-
-  if (llvm::sys::isLittleEndianHost()) {
-    shoff     = ehdr->e_shoff;
-    shentsize = ehdr->e_shentsize;
-    shnum     = ehdr->e_shnum;
-    shstrtab  = ehdr->e_shstrndx;
-  }
-  else {
-    shoff     = bswap32(ehdr->e_shoff);
-    shentsize = bswap16(ehdr->e_shentsize);
-    shnum     = bswap16(ehdr->e_shnum);
-    shstrtab  = bswap16(ehdr->e_shstrndx);
-  }
-
-  // If the file has no section header table, e_shoff holds zero.
-  if (0x0 == shoff)
-    return true;
-
-  MemoryRegion* shdr_region = pInput.memArea()->request(
-                                 pInput.fileOffset() + shoff, shnum*shentsize);
-  llvm::ELF::Elf32_Shdr* shdrTab =
-                reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
-
-  uint32_t sh_name      = 0x0;
-  uint32_t sh_type      = 0x0;
-  uint32_t sh_flags     = 0x0;
-  uint32_t sh_offset    = 0x0;
-  uint32_t sh_size      = 0x0;
-  uint32_t sh_link      = 0x0;
-  uint32_t sh_info      = 0x0;
-  uint32_t sh_addralign = 0x0;
-
-  // get .shstrtab first
-  llvm::ELF::Elf32_Shdr* shdr = &shdrTab[shstrtab];
-  if (llvm::sys::isLittleEndianHost()) {
-    sh_offset = shdr->sh_offset;
-    sh_size   = shdr->sh_size;
-  }
-  else {
-    sh_offset = bswap32(shdr->sh_offset);
-    sh_size   = 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());
-
-  LinkInfoList link_info_list;
-
-  // create all LDSections
-  for (size_t idx = 0; idx < shnum; ++idx) {
-    if (llvm::sys::isLittleEndianHost()) {
-      sh_name      = shdrTab[idx].sh_name;
-      sh_type      = shdrTab[idx].sh_type;
-      sh_flags     = shdrTab[idx].sh_flags;
-      sh_offset    = shdrTab[idx].sh_offset;
-      sh_size      = shdrTab[idx].sh_size;
-      sh_link      = shdrTab[idx].sh_link;
-      sh_info      = shdrTab[idx].sh_info;
-      sh_addralign = shdrTab[idx].sh_addralign;
-    }
-    else {
-      sh_name      = bswap32(shdrTab[idx].sh_name);
-      sh_type      = bswap32(shdrTab[idx].sh_type);
-      sh_flags     = bswap32(shdrTab[idx].sh_flags);
-      sh_offset    = bswap32(shdrTab[idx].sh_offset);
-      sh_size      = bswap32(shdrTab[idx].sh_size);
-      sh_link      = bswap32(shdrTab[idx].sh_link);
-      sh_info      = bswap32(shdrTab[idx].sh_info);
-      sh_addralign = bswap32(shdrTab[idx].sh_addralign);
-    }
-
-    LDFileFormat::Kind kind = getLDSectionKind(sh_type,
-                                               sect_name+sh_name);
-
-    LDSection& section = pLinker.createSectHdr(sect_name+sh_name,
-                                               kind,
-                                               sh_type,
-                                               sh_flags);
-
-    section.setSize(sh_size);
-    section.setOffset(sh_offset);
-    section.setIndex(pInput.context()->numOfSections());
-    section.setInfo(sh_info);
-    section.setAlign(sh_addralign);
-
-    if (sh_link != 0x0 || sh_info != 0x0) {
-      LinkInfo link_info = { &section, sh_link, sh_info };
-      link_info_list.push_back(link_info);
-    }
-
-    pInput.context()->getSectionTable().push_back(&section);
-  } // end of for
-
-  // set up InfoLink
-  LinkInfoList::iterator info, infoEnd = link_info_list.end();
-  for (info = link_info_list.begin(); info != infoEnd; ++info) {
-    if (LDFileFormat::NamePool == info->section->kind() ||
-        LDFileFormat::Group == info->section->kind() ||
-        LDFileFormat::Note == info->section->kind()) {
-      info->section->setLink(pInput.context()->getSection(info->sh_link));
-      continue;
-    }
-    if (LDFileFormat::Relocation == info->section->kind()) {
-      info->section->setLink(pInput.context()->getSection(info->sh_info));
-      continue;
-    }
-  }
-
-  pInput.memArea()->release(shdr_region);
-  pInput.memArea()->release(sect_name_region);
-
-  return true;
-}
-
-/// readRegularSection - read a regular section and create fragments.
-bool ELFReader<32, true>::readRegularSection(Input& pInput,
-                                             MCLinker& pLinker,
-                                             LDSection& pInputSectHdr) const
-{
-  LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
-                                                         pInputSectHdr.kind(),
-                                                         pInputSectHdr.type(),
-                                                         pInputSectHdr.flag());
-
-  MemoryRegion* region = pInput.memArea()->request(
-           pInput.fileOffset() + pInputSectHdr.offset(), pInputSectHdr.size());
-
-  SectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
-
-  Fragment* frag = NULL;
-  if (NULL == region) {
-    // 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);
-
-  uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                     sect_data,
-                                                     pInputSectHdr.align());
-
-  out_sect.setSize(out_sect.size() + size);
-  return true;
-}
-
-/// readRegularSection - read a target section and create fragments.
-bool ELFReader<32, true>::readTargetSection(Input& pInput,
-                                            MCLinker& pLinker,
-                                            LDSection& pInputSectHdr)
-{
-  return target().readSection(pInput, pLinker, pInputSectHdr);
-}
-
-/// readSymbols - read ELF symbols and create LDSymbol
-bool ELFReader<32, true>::readSymbols(Input& pInput,
-                                      MCLinker& pLinker,
-                                      const MemoryRegion& 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());
-
-  uint32_t st_name  = 0x0;
-  uint32_t st_value = 0x0;
-  uint32_t st_size  = 0x0;
-  uint8_t  st_info  = 0x0;
-  uint8_t  st_other = 0x0;
-  uint16_t st_shndx = 0x0;
-  // skip the first NULL symbol
-  pInput.context()->addSymbol(NULL);
-
-  for (size_t idx = 1; idx < entsize; ++idx) {
-    st_info  = symtab[idx].st_info;
-    st_other = symtab[idx].st_other;
-
-    if (llvm::sys::isLittleEndianHost()) {
-      st_name  = symtab[idx].st_name;
-      st_value = symtab[idx].st_value;
-      st_size  = symtab[idx].st_size;
-      st_shndx = symtab[idx].st_shndx;
-    }
-    else {
-      st_name  = bswap32(symtab[idx].st_name);
-      st_value = bswap32(symtab[idx].st_value);
-      st_size  = bswap32(symtab[idx].st_size);
-      st_shndx = bswap16(symtab[idx].st_shndx);
-    }
-
-    // If the section should not be included, set the st_shndx SHN_UNDEF
-    // - A section in interrelated groups are not included.
-    if (pInput.type() == Input::Object &&
-        st_shndx < llvm::ELF::SHN_LORESERVE &&
-        st_shndx != llvm::ELF::SHN_UNDEF) {
-      if (NULL == pInput.context()->getSection(st_shndx))
-        st_shndx = llvm::ELF::SHN_UNDEF;
-    }
-
-    // get ld_type
-    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
-
-    // get ld_desc
-    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
-
-    // get ld_binding
-    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
-
-    // get ld_value - ld_value must be section relative.
-    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
-
-    // get the input fragment
-    FragmentRef* ld_frag_ref = getSymFragmentRef(pInput,
-                                                 pLinker,
-                                                 st_shndx,
-                                                 ld_value);
-
-    // get ld_vis
-    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
-
-    // get ld_name
-    llvm::StringRef ld_name;
-    if (ResolveInfo::Section == ld_type) {
-      // Section symbol's st_name is the section index.
-      LDSection* section = pInput.context()->getSection(st_shndx);
-      assert(NULL != section && "get a invalid section");
-      ld_name = llvm::StringRef(section->name());
-    }
-    else {
-      ld_name = llvm::StringRef(pStrTab + st_name);
-    }
-
-
-    // push into MCLinker
-    LDSymbol* input_sym = NULL;
-
-    if (pInput.type() == Input::Object) {
-      input_sym = pLinker.addSymbol<Input::Object>(ld_name,
-                                                   ld_type,
-                                                   ld_desc,
-                                                   ld_binding,
-                                                   st_size,
-                                                   ld_value,
-                                                   ld_frag_ref,
-                                                   ld_vis);
-      // push into the input file
-      pInput.context()->addSymbol(input_sym);
-      continue;
-    }
-    else if (pInput.type() == Input::DynObj) {
-      input_sym = pLinker.addSymbol<Input::DynObj>(ld_name,
-                                                   ld_type,
-                                                   ld_desc,
-                                                   ld_binding,
-                                                   st_size,
-                                                   ld_value,
-                                                   ld_frag_ref,
-                                                   ld_vis);
-      continue;
-    }
-
-  } // end of for loop
-  return true;
-}
-
-/// readSymbol - read a symbol from the given Input and index in symtab
-/// This is used to get the signature of a group section.
-ResolveInfo* ELFReader<32, true>::readSymbol(Input& pInput,
-                                             LDSection& pSymTab,
-                                             MCLDInfo& pLDInfo,
-                                             uint32_t pSymIdx) const
-{
-  LDSection* symtab = &pSymTab;
-  LDSection* strtab = symtab->getLink();
-  assert(NULL != symtab && NULL != strtab);
-
-  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());
-
-  uint32_t st_name  = 0x0;
-  uint32_t st_size  = 0x0;
-  uint8_t  st_info  = 0x0;
-  uint8_t  st_other = 0x0;
-  uint16_t st_shndx = 0x0;
-  st_info  = entry->st_info;
-  st_other = entry->st_other;
-  if (llvm::sys::isLittleEndianHost()) {
-    st_name  = entry->st_name;
-    st_size  = entry->st_size;
-    st_shndx = entry->st_shndx;
-  }
-  else {
-    st_name  = bswap32(entry->st_name);
-    st_size  = bswap32(entry->st_size);
-    st_shndx = bswap16(entry->st_shndx);
-  }
-
-  MemoryRegion* strtab_region = pInput.memArea()->request(
-                       pInput.fileOffset() + strtab->offset(), strtab->size());
-
-  // get ld_name
-  llvm::StringRef ld_name(
-                    reinterpret_cast<char*>(strtab_region->start() + st_name));
-
-  // get ld_type
-  ResolveInfo::Type ld_type = static_cast<ResolveInfo::Type>(st_info & 0xF);
-
-  // get ld_desc
-  ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
-
-  // get ld_binding
-  ResolveInfo::Binding ld_binding =
-                             getSymBinding((st_info >> 4), st_shndx, st_other);
-
-  // get ld_vis
-  ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
-
-  ResolveInfo* result =
-         pLDInfo.getNamePool().createSymbol(ld_name,
-                                            (pInput.type() == Input::DynObj),
-                                            ld_type,
-                                            ld_desc,
-                                            ld_binding,
-                                            st_size,
-                                            ld_vis);
-  // release regions
-  pInput.memArea()->release(symbol_region);
-  pInput.memArea()->release(strtab_region);
-
-  return result;
-}
-
-/// readRela - read ELF rela and create Relocation
-bool ELFReader<32, true>::readRela(Input& pInput,
-                                   MCLinker& pLinker,
-                                   LDSection& pSection,
-                                   const MemoryRegion& 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());
-
-  for (size_t idx=0; idx < entsize; ++idx) {
-    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 = bswap32(relaTab[idx].r_offset);
-      r_info   = bswap32(relaTab[idx].r_info);
-      r_addend = bswap32(relaTab[idx].r_addend);
-    }
-
-    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();
-
-    ResolveInfo* resolve_info = symbol->resolveInfo();
-
-    FragmentRef* frag_ref =
-         pLinker.getLayout().getFragmentRef(*pSection.getLink(), r_offset);
-
-    if (NULL == frag_ref) {
-      fatal(diag::err_cannot_read_relocated_section)
-                                << pSection.name()
-                                << pSection.getLink()->index()
-                                << pInput.path();
-    }
-
-    pLinker.addRelocation(r_type, *symbol,  *resolve_info, *frag_ref, pSection, r_addend);
-  }
-  return true;
-}
-
-/// readRel - read ELF rel and create Relocation
-bool ELFReader<32, true>::readRel(Input& pInput,
-                                  MCLinker& pLinker,
-                                  LDSection& pSection,
-                                  const MemoryRegion& 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());
-
-  for (size_t idx=0; idx < entsize; ++idx) {
-    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 = bswap32(relTab[idx].r_offset);
-      r_info   = bswap32(relTab[idx].r_info);
-    }
-
-    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();
-    }
-
-    ResolveInfo* resolve_info = symbol->resolveInfo();
-
-    FragmentRef* frag_ref =
-         pLinker.getLayout().getFragmentRef(*pSection.getLink(), r_offset);
-
-    if (NULL == frag_ref) {
-      fatal(diag::err_cannot_read_relocated_section)
-                                << pSection.name()
-                                << pSection.getLink()->index()
-                                << pInput.path();
-    }
-
-    pLinker.addRelocation(r_type, *symbol, *resolve_info, *frag_ref, pSection);
-  }
-  return true;
-}
-
-/// readDynamic - read ELF .dynamic in input dynobj
-bool ELFReader<32, true>::readDynamic(Input& pInput) const
-{
-  assert(pInput.type() == Input::DynObj);
-  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
-  if (NULL == dynamic_sect) {
-    fatal(diag::err_cannot_read_section) << ".dynamic";
-  }
-  const LDSection* dynstr_sect = dynamic_sect->getLink();
-  if (NULL == dynstr_sect) {
-    fatal(diag::err_cannot_read_section) << ".dynstr";
-  }
-
-  MemoryRegion* dynamic_region = pInput.memArea()->request(
-           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
-
-  MemoryRegion* dynstr_region = pInput.memArea()->request(
-             pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
-
-  assert(NULL != dynamic_region && NULL != dynstr_region);
-
-  const llvm::ELF::Elf32_Dyn* dynamic =
-    (llvm::ELF::Elf32_Dyn*) dynamic_region->start();
-  const char* dynstr = (const char*) dynstr_region->start();
-  bool hasSOName = false;
-  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
-
-  for (size_t idx = 0; idx < numOfEntries; ++idx) {
-
-    llvm::ELF::Elf32_Sword d_tag = 0x0;
-    llvm::ELF::Elf32_Word d_val = 0x0;
-
-    if (llvm::sys::isLittleEndianHost()) {
-      d_tag = dynamic[idx].d_tag;
-      d_val = dynamic[idx].d_un.d_val;
-    } else {
-      d_tag = bswap32(dynamic[idx].d_tag);
-      d_val = bswap32(dynamic[idx].d_un.d_val);
-    }
-
-    switch (d_tag) {
-      case llvm::ELF::DT_SONAME:
-        assert(d_val < dynstr_sect->size());
-        pInput.setSOName(dynstr + d_val);
-        hasSOName = true;
-        break;
-      case llvm::ELF::DT_NEEDED:
-        // TODO:
-        break;
-      case llvm::ELF::DT_NULL:
-      default:
-        break;
-    }
-  }
-
-  // if there is no SONAME in .dynamic, then set it from input path
-  if (!hasSOName)
-    pInput.setSOName(pInput.path().native());
-
-  pInput.memArea()->release(dynamic_region);
-  pInput.memArea()->release(dynstr_region);
-  return true;
-}
-
diff --git a/include/mcld/LD/ELFSectionMap.h b/include/mcld/LD/ELFSectionMap.h
deleted file mode 100644
index e832fa9..0000000
--- a/include/mcld/LD/ELFSectionMap.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===- ELFSectionMap.h ----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_ELF_SECTION_MAP_H
-#define MCLD_LD_ELF_SECTION_MAP_H
-
-#include <mcld/LD/SectionMap.h>
-
-namespace mcld
-{
-
-class ELFSectionMap : public SectionMap
-{
-public:
-  ELFSectionMap();
-
-  ~ELFSectionMap();
-
-  void initStandardMaps();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/ELFSegment.h b/include/mcld/LD/ELFSegment.h
index 8b9ff98..d7f769e 100644
--- a/include/mcld/LD/ELFSegment.h
+++ b/include/mcld/LD/ELFSegment.h
@@ -41,45 +41,15 @@
   ~ELFSegment();
 
   ///  -----  iterators  -----  ///
-  sect_iterator sectBegin()
-  { return m_SectionList.begin(); }
+  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(); }
 
-  sect_iterator sectEnd()
-  { return m_SectionList.end(); }
-
-  const_sect_iterator sectBegin() const
-  { return m_SectionList.begin(); }
-
-  const_sect_iterator sectEnd() const
-  { return m_SectionList.end(); }
-
-  LDSection* getFirstSection()
-  {
-    if (0 == numOfSections())
-      return NULL;
-    return m_SectionList[0];
-  }
-
-  LDSection* getLastSection()
-  {
-    if (0 == numOfSections())
-      return NULL;
-    return m_SectionList[numOfSections() - 1];
-  }
-
-  const LDSection* getFirstSection() const
-  {
-    if (0 == numOfSections())
-      return NULL;
-    return m_SectionList[0];
-  }
-
-  const LDSection* getLastSection() const
-  {
-    if (0 == numOfSections())
-      return NULL;
-    return m_SectionList[numOfSections() - 1];
-  }
+  LDSection*       front()       { return m_SectionList.front(); }
+  const LDSection* front() const { return m_SectionList.front(); }
+  LDSection*       back()        { return m_SectionList.back(); }
+  const LDSection* back()  const { return m_SectionList.back(); }
 
   ///  -----  observers  -----  ///
   uint32_t type() const
@@ -109,6 +79,10 @@
   size_t numOfSections() const
   { return m_SectionList.size(); }
 
+  bool isDataSegment() const;
+
+  bool isBssSegment() const;
+
   ///  -----  modifiers  -----  ///
   void setOffset(uint64_t pOffset)
   { m_Offset = pOffset; }
diff --git a/include/mcld/LD/ELFWriter.h b/include/mcld/LD/ELFWriter.h
index 3a73605..b0c4d81 100644
--- a/include/mcld/LD/ELFWriter.h
+++ b/include/mcld/LD/ELFWriter.h
@@ -13,17 +13,20 @@
 #endif
 
 #include <llvm/Support/ELF.h>
-#include <mcld/MC/MCLDOutput.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class MCLDInfo;
-class Layout;
+class Module;
+class FragmentLinker;
+class LinkerConfig;
 class GNULDBackend;
 class Relocation;
 class LDSection;
 class SectionData;
+class RelocData;
+class Output;
+class MemoryRegion;
+class MemoryArea;
 
 /** \class ELFWriter
  *  \brief ELFWriter provides basic functions to write ELF sections, symbols,
@@ -48,54 +51,47 @@
   const GNULDBackend& target() const
   { return f_Backend; }
 
-  virtual void writeELF32Header(const MCLDInfo& pInfo,
-                                const Layout& pLayout,
-                                const GNULDBackend& pBackend,
-                                Output& pOutput) const;
+  virtual void writeELF32Header(const LinkerConfig& pConfig,
+                                const Module& pModule,
+                                MemoryArea& pOutput) const;
 
-  virtual void writeELF64Header(const MCLDInfo& pInfo,
-                                const Layout& pLayout,
-                                const GNULDBackend& pBackend,
-                                Output& pOutput) const;
+  virtual void writeELF64Header(const LinkerConfig& pConfig,
+                                const Module& pModule,
+                                MemoryArea& pOutput) const;
 
-  virtual uint64_t getEntryPoint(const MCLDInfo& pInfo,
-                                 const Layout& pLayout,
-                                 const GNULDBackend& pBackend,
-                                 const Output& pOutput) const;
+  virtual uint64_t getEntryPoint(const LinkerConfig& pConfig,
+                                 const Module& pModule) const;
 
 protected:
-  void emitELF32SectionHeader(Output& pOutput, MCLinker& pLinker) const;
+  void emitELF32SectionHeader(const Module& pModule,
+                              const LinkerConfig& pConfig,
+                              MemoryArea& pOutput) const;
 
-  void emitELF64SectionHeader(Output& pOutput, MCLinker& pLinker) const;
+  void emitELF64SectionHeader(const Module& pModule,
+                              const LinkerConfig& pConfig,
+                              MemoryArea& pOutput) const;
 
-  void emitELF32ProgramHeader(Output& pOutput,
-                              const GNULDBackend& pBackend) const;
+  void emitELF32ProgramHeader(MemoryArea& pOutput) const;
 
-  void emitELF64ProgramHeader(Output& pOutput,
-                              const GNULDBackend& pBackend) const;
+  void emitELF64ProgramHeader(MemoryArea& pOutput) const;
 
   // emitShStrTab - emit .shstrtab
-  void emitELF32ShStrTab(Output& pOutput, MCLinker& pLinker) const;
+  void emitELFShStrTab(const LDSection& pShStrTab, const Module& pModule,
+                       MemoryArea& pOutput);
 
-  void emitELF64ShStrTab(Output& pOutput, MCLinker& pLinker) const;
-
-  void emitSectionData(const Layout& pLayout,
-                       const LDSection& pSection,
+  void emitSectionData(const LDSection& pSection,
                        MemoryRegion& pRegion) const;
 
-  void emitRelocation(const Layout& pLayout,
-                      const Output& pOutput,
+  void emitRelocation(const LinkerConfig& pConfig,
                       const LDSection& pSection,
                       MemoryRegion& pRegion) const;
 
-  void emitRel(const Layout& pLayout,
-               const Output& pOutput,
-               const SectionData& pSectionData,
+  void emitRel(const LinkerConfig& pConfig,
+               const RelocData& pRelocData,
                MemoryRegion& pRegion) const;
 
-  void emitRela(const Layout& pLayout,
-                const Output& pOutput,
-                const SectionData& pSectionData,
+  void emitRela(const LinkerConfig& pConfig,
+                const RelocData& pRelocData,
                 MemoryRegion& pRegion) const;
 
 private:
@@ -106,14 +102,17 @@
   uint64_t getELF64SectEntrySize(const LDSection& pSection) const;
 
   // getSectEntrySize - compute ElfXX_Shdr::sh_link
-  uint64_t getSectLink(const LDSection& pSection, const Output& pOutput) const;
+  uint64_t getSectLink(const LDSection& pSection,
+                       const LinkerConfig& pConfig) const;
 
   // getSectEntrySize - compute ElfXX_Shdr::sh_info
-  uint64_t getSectInfo(const LDSection& pSection, const Output& pOutput) const;
+  uint64_t getSectInfo(const LDSection& pSection) const;
 
-  uint64_t getELF32LastStartOffset(const Output& pOutput) const;
+  uint64_t getELF32LastStartOffset(const Module& pModule) const;
 
-  uint64_t getELF64LastStartOffset(const Output& pOutput) const;
+  uint64_t getELF64LastStartOffset(const Module& pModule) const;
+
+  void emitSectionData(const SectionData& pSD, MemoryRegion& pRegion) const;
 
 protected:
   GNULDBackend& f_Backend;
diff --git a/include/mcld/LD/EhFrame.h b/include/mcld/LD/EhFrame.h
index 9497d79..dc360a2 100644
--- a/include/mcld/LD/EhFrame.h
+++ b/include/mcld/LD/EhFrame.h
@@ -6,136 +6,130 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_EXCEPTION_HANDLING_FRAME_H
-#define MCLD_EXCEPTION_HANDLING_FRAME_H
+#ifndef MCLD_LD_EH_FRAME_H
+#define MCLD_LD_EH_FRAME_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
+
 #include <vector>
+#include <mcld/Fragment/RegionFragment.h>
 
-#include <mcld/ADT/TypeTraits.h>
-#include <mcld/LD/CIE.h>
-#include <mcld/LD/FDE.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/Support/GCFactory.h>
+namespace mcld {
 
-namespace mcld
-{
-
-class Input;
-class Layout;
+class LDSection;
 class SectionData;
-class TargetLDBackend;
 
 /** \class EhFrame
  *  \brief EhFrame represents .eh_frame section
- *  EhFrame is responsible to parse the input eh_frame sections and create
- *  the corresponding CIE and FDE entries.
  */
 class EhFrame
 {
 public:
-  typedef ConstTraits<unsigned char>::pointer ConstAddress;
-  typedef std::vector<CIE*> CIEListType;
-  typedef std::vector<FDE*> FDEListType;
-  typedef CIEListType::iterator cie_iterator;
-  typedef CIEListType::const_iterator const_cie_iterator;
-  typedef FDEListType::iterator fde_iterator;
-  typedef FDEListType::const_iterator const_fde_iterator;
+  /** \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
+  {
+  public:
+    CIE(MemoryRegion& pRegion);
+
+    void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; }
+    uint8_t getFDEEncode() const { return m_FDEEncode; }
+
+  private:
+    uint8_t m_FDEEncode;
+  };
+
+  /** \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
+  {
+  public:
+    FDE(MemoryRegion& pRegion,
+        const CIE& pCIE,
+        uint32_t pDataStart);
+
+    const CIE& getCIE() const { return m_CIE; }
+
+    uint32_t getDataStart() const { return m_DataStart; }
+  private:
+    const CIE& m_CIE;
+    uint32_t m_DataStart;
+  };
+
+  typedef std::vector<CIE*> CIEList;
+
+  // 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;
+
+  typedef std::vector<FDE*> FDEList;
+
+  // 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;
 
 public:
-  EhFrame();
+  EhFrame(LDSection& pSection);
+
   ~EhFrame();
 
-  /// readEhFrame - read an .eh_frame section and create the corresponding
-  /// CIEs and FDEs
-  /// @param pSD - the SectionData of this input eh_frame
-  /// @param pSection - the input eh_frame
-  /// @param pArea - the memory area which pSection is within.
-  /// @ return - size of this eh_frame section, 0 if we do not recognize
-  /// this eh_frame or this is an empty section
-  uint64_t readEhFrame(Layout& pLayout,
-                       const TargetLDBackend& pBackend,
-                       SectionData& pSD,
-                       const Input& pInput,
-                       LDSection& pSection,
-                       MemoryArea& pArea);
+  /// merge - move all data from pOther to this object.
+  EhFrame& merge(EhFrame& pOther);
 
-  // ----- observers ----- //
-  cie_iterator cie_begin()
-  { return m_CIEs.begin(); }
+  const LDSection& getSection() const { return m_Section; }
+  LDSection&       getSection()       { return m_Section; }
 
-  const_cie_iterator cie_begin() const
-  { return m_CIEs.begin(); }
+  const SectionData& getSectionData() const { return *m_pSectionData; }
+  SectionData&       getSectionData()       { return *m_pSectionData; }
 
-  cie_iterator cie_end()
-  { return m_CIEs.end(); }
+  // -----  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);
 
-  const_cie_iterator cie_end() const
-  { return m_CIEs.end(); }
+  /// addCIE - add a CIE entry in EhFrame
+  void addCIE(CIE& pCIE);
 
-  fde_iterator fde_begin()
-  { return m_FDEs.begin(); }
+  /// addFDE - add a FDE entry in EhFrame
+  void addFDE(FDE& pFDE);
 
-  const_fde_iterator fde_begin() const
-  { return m_FDEs.begin(); }
+  // -----  CIE  ----- //
+  const_cie_iterator cie_begin() const { return m_CIEs.begin(); }
+  cie_iterator       cie_begin()       { return m_CIEs.begin(); }
+  const_cie_iterator cie_end  () const { return m_CIEs.end(); }
+  cie_iterator       cie_end  ()       { return m_CIEs.end(); }
 
-  fde_iterator fde_end()
-  { return m_FDEs.end(); }
+  const CIE& cie_front() const { return *m_CIEs.front(); }
+  CIE&       cie_front()       { return *m_CIEs.front(); }
+  const CIE& cie_back () const { return *m_CIEs.back(); }
+  CIE&       cie_back ()       { return *m_CIEs.back(); }
 
-  const_fde_iterator fde_end() const
-  { return m_FDEs.end(); }
+  size_t numOfCIEs() const { return m_CIEs.size(); }
 
-  /// getFDECount - the number of FDE entries
-  size_t getFDECount()
-  { return m_FDEs.size(); }
+  // -----  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(); }
 
-  size_t getFDECount() const
-  { return m_FDEs.size(); }
+  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(); }
 
-  /// canRecognizeAllEhFrame - return if we are able to parse all input
-  /// eh_frame sections
-  /// @return false - if there is any input .eh_frame section that
-  /// we are not able to recognize
-  bool canRecognizeAllEhFrame()
-  { return m_fCanRecognizeAll; }
-
-  bool canRecognizeAllEhFrame() const
-  { return m_fCanRecognizeAll; }
+  size_t numOfFDEs() const { return m_FDEs.size(); }
 
 private:
-  typedef std::vector<Fragment*> FragListType;
+  LDSection& m_Section;
+  SectionData* m_pSectionData;
 
-private:
-  /// addCIE - parse and create a CIE entry
-  /// @return false - cannot recognize this CIE
-  bool addCIE(MemoryRegion& pFrag,
-              const TargetLDBackend& pBackend,
-              FragListType& pFragList);
-
-  /// addFDE - parse and create an FDE entry
-  /// @return false - cannot recognize this FDE
-  bool addFDE(MemoryRegion& pFrag,
-              const TargetLDBackend& pBackend,
-              FragListType& pFragList);
-
-  /// readVal - read a 32 bit data from pAddr, swap it if needed
-  uint32_t readVal(ConstAddress pAddr, bool pIsTargetLittleEndian);
-
-  /// skipLEB128 - skip the first LEB128 encoded value from *pp, update *pp
-  /// to the next character.
-  /// @return - false if we ran off the end of the string.
-  /// @ref - GNU gold 1.11, ehframe.h, Eh_frame::skip_leb128.
-  bool skipLEB128(ConstAddress* pp, ConstAddress pend);
-
-  /// deleteFragments - release the MemoryRegion and delete Fragments in pList
-  void deleteFragments(FragListType& pList, MemoryArea& pArea);
-
-private:
-  CIEListType m_CIEs;
-  FDEListType m_FDEs;
-
-  bool m_fCanRecognizeAll;
+  CIEList m_CIEs;
+  FDEList m_FDEs;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/EhFrameHdr.h b/include/mcld/LD/EhFrameHdr.h
index 70f915c..3a5971d 100644
--- a/include/mcld/LD/EhFrameHdr.h
+++ b/include/mcld/LD/EhFrameHdr.h
@@ -11,36 +11,34 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <llvm/Support/Dwarf.h>
-#include <llvm/Support/DataTypes.h>
 #include <mcld/ADT/SizeTraits.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/CIE.h>
-#include <mcld/LD/FDE.h>
-#include <mcld/LD/Layout.h>
+#include <cassert>
 
-namespace mcld
-{
-class EhFrame;
+#include <mcld/LD/EhFrame.h>
+namespace mcld {
+
 class LDSection;
-class Output;
-class FDE;
-class MCLinker;
+class MemoryArea;
+class MemoryRegion;
 
 /** \class EhFrameHdr
  *  \brief EhFrameHdr represents .eh_frame_hdr section.
+ *
+ *  @ref lsb core generic 4.1
+ *  .eh_frame_hdr section format
+ *  uint8_t : version
+ *  uint8_t : eh_frame_ptr_enc
+ *  uint8_t : fde_count_enc
+ *  uint8_t : table_enc
+ *  uint32_t : eh_frame_ptr
+ *  uint32_t : fde_count
+ *  __________________________ when fde_count > 0
+ *  <uint32_t, uint32_t>+ : binary search table
  */
 class EhFrameHdr
 {
 public:
-  EhFrameHdr(const EhFrame& pEhFrameData,
-             const LDSection& pEhFrameSect,
-             LDSection& pEhFrameHdrSect);
+  EhFrameHdr(LDSection& pEhFrameHdr, const LDSection& pEhFrame);
 
   ~EhFrameHdr();
 
@@ -49,49 +47,28 @@
 
   /// emitOutput - write out eh_frame_hdr
   template<size_t size>
-  void emitOutput(Output& pOutput, MCLinker& pLinker);
+  void emitOutput(MemoryArea& pOutput)
+  { assert(false && "Call invalid EhFrameHdr::emitOutput"); }
 
 private:
-  /// getFDEPC - return the address of FDE's pc
-  /// @param pFDE - FDE
-  /// @param pOffset - the output offset of FDE
-  template<size_t size>
-  typename SizeTraits<size>::Address
-  getFDEPC(const FDE& pFDE,
-           typename SizeTraits<size>::Offset pOffset,
-           const MemoryRegion& pEhFrameRegion);
-
-  template<size_t size>
-  class BSTEntry
-  {
-  public:
-    typedef std::pair<typename SizeTraits<size>::Address,
-                      typename SizeTraits<size>::Address> EntryType;
-  };
-
-  template<size_t size>
-  struct BSTEntryCompare
-    : public std::binary_function<const typename BSTEntry<size>::EntryType&,
-                                  const typename BSTEntry<size>::EntryType&,
-                                  bool>
-  {
-    bool operator()(const typename BSTEntry<size>::EntryType& X,
-                    const typename BSTEntry<size>::EntryType& Y) const
-    { return X.first < Y.first; }
-  };
+  /// computePCBegin - return the address of FDE's pc
+  /// @ref binutils gold: ehframe.cc:222
+  uint32_t computePCBegin(const EhFrame::FDE& pFDE, const MemoryRegion& pEhFrameRegion);
 
 private:
-  /// eh_frame data
-  const EhFrame& m_EhFrameData;
-
-  /// .eh_frame section
-  const LDSection& m_EhFrameSect;
-
   /// .eh_frame_hdr section
-  LDSection& m_EhFrameHdrSect;
+  LDSection& m_EhFrameHdr;
+
+  /// eh_frame
+  const LDSection& m_EhFrame;
 };
 
-#include "EhFrameHdr.tcc"
+//===----------------------------------------------------------------------===//
+// Template Specification Functions
+//===----------------------------------------------------------------------===//
+/// emitOutput - write out eh_frame_hdr
+template<>
+void EhFrameHdr::emitOutput<32>(MemoryArea& pOutput);
 
 } // namespace of mcld
 
diff --git a/include/mcld/LD/EhFrameHdr.tcc b/include/mcld/LD/EhFrameHdr.tcc
deleted file mode 100644
index 3b7d8ee..0000000
--- a/include/mcld/LD/EhFrameHdr.tcc
+++ /dev/null
@@ -1,163 +0,0 @@
-//===- EhFrameHdr.tcc -----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <vector>
-
-using namespace mcld;
-using namespace llvm::dwarf;
-
-/// emitOutput - write out eh_frame_hdr
-template<size_t size>
-void EhFrameHdr::emitOutput(Output& pOutput, MCLinker& pLinker)
-{
-  MemoryRegion* ehframe_region =
-    pOutput.memArea()->request(m_EhFrameSect.offset(), m_EhFrameSect.size());
-
-  MemoryRegion* ehframehdr_region =
-    pOutput.memArea()->request(m_EhFrameHdrSect.offset(),
-                               m_EhFrameHdrSect.size());
-
-  uint8_t* data = (uint8_t*)ehframehdr_region->start();
-  // version
-  data[0] = 1;
-  // eh_frame_ptr_enc
-  data[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
-
-  // eh_frame_ptr
-  uint32_t* eh_frame_ptr = (uint32_t*)(data + 4);
-  *eh_frame_ptr = m_EhFrameSect.addr() - (m_EhFrameHdrSect.addr() + 4);
-
-  // fde_count
-  uint32_t* fde_count = (uint32_t*)(data + 8);
-  *fde_count = m_EhFrameData.getFDECount();
-
-  if (m_EhFrameData.getFDECount() != 0 &&
-      m_EhFrameData.canRecognizeAllEhFrame()) {
-    // fde_count_enc
-    data[2] = DW_EH_PE_udata4;
-    // table_enc
-    data[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
-
-    // prepare the binary search table
-    typedef std::vector<typename BSTEntry<size>::EntryType> SearchTableType;
-    SearchTableType search_table;
-    EhFrame::const_fde_iterator fde = m_EhFrameData.fde_begin(),
-                                fde_end = m_EhFrameData.fde_end();
-    for(; fde != fde_end; ++fde) {
-      assert(*fde != NULL);
-      typename SizeTraits<size>::Offset offset;
-      typename SizeTraits<size>::Address fde_pc;
-      typename SizeTraits<size>::Address fde_addr;
-      offset = pLinker.getLayout().getOutputOffset(**fde);
-      fde_pc = getFDEPC<size>(**fde, offset, *ehframe_region);
-      fde_addr = m_EhFrameSect.addr() + offset;
-      search_table.push_back(std::make_pair(fde_pc, fde_addr));
-    }
-
-    std::sort(search_table.begin(), search_table.end(), BSTEntryCompare<size>());
-
-    // write out the binary search table
-    uint32_t* bst = (uint32_t*)(data + 12);
-    typename SearchTableType::const_iterator entry = search_table.begin(),
-                                             entry_end = search_table.end();
-    for (size_t id = 0; entry != entry_end; ++entry) {
-      bst[id++] = (*entry).first - m_EhFrameHdrSect.addr();
-      bst[id++] = (*entry).second - m_EhFrameHdrSect.addr();
-    }
-  } else {
-    // fde_count_enc
-    data[2] = DW_EH_PE_omit;
-    // table_enc
-    data[3] = DW_EH_PE_omit;
-  }
-
-  pOutput.memArea()->release(ehframe_region);
-  pOutput.memArea()->release(ehframehdr_region);
-}
-
-/// getFDEPC - return the address of FDE's pc
-/// @ref binutils gold: ehframe.cc:222
-template<size_t size>
-typename SizeTraits<size>::Address
-EhFrameHdr::getFDEPC(const FDE& pFDE,
-                     typename SizeTraits<size>::Offset pOffset,
-                     const MemoryRegion& pEhFrameRegion)
-{
-  uint8_t fde_encoding = pFDE.getCIE().getFDEEncode();
-  unsigned int eh_value = fde_encoding & 0x7;
-
-  // check the size to read in
-  if (eh_value == llvm::dwarf::DW_EH_PE_absptr) {
-    if (size == 32)
-      eh_value = DW_EH_PE_udata4;
-    else if (size == 64)
-      eh_value = DW_EH_PE_udata8;
-  }
-
-  size_t pc_size = 0x0;
-  switch (eh_value) {
-    case DW_EH_PE_udata2:
-      pc_size = 2;
-      break;
-    case DW_EH_PE_udata4:
-      pc_size = 4;
-      break;
-    case DW_EH_PE_udata8:
-      pc_size = 8;
-      break;
-    default:
-      // TODO
-      break;
-  }
-
-  typename SizeTraits<size>::Address pc = 0x0;
-  const uint8_t* offset = (const uint8_t*) pEhFrameRegion.start() +
-                          pOffset +
-                          pFDE.getPCBeginOffset();
-  std::memcpy(&pc, offset, pc_size);
-
-  // adjust the signed value
-  bool is_signed = (fde_encoding & llvm::dwarf::DW_EH_PE_signed) != 0x0;
-  switch (eh_value) {
-    case DW_EH_PE_udata2:
-      if (is_signed)
-        pc = (pc ^ 0x8000) - 0x8000;
-      break;
-    case DW_EH_PE_udata4:
-      if (is_signed && size > 32)
-        pc = (pc ^ 0x80000000) - 0x80000000;
-      break;
-    case DW_EH_PE_udata8:
-      break;
-    default:
-      // TODO
-      break;
-  }
-
-  // handle eh application
-  switch (fde_encoding & 0x70)
-  {
-    case DW_EH_PE_absptr:
-      break;
-    case DW_EH_PE_pcrel:
-      pc += m_EhFrameSect.addr() +
-            pOffset +
-            pFDE.getPCBeginOffset();
-      break;
-    case DW_EH_PE_datarel:
-      // TODO
-      break;
-    default:
-      // TODO
-      break;
-  }
-
-  return pc;
-}
-
diff --git a/include/mcld/LD/EhFrameReader.h b/include/mcld/LD/EhFrameReader.h
new file mode 100644
index 0000000..1ac0351
--- /dev/null
+++ b/include/mcld/LD/EhFrameReader.h
@@ -0,0 +1,109 @@
+//===- EhFrameReader.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_EH_FRAME_READER_H
+#define MCLD_EH_FRAME_READER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Support/MemoryRegion.h>
+
+namespace mcld {
+
+class Input;
+class EhFrame;
+class LDSection;
+
+/** \class EhFrameReader
+ *  \brief EhFrameReader reads .eh_frame section
+ *
+ *  EhFrameReader is responsible to parse the input eh_frame sections and create
+ *  the corresponding CIE and FDE entries.
+ */
+class EhFrameReader
+{
+public:
+  typedef const uint8_t* ConstAddress;
+  typedef       uint8_t* Address;
+
+public:
+  /// read - read an .eh_frame section and create the corresponding
+  /// CIEs and FDEs
+  /// @param pInput [in] the Input contains this eh_frame
+  /// @param pEhFrame [inout] the input eh_frame
+  /// @return if we read all CIEs and FDEs successfully, return true. Otherwise,
+  /// return false;
+  template<size_t BITCLASS, bool SAME_ENDIAN>
+  bool read(Input& pInput, EhFrame& pEhFrame);
+
+private:
+  enum TokenKind {
+    CIE,
+    FDE,
+    Terminator,
+    Unknown,
+    NumOfTokenKinds
+  };
+
+  enum State {
+    Q0,
+    Q1,
+    Accept,
+    NumOfStates = 2,
+    Reject      = -1
+  };
+
+  struct Token {
+    TokenKind kind;
+    size_t file_off;
+    size_t data_off;
+    uint64_t size;
+  };
+
+  /// Action - the transition function of autometa.
+  /// @param pEhFrame - the output .eh_frame section
+  /// @param pSection - the input .eh_frame section
+  /// @param pRegion - the memory region that needs to handle with.
+  typedef bool (*Action)(EhFrame& pEhFrame,
+                         MemoryRegion& 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;
+
+  static bool addCIE(EhFrame& pEhFrame,
+                     MemoryRegion& pRegion,
+                     const Token& pToken);
+
+  static bool addFDE(EhFrame& pEhFrame,
+                     MemoryRegion& pRegion,
+                     const Token& pToken);
+
+  static bool addTerm(EhFrame& pEhFrame,
+                      MemoryRegion& pRegion,
+                      const Token& pToken);
+
+  static bool reject(EhFrame& pEhFrame,
+                     MemoryRegion& pRegion,
+                     const Token& pToken);
+
+};
+
+template<> bool
+EhFrameReader::read<32, true>(Input& pInput, EhFrame& pEhFrame);
+
+template<> EhFrameReader::Token
+EhFrameReader::scan<true>(ConstAddress pHandler,
+                          uint64_t pOffset,
+                          const MemoryRegion& pData) const;
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ExecWriter.h b/include/mcld/LD/ExecWriter.h
index edce096..e0ea325 100644
--- a/include/mcld/LD/ExecWriter.h
+++ b/include/mcld/LD/ExecWriter.h
@@ -11,12 +11,14 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <mcld/MC/MCLDOutput.h>
 #include <mcld/LD/LDWriter.h>
 #include <llvm/Support/system_error.h>
 
-namespace mcld
-{
+namespace mcld {
+
+class Module;
+class MemoryArea;
+class TargetLDBackend;
 
 /** \class ExecWriter
  *  \brief ExecWriter provides an common interface for different object
@@ -32,7 +34,8 @@
 public:
   virtual ~ExecWriter() { }
 
-  virtual llvm::error_code writeExecutable(Output& pOutput) = 0;
+  virtual llvm::error_code writeExecutable(Module& pModule,
+                                           MemoryArea& pOutput) = 0;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/FDE.h b/include/mcld/LD/FDE.h
deleted file mode 100644
index 760a584..0000000
--- a/include/mcld/LD/FDE.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- FDE.h --------------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_FRAME_DESCRIPTION_ENTRY_H
-#define MCLD_LD_FRAME_DESCRIPTION_ENTRY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/Support/DataTypes.h>
-#include <mcld/LD/CIE.h>
-#include <mcld/LD/RegionFragment.h>
-
-namespace mcld
-{
-
-/** \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
-{
-public:
-  typedef uint32_t Offset;
-
-public:
-  FDE(MemoryRegion& pRegion, const CIE& pCIE, Offset pPCBeginOffset);
-  ~FDE();
-
-  /// ----- observers ------ ///
-  /// getCIE - the CIE corresponding to this FDE
-  const CIE& getCIE() const
-  { return m_CIE; }
-
-  /// getPCBeginOffset - the offset to the FDE of the PC Begin field
-  Offset getPCBeginOffset() const
-  { return m_PCBeginOffset; }
-
-private:
-  const CIE& m_CIE;
-  Offset m_PCBeginOffset;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/GNUArchiveReader.h b/include/mcld/LD/GNUArchiveReader.h
index 39a9438..7a33ff4 100644
--- a/include/mcld/LD/GNUArchiveReader.h
+++ b/include/mcld/LD/GNUArchiveReader.h
@@ -15,12 +15,12 @@
 #include <mcld/LD/ArchiveReader.h>
 #include <mcld/LD/Archive.h>
 
-namespace mcld
-{
-class MemoryAreaFactory;
-class MCLDInfo;
+namespace mcld {
+
+class Module;
 class Input;
 class ELFObjectReader;
+class MemoryAreaFactory;
 class Archive;
 
 /** \class GNUArchiveReader
@@ -29,9 +29,7 @@
 class GNUArchiveReader : public ArchiveReader
 {
 public:
-  explicit GNUArchiveReader(MCLDInfo& pLDInfo,
-                            MemoryAreaFactory& pMemAreaFactory,
-                            ELFObjectReader& pELFObjectReader);
+  GNUArchiveReader(Module& pModule, ELFObjectReader& pELFObjectReader);
 
   ~GNUArchiveReader();
 
@@ -60,10 +58,12 @@
   /// @param pArchiveFile  - the archive that contains the needed object
   /// @param pFileOffset   - file offset of the member header in the archive
   /// @param pNestedOffset - used when we find a nested archive
+  /// @param pMemberSize   - the file size of this member
   Input* readMemberHeader(Archive& pArchiveRoot,
                           Input& pArchiveFile,
                           uint32_t pFileOffset,
-                          uint32_t& pNestedOffset);
+                          uint32_t& pNestedOffset,
+                          size_t& pMemberSize);
 
   /// readSymbolTable - read the archive symbol map (armap)
   bool readSymbolTable(Archive& pArchive);
@@ -76,9 +76,18 @@
   enum Archive::Symbol::Status
   shouldIncludeSymbol(const llvm::StringRef& pSymName) const;
 
+  /// includeMember - include the object member in the given file offset, and
+  /// return the size of the object
+  /// @param pArchiveRoot - the archive root
+  /// @param pFileOffset  - file offset of the member header in the archive
+  size_t includeMember(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);
+
 private:
-  MCLDInfo& m_LDInfo;
-  MemoryAreaFactory& m_MemAreaFactory;
+  Module& m_Module;
   ELFObjectReader& m_ELFObjectReader;
 };
 
diff --git a/include/mcld/LD/GroupReader.h b/include/mcld/LD/GroupReader.h
new file mode 100644
index 0000000..39c21f8
--- /dev/null
+++ b/include/mcld/LD/GroupReader.h
@@ -0,0 +1,68 @@
+//===- GroupReader.h ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_GROUPREADER_H
+#define MCLD_GROUPREADER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Module.h>
+
+namespace mcld
+{
+class Archive;
+class ArchiveReader;
+class DynObjReader;
+class LinkerConfig;
+class ObjectReader;
+
+/** \class GroupReader
+ *  \brief GroupReader handles the Group Node in InputTree
+ *
+ *  Group Node is the root of sub-tree in InputTree which includes the iputs in
+ *  the command line options --start-group and --end-group options
+ */
+class GroupReader
+{
+public:
+  GroupReader(Module& pModule,
+              ObjectReader& pObjectReader,
+              DynObjReader& pDynObjReader,
+              ArchiveReader& pArchiveReader);
+
+  ~GroupReader();
+
+  /// 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,
+                 InputBuilder& pBuilder,
+                 const LinkerConfig& pConfig);
+
+private:
+  /// ArchiveListEntry - record the Archive and the corresponding input iterator
+  /// of the archive node
+  struct ArchiveListEntry {
+    ArchiveListEntry(Archive& pArchive, Module::input_iterator pIterator)
+      : archive(pArchive), input(pIterator) {
+    }
+    Archive& archive;
+    Module::input_iterator input;
+  };
+
+private:
+  Module& m_Module;
+  ObjectReader& m_ObjectReader;
+  DynObjReader& m_DynObjReader;
+  ArchiveReader& m_ArchiveReader;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/LDContext.h b/include/mcld/LD/LDContext.h
index 878ba8d..3ab6ce1 100644
--- a/include/mcld/LD/LDContext.h
+++ b/include/mcld/LD/LDContext.h
@@ -22,8 +22,7 @@
 class StringRef;
 }
 
-namespace mcld
-{
+namespace mcld {
 
 class LDSymbol;
 class LDSection;
@@ -43,36 +42,20 @@
   typedef SymbolTable::const_iterator const_sym_iterator;
 
 public:
-  LDContext();
-
-  ~LDContext();
-
   // -----  sections  ----- //
-  SectionTable& getSectionTable()
-  { return m_SectionTable; }
+  LDContext& appendSection(LDSection& pSection);
 
-  const SectionTable& getSectionTable() const
-  { return m_SectionTable; }
+  const_sect_iterator sectBegin() const { return m_SectionTable.begin(); }
+  sect_iterator       sectBegin()       { return m_SectionTable.begin(); }
 
-  sect_iterator sectBegin()
-  { return m_SectionTable.begin(); }
-
-  sect_iterator sectEnd()
-  { return m_SectionTable.end(); }
-
-  const_sect_iterator sectBegin() const
-  { return m_SectionTable.begin(); }
-
-  const_sect_iterator sectEnd() const
-  { return m_SectionTable.end(); }
-
-  LDSection* getSection(unsigned int pIdx);
+  const_sect_iterator sectEnd() const { return m_SectionTable.end(); }
+  sect_iterator       sectEnd()       { return m_SectionTable.end(); }
 
   const LDSection* getSection(unsigned int pIdx) const;
-
-  LDSection* getSection(const std::string& pName);
+  LDSection*       getSection(unsigned int pIdx);
 
   const LDSection* getSection(const std::string& pName) const;
+  LDSection*       getSection(const std::string& pName);
 
   size_t getSectionIdx(const std::string& pName) const;
 
@@ -80,20 +63,26 @@
   { return m_SectionTable.size(); }
 
   // -----  symbols  ----- //
-  LDSymbol* getSymbol(unsigned int pIdx);
-
   const LDSymbol* getSymbol(unsigned int pIdx) const;
-
-  LDSymbol* getSymbol(const llvm::StringRef& pName);
+  LDSymbol*       getSymbol(unsigned int pIdx);
 
   const LDSymbol* getSymbol(const llvm::StringRef& pName) const;
+  LDSymbol*       getSymbol(const llvm::StringRef& pName);
 
   void addSymbol(LDSymbol* pSym)
   { m_SymTab.push_back(pSym); }
 
+  // -----  relocations  ----- //
+  const_sect_iterator relocSectBegin() const { return m_RelocSections.begin(); }
+  sect_iterator       relocSectBegin()       { return m_RelocSections.begin(); }
+
+  const_sect_iterator relocSectEnd() const { return m_RelocSections.end(); }
+  sect_iterator       relocSectEnd()       { return m_RelocSections.end(); }
+
 private:
   SectionTable m_SectionTable;
   SymbolTable m_SymTab;
+  SectionTable m_RelocSections;
 
   // FIXME : maintain a map<section name, section index>
 };
diff --git a/include/mcld/LD/LDFileFormat.h b/include/mcld/LD/LDFileFormat.h
index a537fb1..cd4bfd8 100644
--- a/include/mcld/LD/LDFileFormat.h
+++ b/include/mcld/LD/LDFileFormat.h
@@ -15,11 +15,10 @@
 #include <cstdio>
 #include <cassert>
 
-namespace mcld
-{
+namespace mcld {
 
-class MCLinker;
 class LDSection;
+class ObjectBuilder;
 
 /** \class LDFileFormat
  *  \brief LDFileFormat describes the common file formats.
@@ -42,6 +41,8 @@
     Note,
     MetaData,
     Group,
+    StackNote,
+    Ignore
   };
 
 protected:
@@ -50,16 +51,11 @@
 public:
   virtual ~LDFileFormat();
 
-  /// initStdSections - initialize all standard sections.
-  void initStdSections(MCLinker& pLinker);
-
-  /// initObjectFormat - different format, such as ELF and MachO, should
-  /// implement this
-  virtual void initObjectFormat(MCLinker& pLinker) = 0;
-
-  /// initObjectType - different types, such as shared object, executable
-  /// files, should implement this
-  virtual void initObjectType(MCLinker& pLinker) = 0;
+  /// initStdSections - initialize all standard section headers.
+  /// @param [in] pBuilder The ObjectBuilder to create section headers
+  /// @param [in] pBitClass The bitclass of target backend.
+  virtual void initStdSections(ObjectBuilder& pBuilder,
+                               unsigned int pBitClass) = 0;
 
   // -----  access functions  ----- //
   LDSection& getText() {
diff --git a/include/mcld/LD/LDSection.h b/include/mcld/LD/LDSection.h
index 4c881ca..e57b2a6 100644
--- a/include/mcld/LD/LDSection.h
+++ b/include/mcld/LD/LDSection.h
@@ -13,14 +13,17 @@
 #include <gtest.h>
 #endif
 
-#include <llvm/ADT/StringRef.h>
 #include <llvm/Support/DataTypes.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
 #include <mcld/LD/LDFileFormat.h>
 #include <string>
 
 namespace mcld {
 
 class SectionData;
+class RelocData;
+class EhFrame;
 
 /** \class LDSection
  *  \brief LDSection represents a section header entry. It is a unified
@@ -28,15 +31,34 @@
  */
 class LDSection
 {
-public:
+private:
+  friend class Chunk<LDSection, MCLD_SECTIONS_PER_INPUT>;
+
+  LDSection();
+
   LDSection(const std::string& pName,
             LDFileFormat::Kind pKind,
             uint32_t pType,
             uint32_t pFlag,
             uint64_t pSize = 0,
-            uint64_t pOffset = 0,
             uint64_t pAddr = 0);
 
+public:
+  ~LDSection();
+
+  static LDSection* Create(const std::string& pName,
+                           LDFileFormat::Kind pKind,
+                           uint32_t pType,
+                           uint32_t pFlag,
+                           uint64_t pSize = 0,
+                           uint64_t pAddr = 0);
+
+  static void Destroy(LDSection*& pSection);
+
+  static void Clear();
+
+  bool hasOffset() const;
+
   /// name - the name of this section.
   const std::string& name() const
   { return m_Name; }
@@ -128,17 +150,29 @@
   void setType(uint32_t type)
   { m_Type = type; }
 
-  SectionData* getSectionData()
-  { return m_pSectionData; }
+  // -----  SectionData  ----- //
+  const SectionData* getSectionData() const { return m_Data.sect_data; }
+  SectionData*       getSectionData()       { return m_Data.sect_data; }
 
-  const SectionData* getSectionData() const
-  { return m_pSectionData; }
+  void setSectionData(SectionData* pSD) { m_Data.sect_data = pSD; }
 
-  void setSectionData(SectionData* pSD)
-  { m_pSectionData = pSD; }
+  bool hasSectionData() const;
 
-  bool hasSectionData() const
-  { return (NULL != m_pSectionData); }
+  // ------  RelocData  ------ //
+  const RelocData* getRelocData() const { return m_Data.reloc_data; }
+  RelocData*       getRelocData()       { return m_Data.reloc_data; }
+
+  void setRelocData(RelocData* pRD) { m_Data.reloc_data = pRD; }
+
+  bool hasRelocData() const;
+
+  // ------  EhFrame  ------ //
+  const EhFrame* getEhFrame() const { return m_Data.eh_frame; }
+  EhFrame*       getEhFrame()       { return m_Data.eh_frame; }
+
+  void setEhFrame(EhFrame* pEhFrame) { m_Data.eh_frame = pEhFrame; }
+
+  bool hasEhFrame() const;
 
   /// setLink - set the sections should link with.
   /// if pLink is NULL, no Link section is set.
@@ -152,7 +186,16 @@
   { m_Index = pIndex; }
 
 private:
+  union SectOrRelocData
+  {
+    SectionData* sect_data;
+    RelocData*   reloc_data;
+    EhFrame*     eh_frame;
+  };
+
+private:
   std::string m_Name;
+
   LDFileFormat::Kind m_Kind;
   uint32_t m_Type;
   uint32_t m_Flag;
@@ -165,9 +208,10 @@
   size_t m_Info;
   LDSection* m_pLink;
 
-  SectionData* m_pSectionData;
+  /// m_Data - the SectionData or RelocData of this section
+  SectOrRelocData m_Data;
 
-  // the index of the file
+  /// m_Index - the index of the file
   size_t m_Index;
 
 }; // end of LDSection
diff --git a/include/mcld/LD/LDSectionFactory.h b/include/mcld/LD/LDSectionFactory.h
deleted file mode 100644
index b748a64..0000000
--- a/include/mcld/LD/LDSectionFactory.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//===- LDSectionFactory.h -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LDSECTION_FACTORY_H
-#define MCLD_LDSECTION_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <string>
-
-#include <mcld/Support/GCFactory.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/LDFileFormat.h>
-
-namespace mcld
-{
-
-/** \class LDSectionFactory
- *  \brief provide the interface to create and delete section data for output
- */
-class LDSectionFactory : public GCFactory<LDSection, 0>
-{
-public:
-  /// LDSectionFactory - the factory of LDSection
-  /// pNum is the average number of the LDSections in the system.
-  LDSectionFactory(size_t pNum);
-  ~LDSectionFactory();
-
-  /// produce - produce an empty section information.
-  /// This function will create an empty SectionData and its LDSection.
-  /// @param pName - The name of the section.
-  /// @param pKind - The kind of the section. Used to create default section map
-  /// @param pType - sh_type in ELF.
-  /// @param pFlag - is the same as sh_flags.
-  LDSection* produce(const std::string& pName,
-                     LDFileFormat::Kind pKind,
-                     uint32_t pType,
-                     uint32_t pFlag);
-
-  /// destroy - destruct the LDSection.
-  /// @oaram - the reference of the pointer to the destructed LDSection.
-  ///          after the destruction, the pointer is set to zero.
-  void destroy(LDSection*& pSD);
-
-  /// find - find the LDSection* in factory from the given section name.
-  ///        return NULL if not found.
-  /// @param pName - the name of section
-  LDSection* find(const std::string& pName);
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/LDSymbol.h b/include/mcld/LD/LDSymbol.h
index 99b3885..326c82f 100644
--- a/include/mcld/LD/LDSymbol.h
+++ b/include/mcld/LD/LDSymbol.h
@@ -14,12 +14,14 @@
 
 #include <cassert>
 
+#include <mcld/Config/Config.h>
 #include <mcld/ADT/Uncopyable.h>
 #include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/FragmentRef.h>
+#include <mcld/Support/Allocators.h>
 
-namespace mcld
-{
+namespace mcld {
+
+class FragmentRef;
 
 /** \class LDSymbol
  *  \brief LDSymbol provides a consistent abstraction for different formats
@@ -31,15 +33,25 @@
   // FIXME: use SizeTrait<32> or SizeTrait<64> instead of big type
   typedef ResolveInfo::SizeType SizeType;
   typedef uint64_t ValueType;
-  typedef FragmentRef::Offset Offset;
 
 public:
-  LDSymbol();
-  LDSymbol(const LDSymbol& pCopy);
-  LDSymbol& operator=(const LDSymbol& pCopy);
   ~LDSymbol();
 
+  // -----  factory method ----- //
+  static LDSymbol* Create(ResolveInfo& pResolveInfo);
+
+  static void Destroy(LDSymbol*& pSymbol);
+
+  /// Clear - This function tells MCLinker to clear all created LDSymbols.
+  static void Clear();
+
+  /// NullSymbol() - This returns a reference to a LDSymbol that represents Null
+  /// symbol.
+  static LDSymbol* Null();
+
   // -----  observers  ----- //
+  bool isNull() const;
+
   const char* name() const {
     assert(NULL != m_pResolveInfo);
     return m_pResolveInfo->name();
@@ -98,8 +110,7 @@
   const ResolveInfo* resolveInfo() const 
   { return m_pResolveInfo; }
 
-  bool hasFragRef() const
-  { return (NULL != m_pFragRef); }
+  bool hasFragRef() const;
 
   // -----  modifiers  ----- //
   void setSize(SizeType pSize) {
@@ -115,6 +126,13 @@
   void setResolveInfo(const ResolveInfo& pInfo);
 
 private:
+  friend class Chunk<LDSymbol, MCLD_SYMBOLS_PER_INPUT>;
+
+  LDSymbol();
+  LDSymbol(const LDSymbol& pCopy);
+  LDSymbol& operator=(const LDSymbol& pCopy);
+
+private:
   // -----  Symbol's fields  ----- //
   ResolveInfo* m_pResolveInfo;
   FragmentRef* m_pFragRef;
diff --git a/include/mcld/LD/LDWriter.h b/include/mcld/LD/LDWriter.h
index 78c2871..b7dd14c 100644
--- a/include/mcld/LD/LDWriter.h
+++ b/include/mcld/LD/LDWriter.h
@@ -16,10 +16,8 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <mcld/Target/TargetLDBackend.h>
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class LDWriter
  *  \brief LDWriter provides the basic interfaces for all writers.
diff --git a/include/mcld/LD/Layout.h b/include/mcld/LD/Layout.h
index 4dc9897..7380b20 100644
--- a/include/mcld/LD/Layout.h
+++ b/include/mcld/LD/Layout.h
@@ -12,28 +12,29 @@
 #include <gtest.h>
 #endif
 
+#include <vector>
 #include <map>
 
 #include <llvm/ADT/ilist.h>
 #include <llvm/ADT/ilist_node.h>
 #include <llvm/ADT/DenseMap.h>
 
-#include <mcld/LD/FragmentRef.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/SectionData.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Support/GCFactory.h>
 
-namespace mcld
-{
-class MCLinker;
-class Output;
+namespace mcld {
+
+class Module;
+class FragmentRef;
+class FragmentLinker;
 class TargetLDBackend;
 
 /** \class Layout
  *  \brief Layout maintains the mapping between sections and fragments.
  *
- *  MCLinker is a fragment-based linker. But readers and target backends
+ *  FragmentLinker is a fragment-based linker. But readers and target backends
  *  still need section information. Layout is used to maintain the mapping
  *  between sections and fragments. Layout helps readers and target backends
  *  get the input or output section information from a fragment.
@@ -41,229 +42,23 @@
 class Layout
 {
 public:
-  typedef std::vector<LDSection*> SectionOrder;
-  typedef SectionOrder::iterator sect_iterator;
-  typedef SectionOrder::const_iterator const_sect_iterator;
-
-public:
-  /// constructor
-  Layout();
-
-  /// destructor
-  ~Layout();
-
-  /// getInputLDSection - give a Fragment, return the corresponding input
-  /// LDSection*
-  ///
-  /// @return return NULL if the fragment is not found in input
-  LDSection* getInputLDSection(const Fragment& pFrag);
-
-  /// getInputLDSection - give a Fragment, return the corresponding input
-  /// LDSection*
-  ///
-  /// @return return NULL if the fragment is not found in input
-  const LDSection* getInputLDSection(const Fragment& pFrag) const;
-
-  /// getFragmentRef - give a LDSection in input file and an offset, return
-  /// the fragment reference.
-  ///
-  /// @param pInputSection - the given input section
-  /// @param pOffset - the offset, cannot be larger than this input section.
-  /// @return if found, return the fragment. Otherwise, return NULL.
-  FragmentRef*
-  getFragmentRef(const LDSection& pInputSection, uint64_t pOffset);
-
-  /// getFragmentRef - give a fragment and a big offset, return the fragment
-  /// reference in the section data.
-  ///
-  /// @param pFrag - the given fragment
-  /// @param pBigOffset - the offset, can be larger than the fragment, but can
-  ///                     not larger than this input section.
-  /// @return if found, return the fragment. Otherwise, return NULL.
-  FragmentRef* getFragmentRef(const Fragment& pFrag, uint64_t pBigOffset);
-
-  /// getOutputOffset - Get the offset of the given fragment inside the
-  /// the output's SectionData.
-  uint64_t getOutputOffset(const Fragment& pFrag);
-
-  /// getOutputOffset - Get the offset of the given fragment inside the
-  /// the output's SectionData.
-  uint64_t getOutputOffset(const Fragment& pFrag) const;
-
-  /// getOutputOffset - Get the offset of the given fragment inside
-  /// the output's SectionData.
-  ///
-  /// @return return -1 if the fragment is not found in output's SectionData.
-
-  uint64_t getOutputOffset(const FragmentRef& pFragRef);
-  /// getOutputOffset - Get the offset of the given fragment inside
-  /// the output's SectionData.
-  ///
-  /// @return return -1 if the fragment is not found in output's SectionData.
-  uint64_t getOutputOffset(const FragmentRef& pFragRef) const;
-
-  /// getOutputLDSection - give a Fragment, return the corresponding output
-  /// LDSection*
-  ///
-  /// @return return NULL if the fragment is not found in the output
-  LDSection* getOutputLDSection(const Fragment& pFrag);
-
-  /// getOutputLDSection - give a Fragment, return the corresponding output
-  /// LDSection*
-  ///
-  /// @return return NULL if the fragment is not found in the output
-  const LDSection* getOutputLDSection(const Fragment& pFrag) const;
-
   // -----  modifiers  ----- //
-  bool layout(Output& pOutput,
-              const TargetLDBackend& pBackend, const MCLDInfo& pInfo);
-
-  /// addInputRange
-  void addInputRange(const SectionData& pSD, const LDSection& pInputHdr);
-
-  /// appendFragment - append the given Fragment to the given SectionData,
-  /// and insert a AlignFragment to preserve the required align constraint if
-  /// needed
-  /// @return return the inserted size, i.e., the size of pFrag and alignment
-  /// size if any
-  uint64_t appendFragment(Fragment& pFrag, SectionData& pSD,
-                          uint32_t pAlignConstraint = 1);
-private:
-  /** \class Range
-   *  \brief Range is a <input's LDSection, previous rear fragment> pair
-   */
-  struct Range : public llvm::ilist_node<Range>
-  {
-  public:
-    Range();
-    Range(const LDSection& pHeader);
-    ~Range();
-
-  public:
-    LDSection* header;
-    Fragment* prevRear;
-  };
-
-  typedef llvm::iplist<Range> RangeList;
-
-  typedef std::map<const SectionData*, RangeList*> SDRangeMap;
-
-  typedef GCFactory<FragmentRef, 0> FragRefFactory;
+  bool layout(Module& pModule,
+              const TargetLDBackend& pBackend,
+              const LinkerConfig& pConfig);
 
 private:
-  inline bool isFirstRange(const Range& pRange) const
-  { return (NULL == pRange.prevRear); }
-
-  inline bool isLastRange(const Range& pRange) const
-  { return (NULL == pRange.getNextNode()); }
-
-  inline bool isEmptyRange(const Range& pRange) const
-  {
-    if (isFirstRange(pRange)) {
-      if (!pRange.header->hasSectionData() ||
-          pRange.header->getSectionData()->getFragmentList().empty())
-        return true;
-      else
-        return false;
-    }
-    return (NULL == pRange.prevRear->getNextNode());
-  }
-
-  // get the front fragment in the range.
-  inline Fragment* getFront(Range& pRange) const
-  {
-    if (!pRange.header->hasSectionData())
-      return NULL;
-    if (pRange.header->getSectionData()->getFragmentList().empty())
-      return NULL;
-
-    if (isFirstRange(pRange))
-      return &pRange.header->getSectionData()->getFragmentList().front();
-
-    if (isEmptyRange(pRange))
-      return NULL;
-
-    return pRange.prevRear->getNextNode();
-  }
-
-  inline const Fragment* getFront(const Range& pRange) const
-  {
-    if (!pRange.header->hasSectionData())
-      return NULL;
-    if (pRange.header->getSectionData()->getFragmentList().empty())
-      return NULL;
-
-    if (isFirstRange(pRange))
-      return &pRange.header->getSectionData()->getFragmentList().front();
-
-    if (isEmptyRange(pRange))
-      return NULL;
-
-    return pRange.prevRear->getNextNode();
-  }
-
-  // get the rear fragment in the range.
-  inline Fragment* getRear(Range& pRange) const
-  {
-    if (!pRange.header->hasSectionData())
-      return NULL;
-    if (pRange.header->getSectionData()->getFragmentList().empty())
-      return NULL;
-
-    if (isLastRange(pRange)) {
-      if (isEmptyRange(pRange))
-        return NULL;
-      return &pRange.header->getSectionData()->getFragmentList().back();
-    }
-    return pRange.getNextNode()->prevRear;
-  }
-
-  inline const Fragment* getRear(const Range& pRange) const
-  {
-    if (!pRange.header->hasSectionData())
-      return NULL;
-    if (pRange.header->getSectionData()->getFragmentList().empty())
-      return NULL;
-
-    if (isLastRange(pRange)) {
-      if (isEmptyRange(pRange))
-        return NULL;
-      return &pRange.header->getSectionData()->getFragmentList().back();
-    }
-    return pRange.getNextNode()->prevRear;
-  }
-
-  FragmentRef* getFragmentRef(Range &pRange, uint64_t pOffset);
-
-  FragmentRef*
-  getFragmentRef(Fragment& pFront, Fragment& pRear, uint64_t pOffset);
-
-  bool hasLayoutOrder(const Fragment& pFragment) const
-  { return (pFragment.getLayoutOrder() != ~(0U)); }
-
-  bool hasLayoutOffset(const Fragment& pFragment) const
-  { return (pFragment.getOffset() != ~UINT64_C(0)); }
-
-  bool isValidOffset(const Fragment& pFrag, uint64_t pTargetOffset) const;
-
-  void setFragmentLayoutOrder(Fragment* pFragment);
-
-  void setFragmentLayoutOffset(Fragment* pFragment);
-
   /// sortSectionOrder - perform sorting on m_SectionOrder to get final layout
   /// ordering
-  void sortSectionOrder(const Output& pOutput,
-                        const TargetLDBackend& pBackend,
-                        const MCLDInfo& pInfo);
+  void sortSectionOrder(const TargetLDBackend& pBackend,
+                        const LinkerConfig& pConfig);
+
+private:
+  typedef std::vector<LDSection*> SectionOrder;
 
 private:
   /// a vector to describe the order of sections
   SectionOrder m_SectionOrder;
-
-  /// the map from SectionData* to its own RangeList.
-  SDRangeMap m_SDRangeMap;
-
-  FragRefFactory m_FragRefFactory;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/MsgHandler.h b/include/mcld/LD/MsgHandler.h
index d10f8a2..c89f744 100644
--- a/include/mcld/LD/MsgHandler.h
+++ b/include/mcld/LD/MsgHandler.h
@@ -17,8 +17,7 @@
 #include <mcld/Support/Path.h>
 #include <mcld/LD/DiagnosticEngine.h>
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class MsgHandler
  *  \brief MsgHandler controls the timing to output message.
@@ -110,18 +109,6 @@
   return pHandler;
 }
 
-//===----------------------------------------------------------------------===//
-// Inline member functions
-inline MsgHandler
-DiagnosticEngine::report(uint16_t pID, DiagnosticEngine::Severity pSeverity)
-{
-  m_State.ID = pID;
-  m_State.severity = pSeverity;
-
-  MsgHandler result(*this);
-  return result;
-}
-
 } // namespace of mcld
 
 #endif
diff --git a/include/mcld/LD/NamePool.h b/include/mcld/LD/NamePool.h
index 1c0f8b3..12b4b91 100644
--- a/include/mcld/LD/NamePool.h
+++ b/include/mcld/LD/NamePool.h
@@ -19,14 +19,11 @@
 #include <mcld/ADT/HashTable.h>
 #include <mcld/ADT/StringHash.h>
 #include <mcld/ADT/Uncopyable.h>
-#include <mcld/LD/ResolveInfo.h>
 #include <mcld/LD/Resolver.h>
-#include <mcld/LD/ResolveInfoFactory.h>
+#include <mcld/LD/ResolveInfo.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class Resolver;
 class StringTable;
 class SymbolTableIF;
 class SectionData;
@@ -39,15 +36,17 @@
 class NamePool : private Uncopyable
 {
 public:
-  typedef HashTable<ResolveInfo, StringHash<ELF>, ResolveInfoFactory> Table;
+  typedef HashTable<ResolveInfo, StringHash<ELF> > Table;
   typedef size_t size_type;
 
 public:
-  NamePool(const Resolver& pResolver, size_type pSize = 3);
+  explicit NamePool(size_type pSize = 3);
+
   ~NamePool();
 
   // -----  modifiers  ----- //
   /// createSymbol - create a symbol but do not insert into the pool.
+  /// The created symbol did not go through the path of symbol resolution.
   ResolveInfo* createSymbol(const llvm::StringRef& pName,
                             bool pIsDyn,
                             ResolveInfo::Type pType,
@@ -73,12 +72,12 @@
                     Resolver::Result& pResult);
 
   /// findSymbol - find the resolved output LDSymbol
-  LDSymbol* findSymbol(const llvm::StringRef& pName);
   const LDSymbol* findSymbol(const llvm::StringRef& pName) const;
+  LDSymbol*       findSymbol(const llvm::StringRef& pName);
 
   /// findInfo - find the resolved ResolveInfo
-  ResolveInfo* findInfo(const llvm::StringRef& pName);
   const ResolveInfo* findInfo(const llvm::StringRef& pName) const;
+  ResolveInfo*       findInfo(const llvm::StringRef& pName);
 
   /// insertString - insert a string
   /// if the string has existed, modify pString to the existing string
@@ -98,7 +97,7 @@
   size_type capacity() const;
 
 private:
-  const Resolver* m_pResolver;
+  Resolver* m_pResolver;
   Table m_Table;
 
 };
diff --git a/include/mcld/LD/ObjectReader.h b/include/mcld/LD/ObjectReader.h
index 9dbe9ac..b1355e4 100644
--- a/include/mcld/LD/ObjectReader.h
+++ b/include/mcld/LD/ObjectReader.h
@@ -16,11 +16,10 @@
 #include <mcld/ADT/HashTable.h>
 #include <mcld/ADT/StringHash.h>
 #include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/ResolveInfoFactory.h>
 
-namespace mcld
-{
+namespace mcld {
 
+class Module;
 class Input;
 
 /** \class ObjectReader
@@ -30,18 +29,16 @@
 class ObjectReader : public LDReader
 {
 protected:
-  typedef HashTable<ResolveInfo,
-                    StringHash<ELF>,
-                    ResolveInfoFactory> GroupSignatureMap;
+  typedef HashTable<ResolveInfo, StringHash<ELF> > GroupSignatureMap;
 
 protected:
   ObjectReader()
   { }
 
 public:
-  virtual ~ObjectReader() { }
+  virtual ~ObjectReader() { f_GroupSignatureMap.clear(); }
 
-  virtual bool readObject(Input& pFile) = 0;
+  virtual bool readHeader(Input& pFile) = 0;
 
   virtual bool readSymbols(Input& pFile) = 0;
 
diff --git a/include/mcld/LD/ObjectWriter.h b/include/mcld/LD/ObjectWriter.h
index 0c48723..a84e0d3 100644
--- a/include/mcld/LD/ObjectWriter.h
+++ b/include/mcld/LD/ObjectWriter.h
@@ -13,10 +13,10 @@
 #endif
 #include <llvm/Support/system_error.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class Output;
+class Module;
+class MemoryArea;
 class GNULDBackend;
 
 /** \class ObjectWriter
@@ -30,7 +30,7 @@
 public:
   virtual ~ObjectWriter();
 
-  virtual llvm::error_code writeObject(Output& pOutput) = 0;
+  virtual llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput) = 0;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/RelocData.h b/include/mcld/LD/RelocData.h
new file mode 100644
index 0000000..6061544
--- /dev/null
+++ b/include/mcld/LD/RelocData.h
@@ -0,0 +1,96 @@
+//===- RelocData.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_RELOCATION_DATA_H
+#define MCLD_RELOCATION_DATA_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/ADT/ilist.h>
+#include <llvm/ADT/ilist_node.h>
+#include <llvm/Support/DataTypes.h>
+
+#include <mcld/Config/Config.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Support/GCFactoryListTraits.h>
+
+
+namespace mcld {
+
+class LDSection;
+
+/** \class RelocData
+ *  \brief RelocData is the special SectionData to store Relocation fragments.
+ *  Since Relocations are created by GCFactory, we use GCFactoryListTraits for the
+ *  FragmentList here to avoid iplist to delete Relocations.
+ */
+class RelocData
+{
+private:
+  RelocData();
+  explicit RelocData(const LDSection &pSection);
+
+  RelocData(const RelocData &);            // DO NOT IMPLEMENT
+  RelocData& operator=(const RelocData &); // DO NOT IMPLEMENT
+
+public:
+  typedef llvm::iplist<Fragment,
+                       GCFactoryListTraits<Fragment> > FragmentListType;
+
+  typedef FragmentListType::reference reference;
+  typedef FragmentListType::const_reference const_reference;
+
+  typedef FragmentListType::iterator iterator;
+  typedef FragmentListType::const_iterator const_iterator;
+
+  typedef FragmentListType::reverse_iterator reverse_iterator;
+  typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
+
+public:
+  static RelocData* Create(const LDSection& pSection);
+
+  static RelocData* Create();
+
+  static void Destroy(RelocData*& pSection);
+
+  const LDSection &getSection() const
+  { assert(NULL != m_pSection ); return *m_pSection; }
+
+  FragmentListType &getFragmentList() { return m_Fragments; }
+  const FragmentListType &getFragmentList() const { return m_Fragments; }
+
+  size_t size() const { return m_Fragments.size(); }
+
+  bool empty() const { return m_Fragments.empty(); }
+
+  reference              front ()       { return m_Fragments.front();  }
+  const_reference        front () const { return m_Fragments.front();  }
+  reference              back  ()       { return m_Fragments.back();   }
+  const_reference        back  () const { return m_Fragments.back();   }
+
+  const_iterator         begin () const { return m_Fragments.begin();  }
+  iterator               begin ()       { return m_Fragments.begin();  }
+  const_iterator         end   () const { return m_Fragments.end();    }
+  iterator               end   ()       { return m_Fragments.end();    }
+  const_reverse_iterator rbegin() const { return m_Fragments.rbegin(); }
+  reverse_iterator       rbegin()       { return m_Fragments.rbegin(); }
+  const_reverse_iterator rend  () const { return m_Fragments.rend();   }
+  reverse_iterator       rend  ()       { return m_Fragments.rend();   }
+
+private:
+  FragmentListType m_Fragments;
+  const LDSection* m_pSection;
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/RelocationFactory.h b/include/mcld/LD/RelocationFactory.h
index cde120f..c9f0d64 100644
--- a/include/mcld/LD/RelocationFactory.h
+++ b/include/mcld/LD/RelocationFactory.h
@@ -12,18 +12,18 @@
 #include <gtest.h>
 #endif
 #include <mcld/Support/GCFactory.h>
-#include <mcld/LD/Relocation.h>
+#include <mcld/Fragment/Relocation.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class LDSymbol;
 class ResolveInfo;
 class FragmentRef;
+class FragmentLinker;
 class Layout;
 class GOT;
 class TargetLDBackend;
-class MCLDInfo;
+class LinkerConfig;
 
 /** \class RelocationFactory
  *  \brief RelocationFactory provides the interface for generating target
@@ -36,6 +36,7 @@
   typedef Relocation::Type Type;
   typedef Relocation::Address Address;
   typedef Relocation::DWord DWord;
+  typedef Relocation::SWord SWord;
 
   enum Result {
     OK,
@@ -51,8 +52,7 @@
   virtual ~RelocationFactory();
 
   /// apply - general apply function
-  virtual Result applyRelocation(Relocation& pRelocation,
-                                 const MCLDInfo& pLDInfo) = 0;
+  virtual Result applyRelocation(Relocation& pRelocation) = 0;
 
   // ----- production ----- //
   /// produce - produce a relocation entry
@@ -69,10 +69,12 @@
 
   void destroy(Relocation* pRelocation);
 
-  void setLayout(const Layout& pLayout);
+  void setFragmentLinker(const FragmentLinker& pLinker);
 
   // ------ observers -----//
-  const Layout& getLayout() const;
+  const FragmentLinker& getFragmentLinker() const;
+
+  bool hasFragmentLinker() const;
 
   virtual TargetLDBackend& getTarget() = 0;
 
@@ -81,7 +83,7 @@
   virtual const char* getName(Type pType) const = 0;
 
 private:
-  const Layout* m_pLayout;
+  const FragmentLinker* m_pLinker;
 
 };
 
diff --git a/include/mcld/LD/ResolveInfo.h b/include/mcld/LD/ResolveInfo.h
index 7b3cb27..2cff57e 100644
--- a/include/mcld/LD/ResolveInfo.h
+++ b/include/mcld/LD/ResolveInfo.h
@@ -15,8 +15,7 @@
 #include <llvm/Support/DataTypes.h>
 #include <llvm/ADT/StringRef.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class LDSymbol;
 
@@ -30,15 +29,14 @@
  *  - Type - what the symbol points to
  *  - Size  - the size of the symbol point to
  *  - Value - the pointer to another LDSymbol
- *  In order to save the memory and speed up the performance, MCLinker uses
+ *  In order to save the memory and speed up the performance, FragmentLinker uses
  *  a bit field to store all attributes.
  *
  *  The maximum string length is (2^16 - 1)
  */
 class ResolveInfo
 {
-friend class ResolveInfoFactory;
-friend class MCLinker;
+friend class FragmentLinker;
 public:
   typedef uint64_t SizeType;
 
@@ -94,6 +92,13 @@
   typedef llvm::StringRef key_type;
 
 public:
+  // -----  factory method  ----- //
+  static ResolveInfo* Create(const key_type& pKey);
+
+  static void Destroy(ResolveInfo*& pInfo);
+
+  static ResolveInfo* Null();
+
   // -----  modifiers  ----- //
   /// setRegular - set the source of the file is a regular object
   void setRegular();
@@ -138,6 +143,8 @@
 
 
   // -----  observers  ----- //
+  bool isNull() const;
+
   bool isSymbol() const;
 
   bool isString() const;
@@ -271,7 +278,7 @@
    * |length of m_Name|reserved|Symbol|Type |ELF visibility|Local|Com|Def|Dyn|Weak|
    */
   uint32_t m_BitField;
-  char m_Name[0];
+  char m_Name[];
 };
 
 } // namespace of mcld
diff --git a/include/mcld/LD/ResolveInfoFactory.h b/include/mcld/LD/ResolveInfoFactory.h
deleted file mode 100644
index fcadf48..0000000
--- a/include/mcld/LD/ResolveInfoFactory.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- ResolveInfoFactory.h -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_RESOLVE_INFO_FACTORY_H
-#define MCLD_RESOLVE_INFO_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include "mcld/LD/ResolveInfo.h"
-
-namespace mcld
-{
-
-/** \class ResolveInfoFactory
- *  \brief ResolveInfoFactory creates ResolveInfos.
- */
-class ResolveInfoFactory
-{
-public:
-  typedef ResolveInfo           entry_type;
-  typedef ResolveInfo::key_type key_type;
-
-public:
-  entry_type* produce(const key_type& pKey);
-  void destroy(entry_type* pEntry);
-
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/SectionData.h b/include/mcld/LD/SectionData.h
index 8666195..316d92f 100644
--- a/include/mcld/LD/SectionData.h
+++ b/include/mcld/LD/SectionData.h
@@ -16,10 +16,11 @@
 #include <llvm/ADT/ilist_node.h>
 #include <llvm/Support/DataTypes.h>
 
-#include <mcld/LD/Fragment.h>
+#include <mcld/Config/Config.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Fragment/Fragment.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class LDSection;
 
@@ -29,11 +30,20 @@
 class SectionData
 {
 private:
+  friend class Chunk<SectionData, MCLD_SECTIONS_PER_INPUT>;
+
+  SectionData();
+  explicit SectionData(LDSection &pSection);
+
   SectionData(const SectionData &);            // DO NOT IMPLEMENT
   SectionData& operator=(const SectionData &); // DO NOT IMPLEMENT
 
 public:
   typedef llvm::iplist<Fragment> FragmentListType;
+
+  typedef FragmentListType::reference reference;
+  typedef FragmentListType::const_reference const_reference;
+
   typedef FragmentListType::iterator iterator;
   typedef FragmentListType::const_iterator const_iterator;
 
@@ -41,36 +51,37 @@
   typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
 
 public:
-  explicit SectionData(const LDSection &pSection);
+  static SectionData* Create(LDSection& pSection);
 
-  const LDSection &getSection() const { return *m_pSection; }
+  static void Destroy(SectionData*& pSection);
 
-  unsigned int getAlignment() const { return m_Alignment; }
-  void setAlignment(unsigned int pValue) { m_Alignment = pValue; }
+  const LDSection& getSection() const { return *m_pSection; }
+  LDSection&       getSection()       { return *m_pSection; }
 
   FragmentListType &getFragmentList() { return m_Fragments; }
   const FragmentListType &getFragmentList() const { return m_Fragments; }
 
-  iterator begin() { return m_Fragments.begin(); }
-  const_iterator begin() const { return m_Fragments.begin(); }
-
-  iterator end() { return m_Fragments.end(); }
-  const_iterator end() const { return m_Fragments.end(); }
-
-  reverse_iterator rbegin() { return m_Fragments.rbegin(); }
-  const_reverse_iterator rbegin() const { return m_Fragments.rbegin(); }
-
-  reverse_iterator rend() { return m_Fragments.rend(); }
-  const_reverse_iterator rend() const { return m_Fragments.rend(); }
-
   size_t size() const { return m_Fragments.size(); }
 
   bool empty() const { return m_Fragments.empty(); }
 
+  reference              front ()       { return m_Fragments.front();  }
+  const_reference        front () const { return m_Fragments.front();  }
+  reference              back  ()       { return m_Fragments.back();   }
+  const_reference        back  () const { return m_Fragments.back();   }
+
+  const_iterator         begin () const { return m_Fragments.begin();  }
+  iterator               begin ()       { return m_Fragments.begin();  }
+  const_iterator         end   () const { return m_Fragments.end();    }
+  iterator               end   ()       { return m_Fragments.end();    }
+  const_reverse_iterator rbegin() const { return m_Fragments.rbegin(); }
+  reverse_iterator       rbegin()       { return m_Fragments.rbegin(); }
+  const_reverse_iterator rend  () const { return m_Fragments.rend();   }
+  reverse_iterator       rend  ()       { return m_Fragments.rend();   }
+
 private:
   FragmentListType m_Fragments;
-  const LDSection* m_pSection;
-  unsigned int m_Alignment;
+  LDSection* m_pSection;
 
 };
 
diff --git a/include/mcld/LD/SectionMap.h b/include/mcld/LD/SectionMap.h
deleted file mode 100644
index 06ae02e..0000000
--- a/include/mcld/LD/SectionMap.h
+++ /dev/null
@@ -1,103 +0,0 @@
-//===- SectionMap.h -------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTION_MAP_H
-#define MCLD_SECTION_MAP_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/Support/DataTypes.h>
-#include <vector>
-#include <string>
-
-namespace mcld
-{
-
-/** \class SectionMap
- *  \brief descirbe the mappings of input section's name (or prefix) to
- *         its associated output section's name and offset
- */
-class SectionMap
-{
-public:
-  // a mapping in SectionMap is the triple of
-  // {input substr, output section's name, output section's offset}
-  struct Mapping {
-    std::string inputSubStr;
-    std::string outputStr;
-  };
-
-  typedef std::vector<struct Mapping> SectionMappingTy;
-
-  typedef SectionMappingTy::iterator iterator;
-  typedef SectionMappingTy::const_iterator const_iterator;
-
-public:
-  SectionMap();
-  ~SectionMap();
-
-  // get the possible output section name based on the mapping table
-  // return NULL if not found
-  const std::string& getOutputSectName(const std::string& pInput);
-
-  // add a mapping from input substr to output name and offset.
-  bool push_back(const std::string& pInput,
-                 const std::string& pOutput);
-
-  // find - return the iterator to the mapping
-  iterator find(const std::string& pInput);
-
-  // at - return the pointer to the mapping
-  Mapping* at(const std::string& pInput);
-
-  // -----  observers  ----- //
-  bool empty() const
-  { return m_SectMap.empty(); }
-
-  size_t size() const
-  { return m_SectMap.size(); }
-
-  size_t capacity () const
-  { return m_SectMap.capacity(); }
-
-  // -----  iterators  ----- //
-  iterator begin()
-  { return m_SectMap.begin(); }
-
-  iterator end()
-  { return m_SectMap.end(); }
-
-  const_iterator begin() const
-  { return m_SectMap.begin(); }
-
-  const_iterator end() const
-  { return m_SectMap.end(); }
-
-  // initStdSectionMap - add common mappings of ELF and other formats
-  // to SectionMap
-  bool initStdSectionMap();
-
-private:
-  struct SectionNameMapping {
-    const char* from;
-    const char* to;
-  };
-
-  // used to store common mappings of ELF and other formants
-  static const SectionNameMapping m_StdSectionMap[];
-
-  static const int m_StdSectionMapSize;
-
-  SectionMappingTy m_SectMap;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/SectionMerger.h b/include/mcld/LD/SectionMerger.h
deleted file mode 100644
index a9ca0c6..0000000
--- a/include/mcld/LD/SectionMerger.h
+++ /dev/null
@@ -1,98 +0,0 @@
-//===- SectionMerger.h ----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTION_MERGER_H
-#define MCLD_SECTION_MERGER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <vector>
-#include <string>
-
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/SectionMap.h>
-
-namespace mcld
-{
-class MCLinker;
-
-/** \class SectionMerger
- *  \brief maintain the mappings of substr of input section name to associated
- *         output section (data)
- */
-class SectionMerger
-{
-public:
-  struct Mapping {
-    std::string inputSubStr;
-    LDSection* outputSection;
-  };
-  typedef std::vector<Mapping> LDSectionMapTy;
-
-  typedef LDSectionMapTy::iterator iterator;
-  typedef LDSectionMapTy::const_iterator const_iterator;
-
-public:
-  SectionMerger(SectionMap& pSectionMap, LDContext& pContext);
-  ~SectionMerger();
-
-  /// getOutputSectHdr - return a associated output section header
-  LDSection* getOutputSectHdr(const std::string& pName);
-
-  /// getOutputSectData - return a associated output section data
-  SectionData* getOutputSectData(const std::string& pName);
-
-  /// addMapping - add a mapping as creating one new output LDSection
-  /// @param pName - a input section name
-  /// @param pSection - the output LDSection*
-  bool addMapping(const std::string& pName, LDSection* pSection);
-
-  // -----  observers  ----- //
-  bool empty() const
-  { return m_LDSectionMap.empty(); }
-
-  size_t size() const
-  { return m_LDSectionMap.size(); }
-
-  size_t capacity () const
-  { return m_LDSectionMap.capacity(); }
-
-  // -----  iterators  ----- //
-  iterator find(const std::string& pName);
-
-  iterator begin()
-  { return m_LDSectionMap.begin(); }
-
-  iterator end()
-  { return m_LDSectionMap.end(); }
-
-  const_iterator begin() const
-  { return m_LDSectionMap.begin(); }
-
-  const_iterator end() const
-  { return m_LDSectionMap.end(); }
-
-private:
-  /// initOutputSectMap - initialize the map from input substr to associated
-  /// output LDSection*
-  void initOutputSectMap();
-
-private:
-  SectionMap& m_SectionNameMap;
-
-  LDContext& m_Output;
-
-  LDSectionMapTy m_LDSectionMap;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/SectionRules.h b/include/mcld/LD/SectionRules.h
new file mode 100644
index 0000000..bddac20
--- /dev/null
+++ b/include/mcld/LD/SectionRules.h
@@ -0,0 +1,84 @@
+//===- SectionRules.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SECTION_MERGER_H
+#define MCLD_SECTION_MERGER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+#include <string>
+
+#include <mcld/LD/LDSection.h>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+class SectionMap;
+class FragmentLinker;
+
+/** \class SectionRules
+ *  \brief maintain the mappings of substr of input section name to associated
+ *         output section (data)
+ */
+class SectionRules
+{
+public:
+  SectionRules(const LinkerConfig& pConfig, Module& pModule);
+  ~SectionRules();
+
+  /// getMatchedSection - return the matched section by rules.
+  /// @return if we can not find the matched section, return NULL.
+  LDSection* getMatchedSection(const std::string& pName) const;
+
+  /// append - append a new mapping rule.
+  /// appendRule does not check if the appended rule is duplicated.
+  /// @param pName - the matched substring
+  /// @parap pSection - the output section
+  void append(const std::string& pName, LDSection& pSection);
+
+  size_t size () const { return m_RuleList.size(); }
+  bool   empty() const { return m_RuleList.empty(); }
+
+  /// initOutputSectMap - initialize the map from input substr to associated
+  /// output LDSection*
+  void initOutputSectMap();
+
+private:
+  struct Rule {
+  public:
+    Rule(const std::string& pSubStr, LDSection* pTarget);
+
+  public:
+    uint32_t hash;
+    std::string substr;
+    LDSection* target;
+  };
+
+  typedef std::vector<Rule> RuleList;
+
+  typedef RuleList::iterator iterator;
+  typedef RuleList::const_iterator const_iterator;
+
+private:
+  // -----  iterators  ----- //
+  const_iterator find(const std::string& pName) const;
+  iterator       find(const std::string& pName);
+
+private:
+  const SectionMap& m_SectionNameMap;
+  Module& m_Module;
+  RuleList m_RuleList;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/SectionSymbolSet.h b/include/mcld/LD/SectionSymbolSet.h
new file mode 100644
index 0000000..3ec590f
--- /dev/null
+++ b/include/mcld/LD/SectionSymbolSet.h
@@ -0,0 +1,81 @@
+//===- SectionSymbolSet.h -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SECTIONSYMBOLSET_H
+#define MCLD_SECTIONSYMBOLSET_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/ADT/HashTable.h>
+#include <mcld/ADT/HashEntry.h>
+#include <mcld/MC/SymbolCategory.h>
+
+namespace mcld
+{
+
+class LDSection;
+class NamePool;
+class LDSymbol;
+
+/** \class SectionSymbolSet
+ *  \brief SectionSymbolSet contains the section symbols defined by linker for
+ *   the output sections
+ */
+class SectionSymbolSet
+{
+public:
+  typedef SymbolCategory SymbolTable;
+
+public:
+  SectionSymbolSet();
+  ~SectionSymbolSet();
+
+  /// add - create and add an section symbol for the output
+  /// LDSection
+  bool add(LDSection& pOutSect, NamePool& pNamePool);
+
+  /// finalize - set section symbols' fragmentRef and push it into the output
+  /// symbol table
+  bool finalize(LDSection& pOutSect, SymbolTable& pSymTab);
+
+  /// get - get the section symbol for section pOutpSect
+  LDSymbol* get(const LDSection& pOutSect);
+  const LDSymbol* get(const LDSection& pOutSect) const;
+
+private:
+  /// sectCompare - hash compare function for LDSection*
+  struct SectCompare
+  {
+    bool operator()(const LDSection* X, const LDSection* Y) const
+    { return (X==Y); }
+  };
+
+  /// SectPtrHash - hash function for LDSection*
+  struct SectPtrHash
+  {
+    size_t operator()(const LDSection* pKey) const
+    {
+      return (unsigned((uintptr_t)pKey) >> 4) ^
+             (unsigned((uintptr_t)pKey) >> 9);
+    }
+  };
+
+  typedef HashEntry<const LDSection*, LDSymbol*, SectCompare> SectHashEntryType;
+  typedef HashTable<SectHashEntryType,
+                    SectPtrHash,
+                    EntryFactory<SectHashEntryType> > SectHashTableType;
+
+private:
+  SectHashTableType* m_pSectionSymbolMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/StringUnorderedMap.h b/include/mcld/LD/StringUnorderedMap.h
deleted file mode 100644
index 05788aa..0000000
--- a/include/mcld/LD/StringUnorderedMap.h
+++ /dev/null
@@ -1,225 +0,0 @@
-//===- StringUnorderedMap.h -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SEARCH_TABLE_H
-#define MCLD_SEARCH_TABLE_H
-#include <vector>
-// For std::allocate.
-#include <memory>
-// For uint32_t.
-#include <stdint.h>
-#include <cassert>
-// For memset.
-#include <cstring>
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-/* FIXME: Move StringUnorderedMap under ADT. */
-
-namespace mcld
-{
-
-struct StringUnorderedMapDefaultHash
-{
-  size_t operator()(const char *pStr) {
-    size_t hashVal = 31;
-    while (*pStr)
-      hashVal = hashVal * 131 + (*pStr++);
-    return hashVal;
-  }
-};
-
-template<typename ValueType,
-         typename KeyType>
-struct StringUnorderedMapEntryInit
-{
-  template <typename InitType>
-  void operator()(KeyType &pKey, ValueType &pValue,
-                  const KeyType &pStr, InitType pInitVal) {
-    ::new ((void*)&pKey) KeyStorageType(pStr);
-    ::new ((void*)&pValue) ValueType(pInitVal);
-  }
-};
-
-uint32_t findNextPrime(uint32_t x);
-
-/** \class StringUnorderedMap
- *  \brief The most simple hash of linked list version.
- *
- *  \see
- */
-template<typename KeyType,
-         typename ValueType,
-         typename KeyCompareFunctor,
-         typename HashFunction = StringUnorderedMapDefaultHash,
-         typename Allocator = std::allocator<std::pair<KeyType, ValueType> > >
-class StringUnorderedMap
-{
-public:
-  explicit StringUnorderedMap(size_t pCapacity = 17)
-  : m_Impl(pCapacity)
-  {}
-
-  ~StringUnorderedMap();
-
-  void reserve(size_t pCapacity);
-
-  ValueType &getOrCreate(const KeyType &pStr, const ValueType &pInitVal);
-
-  ValueType &getOrCreate(const KeyType &pStr);
-
-  bool empty()
-  { return m_Size == 0; }
-
-  size_t capacity() const
-  { return m_Capacity; }
-
-  void clear();
-
-private:
-  struct HashEntry {
-    size_t hashVal;
-    std::pair<KeyType, ValueType>
-    HashEntry *next;
-  };
-  typedef Allocator::template rebind<HashEntry>::other HashEntryAllocator;
-  void rehash(size_t pCapacity);
-
-private:
-  size_t m_Capacity;
-  size_t m_Size;
-  // array of pointers to hash entries
-  HashEntry **m_HashTable;
-  HashEntryAllocator m_HashEntryAllocator;
-};
-
-
-// =================================implementation============================
-// StringUnorderedMap::StringUnorderedMapImpl
-template<typename ValueType,
-         typename KeyStorageType,
-         typename HashFunction,
-         typename Allocator>
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::StringUnorderedMapImpl(size_t pCapacity)
-  : m_Capacity(0), m_Size(0), m_HashTable(0)
-{
-  this->reserve(pCapacity);
-}
-
-template<typename ValueType,
-         typename KeyStorageType,
-         typename HashFunction,
-         typename Allocator>
-void
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::reserve(size_t pCapacity)
-{
-  if (pCapacity < this->m_Capacity)
-    return;
-  size_t nextSize = findNextPrime(static_cast<uint32_t>(pCapacity));
-  // FIXME: Error handling.
-  assert(nextSize > this->m_Capacity && "findNextPrime error.");
-  if (this->m_Capacity != nextSize)
-    this->rehash(nextSize);
-}
-
-template<typename ValueType,
-         typename KeyStorageType,
-         typename HashFunction,
-         typename Allocator>
-void
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::rehash(size_t pCapacity)
-{
-  HashEntry **tmpTable = new HashEntry*[pCapacity];
-  std::memset(tmpTable, 0, pCapacity * sizeof(HashEntry*));
-  if (this->m_HashTable) {
-    for (size_t i = 0; i < this->m_Capacity; ++i)
-      for (HashEntry *j = this->m_HashTable[i]; j != 0; ) {
-        HashEntry *nextJ = j->next;
-        j->next = tmpTable[j->hashVal % pCapacity];
-        tmpTable[j->hashVal % pCapacity] = j;
-        j = nextJ;
-      }
-    delete[] m_HashTable;
-  }
-  this->m_Capacity = pCapacity;
-  this->m_HashTable = tmpTable;
-}
-
-template<typename ValueType,
-         typename KeyStorageType,
-         typename HashFunction,
-         typename Allocator>
-template<typename InitType>
-ValueType &
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::getOrCreate(const KeyType &pStr, ValueType &pInitVal)
-{
-  HashFunction hash;
-  size_t hashVal = hash(pStr);
-  HashEntry *&head =  this->m_HashTable[hashVal % this->m_Capacity];
-
-  HashEntry *ans = 0;
-  for(HashEntry *ptr = head; ptr != 0; ptr = ptr->next)
-    if(hashVal == ptr->hashVal && pStr.equals(ptr->str)) {
-      ans = ptr;
-      break;
-    }
-  if (ans == 0) {
-    ans = this->allocate(1);
-    ans->hashVal = hashVal;
-    StringUnorderedMapEntryInit<ValueType, KeyStorageType> init;
-    init(ans->str, ans->value, pStr, pInitVal);
-    ans->next = head;
-    head = ans;
-    ++m_Size;
-    if(this->m_Size * 4LL >= this->m_Capacity * 3LL) // load factor = 0.75
-      this->reserve(this->m_Capacity+1);
-  }
-
-  return ans->value;
-}
-
-template<typename ValueType,
-         typename KeyStorageType,
-         typename HashFunction,
-         typename Allocator>
-void
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::clear()
-{
-  if (this->m_HashTable) {
-    for (size_t i = 0; i < this->m_Capacity; ++i)
-      for (HashEntry *j = this->m_HashTable[i]; j != 0; ) {
-        HashEntry *nextJ = j->next;
-        this->destroy(j);
-        this->deallocate(j, 1);
-        j = nextJ;
-      }
-    delete[] m_HashTable;
-  }
-}
-
-
-template<typename ValueType,
-         typename KeyStorageType,
-         typename HashFunction,
-         typename Allocator>
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::~StringUnorderedMapImpl()
-{
-  this->clear();
-}
-
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/StubFactory.h b/include/mcld/LD/StubFactory.h
new file mode 100644
index 0000000..00a65ec
--- /dev/null
+++ b/include/mcld/LD/StubFactory.h
@@ -0,0 +1,65 @@
+//===- StubFactory.h ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_LD_STUB_FACTORY_H
+#define MCLD_LD_STUB_FACTORY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <vector>
+
+namespace mcld
+{
+
+class Stub;
+class Relocation;
+class RelocationFactory;
+class BranchIslandFactory;
+class FragmentLinker;
+
+/** \class StubFactory
+ *  \brief the clone factory of Stub
+ *
+ */
+class StubFactory
+{
+public:
+  StubFactory();
+
+  ~StubFactory();
+
+  /// addPrototype - register a stub prototype
+  void addPrototype(Stub* pPrototype);
+
+  /// create - create a stub if needed, otherwise return NULL
+  Stub* create(Relocation& pReloc,
+               uint64_t pTargetSymValue,
+               FragmentLinker& pLinker,
+               RelocationFactory& pRelocFactory,
+               BranchIslandFactory& pBRIslandFactory);
+
+private:
+  /// findPrototype - find if there is a registered stub prototype for the given
+  ///                 relocation
+  Stub* findPrototype(const Relocation& pReloc,
+                      const uint64_t pSource,
+                      uint64_t pTargetSymValue);
+
+private:
+ typedef std::vector<Stub*> StubPoolType;
+
+private:
+  StubPoolType m_StubPool; // stub pool
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/LD/TextDiagnosticPrinter.h b/include/mcld/LD/TextDiagnosticPrinter.h
index 278c00f..3e7d4c4 100644
--- a/include/mcld/LD/TextDiagnosticPrinter.h
+++ b/include/mcld/LD/TextDiagnosticPrinter.h
@@ -17,7 +17,7 @@
 namespace mcld
 {
 
-class MCLDInfo;
+class LinkerConfig;
 
 /** \class TextDiagnosticPrinter
  *  \brief The plain, text-based DiagnosticPrinter.
@@ -25,7 +25,7 @@
 class TextDiagnosticPrinter : public DiagnosticPrinter
 {
 public:
-  TextDiagnosticPrinter(llvm::raw_ostream& pOStream, const MCLDInfo& pLDInfo);
+  TextDiagnosticPrinter(llvm::raw_ostream& pOStream, const LinkerConfig& pConfig);
 
   virtual ~TextDiagnosticPrinter();
 
@@ -34,13 +34,13 @@
   virtual void handleDiagnostic(DiagnosticEngine::Severity pSeverity,
                                 const Diagnostic& pInfo);
 
-  virtual void beginInput(const Input& pInput, const MCLDInfo& pLDInfo);
+  virtual void beginInput(const Input& pInput, const LinkerConfig& pConfig);
 
   virtual void endInput();
 
 private:
   llvm::raw_ostream& m_OStream;
-  const MCLDInfo& m_LDInfo;
+  const LinkerConfig& m_Config;
   const Input* m_pInput;
 };
 
diff --git a/include/mcld/Linker.h b/include/mcld/Linker.h
new file mode 100644
index 0000000..891372c
--- /dev/null
+++ b/include/mcld/Linker.h
@@ -0,0 +1,75 @@
+//===- Linker.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LINKER_H
+#define MCLD_LINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+
+class Target;
+class TargetLDBackend;
+
+class IRBuilder;
+class ObjectLinker;
+
+class FileHandle;
+class MemoryArea;
+
+/** \class Linker
+*  \brief Linker is a modular linker.
+*/
+class Linker
+{
+public:
+  Linker();
+
+  ~Linker();
+
+  bool config(LinkerConfig& pConfig);
+
+  bool link(Module& pModule, IRBuilder& pBuilder);
+
+  bool emit(MemoryArea& pOutput);
+
+  bool emit(const std::string& pPath);
+
+  bool emit(int pFileDescriptor);
+
+  bool reset();
+
+private:
+  bool initTarget();
+
+  bool initBackend();
+
+  bool initEmulator();
+
+  bool initOStream();
+
+private:
+  LinkerConfig* m_pConfig;
+  Module* m_pModule;
+  IRBuilder* m_pIRBuilder;
+
+  const Target* m_pTarget;
+  TargetLDBackend* m_pBackend;
+  ObjectLinker* m_pObjLinker;
+};
+
+} // namespace of MC Linker
+
+#endif
+
diff --git a/include/mcld/LinkerConfig.h b/include/mcld/LinkerConfig.h
new file mode 100644
index 0000000..7d52819
--- /dev/null
+++ b/include/mcld/LinkerConfig.h
@@ -0,0 +1,90 @@
+//===- LinkerConfig.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LINKER_CONFIG_H
+#define MCLD_LINKER_CONFIG_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/ADT/Triple.h>
+
+#include <mcld/GeneralOptions.h>
+#include <mcld/ScriptOptions.h>
+#include <mcld/BitcodeOption.h>
+#include <mcld/AttributeOption.h>
+#include <mcld/Support/Path.h>
+
+#include <string>
+
+namespace mcld {
+
+/** \class LinkerConfig
+ *  \brief LinkerConfig is composed of argumments of MCLinker.
+ *   options()        - the general options
+ *   scripts()        - the script options
+ *   bitcode()        - the bitcode being linked
+ *   attribute()      - the attribute options
+ */
+class LinkerConfig
+{
+public:
+  enum CodeGenType {
+    Unknown,
+    Object,
+    DynObj,
+    Exec,
+    External
+  };
+
+public:
+  LinkerConfig();
+
+  explicit LinkerConfig(const std::string &pTripleString);
+
+  ~LinkerConfig();
+
+  const GeneralOptions& options() const { return m_Options; }
+  GeneralOptions&       options()       { return m_Options; }
+
+  const ScriptOptions&  scripts() const { return m_Scripts; }
+  ScriptOptions&        scripts()       { return m_Scripts; }
+
+  const BitcodeOption&  bitcode() const { return m_Bitcode; }
+  BitcodeOption&        bitcode()       { return m_Bitcode; }
+
+  const AttributeOption& attribute() const { return m_Attribute; }
+  AttributeOption&       attribute()       { return m_Attribute; }
+
+  CodeGenType codeGenType() const { return m_CodeGenType; }
+
+  void setCodeGenType(CodeGenType pType) { m_CodeGenType = pType; }
+
+  const llvm::Triple& triple() const { return m_Triple; }
+
+  void setTriple(const std::string& pTriple);
+
+  void setTriple(const llvm::Triple& pTriple);
+
+  static const char* version();
+
+private:
+  // -----  General Options  ----- //
+  GeneralOptions m_Options;
+  ScriptOptions m_Scripts;
+  BitcodeOption m_Bitcode;
+  AttributeOption m_Attribute;
+
+  llvm::Triple m_Triple;
+  CodeGenType m_CodeGenType;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/MC/MCLDAttribute.h b/include/mcld/MC/Attribute.h
similarity index 90%
rename from include/mcld/MC/MCLDAttribute.h
rename to include/mcld/MC/Attribute.h
index f7f9f97..11f6d26 100644
--- a/include/mcld/MC/MCLDAttribute.h
+++ b/include/mcld/MC/Attribute.h
@@ -1,4 +1,4 @@
-//===- MCLDAttribute.h ----------------------------------------------------===//
+//===- Attribute.h --------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -11,12 +11,10 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <vector>
-#include <string>
 
-namespace mcld
-{
-class AttributeFactory;
+namespace mcld {
+
+class AttributeSet;
 
 /** \class AttributeBase
  *  \brief AttributeBase provides the real storage for attributes of options.
@@ -73,6 +71,7 @@
   // represent GNU ld -call_shared option
   bool isDynamic() const
   { return !m_Static; }
+
 public:
   bool m_WholeArchive : 1;
   bool m_AsNeeded : 1;
@@ -175,19 +174,19 @@
  *  AttributeProxy hides the reality of sharing. An input file can change
  *  its attribute without explicit searching of existing attributes
  *  as it has a private ownership of the attribute. AttributeProxy does
- *  the searching in the AttributeFactory and changes the pointer of
+ *  the searching in the AttributeSet and changes the pointer of
  *  the attribute of the input file. If the searching fails, AttributeProxy
- *  requests a new attribute from the AttributeFactory.
+ *  requests a new attribute from the AttributeSet.
  */
 class AttributeProxy
 {
-private:
-  friend class AttributeFactory;
+public:
+  AttributeProxy(AttributeSet& pParent,
+                 const Attribute& pBase,
+                 const AttrConstraint& pConstraint);
 
-  explicit AttributeProxy(AttributeFactory& pParent, Attribute& pBase);
   ~AttributeProxy();
 
-public:
   // ----- observers  ----- //
   bool isWholeArchive() const;
 
@@ -199,9 +198,6 @@
 
   bool isDynamic() const;
 
-  Attribute* attr()
-  { return m_pBase; }
-
   const Attribute* attr() const
   { return m_pBase; }
 
@@ -215,15 +211,12 @@
   void setStatic();
   void setDynamic();
 
-private:
-  AttributeProxy* clone() const;
-
-  void change(Attribute* pBase)
-  { m_pBase = pBase; }
+  AttributeProxy& assign(Attribute* pBase);
 
 private:
-  AttributeFactory &m_AttrPool;
-  Attribute *m_pBase;
+  AttributeSet &m_AttrPool;
+  const Attribute *m_pBase;
+  const AttrConstraint& m_Constraint;
 };
 
 
diff --git a/include/mcld/MC/AttributeFactory.h b/include/mcld/MC/AttributeFactory.h
deleted file mode 100644
index 0af1328..0000000
--- a/include/mcld/MC/AttributeFactory.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===- AttributeFactory.h -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_ATTRIBUTE_FACTORY_H
-#define MCLD_ATTRIBUTE_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/ADT/Uncopyable.h>
-#include <mcld/MC/MCLDAttribute.h>
-
-namespace mcld
-{
-
-/** \class AttributeFactory
- *  \brief AttributeFactory contructs the AttributeProxys.
- *
- *  Since the number of AttributeProxys is usually small, sequential search
- *  on a small vector is enough.
- */
-class AttributeFactory : private Uncopyable
-{
-private:
-  typedef std::vector<Attribute*> AttrSet;
-
-public:
-  typedef AttrSet::iterator iterator;
-  typedef AttrSet::const_iterator const_iterator;
-
-public:
-  AttributeFactory();
-  explicit AttributeFactory(size_t pNum);
-  ~AttributeFactory();
-
-  // reserve - reserve the memory space for attributes
-  // @param pNum the number of reserved attributes
-  void reserve(size_t pNum);
-
-  // predefined - return the predefined attribute
-  Attribute& predefined();
-  const Attribute& predefined() const;
-  
-  // constraint - return the constraint of attributes
-  AttrConstraint& constraint()
-  { return m_Constraint; }
-
-  const AttrConstraint& constraint() const
-  { return m_Constraint; }
-
-  // produce - produce a attribute, but do not record it yet.
-  // the produced attribute is identical to the pre-defined attribute.
-  AttributeProxy* produce();
-
-  // last - the last touched attribute.
-  AttributeProxy& last();
-  const AttributeProxy& last() const;
-
-  // exists- return the recorded attribute whose content is identical to the
-  // input attribute.
-  Attribute *exists(const Attribute& pAttr) const;
-
-  // record - record the attribute no mater if it has been recorded.
-  void record(Attribute& pAttr);
-
-  // -----  observers  ----- //
-  size_t size() const
-  { return m_AttrSet.size(); }
-
-  bool empty() const
-  { return m_AttrSet.empty(); }
-
-  // -----  iterators  ----- //
-  iterator begin()
-  { return m_AttrSet.begin(); }
-
-  iterator end()
-  { return m_AttrSet.end(); }
-
-  const_iterator begin() const
-  { return m_AttrSet.begin(); }
-
-  const_iterator end() const
-  { return m_AttrSet.end(); }
-
-private:
-  AttrSet m_AttrSet;
-  AttrConstraint m_Constraint;
-  AttributeProxy *m_pLast;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/MC/AttributeSet.h b/include/mcld/MC/AttributeSet.h
new file mode 100644
index 0000000..e50384d
--- /dev/null
+++ b/include/mcld/MC/AttributeSet.h
@@ -0,0 +1,62 @@
+//===- AttributeSet.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ATTRIBUTE_SET_H
+#define MCLD_ATTRIBUTE_SET_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/ADT/Uncopyable.h>
+#include <vector>
+
+namespace mcld {
+
+class Attribute;
+
+/** \class AttributeSet
+ *  \brief AttributeSet is a set of Attribute.
+ *
+ *  Clients delegates Attributes to AttributeSet. AttributeSet deletes delegated
+ *  Attributes during destruction.
+ */
+class AttributeSet : private Uncopyable
+{
+private:
+  typedef std::vector<Attribute*> AttrSet;
+
+public:
+  typedef AttrSet::iterator iterator;
+  typedef AttrSet::const_iterator const_iterator;
+
+public:
+  AttributeSet(unsigned int pNum, const Attribute& pPredefined);
+
+  ~AttributeSet();
+
+  // -----  iterators  ----- //
+  const_iterator begin() const { return m_AttrSet.begin(); }
+  iterator       begin()       { return m_AttrSet.begin(); }
+  const_iterator end  () const { return m_AttrSet.end(); }
+  iterator       end  ()       { return m_AttrSet.end(); }
+
+  // exists- return the recorded attribute whose content is identical to the
+  // input attribute.
+  Attribute *exists(const Attribute& pAttr) const;
+
+  // record - record the attribute no mater if it has been recorded.
+  void record(Attribute& pAttr);
+
+private:
+  AttrSet m_AttrSet;
+  const Attribute& m_Predefined;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/MC/CommandAction.h b/include/mcld/MC/CommandAction.h
new file mode 100644
index 0000000..a0ff909
--- /dev/null
+++ b/include/mcld/MC/CommandAction.h
@@ -0,0 +1,165 @@
+//===- CommandAction.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MC_COMMAND_ACTION_H
+#define MCLD_MC_COMMAND_ACTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+#include <mcld/Support/Path.h>
+#include <mcld/MC/InputAction.h>
+
+namespace mcld {
+
+class SearchDirs;
+class InputBuilder;
+
+//===----------------------------------------------------------------------===//
+// Derived InputAction
+//===----------------------------------------------------------------------===//
+/// InputFileAction
+class InputFileAction : public InputAction
+{
+public:
+  explicit InputFileAction(unsigned int pPosition, const sys::fs::Path &pPath);
+
+  const sys::fs::Path& path() const { return m_Path; }
+
+  bool activate(InputBuilder&) const;
+
+private:
+  sys::fs::Path m_Path;
+};
+
+/// NamespecAction
+class NamespecAction : public InputAction
+{
+public:
+  NamespecAction(unsigned int pPosition,
+                 const std::string &pNamespec,
+                 SearchDirs& pSearchDirs);
+
+  const std::string &namespec() const { return m_Namespec; }
+
+  bool activate(InputBuilder&) const;
+
+private:
+  std::string m_Namespec;
+  SearchDirs& m_SearchDirs;
+};
+
+/// BitcodeAction
+class BitcodeAction : public InputAction
+{
+public:
+  BitcodeAction(unsigned int pPosition, const sys::fs::Path &pPath);
+
+  const sys::fs::Path& path() const { return m_Path; }
+
+  bool activate(InputBuilder&) const;
+
+private:
+  sys::fs::Path m_Path;
+};
+
+/// StartGroupAction
+class StartGroupAction : public InputAction
+{
+public:
+  explicit StartGroupAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// EndGroupAction
+class EndGroupAction : public InputAction
+{
+public:
+  explicit EndGroupAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// WholeArchiveAction
+class WholeArchiveAction : public InputAction
+{
+public:
+  explicit WholeArchiveAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// NoWholeArchiveAction
+class NoWholeArchiveAction : public InputAction
+{
+public:
+  explicit NoWholeArchiveAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// AsNeededAction
+class AsNeededAction : public InputAction
+{
+public:
+  explicit AsNeededAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// NoAsNeededAction
+class NoAsNeededAction : public InputAction
+{
+public:
+  explicit NoAsNeededAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// AddNeededAction
+class AddNeededAction : public InputAction
+{
+public:
+  explicit AddNeededAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// NoAddNeededAction
+class NoAddNeededAction : public InputAction
+{
+public:
+  explicit NoAddNeededAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// BDynamicAction
+class BDynamicAction : public InputAction
+{
+public:
+  explicit BDynamicAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+/// BStaticAction
+class BStaticAction : public InputAction
+{
+public:
+  explicit BStaticAction(unsigned int pPosition);
+
+  bool activate(InputBuilder&) const;
+};
+
+} // end of namespace mcld
+
+#endif
+
diff --git a/include/mcld/MC/FileAction.h b/include/mcld/MC/FileAction.h
new file mode 100644
index 0000000..4644405
--- /dev/null
+++ b/include/mcld/MC/FileAction.h
@@ -0,0 +1,53 @@
+//===- FileAction.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MC_FILE_ACTION_H
+#define MCLD_MC_FILE_ACTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/MC/InputAction.h>
+#include <mcld/Support/FileHandle.h>
+
+namespace mcld {
+
+class ContextFactory;
+class MemoryAreaFactory;
+
+/** \class ContextAction
+ *  \brief ContextAction is a command object to create input's LDContext.
+ */
+class ContextAction : public InputAction
+{
+public:
+  explicit ContextAction(unsigned int pPosition);
+
+  bool activate(InputBuilder& pBuilder) const;
+};
+
+/** \class MemoryAreaAction
+ *  \brief MemoryAreaAction is a command object to create input's MemoryArea.
+ */
+class MemoryAreaAction : public InputAction
+{
+public:
+  MemoryAreaAction(unsigned int pPosition,
+                   FileHandle::OpenMode pMode,
+                   FileHandle::Permission pPerm = FileHandle::System);
+
+  bool activate(InputBuilder& pBuilder) const;
+
+private:
+  FileHandle::OpenMode m_Mode;
+  FileHandle::Permission m_Permission;
+};
+
+} // end of namespace mcld
+
+#endif
+
diff --git a/include/mcld/MC/InputAction.h b/include/mcld/MC/InputAction.h
new file mode 100644
index 0000000..fb7d660
--- /dev/null
+++ b/include/mcld/MC/InputAction.h
@@ -0,0 +1,53 @@
+//===- InputAction.h ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MC_INPUT_ACTION_H
+#define MCLD_MC_INPUT_ACTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld {
+
+class SearchDirs;
+class InputBuilder;
+
+//===----------------------------------------------------------------------===//
+// Base InputAction
+//===----------------------------------------------------------------------===//
+/** \class InputAction
+ *  \brief InputAction is a command object to construct mcld::InputTree.
+ */
+class InputAction
+{
+protected:
+  explicit InputAction(unsigned int pPosition);
+
+public:
+  virtual ~InputAction();
+
+  virtual bool activate(InputBuilder&) const = 0;
+
+  unsigned int position() const { return m_Position; }
+
+  bool operator<(const InputAction& pOther) const
+  { return (position() < pOther.position()); }
+
+private:
+  InputAction();                               // DO_NOT_IMPLEMENT
+  InputAction(const InputAction& );            // DO_NOT_IMPLEMENT
+  InputAction& operator=(const InputAction& ); // DO_NOT_IMPLEMENT
+
+private:
+  unsigned int m_Position;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/MC/InputBuilder.h b/include/mcld/MC/InputBuilder.h
new file mode 100644
index 0000000..0301c15
--- /dev/null
+++ b/include/mcld/MC/InputBuilder.h
@@ -0,0 +1,141 @@
+//===- InputBuilder.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MC_INPUT_BUILDER_H
+#define MCLD_MC_INPUT_BUILDER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+#include <stack>
+
+#include <mcld/InputTree.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/FileHandle.h>
+
+namespace mcld {
+
+class LinkerConfig;
+class InputFactory;
+class ContextFactory;
+class MemoryAreaFactory;
+class AttrConstraint;
+class raw_mem_ostream;
+
+/** \class InputBuilder
+ *  \brief InputBuilder recieves InputActions and build the InputTree.
+ *
+ *  InputBuilder build input tree and inputs.
+ */
+class InputBuilder
+{
+public:
+  explicit InputBuilder(const LinkerConfig& pConfig);
+
+  InputBuilder(const LinkerConfig& pConfig,
+               InputFactory& pInputFactory,
+               ContextFactory& pContextFactory,
+               MemoryAreaFactory& pMemoryFactory,
+               bool pDelegate = true);
+
+  virtual ~InputBuilder();
+
+  // -----  input tree operations  ----- //
+  const InputTree& getCurrentTree() const;
+  InputTree&       getCurrentTree();
+
+  void setCurrentTree(InputTree& pInputTree);
+
+  // -----  root of input tree  ----- //
+  const InputTree::iterator& getCurrentNode() const { return m_Root; }
+  InputTree::iterator&       getCurrentNode()       { return m_Root; }
+
+  template<InputTree::Direction DIRECTION>
+  InputTree& createNode(const std::string& pName,
+                        const sys::fs::Path& pPath,
+                        unsigned int pType = Input::Unknown);
+
+  // -----  input operations  ----- //
+  Input* createInput(const std::string& pName,
+                     const sys::fs::Path& pPath,
+                     unsigned int pType = Input::Unknown,
+                     off_t pFileOffset = 0);
+
+  bool setContext(Input& pInput, bool pCheck = true);
+
+  bool setMemory(Input& pInput,
+                 FileHandle::OpenMode pMode,
+		 FileHandle::Permission pPerm = FileHandle::System);
+
+  bool setMemory(Input& pInput, void* pMemBuffer, size_t pSize);
+
+  InputTree& enterGroup();
+
+  InputTree& exitGroup();
+
+  bool isInGroup() const;
+
+  const AttrConstraint& getConstraint() const;
+
+  const AttributeProxy& getAttributes() const;
+  AttributeProxy&       getAttributes();
+
+private:
+  const LinkerConfig& m_Config;
+
+  InputFactory* m_pInputFactory;
+  MemoryAreaFactory* m_pMemFactory;
+  ContextFactory* m_pContextFactory;
+
+  InputTree* m_pCurrentTree;
+  InputTree::Mover* m_pMove;
+  InputTree::iterator m_Root;
+  std::stack<InputTree::iterator> m_ReturnStack;
+
+  bool m_bOwnFactory;
+
+};
+
+//===----------------------------------------------------------------------===//
+// Template implement
+//===----------------------------------------------------------------------===//
+template<> inline InputTree&
+InputBuilder::createNode<InputTree::Inclusive>(const std::string& pName,
+                                               const sys::fs::Path& pPath,
+                                               unsigned int pType)
+{
+  assert(NULL != m_pCurrentTree && NULL != m_pMove);
+
+  Input* input = createInput(pName, pPath, pType);
+  m_pCurrentTree->insert(m_Root, *m_pMove, *input);
+  m_pMove->move(m_Root);
+  m_pMove = &InputTree::Downward;
+
+  return *m_pCurrentTree;
+}
+
+template<> inline InputTree&
+InputBuilder::createNode<InputTree::Positional>(const std::string& pName,
+                                               const sys::fs::Path& pPath,
+                                               unsigned int pType)
+{
+  assert(NULL != m_pCurrentTree && NULL != m_pMove);
+
+  Input* input = createInput(pName, pPath, pType);
+  m_pCurrentTree->insert(m_Root, *m_pMove, *input);
+  m_pMove->move(m_Root);
+  m_pMove = &InputTree::Afterward;
+
+  return *m_pCurrentTree;
+}
+
+} // end of namespace mcld
+
+#endif
+
diff --git a/include/mcld/MC/InputFactory.h b/include/mcld/MC/InputFactory.h
index 5dc99c4..d644222 100644
--- a/include/mcld/MC/InputFactory.h
+++ b/include/mcld/MC/InputFactory.h
@@ -11,13 +11,14 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include "mcld/Support/GCFactory.h"
-#include "mcld/MC/MCLDInput.h"
+#include <mcld/Support/GCFactory.h>
+#include <mcld/MC/MCLDInput.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class AttributeFactory;
+class LinkerConfig;
+class AttributeProxy;
+class AttributeSet;
 
 /** \class InputFactory
  *  \brief InputFactory controls the production and destruction of
@@ -26,9 +27,6 @@
  *  All MCLDFiles created by MCLDFileFactory are guaranteed to be destructed
  *  while MCLDFileFactory is destructed.
  *
- *  FIXME: the number of the Inputs should be passed in by Target or any
- *  target specific class.
- *
  *  \see llvm::sys::Path
  */
 class InputFactory : public GCFactory<Input,0>
@@ -37,17 +35,24 @@
   typedef GCFactory<Input, 0> Alloc;
 
 public:
-  InputFactory(size_t pNum, AttributeFactory& pAttrFactory);
+  InputFactory(size_t pNum, const LinkerConfig& pConfig);
+
   ~InputFactory();
 
-  // -----  production  ----- //
+  // -----  input  ----- //
   Input* produce(llvm::StringRef pName,
                  const sys::fs::Path& pPath,
                  unsigned int pType = Input::Unknown,
                  off_t pFileOffset = 0);
 
+  // -----  attributes  ----- //
+  /// attr - the last touched attribute.
+  const AttributeProxy& attr() const { return *m_pLast; }
+  AttributeProxy&       attr()       { return *m_pLast; }
+
 private:
-  AttributeFactory &m_AttrFactory;
+  AttributeProxy* m_pLast;
+  AttributeSet* m_pAttrSet;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/MC/MCFragmentRef.h b/include/mcld/MC/MCFragmentRef.h
deleted file mode 100644
index b7d94cd..0000000
--- a/include/mcld/MC/MCFragmentRef.h
+++ /dev/null
@@ -1,85 +0,0 @@
-//===- MCFragmentRef.h ----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_MCFRAGMENT_REFERENCE_H
-#define MCLD_MCFRAGMENT_REFERENCE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/MC/MCAssembler.h>
-#include <mcld/ADT/SizeTraits.h>
-#include <mcld/ADT/TypeTraits.h>
-
-namespace mcld
-{
-
-class Layout;
-
-/// compunteFragmentSize - compute the specific MCFragment size
-uint64_t computeFragmentSize(const Layout& pLayout,
-                             const llvm::MCFragment& pFrag);
-
-/** \class MCFragmentRef
- *  \brief MCFragmentRef is a reference of a MCFragment's contetnt.
- *
- */
-class MCFragmentRef
-{
-public:
-  typedef uint64_t Offset; // FIXME: use SizeTraits<T>::Offset
-  typedef NonConstTraits<unsigned char>::pointer Address;
-  typedef ConstTraits<unsigned char>::pointer ConstAddress;
-
-public:
-  MCFragmentRef();
-  MCFragmentRef(llvm::MCFragment& pFrag, Offset pOffset = 0);
-  ~MCFragmentRef();
-
-  // -----  modifiers  ----- //
-  MCFragmentRef& assign(const MCFragmentRef& pCopy);
-
-  MCFragmentRef& assign(llvm::MCFragment& pFrag, Offset pOffset = 0);
-
-  /// memcpy - copy memory
-  /// copy memory from the fragment to the pDesc.
-  /// @pDest - the destination address
-  /// @pNBytes - copies pNBytes from the fragment[offset()+pOffset]
-  /// @pOffset - additional offset. 
-  ///            the start address offset from fragment[offset()]
-  void memcpy(void* pDest, size_t pNBytes, Offset pOffset = 0) const;
-
-  // -----  observers  ----- //
-  llvm::MCFragment* frag()
-  { return m_pFragment; }
-
-  const llvm::MCFragment* frag() const
-  { return m_pFragment; }
-
-  Offset offset() const
-  { return m_Offset; }
-
-  // -----  dereference  ----- //
-  Address deref();
-
-  ConstAddress deref() const;
-
-  Address operator*()
-  { return deref(); }
-
-  ConstAddress operator*() const
-  { return deref(); }
-  
-private:
-  llvm::MCFragment* m_pFragment;
-  Offset m_Offset;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/MC/MCLDDriver.h b/include/mcld/MC/MCLDDriver.h
deleted file mode 100644
index 2259186..0000000
--- a/include/mcld/MC/MCLDDriver.h
+++ /dev/null
@@ -1,127 +0,0 @@
-//===- MCLDDriver.h --------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// MCLDDriver plays the same role as GNU collect2 to prepare all implicit
-// parameters for MCLinker.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MCLD_LDDRIVER_H
-#define MCLD_LDDRIVER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <mcld/LD/SectionMap.h>
-
-namespace mcld
-{
-
-class MCLinker;
-class MCLDInfo;
-class TargetLDBackend;
-class MemoryAreaFactory;
-
-/** \class MCLDDriver
- *  \brief MCLDDriver prepares parameters for MCLinker.
- */
-class MCLDDriver
-{
-public:
-  MCLDDriver(MCLDInfo& pLDInfo,
-             TargetLDBackend& pLDBackend,
-             MemoryAreaFactory& pAreaFactory);
-
-  ~MCLDDriver();
-
-  /// initMCLinker - initialize MCLinker
-  ///  Connect all components in MCLinker
-  bool initMCLinker();
-
-  /// initStdSections - initialize standard sections of the output file.
-  bool initStdSections();
-
-  /// normalize - normalize the input files
-  void normalize();
-
-  /// linkable - check the linkability of current MCLDInfo
-  ///  Check list:
-  ///  - check the Attributes are not violate the constaint
-  ///  - check every Input has a correct Attribute
-  bool linkable() const;
-
-  /// mergeSections - put allinput sections into output sections
-  bool mergeSections();
-
-  /// addStandardSymbols - shared object and executable files need some
-  /// standard symbols
-  ///   @return if there are some input symbols with the same name to the
-  ///   standard symbols, return false
-  bool addStandardSymbols();
-
-  /// addTargetSymbols - some targets, such as MIPS and ARM, need some
-  /// target-dependent symbols
-  ///   @return if there are some input symbols with the same name to the
-  ///   target symbols, return false
-  bool addTargetSymbols();
-
-  /// readRelocations - read all relocation entries
-  bool readRelocations();
-
-  /// prelayout - help backend to do some modification before layout
-  bool prelayout();
-
-  /// layout - linearly layout all output sections and reserve some space
-  /// for GOT/PLT
-  ///   Because we do not support instruction relaxing in this early version,
-  ///   if there is a branch can not jump to its target, we return false
-  ///   directly
-  bool layout();
-
-  /// postlayout - help backend to do some modification after layout
-  bool postlayout();
-
-  /// relocate - applying relocation entries and create relocation
-  /// section in the output files
-  /// Create relocation section, asking TargetLDBackend to
-  /// read the relocation information into RelocationEntry
-  /// and push_back into the relocation section
-  bool relocation();
-
-  /// finalizeSymbolValue - finalize the symbol value
-  bool finalizeSymbolValue();
-
-  /// emitOutput - emit the output file.
-  bool emitOutput();
-
-  /// postProcessing - do modificatiion after all processes
-  bool postProcessing();
-
-  /// getLinker - get internal MCLinker object
-  MCLinker* getLinker()
-  { return m_pLinker; }
-
-  /// getLinker - get internal MCLinker object
-  const MCLinker* getLinker() const
-  { return m_pLinker; }
-
-  /// hasInitLinker - has Linker been initialized?
-  bool hasInitLinker() const
-  { return (NULL != m_pLinker); }
-
-private:
-  MCLDInfo& m_LDInfo;
-  TargetLDBackend &m_LDBackend;
-  MCLinker* m_pLinker;
-  SectionMap m_SectionMap;
-  MemoryAreaFactory &m_AreaFactory;
-};
-
-} // end namespace mcld
-#endif
diff --git a/include/mcld/MC/MCLDFile.h b/include/mcld/MC/MCLDFile.h
deleted file mode 100644
index c780cb8..0000000
--- a/include/mcld/MC/MCLDFile.h
+++ /dev/null
@@ -1,174 +0,0 @@
-//===- MCLDFile.h ---------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// MCLDFile represents a file, the content of the file is stored in LDContext.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MCLD_LD_FILE_H
-#define MCLD_LD_FILE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/LD/LDContext.h"
-#include "mcld/Support/Path.h"
-#include "mcld/Support/FileSystem.h"
-#include "mcld/Support/GCFactory.h"
-#include "mcld/Support/MemoryArea.h"
-#include <llvm/ADT/StringRef.h>
-#include <string>
-#include <sys/stat.h>
-
-
-namespace mcld
-{
-class MemoryArea;
-
-/** \class MCLDFile
- *  \brief MCLDFile represents the file being linked or produced.
- *
- *  MCLDFile is the storage of name, path and type
- *  A MCLDFile just refers to LDContext, not owns it.
- *
- *  @see mcld::sys::fs::Path LDContext
- */
-class MCLDFile : private Uncopyable
-{
-public:
-  enum Type {
-    Unknown,
-    Object,
-    Exec,
-    DynObj,
-    CoreFile,
-    Script,
-    Archive,
-    External
-  };
-
-public:
-  MCLDFile();
-  MCLDFile(llvm::StringRef pName);
-  MCLDFile(llvm::StringRef pName,
-           const sys::fs::Path& pPath,
-           unsigned int pType = Unknown);
-
-  virtual ~MCLDFile();
-
-  // -----  modifiers  ----- //
-  void setType(unsigned int pType)
-  { m_Type = pType; }
-
-  void setContext(LDContext* pContext)
-  { m_pContext = pContext; }
-
-  void setPath(const sys::fs::Path& pPath)
-  { m_Path = pPath; }
-
-  void setMemArea(MemoryArea* pMemArea)
-  {
-    m_pMemArea = pMemArea;
-  }
-
-  /// setSOName - set the name of the shared object.
-  /// In ELF, this will be written in DT_SONAME
-  void setSOName(const std::string& pName);
-
-  // -----  observers  ----- //
-  unsigned int type() const
-  { return m_Type; }
-
-  const std::string& name() const
-  { return m_Name; }
-
-  const sys::fs::Path& path() const
-  { return m_Path; }
-
-  bool hasContext() const
-  { return (0 != m_pContext); }
-
-  LDContext* context()
-  { return m_pContext; }
-
-  const LDContext* context() const
-  { return m_pContext; }
-
-  bool hasMemArea() const
-  { return (0 != m_pMemArea); }
-
-  MemoryArea* memArea()
-  { return m_pMemArea; }
-
-  const MemoryArea* memArea() const
-  { return m_pMemArea; }
-
-protected:
-  unsigned int m_Type;
-  LDContext *m_pContext;
-  sys::fs::Path m_Path;
-  std::string m_Name;
-  MemoryArea* m_pMemArea;
-};
-
-/** \class MCLDFileFactory
- *  \brief MCLDFileFactory controls the production and destruction of
- *  MCLDFiles.
- *
- *  All MCLDFiles created by MCLDFileFactory are guaranteed to be destructed
- *  while MCLDFileFactory is destructed.
- *
- *  MCLDFileFactory also provides the MCLCContextFactory to MCLDFile.
- *  MCLDFile is responsed for the life of LDContext, therefore, the best
- *  idea is let MCLDFile control the life of LDContext. Since SectLinker
- *  has the need to count the number of LDContext, we give a central factory
- *  for LDContext.
- *
- *  \see llvm::sys::Path
- */
-template<size_t NUM>
-class MCLDFileFactory : public GCFactory<MCLDFile, NUM>
-{
-public:
-  typedef GCFactory<MCLDFile, NUM> Alloc;
-
-public:
-  // -----  production  ----- //
-  MCLDFile* produce(llvm::StringRef pName,
-                    const sys::fs::Path& pPath,
-                    unsigned int pType = MCLDFile::Unknown);
-
-  MCLDFile* produce();
-};
-
-} // namespace of mcld
-
-//===----------------------------------------------------------------------===//
-// MCLDFileFactory
-template<size_t NUM>
-mcld::MCLDFile* mcld::MCLDFileFactory<NUM>::produce(llvm::StringRef pName,
-                                   const mcld::sys::fs::Path& pPath,
-                                   unsigned int pType)
-{
-    mcld::MCLDFile* result = Alloc::allocate();
-    new (result) mcld::MCLDFile(pName, pPath, pType);
-    return result;
-}
-
-template<size_t NUM>
-mcld::MCLDFile* mcld::MCLDFileFactory<NUM>::produce()
-{
-    mcld::MCLDFile* result = Alloc::allocate();
-    new (result) mcld::MCLDFile();
-    return result;
-}
-
-#endif
-
diff --git a/include/mcld/MC/MCLDInfo.h b/include/mcld/MC/MCLDInfo.h
deleted file mode 100644
index d76fff4..0000000
--- a/include/mcld/MC/MCLDInfo.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//===- MCLDInfo.h ---------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LDINFO_H
-#define MCLD_LDINFO_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/ADT/Triple.h>
-
-#include <mcld/Support/FileSystem.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLDOptions.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/AttributeFactory.h>
-#include <mcld/MC/ContextFactory.h>
-#include <mcld/LD/NamePool.h>
-
-#include <string>
-#include <cassert>
-
-namespace mcld
-{
-class Resolver;
-
-/** \class MCLDInfo
- *  \brief MCLDInfo is composed of argumments of MCLinker.
- *   options()        - the general options
- *   scripts()        - the script options
- *   inputs()         - the tree of inputs
- *   bitcode()        - the bitcode being linked
- *   output()         - the output file
- *   inputFactory()   - the list of all inputs
- *   attrFactory()    - the list of all attributes
- *   contextFactory() - the list of all contexts.
- *   memAreaFactory() - the list of all MemoryAreas.
- */
-class MCLDInfo
-{
-public:
-  explicit MCLDInfo(const std::string &pTripleString,
-                    size_t pAttrNum,
-                    size_t InputSize);
-
-  virtual ~MCLDInfo();
-
-  GeneralOptions& options()
-  { return m_Options; }
-
-  const GeneralOptions& options() const
-  { return m_Options; }
-
-  ScriptOptions& scripts()
-  { return m_Scripts; }
-
-  const ScriptOptions& scripts() const
-  { return m_Scripts; }
-
-  void setBitcode(const Input& pInput);
-  Input& bitcode();
-  const Input& bitcode() const;
-
-  Output& output()
-  { return *m_pOutput; }
-
-  const Output& output() const
-  { return *m_pOutput; }
-
-  InputTree& inputs()
-  { return *m_pInputTree; }
-
-  const InputTree& inputs() const
-  { return *m_pInputTree; }
-
-  InputFactory& inputFactory()
-  { return *m_pInputFactory; }
-
-  const InputFactory& inputFactory() const
-  { return *m_pInputFactory; }
-
-  AttributeFactory& attrFactory()
-  { return *m_pAttrFactory; }
-
-
-  const AttributeFactory& attrFactory() const
-  { return *m_pAttrFactory; }
-
-  ContextFactory& contextFactory()
-  { return *m_pCntxtFactory; }
-
-  const ContextFactory& contextFactory() const
-  { return *m_pCntxtFactory; }
-
-  const llvm::Triple& triple() const
-  { return m_Triple; }
-
-  static const char* version();
-
-  NamePool& getNamePool() {
-    assert(NULL != m_pNamePool);
-    return *m_pNamePool;
-  }
-
-  const NamePool& getNamePool() const {
-    assert(NULL != m_pNamePool);
-    return *m_pNamePool;
-  }
-
-private:
-  // -----  General Options  ----- //
-  GeneralOptions m_Options;
-  ScriptOptions m_Scripts;
-  InputTree *m_pInputTree;
-  Input* m_pBitcode;
-  Output* m_pOutput;
-  llvm::Triple m_Triple;
-
-  // -----  factories  ----- //
-  InputFactory *m_pInputFactory;
-  AttributeFactory *m_pAttrFactory;
-  ContextFactory *m_pCntxtFactory;
-
-  // -----  string and symbols  ----- //
-  Resolver* m_pResolver;
-  NamePool* m_pNamePool;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/MC/MCLDInput.h b/include/mcld/MC/MCLDInput.h
index e9bb4e6..94b9479 100644
--- a/include/mcld/MC/MCLDInput.h
+++ b/include/mcld/MC/MCLDInput.h
@@ -10,43 +10,50 @@
 //  Input class inherits MCLDFile, which is used to represent a input file
 //
 //===----------------------------------------------------------------------===//
-
 #ifndef MCLD_INPUT_H
 #define MCLD_INPUT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
-#include "mcld/MC/MCLDFile.h"
+#include <mcld/Support/Path.h>
 
-namespace mcld
-{
+namespace mcld {
 
+class MemoryArea;
 class AttributeProxy;
 class Attribute;
 class InputFactory;
+class LDContext;
 
 /** \class Input
  *  \brief Input provides the information of a input file.
- *
- *  @see MCLDFile
  */
-class Input : public MCLDFile
+class Input
 {
 friend class InputFactory;
 public:
   enum Type {
-    Unknown = MCLDFile::Unknown,
-    Object = MCLDFile::Object,
-    DynObj = MCLDFile::DynObj,
-    Archive = MCLDFile::Archive,
-    Script = MCLDFile::Script,
-    External = MCLDFile::External
+    Unknown,
+    Object,
+    Exec,
+    DynObj,
+    CoreFile,
+    Script,
+    Archive,
+    External
   };
 
-private:
-  explicit Input(llvm::StringRef pName,
-                 const AttributeProxy& pAttr);
+public:
+  explicit Input(llvm::StringRef pName);
+
+  Input(llvm::StringRef pName,
+        const AttributeProxy& pAttr);
+
+  Input(llvm::StringRef pName,
+        const sys::fs::Path& pPath,
+        unsigned int pType = Unknown,
+        off_t pFileOffset = 0);
 
   Input(llvm::StringRef pName,
         const sys::fs::Path& pPath,
@@ -54,12 +61,32 @@
         unsigned int pType = Unknown,
         off_t pFileOffset = 0);
 
-public:
   ~Input();
 
+  const std::string& name() const
+  { return m_Name; }
+
+  void setName(const std::string& pName)
+  { m_Name = pName; }
+
+  const sys::fs::Path& path() const
+  { return m_Path; }
+
+  void setPath(const sys::fs::Path& pPath)
+  { m_Path = pPath; }
+
+  void setType(unsigned int pType)
+  { m_Type = pType; }
+
+  unsigned int type() const
+  { return m_Type; }
+
   bool isRecognized() const
   { return (m_Type != Unknown); }
 
+  bool hasAttribute() const
+  { return (NULL != m_pAttr); }
+
   const Attribute* attribute() const
   { return m_pAttr; }
 
@@ -75,10 +102,35 @@
   void setFileOffset(off_t pFileOffset)
   { m_fileOffset = pFileOffset; }
 
+  // -----  memory area  ----- //
+  void setMemArea(MemoryArea* pMemArea)
+  { m_pMemArea = pMemArea; }
+
+  bool hasMemArea() const
+  { return (NULL != m_pMemArea); }
+
+  const MemoryArea* memArea() const { return m_pMemArea; }
+  MemoryArea*       memArea()       { return m_pMemArea; }
+
+  // -----  context  ----- //
+  void setContext(LDContext* pContext)
+  { m_pContext = pContext; }
+
+  bool hasContext() const
+  { return (NULL != m_pContext); }
+
+  const LDContext* context() const { return m_pContext; }
+  LDContext*       context()       { return m_pContext; }
+
 private:
+  unsigned int m_Type;
+  std::string m_Name;
+  sys::fs::Path m_Path;
   Attribute *m_pAttr;
   bool m_bNeeded;
   off_t m_fileOffset;
+  MemoryArea* m_pMemArea;
+  LDContext* m_pContext;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/MC/MCLDOutput.h b/include/mcld/MC/MCLDOutput.h
deleted file mode 100644
index 14768ce..0000000
--- a/include/mcld/MC/MCLDOutput.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- MCLDOutput.h -------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//  Output class inherits MCLDFile, which is used to represent a output file.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MCLD_OUTPUT_H
-#define MCLD_OUTPUT_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <mcld/MC/MCLDFile.h>
-#include <mcld/Support/RealPath.h>
-#include <string>
-
-namespace mcld
-{
-
-/** \class MCLDOutput
- *  \brief MCLDOutput provides the information about the output.
- *
- *  @see MCLDFile
- */
-class Output : public MCLDFile
-{
-public:
-  enum Type {
-    Object = MCLDFile::Object,
-    DynObj = MCLDFile::DynObj,
-    Exec   = MCLDFile::Exec
-  };
-
-public:
-  Output();
-  explicit Output(const sys::fs::Path& pRealPath,
-                  Type pType);
-
-  ~Output();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/MC/SearchDirs.h b/include/mcld/MC/SearchDirs.h
index e0cf169..13cc12f 100644
--- a/include/mcld/MC/SearchDirs.h
+++ b/include/mcld/MC/SearchDirs.h
@@ -6,27 +6,25 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef SEARCHDIRS_H
-#define SEARCHDIRS_H
+#ifndef MCLD_MC_SEARCHDIRS_H
+#define MCLD_MC_SEARCHDIRS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <llvm/ADT/StringRef.h>
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/MC/MCLDInput.h"
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/Path.h>
 
-namespace mcld
-{
+#include <llvm/ADT/StringRef.h>
+
+#include <vector>
+#include <string>
+
+namespace mcld {
 
 class MCLDFile;
 class MCLDDirectory;
 
-namespace sys {
-namespace fs {
-class Path;
-} // namespace of fs
-} // namespace of sys
-
 /** \class SearchDirs
  *  \brief SearchDirs contains the list of paths that MCLinker will search for
  *  archive libraries and control scripts.
@@ -45,30 +43,35 @@
 
 public:
   SearchDirs();
+
+  SearchDirs(const sys::fs::Path& pSysRoot);
+
   ~SearchDirs();
 
   // find - give a namespec, return a real path of the shared object.
-  //
-  sys::fs::Path* find(const std::string& pNamespec, mcld::Input::Type pPreferType);
+  sys::fs::Path*
+  find(const std::string& pNamespec, mcld::Input::Type pPreferType);
+
+  const sys::fs::Path*
+  find(const std::string& pNamespec, mcld::Input::Type pPreferType) const;
+
+  void setSysRoot(const sys::fs::Path& pSysRoot) { m_SysRoot = pSysRoot; }
+  const sys::fs::Path& sysroot() const { return m_SysRoot; }
 
   // -----  iterators  ----- //
-  iterator begin()
-  { return m_DirList.begin(); }
-
-  iterator end()
-  { return m_DirList.end(); }
-
-  const_iterator begin() const
-  { return m_DirList.begin(); }
-
-  const_iterator end() const
-  { return m_DirList.end(); }
+  const_iterator begin() const { return m_DirList.begin(); }
+  iterator       begin()       { return m_DirList.begin(); }
+  const_iterator end  () const { return m_DirList.end();   }
+  iterator       end  ()       { return m_DirList.end();   }
 
   // -----  modifiers  ----- //
-  void add(const MCLDDirectory& pDirectory);
+  bool insert(const std::string& pDirectory);
+
+  bool insert(const sys::fs::Path& pDirectory);
 
 private:
   DirList m_DirList;
+  sys::fs::Path m_SysRoot;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/MC/SymbolCategory.h b/include/mcld/MC/SymbolCategory.h
index 9432c2a..3aa16c5 100644
--- a/include/mcld/MC/SymbolCategory.h
+++ b/include/mcld/MC/SymbolCategory.h
@@ -45,6 +45,8 @@
 
   SymbolCategory& changeCommonsToGlobal();
 
+  SymbolCategory& changeLocalToTLS(const LDSymbol& pSymbol);
+
   // -----  access  ----- //
   LDSymbol& at(size_t pPosition)
   { return *m_OutputSymbols.at(pPosition); }
@@ -70,7 +72,7 @@
   bool empty() const;
 
   bool emptyLocals() const;
-  
+
   bool emptyCommons() const;
 
   bool emptyRegulars() const;
@@ -86,6 +88,11 @@
   const_iterator localBegin() const;
   const_iterator localEnd() const;
 
+  iterator tlsBegin();
+  iterator tlsEnd();
+  const_iterator tlsBegin() const;
+  const_iterator tlsEnd() const;
+
   iterator commonBegin();
   iterator commonEnd();
   const_iterator commonBegin() const;
@@ -103,6 +110,7 @@
     enum Type {
       File,
       Local,
+      TLS,
       Common,
       Weak,
       Global
@@ -147,6 +155,7 @@
 
   Category* m_pFile;
   Category* m_pLocal;
+  Category* m_pTLS;
   Category* m_pCommon;
   Category* m_pWeak;
   Category* m_pGlobal;
diff --git a/include/mcld/Module.h b/include/mcld/Module.h
new file mode 100644
index 0000000..36dda97
--- /dev/null
+++ b/include/mcld/Module.h
@@ -0,0 +1,166 @@
+//===- Module.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Module contains the intermediate representation (LDIR) of MCLinker.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MODULE_H
+#define MCLD_MODULE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+#include <string>
+
+#include <llvm/ADT/ilist.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>
+
+namespace mcld {
+
+class LDSection;
+class LDSymbol;
+
+/** \class Module
+ *  \brief Module provides the intermediate representation for linking.
+ */
+class Module
+{
+public:
+  typedef std::vector<Input*> ObjectList;
+  typedef ObjectList::iterator obj_iterator;
+  typedef ObjectList::const_iterator const_obj_iterator;
+
+  typedef std::vector<Input*> LibraryList;
+  typedef LibraryList::iterator lib_iterator;
+  typedef LibraryList::const_iterator const_lib_iterator;
+
+  typedef InputTree::iterator input_iterator;
+  typedef InputTree::const_iterator const_input_iterator;
+
+  typedef std::vector<LDSection*> SectionTable;
+  typedef SectionTable::iterator iterator;
+  typedef SectionTable::const_iterator const_iterator;
+
+  typedef SymbolCategory SymbolTable;
+  typedef SymbolTable::iterator sym_iterator;
+  typedef SymbolTable::const_iterator const_sym_iterator;
+
+public:
+  Module();
+
+  Module(const std::string& pName);
+
+  ~Module();
+
+  // -----  name  ----- //
+  const std::string& name() const { return m_Name; }
+
+  void setName(const std::string& pName) { m_Name = pName; }
+
+  // -----  link-in objects ----- //
+  const ObjectList& getObjectList() const { return m_ObjectList; }
+  ObjectList&       getObjectList()       { return m_ObjectList; }
+
+  const_obj_iterator obj_begin() const { return m_ObjectList.begin(); }
+  obj_iterator       obj_begin()       { return m_ObjectList.begin(); }
+  const_obj_iterator obj_end  () const { return m_ObjectList.end();   }
+  obj_iterator       obj_end  ()       { return m_ObjectList.end();   }
+
+  // -----  link-in libraries  ----- //
+  const LibraryList& getLibraryList() const { return m_LibraryList; }
+  LibraryList&       getLibraryList()       { return m_LibraryList; }
+
+  const_lib_iterator lib_begin() const { return m_LibraryList.begin(); }
+  lib_iterator       lib_begin()       { return m_LibraryList.begin(); }
+  const_lib_iterator lib_end  () const { return m_LibraryList.end();   }
+  lib_iterator       lib_end  ()       { return m_LibraryList.end();   }
+
+  // -----  link-in inputs  ----- //
+  const InputTree& getInputTree() const { return m_MainTree; }
+  InputTree&       getInputTree()       { return m_MainTree; }
+
+  const_input_iterator input_begin() const { return m_MainTree.begin(); }
+  input_iterator       input_begin()       { return m_MainTree.begin(); }
+  const_input_iterator input_end  () const { return m_MainTree.end();   }
+  input_iterator       input_end  ()       { return m_MainTree.end();   }
+
+/// @}
+/// @name Section Accessors
+/// @{
+
+  // -----  sections  ----- //
+  const SectionTable& getSectionTable() const { return m_SectionTable; }
+  SectionTable&       getSectionTable()       { return m_SectionTable; }
+
+  iterator         begin()       { return m_SectionTable.begin(); }
+  const_iterator   begin() const { return m_SectionTable.begin(); }
+  iterator         end  ()       { return m_SectionTable.end();   }
+  const_iterator   end  () const { return m_SectionTable.end();   }
+  LDSection*       front()       { return m_SectionTable.front(); }
+  const LDSection* front() const { return m_SectionTable.front(); }
+  LDSection*       back ()       { return m_SectionTable.back();  }
+  const LDSection* back () const { return m_SectionTable.back();  }
+  size_t           size () const { return m_SectionTable.size();  }
+  bool             empty() const { return m_SectionTable.empty(); }
+
+  LDSection*       getSection(const std::string& pName);
+  const LDSection* getSection(const std::string& pName) const;
+
+  LDSymbol*       getSectionSymbol(const LDSection* pSection);
+  const LDSymbol* getSectionSymbol(const LDSection* pSection) const;
+
+/// @}
+/// @name Symbol Accessors
+/// @{
+
+  // -----  symbols  ----- //
+  const SymbolTable& getSymbolTable() const { return m_SymbolTable; }
+  SymbolTable&       getSymbolTable()       { return m_SymbolTable; }
+
+  sym_iterator       sym_begin()       { return m_SymbolTable.begin();         }
+  const_sym_iterator sym_begin() const { return m_SymbolTable.begin();         }
+  sym_iterator       sym_end  ()       { return m_SymbolTable.end();           }
+  const_sym_iterator sym_end  () const { return m_SymbolTable.end();           }
+  size_t             sym_size () const { return m_SymbolTable.numOfSymbols();  }
+
+  // ----- section symbols ----- //
+  const SectionSymbolSet& getSectionSymbolSet() const
+  { return m_SectSymbolSet; }
+  SectionSymbolSet&       getSectionSymbolSet()
+  { return m_SectSymbolSet; }
+
+  // -----  names  ----- //
+  const NamePool& getNamePool() const { return m_NamePool; }
+  NamePool&       getNamePool()       { return m_NamePool; }
+
+private:
+  std::string m_Name;
+  ObjectList m_ObjectList;
+  LibraryList m_LibraryList;
+  InputTree m_MainTree;
+  SectionTable m_SectionTable;
+  SymbolTable m_SymbolTable;
+  NamePool m_NamePool;
+  SectionSymbolSet m_SectSymbolSet;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Object/ObjectBuilder.h b/include/mcld/Object/ObjectBuilder.h
new file mode 100644
index 0000000..bfa4c6b
--- /dev/null
+++ b/include/mcld/Object/ObjectBuilder.h
@@ -0,0 +1,99 @@
+//===- ObjectBuilder.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_OBJECT_OBJECT_BUILDER_H
+#define MCLD_OBJECT_OBJECT_BUILDER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/LD/EhFrame.h>
+
+#include <llvm/Support/DataTypes.h>
+
+#include <string>
+
+namespace mcld {
+
+class LinkerConfig;
+class Module;
+class LDSection;
+class SectionData;
+class RelocData;
+class Fragment;
+class Relocation;
+
+/** \class ObjectBuilder
+ *  \brief ObjectBuilder recieve ObjectAction and build the mcld::Module.
+ */
+class ObjectBuilder
+{
+public:
+  ObjectBuilder(const LinkerConfig& pConfig,
+                Module& pTheModule);
+
+/// @}
+/// @name Section Methods
+/// @{
+  /// CreateSection - To create an output LDSection in mcld::Module.
+  /// Link scripts and command line options define some SECTIONS commands that
+  /// specify where input sections are placed into output sections. This function
+  /// checks SECTIONS commands to change given name to the output section name.
+  /// This function creates a new LDSection and push the created LDSection into
+  /// @ref mcld::Module.
+  ///
+  /// To create an input LDSection in mcld::LDContext, use @ref LDSection::Create().
+  ///
+  /// @see SectionMap
+  ///
+  /// @param [in] pName The given name. Returned LDSection used the changed name
+  ///                   by SectionMap.
+  LDSection* CreateSection(const std::string& pInputName,
+                           LDFileFormat::Kind pKind,
+                           uint32_t pType,
+                           uint32_t pFlag,
+                           uint32_t pAlign = 0x0);
+
+  /// MergeSection - merge the pInput section to mcld::Module.
+  /// This function moves all fragments in pInputSection to the corresponding
+  /// output section of mcld::Module. 
+  ///
+  /// @see SectionMap
+  /// @param [in] pInputSection The merged input section.
+  /// @return If the corresponding output sections is not defined, return false.
+  bool MergeSection(LDSection& pInputSection);
+
+  /// MoveSectionData - move the fragment of pFrom to pTo section data.
+  static bool MoveSectionData(SectionData& pFrom, SectionData& pTo);
+
+/// @}
+/// @name Fragment Methods
+/// @{
+  /// AppendFragment - To append pFrag to the given SectionData pSD.
+  /// In order to keep the alignment of pFrag, This function inserts an
+  /// AlignFragment before pFrag if pAlignConstraint is larger than 1.
+  ///
+  /// @note This function does not update the alignment constraint of LDSection.
+  ///
+  /// @param [in, out] pFrag The appended fragment. The offset of the appended
+  ///        pFrag is set to the offset in pSD.
+  /// @param [in, out] pSD The section data being appended.
+  /// @param [in] pAlignConstraint The alignment constraint.
+  /// @return Total size of the inserted fragments.
+  static uint64_t AppendFragment(Fragment& pFrag, SectionData& pSD,
+                                 uint32_t pAlignConstraint = 1);
+
+private:
+  const LinkerConfig& m_Config;
+  Module& m_Module;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Object/ObjectLinker.h b/include/mcld/Object/ObjectLinker.h
new file mode 100644
index 0000000..4d9f642
--- /dev/null
+++ b/include/mcld/Object/ObjectLinker.h
@@ -0,0 +1,168 @@
+//===- ObjectLinker.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// 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
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <stddef.h>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+class InputBuilder;
+class FragmentLinker;
+class TargetLDBackend;
+class MemoryArea;
+class MemoryAreaFactory;
+class ObjectReader;
+class DynObjReader;
+class ArchiveReader;
+class GroupReader;
+class ObjectWriter;
+class DynObjWriter;
+class ExecWriter;
+
+/** \class ObjectLinker
+ *  \brief ObjectLinker prepares parameters for FragmentLinker.
+ */
+class ObjectLinker
+{
+public:
+  ObjectLinker(const LinkerConfig& pConfig,
+               Module& pModule,
+               InputBuilder& pInputBuilder,
+               TargetLDBackend& pLDBackend);
+
+  ~ObjectLinker();
+
+  /// initFragmentLinker - initialize FragmentLinker
+  ///  Connect all components in FragmentLinker
+  bool initFragmentLinker();
+
+  /// initStdSections - initialize standard sections of the output file.
+  bool initStdSections();
+
+  /// normalize - normalize the input files
+  void normalize();
+
+  /// linkable - check the linkability of current LinkerConfig
+  ///  Check list:
+  ///  - check the Attributes are not violate the constaint
+  ///  - check every Input has a correct Attribute
+  bool linkable() const;
+
+  /// readRelocations - read all relocation entries
+  bool readRelocations();
+
+  /// mergeSections - put allinput sections into output sections
+  bool mergeSections();
+
+  /// addStandardSymbols - shared object and executable files need some
+  /// standard symbols
+  ///   @return if there are some input symbols with the same name to the
+  ///   standard symbols, return false
+  bool addStandardSymbols();
+
+  /// addTargetSymbols - some targets, such as MIPS and ARM, need some
+  /// target-dependent symbols
+  ///   @return if there are some input symbols with the same name to the
+  ///   target symbols, return false
+  bool addTargetSymbols();
+
+  /// scanRelocations - scan all relocation entries by output symbols.
+  bool scanRelocations();
+
+  /// prelayout - help backend to do some modification before layout
+  bool prelayout();
+
+  /// layout - linearly layout all output sections and reserve some space
+  /// for GOT/PLT
+  ///   Because we do not support instruction relaxing in this early version,
+  ///   if there is a branch can not jump to its target, we return false
+  ///   directly
+  bool layout();
+
+  /// postlayout - help backend to do some modification after layout
+  bool postlayout();
+
+  /// relocate - applying relocation entries and create relocation
+  /// section in the output files
+  /// Create relocation section, asking TargetLDBackend to
+  /// read the relocation information into RelocationEntry
+  /// and push_back into the relocation section
+  bool relocation();
+
+  /// finalizeSymbolValue - finalize the symbol value
+  bool finalizeSymbolValue();
+
+  /// emitOutput - emit the output file.
+  bool emitOutput(MemoryArea& 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); }
+
+  // -----  readers and writers  ----- //
+  const ObjectReader*  getObjectReader () const { return m_pObjectReader;  }
+  ObjectReader*        getObjectReader ()       { return m_pObjectReader;  }
+
+  const DynObjReader*  getDynObjReader () const { return m_pDynObjReader;  }
+  DynObjReader*        getDynObjReader ()       { return m_pDynObjReader;  }
+
+  const ArchiveReader* getArchiveReader() const { return m_pArchiveReader; }
+  ArchiveReader*       getArchiveReader()       { return m_pArchiveReader; }
+
+  const GroupReader* getGroupReader() const { return m_pGroupReader; }
+  GroupReader*       getGroupReader()       { return m_pGroupReader; }
+
+  const ObjectWriter*  getObjectWriter () const { return m_pObjectWriter;  }
+  ObjectWriter*        getObjectWriter ()       { return m_pObjectWriter;  }
+
+  const DynObjWriter*  getDynObjWriter () const { return m_pDynObjWriter;  }
+  DynObjWriter*        getDynObjWriter ()       { return m_pDynObjWriter;  }
+
+  const ExecWriter*    getExecWriter   () const { return m_pExecWriter;    }
+  ExecWriter*          getExecWriter   ()       { return m_pExecWriter;    }
+
+private:
+  const LinkerConfig& m_Config;
+  Module& m_Module;
+
+  // we pass in InputBuilder for Archive and GroupReader.
+  InputBuilder& m_InputBuilder; 
+
+  FragmentLinker* m_pLinker;
+  TargetLDBackend &m_LDBackend;
+
+  // -----  readers and writers  ----- //
+  ObjectReader* m_pObjectReader;
+  DynObjReader* m_pDynObjReader;
+  ArchiveReader* m_pArchiveReader;
+  ObjectWriter* m_pObjectWriter;
+  DynObjWriter* m_pDynObjWriter;
+  ExecWriter* m_pExecWriter;
+  GroupReader* m_pGroupReader;
+};
+
+} // end namespace mcld
+#endif
diff --git a/include/mcld/Object/SectionMap.h b/include/mcld/Object/SectionMap.h
new file mode 100644
index 0000000..37df4a3
--- /dev/null
+++ b/include/mcld/Object/SectionMap.h
@@ -0,0 +1,90 @@
+//===- SectionMap.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SECTION_MAP_H
+#define MCLD_SECTION_MAP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+#include <string>
+
+#include <llvm/Support/DataTypes.h>
+
+namespace mcld {
+
+/** \class SectionMap
+ *  \brief descirbe the mappings of input section's name (or prefix) to
+ *         its associated output section's name and offset
+ */
+class SectionMap
+{
+public:
+  // a mapping in SectionMap is the triple of
+  // {input substr, output section's name, output section's offset}
+  struct NamePair
+  {
+  public:
+    NamePair();
+    NamePair(const std::string& pFrom, const std::string& pTo);
+
+    bool isNull() const;
+
+  public:
+    unsigned int hash;
+    std::string from;
+    std::string to;
+  };
+
+  typedef std::vector<NamePair> NamePairList;
+  typedef NamePairList::iterator iterator;
+  typedef NamePairList::const_iterator const_iterator;
+
+  /// NullName - the null object of NamePair
+  static NamePair NullName;
+
+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);
+
+  const NamePair& find(const std::string& pFrom, unsigned int pHash) const;
+  NamePair&       find(const std::string& pFrom, unsigned int pHash);
+
+  // 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 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(); }
+
+  bool           empty() const { return m_NamePairList.empty(); }
+  size_t         size () const { return m_NamePairList.size(); }
+
+  static unsigned int hash(const std::string& pString);
+
+private:
+  bool matched(const NamePair& pNamePair,
+               const std::string& pInput,
+               unsigned int pHash) const;
+private:
+  NamePairList m_NamePairList;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ScriptOptions.h b/include/mcld/ScriptOptions.h
new file mode 100644
index 0000000..e240169
--- /dev/null
+++ b/include/mcld/ScriptOptions.h
@@ -0,0 +1,60 @@
+//===- ScriptOptions.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OPTIONS_H
+#define MCLD_SCRIPT_OPTIONS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <string>
+#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>
+
+namespace mcld {
+
+/** \class ScriptOptions
+ *
+ */
+class ScriptOptions
+{
+public:
+  typedef HashTable<StringEntry<llvm::StringRef>,
+                    StringHash<ELF>,
+                    StringEntryFactory<llvm::StringRef> > SymbolRenameMap;
+
+  typedef HashTable<StringEntry<uint64_t>,
+                    StringHash<ELF>,
+                    StringEntryFactory<uint64_t> > AddressMap;
+
+public:
+  ScriptOptions();
+
+  ~ScriptOptions();
+
+  const SymbolRenameMap& renameMap() const { return m_SymbolRenames; }
+  SymbolRenameMap&       renameMap()       { return m_SymbolRenames; }
+
+  const AddressMap& addressMap() const { return m_AddressMap; }
+  AddressMap&       addressMap()       { return m_AddressMap; }
+
+  const SectionMap& sectionMap() const { return m_SectionMap; }
+  SectionMap&       sectionMap()       { return m_SectionMap; }
+
+private:
+  SymbolRenameMap m_SymbolRenames;
+  AddressMap m_AddressMap;
+  SectionMap m_SectionMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/Allocators.h b/include/mcld/Support/Allocators.h
index de6edec..e651093 100644
--- a/include/mcld/Support/Allocators.h
+++ b/include/mcld/Support/Allocators.h
@@ -6,20 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ALLOCATORS_H
-#define LLVM_ALLOCATORS_H
+#ifndef MCLD_SUPPORT_ALLOCATORS_H
+#define MCLD_SUPPORT_ALLOCATORS_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/ADT/TypeTraits.h"
-#include "mcld/LD/LDContext.h"
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/ADT/TypeTraits.h>
+
 #include <cstddef>
 #include <cstdlib>
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class Chunk
  *  \brief Chunk is the basic unit of the storage of the LinearAllocator
@@ -27,7 +25,7 @@
  *  @see LinearAllocator
  */
 template<typename DataType, size_t ChunkSize>
-struct Chunk
+class Chunk
 {
 public:
   typedef DataType value_type;
@@ -38,6 +36,15 @@
 
   static size_t size() { return ChunkSize; }
 
+  static void construct(value_type* pPtr)
+  { new (pPtr) value_type(); }
+
+  static void construct(value_type* pPtr, const value_type& pValue)
+  { new (pPtr) value_type(pValue); }
+
+  static void destroy(value_type* pPtr)
+  { }
+
 public:
   Chunk* next;
   size_t bound;
@@ -45,7 +52,7 @@
 };
 
 template<typename DataType>
-struct Chunk<DataType, 0>
+class Chunk<DataType, 0>
 {
 public:
   typedef DataType value_type;
@@ -64,9 +71,19 @@
       free(data);
   }
 
-  static size_t size()              { return m_Size; }
+  static size_t size() { return m_Size; }
+
   static void setSize(size_t pSize) { m_Size = pSize; }
 
+  static void construct(value_type* pPtr)
+  { new (pPtr) value_type(); }
+
+  static void construct(value_type* pPtr, const value_type& pValue)
+  { new (pPtr) value_type(pValue); }
+
+  static void destroy(value_type* pPtr)
+  { pPtr->~value_type(); }
+
 public:
   Chunk* next;
   size_t bound;
@@ -117,7 +134,7 @@
   //  @param pPtr the address where the object to be constructed
   //  @param pValue the value to be constructed
   void construct(pointer pPtr, const_reference pValue)
-  { new (pPtr) value_type(pValue); }
+  { chunk_type::construct(pPtr, pValue); }
 
   /// default construct - constructing an object on the location pointed by
   //  pPtr, and using its default constructor to initialized its value to
@@ -125,12 +142,12 @@
   //
   //  @param pPtr the address where the object to be constructed
   void construct(pointer pPtr)
-  { new (pPtr) value_type(); }
+  { chunk_type::construct(pPtr); }
 
   /// standard destroy - destroy data on arbitrary address
   //  @para pPtr the address where the data to be destruected.
   void destroy(pointer pPtr)
-  { pPtr->~value_type(); }
+  { chunk_type::destroy(pPtr); }
 
   /// allocate - allocate N data in order.
   //  - Disallow to allocate a chunk whose size is bigger than a chunk.
@@ -147,8 +164,8 @@
     size_type rest_num_elem = chunk_type::size() - m_pCurrent->bound;
     pointer result = 0;
     if (N > rest_num_elem)
-      createChunk();
-    result = const_cast<pointer>(&(m_pCurrent->data[m_pCurrent->bound]));
+      getNewChunk();
+    result = m_pCurrent->data + m_pCurrent->bound;
     m_pCurrent->bound += N;
     return result;
   }
@@ -160,8 +177,8 @@
 
     pointer result = 0;
     if (chunk_type::size() == m_pCurrent->bound)
-      createChunk();
-    result = const_cast<pointer>(&(m_pCurrent->data[m_pCurrent->bound]));
+      getNewChunk();
+    result = m_pCurrent->data + m_pCurrent->bound;
     ++m_pCurrent->bound;
     return result;
   }
@@ -217,13 +234,10 @@
   void clear() {
     chunk_type *cur = m_pRoot, *prev;
     while (0 != cur) {
-      unsigned int idx=0;
       prev = cur;
       cur = cur->next;
-      while (idx != prev->bound) {
-        destroy(&prev->data[idx]);
-        ++idx;
-      }
+      for (unsigned int idx = 0; idx != prev->bound; ++idx)
+        destroy(prev->data + idx);
       delete prev;
     }
     reset();
@@ -244,7 +258,7 @@
     m_AllocatedNum += chunk_type::size();
   }
 
-  inline chunk_type *createChunk() {
+  inline chunk_type *getNewChunk() {
     chunk_type *result = new chunk_type();
     m_pCurrent->next = result;
     m_pCurrent = result;
diff --git a/include/mcld/Support/DerivedPositionDependentOptions.h b/include/mcld/Support/DerivedPositionDependentOptions.h
deleted file mode 100644
index 2254a5f..0000000
--- a/include/mcld/Support/DerivedPositionDependentOptions.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//===- DerivedPositionDependentOptions.h ----------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_DERIVEDPOSITIONDEPENDENTOPTIONS_H
-#define MCLD_DERIVEDPOSITIONDEPENDENTOPTIONS_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <string>
-
-#include "mcld/Support/RealPath.h"
-#include "mcld/Support/PositionDependentOption.h"
-
-namespace mcld
-{
-
-  /** \class DerivedPositionDependentOptions
-   *  \brief This file contains the declarations of classes derived from PositionDependentOption.
-   */
-
-  class FileOption : public PositionDependentOption {
-  private:
-    sys::fs::RealPath m_Path;
-
-  protected:
-    FileOption(unsigned pPosition, Type pType, const sys::fs::Path &pPath)
-      : PositionDependentOption(pPosition, pType)
-    { m_Path.assign(pPath); }
-
-  public:
-    inline const sys::fs::Path *path() const { return &m_Path; }
-  };
-
-  class NamespecOption : public PositionDependentOption {
-  private:
-    std::string m_pNamespec;
-
-  public:
-    NamespecOption(unsigned pPosition, const std::string &pNamespec)
-      : PositionDependentOption(pPosition, PositionDependentOption::NAMESPEC),
-        m_pNamespec(pNamespec) { }
-
-    inline const std::string &namespec() const { return m_pNamespec; }
-  };
-
-  class BitcodeOption : public FileOption {
-  public:
-    BitcodeOption(unsigned pPosition, const sys::fs::Path &pPath)
-      : FileOption(pPosition, PositionDependentOption::BITCODE, pPath) { }
-  };
-
-  class StartGroupOption : public PositionDependentOption {
-  public:
-    StartGroupOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::START_GROUP) { }
-  };
-
-  class EndGroupOption : public PositionDependentOption {
-  public:
-    EndGroupOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::END_GROUP) { }
-  };
-
-  class InputFileOption : public FileOption {
-  public:
-    InputFileOption(unsigned pPosition, const sys::fs::Path &pPath)
-      : FileOption(pPosition, PositionDependentOption::INPUT_FILE, pPath) { }
-  };
-
-  class WholeArchiveOption : public PositionDependentOption {
-  public:
-    WholeArchiveOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::WHOLE_ARCHIVE) { }
-  };
-
-  class NoWholeArchiveOption : public PositionDependentOption {
-  public:
-    NoWholeArchiveOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::NO_WHOLE_ARCHIVE) { }
-  };
-
-  class AsNeededOption : public PositionDependentOption {
-  public:
-    AsNeededOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::AS_NEEDED) { }
-  };
-
-  class NoAsNeededOption : public PositionDependentOption {
-  public:
-    NoAsNeededOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::NO_AS_NEEDED) { }
-  };
-
-  class AddNeededOption : public PositionDependentOption {
-  public:
-    AddNeededOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::ADD_NEEDED) { }
-  };
-
-  class NoAddNeededOption : public PositionDependentOption {
-  public:
-    NoAddNeededOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::NO_ADD_NEEDED) { }
-  };
-
-  class BDynamicOption : public PositionDependentOption {
-  public:
-    BDynamicOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::BDYNAMIC) { }
-  };
-
-  class BStaticOption : public PositionDependentOption {
-  public:
-    BStaticOption(unsigned pPosition)
-      : PositionDependentOption(pPosition,
-                                PositionDependentOption::BSTATIC) { }
-  };
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/FileHandle.h b/include/mcld/Support/FileHandle.h
index f6881c3..3b4fe81 100644
--- a/include/mcld/Support/FileHandle.h
+++ b/include/mcld/Support/FileHandle.h
@@ -13,10 +13,11 @@
 #endif
 #include <mcld/Support/Path.h>
 #include <mcld/ADT/Flags.h>
+
+#include <sys/stat.h>
 #include <errno.h>
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class FileHandle
  *  \brief FileHandle class provides an interface for reading from and writing
@@ -53,15 +54,16 @@
 
   enum PermissionEnum
   {
-    ReadOwner   = 0x0400,
-    WriteOwner  = 0x0200,
-    ExeOwner    = 0x0100,
-    ReadGroup   = 0x0040,
-    WriteGroup  = 0x0020,
-    ExeGroup    = 0x0010,
-    ReadOther   = 0x0004,
-    WriteOther  = 0x0002,
-    ExeOther    = 0x0001
+    ReadOwner   = S_IRUSR,
+    WriteOwner  = S_IWUSR,
+    ExeOwner    = S_IXUSR,
+    ReadGroup   = S_IRGRP,
+    WriteGroup  = S_IWGRP,
+    ExeGroup    = S_IXGRP,
+    ReadOther   = S_IROTH,
+    WriteOther  = S_IWOTH,
+    ExeOther    = S_IXOTH,
+    System      = 0xFFFFFFFF
   };
 
   typedef Flags<PermissionEnum> Permission;
@@ -71,12 +73,12 @@
 
   ~FileHandle();
 
-  bool open(const sys::fs::Path& pPath,
-            OpenMode pMode);
-
+  /// open - open the file.
+  /// @return if we meet any trouble during opening the file, return false.
+  ///         use rdstate() to see what happens.
   bool open(const sys::fs::Path& pPath,
             OpenMode pMode,
-            Permission pPerm);
+            Permission pPerm = System);
 
   bool delegate(int pFD, OpenMode pMode = Unknown);
 
diff --git a/include/mcld/Support/GCFactoryListTraits.h b/include/mcld/Support/GCFactoryListTraits.h
index 418ec57..8a768c8 100644
--- a/include/mcld/Support/GCFactoryListTraits.h
+++ b/include/mcld/Support/GCFactoryListTraits.h
@@ -25,11 +25,13 @@
  *  the nodes in the list is produced by GCFactory.
  */
 template<typename DataType>
-class GCFactoryListTraits : public llvm::ilist_default_traits<DataType> {
+class GCFactoryListTraits : public llvm::ilist_default_traits<DataType>
+{
 private:
-  class SentinelNode : public llvm::ilist_node<DataType> {
+  class SentinelNode : public DataType
+  {
   public:
-    SentinelNode() : llvm::ilist_node<DataType>() { }
+    SentinelNode() { }
   };
 
 public:
diff --git a/include/mcld/Support/MemoryArea.h b/include/mcld/Support/MemoryArea.h
index 5337f48..a735f62 100644
--- a/include/mcld/Support/MemoryArea.h
+++ b/include/mcld/Support/MemoryArea.h
@@ -6,34 +6,27 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_MEMORY_AREA_H
-#define MCLD_MEMORY_AREA_H
+#ifndef MCLD_SUPPORT_MEMORY_AREA_H
+#define MCLD_SUPPORT_MEMORY_AREA_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 
 #include <mcld/ADT/Uncopyable.h>
-#include <mcld/Support/Path.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/Space.h>
-#include <fcntl.h>
-#include <string>
-#include <list>
-
+#include <cstddef>
+#include <map>
 
 #if defined(ENABLE_UNITTEST)
-namespace mcldtest
-{
+namespace mcldtest {
   class MemoryAreaTest;
 } // namespace of mcldtest
 #endif
 
-namespace mcld
-{
+namespace mcld {
 
+class Space;
+class FileHandle;
 class MemoryRegion;
-class RegionFactory;
 
 /** \class MemoryArea
  *  \brief MemoryArea is used to manage distinct MemoryRegions of address space.
@@ -55,19 +48,16 @@
 {
   friend class MemoryAreaFactory;
 public:
-  typedef llvm::iplist<Space> SpaceList;
-
-public:
   // constructor by file handler.
   // If the given file handler is read-only, client can not request a region
   // that out of the file size.
   // @param pFileHandle - file handler
-  MemoryArea(RegionFactory& pRegionFactory, FileHandle& pFileHandle);
+  explicit MemoryArea(FileHandle& pFileHandle);
 
   // constructor by set universal space.
   // Client can not request a region that out of the universal space.
   // @param pUniverse - file handler
-  MemoryArea(RegionFactory& pRegionFactory, Space& pUniverse);
+  explicit MemoryArea(Space& pUniverse);
 
   // destructor
   ~MemoryArea();
@@ -85,11 +75,10 @@
   // clear - release all memory regions.
   void clear();
 
-  FileHandle* handler()
-  { return m_pFileHandle; }
+  const FileHandle* handler() const { return m_pFileHandle; }
+  FileHandle*       handler()       { return m_pFileHandle; }
 
-  const FileHandle* handler() const
-  { return m_pFileHandle; }
+  bool hasHandler() const { return (NULL != m_pFileHandle); }
 
   // -----  space list methods  ----- //
   Space* find(size_t pOffset, size_t pLength);
@@ -97,8 +86,34 @@
   const Space* find(size_t pOffset, size_t pLength) const;
 
 private:
-  RegionFactory& m_RegionFactory;
-  SpaceList m_SpaceList;
+  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::map<Key, Space*, Key::Compare> SpaceMapType;
+
+private:
+  SpaceMapType m_SpaceMap;
   FileHandle* m_pFileHandle;
 };
 
diff --git a/include/mcld/Support/MemoryAreaFactory.h b/include/mcld/Support/MemoryAreaFactory.h
index be86b8c..b28f096 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_MEMORY_AREA_FACTORY_H
-#define MCLD_MEMORY_AREA_FACTORY_H
+#ifndef MCLD_SUPPORT_MEMORY_AREA_FACTORY_H
+#define MCLD_SUPPORT_MEMORY_AREA_FACTORY_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -20,7 +20,6 @@
 namespace mcld
 {
 
-class RegionFactory;
 /** \class MemoryAreaFactory
  *  \brief MemoryAreaFactory avoids creating duplicated MemoryAreas of the
  *   same file.
@@ -55,19 +54,18 @@
                       FileHandle::OpenMode pMode,
                       FileHandle::Permission pPerm);
 
-  void destruct(MemoryArea* pArea);
-
-protected:
   // Create a MemoryArea with an universal space.
   // The created MemoryArea is not moderated by m_HandleToArea.
-  MemoryArea* create(void* pMemBuffer, size_t pSize);
+  MemoryArea* produce(void* pMemBuffer, size_t pSize);
 
   // Create a MemoryArea by the given file handler
-  MemoryArea* create(int pFD, FileHandle::OpenMode pMode);
+  // The created MemoryArea is not moderated by m_HandleToArea.
+  MemoryArea* produce(int pFD, FileHandle::OpenMode pMode);
+
+  void destruct(MemoryArea* pArea);
 
 private:
   HandleToArea m_HandleToArea;
-  RegionFactory* m_pRegionFactory;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Support/MemoryRegion.h b/include/mcld/Support/MemoryRegion.h
index caa929f..0984873 100644
--- a/include/mcld/Support/MemoryRegion.h
+++ b/include/mcld/Support/MemoryRegion.h
@@ -12,13 +12,14 @@
 #include <gtest.h>
 #endif
 
+#include <mcld/Config/Config.h>
 #include <mcld/ADT/Uncopyable.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/Allocators.h>
 #include <mcld/Support/Space.h>
 
-namespace mcld
-{
+namespace mcld {
+
+class MemoryArea;
 
 /** \class MemoryRegion
  *  \brief MemoryRegion is a range of virtual memory which is mapped onto a
@@ -35,6 +36,7 @@
  */
 class MemoryRegion : private Uncopyable
 {
+friend class Chunk<MemoryRegion, MCLD_REGION_CHUNK_SIZE>;
 friend class RegionFactory;
 friend class MemoryArea;
 
@@ -43,40 +45,68 @@
   typedef Space::ConstAddress ConstAddress;
 
 private:
-  MemoryRegion(Space& pParent, const Address pVMAStart, size_t pSize);
+  MemoryRegion();
 
-  Space* parent()
-  { return &m_Parent; }
+  MemoryRegion(const Address pVMAStart, size_t pSize);
 
-  const Space* parent() const
-  { return &m_Parent; }
-
-public:
   ~MemoryRegion();
 
-  Address start()
-  { return m_VMAStart; }
+  void setParent(Space& pSpace) { m_pParent = &pSpace; }
 
-  ConstAddress start() const
-  { return m_VMAStart; }
+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);
 
-  Address end()
-  { return m_VMAStart+m_Length; }
+  /// 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);
 
-  ConstAddress end() const
-  { return m_VMAStart+m_Length; }
+  /// 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);
 
-  size_t size() const
-  { return m_Length; }
+  const Space* parent() const { return m_pParent; }
+  Space*       parent()       { return m_pParent; }
 
-  Address getBuffer(size_t pOffset = 0)
-  { return m_VMAStart+pOffset; }
+  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_Parent;
+  Space* m_pParent;
   Address m_VMAStart;
   size_t m_Length;
 };
diff --git a/include/mcld/Support/MsgHandling.h b/include/mcld/Support/MsgHandling.h
index a42bb54..d00132c 100644
--- a/include/mcld/Support/MsgHandling.h
+++ b/include/mcld/Support/MsgHandling.h
@@ -13,16 +13,18 @@
 #endif
 #include <mcld/LD/MsgHandler.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class MCLDInfo;
+class LinkerConfig;
 class DiagnosticPrinter;
 class DiagnosticLineInfo;
 
-void InitializeDiagnosticEngine(const MCLDInfo& pLDInfo,
-                                DiagnosticLineInfo* pLineInfo,
-                                DiagnosticPrinter* pPrinter);
+void InitializeDiagnosticEngine(const LinkerConfig& pConfig,
+                                DiagnosticPrinter* pPrinter = NULL);
+
+void FinalizeDiagnosticEngine();
+
+bool Diagnose();
 
 DiagnosticEngine& getDiagnosticEngine();
 
@@ -38,6 +40,7 @@
 
 //===----------------------------------------------------------------------===//
 //  Inline functions
+//===----------------------------------------------------------------------===//
 inline mcld::MsgHandler mcld::unreachable(unsigned int pID)
 {
   return getDiagnosticEngine().report(pID, DiagnosticEngine::Unreachable);
diff --git a/include/mcld/Support/Path.h b/include/mcld/Support/Path.h
index de49d3e..b53cd1a 100644
--- a/include/mcld/Support/Path.h
+++ b/include/mcld/Support/Path.h
@@ -89,6 +89,7 @@
 
   // -----  decomposition  ----- //
   Path parent_path() const;
+  Path filename() const;
   Path stem() const;
   Path extension() const;
 
diff --git a/include/mcld/Support/PositionDependentOption.h b/include/mcld/Support/PositionDependentOption.h
deleted file mode 100644
index 8dd969d..0000000
--- a/include/mcld/Support/PositionDependentOption.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//===- PositionDependentOption.h ------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_POSITIONDEPENDENTOPTION_H
-#define MCLD_POSITIONDEPENDENTOPTION_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <vector>
-
-namespace mcld
-{
-
-  /** \class PositionDependentOption
-   *  \brief PositionDependentOptions converts LLVM options into MCLDInfo
-   */
-  class PositionDependentOption
-  {
-  public:
-    enum Type {
-      BITCODE,
-      NAMESPEC,
-      INPUT_FILE,
-      START_GROUP,
-      END_GROUP,
-      WHOLE_ARCHIVE,
-      NO_WHOLE_ARCHIVE,
-      AS_NEEDED,
-      NO_AS_NEEDED,
-      ADD_NEEDED,
-      NO_ADD_NEEDED,
-      BDYNAMIC,
-      BSTATIC
-    };
-
-  protected:
-    PositionDependentOption(unsigned int pPosition, Type pType)
-      : m_Type(pType),
-        m_Position(pPosition) {}
-
-  public:
-    Type type()
-    { return m_Type; }
-
-    Type type() const
-    { return m_Type; }
-
-    unsigned int position()
-    { return m_Position; }
-
-    unsigned int position() const
-    { return m_Position; }
-
-  private:
-    Type m_Type;
-    unsigned int m_Position;
-  };
-
-  typedef std::vector<PositionDependentOption*> PositionDependentOptions;
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/RegionFactory.h b/include/mcld/Support/RegionFactory.h
index 8893500..fd90186 100644
--- a/include/mcld/Support/RegionFactory.h
+++ b/include/mcld/Support/RegionFactory.h
@@ -6,18 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_REGION_FACTORY_H
-#define MCLD_REGION_FACTORY_H
+#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>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/FileSystem.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class MemoryArea;
 
@@ -25,17 +23,15 @@
  *  \brief RegionFactory produces and destroys MemoryRegions
  *
  */
-class RegionFactory : public GCFactory<MemoryRegion, 0>
+class RegionFactory : public GCFactory<MemoryRegion, MCLD_REGION_CHUNK_SIZE>
 {
 public:
-  typedef GCFactory<MemoryRegion, 0> Alloc;
+  typedef GCFactory<MemoryRegion, MCLD_REGION_CHUNK_SIZE> Alloc;
+  typedef MemoryRegion::Address Address;
+  typedef MemoryRegion::ConstAddress ConstAddress;
 
 public:
-  RegionFactory(size_t pNum);
-  ~RegionFactory();
-
-  // ----- production ----- //
-  MemoryRegion* produce(Space& pSpace, void* pVMAStart, size_t pSize);
+  MemoryRegion* produce(Address pVMAStart, size_t pSize);
 
   void destruct(MemoryRegion* pRegion);
 };
diff --git a/include/mcld/Support/Space.h b/include/mcld/Support/Space.h
index 7ebedce..cdf69b0 100644
--- a/include/mcld/Support/Space.h
+++ b/include/mcld/Support/Space.h
@@ -12,12 +12,9 @@
 #include <gtest.h>
 #endif
 #include <llvm/Support/DataTypes.h>
-#include <llvm/ADT/ilist.h>
-#include <llvm/ADT/ilist_node.h>
 #include <mcld/ADT/TypeTraits.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class FileHandle;
 class MemoryRegion;
@@ -27,7 +24,7 @@
  *  the other Space.
  *
  */
-class Space : public llvm::ilist_node<Space>
+class Space
 {
 public:
   enum Type
@@ -41,20 +38,13 @@
   typedef NonConstTraits<uint8_t>::pointer Address;
   typedef ConstTraits<uint8_t>::pointer ConstAddress;
 
-// llvm::iplist functions
-public:
-  // llvm::iplist needs default constructor to make a sentinel.
-  // Normal users should use @ref Space::createSpace function.
+private:
   Space();
 
-  // llvm::iplist needs public destructor to delete the sentinel.
-  // Normal users should use @ref Space::releaseSpace function.
   ~Space();
 
-  // This constructor is opened for the clients who want to control the
-  // details. In MCLinker, this constructor is used no where.
   Space(Type pType, void* pMemBuffer, size_t pSize);
-  
+
 public:
   void setStart(size_t pOffset)
   { m_StartOffset = pOffset; }
@@ -83,12 +73,17 @@
   size_t numOfRegions() const
   { return m_RegionCount; }
 
-  static Space* createSpace(FileHandle& pHandler,
-                            size_t pOffset, size_t pSize);
-  
-  static void releaseSpace(Space* pSpace, FileHandle& pHandler);
+  /// Create - Create a Space from external memory
+  static Space* Create(void* pMemBuffer, size_t pSize);
 
-  static void syncSpace(Space* pSpace, FileHandle& pHandler);
+  /// 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;
diff --git a/include/mcld/Support/TargetRegistry.h b/include/mcld/Support/TargetRegistry.h
index 8d0fee8..560a61e 100644
--- a/include/mcld/Support/TargetRegistry.h
+++ b/include/mcld/Support/TargetRegistry.h
@@ -20,10 +20,13 @@
 } // namespace of llvm
 
 namespace mcld {
-class LLVMTargetMachine;
+
+class Module;
+class LinkerConfig;
+class MemoryArea;
+class MCLDTargetMachine;
 class TargetRegistry;
-class SectLinker;
-class SectLinkerOption;
+class MCLinker;
 class TargetLDBackend;
 class AttributeFactory;
 class InputFactory;
@@ -32,22 +35,25 @@
 
 //===----------------------------------------------------------------------===//
 /// Target - mcld::Target is an object adapter of llvm::Target
-///
+//===----------------------------------------------------------------------===//
 class Target
 {
-  friend class mcld::LLVMTargetMachine;
+  friend class mcld::MCLDTargetMachine;
   friend class mcld::TargetRegistry;
 public:
-  typedef mcld::LLVMTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &,
+  typedef mcld::MCLDTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &,
                                                           llvm::TargetMachine &,
                                                           const std::string&);
 
-  typedef SectLinker *(*SectLinkerCtorTy)(const std::string& pTriple,
-                                          SectLinkerOption &,
-                                          TargetLDBackend&);
+  typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple,
+                                      LinkerConfig&,
+                                      Module&,
+                                      MemoryArea& pOutput);
+
+  typedef bool (*EmulationFnTy)(const std::string& pTriple, LinkerConfig&);
 
   typedef TargetLDBackend  *(*TargetLDBackendCtorTy)(const llvm::Target&,
-                                                     const std::string&);
+                                                     const LinkerConfig&);
 
   typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&,
                                                           const std::string&);
@@ -58,7 +64,7 @@
   void setTarget(const llvm::Target& pTarget)
   { m_pT = &pTarget; }
 
-  mcld::LLVMTargetMachine *createTargetMachine(const std::string &pTriple,
+  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,
@@ -73,27 +79,34 @@
     return NULL;
   }
 
-  /// createSectLinker - create target-specific SectLinker
+  /// createMCLinker - create target-specific MCLinker
   ///
-  /// @return created SectLinker
-  SectLinker *createSectLinker(const std::string &pTriple,
-                               SectLinkerOption &pOption,
-                               TargetLDBackend &pLDBackend) const {
-    if (!SectLinkerCtorFn)
+  /// @return created MCLinker
+  MCLinker *createMCLinker(const std::string &pTriple,
+                           LinkerConfig& pConfig,
+                           Module& pModule,
+                           MemoryArea& pOutput) const {
+    if (!MCLinkerCtorFn)
       return NULL;
-    return SectLinkerCtorFn(pTriple,
-                            pOption,
-                            pLDBackend);
+    return MCLinkerCtorFn(pTriple, pConfig, pModule, pOutput);
+  }
+
+  /// emulate - given MCLinker default values for the other aspects of the
+  /// target system.
+  bool emulate(const std::string& pTriple, LinkerConfig& pConfig) const {
+    if (!EmulationFn)
+      return false;
+    return EmulationFn(pTriple, pConfig);
   }
 
   /// createLDBackend - create target-specific LDBackend
   ///
   /// @return created TargetLDBackend
-  TargetLDBackend* createLDBackend(const std::string& Triple) const
+  TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const
   {
     if (!TargetLDBackendCtorFn)
       return NULL;
-    return TargetLDBackendCtorFn(*get(), Triple);
+    return TargetLDBackendCtorFn(*get(), pConfig);
   }
 
   /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
@@ -105,13 +118,13 @@
     return DiagnosticLineInfoCtorFn(pTarget, pTriple);
   }
 
-  const llvm::Target* get() const
-  { return m_pT; }
+  const llvm::Target* get() const { return m_pT; }
 
 private:
   // -----  function pointers  ----- //
   TargetMachineCtorTy TargetMachineCtorFn;
-  SectLinkerCtorTy SectLinkerCtorFn;
+  MCLinkerCtorTy MCLinkerCtorFn;
+  EmulationFnTy EmulationFn;
   TargetLDBackendCtorTy TargetLDBackendCtorFn;
   DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn;
 
@@ -161,15 +174,26 @@
       T.TargetMachineCtorFn = Fn;
   }
 
-  /// RegisterSectLinker - Register a SectLinker implementation for the given
+  /// RegisterMCLinker - Register a MCLinker implementation for the given
   /// target.
   ///
   /// @param T - the target being registered
-  /// @param Fn - A function to create SectLinker for the target
-  static void RegisterSectLinker(mcld::Target &T, mcld::Target::SectLinkerCtorTy Fn)
+  /// @param Fn - A function to create MCLinker for the target
+  static void RegisterMCLinker(mcld::Target &T, mcld::Target::MCLinkerCtorTy Fn)
   {
-    if (!T.SectLinkerCtorFn)
-      T.SectLinkerCtorFn = Fn;
+    if (!T.MCLinkerCtorFn)
+      T.MCLinkerCtorFn = Fn;
+  }
+
+  /// RegisterEmulation - Register a emulation function for the target.
+  /// target.
+  ///
+  /// @param T - the target being registered
+  /// @param Fn - A emulation function
+  static void RegisterEmulation(mcld::Target &T, mcld::Target::EmulationFnTy Fn)
+  {
+    if (!T.EmulationFn)
+      T.EmulationFn = Fn;
   }
 
   /// RegisterTargetLDBackend - Register a TargetLDBackend implementation for
@@ -214,7 +238,7 @@
 ///
 /// Target TheFooTarget; // The global target instance.
 ///
-/// extern "C" void LLVMInitializeFooTargetInfo() {
+/// extern "C" void MCLDInitializeFooTargetInfo() {
 ///   RegisterTarget X(TheFooTarget, "foo", "Foo description");
 /// }
 struct RegisterTarget
@@ -226,7 +250,9 @@
       if( 0==strcmp(TIter->getName(), Name) )
         break;
     }
-    T.setTarget(*TIter);
+
+    if (TIter != TEnd)
+      T.setTarget(*TIter);
 
     TargetRegistry::RegisterTarget(T);
   }
@@ -236,7 +262,7 @@
 /// implementation, for use in the target machine initialization
 /// function. Usage:
 ///
-/// extern "C" void LLVMInitializeFooTarget() {
+/// extern "C" void MCLDInitializeFooTarget() {
 ///   extern mcld::Target TheFooTarget;
 ///   RegisterTargetMachine<mcld::FooTargetMachine> X(TheFooTarget);
 /// }
@@ -248,7 +274,7 @@
   }
 
 private:
-  static mcld::LLVMTargetMachine *Allocator(const mcld::Target &T,
+  static mcld::MCLDTargetMachine *Allocator(const mcld::Target &T,
                                             llvm::TargetMachine& TM,
                                             const std::string &Triple) {
     return new TargetMachineImpl(TM, T, Triple);
diff --git a/include/mcld/Support/TargetSelect.h b/include/mcld/Support/TargetSelect.h
index 0788d1d..7fcb74a 100644
--- a/include/mcld/Support/TargetSelect.h
+++ b/include/mcld/Support/TargetSelect.h
@@ -14,27 +14,31 @@
 
 extern "C" {
   // Declare all of the target-initialization functions that are available.
-#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##LDTargetInfo();
+#define MCLD_TARGET(TargetName) void MCLDInitialize##TargetName##LDTargetInfo();
 #include "mcld/Config/Targets.def"
 
   // Declare all of the target-dependent functions that are available.
-#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##LDTarget();
+#define MCLD_TARGET(TargetName) void MCLDInitialize##TargetName##LDTarget();
 #include "mcld/Config/Targets.def"
 
   // Declare all of the target-depedent linker information
-#define LLVM_LINKER(TargetName) void LLVMInitialize##TargetName##LDInfo();
+#define MCLD_LINKER(TargetName) void MCLDInitialize##TargetName##LDInfo();
 #include "mcld/Config/Linkers.def"
 
   // Declare all of the available linker environment.
-#define LLVM_LINKER(TargetName) void LLVMInitialize##TargetName##SectLinker();
+#define MCLD_LINKER(TargetName) void MCLDInitialize##TargetName##MCLinker();
 #include "mcld/Config/Linkers.def"
 
+  // Declare all of the available emulators.
+#define MCLD_TARGET(TargetName) void MCLDInitialize##TargetName##Emulation();
+#include "mcld/Config/Targets.def"
+
   // Declare all of the available target-specific linker
-#define LLVM_LINKER(TargetName) void LLVMInitialize##TargetName##LDBackend();
+#define MCLD_LINKER(TargetName) void MCLDInitialize##TargetName##LDBackend();
 #include "mcld/Config/Linkers.def"
 
   // Declare all of the available target-specific diagnostic line infomation
-#define LLVM_LINKER(TargetName) void LLVMInitialize##TargetName##DiagnosticLineInfo();
+#define MCLD_LINKER(TargetName) void MCLDInitialize##TargetName##DiagnosticLineInfo();
 #include "mcld/Config/Linkers.def"
 
 } // extern "C"
@@ -42,37 +46,45 @@
 namespace mcld
 {
   /// InitializeAllTargetInfos - The main program should call this function if
-  /// it wants access to all available targets that LLVM is configured to
+  /// it wants access to all available targets that MCLD is configured to
   /// support, to make them available via the TargetRegistry.
   ///
   /// It is legal for a client to make multiple calls to this function.
   inline void InitializeAllTargetInfos() {
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##LDTargetInfo();
+#define MCLD_TARGET(TargetName) MCLDInitialize##TargetName##LDTargetInfo();
 #include "mcld/Config/Targets.def"
   }
 
   /// InitializeAllTargets - The main program should call this function if it
-  /// wants access to all available target machines that LLVM is configured to
+  /// wants access to all available target machines that MCLD is configured to
   /// support, to make them available via the TargetRegistry.
   ///
   /// It is legal for a client to make multiple calls to this function.
   inline void InitializeAllTargets() {
     mcld::InitializeAllTargetInfos();
 
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##LDTarget();
+#define MCLD_TARGET(TargetName) MCLDInitialize##TargetName##LDBackend();
 #include "mcld/Config/Targets.def"
+  }
 
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##LDBackend();
+  /// InitializeAllEmulations - The main program should call this function if
+  /// it wants all emulations to be configured to support. This function makes
+  /// all emulations available via the TargetRegistry.
+  inline void InitializeAllEmulations() {
+#define MCLD_TARGET(TargetName) MCLDInitialize##TargetName##Emulation();
 #include "mcld/Config/Targets.def"
   }
 
   /// InitializeAllLinkers - The main program should call this function if it
-  /// wants all linkers that LLVM is configured to support, to make them
+  /// wants all linkers that is configured to support, to make them
   /// available via the TargetRegistry.
   ///
   /// It is legal for a client to make multiple calls to this function.
   inline void InitializeAllLinkers() {
-#define LLVM_LINKER(TargetName) LLVMInitialize##TargetName##SectLinker();
+#define MCLD_TARGET(TargetName) MCLDInitialize##TargetName##LDTarget();
+#include "mcld/Config/Targets.def"
+
+#define MCLD_LINKER(TargetName) MCLDInitialize##TargetName##MCLinker();
 #include "mcld/Config/Linkers.def"
   }
 
@@ -80,7 +92,7 @@
   /// wants to print linker-specific messages. To make them available via the
   /// TargetRegistry.
   inline void InitializeAllDiagnostics() {
-#define LLVM_LINKER(TargetName)  LLVMInitialize##TargetName##DiagnosticLineInfo();
+#define MCLD_LINKER(TargetName)  MCLDInitialize##TargetName##DiagnosticLineInfo();
 #include "mcld/Config/Linkers.def"
   }
 
diff --git a/include/mcld/Support/ToolOutputFile.h b/include/mcld/Support/ToolOutputFile.h
new file mode 100644
index 0000000..e0e8752
--- /dev/null
+++ b/include/mcld/Support/ToolOutputFile.h
@@ -0,0 +1,85 @@
+//===- ToolOutputFile.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SUPPORT_TOOL_OUTPUT_FILE_H
+#define MCLD_SUPPORT_TOOL_OUTPUT_FILE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+#include <mcld/Support/FileHandle.h>
+
+namespace llvm {
+class formatted_raw_ostream;
+} // end of namespace llvm
+
+namespace mcld {
+
+class Path;
+class FileHandle;
+class MemoryArea;
+class raw_mem_ostream;
+
+/** \class ToolOutputFile
+ *  \brief ToolOutputFile contains a raw_mem_ostream and adds extra new
+ *  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().
+ */
+class ToolOutputFile
+{
+public:
+  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();
+
+  /// 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();
+
+private:
+  class CleanupInstaller
+  {
+  public:
+    explicit CleanupInstaller(const std::string& pFilename);
+
+    ~CleanupInstaller();
+
+    /// Keep - The flag which indicates whether we should not delete the file.
+    bool Keep;
+
+  private:
+    std::string m_Filename;
+  }; 
+
+private:
+  FileHandle m_FileHandle;
+  CleanupInstaller m_Installer;
+  MemoryArea* m_pMemoryArea;
+  raw_mem_ostream* m_pOStream;
+  llvm::formatted_raw_ostream* m_pFOStream;
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/raw_mem_ostream.h b/include/mcld/Support/raw_mem_ostream.h
new file mode 100644
index 0000000..b2db64a
--- /dev/null
+++ b/include/mcld/Support/raw_mem_ostream.h
@@ -0,0 +1,51 @@
+//===- 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 61706de..9b52578 100644
--- a/include/mcld/Support/raw_ostream.h
+++ b/include/mcld/Support/raw_ostream.h
@@ -13,10 +13,8 @@
 #endif
 #include <string>
 #include <llvm/Support/raw_ostream.h>
-#include <mcld/MC/MCLDInfo.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class raw_fd_ostream : public llvm::raw_fd_ostream
 {
@@ -33,18 +31,15 @@
   /// output errors).
   raw_fd_ostream(const char *pFilename,
                  std::string &pErrorInfo,
-                 unsigned int pFlags = 0,
-                 const MCLDInfo* pLDInfo = NULL);
+                 unsigned int pFlags = 0);
 
   /// raw_fd_ostream ctor - FD is the file descriptor that this writes to.  If
   /// ShouldClose is true, this closes the file when the stream is destroyed.
-  raw_fd_ostream(int pFD, bool pShouldClose,
-                 bool pUnbuffered=false,
-                 const MCLDInfo* pLDInfo = NULL);
+  raw_fd_ostream(int pFD, bool pShouldClose, bool pUnbuffered=false);
 
   virtual ~raw_fd_ostream();
 
-  void setLDInfo(const MCLDInfo& pLDInfo);
+  void setColor(bool pEnable = true);
 
 
   llvm::raw_ostream &changeColor(enum llvm::raw_ostream::Colors pColors,
@@ -53,20 +48,16 @@
 
   llvm::raw_ostream &resetColor();
 
-  // FIXME: migrate to newer LLVM
-  // llvm::raw_ostream &reverseColor();
+  llvm::raw_ostream &reverseColor();
 
   bool is_displayed() const;
 
 private:
-  const MCLDInfo* m_pLDInfo;
+  bool m_bConfigColor : 1;
+  bool m_bSetColor : 1;
 
 };
 
-/// InitializeOStreams - This initialize mcld::outs() and mcld::errs().
-/// Call it before you use mcld::outs() and mcld::errs().
-void InitializeOStreams(const MCLDInfo& pLDInfo);
-
 /// outs() - This returns a reference to a raw_ostream for standard output.
 /// Use it like: outs() << "foo" << "bar";
 mcld::raw_fd_ostream &outs();
diff --git a/include/mcld/Target/ELFDynamic.h b/include/mcld/Target/ELFDynamic.h
index ed18dc0..2298bfd 100644
--- a/include/mcld/Target/ELFDynamic.h
+++ b/include/mcld/Target/ELFDynamic.h
@@ -22,7 +22,7 @@
 
 class GNULDBackend;
 class ELFFileFormat;
-class MCLDInfo;
+class LinkerConfig;
 class MemoryRegion;
 
 namespace elf_dynamic {
@@ -37,7 +37,7 @@
   EntryIF();
 
 public:
-  virtual ~EntryIF(); 
+  virtual ~EntryIF();
 
   virtual EntryIF* clone() const = 0;
   virtual size_t size() const = 0;
@@ -87,7 +87,7 @@
 
 private:
   Pair m_Pair;
-}; 
+};
 
 #include "ELFDynamic.tcc"
 
@@ -116,14 +116,14 @@
   size_t numOfBytes() const;
 
   /// reserveEntries - reserve entries
-  void reserveEntries(const MCLDInfo& pInfo,
+  void reserveEntries(const LinkerConfig& pConfig,
                       const ELFFileFormat& pFormat);
 
   /// reserveNeedEntry - reserve on DT_NEED entry.
   void reserveNeedEntry();
-  
+
   /// applyEntries - apply entries
-  void applyEntries(const MCLDInfo& pInfo,
+  void applyEntries(const LinkerConfig& pConfig,
                     const ELFFileFormat& pFormat);
 
   void applySoname(uint64_t pStrTabIdx);
@@ -161,6 +161,7 @@
   EntryListType m_EntryList;
   EntryListType m_NeedList;
   elf_dynamic::EntryIF* m_pEntryFactory;
+  const GNULDBackend& m_Backend;
 
   // The entry reserved and the entry being applied are not must matched.
   // For better performance, we use a simple counter and apply entry one-by-one
diff --git a/include/mcld/Target/Stub.h b/include/mcld/Target/ELFEmulation.h
similarity index 60%
rename from include/mcld/Target/Stub.h
rename to include/mcld/Target/ELFEmulation.h
index 3bc778f..341b2e8 100644
--- a/include/mcld/Target/Stub.h
+++ b/include/mcld/Target/ELFEmulation.h
@@ -1,4 +1,4 @@
-//===- Stub.h -------------------------------------------------------------===//
+//===- ELFEmulation.h -----------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,23 +6,17 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef LD_STUB_H
-#define LD_STUB_H
+#ifndef MCLD_ELF_EMULATION_H
+#define MCLD_ELF_EMULATION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include "mcld/LD/Relocation.h"
 
-namespace mcld
-{
+namespace mcld {
 
-/** \class Stub
- *  \brief Stub is a piece of jumpping code.
- */
-class Stub
-{
+class LinkerConfig;
 
-};
+bool MCLDEmulateELF(LinkerConfig& pConfig);
 
 } // namespace of mcld
 
diff --git a/include/mcld/Target/ELFSectLinker.h b/include/mcld/Target/ELFMCLinker.h
similarity index 60%
rename from include/mcld/Target/ELFSectLinker.h
rename to include/mcld/Target/ELFMCLinker.h
index 04234a8..76f46e8 100644
--- a/include/mcld/Target/ELFSectLinker.h
+++ b/include/mcld/Target/ELFMCLinker.h
@@ -1,4 +1,4 @@
-//===- ELFSectLinker.h ----------------------------------------------------===//
+//===- ELFMCLinker.h ------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// ELFSectLinker is a customized linker pass for ELF platform.
+// ELFMCLinker is a customized linker pass for ELF platform.
 // This pass set up default parameters for ELF.
 //
 //===----------------------------------------------------------------------===//
@@ -16,18 +16,21 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include <mcld/CodeGen/SectLinker.h>
+#include <mcld/CodeGen/MCLinker.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class ELFSectLinker : public SectLinker
+class Module;
+class Output;
+
+class ELFMCLinker : public MCLinker
 {
 public:
-  ELFSectLinker(SectLinkerOption &pOption,
-                mcld::TargetLDBackend &pLDBackend);
+  ELFMCLinker(LinkerConfig& pConfig,
+              mcld::Module& pModule,
+              MemoryArea& pOutput);
 
-  virtual ~ELFSectLinker();
+  virtual ~ELFMCLinker();
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Target/GNULDBackend.h b/include/mcld/Target/GNULDBackend.h
index d05fe72..4623e33 100644
--- a/include/mcld/Target/GNULDBackend.h
+++ b/include/mcld/Target/GNULDBackend.h
@@ -11,46 +11,36 @@
 #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/EhFrameHdr.h>
 #include <mcld/LD/ELFDynObjFileFormat.h>
+#include <mcld/LD/ELFExecFileFormat.h>
+#include <mcld/LD/ELFObjectFileFormat.h>
+#include <mcld/LD/GNUArchiveReader.h>
+#include <mcld/LD/ELFObjectReader.h>
 #include <mcld/LD/ELFDynObjReader.h>
 #include <mcld/LD/ELFDynObjWriter.h>
-#include <mcld/LD/ELFExecFileFormat.h>
 #include <mcld/LD/ELFExecWriter.h>
-#include <mcld/LD/ELFObjectReader.h>
 #include <mcld/LD/ELFObjectWriter.h>
 #include <mcld/LD/ELFSegment.h>
 #include <mcld/LD/ELFSegmentFactory.h>
-#include <mcld/LD/GNUArchiveReader.h>
-#include <mcld/Support/GCFactory.h>
 #include <mcld/Target/ELFDynamic.h>
-#include <mcld/Target/TargetLDBackend.h>
 
-namespace mcld
-{
+#include <mcld/Support/GCFactory.h>
+#include <mcld/Module.h>
 
-struct SymCompare
-{
-  bool operator()(const LDSymbol* X, const LDSymbol* Y) const
-  { return (X==Y); }
-};
+namespace mcld {
 
-struct PtrHash
-{
-  size_t operator()(const LDSymbol* pKey) const
-  {
-    return (unsigned((uintptr_t)pKey) >> 4) ^
-           (unsigned((uintptr_t)pKey) >> 9);
-  }
-};
-
-class MCLDInfo;
+class Module;
+class LinkerConfig;
 class Layout;
-class SymbolCategory;
+class EhFrame;
+class EhFrameHdr;
+class BranchIslandFactory;
+class StubFactory;
 
 /** \class GNULDBackend
  *  \brief GNULDBackend provides a common interface for all GNU Unix-OS
@@ -59,82 +49,54 @@
 class GNULDBackend : public TargetLDBackend
 {
 protected:
-  GNULDBackend();
+  GNULDBackend(const LinkerConfig& pConfig);
 
 public:
   virtual ~GNULDBackend();
 
   // -----  readers/writers  ----- //
-  bool initArchiveReader(MCLinker& pLinker,
-                         MCLDInfo& pInfo,
-                         MemoryAreaFactory& pMemAreaFactory);
-  bool initObjectReader(MCLinker& pLinker);
-  bool initDynObjReader(MCLinker& pLinker);
-  bool initObjectWriter(MCLinker& pLinker);
-  bool initDynObjWriter(MCLinker& pLinker);
-  bool initExecWriter(MCLinker& pLinker);
-
-  GNUArchiveReader *getArchiveReader();
-  const GNUArchiveReader *getArchiveReader() const;
-
-  ELFObjectReader *getObjectReader();
-  const ELFObjectReader *getObjectReader() const;
-
-  ELFDynObjReader *getDynObjReader();
-  const ELFDynObjReader *getDynObjReader() const;
-
-  ELFObjectWriter *getObjectWriter();
-  const ELFObjectWriter *getObjectWriter() const;
-
-  ELFDynObjWriter *getDynObjWriter();
-  const ELFDynObjWriter *getDynObjWriter() const;
-
-  ELFExecWriter *getExecWriter();
-  const ELFExecWriter *getExecWriter() const;
+  GNUArchiveReader* createArchiveReader(Module& pModule);
+  ELFObjectReader* createObjectReader(FragmentLinker& pLinker);
+  ELFDynObjReader* createDynObjReader(FragmentLinker& pLinker);
+  ELFObjectWriter* createObjectWriter(FragmentLinker& pLinker);
+  ELFDynObjWriter* createDynObjWriter(FragmentLinker& pLinker);
+  ELFExecWriter*   createExecWriter(FragmentLinker& pLinker);
 
   // -----  output sections  ----- //
-  /// initExecSections - initialize sections of the output executable file.
-  bool initExecSections(MCLinker& pMCLinker);
-
-  /// initDynObjSections - initialize sections of the output shared object.
-  bool initDynObjSections(MCLinker& pMCLinker);
+  /// initStdSections - initialize standard sections of the output file.
+  bool initStdSections(ObjectBuilder& pBuilder);
 
   /// getOutputFormat - get the sections of the output file.
-  ELFFileFormat* getOutputFormat(const Output& pOutput);
-  const ELFFileFormat* getOutputFormat(const Output& pOutput) const;
-
-  ELFDynObjFileFormat* getDynObjFileFormat();
-  const ELFDynObjFileFormat* getDynObjFileFormat() const;
-
-  ELFExecFileFormat* getExecFileFormat();
-  const ELFExecFileFormat* getExecFileFormat() const;
+  const ELFFileFormat* getOutputFormat() const;
+  ELFFileFormat*       getOutputFormat();
 
   // -----  target symbols ----- //
   /// initStandardSymbols - initialize standard symbols.
   /// Some section symbols is undefined in input object, and linkers must set
   /// up its value. Take __init_array_begin for example. This symbol is an
-  /// undefined symbol in input objects. MCLinker must finalize its value
+  /// undefined symbol in input objects. FragmentLinker must finalize its value
   /// to the begin of the .init_array section, then relocation enties to
   /// __init_array_begin can be applied without emission of "undefined
   /// reference to `__init_array_begin'".
-  bool initStandardSymbols(MCLinker& pLinker, const Output& pOutput);
+  bool initStandardSymbols(FragmentLinker& pLinker, Module& pModule);
 
   /// finalizeSymbol - Linker checks pSymbol.reserved() if it's not zero,
   /// then it will ask backend to finalize the symbol value.
   /// @return ture - if backend set the symbol value sucessfully
   /// @return false - if backend do not recognize the symbol
-  bool finalizeSymbols(MCLinker& pLinker, const Output& pOutput) {
-    return (finalizeStandardSymbols(pLinker, pOutput) &&
-            finalizeTargetSymbols(pLinker, pOutput));
+  bool finalizeSymbols(FragmentLinker& pLinker) {
+    return (finalizeStandardSymbols(pLinker) &&
+            finalizeTargetSymbols(pLinker));
   }
 
   /// finalizeStandardSymbols - set the value of standard symbols
-  virtual bool finalizeStandardSymbols(MCLinker& pLinker,
-                                       const Output& pOutput);
+  virtual bool finalizeStandardSymbols(FragmentLinker& pLinker);
 
   /// finalizeTargetSymbols - set the value of target symbols
-  virtual bool finalizeTargetSymbols(MCLinker& pLinker,
-                                     const Output& pOutput) = 0;
+  virtual bool finalizeTargetSymbols(FragmentLinker& pLinker) = 0;
+
+  /// finalizeTLSSymbol - set the value of a TLS symbol
+  virtual bool finalizeTLSSymbol(LDSymbol& pSymbol);
 
   size_t sectionStartOffset() const;
 
@@ -169,42 +131,45 @@
   virtual uint64_t defaultTextSegmentAddr() const
   { return 0x0; }
 
+  bool hasTextRel() const
+  { return m_bHasTextRel; }
+
+  bool hasStaticTLS() const
+  { return m_bHasStaticTLS; }
+
   /// segmentStartAddr - this function returns the start address of the segment
-  uint64_t segmentStartAddr(const Output& pOutput,
-                            const MCLDInfo& pInfo) const;
+  uint64_t segmentStartAddr(const FragmentLinker& pLinker) const;
+
+  /// partialScanRelocation - When doing partial linking, fix the relocation
+  /// offset after section merge
+  void partialScanRelocation(Relocation& pReloc,
+                             FragmentLinker& pLinker,
+                             Module& pModule,
+                             const LDSection& pSection);
 
   /// sizeNamePools - compute the size of regular name pools
   /// In ELF executable files, regular name pools are .symtab, .strtab.,
   /// .dynsym, .dynstr, and .hash
-  virtual void sizeNamePools(const Output& pOutput,
-                             const SymbolCategory& pSymbols,
-                             const MCLDInfo& pLDInfo);
+  virtual void sizeNamePools(const Module& pModule, bool pIsStaticLink);
 
   /// emitSectionData - emit target-dependent section data
-  virtual uint64_t emitSectionData(const Output& pOutput,
-                                   const LDSection& pSection,
-                                   const MCLDInfo& pInfo,
-                                   const Layout& pLayout,
+  virtual uint64_t emitSectionData(const LDSection& pSection,
                                    MemoryRegion& pRegion) const = 0;
 
   /// emitRegNamePools - emit regular name pools - .symtab, .strtab
-  virtual void emitRegNamePools(Output& pOutput,
-                                SymbolCategory& pSymbols,
-                                const Layout& pLayout,
-                                const MCLDInfo& pLDInfo);
+  virtual void emitRegNamePools(const Module& pModule,
+                                MemoryArea& pOutput);
 
   /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
-  virtual void emitDynNamePools(Output& pOutput,
-                                SymbolCategory& pSymbols,
-                                const Layout& pLayout,
-                                const MCLDInfo& pLDInfo);
+  virtual void emitDynNamePools(const Module& pModule,
+                                MemoryArea& 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(const Output& pOutput, const MCLDInfo& pLDInfo);
+  virtual void sizeInterp();
 
   /// emitInterp - emit the .interp
-  virtual void emitInterp(Output& pOutput, const MCLDInfo& pLDInfo);
+  virtual void emitInterp(MemoryArea& pOutput);
 
   /// getSectionOrder - compute the layout order of the section
   /// Layout calls this function to get the default order of the pSectHdr.
@@ -215,9 +180,7 @@
   /// this function.
   ///
   /// @see getTargetSectionOrder
-  virtual unsigned int getSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr,
-                                       const MCLDInfo& pInfo) const;
+  virtual unsigned int getSectionOrder(const LDSection& pSectHdr) const;
 
   /// getTargetSectionOrder - compute the layout order of target section
   /// If the target favors certain order for the given gSectHdr, please
@@ -225,10 +188,7 @@
   ///
   /// By default, this function returns the maximun order, and pSectHdr
   /// will be the last section to be laid out.
-  virtual unsigned int
-  getTargetSectionOrder(const Output& pOutput,
-                        const LDSection& pSectHdr,
-                        const MCLDInfo& pInfo) const
+  virtual unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const
   { return (unsigned int)-1; }
 
   /// numOfSegments - return the number of segments
@@ -248,11 +208,11 @@
   /// commonPageSize - the common page size of the target machine, and we set it
   /// to 4K here. If target favors the different size, please override this
   /// function
-  virtual uint64_t commonPageSize(const MCLDInfo& pInfo) const;
+  virtual uint64_t commonPageSize() const;
 
   /// abiPageSize - the abi page size of the target machine, and we set it to 4K
   /// here. If target favors the different size, please override this function
-  virtual uint64_t abiPageSize(const MCLDInfo& pInfo) const;
+  virtual uint64_t abiPageSize() const;
 
   /// getSymbolIdx - get the symbol index of ouput symbol table
   size_t getSymbolIdx(LDSymbol* pSymbol) const;
@@ -265,23 +225,45 @@
   /// allocateCommonSymbols - allocate common symbols in the corresponding
   /// sections.
   /// Different concrete target backend may overlap this function.
-  virtual bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
+  virtual bool allocateCommonSymbols(Module& pModule);
 
   /// isSymbolPreemtible - whether the symbol can be preemted by other
   /// link unit
   /// @ref Google gold linker, symtab.h:551
-  bool isSymbolPreemptible(const ResolveInfo& pSym,
-                           const MCLDInfo& pLDInfo,
-                           const Output& pOutput) const;
+  bool isSymbolPreemptible(const ResolveInfo& pSym) const;
 
   /// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
   /// @ref Google gold linker, symtab.h:645
-  bool symbolNeedsDynRel(const ResolveInfo& pSym,
+  bool symbolNeedsDynRel(const FragmentLinker& pLinker,
+                         const ResolveInfo& pSym,
                          bool pSymHasPLT,
-                         const MCLDInfo& pLDInfo,
-                         const Output& pOutput,
                          bool isAbsReloc) const;
 
+  // getTDATASymbol - get section symbol of .tdata
+  LDSymbol& getTDATASymbol();
+  const LDSymbol& getTDATASymbol() const;
+
+  /// getTBSSSymbol - get section symbol of .tbss
+  LDSymbol& getTBSSSymbol();
+  const LDSymbol& getTBSSSymbol() const;
+
+  //  -----  relaxation  -----  //
+  /// initBRIslandFactory - initialize the branch island factory for relaxation
+  bool initBRIslandFactory();
+
+  /// initStubFactory - initialize the stub factory for relaxation
+  bool initStubFactory();
+
+  /// getBRIslandFactory
+  BranchIslandFactory* getBRIslandFactory() { return m_pBRIslandFactory; }
+
+  /// getStubFactory
+  StubFactory*         getStubFactory()     { return m_pStubFactory; }
+
+  /// maxBranchOffset - return the max (forward) branch offset of the backend.
+  /// Target can override this function if needed.
+  virtual uint64_t maxBranchOffset() { return (uint64_t)-1; }
+
 protected:
   uint64_t getSymbolSize(const LDSymbol& pSymbol) const;
 
@@ -289,7 +271,7 @@
 
   uint64_t getSymbolValue(const LDSymbol& pSymbol) const;
 
-  uint64_t getSymbolShndx(const LDSymbol& pSymbol, const Layout& pLayout) const;
+  uint64_t getSymbolShndx(const LDSymbol& pSymbol) const;
 
   /// getHashBucketCount - calculate hash bucket count.
   /// @ref Google gold linker, dynobj.cc:791
@@ -297,35 +279,59 @@
 
   /// isDynamicSymbol
   /// @ref Google gold linker: symtab.cc:311
-  static bool isDynamicSymbol(const LDSymbol& pSymbol, const Output& pOutput);
+  bool isDynamicSymbol(const LDSymbol& pSymbol);
 
-  /// isOutputPIC - return whether the output is position-independent
-  bool isOutputPIC(const Output& pOutput, const MCLDInfo& pInfo) const;
-
-  /// isStaticLink - return whether we're doing static link
-  bool isStaticLink(const Output& pOutput, const MCLDInfo& pInfo) const;
+  /// isDynamicSymbol
+  /// @ref Google gold linker: symtab.cc:311
+  bool isDynamicSymbol(const ResolveInfo& pResolveInfo);
 
   /// symbolNeedsPLT - return whether the symbol needs a PLT entry
   /// @ref Google gold linker, symtab.h:596
-  bool symbolNeedsPLT(const ResolveInfo& pSym,
-                      const MCLDInfo& pLDInfo,
-                      const Output& pOutput) const;
+  bool symbolNeedsPLT(const FragmentLinker& pLinker,
+                      const ResolveInfo& pSym) const;
 
   /// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
-  bool symbolNeedsCopyReloc(const Layout& pLayout,
+  bool symbolNeedsCopyReloc(const FragmentLinker& pLinker,
                             const Relocation& pReloc,
-                            const ResolveInfo& pSym,
-                            const MCLDInfo& pLDInfo,
-                            const Output& pOutput) const;
+                            const ResolveInfo& pSym) const;
+
+  /// symbolHasFinalValue - return true if the symbol's value can be decided at
+  /// link time
+  bool symbolFinalValueIsKnown(const FragmentLinker& pLinker,
+                               const ResolveInfo& pSym) const;
+
+  /// emitSymbol32 - emit an ELF32 symbol
+  void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32,
+                    LDSymbol& pSymbol,
+                    char* pStrtab,
+                    size_t pStrtabsize,
+                    size_t pSymtabIdx);
+
+  /// emitSymbol64 - emit an ELF64 symbol
+  void emitSymbol64(llvm::ELF::Elf64_Sym& pSym64,
+                    LDSymbol& pSymbol,
+                    char* pStrtab,
+                    size_t pStrtabsize,
+                    size_t pSymtabIdx);
+
+  /// checkAndSetHasTextRel - check pSection flag to set HasTextRel
+  void checkAndSetHasTextRel(const LDSection& pSection);
+
+  void setHasStaticTLS(bool pVal = true)
+  { m_bHasStaticTLS = pVal; }
 
 private:
   /// createProgramHdrs - base on output sections to create the program headers
-  void createProgramHdrs(Output& pOutput,
-                         const MCLDInfo& pInfo);
+  void createProgramHdrs(Module& pModule, const FragmentLinker& pLinker);
+
+  /// doCreateProgramHdrs - backend can implement this function to create the
+  /// target-dependent segments
+  virtual void doCreateProgramHdrs(Module& pModule,
+                                   const FragmentLinker& pLinker) = 0;
 
   /// setupProgramHdrs - set up the attributes of segments
   ///  (i.e., offset, addresses, file/mem size, flag,  and alignment)
-  void setupProgramHdrs(const Output& pOutput, const MCLDInfo& pInfo);
+  void setupProgramHdrs(const FragmentLinker& pLinker);
 
   /// getSegmentFlag - give a section flag and return the corresponding segment
   /// flag
@@ -339,35 +345,39 @@
     return flag;
   }
 
-  /// createGNUStackInfo - create an output GNU stack section or segment if needed
-  void createGNUStackInfo(const Output& pOutput,
-                          const MCLDInfo& pInfo,
-                          MCLinker& pLinker);
+  /// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
+  void setupGNUStackInfo(Module& pModule, FragmentLinker& pLinker);
+
+  /// setupRelro - setup the offset constraint of PT_RELRO
+  void setupRelro(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);
+
+  /// setOutputSectionOffset - helper function to set output sections' address.
+  void setOutputSectionAddress(FragmentLinker& pLinker,
+                               Module& pModule,
+                               Module::iterator pSectBegin,
+                               Module::iterator pSectEnd);
 
   /// preLayout - Backend can do any needed modification before layout
-  void preLayout(const Output& pOutput,
-                 const MCLDInfo& pInfo,
-                 MCLinker& pLinker);
+  void preLayout(Module& pModule, FragmentLinker& pLinker);
 
   /// postLayout -Backend can do any needed modification after layout
-  void postLayout(const Output& pOutput,
-                 const MCLDInfo& pInfo,
-                 MCLinker& pLinker);
+  void postLayout(Module& pModule, FragmentLinker& pLinker);
 
   /// preLayout - Backend can do any needed modification before layout
-  virtual void doPreLayout(const Output& pOutput,
-                         const MCLDInfo& pInfo,
-                         MCLinker& pLinker) = 0;
+  virtual void doPreLayout(FragmentLinker& pLinker) = 0;
 
   /// postLayout -Backend can do any needed modification after layout
-  virtual void doPostLayout(const Output& pOutput,
-                          const MCLDInfo& pInfo,
-                          MCLinker& pLinker) = 0;
+  virtual void doPostLayout(Module& pModule, FragmentLinker& pLinker) = 0;
 
   /// postProcessing - Backend can do any needed modification in the final stage
-  void postProcessing(const Output& pOutput,
-                      const MCLDInfo& pInfo,
-                      MCLinker& pLinker);
+  void postProcessing(FragmentLinker& pLinker, MemoryArea& pOutput);
 
   /// dynamic - the dynamic section of the target machine.
   virtual ELFDynamic& dynamic() = 0;
@@ -375,6 +385,25 @@
   /// dynamic - the dynamic section of the target machine.
   virtual const ELFDynamic& dynamic() const = 0;
 
+  /// relax - the relaxation pass
+  bool relax(Module& pModule, FragmentLinker& pLinker);
+
+  /// mayRelax - Backends should override this function if they need relaxation
+  virtual bool mayRelax() { return false; }
+
+  /// 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.
+  virtual bool doRelax(Module& pModule, FragmentLinker& pLinker, 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
@@ -403,34 +432,64 @@
     SHO_SMALL_BSS,           // .sbss
     SHO_BSS,                 // .bss
     SHO_LARGE_BSS,           // .lbss
-    SHO_UNDEFINED = ~(0U)    // default order
+    SHO_UNDEFINED,           // default order
+    SHO_STRTAB               // .strtab
   };
 
-  typedef HashEntry<LDSymbol*, size_t, SymCompare> HashEntryType;
-  typedef HashTable<HashEntryType, PtrHash, EntryFactory<HashEntryType> > HashTableType;
+  struct SymCompare
+  {
+    bool operator()(const LDSymbol* X, const LDSymbol* Y) const
+    { return (X==Y); }
+  };
+
+  struct SymPtrHash
+  {
+    size_t operator()(const LDSymbol* pKey) const
+    {
+      return (unsigned((uintptr_t)pKey) >> 4) ^
+             (unsigned((uintptr_t)pKey) >> 9);
+    }
+  };
+
+  typedef HashEntry<LDSymbol*, size_t, SymCompare> SymHashEntryType;
+  typedef HashTable<SymHashEntryType,
+                    SymPtrHash,
+                    EntryFactory<SymHashEntryType> > HashTableType;
+
 
 protected:
-  // ----- readers and writers ----- //
-  GNUArchiveReader* m_pArchiveReader;
   ELFObjectReader* m_pObjectReader;
-  ELFDynObjReader* m_pDynObjReader;
-  ELFObjectWriter* m_pObjectWriter;
-  ELFDynObjWriter* m_pDynObjWriter;
-  ELFExecWriter*   m_pExecWriter;
 
   // -----  file formats  ----- //
   ELFDynObjFileFormat* m_pDynObjFileFormat;
-  ELFExecFileFormat* m_pExecFileFormat;
+  ELFExecFileFormat*   m_pExecFileFormat;
+  ELFObjectFileFormat* m_pObjectFileFormat;
 
   // ELF segment factory
   ELFSegmentFactory m_ELFSegmentTable;
 
+  // branch island factory
+  BranchIslandFactory* m_pBRIslandFactory;
+
+  // stub factory
+  StubFactory* m_pStubFactory;
+
   // map the LDSymbol to its index in the output symbol table
   HashTableType* m_pSymIndexMap;
 
+  /// m_pEhFrame - section .eh_frame
+  EhFrame* m_pEhFrame;
+
   // section .eh_frame_hdr
   EhFrameHdr* m_pEhFrameHdr;
 
+  // ----- dynamic flags ----- //
+  // DF_TEXTREL of DT_FLAGS
+  bool m_bHasTextRel;
+
+  // DF_STATIC_TLS of DT_FLAGS
+  bool m_bHasStaticTLS;
+
   // -----  standard symbols  ----- //
   // section symbols
   LDSymbol* f_pPreInitArrayStart;
@@ -440,6 +499,11 @@
   LDSymbol* f_pFiniArrayStart;
   LDSymbol* f_pFiniArrayEnd;
   LDSymbol* f_pStack;
+  LDSymbol* f_pDynamic;
+
+  // section symbols for .tdata and .tbss
+  LDSymbol* f_pTDATA;
+  LDSymbol* f_pTBSS;
 
   // segment symbols
   LDSymbol* f_pExecutableStart;
diff --git a/include/mcld/Target/GOT.h b/include/mcld/Target/GOT.h
index 5621778..6dfa9b1 100644
--- a/include/mcld/Target/GOT.h
+++ b/include/mcld/Target/GOT.h
@@ -13,49 +13,14 @@
 #endif
 
 #include <mcld/LD/LDSection.h>
-#include <mcld/LD/TargetFragment.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Fragment/TargetFragment.h>
 
-namespace mcld
-{
+namespace mcld {
 
 class GOT;
+class LDSection;
 class ResolveInfo;
-class SectionData;
-
-/** \class GOTEntry
- *  \brief The entry of Global Offset Table
- */
-class GOTEntry : public TargetFragment
-{
-public:
-  explicit GOTEntry(uint64_t pContent, size_t pEntrySize,
-                    SectionData* pParent);
-
-  virtual ~GOTEntry();
-
-  uint64_t& getContent()
-  { return f_Content; }
-
-  uint64_t getContent() const
-  { return f_Content; }
-
-  void setContent(uint64_t pValue)
-  { f_Content = pValue; }
-
-  static bool classof(const Fragment *pFrag)
-  { return pFrag->getKind() == Fragment::Target; }
-
-  static bool classof(const GOTEntry* pFrag)
-  { return true; }
-
-  // Override pure virtual function
-  size_t getSize() const
-  { return m_EntrySize; }
-
-protected:
-  uint64_t f_Content;
-  size_t m_EntrySize;
-};
 
 /** \class GOT
  *  \brief The Global Offset Table
@@ -63,40 +28,70 @@
 class GOT
 {
 protected:
-  GOT(LDSection& pSection, SectionData& pSectionData, size_t pEntrySize);
+  GOT(LDSection& pSection, size_t pEntrySize);
+
+public:
+  typedef SectionData::iterator iterator;
+  typedef SectionData::const_iterator const_iterator;
+
+  class Entry : public TargetFragment
+  {
+  public:
+    Entry(uint64_t pContent, size_t pEntrySize, SectionData* pParent);
+
+    virtual ~Entry();
+
+    uint64_t getContent() const
+    { return f_Content; }
+
+    void setContent(uint64_t pValue)
+    { f_Content = pValue; }
+
+    // Override pure virtual function
+    size_t size() const
+    { return m_EntrySize; }
+
+  protected:
+    uint64_t f_Content;
+    size_t m_EntrySize;
+  };
 
 public:
   virtual ~GOT();
 
+  // ----- observers -----//
   /// entrySize - the number of bytes per entry
   size_t getEntrySize() const;
 
-  const LDSection& getSection() const
-  { return m_Section; }
+  uint64_t addr() const { return m_Section.addr(); }
 
-  SectionData& getSectionData()
-  { return m_SectionData; }
+  const_iterator begin() const { return m_SectionData->begin(); }
+  iterator       begin()       { return m_SectionData->begin(); }
+  const_iterator end  () const { return m_SectionData->end();   }
+  iterator       end  ()       { return m_SectionData->end();   }
 
-  const SectionData& getSectionData() const
-  { return m_SectionData; }
+  bool empty() const
+  { return m_SectionData->empty(); }
 
-public:
-  /// reserveEntry - reseve number of pNum of empty entries
+  // 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 reserveEntry(size_t pNum = 1) = 0;
+  virtual void reserve(size_t pNum = 1);
 
-  /// getEntry - get an empty entry or an exitsted filled entry with pSymbol.
-  /// @param pSymbol - the target symbol
-  /// @param pExist - ture if a filled entry with pSymbol existed, otherwise false.
-  virtual GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist) = 0;
+  /// consume - consume and return an empty entry
+  virtual Entry* consume();
 
 protected:
   LDSection& m_Section;
-  SectionData& m_SectionData;
+  SectionData* m_SectionData;
   size_t f_EntrySize;
+
+  Entry* m_pLast; ///< the last consumed entry
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Target/OutputRelocSection.h b/include/mcld/Target/OutputRelocSection.h
index b75952b..ace0c71 100644
--- a/include/mcld/Target/OutputRelocSection.h
+++ b/include/mcld/Target/OutputRelocSection.h
@@ -12,15 +12,15 @@
 #include <gtest.h>
 #endif
 
-#include <llvm/ADT/DenseMap.h>
-#include <mcld/LD/SectionData.h>
-#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/RelocData.h>
 
 namespace mcld
 {
 
-class ResolveInfo;
+class LDSymbol;
+class Module;
 class Relocation;
+class RelocationFactory;
 
 /** \class OutputRelocSection
  *  \brief Dynamic relocation section for ARM .rel.dyn and .rel.plt
@@ -28,31 +28,38 @@
 class OutputRelocSection
 {
 public:
-  OutputRelocSection(LDSection& pSection,
-                     SectionData& pSectionData,
+  OutputRelocSection(Module& pModule,
+                     LDSection& pSection,
                      unsigned int pEntrySize);
 
   ~OutputRelocSection();
 
   void reserveEntry(RelocationFactory& pRelFactory, size_t pNum=1);
 
-  Relocation* getEntry(const ResolveInfo& pSymbol,
-                       bool isForGOT,
-                       bool& pExist);
+  Relocation* consumeEntry();
+
+  void finalizeSectionSize();
+
+  /// addSymbolToDynSym - add local symbol to TLS category so that it'll be
+  /// emitted into .dynsym
+  bool addSymbolToDynSym(LDSymbol& pSymbol);
+
+  // ----- observers ----- //
+  bool empty()
+  { return m_pRelocData->empty(); }
 
 private:
-  typedef llvm::DenseMap<const ResolveInfo*, Relocation*> SymRelMapType;
-
-  typedef SymRelMapType::iterator SymRelMapIterator;
-
-  typedef SectionData::iterator FragmentIterator;
+  typedef RelocData::iterator FragmentIterator;
 
 private:
+  Module& m_Module;
+
   /// m_pSection - LDSection of this Section
   LDSection* m_pSection;
 
-  /// m_SectionData - SectionData which contains the dynamic relocations
-  SectionData* m_pSectionData;
+  /// m_RelocData - the output RelocData which contains the dynamic
+  /// relocations
+  RelocData* m_pRelocData;
 
   /// m_EntryBytes - size of a relocation entry
   unsigned int m_EntryBytes;
@@ -62,9 +69,6 @@
 
   /// m_ValidEntryIterator - point to the first valid entry
   FragmentIterator m_ValidEntryIterator;
-
-  /// m_SymRelMap - map the resolved symbol to the Relocation entry
-  SymRelMapType m_SymRelMap;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Target/PLT.h b/include/mcld/Target/PLT.h
index 2a4f641..bd5936a 100644
--- a/include/mcld/Target/PLT.h
+++ b/include/mcld/Target/PLT.h
@@ -12,74 +12,73 @@
 #include <gtest.h>
 #endif
 
-#include <llvm/ADT/ilist.h>
-
 #include <mcld/LD/LDSection.h>
-#include <mcld/LD/TargetFragment.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Fragment/TargetFragment.h>
 
-namespace mcld
-{
+namespace mcld {
 
-class SectionData;
+class LDSection;
 class ResolveInfo;
 
-/** \class PLTEntry
- */
-class PLTEntry : public TargetFragment
-{
-public:
-  PLTEntry(size_t pSize, SectionData* pParent);
-  virtual ~PLTEntry();
-
-  size_t getEntrySize() const
-  { return m_EntrySize; }
-
-  void setContent(unsigned char* pContent)
-  { m_pContent = pContent; }
-
-  const unsigned char* getContent() const
-  { return m_pContent; }
-
-  //Used by llvm::cast<>.
-  static bool classof(const Fragment *O)
-  { return true; }
-
-  size_t getSize() const
-  { return m_EntrySize; }
-
-protected:
-  size_t m_EntrySize;
-  unsigned char* m_pContent;
-};
-
 /** \class PLT
  *  \brief Procedure linkage table
  */
 class PLT
 {
 public:
-  PLT(LDSection& pSection, SectionData& pSectionData);
-  virtual ~PLT();
+  typedef SectionData::iterator iterator;
+  typedef SectionData::const_iterator const_iterator;
 
-  const LDSection& getSection() const
-  { return m_Section; }
+  class Entry : public TargetFragment
+  {
+  public:
+    Entry(size_t pSize, SectionData& pParent);
+    virtual ~Entry();
 
-  const SectionData& getSectionData() const
-  { return m_SectionData; }
+    size_t getEntrySize() const
+    { return m_EntrySize; }
+
+    void setContent(unsigned char* pContent)
+    { m_pContent = pContent; }
+
+    const unsigned char* getContent() const
+    { return m_pContent; }
+
+    //Used by llvm::cast<>.
+    static bool classof(const Fragment *O)
+    { return true; }
+
+    size_t size() const
+    { return m_EntrySize; }
+
+  protected:
+    size_t m_EntrySize;
+    unsigned char* m_pContent;
+  };
 
 public:
+  PLT(LDSection& pSection);
+
+  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;
 
-  /// getPLTEntry - get an empty entry or an exitsted filled entry with pSymbol.
-  /// @param pSymbol - the target symbol
-  /// @param pExist - ture if the a filled entry with pSymbol existed, otherwise false.
-  virtual PLTEntry* getPLTEntry(const ResolveInfo& pSymbol, bool& pExist) = 0;
+  // finalizeSectionSize - set LDSection size
+  virtual void finalizeSectionSize() = 0;
+
+  uint64_t addr() const { return m_Section.addr(); }
+
+  const_iterator begin() const { return m_SectionData->begin(); }
+  iterator       begin()       { return m_SectionData->begin(); }
+  const_iterator end  () const { return m_SectionData->end();   }
+  iterator       end  ()       { return m_SectionData->end();   }
 
 protected:
   LDSection& m_Section;
-  SectionData& m_SectionData;
+  SectionData* m_SectionData;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Target/SymbolEntryMap.h b/include/mcld/Target/SymbolEntryMap.h
new file mode 100644
index 0000000..fc5ea93
--- /dev/null
+++ b/include/mcld/Target/SymbolEntryMap.h
@@ -0,0 +1,104 @@
+//===- 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 f4c02b5..c18bc79 100644
--- a/include/mcld/Target/TargetLDBackend.h
+++ b/include/mcld/Target/TargetLDBackend.h
@@ -6,16 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef LLVM_TARGET_TARGETLDBACKEND_H
-#define LLVM_TARGET_TARGETLDBACKEND_H
+#ifndef MCLD_TARGET_TARGETLDBACKEND_H
+#define MCLD_TARGET_TARGETLDBACKEND_H
 
 #include <llvm/Support/DataTypes.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/LD/EhFrame.h>
 
 namespace mcld {
 
-class MCLinker;
+class Module;
+class LinkerConfig;
+class FragmentLinker;
 class Relocation;
 class RelocationFactory;
 class Layout;
@@ -25,38 +25,39 @@
 class ObjectWriter;
 class DynObjWriter;
 class ExecWriter;
-class LDContext;
-class SectionMap;
-class Output;
-class MCLDInfo;
-class SymbolCategory;
-class Input;
 class LDFileFormat;
+class LDSymbol;
+class LDSection;
+class SectionData;
+class Input;
 class GOT;
+class MemoryArea;
 class MemoryAreaFactory;
+class BranchIslandFactory;
+class StubFactory;
+class ObjectBuilder;
 
 //===----------------------------------------------------------------------===//
 /// TargetLDBackend - Generic interface to target specific assembler backends.
-///
+//===----------------------------------------------------------------------===//
 class TargetLDBackend
 {
   TargetLDBackend(const TargetLDBackend &);   // DO NOT IMPLEMENT
   void operator=(const TargetLDBackend &);  // DO NOT IMPLEMENT
 
 protected:
-  TargetLDBackend();
+  TargetLDBackend(const LinkerConfig& pConfig);
 
 public:
   virtual ~TargetLDBackend();
 
   // -----  target dependent  ----- //
-  virtual bool initTargetSectionMap(SectionMap& pSectionMap) { return true;}
-  virtual void initTargetSegments(MCLinker& pLinker) { }
-  virtual void initTargetSections(MCLinker& pLinker) { }
-  virtual void initTargetSymbols(MCLinker& pLinker, const Output& pOutput) { }
-  virtual void initTargetRelocation(MCLinker& pLinker) { }
-  virtual bool initStandardSymbols(MCLinker& pLinker, const Output& pOutput) = 0;
-  virtual bool initRelocFactory(const MCLinker& pLinker) = 0;
+  virtual void initTargetSegments(FragmentLinker& pLinker) { }
+  virtual void initTargetSections(Module& pModule, ObjectBuilder& pBuilder) { }
+  virtual void initTargetSymbols(FragmentLinker& pLinker) { }
+  virtual void initTargetRelocation(FragmentLinker& pLinker) { }
+  virtual bool initStandardSymbols(FragmentLinker& pLinker, Module& pModule) = 0;
+  virtual bool initRelocFactory(const FragmentLinker& pLinker) = 0;
 
   virtual RelocationFactory* getRelocFactory() = 0;
 
@@ -66,51 +67,42 @@
   /// for layout to adjust the ouput offset.
   /// @param pReloc - a read in relocation entry
   /// @param pInputSym - the input LDSymbol of relocation target symbol
-  /// @param pOutput - the ouput file
+  /// @param pSection - the section of relocation applying target
   virtual void scanRelocation(Relocation& pReloc,
-                              const LDSymbol& pInputSym,
-                              MCLinker& pLinker,
-                              const MCLDInfo& pLDInfo,
-                              const Output& pOutput,
+                              FragmentLinker& pLinker,
+                              Module& pModule,
                               const LDSection& pSection) = 0;
 
+  /// partialScanRelocation - When doing partial linking, backend can do any
+  /// modification to relocation to fix the relocation offset after section
+  /// merge
+  /// @param pReloc - a read in relocation entry
+  /// @param pInputSym - the input LDSymbol of relocation target symbol
+  /// @param pSection - the section of relocation applying target
+  virtual void partialScanRelocation(Relocation& pReloc,
+                                     FragmentLinker& pLinker,
+                                     Module& pModule,
+                                     const LDSection& pSection) = 0;
+
   // -----  format dependent  ----- //
-  virtual bool initArchiveReader(MCLinker&,
-                                 MCLDInfo&,
-                                 MemoryAreaFactory&) = 0;
-  virtual bool initObjectReader(MCLinker&) = 0;
-  virtual bool initDynObjReader(MCLinker&) = 0;
-  virtual bool initObjectWriter(MCLinker&) = 0;
-  virtual bool initDynObjWriter(MCLinker&) = 0;
-  virtual bool initExecWriter(MCLinker&) = 0;
+  virtual ArchiveReader* createArchiveReader(Module&) = 0;
+  virtual ObjectReader*  createObjectReader(FragmentLinker&) = 0;
+  virtual DynObjReader*  createDynObjReader(FragmentLinker&) = 0;
+  virtual ObjectWriter*  createObjectWriter(FragmentLinker&) = 0;
+  virtual DynObjWriter*  createDynObjWriter(FragmentLinker&) = 0;
+  virtual ExecWriter*    createExecWriter(FragmentLinker&) = 0;
 
-  virtual bool initExecSections(MCLinker&) = 0;
-  virtual bool initDynObjSections(MCLinker&) = 0;
-
-  virtual ArchiveReader *getArchiveReader() = 0;
-  virtual ObjectReader *getObjectReader() = 0;
-  virtual DynObjReader *getDynObjReader() = 0;
-  virtual ObjectWriter *getObjectWriter() = 0;
-  virtual DynObjWriter *getDynObjWriter() = 0;
-  virtual ExecWriter *getExecWriter() = 0;
-
-  virtual LDFileFormat* getDynObjFileFormat() = 0;
-  virtual LDFileFormat* getExecFileFormat() = 0;
+  virtual bool initStdSections(ObjectBuilder& pBuilder) = 0;
 
   /// preLayout - Backend can do any needed modification before layout
-  virtual void preLayout(const Output& pOutput,
-                         const MCLDInfo& pInfo,
-                         MCLinker& pLinker) = 0;
+  virtual void preLayout(Module& pModule, FragmentLinker& pLinker) = 0;
 
   /// postLayout -Backend can do any needed modification after layout
-  virtual void postLayout(const Output& pOutput,
-                          const MCLDInfo& pInfo,
-                          MCLinker& pLinker) = 0;
+  virtual void postLayout(Module& pModule, FragmentLinker& pLinker) = 0;
 
   /// postProcessing - Backend can do any needed modification in the final stage
-  virtual void postProcessing(const Output& pOutput,
-                              const MCLDInfo& pInfo,
-                              MCLinker& pLinker) = 0;
+  virtual void postProcessing(FragmentLinker& pLinker,
+                              MemoryArea& pOutput) = 0;
 
   /// Is the target machine little endian? **/
   virtual bool isLittleEndian() const = 0;
@@ -119,41 +111,43 @@
   virtual unsigned int bitclass() const = 0;
 
   /// the common page size of the target machine
-  virtual uint64_t commonPageSize(const MCLDInfo& pInfo) const = 0;
+  virtual uint64_t commonPageSize() const = 0;
 
   /// the abi page size of the target machine
-  virtual uint64_t abiPageSize(const MCLDInfo& pInfo) const = 0;
+  virtual uint64_t abiPageSize() const = 0;
 
   /// section start offset in the output file
   virtual size_t sectionStartOffset() const = 0;
 
   /// computeSectionOrder - compute the layout order of the given section
-  virtual unsigned int getSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr,
-                                       const MCLDInfo& pInfo) const = 0;
+  virtual unsigned int getSectionOrder(const LDSection& pSectHdr) const = 0;
 
   /// sizeNamePools - compute the size of regular name pools
   /// In ELF executable files, regular name pools are .symtab, .strtab.,
   /// .dynsym, .dynstr, and .hash
   virtual void
-  sizeNamePools(const Output& pOutput,
-                const SymbolCategory& pSymbols,
-                const MCLDInfo& pLDInfo) = 0;
+  sizeNamePools(const Module& pModule, bool pIsStaticLink) = 0;
 
   /// finalizeSymbol - Linker checks pSymbol.reserved() if it's not zero,
   /// then it will ask backend to finalize the symbol value.
   /// @return ture - if backend set the symbol value sucessfully
   /// @return false - if backend do not recognize the symbol
-  virtual bool finalizeSymbols(MCLinker& pLinker, const Output& pOutput) = 0;
+  virtual bool finalizeSymbols(FragmentLinker& pLinker) = 0;
+
+  /// finalizeTLSSymbol - Linker asks backend to set the symbol value when it
+  /// meets a TLS symbol
+  virtual bool finalizeTLSSymbol(LDSymbol& pSymbol) = 0;
 
   /// allocateCommonSymbols - allocate common symbols in the corresponding
   /// sections.
-  virtual bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const = 0;
+  virtual bool allocateCommonSymbols(Module& pModule) = 0;
+
+  /// mergeSection - merge target dependent sections.
+  virtual bool mergeSection(Module& pModule, LDSection& pInputSection)
+  { return true; }
 
   /// readSection - read a target dependent section
-  virtual bool readSection(Input& pInput,
-                           MCLinker& pLinker,
-                           LDSection& pInputSectHdr)
+  virtual bool readSection(Input& pInput, SectionData& pSD)
   { return true; }
 
   /// dyld - the name of the default dynamic linker
@@ -161,17 +155,27 @@
 
   /// 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(const Output& pOutput, const MCLDInfo& pLDInfo) = 0;
+  virtual void sizeInterp() = 0;
 
-public:
-  EhFrame* getEhFrame();
+  // -----  relaxation  ----- //
+  virtual bool initBRIslandFactory() = 0;
+  virtual bool initStubFactory() = 0;
+  virtual bool initTargetStubs(FragmentLinker& pLinker) { return true; }
 
-  const EhFrame* getEhFrame() const;
+  virtual BranchIslandFactory* getBRIslandFactory() = 0;
+  virtual StubFactory*         getStubFactory() = 0;
+
+  /// relax - the relaxation pass
+  virtual bool relax(Module& pModule, FragmentLinker& pLinker) = 0;
+
+  /// mayRelax - return true if the backend needs to do relaxation
+  virtual bool mayRelax() = 0;
+
+protected:
+  const LinkerConfig& config() const { return m_Config; }
 
 private:
-  /// m_pEhFrame - section .eh_frame
-  EhFrame* m_pEhFrame;
-
+  const LinkerConfig& m_Config;
 };
 
 } // End mcld namespace
diff --git a/include/mcld/Target/TargetMachine.h b/include/mcld/Target/TargetMachine.h
index 02df7fd..1b167ab 100644
--- a/include/mcld/Target/TargetMachine.h
+++ b/include/mcld/Target/TargetMachine.h
@@ -6,31 +6,31 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_MACHINE_H
-#define MCLD_TARGET_MACHINE_H
+#ifndef MCLD_TARGET_TARGET_MACHINE_H
+#define MCLD_TARGET_TARGET_MACHINE_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
 #include <llvm/Target/TargetMachine.h>
 #include <string>
-#include "mcld/MC/MCLDFile.h"
 
-namespace llvm
-{
+namespace llvm {
+
 class Target;
 class TargetData;
 class TargetMachine;
 class PassManagerBase;
-class formatted_raw_ostream;
 
 } // namespace of llvm
 
-namespace mcld
-{
+namespace mcld {
 
+class Module;
 class Target;
-class MCLDInfo;
-class SectLinkerOption;
+class MemoryArea;
+class LinkerConfig;
+class ToolOutputFile;
+
 using namespace llvm;
 
 enum CodeGenFileType {
@@ -38,47 +38,40 @@
   CGFT_OBJFile,
   CGFT_DSOFile,
   CGFT_EXEFile,
+  CGFT_PARTIAL,
   CGFT_NULLFile
 };
 
 
-/** \class mcld::LLVMTargetMachine
- *  \brief mcld::LLVMTargetMachine is a object adapter of
- *  llvm::LLVMTargetMachine.
- *
- *  mcld::LLVMTargetMachine is also in charge of MCLDInfo.
- *
- *  @see MCLDInfo
+/** \class mcld::MCLDTargetMachine
+ *  \brief mcld::MCLDTargetMachine is a object adapter of LLVMTargetMachine.
  */
-class LLVMTargetMachine
+class MCLDTargetMachine
 {
 public:
   /// Adapter of llvm::TargetMachine
   ///
-  LLVMTargetMachine(llvm::TargetMachine &pTM,
+  MCLDTargetMachine(llvm::TargetMachine &pTM,
                     const mcld::Target &pTarget,
                     const std::string &pTriple);
-  virtual ~LLVMTargetMachine();
+
+  virtual ~MCLDTargetMachine();
 
   /// getTarget - adapt llvm::TargetMachine::getTarget
   const mcld::Target& getTarget() const;
 
   /// getTM - return adapted the llvm::TargetMachine.
   const llvm::TargetMachine& getTM() const { return m_TM; }
-  llvm::TargetMachine& getTM() { return m_TM; }
-
-  /// getLDInfo - return the mcld::MCLDInfo
-  virtual mcld::MCLDInfo& getLDInfo() = 0;
-  virtual const mcld::MCLDInfo& getLDInfo() const = 0;
+  llvm::TargetMachine&       getTM()       { return m_TM; }
 
   /// appPassesToEmitFile - The target function which we has to modify as
   /// upstreaming.
   bool addPassesToEmitFile(PassManagerBase &,
-                           formatted_raw_ostream &Out,
-                           const std::string &pOutputFilename,
+                           mcld::ToolOutputFile& pOutput,
                            mcld::CodeGenFileType,
                            CodeGenOpt::Level,
-                           SectLinkerOption *pLinkerOpt = NULL,
+                           mcld::Module& pModule,
+                           mcld::LinkerConfig& pConfig,
                            bool DisableVerify = true);
 
   /// getTargetData
@@ -98,20 +91,18 @@
                               bool DisableVerify,
                               llvm::MCContext *&OutCtx);
 
-  bool addCompilerPasses(PassManagerBase &,
-                         formatted_raw_ostream &Out,
-                         const std::string& pOutputFilename,
+  bool addCompilerPasses(PassManagerBase &pPM,
+                         llvm::formatted_raw_ostream &pOutput,
                          llvm::MCContext *&OutCtx);
 
-  bool addAssemblerPasses(PassManagerBase &,
-                          formatted_raw_ostream &Out,
-                          const std::string& pOutputFilename,
+  bool addAssemblerPasses(PassManagerBase &pPM,
+                          llvm::raw_ostream &pOutput,
                           llvm::MCContext *&OutCtx);
 
-  bool addLinkerPasses(PassManagerBase &,
-                       SectLinkerOption *pLinkerOpt,
-                       const std::string& pOutputFilename,
-                       MCLDFile::Type pOutputLinkType,
+  bool addLinkerPasses(PassManagerBase &pPM,
+                       LinkerConfig& pConfig,
+                       Module& pModule,
+                       mcld::MemoryArea& pOutput,
                        llvm::MCContext *&OutCtx);
 
 private:
diff --git a/lib/CodeGen/Android.mk b/lib/CodeGen/Android.mk
index 8754d65..9954552 100644
--- a/lib/CodeGen/Android.mk
+++ b/lib/CodeGen/Android.mk
@@ -1,9 +1,8 @@
 LOCAL_PATH:= $(call my-dir)
 
 mcld_codegen_SRC_FILES := \
-  LLVMTargetMachine.cpp \
-  SectLinker.cpp  \
-  SectLinkerOption.cpp
+  MCLDTargetMachine.cpp \
+  MCLinker.cpp
 
 # For the host
 # =====================================================
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/MCLDTargetMachine.cpp
similarity index 79%
rename from lib/CodeGen/LLVMTargetMachine.cpp
rename to lib/CodeGen/MCLDTargetMachine.cpp
index 822ff36..e0eeb63 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/MCLDTargetMachine.cpp
@@ -1,4 +1,4 @@
-//===- LLVMTargetMachine.cpp ----------------------------------------------===//
+//===- MCLDTargetMachine.cpp ----------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,13 +6,15 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#include <mcld/CodeGen/SectLinker.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
-#include <mcld/MC/MCLDFile.h>
-#include <mcld/Support/RealPath.h>
-#include <mcld/Support/TargetRegistry.h>
 #include <mcld/Target/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>
@@ -37,7 +39,6 @@
 #include <llvm/Support/Debug.h>
 #include <llvm/Support/TargetRegistry.h>
 #include <llvm/Support/FormattedStream.h>
-#include <llvm/Support/ToolOutputFile.h>
 #include <llvm/Target/TargetData.h>
 #include <llvm/Target/TargetInstrInfo.h>
 #include <llvm/Target/TargetLowering.h>
@@ -90,19 +91,19 @@
 
 
 //===---------------------------------------------------------------------===//
-/// LLVMTargetMachine
+/// MCLDTargetMachine
 //===----------------------------------------------------------------------===//
-mcld::LLVMTargetMachine::LLVMTargetMachine(llvm::TargetMachine &pTM,
+mcld::MCLDTargetMachine::MCLDTargetMachine(llvm::TargetMachine &pTM,
                                            const mcld::Target& pTarget,
-                                           const std::string& pTriple )
+                                           const std::string& pTriple)
   : m_TM(pTM), m_pTarget(&pTarget), m_Triple(pTriple) {
 }
 
-mcld::LLVMTargetMachine::~LLVMTargetMachine() {
+mcld::MCLDTargetMachine::~MCLDTargetMachine() {
   m_pTarget = 0;
 }
 
-const mcld::Target& mcld::LLVMTargetMachine::getTarget() const
+const mcld::Target& mcld::MCLDTargetMachine::getTarget() const
 {
   return *m_pTarget;
 }
@@ -137,8 +138,8 @@
 
 
 static llvm::MCContext *addPassesToGenerateCode(llvm::LLVMTargetMachine *TM,
-                                     PassManagerBase &PM,
-                                     bool DisableVerify)
+                                                PassManagerBase &PM,
+                                                bool DisableVerify)
 {
   // Targets may override createPassConfig to provide a target-specific sublass.
   TargetPassConfig *PassConfig = TM->createPassConfig(PM);
@@ -183,12 +184,12 @@
 
 }
 
-bool mcld::LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &pPM,
-                                             formatted_raw_ostream &Out,
-                                             const std::string& pOutputFilename,
+bool mcld::MCLDTargetMachine::addPassesToEmitFile(PassManagerBase &pPM,
+                                             mcld::ToolOutputFile& pOutput,
                                              mcld::CodeGenFileType pFileType,
                                              CodeGenOpt::Level pOptLvl,
-                                             SectLinkerOption *pLinkerOpt,
+                                             mcld::Module& pModule,
+                                             LinkerConfig& pConfig,
                                              bool pDisableVerify)
 {
 
@@ -210,8 +211,7 @@
       Context->setAllowTemporaryLabels(false);
 
     if (addCompilerPasses(pPM,
-                          Out,
-                          pOutputFilename,
+                          pOutput.formatted_os(),
                           Context))
       return true;
 
@@ -224,8 +224,7 @@
     if (getTM().hasMCSaveTempLabels())
       Context->setAllowTemporaryLabels(false);
     if (addAssemblerPasses(pPM,
-                           Out,
-                           pOutputFilename,
+                           pOutput.mem_os(),
                            Context))
       return true;
 
@@ -233,25 +232,31 @@
     break;
   }
   case CGFT_EXEFile: {
-    if (pLinkerOpt == NULL)
-      return true;
-
+    pConfig.setCodeGenType(LinkerConfig::Exec);
     if (addLinkerPasses(pPM,
-                        pLinkerOpt,
-                        pOutputFilename,
-                        MCLDFile::Exec,
+                        pConfig,
+                        pModule,
+                        pOutput.memory(),
                         Context))
       return true;
     break;
   }
   case CGFT_DSOFile: {
-    if (pLinkerOpt == NULL)
-      return true;
-
+    pConfig.setCodeGenType(LinkerConfig::DynObj);
     if (addLinkerPasses(pPM,
-                        pLinkerOpt,
-                        pOutputFilename,
-                        MCLDFile::DynObj,
+                        pConfig,
+                        pModule,
+                        pOutput.memory(),
+                        Context))
+      return true;
+    break;
+  }
+  case CGFT_PARTIAL: {
+    pConfig.setCodeGenType(LinkerConfig::Object);
+    if (addLinkerPasses(pPM,
+                        pConfig,
+                        pModule,
+                        pOutput.memory(),
                         Context))
       return true;
     break;
@@ -260,9 +265,8 @@
   return false;
 }
 
-bool mcld::LLVMTargetMachine::addCompilerPasses(PassManagerBase &pPM,
-                                                formatted_raw_ostream &Out,
-                                                const std::string& pOutputFilename,
+bool mcld::MCLDTargetMachine::addCompilerPasses(PassManagerBase &pPM,
+                                                llvm::formatted_raw_ostream &pOutput,
                                                 llvm::MCContext *&Context)
 {
   const MCAsmInfo &MAI = *getTM().getMCAsmInfo();
@@ -285,7 +289,7 @@
 
   // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
   OwningPtr<MCStreamer> AsmStreamer(
-    getTarget().get()->createAsmStreamer(*Context, Out,
+    getTarget().get()->createAsmStreamer(*Context, pOutput,
                                          getVerboseAsm(),
                                          getTM().hasMCUseLoc(),
                                          getTM().hasMCUseCFI(),
@@ -305,9 +309,8 @@
   return false;
 }
 
-bool mcld::LLVMTargetMachine::addAssemblerPasses(PassManagerBase &pPM,
-                                                 formatted_raw_ostream &Out,
-                                                 const std::string& pOutputFilename,
+bool mcld::MCLDTargetMachine::addAssemblerPasses(PassManagerBase &pPM,
+                                                 llvm::raw_ostream &pOutput,
                                                  llvm::MCContext *&Context)
 {
   // MCCodeEmitter
@@ -327,7 +330,7 @@
                                                               m_Triple,
                                                               *Context,
                                                               *MAB,
-                                                              Out,
+                                                              pOutput,
                                                               MCE,
                                                               getTM().hasMCRelaxAll(),
                                                               getTM().hasMCNoExecStack()));
@@ -342,31 +345,30 @@
   return false;
 }
 
-bool mcld::LLVMTargetMachine::addLinkerPasses(PassManagerBase &pPM,
-                                              SectLinkerOption *pLinkerOpt,
-                                              const std::string &pOutputFilename,
-                                              MCLDFile::Type pOutputLinkType,
+bool mcld::MCLDTargetMachine::addLinkerPasses(PassManagerBase &pPM,
+                                              LinkerConfig& pConfig,
+                                              mcld::Module& pModule,
+                                              mcld::MemoryArea& pOutput,
                                               llvm::MCContext *&Context)
 {
-  TargetLDBackend* ldBackend = getTarget().createLDBackend(m_Triple);
-  if (0 == ldBackend)
+  if (NULL == pOutput.handler())
     return true;
 
   // set up output's SOName
-  if (pOutputLinkType == MCLDFile::DynObj &&
-      pLinkerOpt->info().output().name().empty()) {
+  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.
-    pLinkerOpt->info().output().setSOName(pOutputFilename);
+    pModule.setName(pOutput.handler()->path().native());
+  }
+  else {
+    pModule.setName(pConfig.options().soname());
   }
 
-  pLinkerOpt->info().output().setPath(sys::fs::RealPath(pOutputFilename));
-  pLinkerOpt->info().output().setType(pOutputLinkType);
-
-  MachineFunctionPass* funcPass = getTarget().createSectLinker(m_Triple,
-                                                               *pLinkerOpt,
-                                                               *ldBackend);
-  if (0 == funcPass)
+  MachineFunctionPass* funcPass = getTarget().createMCLinker(m_Triple,
+                                                             pConfig,
+                                                             pModule,
+                                                             pOutput);
+  if (NULL == funcPass)
     return true;
 
   pPM.add(funcPass);
diff --git a/lib/CodeGen/MCLinker.cpp b/lib/CodeGen/MCLinker.cpp
new file mode 100644
index 0000000..bce4689
--- /dev/null
+++ b/lib/CodeGen/MCLinker.cpp
@@ -0,0 +1,390 @@
+//===- MCLinker.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 MCLinker class.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/CodeGen/MCLinker.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/InputTree.h>
+#include <mcld/Linker.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/FileAction.h>
+#include <mcld/MC/CommandAction.h>
+#include <mcld/Object/ObjectLinker.h>
+#include <mcld/Support/CommandLine.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/MemoryArea.h>
+
+#include <llvm/Module.h>
+#include <llvm/Support/CommandLine.h>
+
+#include <algorithm>
+#include <vector>
+#include <string>
+
+using namespace mcld;
+using namespace llvm;
+
+char MCLinker::m_ID = 0;
+
+//===----------------------------------------------------------------------===//
+// Help Functions
+//===----------------------------------------------------------------------===//
+static inline bool CompareAction(const InputAction* X, const InputAction* Y)
+{
+  return (X->position() < Y->position());
+}
+
+//===----------------------------------------------------------------------===//
+// Positional Options
+// There are four kinds of positional options:
+//   1. Inputs, object files, such as /tmp/XXXX.o
+//   2. Namespecs, short names of libraries. A namespec may refer to an archive
+//      or a shared library. For example, -lm.
+//   3. Attributes of inputs. Attributes describe inputs appears after them.
+//      For example, --as-needed and --whole-archive.
+//   4. Groups. A Group is a set of archives. Linkers repeatedly read archives
+//      in groups until there is no new undefined symbols.
+//   5. Bitcode. Bitcode is a kind of object files. MCLinker compiles it to
+//      object file first, then link it as a object file. (Bitcode is recorded
+//      in BitcodeOption, not be read by LLVM Command Line library.)
+//===----------------------------------------------------------------------===//
+// Inputs
+//===----------------------------------------------------------------------===//
+static cl::list<mcld::sys::fs::Path>
+ArgInputObjectFiles(cl::Positional,
+                    cl::desc("[input object files]"),
+                    cl::ZeroOrMore);
+
+//===----------------------------------------------------------------------===//
+// Namespecs
+//===----------------------------------------------------------------------===//
+static cl::list<std::string>
+ArgNameSpecList("l",
+            cl::ZeroOrMore,
+            cl::desc("Add the archive or object file specified by namespec to "
+                     "the list of files to link."),
+            cl::value_desc("namespec"),
+            cl::Prefix);
+
+static cl::alias
+ArgNameSpecListAlias("library",
+                 cl::desc("alias for -l"),
+                 cl::aliasopt(ArgNameSpecList));
+
+//===----------------------------------------------------------------------===//
+// Attributes
+//===----------------------------------------------------------------------===//
+static cl::list<bool>
+ArgWholeArchiveList("whole-archive",
+               cl::ValueDisallowed,
+               cl::desc("For each archive mentioned on the command line after "
+                        "the --whole-archive option, include all object files "
+                        "in the archive."));
+
+static cl::list<bool>
+ArgNoWholeArchiveList("no-whole-archive",
+               cl::ValueDisallowed,
+               cl::desc("Turn off the effect of the --whole-archive option for "
+                        "subsequent archive files."));
+
+static cl::list<bool>
+ArgAsNeededList("as-needed",
+               cl::ValueDisallowed,
+               cl::desc("This option affects ELF DT_NEEDED tags for dynamic "
+                        "libraries mentioned on the command line after the "
+                        "--as-needed option."));
+
+static cl::list<bool>
+ArgNoAsNeededList("no-as-needed",
+               cl::ValueDisallowed,
+               cl::desc("Turn off the effect of the --as-needed option for "
+                        "subsequent dynamic libraries"));
+
+static cl::list<bool>
+ArgAddNeededList("add-needed",
+                cl::ValueDisallowed,
+                cl::desc("--add-needed causes DT_NEEDED tags are always "
+                         "emitted for those libraries from DT_NEEDED tags. "
+                         "This is the default behavior."));
+
+static cl::list<bool>
+ArgNoAddNeededList("no-add-needed",
+                cl::ValueDisallowed,
+                cl::desc("--no-add-needed causes DT_NEEDED tags will never be "
+                         "emitted for those libraries from DT_NEEDED tags"));
+
+static cl::list<bool>
+ArgBDynamicList("Bdynamic",
+                cl::ValueDisallowed,
+                cl::desc("Link against dynamic library"));
+
+static cl::alias
+ArgBDynamicListAlias1("dy",
+                cl::desc("alias for --Bdynamic"),
+                cl::aliasopt(ArgBDynamicList));
+
+static cl::alias
+ArgBDynamicListAlias2("call_shared",
+                cl::desc("alias for --Bdynamic"),
+                cl::aliasopt(ArgBDynamicList));
+
+static cl::list<bool>
+ArgBStaticList("Bstatic",
+                cl::ValueDisallowed,
+                cl::desc("Link against static library"));
+
+static cl::alias
+ArgBStaticListAlias1("dn",
+                cl::desc("alias for --Bstatic"),
+                cl::aliasopt(ArgBStaticList));
+
+static cl::alias
+ArgBStaticListAlias2("static",
+                cl::desc("alias for --Bstatic"),
+                cl::aliasopt(ArgBStaticList));
+
+static cl::alias
+ArgBStaticListAlias3("non_shared",
+                cl::desc("alias for --Bstatic"),
+                cl::aliasopt(ArgBStaticList));
+
+//===----------------------------------------------------------------------===//
+// Groups
+//===----------------------------------------------------------------------===//
+static cl::list<bool>
+ArgStartGroupList("start-group",
+                  cl::ValueDisallowed,
+                  cl::desc("start to record a group of archives"));
+
+static cl::alias
+ArgStartGroupListAlias("(",
+                       cl::desc("alias for --start-group"),
+                       cl::aliasopt(ArgStartGroupList));
+
+static cl::list<bool>
+ArgEndGroupList("end-group",
+                cl::ValueDisallowed,
+                cl::desc("stop recording a group of archives"));
+
+static cl::alias
+ArgEndGroupListAlias(")",
+                     cl::desc("alias for --end-group"),
+                     cl::aliasopt(ArgEndGroupList));
+
+//===----------------------------------------------------------------------===//
+// MCLinker
+//===----------------------------------------------------------------------===//
+MCLinker::MCLinker(LinkerConfig& pConfig,
+                   mcld::Module& pModule,
+                   MemoryArea& pOutput)
+  : MachineFunctionPass(m_ID),
+    m_Config(pConfig),
+    m_Module(pModule),
+    m_Output(pOutput),
+    m_pBuilder(NULL),
+    m_pLinker(NULL) {
+}
+
+MCLinker::~MCLinker()
+{
+  delete m_pLinker;
+  delete m_pBuilder;
+}
+
+bool MCLinker::doInitialization(llvm::Module &pM)
+{
+  // Now, all input arguments are prepared well, send it into ObjectLinker
+  m_pLinker = new Linker();
+
+  if (!m_pLinker->config(m_Config))
+    return false;
+
+  m_pBuilder = new IRBuilder(m_Module, m_Config);
+
+  initializeInputTree(*m_pBuilder);
+
+  return true;
+}
+
+bool MCLinker::doFinalization(llvm::Module &pM)
+{
+  if (!m_pLinker->link(m_Module, *m_pBuilder))
+    return true;
+
+  if (!m_pLinker->emit(m_Output))
+    return true;
+
+  return false;
+}
+
+bool MCLinker::runOnMachineFunction(MachineFunction& pF)
+{
+  // basically, linkers do nothing during function is generated.
+  return false;
+}
+
+void MCLinker::initializeInputTree(IRBuilder& pBuilder)
+{
+  if (0 == ArgInputObjectFiles.size() &&
+      0 == ArgNameSpecList.size() &&
+      !m_Config.bitcode().hasDefined()) {
+    fatal(diag::err_no_inputs);
+    return;
+  }
+
+  size_t num_actions = ArgInputObjectFiles.size() +
+                       ArgNameSpecList.size() +
+                       ArgWholeArchiveList.size() +
+                       ArgNoWholeArchiveList.size() +
+                       ArgAsNeededList.size() +
+                       ArgNoAsNeededList.size() +
+                       ArgAddNeededList.size() +
+                       ArgNoAddNeededList.size() +
+                       ArgBDynamicList.size() +
+                       ArgBStaticList.size() +
+                       ArgStartGroupList.size() +
+                       ArgEndGroupList.size() +
+                       1; // bitcode
+  std::vector<InputAction*> actions;
+  actions.reserve(num_actions);
+
+  // -----  inputs  ----- //
+  cl::list<mcld::sys::fs::Path>::iterator input, inBegin, inEnd;
+  inBegin = ArgInputObjectFiles.begin();
+  inEnd = ArgInputObjectFiles.end();
+  for (input = inBegin; input != inEnd; ++input) {
+    unsigned int pos = ArgInputObjectFiles.getPosition(input - inBegin);
+    actions.push_back(new InputFileAction(pos, *input));
+    actions.push_back(new ContextAction(pos));
+    actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
+  }
+
+  // -----  namespecs  ----- //
+  cl::list<std::string>::iterator namespec, nsBegin, nsEnd;
+  nsBegin = ArgNameSpecList.begin();
+  nsEnd = ArgNameSpecList.end();
+  for (namespec = nsBegin; namespec != nsEnd; ++namespec) {
+    unsigned int pos = ArgNameSpecList.getPosition(namespec - nsBegin);
+    actions.push_back(new NamespecAction(pos, *namespec,
+                                         m_Config.options().directories()));
+    actions.push_back(new ContextAction(pos));
+    actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
+  }
+
+  // -----  attributes  ----- //
+  /// --whole-archive
+  cl::list<bool>::iterator attr, attrBegin, attrEnd;
+  attrBegin = ArgWholeArchiveList.begin();
+  attrEnd   = ArgWholeArchiveList.end();
+  for (attr = attrBegin; attr != attrEnd; ++attr) {
+    unsigned int pos = ArgWholeArchiveList.getPosition(attr - attrBegin);
+    actions.push_back(new WholeArchiveAction(pos));
+  }
+
+  /// --no-whole-archive
+  attrBegin = ArgNoWholeArchiveList.begin();
+  attrEnd   = ArgNoWholeArchiveList.end();
+  for (attr = attrBegin; attr != attrEnd; ++attr) {
+    unsigned int pos = ArgNoWholeArchiveList.getPosition(attr - attrBegin);
+    actions.push_back(new NoWholeArchiveAction(pos));
+  }
+
+  /// --as-needed
+  attrBegin = ArgAsNeededList.begin();
+  attrEnd   = ArgAsNeededList.end();
+  for (attr = attrBegin; attr != attrEnd; ++attr) {
+    unsigned int pos = ArgAsNeededList.getPosition(attr - attrBegin);
+    actions.push_back(new AsNeededAction(pos));
+  }
+
+  /// --no-as-needed
+  attrBegin = ArgNoAsNeededList.begin();
+  attrEnd   = ArgNoAsNeededList.end();
+  for (attr = attrBegin; attr != attrEnd; ++attr) {
+    unsigned int pos = ArgNoAsNeededList.getPosition(attr - attrBegin);
+    actions.push_back(new NoAsNeededAction(pos));
+  }
+
+  /// --add--needed
+  attrBegin = ArgAddNeededList.begin();
+  attrEnd   = ArgAddNeededList.end();
+  for (attr = attrBegin; attr != attrEnd; ++attr) {
+    unsigned int pos = ArgAddNeededList.getPosition(attr - attrBegin);
+    actions.push_back(new AddNeededAction(pos));
+  }
+
+  /// --no-add--needed
+  attrBegin = ArgNoAddNeededList.begin();
+  attrEnd   = ArgNoAddNeededList.end();
+  for (attr = attrBegin; attr != attrEnd; ++attr) {
+    unsigned int pos = ArgNoAddNeededList.getPosition(attr - attrBegin);
+    actions.push_back(new NoAddNeededAction(pos));
+  }
+
+  /// --Bdynamic
+  attrBegin = ArgBDynamicList.begin();
+  attrEnd   = ArgBDynamicList.end();
+  for (attr = attrBegin; attr != attrEnd; ++attr) {
+    unsigned int pos = ArgBDynamicList.getPosition(attr - attrBegin);
+    actions.push_back(new BDynamicAction(pos));
+  }
+
+  /// --Bstatic
+  attrBegin = ArgBStaticList.begin();
+  attrEnd   = ArgBStaticList.end();
+  for (attr = attrBegin; attr != attrEnd; ++attr) {
+    unsigned int pos = ArgBStaticList.getPosition(attr - attrBegin);
+    actions.push_back(new BStaticAction(pos));
+  }
+
+  // -----  groups  ----- //
+  /// --start-group
+  cl::list<bool>::iterator group, gsBegin, gsEnd;
+  gsBegin = ArgStartGroupList.begin();
+  gsEnd   = ArgStartGroupList.end();
+  for (group = gsBegin; group != gsEnd; ++group) {
+    unsigned int pos = ArgStartGroupList.getPosition(group - gsBegin);
+    actions.push_back(new StartGroupAction(pos));
+  }
+
+  /// --end-group
+  gsBegin = ArgEndGroupList.begin();
+  gsEnd   = ArgEndGroupList.end();
+  for (group = gsBegin; group != gsEnd; ++group) {
+    unsigned int pos = ArgEndGroupList.getPosition(group - gsBegin);
+    actions.push_back(new EndGroupAction(pos));
+  }
+
+  // -----  bitcode  ----- //
+  if (m_Config.bitcode().hasDefined()) {
+    actions.push_back(new BitcodeAction(m_Config.bitcode().getPosition(),
+                                        m_Config.bitcode().getPath()));
+  }
+
+  // stable sort
+  std::stable_sort(actions.begin(), actions.end(), CompareAction);
+
+  // build up input tree
+  std::vector<InputAction*>::iterator action, actionEnd = actions.end();
+  for (action = actions.begin(); action != actionEnd; ++action) {
+    (*action)->activate(pBuilder.getInputBuilder());
+  }
+
+  if (pBuilder.getInputBuilder().isInGroup())
+    report_fatal_error("no matched --start-group and --end-group");
+}
+
diff --git a/lib/CodeGen/SectLinker.cpp b/lib/CodeGen/SectLinker.cpp
deleted file mode 100644
index 0e4c3ad..0000000
--- a/lib/CodeGen/SectLinker.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-//===- SectLinker.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 SectLinker class.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/FileHandle.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/raw_ostream.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Support/DerivedPositionDependentOptions.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/CodeGen/SectLinker.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-#include <llvm/Module.h>
-
-#include <algorithm>
-#include <stack>
-#include <string>
-
-using namespace mcld;
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Forward declarations
-char SectLinker::m_ID = 0;
-static bool CompareOption(const PositionDependentOption* X,
-                          const PositionDependentOption* Y);
-
-//===----------------------------------------------------------------------===//
-// SectLinker
-SectLinker::SectLinker(SectLinkerOption &pOption,
-                       TargetLDBackend& pLDBackend)
-  : MachineFunctionPass(m_ID),
-    m_pOption(&pOption),
-    m_pLDBackend(&pLDBackend),
-    m_pLDDriver(NULL),
-    m_pMemAreaFactory(NULL)
-{
-  m_pMemAreaFactory = new MemoryAreaFactory(32);
-}
-
-SectLinker::~SectLinker()
-{
-  delete m_pLDDriver;
-
-  // FIXME: current implementation can not change the order of delete.
-  //
-  // Instance of TargetLDBackend was created outside and is not managed by
-  // SectLinker. It should not be destroyed here and by SectLinker. However, in
-  // order to follow the LLVM convention - that is, the pass manages all the
-  // objects it used during the processing, we destroy the object of
-  // TargetLDBackend here.
-  delete m_pLDBackend;
-
-  delete m_pMemAreaFactory;
-}
-
-bool SectLinker::doInitialization(Module &pM)
-{
-  MCLDInfo &info = m_pOption->info();
-
-  // ----- convert position dependent options into tree of input files  ----- //
-  PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options();
-  std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption);
-  initializeInputTree(PosDepOpts);
-  initializeInputOutput(info);
-  // Now, all input arguments are prepared well, send it into MCLDDriver
-  m_pLDDriver = new MCLDDriver(info, *m_pLDBackend, *memAreaFactory());
-
-  return false;
-}
-
-bool SectLinker::doFinalization(Module &pM)
-{
-  const MCLDInfo &info = m_pOption->info();
-
-  // 2. - initialize MCLinker
-  if (!m_pLDDriver->initMCLinker())
-    return true;
-
-  // 3. - initialize output's standard sections
-  if (!m_pLDDriver->initStdSections())
-    return true;
-
-  // 4. - normalize the input tree
-  m_pLDDriver->normalize();
-
-  if (info.options().trace()) {
-    static int counter = 0;
-    mcld::outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
-    InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end();
-    for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) {
-      mcld::outs() << counter++ << " *  " << (*input)->name();
-      switch((*input)->type()) {
-      case Input::Archive:
-        mcld::outs() << "\tarchive\t(";
-        break;
-      case Input::Object:
-        mcld::outs() << "\tobject\t(";
-        break;
-      case Input::DynObj:
-        mcld::outs() << "\tshared\t(";
-        break;
-      case Input::Script:
-        mcld::outs() << "\tscript\t(";
-        break;
-      case Input::External:
-        mcld::outs() << "\textern\t(";
-        break;
-      default:
-        unreachable(diag::err_cannot_trace_file) << (*input)->type()
-                                                 << (*input)->name()
-                                                 << (*input)->path();
-      }
-      mcld::outs() << (*input)->path() << ")\n";
-    }
-  }
-
-  // 5. - check if we can do static linking and if we use split-stack.
-  if (!m_pLDDriver->linkable())
-    return true;
-
-
-  // 6. - merge all sections
-  if (!m_pLDDriver->mergeSections())
-    return true;
-
-  // 7. - add standard symbols and target-dependent symbols
-  // m_pLDDriver->addUndefSymbols();
-  if (!m_pLDDriver->addStandardSymbols() ||
-      !m_pLDDriver->addTargetSymbols())
-    return true;
-
-  // 8. - read all relocation entries from input files
-  m_pLDDriver->readRelocations();
-
-  // 9. - pre-layout
-  m_pLDDriver->prelayout();
-
-  // 10. - linear layout
-  m_pLDDriver->layout();
-
-  // 10.b - post-layout (create segment, instruction relaxing)
-  m_pLDDriver->postlayout();
-
-  // 11. - finalize symbol value
-  m_pLDDriver->finalizeSymbolValue();
-
-  // 12. - apply relocations
-  m_pLDDriver->relocation();
-
-  // 13. - write out output
-  m_pLDDriver->emitOutput();
-
-  // 14. - post processing
-  m_pLDDriver->postProcessing();
-  return false;
-}
-
-bool SectLinker::runOnMachineFunction(MachineFunction& pF)
-{
-  // basically, linkers do nothing during function is generated.
-  return false;
-}
-
-void SectLinker::initializeInputOutput(MCLDInfo &pLDInfo)
-{
-  // -----  initialize output file  ----- //
-  FileHandle::Permission perm;
-  if (Output::Object == pLDInfo.output().type())
-    perm = 0544;
-  else
-    perm = 0755;
-
-  MemoryArea* out_area = memAreaFactory()->produce(pLDInfo.output().path(),
-                                                 FileHandle::ReadWrite,
-                                                 perm);
-
-  if (!out_area->handler()->isGood()) {
-    // make sure output is openend successfully.
-    fatal(diag::err_cannot_open_output_file) << pLDInfo.output().name()
-                                             << pLDInfo.output().path();
-  }
-
-  pLDInfo.output().setMemArea(out_area);
-  pLDInfo.output().setContext(pLDInfo.contextFactory().produce());
-
-  // -----  initialize input files  ----- //
-  InputTree::dfs_iterator input, inEnd = pLDInfo.inputs().dfs_end();
-  for (input = pLDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
-    // already got type - for example, bitcode
-    if ((*input)->type() == Input::Script ||
-        (*input)->type() == Input::Object ||
-        (*input)->type() == Input::DynObj  ||
-        (*input)->type() == Input::Archive)
-      continue;
-
-    MemoryArea *input_memory =
-        memAreaFactory()->produce((*input)->path(), FileHandle::ReadOnly);
-
-    if (input_memory->handler()->isGood()) {
-      (*input)->setMemArea(input_memory);
-    }
-    else {
-      error(diag::err_cannot_open_input) << (*input)->name() << (*input)->path();
-      return;
-    }
-
-    LDContext *input_context =
-        pLDInfo.contextFactory().produce((*input)->path());
-
-    (*input)->setContext(input_context);
-  }
-}
-
-void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const
-{
-  if (pPosDepOptions.empty())
-    fatal(diag::err_no_inputs);
-
-  MCLDInfo &info = m_pOption->info();
-  PositionDependentOptions::const_iterator option = pPosDepOptions.begin();
-  if (1 == pPosDepOptions.size() &&
-      ((*option)->type() != PositionDependentOption::INPUT_FILE &&
-       (*option)->type() != PositionDependentOption::NAMESPEC) &&
-       (*option)->type() != PositionDependentOption::BITCODE) {
-    // if we only have one positional options, and the option is
-    // not an input file, then emit error message.
-    fatal(diag::err_no_inputs);
-  }
-
-  // -----  Input tree insertion algorithm  ----- //
-  //   The type of the previsou node indicates the direction of the current
-  //   insertion.
-  //
-  //     root   : the parent node who being inserted.
-  //     mover  : the direcion of current movement.
-  //
-  //   for each positional options:
-  //     insert the options in current root.
-  //     calculate the next movement
-
-  // Initialization
-  InputTree::Mover *move = &InputTree::Downward;
-  InputTree::iterator root = info.inputs().root();
-  PositionDependentOptions::const_iterator optionEnd = pPosDepOptions.end();
-  std::stack<InputTree::iterator> returnStack;
-
-  while (option != optionEnd ) {
-
-    switch ((*option)->type()) {
-      /** bitcode **/
-      case PositionDependentOption::BITCODE: {
-
-        const BitcodeOption *bitcode_option =
-            static_cast<const BitcodeOption*>(*option);
-
-        // threat bitcode as an external IR in this version.
-        info.inputs().insert(root, *move,
-                             bitcode_option->path()->native(),
-                             *(bitcode_option->path()),
-                             Input::External);
-
-        info.setBitcode(**root);
-
-        // move root on the new created node.
-        move->move(root);
-
-        // the next file is appended after bitcode file.
-        move = &InputTree::Afterward;
-        break;
-      }
-
-      /** input object file **/
-      case PositionDependentOption::INPUT_FILE: {
-        const InputFileOption *input_file_option =
-            static_cast<const InputFileOption*>(*option);
-
-        info.inputs().insert(root, *move,
-                             input_file_option->path()->native(),
-                             *(input_file_option->path()));
-
-        // move root on the new created node.
-        move->move(root);
-
-        // the next file is appended after object file.
-        move = &InputTree::Afterward;
-        break;
-      }
-
-    /** -lnamespec **/
-    case PositionDependentOption::NAMESPEC: {
-      sys::fs::Path* path = NULL;
-      const NamespecOption *namespec_option =
-          static_cast<const NamespecOption*>(*option);
-
-      // find out the real path of the namespec.
-      if (info.attrFactory().constraint().isSharedSystem()) {
-        // In the system with shared object support, we can find both archive
-        // and shared object.
-
-        if (info.attrFactory().last().isStatic()) {
-          // with --static, we must search an archive.
-          path = info.options().directories().find(namespec_option->namespec(),
-                                                   Input::Archive);
-        }
-        else {
-          // otherwise, with --Bdynamic, we can find either an archive or a
-          // shared object.
-          path = info.options().directories().find(namespec_option->namespec(),
-                                                   Input::DynObj);
-        }
-      }
-      else {
-        // In the system without shared object support, we only look for an
-        // archive.
-        path = info.options().directories().find(namespec_option->namespec(),
-                                                 Input::Archive);
-      }
-
-      if (NULL == path)
-        fatal(diag::err_cannot_find_namespec) << namespec_option->namespec();
-
-      info.inputs().insert(root, *move,
-                           namespec_option->namespec(),
-                           *path);
-
-      // iterate root on the new created node.
-      move->move(root);
-
-      // the file after a namespec must be appended afterward.
-      move = &InputTree::Afterward;
-      break;
-    }
-
-    /** start group **/
-    case PositionDependentOption::START_GROUP:
-      info.inputs().enterGroup(root, *move);
-      move->move(root);
-      returnStack.push(root);
-      move = &InputTree::Downward;
-      break;
-    /** end group **/
-    case PositionDependentOption::END_GROUP:
-      root = returnStack.top();
-      returnStack.pop();
-      move = &InputTree::Afterward;
-      break;
-    case PositionDependentOption::WHOLE_ARCHIVE:
-      info.attrFactory().last().setWholeArchive();
-      break;
-    case PositionDependentOption::NO_WHOLE_ARCHIVE:
-      info.attrFactory().last().unsetWholeArchive();
-      break;
-    case PositionDependentOption::AS_NEEDED:
-      info.attrFactory().last().setAsNeeded();
-      break;
-    case PositionDependentOption::NO_AS_NEEDED:
-      info.attrFactory().last().unsetAsNeeded();
-      break;
-    case PositionDependentOption::ADD_NEEDED:
-      info.attrFactory().last().setAddNeeded();
-      break;
-    case PositionDependentOption::NO_ADD_NEEDED:
-      info.attrFactory().last().unsetAddNeeded();
-      break;
-    case PositionDependentOption::BSTATIC:
-      info.attrFactory().last().setStatic();
-      break;
-    case PositionDependentOption::BDYNAMIC:
-      info.attrFactory().last().setDynamic();
-      break;
-    default:
-      fatal(diag::err_cannot_identify_option) << (*option)->position()
-                                              << (uint32_t)(*option)->type();
-    } // end of switch
-    ++option;
-  } // end of while
-
-  if (!returnStack.empty()) {
-    report_fatal_error("no matched --start-group and --end-group");
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// Non-member functions
-static bool CompareOption(const PositionDependentOption* X,
-                          const PositionDependentOption* Y)
-{
-  return (X->position() < Y->position());
-}
-
diff --git a/lib/CodeGen/SectLinkerOption.cpp b/lib/CodeGen/SectLinkerOption.cpp
deleted file mode 100644
index 85d6b10..0000000
--- a/lib/CodeGen/SectLinkerOption.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- SectLinkerOption.cpp -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/CodeGen/SectLinkerOption.h"
-#include "mcld/Support/DerivedPositionDependentOptions.h"
-#include "mcld/Support/RealPath.h"
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// SectLinkerOption
-SectLinkerOption::SectLinkerOption(MCLDInfo &pLDInfo)
-  : m_pLDInfo(&pLDInfo) { }
-
-SectLinkerOption::~SectLinkerOption() {
-  for (PositionDependentOptions::iterator pdoption = m_PosDepOptions.begin(),
-       pdoptionEnd = m_PosDepOptions.end(); pdoption != pdoptionEnd; ++pdoption)
-    delete *pdoption;
-}
diff --git a/lib/Core/Android.mk b/lib/Core/Android.mk
new file mode 100644
index 0000000..c30d80c
--- /dev/null
+++ b/lib/Core/Android.mk
@@ -0,0 +1,37 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_core_SRC_FILES := \
+  AttributeOption.cpp \
+  BitcodeOption.cpp \
+  Environment.cpp \
+  GeneralOptions.cpp \
+  IRBuilder.cpp \
+  InputTree.cpp \
+  LinkerConfig.cpp  \
+  Linker.cpp \
+  Module.cpp \
+  ScriptOptions.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_core_SRC_FILES)
+LOCAL_MODULE:= libmcldCore
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_core_SRC_FILES)
+LOCAL_MODULE:= libmcldCore
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/lib/LD/CIE.cpp b/lib/Core/AttributeOption.cpp
similarity index 64%
copy from lib/LD/CIE.cpp
copy to lib/Core/AttributeOption.cpp
index 5ddb166..d2a7947 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/Core/AttributeOption.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- AttributeOption.cpp ------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,18 +6,17 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/AttributeOption.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// CIE
+// AttributeOption
 //===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
-  : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+AttributeOption::AttributeOption()
+{
 }
 
-CIE::~CIE()
+AttributeOption::~AttributeOption()
 {
 }
diff --git a/lib/LD/CIE.cpp b/lib/Core/BitcodeOption.cpp
similarity index 62%
copy from lib/LD/CIE.cpp
copy to lib/Core/BitcodeOption.cpp
index 5ddb166..47d6667 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/Core/BitcodeOption.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- BitcodeOption.cpp --------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,18 +6,22 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/BitcodeOption.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// CIE
+// BitcodeOption
 //===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
-  : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+BitcodeOption::BitcodeOption()
+  : m_Position(-1) {
 }
 
-CIE::~CIE()
+BitcodeOption::~BitcodeOption()
 {
 }
+
+bool BitcodeOption::hasDefined() const
+{
+  return (m_Position != -1);
+}
diff --git a/lib/Core/Environment.cpp b/lib/Core/Environment.cpp
new file mode 100644
index 0000000..5755fe7
--- /dev/null
+++ b/lib/Core/Environment.cpp
@@ -0,0 +1,29 @@
+//===- Environment.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Environment.h>
+#include <mcld/Support/TargetSelect.h>
+
+void mcld::Initialize()
+{
+  static bool is_initialized = false;
+
+  if (is_initialized)
+    return;
+
+  mcld::InitializeAllTargets();
+  mcld::InitializeAllEmulations();
+  mcld::InitializeAllDiagnostics();
+
+  is_initialized = true;
+}
+
+void mcld::Finalize()
+{
+}
+
diff --git a/lib/MC/MCLDOptions.cpp b/lib/Core/GeneralOptions.cpp
similarity index 83%
rename from lib/MC/MCLDOptions.cpp
rename to lib/Core/GeneralOptions.cpp
index 47dbc35..902f753 100644
--- a/lib/MC/MCLDOptions.cpp
+++ b/lib/Core/GeneralOptions.cpp
@@ -1,4 +1,4 @@
-//===- MCLDOptions.cpp ----------------------------------------------------===//
+//===- GeneralOptions.cpp -------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,23 +6,14 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLDOptions.h>
+#include <mcld/GeneralOptions.h>
 #include <mcld/MC/MCLDInput.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// ScriptOptions
-ScriptOptions::ScriptOptions()
-{
-}
-
-ScriptOptions::~ScriptOptions()
-{
-}
-
-//===----------------------------------------------------------------------===//
 // GeneralOptions
+//===----------------------------------------------------------------------===//
 GeneralOptions::GeneralOptions()
   : m_pDefaultBitcode(NULL),
     m_Verbose(-1),
@@ -51,7 +42,12 @@
     m_bPIE(false),
     m_bColor(true),
     m_bAllowShlibUndefined(true),
-    m_bCreateEhFrameHdr(false)
+    m_bCreateEhFrameHdr(false),
+    m_NMagic(false),
+    m_OMagic(false),
+    m_StripDebug(false),
+    m_ExportDynamic(false),
+    m_WarnSharedTextrel(false)
 {
 }
 
@@ -73,9 +69,23 @@
 {
 }
 
+const mcld::sys::fs::Path& GeneralOptions::sysroot() const
+{
+  return m_SearchDirs.sysroot();
+}
+
 void GeneralOptions::setSysroot(const mcld::sys::fs::Path &pSysroot)
 {
-  m_Sysroot.assign(pSysroot);
+  m_SearchDirs.setSysRoot(pSysroot);
+}
+
+void GeneralOptions::setSOName(const std::string& pName)
+{
+  size_t pos = pName.find_last_of(sys::fs::separator);
+  if (std::string::npos == pos)
+    m_SOName = pName;
+  else
+    m_SOName = pName.substr(pos + 1);
 }
 
 void GeneralOptions::addZOption(const ZOption& pOption)
diff --git a/lib/Core/IRBuilder.cpp b/lib/Core/IRBuilder.cpp
new file mode 100644
index 0000000..58c1360
--- /dev/null
+++ b/lib/Core/IRBuilder.cpp
@@ -0,0 +1,413 @@
+//===- IRBuilder.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/IRBuilder.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>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Helper Functions
+//===----------------------------------------------------------------------===//
+LDFileFormat::Kind GetELFSectionKind(uint32_t pType, const char* pName)
+{
+  // name rules
+  llvm::StringRef name(pName);
+  if (name.startswith(".debug") ||
+      name.startswith(".zdebug") ||
+      name.startswith(".gnu.linkonce.wi.") ||
+      name.startswith(".line") ||
+      name.startswith(".stab"))
+    return LDFileFormat::Debug;
+  if (name.startswith(".comment"))
+    return LDFileFormat::MetaData;
+  if (name.startswith(".interp") || name.startswith(".dynamic"))
+    return LDFileFormat::Note;
+  if (name.startswith(".eh_frame"))
+    return LDFileFormat::EhFrame;
+  if (name.startswith(".eh_frame_hdr"))
+    return LDFileFormat::EhFrameHdr;
+  if (name.startswith(".gcc_except_table"))
+    return LDFileFormat::GCCExceptTable;
+  if (name.startswith(".note.GNU-stack"))
+    return LDFileFormat::StackNote;
+
+  // type rules
+  switch(pType) {
+  case llvm::ELF::SHT_NULL:
+    return LDFileFormat::Null;
+  case llvm::ELF::SHT_INIT_ARRAY:
+  case llvm::ELF::SHT_FINI_ARRAY:
+  case llvm::ELF::SHT_PREINIT_ARRAY:
+  case llvm::ELF::SHT_PROGBITS:
+    return LDFileFormat::Regular;
+  case llvm::ELF::SHT_SYMTAB:
+  case llvm::ELF::SHT_DYNSYM:
+  case llvm::ELF::SHT_STRTAB:
+  case llvm::ELF::SHT_HASH:
+  case llvm::ELF::SHT_DYNAMIC:
+    return LDFileFormat::NamePool;
+  case llvm::ELF::SHT_RELA:
+  case llvm::ELF::SHT_REL:
+    return LDFileFormat::Relocation;
+  case llvm::ELF::SHT_NOBITS:
+    return LDFileFormat::BSS;
+  case llvm::ELF::SHT_NOTE:
+    return LDFileFormat::Note;
+  case llvm::ELF::SHT_GROUP:
+    return LDFileFormat::Group;
+  case llvm::ELF::SHT_GNU_versym:
+  case llvm::ELF::SHT_GNU_verdef:
+  case llvm::ELF::SHT_GNU_verneed:
+    return LDFileFormat::Version;
+  case llvm::ELF::SHT_SHLIB:
+    return LDFileFormat::Target;
+  default:
+    if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) ||
+        (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) ||
+        (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER))
+      return LDFileFormat::Target;
+    fatal(diag::err_unsupported_section) << pName << pType;
+  }
+  return LDFileFormat::MetaData;
+}
+
+//===----------------------------------------------------------------------===//
+// IRBuilder
+//===----------------------------------------------------------------------===//
+IRBuilder::IRBuilder(Module& pModule, const LinkerConfig& pConfig)
+  : m_Module(pModule), m_Config(pConfig), m_InputBuilder(pConfig) {
+  m_InputBuilder.setCurrentTree(m_Module.getInputTree());
+}
+
+IRBuilder::~IRBuilder()
+{
+}
+
+/// CreateInput - To create an input file and append it to the input tree.
+Input* IRBuilder::CreateInput(const std::string& pName,
+                              const sys::fs::Path& pPath, Input::Type pType)
+{
+  if (Input::Unknown == pType)
+    return ReadInput(pName, pPath);
+
+  m_InputBuilder.createNode<InputTree::Positional>(pName, pPath, pType);
+  Input* input = *m_InputBuilder.getCurrentNode();
+
+  if (!input->hasContext())
+    m_InputBuilder.setContext(*input, false);
+
+  return input;
+}
+
+/// ReadInput - To read an input file and append it to the input tree.
+Input*
+IRBuilder::ReadInput(const std::string& pName, const sys::fs::Path& pPath)
+{
+  m_InputBuilder.createNode<InputTree::Positional>(pName, pPath, Input::Unknown);
+  Input* input = *m_InputBuilder.getCurrentNode();
+
+  if (!input->hasContext())
+    m_InputBuilder.setContext(*input);
+
+  if (!input->hasMemArea())
+    m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System);
+
+  return input;
+}
+
+/// ReadInput - To read an input file and append it to the input tree.
+Input* IRBuilder::ReadInput(const std::string& pNameSpec)
+{
+  const sys::fs::Path* path = NULL;
+  // find out the real path of the namespec.
+  if (m_InputBuilder.getConstraint().isSharedSystem()) {
+    // In the system with shared object support, we can find both archive
+    // and shared object.
+
+    if (m_InputBuilder.getAttributes().isStatic()) {
+      // with --static, we must search an archive.
+      path = m_Config.options().directories().find(pNameSpec, Input::Archive);
+    }
+    else {
+      // otherwise, with --Bdynamic, we can find either an archive or a
+      // shared object.
+      path = m_Config.options().directories().find(pNameSpec, Input::DynObj);
+    }
+  }
+  else {
+    // In the system without shared object support, we only look for an archive
+    path = m_Config.options().directories().find(pNameSpec, Input::Archive);
+  }
+
+  if (NULL == path) {
+    fatal(diag::err_cannot_find_namespec) << pNameSpec;
+    return NULL;
+  }
+
+  m_InputBuilder.createNode<InputTree::Positional>(pNameSpec, *path);
+  Input* input = *m_InputBuilder.getCurrentNode();
+
+  if (!input->hasContext())
+    m_InputBuilder.setContext(*input);
+
+  if (!input->hasMemArea())
+    m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System);
+
+  return input;
+}
+
+/// 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",
+                                                   pFileHandle.path());
+
+  Input* input = *m_InputBuilder.getCurrentNode();
+  if (pFileHandle.path().empty()) {
+    m_InputBuilder.setContext(*input, false);
+    m_InputBuilder.setMemory(*input, pFileHandle.handler(), FileHandle::ReadOnly);
+  }
+  else {
+    m_InputBuilder.setContext(*input, true);
+    m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System);
+  }
+
+  return input;
+}
+
+/// ReadInput - To read an input file and append it to the input tree.
+Input* IRBuilder::ReadInput(const std::string& pName, void* pRawMemory, size_t pSize)
+{
+  m_InputBuilder.createNode<InputTree::Positional>(pName, "NAN");
+  Input* input = *m_InputBuilder.getCurrentNode();
+  m_InputBuilder.setContext(*input, false);
+  m_InputBuilder.setMemory(*input, pRawMemory, pSize);
+  return input;
+}
+
+bool IRBuilder::StartGroup()
+{
+  if (m_InputBuilder.isInGroup()) {
+    fatal(diag::fatal_forbid_nest_group);
+    return false;
+  }
+  m_InputBuilder.enterGroup();
+  return true;
+}
+
+bool IRBuilder::EndGroup()
+{
+  m_InputBuilder.exitGroup();
+  return true;
+}
+
+void IRBuilder::WholeArchive()
+{
+  m_InputBuilder.getAttributes().setWholeArchive();
+}
+
+void IRBuilder::NoWholeArchive()
+{
+  m_InputBuilder.getAttributes().unsetWholeArchive();
+}
+
+void IRBuilder::AsNeeded()
+{
+  m_InputBuilder.getAttributes().setAsNeeded();
+}
+
+void IRBuilder::NoAsNeeded()
+{
+  m_InputBuilder.getAttributes().unsetAsNeeded();
+}
+
+void IRBuilder::CopyDTNeeded()
+{
+  m_InputBuilder.getAttributes().setAddNeeded();
+}
+
+void IRBuilder::NoCopyDTNeeded()
+{
+  m_InputBuilder.getAttributes().unsetAddNeeded();
+}
+
+void IRBuilder::AgainstShared()
+{
+  m_InputBuilder.getAttributes().setDynamic();
+}
+
+void IRBuilder::AgainstStatic()
+{
+  m_InputBuilder.getAttributes().setStatic();
+}
+
+LDSection* IRBuilder::CreateELFHeader(Input& pInput,
+                                      const std::string& pName,
+                                      uint32_t pType,
+                                      uint32_t pFlag,
+                                      uint32_t pAlign)
+{
+  // Create section header
+  LDFileFormat::Kind kind = GetELFSectionKind(pType, pName.c_str());
+  LDSection* header = LDSection::Create(pName, kind, pType, pFlag);
+  header->setAlign(pAlign);
+
+  // Append section header in input
+  pInput.context()->appendSection(*header);
+  return header;
+}
+
+/// CreateSectionData - To create a section data for given pSection.
+SectionData* IRBuilder::CreateSectionData(LDSection& pSection)
+{
+  assert(!pSection.hasSectionData() && "pSection already has section data.");
+
+  SectionData* sect_data = SectionData::Create(pSection);
+  pSection.setSectionData(sect_data);
+  return sect_data;
+}
+
+/// CreateRelocData - To create a relocation data for given pSection.
+RelocData* IRBuilder::CreateRelocData(LDSection &pSection)
+{
+  assert(!pSection.hasRelocData() && "pSection already has relocation data.");
+
+  RelocData* reloc_data = RelocData::Create(pSection);
+  pSection.setRelocData(reloc_data);
+  return reloc_data;
+}
+
+/// CreateEhFrame - To create a eh_frame for given pSection
+EhFrame* IRBuilder::CreateEhFrame(LDSection& pSection)
+{
+  assert(!pSection.hasEhFrame() && "pSection already has eh_frame.");
+
+  EhFrame* eh_frame = new EhFrame(pSection);
+  pSection.setEhFrame(eh_frame);
+  return eh_frame;
+}
+
+/// CreateBSS - To create a bss section for given pSection
+SectionData* IRBuilder::CreateBSS(LDSection& pSection)
+{
+  assert(!pSection.hasSectionData() && "pSection already has section data.");
+  assert((pSection.kind() == LDFileFormat::BSS) && "pSection is not a BSS section.");
+
+  SectionData* sect_data = SectionData::Create(pSection);
+  pSection.setSectionData(sect_data);
+
+                                   /*  value, valsize, size*/
+  FillFragment* frag = new FillFragment(0x0, 1, pSection.size());
+
+  ObjectBuilder::AppendFragment(*frag, *sect_data);
+  return sect_data;
+}
+
+/// CreateRegion - To create a region fragment in the input file.
+Fragment* IRBuilder::CreateRegion(Input& pInput, size_t pOffset, size_t pLength)
+{
+  if (!pInput.hasMemArea()) {
+    fatal(diag::fatal_cannot_read_input) << pInput.path();
+    return NULL;
+  }
+
+  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);
+}
+
+/// CreateRegion - To create a region fragment wrapping the given memory
+Fragment* IRBuilder::CreateRegion(void* pMemory, size_t pLength)
+{
+  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);
+}
+
+/// AppendFragment - To append pFrag to the given SectionData pSD
+uint64_t IRBuilder::AppendFragment(Fragment& pFrag, SectionData& pSD)
+{
+  uint64_t size = ObjectBuilder::AppendFragment(pFrag,
+                                                pSD,
+                                                pSD.getSection().align());
+  pSD.getSection().setSize(pSD.getSection().size() + size);
+  return size;
+}
+
+/// AppendRelocation - To append an relocation to the given RelocData pRD.
+void IRBuilder::AppendRelocation(Relocation& pRelocation, RelocData& pRD)
+{
+  pRD.getFragmentList().push_back(&pRelocation);
+}
+
+/// AppendEhFrame - To append a fragment to EhFrame.
+uint64_t IRBuilder::AppendEhFrame(Fragment& pFrag, EhFrame& pEhFrame)
+{
+  uint64_t size = ObjectBuilder::AppendFragment(pFrag,
+                              pEhFrame.getSectionData(),
+                              pEhFrame.getSection().align());
+  pEhFrame.getSection().setSize(pEhFrame.getSection().size() + size);
+  return size;
+}
+
+/// AppendEhFrame - To append a FDE to the given EhFrame pEhFram.
+uint64_t IRBuilder::AppendEhFrame(EhFrame::FDE& pFDE, EhFrame& pEhFrame)
+{
+  pEhFrame.addFDE(pFDE);
+  pEhFrame.getSection().setSize(pEhFrame.getSection().size() + pFDE.size());
+  return pFDE.size();
+}
+
+/// AppendEhFrame - To append a CIE to the given EhFrame pEhFram.
+uint64_t IRBuilder::AppendEhFrame(EhFrame::CIE& pCIE, EhFrame& pEhFrame)
+{
+  pEhFrame.addCIE(pCIE);
+  pEhFrame.getSection().setSize(pEhFrame.getSection().size() + pCIE.size());
+  return pCIE.size();
+}
+
diff --git a/lib/MC/InputTree.cpp b/lib/Core/InputTree.cpp
similarity index 66%
rename from lib/MC/InputTree.cpp
rename to lib/Core/InputTree.cpp
index 1416b6a..15f6f5e 100644
--- a/lib/MC/InputTree.cpp
+++ b/lib/Core/InputTree.cpp
@@ -6,8 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/InputFactory.h>
+#include <mcld/InputTree.h>
 
 using namespace mcld;
 
@@ -16,15 +15,8 @@
 
 //===----------------------------------------------------------------------===//
 // InputTree
-InputTree::InputTree(InputFactory& pInputFactory)
-  : m_FileFactory(pInputFactory) {
-}
-
-InputTree::~InputTree()
-{
-}
-
-InputTree& InputTree::merge(TreeIteratorBase pRoot, 
+//===----------------------------------------------------------------------===//
+InputTree& InputTree::merge(TreeIteratorBase pRoot,
                             const InputTree::Mover& pMover,
                             InputTree& pTree)
 {
@@ -41,18 +33,6 @@
   return *this;
 }
 
-InputTree& InputTree::insert(TreeIteratorBase pRoot,
-                             const InputTree::Mover& pMover,
-                             const std::string& pNamespec,
-                             const sys::fs::Path& pPath,
-                             unsigned int pType)
-{
-  BinaryTree<Input>::node_type* node = createNode();
-  node->data = m_FileFactory.produce(pNamespec, pPath, pType);
-  pMover.connect(pRoot, iterator(node));
-  return *this;
-}
-
 InputTree& InputTree::enterGroup(TreeIteratorBase pRoot,
                                  const InputTree::Mover& pMover)
 {
@@ -63,45 +43,44 @@
 
 InputTree& InputTree::insert(TreeIteratorBase pRoot,
                              const InputTree::Mover& pMover,
-                             const mcld::Input& pInput)
+                             mcld::Input& pInput)
 {
   BinaryTree<Input>::node_type* node = createNode();
-  node->data = const_cast<mcld::Input*>(&pInput);
+  node->data = &pInput;
   pMover.connect(pRoot, iterator(node));
   return *this;
 }
 
-
-
 //===----------------------------------------------------------------------===//
 // non-member functions
+//===----------------------------------------------------------------------===//
 bool mcld::isGroup(const InputTree::iterator& pos)
 {
-  return !pos.hasData();
+  return !pos.hasData() && !pos.isRoot();
 }
 
 bool mcld::isGroup(const InputTree::const_iterator& pos)
 {
-  return !pos.hasData();
+  return !pos.hasData() && !pos.isRoot();
 }
 
 bool mcld::isGroup(const InputTree::dfs_iterator& pos)
 {
-  return !pos.hasData();
+  return !pos.hasData() && !pos.isRoot();
 }
 
 bool mcld::isGroup(const InputTree::const_dfs_iterator& pos)
 {
-  return !pos.hasData();
+  return !pos.hasData() && !pos.isRoot();
 }
 
 bool mcld::isGroup(const InputTree::bfs_iterator& pos)
 {
-  return !pos.hasData();
+  return !pos.hasData() && !pos.isRoot();
 }
 
 bool mcld::isGroup(const InputTree::const_bfs_iterator& pos)
 {
-  return !pos.hasData();
+  return !pos.hasData() && !pos.isRoot();
 }
 
diff --git a/lib/Core/Linker.cpp b/lib/Core/Linker.cpp
new file mode 100644
index 0000000..7262537
--- /dev/null
+++ b/lib/Core/Linker.cpp
@@ -0,0 +1,257 @@
+//===- Linker.cpp ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Linker.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Module.h>
+#include <mcld/IRBuilder.h>
+
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/raw_ostream.h>
+
+#include <mcld/Object/ObjectLinker.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/FragmentRef.h>
+
+#include <cassert>
+
+using namespace mcld;
+
+Linker::Linker()
+  : m_pConfig(NULL), m_pModule(NULL), m_pIRBuilder(NULL),
+    m_pTarget(NULL), m_pBackend(NULL), m_pObjLinker(NULL) {
+}
+
+Linker::~Linker()
+{
+  reset();
+}
+
+bool Linker::config(LinkerConfig& pConfig)
+{
+  m_pConfig = &pConfig;
+
+  if (!initTarget())
+    return false;
+
+  if (!initBackend())
+    return false;
+
+  if (!initEmulator())
+    return false;
+
+  if (!initOStream())
+    return false;
+
+  return true;
+}
+
+bool Linker::link(Module& pModule, IRBuilder& pBuilder)
+{
+  assert(NULL != m_pConfig);
+
+  m_pIRBuilder = &pBuilder;
+  m_pObjLinker = new ObjectLinker(*m_pConfig,
+                                  pModule,
+                                  m_pIRBuilder->getInputBuilder(),
+                                  *m_pBackend);
+
+  // 2. - initialize FragmentLinker
+  if (!m_pObjLinker->initFragmentLinker())
+    return false;
+
+  // 3. - initialize output's standard sections
+  if (!m_pObjLinker->initStdSections())
+    return false;
+
+  // 4. - normalize the input tree
+  m_pObjLinker->normalize();
+
+  if (m_pConfig->options().trace()) {
+    static int counter = 0;
+    mcld::outs() << "** name\ttype\tpath\tsize (" << pModule.getInputTree().size() << ")\n";
+    InputTree::const_dfs_iterator input, inEnd = pModule.getInputTree().dfs_end();
+    for (input=pModule.getInputTree().dfs_begin(); input!=inEnd; ++input) {
+      mcld::outs() << counter++ << " *  " << (*input)->name();
+      switch((*input)->type()) {
+      case Input::Archive:
+        mcld::outs() << "\tarchive\t(";
+        break;
+      case Input::Object:
+        mcld::outs() << "\tobject\t(";
+        break;
+      case Input::DynObj:
+        mcld::outs() << "\tshared\t(";
+        break;
+      case Input::Script:
+        mcld::outs() << "\tscript\t(";
+        break;
+      case Input::External:
+        mcld::outs() << "\textern\t(";
+        break;
+      default:
+        unreachable(diag::err_cannot_trace_file) << (*input)->type()
+                                                 << (*input)->name()
+                                                 << (*input)->path();
+      }
+      mcld::outs() << (*input)->path() << ")\n";
+    }
+  }
+
+  // 5. - check if we can do static linking and if we use split-stack.
+  if (!m_pObjLinker->linkable())
+    return Diagnose();
+
+  // 6. - read all relocation entries from input files
+  m_pObjLinker->readRelocations();
+
+  // 7. - merge all sections
+  if (!m_pObjLinker->mergeSections())
+    return false;
+
+  // 8. - add standard symbols and target-dependent symbols
+  // m_pObjLinker->addUndefSymbols();
+  if (!m_pObjLinker->addStandardSymbols() ||
+      !m_pObjLinker->addTargetSymbols())
+    return false;
+
+  // 9. - scan all relocation entries by output symbols.
+  m_pObjLinker->scanRelocations();
+
+  // 10.a - pre-layout
+  m_pObjLinker->prelayout();
+
+  // 10.b - linear layout
+  m_pObjLinker->layout();
+
+  // 10.c - post-layout (create segment, instruction relaxing)
+  m_pObjLinker->postlayout();
+
+  // 11. - finalize symbol value
+  m_pObjLinker->finalizeSymbolValue();
+
+  // 12. - apply relocations
+  m_pObjLinker->relocation();
+
+  if (!Diagnose())
+    return false;
+  return true;
+}
+
+bool Linker::emit(MemoryArea& pOutput)
+{
+  // 13. - write out output
+  m_pObjLinker->emitOutput(pOutput);
+
+  // 14. - post processing
+  m_pObjLinker->postProcessing(pOutput);
+
+  if (!Diagnose())
+    return false;
+
+  return true;
+}
+
+bool Linker::emit(const std::string& pPath)
+{
+  FileHandle file;
+  FileHandle::Permission perm = 0755;
+  if (!file.open(pPath,
+            FileHandle::ReadWrite | FileHandle::Truncate | FileHandle::Create,
+            perm)) {
+    error(diag::err_cannot_open_output_file) << "Linker::emit()" << pPath;
+    return false;
+  }
+
+  MemoryArea* output = new MemoryArea(file);
+
+  bool result = emit(*output);
+
+  delete output;
+  file.close();
+  return result;
+}
+
+bool Linker::emit(int pFileDescriptor)
+{
+  FileHandle file;
+  file.delegate(pFileDescriptor);
+  MemoryArea* output = new MemoryArea(file);
+
+  bool result = emit(*output);
+
+  delete output;
+  file.close();
+  return result;
+}
+
+bool Linker::reset()
+{
+  m_pConfig = NULL;
+  m_pModule = NULL;
+  m_pIRBuilder = NULL;
+  m_pTarget = NULL;
+
+  delete m_pBackend;
+  m_pBackend = NULL;
+
+  delete m_pObjLinker;
+  m_pObjLinker = NULL;
+
+  LDSection::Clear();
+  LDSymbol::Clear();
+  FragmentRef::Clear();
+  return true;
+}
+
+bool Linker::initTarget()
+{
+  assert(NULL != m_pConfig);
+
+  std::string error;
+  m_pTarget = TargetRegistry::lookupTarget(m_pConfig->triple().str(), error);
+  if (NULL == m_pTarget) {
+    fatal(diag::fatal_cannot_init_target) << m_pConfig->triple().str() << error;
+    return false;
+  }
+  return true;
+}
+
+bool Linker::initBackend()
+{
+  assert(NULL != m_pTarget);
+  m_pBackend = m_pTarget->createLDBackend(*m_pConfig);
+  if (NULL == m_pBackend) {
+    fatal(diag::fatal_cannot_init_backend) << m_pConfig->triple().str();
+    return false;
+  }
+  return true;
+}
+
+bool Linker::initEmulator()
+{
+  assert(NULL != m_pTarget && NULL != m_pConfig);
+  return m_pTarget->emulate(m_pConfig->triple().str(), *m_pConfig);
+}
+
+bool Linker::initOStream()
+{
+  assert(NULL != m_pConfig);
+
+  mcld::outs().setColor(m_pConfig->options().color());
+  mcld::errs().setColor(m_pConfig->options().color());
+
+  return true;
+}
+
diff --git a/lib/Core/LinkerConfig.cpp b/lib/Core/LinkerConfig.cpp
new file mode 100644
index 0000000..d94bbe2
--- /dev/null
+++ b/lib/Core/LinkerConfig.cpp
@@ -0,0 +1,62 @@
+//===- LinkerConfig.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LinkerConfig.h>
+#include <mcld/Config/Config.h>
+
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// LinkerConfig
+//===----------------------------------------------------------------------===//
+LinkerConfig::LinkerConfig()
+  : m_Options(),
+    m_Scripts(),
+    m_Bitcode(),
+    m_Attribute(),
+    m_Triple(),
+    m_CodeGenType(Unknown)
+{
+  // FIXME: is here the right place to hold this?
+  InitializeDiagnosticEngine(*this);
+}
+
+LinkerConfig::LinkerConfig(const std::string& pTripleString)
+  : m_Options(),
+    m_Scripts(),
+    m_Bitcode(),
+    m_Attribute(),
+    m_Triple(pTripleString),
+    m_CodeGenType(Unknown)
+{
+  // FIXME: is here the right place to hold this?
+  InitializeDiagnosticEngine(*this);
+}
+
+LinkerConfig::~LinkerConfig()
+{
+  // FIXME: is here the right place to hold this?
+  FinalizeDiagnosticEngine();
+}
+
+void LinkerConfig::setTriple(const llvm::Triple& pTriple)
+{
+  m_Triple = pTriple;
+}
+
+void LinkerConfig::setTriple(const std::string& pTriple)
+{
+  m_Triple.setTriple(pTriple);
+}
+
+const char* LinkerConfig::version()
+{
+  return MCLD_VERSION;
+}
diff --git a/lib/Core/Module.cpp b/lib/Core/Module.cpp
new file mode 100644
index 0000000..e186aaf
--- /dev/null
+++ b/lib/Core/Module.cpp
@@ -0,0 +1,56 @@
+//===- Module.cpp ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Module.h>
+#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/NamePool.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/StaticResolver.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Module
+//===----------------------------------------------------------------------===//
+Module::Module()
+  : m_NamePool(1024) {
+}
+
+Module::Module(const std::string& pName)
+  : m_Name(pName), m_NamePool(1024) {
+}
+
+Module::~Module()
+{
+}
+
+// Following two functions will be obsolette when we have new section merger.
+LDSection* Module::getSection(const std::string& pName)
+{
+  iterator sect, sectEnd = end();
+  for (sect = begin(); sect != sectEnd; ++sect) {
+    if ((*sect)->name() == pName)
+      return *sect;
+  }
+  return NULL;
+}
+
+const LDSection* Module::getSection(const std::string& pName) const
+{
+  const_iterator sect, sectEnd = end();
+  for (sect = begin(); sect != sectEnd; ++sect) {
+    if ((*sect)->name() == pName)
+      return *sect;
+  }
+  return NULL;
+}
+
diff --git a/lib/LD/CIE.cpp b/lib/Core/ScriptOptions.cpp
similarity index 64%
copy from lib/LD/CIE.cpp
copy to lib/Core/ScriptOptions.cpp
index 5ddb166..930eeea 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/Core/ScriptOptions.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- ScriptOptions.cpp --------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,18 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/ScriptOptions.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// CIE
+// ScriptOptions
 //===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
-  : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
-}
-
-CIE::~CIE()
+ScriptOptions::ScriptOptions()
 {
 }
+
+ScriptOptions::~ScriptOptions()
+{
+}
+
diff --git a/lib/LD/AlignFragment.cpp b/lib/Fragment/AlignFragment.cpp
similarity index 74%
rename from lib/LD/AlignFragment.cpp
rename to lib/Fragment/AlignFragment.cpp
index 5154b0b..7cc1065 100644
--- a/lib/LD/AlignFragment.cpp
+++ b/lib/Fragment/AlignFragment.cpp
@@ -6,8 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/LD/AlignFragment.h>
+#include <mcld/Fragment/AlignFragment.h>
 
+#include <llvm/Support/MathExtras.h>
 #include <mcld/LD/SectionData.h>
 
 using namespace mcld;
@@ -25,3 +26,13 @@
     m_bEmitNops(false) {
 }
 
+size_t AlignFragment::size() const
+{
+  assert(hasOffset() && "AlignFragment::size() should not be called before layout.");
+  uint64_t size = llvm::OffsetToAlignment(getOffset(), m_Alignment);
+  if (size > m_MaxBytesToEmit)
+    return 0;
+
+  return size;
+}
+
diff --git a/lib/Fragment/Android.mk b/lib/Fragment/Android.mk
new file mode 100644
index 0000000..0da2051
--- /dev/null
+++ b/lib/Fragment/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_fragment_SRC_FILES := \
+  AlignFragment.cpp \
+  FillFragment.cpp \
+  Fragment.cpp \
+  FragmentLinker.cpp \
+  FragmentRef.cpp \
+  NullFragment.cpp \
+  RegionFragment.cpp \
+  Relocation.cpp \
+  Stub.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_fragment_SRC_FILES)
+LOCAL_MODULE:= libmcldFragment
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_fragment_SRC_FILES)
+LOCAL_MODULE:= libmcldFragment
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/lib/LD/FillFragment.cpp b/lib/Fragment/FillFragment.cpp
similarity index 95%
rename from lib/LD/FillFragment.cpp
rename to lib/Fragment/FillFragment.cpp
index 8f127ca..16de4f0 100644
--- a/lib/LD/FillFragment.cpp
+++ b/lib/Fragment/FillFragment.cpp
@@ -6,8 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#include <mcld/LD/FillFragment.h>
+#include <mcld/Fragment/FillFragment.h>
 #include <mcld/LD/SectionData.h>
 #include <cassert>
 
diff --git a/lib/LD/Fragment.cpp b/lib/Fragment/Fragment.cpp
similarity index 67%
rename from lib/LD/Fragment.cpp
rename to lib/Fragment/Fragment.cpp
index 6e1e3a7..df66694 100644
--- a/lib/LD/Fragment.cpp
+++ b/lib/Fragment/Fragment.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
 
 #include <llvm/Support/DataTypes.h>
 
@@ -19,11 +19,11 @@
 // Fragment
 //===----------------------------------------------------------------------===//
 Fragment::Fragment()
-  : m_Kind(Type(~0)), m_pParent(NULL), m_Offset(~uint64_t(0)), m_LayoutOrder(~(0U)) {
+  : m_Kind(Type(~0)), m_pParent(NULL), m_Offset(~uint64_t(0)) {
 }
 
 Fragment::Fragment(Type pKind, SectionData *pParent)
-  : m_Kind(pKind), m_pParent(pParent), m_Offset(~uint64_t(0)), m_LayoutOrder(~(0U)) {
+  : m_Kind(pKind), m_pParent(pParent), m_Offset(~uint64_t(0)) {
   if (NULL != m_pParent)
     m_pParent->getFragmentList().push_back(this);
 }
@@ -32,3 +32,14 @@
 {
 }
 
+uint64_t Fragment::getOffset() const
+{
+  assert(hasOffset() && "Cannot getOffset() before setting it up.");
+  return m_Offset;
+}
+
+bool Fragment::hasOffset() const
+{
+  return (m_Offset != ~uint64_t(0));
+}
+
diff --git a/lib/Fragment/FragmentLinker.cpp b/lib/Fragment/FragmentLinker.cpp
new file mode 100644
index 0000000..4ad3d90
--- /dev/null
+++ b/lib/Fragment/FragmentLinker.cpp
@@ -0,0 +1,681 @@
+//===- 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/MC/MCLDInput.h>
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/LD/Layout.h>
+#include <mcld/LD/Resolver.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/SectionRules.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>
+
+using namespace mcld;
+
+/// Constructor
+FragmentLinker::FragmentLinker(const LinkerConfig& pConfig,
+                               Module& pModule,
+                               TargetLDBackend& pBackend)
+
+  : m_Config(pConfig),
+    m_Module(pModule),
+    m_Backend(pBackend) {
+}
+
+/// Destructor
+FragmentLinker::~FragmentLinker()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Symbol Operations
+//===----------------------------------------------------------------------===//
+/// addSymbolFromObject - add a symbol from object file and resolve it
+/// immediately
+LDSymbol* FragmentLinker::addSymbolFromObject(const llvm::StringRef& pName,
+                                        ResolveInfo::Type pType,
+                                        ResolveInfo::Desc pDesc,
+                                        ResolveInfo::Binding pBinding,
+                                        ResolveInfo::SizeType pSize,
+                                        LDSymbol::ValueType pValue,
+                                        FragmentRef* pFragmentRef,
+                                        ResolveInfo::Visibility pVisibility)
+{
+
+  // Step 1. calculate a Resolver::Result
+  // resolved_result is a triple <resolved_info, existent, override>
+  Resolver::Result resolved_result;
+  ResolveInfo old_info; // used for arrange output symbols
+
+  if (pBinding == ResolveInfo::Local) {
+    // if the symbol is a local symbol, create a LDSymbol for input, but do not
+    // resolve them.
+    resolved_result.info     = m_Module.getNamePool().createSymbol(pName,
+                                                                   false,
+                                                                   pType,
+                                                                   pDesc,
+                                                                   pBinding,
+                                                                   pSize,
+                                                                   pVisibility);
+
+    // No matter if there is a symbol with the same name, insert the symbol
+    // into output symbol table. So, we let the existent false.
+    resolved_result.existent  = false;
+    resolved_result.overriden = true;
+  }
+  else {
+    // if the symbol is not local, insert and resolve it immediately
+    m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
+                                        pSize, pVisibility,
+                                        &old_info, resolved_result);
+  }
+
+  // the return ResolveInfo should not NULL
+  assert(NULL != resolved_result.info);
+
+  /// Step 2. create an input LDSymbol.
+  // create a LDSymbol for the input file.
+  LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
+  input_sym->setFragmentRef(pFragmentRef);
+  input_sym->setValue(pValue);
+
+  // Step 3. Set up corresponding output LDSymbol
+  LDSymbol* output_sym = resolved_result.info->outSymbol();
+  bool has_output_sym = (NULL != output_sym);
+  if (!resolved_result.existent || !has_output_sym) {
+    // it is a new symbol, the output_sym should be NULL.
+    assert(NULL == output_sym);
+
+    if (pType == ResolveInfo::Section) {
+      // if it is a section symbol, its output LDSymbol is the input LDSymbol.
+      output_sym = input_sym;
+    }
+    else {
+      // if it is a new symbol, create a LDSymbol for the output
+      output_sym = LDSymbol::Create(*resolved_result.info);
+    }
+    resolved_result.info->setSymPtr(output_sym);
+  }
+
+  if (resolved_result.overriden || !has_output_sym) {
+    // symbol can be overriden only if it exists.
+    assert(output_sym != NULL);
+
+    // should override output LDSymbol
+    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_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) ||
+          !shouldForceLocal(*resolved_result.info)) {
+        // 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;
+}
+
+/// addSymbolFromDynObj - add a symbol from object file and resolve it
+/// immediately
+LDSymbol* FragmentLinker::addSymbolFromDynObj(const llvm::StringRef& pName,
+                                        ResolveInfo::Type pType,
+                                        ResolveInfo::Desc pDesc,
+                                        ResolveInfo::Binding pBinding,
+                                        ResolveInfo::SizeType pSize,
+                                        LDSymbol::ValueType pValue,
+                                        FragmentRef* pFragmentRef,
+                                        ResolveInfo::Visibility pVisibility)
+{
+  // We don't need sections of dynamic objects. So we ignore section symbols.
+  if (pType == ResolveInfo::Section)
+    return NULL;
+
+  // ignore symbols with local binding or that have internal or hidden
+  // visibility
+  if (pBinding == ResolveInfo::Local ||
+      pVisibility == ResolveInfo::Internal ||
+      pVisibility == ResolveInfo::Hidden)
+    return NULL;
+
+  // A protected symbol in a shared library must be treated as a
+  // normal symbol when viewed from outside the shared library.
+  if (pVisibility == ResolveInfo::Protected)
+    pVisibility = ResolveInfo::Default;
+
+  // insert symbol and resolve it immediately
+  // resolved_result is a triple <resolved_info, existent, override>
+  Resolver::Result resolved_result;
+  m_Module.getNamePool().insertSymbol(pName, true, pType, pDesc,
+                                      pBinding, pSize, pVisibility,
+                                      NULL, resolved_result);
+
+  // the return ResolveInfo should not NULL
+  assert(NULL != resolved_result.info);
+
+  // create a LDSymbol for the input file.
+  LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
+  input_sym->setFragmentRef(pFragmentRef);
+  input_sym->setValue(pValue);
+
+  LDSymbol* output_sym = NULL;
+  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_Module.getSymbolTable().forceLocal(*output_sym);
+    }
+  }
+
+  return input_sym;
+}
+
+/// defineSymbolForcefully - define an output symbol and override it immediately
+LDSymbol* FragmentLinker::defineSymbolForcefully(const llvm::StringRef& pName,
+                                           bool pIsDyn,
+                                           ResolveInfo::Type pType,
+                                           ResolveInfo::Desc pDesc,
+                                           ResolveInfo::Binding pBinding,
+                                           ResolveInfo::SizeType pSize,
+                                           LDSymbol::ValueType pValue,
+                                           FragmentRef* pFragmentRef,
+                                           ResolveInfo::Visibility pVisibility)
+{
+  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+  LDSymbol* output_sym = NULL;
+  if (NULL == info) {
+    // the symbol is not in the pool, create a new one.
+    // create a ResolveInfo
+    Resolver::Result result;
+    m_Module.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc,
+                                        pBinding, pSize, pVisibility,
+                                        NULL, result);
+    assert(!result.existent);
+
+    // create a output LDSymbol
+    output_sym = LDSymbol::Create(*result.info);
+    result.info->setSymPtr(output_sym);
+
+    if (shouldForceLocal(*result.info))
+      m_Module.getSymbolTable().forceLocal(*output_sym);
+    else
+      m_Module.getSymbolTable().add(*output_sym);
+  }
+  else {
+    // the symbol is already in the pool, override it
+    ResolveInfo old_info;
+    old_info.override(*info);
+
+    info->setSource(pIsDyn);
+    info->setType(pType);
+    info->setDesc(pDesc);
+    info->setBinding(pBinding);
+    info->setVisibility(pVisibility);
+    info->setIsSymbol(true);
+    info->setSize(pSize);
+
+    output_sym = info->outSymbol();
+    if (NULL != output_sym)
+      m_Module.getSymbolTable().arrange(*output_sym, old_info);
+    else {
+      // create a output LDSymbol
+      output_sym = LDSymbol::Create(*info);
+      info->setSymPtr(output_sym);
+
+      m_Module.getSymbolTable().add(*output_sym);
+    }
+  }
+
+  if (NULL != output_sym) {
+    output_sym->setFragmentRef(pFragmentRef);
+    output_sym->setValue(pValue);
+  }
+
+  return output_sym;
+}
+
+/// defineSymbolAsRefered - define an output symbol and override it immediately
+LDSymbol* FragmentLinker::defineSymbolAsRefered(const llvm::StringRef& pName,
+                                           bool pIsDyn,
+                                           ResolveInfo::Type pType,
+                                           ResolveInfo::Desc pDesc,
+                                           ResolveInfo::Binding pBinding,
+                                           ResolveInfo::SizeType pSize,
+                                           LDSymbol::ValueType pValue,
+                                           FragmentRef* pFragmentRef,
+                                           ResolveInfo::Visibility pVisibility)
+{
+  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+
+  if (NULL == info || !(info->isUndef() || info->isDyn())) {
+    // only undefined symbol and dynamic symbol can make a reference.
+    return NULL;
+  }
+
+  // the symbol is already in the pool, override it
+  ResolveInfo old_info;
+  old_info.override(*info);
+
+  info->setSource(pIsDyn);
+  info->setType(pType);
+  info->setDesc(pDesc);
+  info->setBinding(pBinding);
+  info->setVisibility(pVisibility);
+  info->setIsSymbol(true);
+  info->setSize(pSize);
+
+  LDSymbol* output_sym = info->outSymbol();
+  if (NULL != output_sym) {
+    output_sym->setFragmentRef(pFragmentRef);
+    output_sym->setValue(pValue);
+    m_Module.getSymbolTable().arrange(*output_sym, old_info);
+  }
+  else {
+    // create a output LDSymbol
+    output_sym = LDSymbol::Create(*info);
+    info->setSymPtr(output_sym);
+
+    m_Module.getSymbolTable().add(*output_sym);
+  }
+
+  return output_sym;
+}
+
+/// defineAndResolveSymbolForcefully - define an output symbol and resolve it
+/// immediately
+LDSymbol* FragmentLinker::defineAndResolveSymbolForcefully(const llvm::StringRef& pName,
+                                                     bool pIsDyn,
+                                                     ResolveInfo::Type pType,
+                                                     ResolveInfo::Desc pDesc,
+                                                     ResolveInfo::Binding pBinding,
+                                                     ResolveInfo::SizeType pSize,
+                                                     LDSymbol::ValueType pValue,
+                                                     FragmentRef* pFragmentRef,
+                                                     ResolveInfo::Visibility pVisibility)
+{
+  // Result is <info, existent, override>
+  Resolver::Result result;
+  ResolveInfo old_info;
+  m_Module.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc, pBinding,
+                                      pSize, pVisibility,
+                                      &old_info, result);
+
+  LDSymbol* output_sym = result.info->outSymbol();
+  bool has_output_sym = (NULL != output_sym);
+
+  if (!result.existent || !has_output_sym) {
+    output_sym = LDSymbol::Create(*result.info);
+    result.info->setSymPtr(output_sym);
+  }
+
+  if (result.overriden || !has_output_sym) {
+    output_sym->setFragmentRef(pFragmentRef);
+    output_sym->setValue(pValue);
+  }
+
+  // After symbol resolution, the visibility is changed to the most restrict.
+  // arrange the output position
+  if (shouldForceLocal(*result.info))
+    m_Module.getSymbolTable().forceLocal(*output_sym);
+  else if (has_output_sym)
+    m_Module.getSymbolTable().arrange(*output_sym, old_info);
+  else
+    m_Module.getSymbolTable().add(*output_sym);
+
+  return output_sym;
+}
+
+/// defineAndResolveSymbolAsRefered - define an output symbol and resolve it
+/// immediately.
+LDSymbol* FragmentLinker::defineAndResolveSymbolAsRefered(const llvm::StringRef& pName,
+                                                    bool pIsDyn,
+                                                    ResolveInfo::Type pType,
+                                                    ResolveInfo::Desc pDesc,
+                                                    ResolveInfo::Binding pBinding,
+                                                    ResolveInfo::SizeType pSize,
+                                                    LDSymbol::ValueType pValue,
+                                                    FragmentRef* pFragmentRef,
+                                                    ResolveInfo::Visibility pVisibility)
+{
+  ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+
+  if (NULL == info || !(info->isUndef() || info->isDyn())) {
+    // only undefined symbol and dynamic symbol can make a reference.
+    return NULL;
+  }
+
+  return defineAndResolveSymbolForcefully(pName,
+                                          pIsDyn,
+                                          pType,
+                                          pDesc,
+                                          pBinding,
+                                          pSize,
+                                          pValue,
+                                          pFragmentRef,
+                                          pVisibility);
+}
+
+bool FragmentLinker::finalizeSymbols()
+{
+  Module::sym_iterator symbol, symEnd = m_Module.sym_end();
+  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;
+    }
+  }
+
+  // finialize target-dependent symbols
+  return m_Backend.finalizeSymbols(*this);
+}
+
+bool FragmentLinker::shouldForceLocal(const ResolveInfo& pInfo) const
+{
+  // forced local symbol matches all rules:
+  // 1. We are not doing incremental linking.
+  // 2. The symbol is with Hidden or Internal visibility.
+  // 3. The symbol should be global or weak. Otherwise, local symbol is local.
+  // 4. The symbol is defined or common
+  if (LinkerConfig::Object != m_Config.codeGenType() &&
+      (pInfo.visibility() == ResolveInfo::Hidden ||
+         pInfo.visibility() == ResolveInfo::Internal) &&
+      (pInfo.isGlobal() || pInfo.isWeak()) &&
+      (pInfo.isDefine() || pInfo.isCommon()))
+    return true;
+  return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Relocation Operations
+//===----------------------------------------------------------------------===//
+/// addRelocation - add a relocation entry in FragmentLinker (only for object file)
+///
+/// All symbols should be read and resolved before calling this function.
+Relocation* FragmentLinker::addRelocation(Relocation::Type pType,
+                                          LDSymbol& pSym,
+                                          LDSection& pSection,
+                                          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() &&
+      resolve_info->type() == ResolveInfo::Section &&
+      resolve_info->desc() == ResolveInfo::Undefined)
+    return NULL;
+
+  FragmentRef* frag_ref = FragmentRef::Create(*pSection.getLink(), pOffset);
+
+  Relocation* relocation = m_Backend.getRelocFactory()->produce(pType,
+                                                                *frag_ref,
+                                                                pAddend);
+
+  relocation->setSymInfo(resolve_info);
+  pSection.getRelocData()->getFragmentList().push_back(relocation);
+
+  return relocation;
+}
+
+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) {
+    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.getRelocFactory());
+      } // for all relocations
+    } // for all relocation section
+  } // 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.getRelocFactory());
+  }
+  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_Backend.isLittleEndian()) {
+     uint64_t tmp_data = 0;
+
+     switch(m_Backend.bitclass()) {
+       case 32u:
+         tmp_data = bswap32(pReloc.target());
+         std::memcpy(target_addr, &tmp_data, 4);
+         break;
+
+       case 64u:
+         tmp_data = bswap64(pReloc.target());
+         std::memcpy(target_addr, &tmp_data, 8);
+         break;
+
+       default:
+         break;
+    }
+  }
+  else
+    std::memcpy(target_addr, &pReloc.target(), m_Backend.bitclass()/8);
+}
+
+/// isOutputPIC - return whether the output is position-independent
+bool FragmentLinker::isOutputPIC() const
+{
+  return checkIsOutputPIC();
+}
+
+/// isStaticLink - return whether we're doing static link
+bool FragmentLinker::isStaticLink() const
+{
+  return checkIsStaticLink();
+}
+
+bool FragmentLinker::checkIsOutputPIC() const
+{
+  if (LinkerConfig::DynObj == m_Config.codeGenType() ||
+      m_Config.options().isPIE())
+    return true;
+  return false;
+}
+
+bool FragmentLinker::checkIsStaticLink() const
+{
+  if (m_Module.getLibraryList().empty() && !isOutputPIC())
+    return true;
+  return false;
+}
+
diff --git a/lib/Fragment/FragmentRef.cpp b/lib/Fragment/FragmentRef.cpp
new file mode 100644
index 0000000..aec7b8c
--- /dev/null
+++ b/lib/Fragment/FragmentRef.cpp
@@ -0,0 +1,194 @@
+//===- FragmentRef.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#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>
+
+using namespace mcld;
+
+typedef GCFactory<FragmentRef, MCLD_SECTIONS_PER_INPUT> FragRefFactory;
+
+static llvm::ManagedStatic<FragRefFactory> g_FragRefFactory;
+
+FragmentRef FragmentRef::g_NullFragmentRef;
+
+//===----------------------------------------------------------------------===//
+// FragmentRef
+//===----------------------------------------------------------------------===//
+FragmentRef::FragmentRef()
+  : m_pFragment(NULL), m_Offset(0) {
+}
+
+FragmentRef::FragmentRef(Fragment& pFrag,
+                         FragmentRef::Offset pOffset)
+  : m_pFragment(&pFrag), m_Offset(pOffset) {
+}
+
+/// Create - create a fragment reference for a given fragment.
+///
+/// @param pFrag - the given fragment
+/// @param pOffset - the offset, can be larger than the fragment, but can not
+///                  be larger than the section size.
+/// @return if the offset is legal, return the fragment reference. Otherwise,
+/// return NULL.
+FragmentRef* FragmentRef::Create(Fragment& pFrag, uint64_t pOffset)
+{
+  int64_t offset = pOffset;
+  Fragment* frag = &pFrag;
+
+  while (NULL != frag) {
+    offset -= frag->size();
+    if (offset <= 0)
+      break;
+    frag = frag->getNextNode();
+  }
+
+
+  if (NULL == frag)
+    return Null();
+
+  FragmentRef* result = g_FragRefFactory->allocate();
+  new (result) FragmentRef(*frag, offset + frag->size());
+
+  return result;
+}
+
+FragmentRef* FragmentRef::Create(LDSection& pSection, uint64_t pOffset)
+{
+  SectionData* data = NULL;
+  switch (pSection.kind()) {
+    case LDFileFormat::Relocation:
+      // No fragment reference refers to a relocation section
+      break;
+    case LDFileFormat::EhFrame:
+      if (pSection.hasEhFrame())
+        data = &pSection.getEhFrame()->getSectionData();
+      break;
+    default:
+      data = pSection.getSectionData();
+      break;
+  }
+
+  if (NULL == data || data->empty()) {
+    return Null();
+  }
+
+  return Create(data->front(), pOffset);
+}
+
+void FragmentRef::Clear()
+{
+  g_FragRefFactory->clear();
+}
+
+FragmentRef* FragmentRef::Null()
+{
+  return &g_NullFragmentRef;
+}
+
+FragmentRef& FragmentRef::assign(const FragmentRef& pCopy)
+{
+  m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment);
+  m_Offset = pCopy.m_Offset;
+  return *this;
+}
+
+FragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset)
+{
+  m_pFragment = &pFrag;
+  m_Offset = pOffset;
+  return *this;
+}
+
+void FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const
+{
+  // check if the offset is still in a legal range.
+  if (NULL == m_pFragment)
+    return;
+  unsigned int total_offset = m_Offset + pOffset;
+  switch(m_pFragment->getKind()) {
+    case Fragment::Region: {
+      RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment);
+      unsigned int total_length = region_frag->getRegion().size();
+      if (total_length < (total_offset+pNBytes))
+        pNBytes = total_length - total_offset;
+
+      std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes);
+      return;
+    }
+    case Fragment::Stub: {
+      Stub* stub_frag = static_cast<Stub*>(m_pFragment);
+      unsigned int total_length = stub_frag->size();
+      if (total_length < (total_offset+pNBytes))
+        pNBytes = total_length - total_offset;
+      std::memcpy(pDest, stub_frag->getContent() + total_offset, pNBytes);
+      return;
+    }
+    case Fragment::Alignment:
+    case Fragment::Fillment:
+    default:
+      return;
+  }
+}
+
+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;
+  if (NULL != m_pFragment)
+    result = m_pFragment->getOffset();
+  return (result + m_Offset);
+}
+
diff --git a/lib/LD/CIE.cpp b/lib/Fragment/NullFragment.cpp
similarity index 64%
copy from lib/LD/CIE.cpp
copy to lib/Fragment/NullFragment.cpp
index 5ddb166..a1d1626 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/Fragment/NullFragment.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- NullFragment.cpp ---------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,18 +6,15 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/Fragment/NullFragment.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// CIE
+// NullFragment
 //===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
-  : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
-}
-
-CIE::~CIE()
+NullFragment::NullFragment(SectionData* pSD)
+  : Fragment(Fragment::Null, pSD)
 {
 }
+
diff --git a/lib/LD/RegionFragment.cpp b/lib/Fragment/RegionFragment.cpp
similarity index 82%
rename from lib/LD/RegionFragment.cpp
rename to lib/Fragment/RegionFragment.cpp
index 7508ed5..363a0f2 100644
--- a/lib/LD/RegionFragment.cpp
+++ b/lib/Fragment/RegionFragment.cpp
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#include <mcld/LD/RegionFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Support/MemoryRegion.h>
 
 using namespace mcld;
 
@@ -22,3 +22,8 @@
 {
 }
 
+size_t RegionFragment::size() const
+{
+  return m_Region.size();
+}
+
diff --git a/lib/LD/Relocation.cpp b/lib/Fragment/Relocation.cpp
similarity index 68%
rename from lib/LD/Relocation.cpp
rename to lib/Fragment/Relocation.cpp
index 0c95e06..bae49af 100644
--- a/lib/LD/Relocation.cpp
+++ b/lib/Fragment/Relocation.cpp
@@ -6,10 +6,12 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#include <mcld/LD/Relocation.h>
+#include <mcld/Fragment/Relocation.h>
 #include <mcld/LD/RelocationFactory.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
 #include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
@@ -32,10 +34,10 @@
 {
 }
 
-Relocation::Address Relocation::place(const Layout& pLayout) const
+Relocation::Address Relocation::place() const
 {
-  Address sect_addr = pLayout.getOutputLDSection(*(m_TargetAddress.frag()))->addr();
-  return sect_addr + pLayout.getOutputOffset(m_TargetAddress);
+  Address sect_addr = m_TargetAddress.frag()->getParent()->getSection().addr();
+  return sect_addr + m_TargetAddress.getOutputOffset();
 }
 
 Relocation::Address Relocation::symValue() const
@@ -47,11 +49,9 @@
   return m_pSymInfo->outSymbol()->value();
 }
 
-void Relocation::apply(RelocationFactory& pRelocFactory,
-                       const MCLDInfo& pLDInfo)
+void Relocation::apply(RelocationFactory& pRelocFactory)
 {
-  RelocationFactory::Result result =
-                                 pRelocFactory.applyRelocation(*this, pLDInfo);
+  RelocationFactory::Result result = pRelocFactory.applyRelocation(*this);
 
   switch (result) {
     case RelocationFactory::OK: {
@@ -73,6 +73,10 @@
                                           << "mclinker@googlegroups.com";
       return;
     }
+    case RelocationFactory::Unknown: {
+      fatal(diag::unknown_relocation) << type() << symInfo()->name();
+      return;
+    }
   } // end of switch
 }
 
@@ -91,13 +95,18 @@
   m_pSymInfo = pSym;
 }
 
-Relocation::DWord& Relocation::target()
+size_t Relocation::size() const
 {
-  return m_TargetData;
+  // TODO: the size of Relocation fragment is handled by backend
+  return 0;
 }
 
-const Relocation::DWord& Relocation::target() const
+void Relocation::updateAddend()
 {
-  return m_TargetData;
+  // Update value keep in addend if we meet a section symbol
+  if (m_pSymInfo->type() == ResolveInfo::Section) {
+    uint32_t offset = m_pSymInfo->outSymbol()->fragRef()->getOutputOffset();
+    m_Addend += offset;
+  }
 }
 
diff --git a/lib/Fragment/Stub.cpp b/lib/Fragment/Stub.cpp
new file mode 100644
index 0000000..b7122bd
--- /dev/null
+++ b/lib/Fragment/Stub.cpp
@@ -0,0 +1,42 @@
+//===- Stub.cpp -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/Fragment/Stub.h>
+
+using namespace mcld;
+
+Stub::Stub()
+ : Fragment(Fragment::Stub),
+   m_pSymInfo(NULL)
+{
+}
+
+Stub::~Stub()
+{
+  for (fixup_iterator fixup= fixup_begin(); fixup != fixup_end(); ++fixup)
+    delete(*fixup);
+}
+
+void Stub::setSymInfo(ResolveInfo* pSymInfo)
+{
+  m_pSymInfo = pSymInfo;
+}
+
+void Stub::addFixup(DWord pOffset, SWord pAddend, Type pType)
+{
+  assert(pOffset < size());
+  m_FixupList.push_back(new Fixup(pOffset, pAddend, pType));
+}
+
+void Stub::addFixup(const Fixup& pFixup)
+{
+  assert(pFixup.offset() < size());
+  m_FixupList.push_back(new Fixup(pFixup));
+}
+
diff --git a/lib/LD/Android.mk b/lib/LD/Android.mk
index d3c9dd8..21e452e 100644
--- a/lib/LD/Android.mk
+++ b/lib/LD/Android.mk
@@ -5,11 +5,10 @@
 # =====================================================
 
 mcld_ld_SRC_FILES := \
-  AlignFragment.cpp \
   Archive.cpp \
   ArchiveReader.cpp \
   BranchIsland.cpp  \
-  CIE.cpp \
+  BranchIslandFactory.cpp  \
   DWARFLineInfo.cpp \
   Diagnostic.cpp  \
   DiagnosticEngine.cpp  \
@@ -22,32 +21,28 @@
   ELFSegmentFactory.cpp \
   EhFrame.cpp \
   EhFrameHdr.cpp  \
+  EhFrameReader.cpp  \
   ExecWriter.cpp  \
-  FDE.cpp \
-  FillFragment.cpp \
-  Fragment.cpp \
-  FragmentRef.cpp \
+  GroupReader.cpp \
   Layout.cpp  \
   LDContext.cpp \
   LDFileFormat.cpp  \
   LDReader.cpp  \
   LDSection.cpp \
-  LDSectionFactory.cpp  \
   LDSymbol.cpp  \
   LDWriter.cpp  \
   MsgHandler.cpp  \
   NamePool.cpp  \
   ObjectWriter.cpp  \
-  RegionFragment.cpp \
-  Relocation.cpp  \
+  RelocData.cpp  \
   RelocationFactory.cpp \
   ResolveInfo.cpp \
-  ResolveInfoFactory.cpp  \
   Resolver.cpp  \
   SectionData.cpp \
-  SectionMap.cpp  \
-  SectionMerger.cpp \
+  SectionRules.cpp \
+  SectionSymbolSet.cpp \
   StaticResolver.cpp  \
+  StubFactory.cpp  \
   TextDiagnosticPrinter.cpp
 
 # For the host
diff --git a/lib/LD/Archive.cpp b/lib/LD/Archive.cpp
index 2805541..be82922 100644
--- a/lib/LD/Archive.cpp
+++ b/lib/LD/Archive.cpp
@@ -7,8 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/Archive.h>
-#include <mcld/MC/InputFactory.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/AttributeSet.h>
+#include <mcld/MC/ContextFactory.h>
 #include <llvm/ADT/StringRef.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
@@ -22,12 +27,14 @@
 const char   Archive::PAD[]              = "\n";
 const char   Archive::MEMBER_MAGIC[]     = "`\n";
 
-Archive::Archive(Input& pInputFile, InputFactory& pInputFactory)
+Archive::Archive(Input& pInputFile, InputBuilder& pBuilder)
  : m_ArchiveFile(pInputFile),
    m_pInputTree(NULL),
-   m_SymbolFactory(32)
+   m_SymbolFactory(32),
+   m_Builder(pBuilder)
 {
-  m_pInputTree = new InputTree(pInputFactory);
+  // FIXME: move creation of input tree out of Archive.
+  m_pInputTree = new InputTree();
 }
 
 Archive::~Archive()
@@ -227,3 +234,41 @@
   return m_StrTab;
 }
 
+/// hasStrTable()
+bool Archive::hasStrTable() const
+{
+  return (m_StrTab.size() > 0);
+}
+
+/// getMemberFile - get the member file in an archive member
+/// @param pArchiveFile - Input reference of the archive member
+/// @param pIsThinAR    - denote the archive menber is a Thin Archive or not
+/// @param pName        - the name of the member file we want to get
+/// @param pPath        - the path of the member file
+/// @param pFileOffset  - the file offset of the member file in a regular AR
+/// FIXME: maybe we should not construct input file here
+Input* Archive::getMemberFile(Input& pArchiveFile,
+                              bool isThinAR,
+                              const std::string& pName,
+                              const sys::fs::Path& pPath,
+                              off_t pFileOffset)
+{
+  Input* member = NULL;
+  if (!isThinAR) {
+    member = m_Builder.createInput(pName, pPath, Input::Unknown, pFileOffset);
+    assert(member != NULL);
+    member->setMemArea(pArchiveFile.memArea());
+    m_Builder.setContext(*member);
+  }
+  else {
+    member = m_Builder.createInput(pName, pPath, Input::Unknown);
+    assert(member != NULL);
+    if (!m_Builder.setMemory(*member, FileHandle::ReadOnly)) {
+      error(diag::err_cannot_open_input) << member->name() << member->path();
+      return NULL;
+    }
+    m_Builder.setContext(*member);
+  }
+  return member;
+}
+
diff --git a/lib/LD/BranchIsland.cpp b/lib/LD/BranchIsland.cpp
index 7a42717..c6f5b02 100644
--- a/lib/LD/BranchIsland.cpp
+++ b/lib/LD/BranchIsland.cpp
@@ -6,10 +6,143 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/LD/BranchIsland.h"
+#include <mcld/LD/BranchIsland.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/Fragment/AlignFragment.h>
+
+#include <sstream>
 
 using namespace mcld;
 
 //==========================
 // BranchIsland
 
+BranchIsland::BranchIsland(Fragment& pEntryFrag,
+                           size_t pMaxSize,
+                           size_t pIndex)
+ : m_Entry(pEntryFrag),
+   m_pExit(pEntryFrag.getNextNode()),
+   m_pRear(NULL),
+   m_MaxSize(pMaxSize),
+   m_Name("island-")
+{
+  // island name
+  std::ostringstream index;
+  index << pIndex;
+  m_Name.append(index.str());
+}
+
+BranchIsland::~BranchIsland()
+{
+}
+
+/// fragment iterators of the island
+SectionData::iterator BranchIsland::begin()
+{
+  return ++iterator(&m_Entry);
+}
+
+SectionData::const_iterator BranchIsland::begin() const
+{
+  return ++iterator(&m_Entry);
+}
+
+SectionData::iterator BranchIsland::end()
+{
+  if (NULL != m_pExit)
+    return iterator(m_pExit);
+  return m_Entry.getParent()->end();
+}
+
+SectionData::const_iterator BranchIsland::end() const
+{
+  if (NULL != m_pExit)
+    return iterator(m_pExit);
+  return m_Entry.getParent()->end();
+}
+
+uint64_t BranchIsland::offset() const
+{
+  return m_Entry.getOffset() + m_Entry.size();
+}
+
+size_t BranchIsland::size() const
+{
+  size_t size = 0x0;
+  if (0x0 != numOfStubs()) {
+    size = m_pRear->getOffset() + m_pRear->size() -
+           m_Entry.getNextNode()->getOffset();
+  }
+  return size;
+}
+
+size_t BranchIsland::maxSize() const
+{
+  return m_MaxSize;
+}
+
+const std::string& BranchIsland::name() const
+{
+  return m_Name;
+}
+
+size_t BranchIsland::numOfStubs() const
+{
+  return m_StubMap.numOfEntries();
+}
+
+/// findStub - return true if there is a stub built from the given prototype
+///            for the given relocation
+Stub* BranchIsland::findStub(const Stub* pPrototype, const Relocation& pReloc)
+{
+  Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
+  StubMapType::iterator it = m_StubMap.find(key);
+  if (it != m_StubMap.end()) {
+    assert(NULL != it.getEntry()->value());
+    return it.getEntry()->value();
+  }
+  return NULL;
+}
+
+/// addStub - add a stub into the island
+bool BranchIsland::addStub(const Stub* pPrototype,
+                           const Relocation& pReloc,
+                           Stub& pStub)
+{
+  bool exist = false;
+  Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
+  StubEntryType* entry = m_StubMap.insert(key, exist);
+  if (!exist) {
+    entry->setValue(&pStub);
+    m_pRear = &pStub;
+    SectionData* sd = m_Entry.getParent();
+
+    // insert alignment fragment
+    // TODO: check if we can reduce this alignment fragment for some cases
+    AlignFragment* align_frag = new AlignFragment(pStub.alignment(),
+                                                  0x0,
+                                                  1u,
+                                                  pStub.alignment() - 1);
+    align_frag->setParent(sd);
+    sd->getFragmentList().insert(end(), align_frag);
+    align_frag->setOffset(align_frag->getPrevNode()->getOffset() +
+                          align_frag->getPrevNode()->size());
+
+    // insert stub fragment
+    pStub.setParent(sd);
+    sd->getFragmentList().insert(end(), &pStub);
+    pStub.setOffset(pStub.getPrevNode()->getOffset() +
+                    pStub.getPrevNode()->size());
+  }
+  return !exist;
+}
+
+/// addRelocation - add a relocation into island
+bool BranchIsland::addRelocation(Relocation& pReloc)
+{
+  m_Relocations.push_back(&pReloc);
+  return true;
+}
+
diff --git a/lib/LD/BranchIslandFactory.cpp b/lib/LD/BranchIslandFactory.cpp
new file mode 100644
index 0000000..6a61481
--- /dev/null
+++ b/lib/LD/BranchIslandFactory.cpp
@@ -0,0 +1,87 @@
+//===- BranchIslandFactory.cpp --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/Fragment/Fragment.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// BranchIslandFactory
+//===----------------------------------------------------------------------===//
+
+/// ctor
+/// @param pMaxBranchRange - the max branch range of the target backend
+/// @param pMaxIslandSize - a predifned value (1KB here) to decide the max
+///                         size of the island
+BranchIslandFactory::BranchIslandFactory(uint64_t pMaxBranchRange,
+                                         uint64_t pMaxIslandSize)
+ : GCFactory<BranchIsland, 0>(1u), // magic number
+   m_MaxBranchRange(pMaxBranchRange - pMaxIslandSize),
+   m_MaxIslandSize(pMaxIslandSize)
+{
+}
+
+BranchIslandFactory::~BranchIslandFactory()
+{
+}
+
+/// 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
+                            m_MaxIslandSize, // the max size of the island
+                            size() - 1u);     // index in the island factory
+  return island;
+}
+
+/// find - find a island for the given fragment
+/// @param pFragment - the fragment needs a branch isladn
+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.
+  for (iterator it = begin(), ie = end(); it != ie; ++it) {
+    if ((pFragment.getOffset() < (*it).offset()) &&
+        ((pFragment.getOffset() + m_MaxBranchRange) >= (*it).offset()))
+      return &(*it);
+  }
+  return NULL;
+}
+
diff --git a/lib/LD/Diagnostic.cpp b/lib/LD/Diagnostic.cpp
index 5175ebd..786a68b 100644
--- a/lib/LD/Diagnostic.cpp
+++ b/lib/LD/Diagnostic.cpp
@@ -87,8 +87,8 @@
     // skip the %.
     ++cur_char;
 
-    const char* modifier = NULL, *argument = NULL;
-    size_t modifier_len = 0, argument_len = 0;
+    const char* modifier = NULL;
+    size_t modifier_len = 0;
 
     // we get a modifier
     if (!isdigit(*cur_char)) {
@@ -100,7 +100,6 @@
       // we get an argument
       if ('{' == *cur_char) {
         ++cur_char; // skip '{'
-        argument = cur_char;
         cur_char = findMatch('}', cur_char, pEnd);
 
         if (cur_char == pEnd) {
@@ -109,7 +108,6 @@
                                    llvm::Twine(getID()));
         }
 
-        argument_len = cur_char - argument;
         ++cur_char; // skip '}'
       }
     }
diff --git a/lib/LD/DiagnosticEngine.cpp b/lib/LD/DiagnosticEngine.cpp
index 173b4f2..c2e52d7 100644
--- a/lib/LD/DiagnosticEngine.cpp
+++ b/lib/LD/DiagnosticEngine.cpp
@@ -9,7 +9,10 @@
 #include <mcld/LD/DiagnosticEngine.h>
 #include <mcld/LD/DiagnosticPrinter.h>
 #include <mcld/LD/DiagnosticLineInfo.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LD/MsgHandler.h>
+#include <mcld/LinkerConfig.h>
+
+#include <cassert>
 
 using namespace mcld;
 
@@ -17,7 +20,7 @@
 // DiagnosticEngine
 //===----------------------------------------------------------------------===//
 DiagnosticEngine::DiagnosticEngine()
-  : m_pLDInfo(NULL), m_pLineInfo(NULL), m_pPrinter(NULL),
+  : m_pConfig(NULL), m_pLineInfo(NULL), m_pPrinter(NULL),
     m_pInfoMap(NULL), m_OwnPrinter(false) {
 }
 
@@ -25,12 +28,15 @@
 {
   if (m_OwnPrinter && m_pPrinter != NULL)
     delete m_pPrinter;
+
+  delete m_pInfoMap;
 }
 
-void DiagnosticEngine::reset(const MCLDInfo& pLDInfo)
+void DiagnosticEngine::reset(const LinkerConfig& pConfig)
 {
-  m_pLDInfo = &pLDInfo;
-  m_pInfoMap = new DiagnosticInfos(*m_pLDInfo);
+  m_pConfig = &pConfig;
+  delete m_pInfoMap;
+  m_pInfoMap = new DiagnosticInfos(*m_pConfig);
   m_State.reset();
 }
 
@@ -51,8 +57,19 @@
 // emit - process current diagnostic.
 bool DiagnosticEngine::emit()
 {
+  assert(NULL != m_pInfoMap);
   bool emitted = m_pInfoMap->process(*this);
   m_State.reset();
   return emitted;
 }
 
+MsgHandler
+DiagnosticEngine::report(uint16_t pID, DiagnosticEngine::Severity pSeverity)
+{
+  m_State.ID = pID;
+  m_State.severity = pSeverity;
+
+  MsgHandler result(*this);
+  return result;
+}
+
diff --git a/lib/LD/DiagnosticInfos.cpp b/lib/LD/DiagnosticInfos.cpp
index b9a6fa9..6639d0a 100644
--- a/lib/LD/DiagnosticInfos.cpp
+++ b/lib/LD/DiagnosticInfos.cpp
@@ -10,11 +10,13 @@
 #include <llvm/Support/DataTypes.h>
 
 #include <mcld/ADT/SizeTraits.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/LD/Diagnostic.h>
 #include <mcld/LD/DiagnosticInfos.h>
 #include <mcld/LD/DiagnosticPrinter.h>
 
+#include <algorithm>
+
 using namespace mcld;
 
 namespace {
@@ -85,8 +87,9 @@
 
 //===----------------------------------------------------------------------===//
 //  DiagnosticInfos
-DiagnosticInfos::DiagnosticInfos(const MCLDInfo& pLDInfo)
-  : m_LDInfo(pLDInfo) {
+//===----------------------------------------------------------------------===//
+DiagnosticInfos::DiagnosticInfos(const LinkerConfig& pConfig)
+  : m_Config(pConfig) {
 }
 
 DiagnosticInfos::~DiagnosticInfos()
@@ -111,7 +114,7 @@
 
   switch (ID) {
     case diag::multiple_definitions: {
-      if (m_LDInfo.options().hasMulDefs()) {
+      if (m_Config.options().hasMulDefs()) {
         severity = DiagnosticEngine::Ignore;
       }
       break;
@@ -119,22 +122,23 @@
     case diag::undefined_reference: {
       // 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_LDInfo.output().type()) {
-        case Output::Object:
-          if (m_LDInfo.options().isNoUndefined())
+      switch(m_Config.codeGenType()) {
+        case LinkerConfig::Object:
+          if (m_Config.options().isNoUndefined())
             severity = DiagnosticEngine::Error;
           else
             severity = DiagnosticEngine::Ignore;
-        break;
-        case Output::DynObj:
-          if (m_LDInfo.options().isNoUndefined() || !m_LDInfo.options().isAllowShlibUndefined())
+          break;
+        case LinkerConfig::DynObj:
+          if (m_Config.options().isNoUndefined() || !m_Config.options().isAllowShlibUndefined())
             severity = DiagnosticEngine::Error;
           else
             severity = DiagnosticEngine::Ignore;
-        break;
-        case Output::Exec:
+          break;
+        case LinkerConfig::Exec:
+        default:
           severity = DiagnosticEngine::Error;
-        break;
+          break;
       }
       break;
     }
diff --git a/lib/LD/DiagnosticPrinter.cpp b/lib/LD/DiagnosticPrinter.cpp
index 7bbf473..245555f 100644
--- a/lib/LD/DiagnosticPrinter.cpp
+++ b/lib/LD/DiagnosticPrinter.cpp
@@ -28,7 +28,8 @@
 {
   if (pSeverity == DiagnosticEngine::Warning)
     ++m_NumWarnings;
-  else if (pSeverity <= DiagnosticEngine::Error)
+
+  if (pSeverity <= DiagnosticEngine::Error)
     ++m_NumErrors;
 }
 
diff --git a/lib/LD/ELFDynObjFileFormat.cpp b/lib/LD/ELFDynObjFileFormat.cpp
index 30183cc..9ccf967 100644
--- a/lib/LD/ELFDynObjFileFormat.cpp
+++ b/lib/LD/ELFDynObjFileFormat.cpp
@@ -6,78 +6,78 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/Support/ELF.h>
 #include <mcld/LD/ELFDynObjFileFormat.h>
-#include <mcld/LD/LDFileFormat.h>
 #include <mcld/LD/LDSection.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <llvm/Support/ELF.h>
 
 using namespace mcld;
 
-void ELFDynObjFileFormat::initObjectType(MCLinker& pLinker)
+void ELFDynObjFileFormat::initObjectFormat(ObjectBuilder& pBuilder,
+                                           unsigned int pBitClass)
 {
-  f_pDynSymTab    = &pLinker.getOrCreateOutputSectHdr(".dynsym",
+  f_pDynSymTab    = pBuilder.CreateSection(".dynsym",
                                            LDFileFormat::NamePool,
                                            llvm::ELF::SHT_DYNSYM,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pDynStrTab    = &pLinker.getOrCreateOutputSectHdr(".dynstr",
+                                           pBitClass / 8);
+  f_pDynStrTab    = pBuilder.CreateSection(".dynstr",
                                            LDFileFormat::NamePool,
                                            llvm::ELF::SHT_STRTAB,
                                            llvm::ELF::SHF_ALLOC,
                                            0x1);
-  f_pInterp       = &pLinker.getOrCreateOutputSectHdr(".interp",
+  f_pInterp       = pBuilder.CreateSection(".interp",
                                            LDFileFormat::Note,
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC,
                                            0x1);
-  f_pHashTab      = &pLinker.getOrCreateOutputSectHdr(".hash",
+  f_pHashTab      = pBuilder.CreateSection(".hash",
                                            LDFileFormat::NamePool,
                                            llvm::ELF::SHT_HASH,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pDynamic      = &pLinker.getOrCreateOutputSectHdr(".dynamic",
+                                           pBitClass / 8);
+  f_pDynamic      = pBuilder.CreateSection(".dynamic",
                                            LDFileFormat::NamePool,
                                            llvm::ELF::SHT_DYNAMIC,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
-                                           f_Backend.bitclass() / 8);
-  f_pRelaDyn      = &pLinker.getOrCreateOutputSectHdr(".rela.dyn",
+                                           pBitClass / 8);
+  f_pRelaDyn      = pBuilder.CreateSection(".rela.dyn",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_RELA,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pRelaPlt      = &pLinker.getOrCreateOutputSectHdr(".rela.plt",
+                                           pBitClass / 8);
+  f_pRelaPlt      = pBuilder.CreateSection(".rela.plt",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_RELA,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pRelDyn      = &pLinker.getOrCreateOutputSectHdr(".rel.dyn",
+                                           pBitClass / 8);
+  f_pRelDyn      = pBuilder.CreateSection(".rel.dyn",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_REL,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pRelPlt      = &pLinker.getOrCreateOutputSectHdr(".rel.plt",
+                                           pBitClass / 8);
+  f_pRelPlt      = pBuilder.CreateSection(".rel.plt",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_REL,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pGOT          = &pLinker.getOrCreateOutputSectHdr(".got",
+                                           pBitClass / 8);
+  f_pGOT          = pBuilder.CreateSection(".got",
                                            LDFileFormat::Target,
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
-                                           f_Backend.bitclass() / 8);
-  f_pPLT          = &pLinker.getOrCreateOutputSectHdr(".plt",
+                                           pBitClass / 8);
+  f_pPLT          = pBuilder.CreateSection(".plt",
                                            LDFileFormat::Target,
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
-                                           f_Backend.bitclass() / 8);
-  f_pGOTPLT       = &pLinker.getOrCreateOutputSectHdr(".got.plt",
+                                           pBitClass / 8);
+  f_pGOTPLT       = pBuilder.CreateSection(".got.plt",
                                            LDFileFormat::Target,
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
-                                           f_Backend.bitclass() / 8);
-  f_pEhFrameHdr     = &pLinker.getOrCreateOutputSectHdr(".eh_frame_hdr",
+                                           pBitClass / 8);
+  f_pEhFrameHdr     = pBuilder.CreateSection(".eh_frame_hdr",
                                               LDFileFormat::EhFrameHdr,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
diff --git a/lib/LD/ELFDynObjReader.cpp b/lib/LD/ELFDynObjReader.cpp
index 1251656..740577c 100644
--- a/lib/LD/ELFDynObjReader.cpp
+++ b/lib/LD/ELFDynObjReader.cpp
@@ -13,7 +13,7 @@
 #include <mcld/LD/ELFDynObjReader.h>
 #include <mcld/LD/ELFReader.h>
 #include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/Support/MemoryRegion.h>
 
@@ -21,9 +21,10 @@
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // ELFDynObjReader
-ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend, MCLinker& pLinker)
+//===----------------------------------------------------------------------===//
+ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend, FragmentLinker& pLinker)
   : DynObjReader(),
     m_pELFReader(0),
     m_Linker(pLinker) {
@@ -55,14 +56,14 @@
     result = false;
   else if (!m_pELFReader->isMyMachine(ELF_hdr))
     result = false;
-  else if (MCLDFile::DynObj != m_pELFReader->fileType(ELF_hdr))
+  else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr))
     result = false;
   pInput.memArea()->release(region);
   return result;
 }
 
-/// readDSO
-bool ELFDynObjReader::readDSO(Input& pInput)
+/// readHeader
+bool ELFDynObjReader::readHeader(Input& pInput)
 {
   assert(pInput.hasMemArea());
 
@@ -71,7 +72,7 @@
                                                    hdr_size);
   uint8_t* ELF_hdr = region->start();
 
-  bool shdr_result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
+  bool shdr_result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
   pInput.memArea()->release(region);
 
   // read .dynamic to get the correct SONAME
diff --git a/lib/LD/ELFDynObjWriter.cpp b/lib/LD/ELFDynObjWriter.cpp
index cabc9e9..48ce0a3 100644
--- a/lib/LD/ELFDynObjWriter.cpp
+++ b/lib/LD/ELFDynObjWriter.cpp
@@ -7,25 +7,28 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/ELFDynObjWriter.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Support/MemoryArea.h>
+
 #include <llvm/Support/ELF.h>
+
 #include <vector>
 
 using namespace llvm;
 using namespace mcld;
 
-
-//==========================
+//===----------------------------------------------------------------------===//
 // ELFDynObjWriter
-ELFDynObjWriter::ELFDynObjWriter(GNULDBackend& pBackend, MCLinker& pLinker)
+//===----------------------------------------------------------------------===//
+ELFDynObjWriter::ELFDynObjWriter(GNULDBackend& pBackend, FragmentLinker& pLinker)
   : DynObjWriter(pBackend),
     ELFWriter(pBackend),
-    m_Backend(pBackend),
     m_Linker(pLinker) {
 
 }
@@ -34,41 +37,34 @@
 {
 }
 
-llvm::error_code ELFDynObjWriter::writeDynObj(Output& pOutput)
+llvm::error_code ELFDynObjWriter::writeDynObj(Module& pModule,
+                                              MemoryArea& pOutput)
 {
+  target().emitInterp(pOutput);
+
   // Write out name pool sections: .dynsym, .dynstr, .hash
-  target().emitDynNamePools(pOutput,
-                            m_Linker.getOutputSymbols(),
-                            m_Linker.getLayout(),
-                            m_Linker.getLDInfo());
+  target().emitDynNamePools(pModule, pOutput);
 
   // Write out name pool sections: .symtab, .strtab
-  target().emitRegNamePools(pOutput,
-                            m_Linker.getOutputSymbols(),
-                            m_Linker.getLayout(),
-                            m_Linker.getLDInfo());
+  target().emitRegNamePools(pModule, pOutput);
 
   // Write out regular ELF sections
-  unsigned int secIdx = 0;
-  unsigned int secEnd = pOutput.context()->numOfSections();
-  for (secIdx = 0; secIdx < secEnd; ++secIdx) {
-    LDSection* sect = pOutput.context()->getSection(secIdx);
+  Module::iterator sect, sectEnd = pModule.end();
+  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
     MemoryRegion* region = NULL;
     // request output region
-    switch(sect->kind()) {
+    switch((*sect)->kind()) {
       case LDFileFormat::Regular:
       case LDFileFormat::Relocation:
       case LDFileFormat::Target:
       case LDFileFormat::Debug:
       case LDFileFormat::GCCExceptTable:
       case LDFileFormat::EhFrame: {
-        region = pOutput.memArea()->request(sect->offset(), sect->size());
+        region = pOutput.request((*sect)->offset(), (*sect)->size());
         if (NULL == region) {
-          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") +
-                                   llvm::Twine(secIdx) +
-                                   llvm::Twine("] - `") +
-                                   sect->name() +
-                                   llvm::Twine("'.\n"));
+          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section ") +
+                                   llvm::Twine((*sect)->name()) +
+                                   llvm::Twine(".\n"));
         }
         break;
       }
@@ -79,38 +75,35 @@
       case LDFileFormat::MetaData:
       case LDFileFormat::Version:
       case LDFileFormat::EhFrameHdr:
+      case LDFileFormat::StackNote:
         // ignore these sections
         continue;
       default: {
         llvm::errs() << "WARNING: unsupported section kind: "
-                     << sect->kind()
+                     << (*sect)->kind()
                      << " of section "
-                     << sect->name()
+                     << (*sect)->name()
                      << ".\n";
         continue;
       }
     }
 
     // write out sections with data
-    switch(sect->kind()) {
+    switch((*sect)->kind()) {
       case LDFileFormat::Regular:
       case LDFileFormat::Debug:
       case LDFileFormat::GCCExceptTable:
       case LDFileFormat::EhFrame: {
         // FIXME: if optimization of exception handling sections is enabled,
         // then we should emit these sections by the other way.
-        emitSectionData(m_Linker.getLayout(), *sect, *region);
+        emitSectionData(**sect, *region);
         break;
       }
       case LDFileFormat::Relocation:
-        emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
+        emitRelocation(m_Linker.getLDInfo(), **sect, *region);
         break;
       case LDFileFormat::Target:
-        target().emitSectionData(pOutput,
-                                 *sect,
-                                 m_Linker.getLDInfo(),
-                                 m_Linker.getLayout(),
-                                 *region);
+        target().emitSectionData(**sect, *region);
         break;
       default:
         continue;
@@ -118,37 +111,35 @@
 
   } // end of for loop
 
+  emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
+                  pModule,
+                  pOutput);
+
   if (32 == target().bitclass()) {
     // Write out ELF header
     // Write out section header table
-    emitELF32ShStrTab(pOutput, m_Linker);
-
     writeELF32Header(m_Linker.getLDInfo(),
-                     m_Linker.getLayout(),
-                     target(),
+                     pModule,
                      pOutput);
 
-    emitELF32ProgramHeader(pOutput, target());
+    emitELF32ProgramHeader(pOutput);
 
-    emitELF32SectionHeader(pOutput, m_Linker);
+    emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
   }
   else if (64 == target().bitclass()) {
     // Write out ELF header
     // Write out section header table
-    emitELF64ShStrTab(pOutput, m_Linker);
-
     writeELF64Header(m_Linker.getLDInfo(),
-                     m_Linker.getLayout(),
-                     target(),
+                     pModule,
                      pOutput);
 
-    emitELF64ProgramHeader(pOutput, target());
+    emitELF64ProgramHeader(pOutput);
 
-    emitELF64SectionHeader(pOutput, m_Linker);
+    emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
   }
   else
     return make_error_code(errc::not_supported);
-  pOutput.memArea()->clear();
+  pOutput.clear();
   return llvm::make_error_code(llvm::errc::success);
 }
 
diff --git a/lib/LD/ELFExecFileFormat.cpp b/lib/LD/ELFExecFileFormat.cpp
index 8ae0de0..a05c058 100644
--- a/lib/LD/ELFExecFileFormat.cpp
+++ b/lib/LD/ELFExecFileFormat.cpp
@@ -6,81 +6,81 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/Support/ELF.h>
 #include <mcld/LD/ELFExecFileFormat.h>
-#include <mcld/LD/LDFileFormat.h>
 #include <mcld/LD/LDSection.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <llvm/Support/ELF.h>
 
 using namespace mcld;
 
-void ELFExecFileFormat::initObjectType(MCLinker& pLinker)
+void ELFExecFileFormat::initObjectFormat(ObjectBuilder& pBuilder,
+                                         unsigned int pBitClass)
 {
   // FIXME: make sure ELF executable files has these sections.
-  f_pDynSymTab    = &pLinker.getOrCreateOutputSectHdr(".dynsym",
+  f_pDynSymTab    = pBuilder.CreateSection(".dynsym",
                                            LDFileFormat::NamePool,
                                            llvm::ELF::SHT_DYNSYM,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pDynStrTab    = &pLinker.getOrCreateOutputSectHdr(".dynstr",
+                                           pBitClass / 8);
+  f_pDynStrTab    = pBuilder.CreateSection(".dynstr",
                                            LDFileFormat::NamePool,
                                            llvm::ELF::SHT_STRTAB,
                                            llvm::ELF::SHF_ALLOC,
                                            0x1);
-  f_pInterp       = &pLinker.getOrCreateOutputSectHdr(".interp",
+  f_pInterp       = pBuilder.CreateSection(".interp",
                                            LDFileFormat::Note,
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC,
                                            0x1);
-  f_pHashTab      = &pLinker.getOrCreateOutputSectHdr(".hash",
+  f_pHashTab      = pBuilder.CreateSection(".hash",
                                            LDFileFormat::NamePool,
                                            llvm::ELF::SHT_HASH,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pDynamic      = &pLinker.getOrCreateOutputSectHdr(".dynamic",
+                                           pBitClass / 8);
+  f_pDynamic      = pBuilder.CreateSection(".dynamic",
                                            LDFileFormat::NamePool,
                                            llvm::ELF::SHT_DYNAMIC,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
-                                           f_Backend.bitclass() / 8);
-  f_pRelaDyn      = &pLinker.getOrCreateOutputSectHdr(".rela.dyn",
+                                           pBitClass / 8);
+  f_pRelaDyn      = pBuilder.CreateSection(".rela.dyn",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_RELA,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pRelaPlt      = &pLinker.getOrCreateOutputSectHdr(".rela.plt",
+                                           pBitClass / 8);
+  f_pRelaPlt      = pBuilder.CreateSection(".rela.plt",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_RELA,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pRelDyn      = &pLinker.getOrCreateOutputSectHdr(".rel.dyn",
+                                           pBitClass / 8);
+  f_pRelDyn      = pBuilder.CreateSection(".rel.dyn",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_REL,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pRelPlt      = &pLinker.getOrCreateOutputSectHdr(".rel.plt",
+                                           pBitClass / 8);
+  f_pRelPlt      = pBuilder.CreateSection(".rel.plt",
                                            LDFileFormat::Relocation,
                                            llvm::ELF::SHT_REL,
                                            llvm::ELF::SHF_ALLOC,
-                                           f_Backend.bitclass() / 8);
-  f_pGOT          = &pLinker.getOrCreateOutputSectHdr(".got",
+                                           pBitClass / 8);
+  f_pGOT          = pBuilder.CreateSection(".got",
                                            LDFileFormat::Target,
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
-                                           f_Backend.bitclass() / 8);
-  f_pPLT          = &pLinker.getOrCreateOutputSectHdr(".plt",
+                                           pBitClass / 8);
+  f_pPLT          = pBuilder.CreateSection(".plt",
                                            LDFileFormat::Target,
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
-                                           f_Backend.bitclass() / 8);
-  f_pGOTPLT       = &pLinker.getOrCreateOutputSectHdr(".got.plt",
+                                           pBitClass / 8);
+  f_pGOTPLT       = pBuilder.CreateSection(".got.plt",
                                            LDFileFormat::Target,
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
-                                           f_Backend.bitclass() / 8);
-  f_pEhFrameHdr     = &pLinker.getOrCreateOutputSectHdr(".eh_frame_hdr",
-                                              LDFileFormat::EhFrameHdr,
-                                              llvm::ELF::SHT_PROGBITS,
-                                              llvm::ELF::SHF_ALLOC,
-                                              0x4);
+                                           pBitClass / 8);
+  f_pEhFrameHdr   = pBuilder.CreateSection(".eh_frame_hdr",
+                                           LDFileFormat::EhFrameHdr,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC,
+                                           0x4);
 }
diff --git a/lib/LD/ELFExecWriter.cpp b/lib/LD/ELFExecWriter.cpp
index 7438180..dec5e26 100644
--- a/lib/LD/ELFExecWriter.cpp
+++ b/lib/LD/ELFExecWriter.cpp
@@ -7,12 +7,14 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/ELFExecWriter.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/Target/GNULDBackend.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Support/MemoryArea.h>
+
 #include <llvm/Support/ELF.h>
 #include <vector>
 
@@ -20,12 +22,12 @@
 using namespace mcld;
 
 
-//==========================
+//===----------------------------------------------------------------------===//
 // ELFExecWriter
-ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker)
+//===----------------------------------------------------------------------===//
+ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, FragmentLinker& pLinker)
   : ExecWriter(pBackend),
     ELFWriter(pBackend),
-    m_Backend(pBackend),
     m_Linker(pLinker) {
 
 }
@@ -34,43 +36,34 @@
 {
 }
 
-llvm::error_code ELFExecWriter::writeExecutable(Output& pOutput)
+llvm::error_code ELFExecWriter::writeExecutable(Module& pModule,
+                                                MemoryArea& pOutput)
 {
   // write out the interpreter section: .interp
-  target().emitInterp(pOutput, m_Linker.getLDInfo());
+  target().emitInterp(pOutput);
 
   // Write out name pool sections: .dynsym, .dynstr, .hash
-  target().emitDynNamePools(pOutput,
-                            m_Linker.getOutputSymbols(),
-                            m_Linker.getLayout(),
-                            m_Linker.getLDInfo());
+  target().emitDynNamePools(pModule, pOutput);
 
   // Write out name pool sections: .symtab, .strtab
-  target().emitRegNamePools(pOutput,
-                            m_Linker.getOutputSymbols(),
-                            m_Linker.getLayout(),
-                            m_Linker.getLDInfo());
+  target().emitRegNamePools(pModule, pOutput);
 
   // Write out regular ELF sections
-  unsigned int secIdx = 0;
-  unsigned int secEnd = pOutput.context()->numOfSections();
-  for (secIdx = 0; secIdx < secEnd; ++secIdx) {
-    LDSection* sect = pOutput.context()->getSection(secIdx);
+  Module::iterator sect, sectEnd = pModule.end();
+  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
     MemoryRegion* region = NULL;
     // request output region
-    switch(sect->kind()) {
+    switch((*sect)->kind()) {
       case LDFileFormat::Regular:
       case LDFileFormat::Relocation:
       case LDFileFormat::Target:
       case LDFileFormat::Debug:
       case LDFileFormat::GCCExceptTable:
       case LDFileFormat::EhFrame: {
-        region = pOutput.memArea()->request(sect->offset(), sect->size());
+        region = pOutput.request((*sect)->offset(), (*sect)->size());
         if (NULL == region) {
-          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") +
-                                   llvm::Twine(secIdx) +
-                                   llvm::Twine("] - `") +
-                                   sect->name() +
+          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
+                                   llvm::Twine((*sect)->name()) +
                                    llvm::Twine("'.\n"));
         }
         break;
@@ -82,76 +75,71 @@
       case LDFileFormat::MetaData:
       case LDFileFormat::Version:
       case LDFileFormat::EhFrameHdr:
+      case LDFileFormat::StackNote:
         // ignore these sections
         continue;
       default: {
         llvm::errs() << "WARNING: unsupported section kind: "
-                     << sect->kind()
+                     << (*sect)->kind()
                      << " of section "
-                     << sect->name()
+                     << (*sect)->name()
                      << ".\n";
         continue;
       }
     }
 
     // write out sections with data
-    switch(sect->kind()) {
+    switch((*sect)->kind()) {
       case LDFileFormat::Regular:
       case LDFileFormat::Debug:
       case LDFileFormat::GCCExceptTable:
       case LDFileFormat::EhFrame: {
         // FIXME: if optimization of exception handling sections is enabled,
         // then we should emit these sections by the other way.
-        emitSectionData(m_Linker.getLayout(), *sect, *region);
+        emitSectionData(**sect, *region);
         break;
       }
       case LDFileFormat::Relocation:
-        emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
+        emitRelocation(m_Linker.getLDInfo(), **sect, *region);
         break;
       case LDFileFormat::Target:
-        target().emitSectionData(pOutput,
-                                 *sect,
-                                 m_Linker.getLDInfo(),
-                                 m_Linker.getLayout(),
-                                 *region);
+        target().emitSectionData(**sect, *region);
         break;
       default:
         continue;
     }
   } // end of for loop
 
+  emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
+                  pModule,
+                  pOutput);
+
   if (32 == target().bitclass()) {
     // Write out ELF header
     // Write out section header table
-    emitELF32ShStrTab(pOutput, m_Linker);
-
     writeELF32Header(m_Linker.getLDInfo(),
-                     m_Linker.getLayout(),
-                     target(),
+                     pModule,
                      pOutput);
 
-    emitELF32ProgramHeader(pOutput, target());
+    emitELF32ProgramHeader(pOutput);
 
-    emitELF32SectionHeader(pOutput, m_Linker);
+    emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
   }
   else if (64 == target().bitclass()) {
     // Write out ELF header
     // Write out section header table
-    emitELF64ShStrTab(pOutput, m_Linker);
-
     writeELF64Header(m_Linker.getLDInfo(),
-                     m_Linker.getLayout(),
-                     target(),
+                     pModule,
                      pOutput);
 
-    emitELF64ProgramHeader(pOutput, target());
+    emitELF64ProgramHeader(pOutput);
 
-    emitELF64SectionHeader(pOutput, m_Linker);
+    emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
   }
   else
     return make_error_code(errc::not_supported);
 
-  pOutput.memArea()->clear();
+  pOutput.clear();
   return llvm::make_error_code(llvm::errc::success);
 }
 
diff --git a/lib/LD/ELFFileFormat.cpp b/lib/LD/ELFFileFormat.cpp
index f1c39cb..7512e38 100644
--- a/lib/LD/ELFFileFormat.cpp
+++ b/lib/LD/ELFFileFormat.cpp
@@ -7,16 +7,15 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/ELFFileFormat.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCLDFile.h>
-#include <llvm/Support/ELF.h>
+#include <mcld/Object/ObjectBuilder.h>
 #include <mcld/Target/GNULDBackend.h>
 
+#include <llvm/Support/ELF.h>
+
 using namespace mcld;
 
-ELFFileFormat::ELFFileFormat(GNULDBackend& pBackend)
-  : f_Backend(pBackend),
-    f_pNULLSection(NULL),
+ELFFileFormat::ELFFileFormat()
+  : f_pNULLSection(NULL),
     f_pGOT(NULL),
     f_pPLT(NULL),
     f_pRelDyn(NULL),
@@ -58,94 +57,92 @@
     f_pNoteABITag(NULL),
     f_pStab(NULL),
     f_pStabStr(NULL),
-    f_pStack(NULL) {
+    f_pStack(NULL),
+    f_pStackNote(NULL),
+    f_pDataRelRoLocal(NULL) {
 
 }
 
-ELFFileFormat::~ELFFileFormat()
+void ELFFileFormat::initStdSections(ObjectBuilder& pBuilder, unsigned int pBitClass)
 {
-}
-
-void ELFFileFormat::initObjectFormat(MCLinker& pLinker)
-{
-  f_pTextSection     = &pLinker.getOrCreateOutputSectHdr(".text",
+  f_pTextSection     = pBuilder.CreateSection(".text",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
                                               0x1);
-  f_pNULLSection     = &pLinker.getOrCreateOutputSectHdr("",
+  f_pNULLSection     = pBuilder.CreateSection("",
                                               LDFileFormat::Null,
                                               llvm::ELF::SHT_NULL,
                                               0x0);
-  f_pReadOnlySection = &pLinker.getOrCreateOutputSectHdr(".rodata",
+  f_pReadOnlySection = pBuilder.CreateSection(".rodata",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
                                               0x1);
 
-  f_pBSSSection      = &pLinker.getOrCreateOutputSectHdr(".bss",
+  f_pBSSSection      = pBuilder.CreateSection(".bss",
                                               LDFileFormat::BSS,
                                               llvm::ELF::SHT_NOBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pComment         = &pLinker.getOrCreateOutputSectHdr(".comment",
+  f_pComment         = pBuilder.CreateSection(".comment",
                                               LDFileFormat::MetaData,
                                               llvm::ELF::SHT_PROGBITS,
                                               0x0,
                                               0x1);
-  f_pDataSection     = &pLinker.getOrCreateOutputSectHdr(".data",
+  f_pDataSection     = pBuilder.CreateSection(".data",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pData1           = &pLinker.getOrCreateOutputSectHdr(".data1",
+  f_pData1           = pBuilder.CreateSection(".data1",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pDebug           = &pLinker.getOrCreateOutputSectHdr(".debug",
+  f_pDebug           = pBuilder.CreateSection(".debug",
                                               LDFileFormat::Debug,
                                               llvm::ELF::SHT_PROGBITS,
                                               0x0,
                                               0x1);
-  f_pInit            = &pLinker.getOrCreateOutputSectHdr(".init",
+  f_pInit            = pBuilder.CreateSection(".init",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
                                               0x1);
-  f_pInitArray       = &pLinker.getOrCreateOutputSectHdr(".init_array",
+  f_pInitArray       = pBuilder.CreateSection(".init_array",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_INIT_ARRAY,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pFini            = &pLinker.getOrCreateOutputSectHdr(".fini",
+  f_pFini            = pBuilder.CreateSection(".fini",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
                                               0x1);
-  f_pFiniArray       = &pLinker.getOrCreateOutputSectHdr(".fini_array",
+  f_pFiniArray       = pBuilder.CreateSection(".fini_array",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_FINI_ARRAY,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pLine            = &pLinker.getOrCreateOutputSectHdr(".line",
+  f_pLine            = pBuilder.CreateSection(".line",
                                               LDFileFormat::Debug,
                                               llvm::ELF::SHT_PROGBITS,
                                               0x0,
                                               0x1);
-  f_pPreInitArray    = &pLinker.getOrCreateOutputSectHdr(".preinit_array",
+  f_pPreInitArray    = pBuilder.CreateSection(".preinit_array",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PREINIT_ARRAY,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
   // the definition of SHF_XXX attributes of rodata in Linux Standard Base
   // conflicts with System V standard. We follow System V standard.
-  f_pROData1         = &pLinker.getOrCreateOutputSectHdr(".rodata1",
+  f_pROData1         = pBuilder.CreateSection(".rodata1",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
                                               0x1);
-  f_pShStrTab        = &pLinker.getOrCreateOutputSectHdr(".shstrtab",
+  f_pShStrTab        = pBuilder.CreateSection(".shstrtab",
                                               LDFileFormat::NamePool,
                                               llvm::ELF::SHT_STRTAB,
                                               0x0,
@@ -153,24 +150,24 @@
   // In ELF Spec Book I, p1-16. If symbol table and string table are in 
   // loadable segments, set the attribute to SHF_ALLOC bit. But in the
   // real world, this bit always turn off.
-  f_pSymTab       = &pLinker.getOrCreateOutputSectHdr(".symtab",
+  f_pSymTab          = pBuilder.CreateSection(".symtab",
                                               LDFileFormat::NamePool,
                                               llvm::ELF::SHT_SYMTAB,
                                               0x0,
-                                              f_Backend.bitclass() / 8);
-  f_pStrTab       = &pLinker.getOrCreateOutputSectHdr(".strtab",
+                                              pBitClass / 8);
+  f_pStrTab          = pBuilder.CreateSection(".strtab",
                                               LDFileFormat::NamePool,
                                               llvm::ELF::SHT_STRTAB,
                                               0x0,
                                               0x1);
-  f_pTBSS         = &pLinker.getOrCreateOutputSectHdr(".tbss",
+  f_pTBSS            = pBuilder.CreateSection(".tbss",
                                               LDFileFormat::BSS,
                                               llvm::ELF::SHT_NOBITS,
                                               llvm::ELF::SHF_ALLOC |
                                               llvm::ELF::SHF_WRITE |
                                               llvm::ELF::SHF_TLS,
                                               0x1);
-  f_pTData        = &pLinker.getOrCreateOutputSectHdr(".tdata",
+  f_pTData           = pBuilder.CreateSection(".tdata",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC |
@@ -179,60 +176,75 @@
                                               0x1);
 
   /// @ref 10.3.1.2, ISO/IEC 23360, Part 1:2010(E), p. 24.
-  f_pCtors          = &pLinker.getOrCreateOutputSectHdr(".ctor",
+  f_pCtors           = pBuilder.CreateSection(".ctors",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pDataRelRo      = &pLinker.getOrCreateOutputSectHdr(".data.rel.ro",
+  f_pDataRelRo       = pBuilder.CreateSection(".data.rel.ro",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pDtors          = &pLinker.getOrCreateOutputSectHdr(".dtors",
+  f_pDtors           = pBuilder.CreateSection(".dtors",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pEhFrame        = &pLinker.getOrCreateOutputSectHdr(".eh_frame",
+  f_pEhFrame         = pBuilder.CreateSection(".eh_frame",
                                               LDFileFormat::EhFrame,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
                                               0x4);
-  f_pGCCExceptTable = &pLinker.getOrCreateOutputSectHdr(".gcc_except_table",
+  f_pGCCExceptTable  = pBuilder.CreateSection(".gcc_except_table",
                                               LDFileFormat::GCCExceptTable,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
                                               0x4);
-  f_pGNUVersion     = &pLinker.getOrCreateOutputSectHdr(".gnu.version",
+  f_pGNUVersion      = pBuilder.CreateSection(".gnu.version",
                                               LDFileFormat::Version,
                                               llvm::ELF::SHT_GNU_versym,
                                               llvm::ELF::SHF_ALLOC,
                                               0x1);
-  f_pGNUVersionD    = &pLinker.getOrCreateOutputSectHdr(".gnu.version_d",
+  f_pGNUVersionD     = pBuilder.CreateSection(".gnu.version_d",
                                               LDFileFormat::Version,
                                               llvm::ELF::SHT_GNU_verdef,
                                               llvm::ELF::SHF_ALLOC,
                                               0x1);
-  f_pGNUVersionR    = &pLinker.getOrCreateOutputSectHdr(".gnu.version_r",
+  f_pGNUVersionR     = pBuilder.CreateSection(".gnu.version_r",
                                               LDFileFormat::Version,
                                               llvm::ELF::SHT_GNU_verneed,
                                               llvm::ELF::SHF_ALLOC,
                                               0x1);
-  f_pJCR            = &pLinker.getOrCreateOutputSectHdr(".jcr",
+  f_pJCR             = pBuilder.CreateSection(".jcr",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
-  f_pStab           = &pLinker.getOrCreateOutputSectHdr(".stab",
+  f_pStab            = pBuilder.CreateSection(".stab",
                                               LDFileFormat::Debug,
                                               llvm::ELF::SHT_PROGBITS,
                                               0x0,
                                               0x1);
-  f_pStabStr        = &pLinker.getOrCreateOutputSectHdr(".stabstr",
+  f_pStabStr         = pBuilder.CreateSection(".stabstr",
                                               LDFileFormat::Debug,
                                               llvm::ELF::SHT_STRTAB,
                                               0x0,
                                               0x1);
+  f_pStackNote       = pBuilder.CreateSection(".note.GNU-stack",
+                                              LDFileFormat::StackNote,
+                                              llvm::ELF::SHT_PROGBITS,
+                                              0x0,
+                                              0x1);
+
+  /// @ref GCC convention, see http://www.airs.com/blog/archives/189
+  f_pDataRelRoLocal  = pBuilder.CreateSection(".data.rel.ro.local",
+                                              LDFileFormat::Regular,
+                                              llvm::ELF::SHT_PROGBITS,
+                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+                                              0x1);
+  /// Initialize format dependent sections. (sections for executable and shared
+  /// objects)
+  initObjectFormat(pBuilder, pBitClass);
 }
 
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index e645567..4124098 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -6,6 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFObjectReader.h>
 
 #include <string>
 #include <cassert>
@@ -13,33 +14,41 @@
 #include <llvm/Support/ELF.h>
 #include <llvm/ADT/Twine.h>
 
+#include <mcld/IRBuilder.h>
 #include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/RegionFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/LD/ELFReader.h>
-#include <mcld/LD/ELFObjectReader.h>
+#include <mcld/LD/EhFrameReader.h>
+#include <mcld/LD/EhFrame.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/Support/MsgHandling.h>
+#include <mcld/Object/ObjectBuilder.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // ELFObjectReader
+//===----------------------------------------------------------------------===//
 /// constructor
-ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend, MCLinker& pLinker)
+ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend, FragmentLinker& pLinker)
   : ObjectReader(),
-    m_pELFReader(0),
-    m_Linker(pLinker)
-{
+    m_pELFReader(NULL),
+    m_pEhFrameReader(NULL),
+    m_Linker(pLinker),
+    m_ReadFlag(ParseEhFrame),
+    m_Backend(pBackend) {
   if (32 == pBackend.bitclass() && pBackend.isLittleEndian()) {
     m_pELFReader = new ELFReader<32, true>(pBackend);
   }
+
+  m_pEhFrameReader = new EhFrameReader();
 }
 
 /// destructor
 ELFObjectReader::~ELFObjectReader()
 {
   delete m_pELFReader;
+  delete m_pEhFrameReader;
 }
 
 /// isMyFormat
@@ -61,14 +70,14 @@
     result = false;
   else if (!m_pELFReader->isMyMachine(ELF_hdr))
     result = false;
-  else if (MCLDFile::Object != m_pELFReader->fileType(ELF_hdr))
+  else if (Input::Object != m_pELFReader->fileType(ELF_hdr))
     result = false;
   pInput.memArea()->release(region);
   return result;
 }
 
-/// readObject - read section header and create LDSections.
-bool ELFObjectReader::readObject(Input& pInput)
+/// readHeader - read section header and create LDSections.
+bool ELFObjectReader::readHeader(Input& pInput)
 {
   assert(pInput.hasMemArea());
 
@@ -76,7 +85,7 @@
   MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
                                                      hdr_size);
   uint8_t* ELF_hdr = region->start();
-  bool result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
+  bool result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
   pInput.memArea()->release(region);
   return result;
 }
@@ -96,13 +105,12 @@
       case LDFileFormat::Group: {
         assert(NULL != (*section)->getLink());
         ResolveInfo* signature =
-              m_pELFReader->readSymbol(pInput,
-                                       *(*section)->getLink(),
-                                       m_Linker.getLDInfo(),
-                                       (*section)->getInfo());
+              m_pELFReader->readSignature(pInput,
+                                          *(*section)->getLink(),
+                                          (*section)->getInfo());
 
         bool exist = false;
-        if (0 == std::strlen(signature->name()) &&
+        if (0 == signature->nameSize() &&
             ResolveInfo::Section == signature->type()) {
           // if the signature is a section symbol in input object, we use the
           // section name as group signature.
@@ -113,7 +121,7 @@
 
         if (exist) {
           // if this is not the first time we see this group signature, then
-          // ignore all the members in this group (set NULL)
+          // ignore all the members in this group (set Ignore)
           MemoryRegion* region = pInput.memArea()->request(
                pInput.fileOffset() + (*section)->offset(), (*section)->size());
           llvm::ELF::Elf32_Word* value =
@@ -121,75 +129,93 @@
 
           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()->getSectionTable()[value[index]] = NULL;
+            for (size_t index = 1; index < size; ++index) {
+              pInput.context()->getSection(value[index])->setKind(LDFileFormat::Ignore);
+            }
           }
           pInput.memArea()->release(region);
         }
+        ResolveInfo::Destroy(signature);
         break;
       }
       /** relocation sections **/
       case LDFileFormat::Relocation: {
         assert(NULL != (*section)->getLink());
         size_t link_index = (*section)->getLink()->index();
-        if (NULL == pInput.context()->getSectionTable()[link_index]) {
+        LDSection* link_sect = pInput.context()->getSection(link_index);
+        if (NULL == link_sect || LDFileFormat::Ignore == link_sect->kind()) {
           // Relocation sections of group members should also be part of the
           // group. Thus, if the associated member sections are ignored, the
           // related relocations should be also ignored.
-          *section = NULL;
+          (*section)->setKind(LDFileFormat::Ignore);
         }
         break;
       }
       /** normal sections **/
-      // FIXME: support Version Kinds
+      // FIXME: support Version Kind
       case LDFileFormat::Version:
+      // FIXME: support GCCExceptTable Kind
+      case LDFileFormat::GCCExceptTable:
       /** Fall through **/
       case LDFileFormat::Regular:
       case LDFileFormat::Note:
-      case LDFileFormat::Debug:
       case LDFileFormat::MetaData: {
-        if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
+        SectionData* sd = IRBuilder::CreateSectionData(**section);
+        if (!m_pELFReader->readRegularSection(pInput, *sd))
           fatal(diag::err_cannot_read_section) << (*section)->name();
         break;
       }
+      case LDFileFormat::Debug: {
+        if (m_Linker.getLDInfo().options().stripDebug()) {
+          (*section)->setKind(LDFileFormat::Ignore);
+        }
+        else {
+          SectionData* sd = IRBuilder::CreateSectionData(**section);
+          if (!m_pELFReader->readRegularSection(pInput, *sd)) {
+            fatal(diag::err_cannot_read_section) << (*section)->name();
+          }
+        }
+        break;
+      }
       case LDFileFormat::EhFrame: {
-        if (!m_pELFReader->readEhFrame(pInput, m_Linker, **section))
-          fatal(diag::err_cannot_read_section) <<(*section)->name();
-        break;
-      }
-      case LDFileFormat::GCCExceptTable: {
-        //if (!m_pELFReader->readExceptionSection(pInput, m_Linker, **section))
-        if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
-          fatal(diag::err_cannot_read_section) << (*section)->name();
+        EhFrame* eh_frame = IRBuilder::CreateEhFrame(**section);
+
+        if (m_Linker.getLDInfo().options().hasEhFrameHdr() &&
+            (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.
+            m_ReadFlag ^= ParseEhFrame;
+          }
+        }
+        else {
+          if (!m_pELFReader->readRegularSection(pInput,
+                                                eh_frame->getSectionData())) {
+            fatal(diag::err_cannot_read_section) << (*section)->name();
+          }
+        }
         break;
       }
       /** target dependent sections **/
       case LDFileFormat::Target: {
-        if (!m_pELFReader->readTargetSection(pInput, m_Linker, **section))
+        SectionData* sd = IRBuilder::CreateSectionData(**section);
+        if (!m_Backend.readSection(pInput, *sd)) {
           fatal(diag::err_cannot_read_target_section) << (*section)->name();
+        }
         break;
       }
       /** BSS sections **/
       case LDFileFormat::BSS: {
-        LDSection& output_bss = m_Linker.getOrCreateOutputSectHdr(
-                                               (*section)->name(),
-                                               LDFileFormat::BSS,
-                                               llvm::ELF::SHT_NOBITS,
-                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE);
-
-        SectionData& sect_data = m_Linker.getOrCreateSectData(**section);
-                                            /*  value, valsize, size*/
-        FillFragment* frag = new FillFragment(0x0,   1,       (*section)->size());
-
-        uint64_t size = m_Linker.getLayout().appendFragment(*frag,
-                                                            sect_data,
-                                                            (*section)->align());
-        output_bss.setSize(output_bss.size() + size);
+        IRBuilder::CreateBSS(**section);
         break;
       }
       // ignore
       case LDFileFormat::Null:
       case LDFileFormat::NamePool:
+      case LDFileFormat::Ignore:
+      case LDFileFormat::StackNote:
         continue;
       // warning
       case LDFileFormat::EhFrameHdr:
@@ -205,7 +231,7 @@
   return true;
 }
 
-/// readSymbols - read symbols into MCLinker from the input relocatable object.
+/// readSymbols - read symbols into FragmentLinker from the input relocatable object.
 bool ELFObjectReader::readSymbols(Input& pInput)
 {
   assert(pInput.hasMemArea());
@@ -245,32 +271,39 @@
   assert(pInput.hasMemArea());
 
   MemoryArea* mem = pInput.memArea();
-  LDContext::sect_iterator section, sectEnd = pInput.context()->sectEnd();
-  for (section = pInput.context()->sectBegin(); section != sectEnd; ++section) {
-    // ignore the section if the LDSection* in input context is NULL
-    if (NULL == *section)
-        continue;
+  LDContext::sect_iterator rs, rsEnd = pInput.context()->relocSectEnd();
+  for (rs = pInput.context()->relocSectBegin(); rs != rsEnd; ++rs) {
+    if (LDFileFormat::Ignore == (*rs)->kind())
+      continue;
 
-    if ((*section)->type() == llvm::ELF::SHT_RELA &&
-        (*section)->kind() == LDFileFormat::Relocation) {
-      MemoryRegion* region = mem->request(
-               pInput.fileOffset() + (*section)->offset(), (*section)->size());
-      bool result = m_pELFReader->readRela(pInput, m_Linker, **section,
-                                           *region);
-      mem->release(region);
-      if (!result)
+    uint32_t offset = pInput.fileOffset() + (*rs)->offset();
+    uint32_t size = (*rs)->size();
+    MemoryRegion* 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, m_Linker, **rs, *region)) {
+          mem->release(region);
+          return false;
+        }
+        break;
+      }
+      case llvm::ELF::SHT_REL: {
+        if (!m_pELFReader->readRel(pInput, m_Linker, **rs, *region)) {
+          mem->release(region);
+          return false;
+        }
+        break;
+      }
+      default: { ///< should not enter
+        mem->release(region);
         return false;
-    }
-    else if ((*section)->type() == llvm::ELF::SHT_REL &&
-             (*section)->kind() == LDFileFormat::Relocation) {
-      MemoryRegion* region = mem->request(
-               pInput.fileOffset() + (*section)->offset(), (*section)->size());
-      bool result = m_pELFReader->readRel(pInput, m_Linker, **section, *region);
-      mem->release(region);
-      if (!result)
-        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 2795d3f..ee9a7ac 100644
--- a/lib/LD/ELFObjectWriter.cpp
+++ b/lib/LD/ELFObjectWriter.cpp
@@ -6,13 +6,22 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/LD/ELFObjectWriter.h"
+#include <mcld/LD/ELFObjectWriter.h>
 
+#include <mcld/Module.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Support/MemoryArea.h>
+
+#include <llvm/Support/system_error.h>
+using namespace llvm;
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // ELFObjectWriter
-ELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend, MCLinker& pLinker)
+//===----------------------------------------------------------------------===//
+ELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend,
+                                 FragmentLinker& pLinker)
   : ObjectWriter(pBackend), ELFWriter(pBackend), m_Linker(pLinker) {
 }
 
@@ -20,4 +29,100 @@
 {
 }
 
+llvm::error_code ELFObjectWriter::writeObject(Module& pModule,
+                                              MemoryArea& pOutput)
+{
+  // Write out name pool sections: .symtab, .strtab
+  target().emitRegNamePools(pModule, pOutput);
+
+  // Write out regular ELF sections
+  Module::iterator sect, sectEnd = pModule.end();
+  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+    MemoryRegion* region = NULL;
+    // request output region
+    switch((*sect)->kind()) {
+      case LDFileFormat::Regular:
+      case LDFileFormat::Relocation:
+      case LDFileFormat::Target:
+      case LDFileFormat::Debug:
+      case LDFileFormat::GCCExceptTable:
+      case LDFileFormat::EhFrame: {
+        region = pOutput.request((*sect)->offset(), (*sect)->size());
+        if (NULL == region) {
+          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
+                                   llvm::Twine((*sect)->name()) +
+                                   llvm::Twine("'.\n"));
+        }
+        break;
+      }
+      case LDFileFormat::Null:
+      case LDFileFormat::NamePool:
+      case LDFileFormat::BSS:
+      case LDFileFormat::Note:
+      case LDFileFormat::MetaData:
+      case LDFileFormat::Version:
+      case LDFileFormat::EhFrameHdr:
+      case LDFileFormat::StackNote:
+        // ignore these sections
+        continue;
+      default: {
+        llvm::errs() << "WARNING: unsupported section kind: "
+                     << (*sect)->kind()
+                     << " of section "
+                     << (*sect)->name()
+                     << ".\n";
+        continue;
+      }
+    }
+
+    // write out sections with data
+    switch((*sect)->kind()) {
+      case LDFileFormat::Regular:
+      case LDFileFormat::Debug:
+      case LDFileFormat::GCCExceptTable:
+      case LDFileFormat::EhFrame: {
+        // FIXME: if optimization of exception handling sections is enabled,
+        // then we should emit these sections by the other way.
+        emitSectionData(**sect, *region);
+        break;
+      }
+      case LDFileFormat::Relocation:
+        emitRelocation(m_Linker.getLDInfo(), **sect, *region);
+        break;
+      case LDFileFormat::Target:
+        target().emitSectionData(**sect, *region);
+        break;
+      default:
+        continue;
+    }
+  } // end of for loop
+
+  emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
+                  pModule,
+                  pOutput);
+
+  if (32 == target().bitclass()) {
+    // Write out ELF header
+    // Write out section header table
+    writeELF32Header(m_Linker.getLDInfo(),
+                     pModule,
+                     pOutput);
+
+    emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+  }
+  else if (64 == target().bitclass()) {
+    // Write out ELF header
+    // Write out section header table
+    writeELF64Header(m_Linker.getLDInfo(),
+                     pModule,
+                     pOutput);
+
+    emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+  }
+  else
+    return make_error_code(errc::not_supported);
+
+  pOutput.clear();
+  return llvm::make_error_code(llvm::errc::success);
+}
 
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index fce4e8b..7f105b3 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -6,87 +6,31 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFReader.h>
+
+#include <mcld/IRBuilder.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <cstring>
 
 #include <llvm/ADT/StringRef.h>
 #include <llvm/ADT/Twine.h>
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Host.h>
 
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/ELFReader.h>
-#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MsgHandling.h>
-#include <cstring>
-
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
 // ELFReaderIF
-/// getLDSectionKind
-LDFileFormat::Kind
-ELFReaderIF::getLDSectionKind(uint32_t pType, const char* pName) const
-{
-  // name rules
-  llvm::StringRef name(pName);
-  if (name.startswith(".debug") ||
-      name.startswith(".zdebug") ||
-      name.startswith(".gnu.linkonce.wi.") ||
-      name.startswith(".line") ||
-      name.startswith(".stab"))
-    return LDFileFormat::Debug;
-  if (name.startswith(".comment"))
-    return LDFileFormat::MetaData;
-  if (name.startswith(".interp") || name.startswith(".dynamic"))
-    return LDFileFormat::Note;
-  if (name.startswith(".eh_frame"))
-    return LDFileFormat::EhFrame;
-  if (name.startswith(".eh_frame_hdr"))
-    return LDFileFormat::EhFrameHdr;
-  if (name.startswith(".gcc_except_table"))
-    return LDFileFormat::GCCExceptTable;
-
-  // type rules
-  switch(pType) {
-  case llvm::ELF::SHT_NULL:
-    return LDFileFormat::Null;
-  case llvm::ELF::SHT_INIT_ARRAY:
-  case llvm::ELF::SHT_FINI_ARRAY:
-  case llvm::ELF::SHT_PREINIT_ARRAY:
-  case llvm::ELF::SHT_PROGBITS:
-    return LDFileFormat::Regular;
-  case llvm::ELF::SHT_SYMTAB:
-  case llvm::ELF::SHT_DYNSYM:
-  case llvm::ELF::SHT_STRTAB:
-    return LDFileFormat::NamePool;
-  case llvm::ELF::SHT_RELA:
-  case llvm::ELF::SHT_REL:
-    return LDFileFormat::Relocation;
-  case llvm::ELF::SHT_NOBITS:
-    return LDFileFormat::BSS;
-  case llvm::ELF::SHT_DYNAMIC:
-  case llvm::ELF::SHT_NOTE:
-    return LDFileFormat::Note;
-  case llvm::ELF::SHT_HASH:
-  case llvm::ELF::SHT_SHLIB:
-    return LDFileFormat::MetaData;
-  case llvm::ELF::SHT_GROUP:
-    return LDFileFormat::Group;
-  case llvm::ELF::SHT_GNU_versym:
-  case llvm::ELF::SHT_GNU_verdef:
-  case llvm::ELF::SHT_GNU_verneed:
-    return LDFileFormat::Version;
-  default:
-    if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) ||
-        (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) ||
-        (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER))
-      return LDFileFormat::Target;
-    fatal(diag::err_unsupported_section) << pName << pType;
-  }
-  return LDFileFormat::MetaData;
-}
-
+//===----------------------------------------------------------------------===//
 /// getSymType
 ResolveInfo::Type ELFReaderIF::getSymType(uint8_t pInfo, uint16_t pShndx) const
 {
@@ -112,7 +56,8 @@
     // an ELF symbol defined in a section which we are not including
     // must be treated as an Undefined.
     // @ref Google gold linker: symtab.cc: 1086
-    if (NULL == pInput.context()->getSection(pShndx))
+    if (NULL == pInput.context()->getSection(pShndx) ||
+        LDFileFormat::Ignore == pInput.context()->getSection(pShndx)->kind())
       return ResolveInfo::Undefined;
     return ResolveInfo::Define;
   }
@@ -153,13 +98,15 @@
 /// getSymFragmentRef
 FragmentRef*
 ELFReaderIF::getSymFragmentRef(Input& pInput,
-                               MCLinker& pLinker,
                                uint16_t pShndx,
                                uint32_t pOffset) const
 {
 
+  if (Input::DynObj == pInput.type())
+    return FragmentRef::Null();
+
   if (pShndx == llvm::ELF::SHN_UNDEF || pShndx >= llvm::ELF::SHN_LORESERVE)
-    return NULL;
+    return FragmentRef::Null();
 
   LDSection* sect_hdr = pInput.context()->getSection(pShndx);
 
@@ -167,8 +114,13 @@
     unreachable(diag::unreachable_invalid_section_idx) << pShndx
                                                        << pInput.path().native();
 
-  FragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset);
-  return result;
+  if (LDFileFormat::Ignore == sect_hdr->kind())
+    return FragmentRef::Null();
+
+  if (LDFileFormat::Group == sect_hdr->kind())
+    return FragmentRef::Null();
+
+  return FragmentRef::Create(*sect_hdr, pOffset);
 }
 
 /// getSymVisibility
@@ -204,17 +156,510 @@
   return 0x0;
 }
 
-bool ELFReaderIF::readEhFrame(Input& pInput,
-                              MCLinker& pLinker,
-                              LDSection& pInputSectHdr) const
+//===----------------------------------------------------------------------===//
+// ELFReader<32, true>
+//===----------------------------------------------------------------------===//
+/// constructor
+ELFReader<32, true>::ELFReader(GNULDBackend& pBackend)
+  : ELFReaderIF(pBackend) {
+}
+
+/// destructor
+ELFReader<32, true>::~ELFReader()
 {
-  LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
-                                                         pInputSectHdr.kind(),
-                                                         pInputSectHdr.type(),
-                                                         pInputSectHdr.flag());
+}
 
-  size_t size = pLinker.addEhFrame(pInput, pInputSectHdr, *pInput.memArea());
+/// isELF - is this a ELF file
+bool ELFReader<32, true>::isELF(void* pELFHeader) const
+{
+  llvm::ELF::Elf32_Ehdr* hdr =
+                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+  if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
+    return true;
+  return false;
+}
 
-  out_sect.setSize(out_sect.size() + size);
+/// readRegularSection - read a regular section and create fragments.
+bool
+ELFReader<32, true>::readRegularSection(Input& pInput, SectionData& pSD) const
+{
+  uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
+  uint32_t size = pSD.getSection().size();
+
+  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
+  ObjectBuilder::AppendFragment(*frag, pSD);
   return true;
 }
+
+/// readSymbols - read ELF symbols and create LDSymbol
+bool ELFReader<32, true>::readSymbols(Input& pInput,
+                                      FragmentLinker& pLinker,
+                                      const MemoryRegion& 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());
+
+  uint32_t st_name  = 0x0;
+  uint32_t st_value = 0x0;
+  uint32_t st_size  = 0x0;
+  uint8_t  st_info  = 0x0;
+  uint8_t  st_other = 0x0;
+  uint16_t st_shndx = 0x0;
+
+  // skip the first NULL symbol
+  pInput.context()->addSymbol(LDSymbol::Null());
+
+  for (size_t idx = 1; idx < entsize; ++idx) {
+    st_info  = symtab[idx].st_info;
+    st_other = symtab[idx].st_other;
+
+    if (llvm::sys::isLittleEndianHost()) {
+      st_name  = symtab[idx].st_name;
+      st_value = symtab[idx].st_value;
+      st_size  = symtab[idx].st_size;
+      st_shndx = symtab[idx].st_shndx;
+    }
+    else {
+      st_name  = bswap32(symtab[idx].st_name);
+      st_value = bswap32(symtab[idx].st_value);
+      st_size  = bswap32(symtab[idx].st_size);
+      st_shndx = bswap16(symtab[idx].st_shndx);
+    }
+
+    // If the section should not be included, set the st_shndx SHN_UNDEF
+    // - A section in interrelated groups are not included.
+    if (pInput.type() == Input::Object &&
+        st_shndx < llvm::ELF::SHN_LORESERVE &&
+        st_shndx != llvm::ELF::SHN_UNDEF) {
+      if (NULL == pInput.context()->getSection(st_shndx))
+        st_shndx = llvm::ELF::SHN_UNDEF;
+    }
+
+    // get ld_type
+    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
+
+    // get ld_desc
+    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
+
+    // get ld_binding
+    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
+
+    // get ld_value - ld_value must be section relative.
+    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
+
+    // get the input fragment
+    FragmentRef* ld_frag_ref = getSymFragmentRef(pInput,
+                                                 st_shndx,
+                                                 ld_value);
+
+    // get ld_vis
+    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
+
+    // get ld_name
+    llvm::StringRef ld_name;
+    if (ResolveInfo::Section == ld_type) {
+      // Section symbol's st_name is the section index.
+      LDSection* section = pInput.context()->getSection(st_shndx);
+      assert(NULL != section && "get a invalid section");
+      ld_name = llvm::StringRef(section->name());
+    }
+    else {
+      ld_name = llvm::StringRef(pStrTab + st_name);
+    }
+
+
+    // push into FragmentLinker
+    LDSymbol* input_sym = NULL;
+
+    if (pInput.type() == Input::Object) {
+      input_sym = pLinker.addSymbol<Input::Object>(ld_name,
+                                                   ld_type,
+                                                   ld_desc,
+                                                   ld_binding,
+                                                   st_size,
+                                                   ld_value,
+                                                   ld_frag_ref,
+                                                   ld_vis);
+      // push into the input file
+      pInput.context()->addSymbol(input_sym);
+      continue;
+    }
+    else if (pInput.type() == Input::DynObj) {
+      input_sym = pLinker.addSymbol<Input::DynObj>(ld_name,
+                                                   ld_type,
+                                                   ld_desc,
+                                                   ld_binding,
+                                                   st_size,
+                                                   ld_value,
+                                                   ld_frag_ref,
+                                                   ld_vis);
+      continue;
+    }
+
+  } // end of for loop
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// ELFReader::read relocations - read ELF rela and rel, and create Relocation
+//===----------------------------------------------------------------------===//
+/// ELFReader::readRela - read ELF rela and create Relocation
+bool ELFReader<32, true>::readRela(Input& pInput,
+                                   FragmentLinker& pLinker,
+                                   LDSection& pSection,
+                                   const MemoryRegion& 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());
+
+  for (size_t idx=0; idx < entsize; ++idx) {
+    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 = bswap32(relaTab[idx].r_offset);
+      r_info   = bswap32(relaTab[idx].r_info);
+      r_addend = bswap32(relaTab[idx].r_addend);
+    }
+
+    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();
+    }
+
+    pLinker.addRelocation(r_type, *symbol, pSection, r_offset, r_addend);
+  } // end of for
+  return true;
+}
+
+/// readRel - read ELF rel and create Relocation
+bool ELFReader<32, true>::readRel(Input& pInput,
+                                  FragmentLinker& pLinker,
+                                  LDSection& pSection,
+                                  const MemoryRegion& 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());
+
+  for (size_t idx=0; idx < entsize; ++idx) {
+    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 = bswap32(relTab[idx].r_offset);
+      r_info   = bswap32(relTab[idx].r_info);
+    }
+
+    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();
+    }
+
+    pLinker.addRelocation(r_type, *symbol, pSection, r_offset);
+  } // end of for
+  return true;
+}
+
+/// isMyEndian - is this ELF file in the same endian to me?
+bool ELFReader<32, true>::isMyEndian(void* pELFHeader) const
+{
+  llvm::ELF::Elf32_Ehdr* hdr =
+                          reinterpret_cast<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
+{
+  llvm::ELF::Elf32_Ehdr* hdr =
+                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+
+  if (llvm::sys::isLittleEndianHost())
+    return (hdr->e_machine == target().machine());
+  return (bswap16(hdr->e_machine) == target().machine());
+}
+
+/// fileType - return the file type
+Input::Type ELFReader<32, true>::fileType(void* pELFHeader) const
+{
+  llvm::ELF::Elf32_Ehdr* hdr =
+                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+  uint32_t type = 0x0;
+  if (llvm::sys::isLittleEndianHost())
+    type = hdr->e_type;
+  else
+    type = bswap16(hdr->e_type);
+
+  switch(type) {
+  case llvm::ELF::ET_REL:
+    return Input::Object;
+  case llvm::ELF::ET_EXEC:
+    return Input::Exec;
+  case llvm::ELF::ET_DYN:
+    return Input::DynObj;
+  case llvm::ELF::ET_CORE:
+    return Input::CoreFile;
+  case llvm::ELF::ET_NONE:
+  default:
+    return Input::Unknown;
+  }
+}
+
+/// readSectionHeaders - read ELF section header table and create LDSections
+bool
+ELFReader<32, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
+{
+  llvm::ELF::Elf32_Ehdr* ehdr =
+                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+
+  uint32_t shoff     = 0x0;
+  uint16_t shentsize = 0x0;
+  uint16_t shnum     = 0x0;
+  uint16_t shstrtab  = 0x0;
+
+  if (llvm::sys::isLittleEndianHost()) {
+    shoff     = ehdr->e_shoff;
+    shentsize = ehdr->e_shentsize;
+    shnum     = ehdr->e_shnum;
+    shstrtab  = ehdr->e_shstrndx;
+  }
+  else {
+    shoff     = bswap32(ehdr->e_shoff);
+    shentsize = bswap16(ehdr->e_shentsize);
+    shnum     = bswap16(ehdr->e_shnum);
+    shstrtab  = bswap16(ehdr->e_shstrndx);
+  }
+
+  // If the file has no section header table, e_shoff holds zero.
+  if (0x0 == shoff)
+    return true;
+
+  MemoryRegion* shdr_region = pInput.memArea()->request(
+                                 pInput.fileOffset() + shoff, shnum*shentsize);
+  llvm::ELF::Elf32_Shdr* shdrTab =
+                reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
+
+  uint32_t sh_name      = 0x0;
+  uint32_t sh_type      = 0x0;
+  uint32_t sh_flags     = 0x0;
+  uint32_t sh_offset    = 0x0;
+  uint32_t sh_size      = 0x0;
+  uint32_t sh_link      = 0x0;
+  uint32_t sh_info      = 0x0;
+  uint32_t sh_addralign = 0x0;
+
+  // get .shstrtab first
+  llvm::ELF::Elf32_Shdr* shdr = &shdrTab[shstrtab];
+  if (llvm::sys::isLittleEndianHost()) {
+    sh_offset = shdr->sh_offset;
+    sh_size   = shdr->sh_size;
+  }
+  else {
+    sh_offset = bswap32(shdr->sh_offset);
+    sh_size   = 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());
+
+  LinkInfoList link_info_list;
+
+  // create all LDSections, including first NULL section.
+  for (size_t idx = 0; idx < shnum; ++idx) {
+    if (llvm::sys::isLittleEndianHost()) {
+      sh_name      = shdrTab[idx].sh_name;
+      sh_type      = shdrTab[idx].sh_type;
+      sh_flags     = shdrTab[idx].sh_flags;
+      sh_offset    = shdrTab[idx].sh_offset;
+      sh_size      = shdrTab[idx].sh_size;
+      sh_link      = shdrTab[idx].sh_link;
+      sh_info      = shdrTab[idx].sh_info;
+      sh_addralign = shdrTab[idx].sh_addralign;
+    }
+    else {
+      sh_name      = bswap32(shdrTab[idx].sh_name);
+      sh_type      = bswap32(shdrTab[idx].sh_type);
+      sh_flags     = bswap32(shdrTab[idx].sh_flags);
+      sh_offset    = bswap32(shdrTab[idx].sh_offset);
+      sh_size      = bswap32(shdrTab[idx].sh_size);
+      sh_link      = bswap32(shdrTab[idx].sh_link);
+      sh_info      = bswap32(shdrTab[idx].sh_info);
+      sh_addralign = bswap32(shdrTab[idx].sh_addralign);
+    }
+
+    LDSection* section = IRBuilder::CreateELFHeader(pInput,
+                                                    sect_name+sh_name,
+                                                    sh_type,
+                                                    sh_flags,
+                                                    sh_addralign);
+    section->setSize(sh_size);
+    section->setOffset(sh_offset);
+    section->setInfo(sh_info);
+
+    if (sh_link != 0x0 || sh_info != 0x0) {
+      LinkInfo link_info = { section, sh_link, sh_info };
+      link_info_list.push_back(link_info);
+    }
+  } // end of for
+
+  // set up InfoLink
+  LinkInfoList::iterator info, infoEnd = link_info_list.end();
+  for (info = link_info_list.begin(); info != infoEnd; ++info) {
+    if (LDFileFormat::NamePool == info->section->kind() ||
+        LDFileFormat::Group == info->section->kind() ||
+        LDFileFormat::Note == info->section->kind()) {
+      info->section->setLink(pInput.context()->getSection(info->sh_link));
+      continue;
+    }
+    if (LDFileFormat::Relocation == info->section->kind()) {
+      info->section->setLink(pInput.context()->getSection(info->sh_info));
+      continue;
+    }
+  }
+
+  pInput.memArea()->release(shdr_region);
+  pInput.memArea()->release(sect_name_region);
+
+  return true;
+}
+
+/// readSignature - read a symbol from the given Input and index in symtab
+/// This is used to get the signature of a group section.
+ResolveInfo* ELFReader<32, true>::readSignature(Input& pInput,
+                                                LDSection& pSymTab,
+                                                uint32_t pSymIdx) const
+{
+  LDSection* symtab = &pSymTab;
+  LDSection* strtab = symtab->getLink();
+  assert(NULL != symtab && NULL != strtab);
+
+  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());
+
+  uint32_t st_name  = 0x0;
+  uint8_t  st_info  = 0x0;
+  uint8_t  st_other = 0x0;
+  uint16_t st_shndx = 0x0;
+  st_info  = entry->st_info;
+  st_other = entry->st_other;
+  if (llvm::sys::isLittleEndianHost()) {
+    st_name  = entry->st_name;
+    st_shndx = entry->st_shndx;
+  }
+  else {
+    st_name  = bswap32(entry->st_name);
+    st_shndx = bswap16(entry->st_shndx);
+  }
+
+  MemoryRegion* strtab_region = pInput.memArea()->request(
+                       pInput.fileOffset() + strtab->offset(), strtab->size());
+
+  // get ld_name
+  llvm::StringRef ld_name(
+                    reinterpret_cast<char*>(strtab_region->start() + st_name));
+
+  ResolveInfo* result = ResolveInfo::Create(ld_name);
+  result->setSource(pInput.type() == Input::DynObj);
+  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
+  result->setDesc(getSymDesc(st_shndx, pInput));
+  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
+  result->setVisibility(getSymVisibility(st_other));
+
+  // release regions
+  pInput.memArea()->release(symbol_region);
+  pInput.memArea()->release(strtab_region);
+
+  return result;
+}
+
+/// readDynamic - read ELF .dynamic in input dynobj
+bool ELFReader<32, true>::readDynamic(Input& pInput) const
+{
+  assert(pInput.type() == Input::DynObj);
+  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
+  if (NULL == dynamic_sect) {
+    fatal(diag::err_cannot_read_section) << ".dynamic";
+  }
+  const LDSection* dynstr_sect = dynamic_sect->getLink();
+  if (NULL == dynstr_sect) {
+    fatal(diag::err_cannot_read_section) << ".dynstr";
+  }
+
+  MemoryRegion* dynamic_region = pInput.memArea()->request(
+           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
+
+  MemoryRegion* dynstr_region = pInput.memArea()->request(
+             pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
+
+  assert(NULL != dynamic_region && NULL != dynstr_region);
+
+  const llvm::ELF::Elf32_Dyn* dynamic =
+    (llvm::ELF::Elf32_Dyn*) dynamic_region->start();
+  const char* dynstr = (const char*) dynstr_region->start();
+  bool hasSOName = false;
+  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
+
+  for (size_t idx = 0; idx < numOfEntries; ++idx) {
+
+    llvm::ELF::Elf32_Sword d_tag = 0x0;
+    llvm::ELF::Elf32_Word d_val = 0x0;
+
+    if (llvm::sys::isLittleEndianHost()) {
+      d_tag = dynamic[idx].d_tag;
+      d_val = dynamic[idx].d_un.d_val;
+    } else {
+      d_tag = bswap32(dynamic[idx].d_tag);
+      d_val = bswap32(dynamic[idx].d_un.d_val);
+    }
+
+    switch (d_tag) {
+      case llvm::ELF::DT_SONAME:
+        assert(d_val < dynstr_sect->size());
+        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
+        hasSOName = true;
+        break;
+      case llvm::ELF::DT_NEEDED:
+        // TODO:
+        break;
+      case llvm::ELF::DT_NULL:
+      default:
+        break;
+    }
+  }
+
+  // if there is no SONAME in .dynamic, then set it from input path
+  if (!hasSOName)
+    pInput.setName(pInput.path().filename().native());
+
+  pInput.memArea()->release(dynamic_region);
+  pInput.memArea()->release(dynstr_region);
+  return true;
+}
+
diff --git a/lib/LD/ELFSegment.cpp b/lib/LD/ELFSegment.cpp
index dbefbc5..ae328ca 100644
--- a/lib/LD/ELFSegment.cpp
+++ b/lib/LD/ELFSegment.cpp
@@ -35,3 +35,33 @@
 ELFSegment::~ELFSegment()
 {
 }
+
+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;
+}
+
+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;
+  }
+  return result;
+}
+
diff --git a/lib/LD/ELFWriter.cpp b/lib/LD/ELFWriter.cpp
index bf3152a..93fc4b9 100644
--- a/lib/LD/ELFWriter.cpp
+++ b/lib/LD/ELFWriter.cpp
@@ -13,146 +13,152 @@
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Casting.h>
 
+#include <mcld/LinkerConfig.h>
+#include <mcld/Module.h>
 #include <mcld/ADT/SizeTraits.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/RegionFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Fragment/AlignFragment.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/Fragment/NullFragment.h>
 #include <mcld/LD/ELFWriter.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/LDSection.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/LD/SectionData.h>
 #include <mcld/LD/ELFSegment.h>
 #include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/EhFrame.h>
 #include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MemoryRegion.h>
 
 using namespace llvm::ELF;
 using namespace mcld;
 
 /// writeELF32Header - write ELF header
-void ELFWriter::writeELF32Header(const MCLDInfo& pLDInfo,
-                                 const Layout& pLayout,
-                                 const GNULDBackend& pBackend,
-                                 Output& pOutput) const
+void ELFWriter::writeELF32Header(const LinkerConfig& pConfig,
+                                 const Module& pModule,
+                                 MemoryArea& pOutput) const
 {
-    assert(pOutput.hasMemArea());
+  // ELF header must start from 0x0
+  MemoryRegion *region = pOutput.request(0, sizeof(Elf32_Ehdr));
+  Elf32_Ehdr* header = (Elf32_Ehdr*)region->start();
 
-    // ELF header must start from 0x0
-    MemoryRegion *region = pOutput.memArea()->request(0,
-                                                      sizeof(Elf32_Ehdr));
-    Elf32_Ehdr* header = (Elf32_Ehdr*)region->start();
+  memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
 
-    memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
-
-    header->e_ident[EI_CLASS]      = ELFCLASS32;
-    header->e_ident[EI_DATA]       = pBackend.isLittleEndian()?
+  header->e_ident[EI_CLASS]      = ELFCLASS32;
+  header->e_ident[EI_DATA]       = target().isLittleEndian()?
                                        ELFDATA2LSB : ELFDATA2MSB;
-    header->e_ident[EI_VERSION]    = pBackend.ELFVersion();
-    header->e_ident[EI_OSABI]      = pBackend.OSABI();
-    header->e_ident[EI_ABIVERSION] = pBackend.ABIVersion();
+  header->e_ident[EI_VERSION]    = target().ELFVersion();
+  header->e_ident[EI_OSABI]      = target().OSABI();
+  header->e_ident[EI_ABIVERSION] = target().ABIVersion();
 
-    // FIXME: add processor-specific and core file types.
-    switch(pOutput.type()) {
-    case Output::Object:
+  // FIXME: add processor-specific and core file types.
+  switch(pConfig.codeGenType()) {
+    case LinkerConfig::Object:
       header->e_type = ET_REL;
       break;
-    case Output::DynObj:
+    case LinkerConfig::DynObj:
       header->e_type = ET_DYN;
       break;
-    case Output::Exec:
+    case LinkerConfig::Exec:
       header->e_type = ET_EXEC;
       break;
     default:
-      llvm::errs() << "unspported output file type: " << pOutput.type() << ".\n";
+      llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
       header->e_type = ET_NONE;
-    }
-    header->e_machine   = pBackend.machine();
-    header->e_version   = header->e_ident[EI_VERSION];
-    header->e_entry     = getEntryPoint(pLDInfo, pLayout, pBackend, pOutput);
-    header->e_phoff     = sizeof(Elf32_Ehdr);
-    header->e_shoff     = getELF32LastStartOffset(pOutput);
-    header->e_flags     = pBackend.flags();
-    header->e_ehsize    = sizeof(Elf32_Ehdr);
-    header->e_phentsize = sizeof(Elf32_Phdr);
-    header->e_phnum     = pBackend.numOfSegments();
-    header->e_shentsize = sizeof(Elf32_Shdr);
-    header->e_shnum     = pOutput.context()->numOfSections();
-    header->e_shstrndx  = pOutput.context()->getSectionIdx(".shstrtab");
+  }
+  header->e_machine   = target().machine();
+  header->e_version   = header->e_ident[EI_VERSION];
+  header->e_entry     = getEntryPoint(pConfig, pModule);
+
+  if (LinkerConfig::Object != pConfig.codeGenType())
+    header->e_phoff   = sizeof(Elf32_Ehdr);
+  else
+    header->e_phoff   = 0x0;
+
+  header->e_shoff     = getELF32LastStartOffset(pModule);
+  header->e_flags     = target().flags();
+  header->e_ehsize    = sizeof(Elf32_Ehdr);
+  header->e_phentsize = sizeof(Elf32_Phdr);
+  header->e_phnum     = target().numOfSegments();
+  header->e_shentsize = sizeof(Elf32_Shdr);
+  header->e_shnum     = pModule.size();
+  header->e_shstrndx  = pModule.getSection(".shstrtab")->index();
 }
 
 /// writeELF64Header - write ELF header
-void ELFWriter::writeELF64Header(const MCLDInfo& pLDInfo,
-                                 const Layout& pLayout,
-                                 const GNULDBackend& pBackend,
-                                 Output& pOutput) const
+void ELFWriter::writeELF64Header(const LinkerConfig& pConfig,
+                                 const Module& pModule,
+                                 MemoryArea& pOutput) const
 {
-    assert(pOutput.hasMemArea());
+  // ELF header must start from 0x0
+  MemoryRegion *region = pOutput.request(0, sizeof(Elf64_Ehdr));
+  Elf64_Ehdr* header = (Elf64_Ehdr*)region->start();
 
-    // ELF header must start from 0x0
-    MemoryRegion *region = pOutput.memArea()->request(0,
-                                                      sizeof(Elf64_Ehdr));
-    Elf64_Ehdr* header = (Elf64_Ehdr*)region->start();
+  memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
 
-    memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
-
-    header->e_ident[EI_CLASS]      = ELFCLASS64;
-    header->e_ident[EI_DATA]       = pBackend.isLittleEndian()?
+  header->e_ident[EI_CLASS]      = ELFCLASS64;
+  header->e_ident[EI_DATA]       = target().isLittleEndian()?
                                        ELFDATA2LSB : ELFDATA2MSB;
-    header->e_ident[EI_VERSION]    = pBackend.ELFVersion();
-    header->e_ident[EI_OSABI]      = pBackend.OSABI();
-    header->e_ident[EI_ABIVERSION] = pBackend.ABIVersion();
+  header->e_ident[EI_VERSION]    = target().ELFVersion();
+  header->e_ident[EI_OSABI]      = target().OSABI();
+  header->e_ident[EI_ABIVERSION] = target().ABIVersion();
 
-    // FIXME: add processor-specific and core file types.
-    switch(pOutput.type()) {
-    case Output::Object:
+  // FIXME: add processor-specific and core file types.
+  switch(pConfig.codeGenType()) {
+    case LinkerConfig::Object:
       header->e_type = ET_REL;
       break;
-    case Output::DynObj:
+    case LinkerConfig::DynObj:
       header->e_type = ET_DYN;
       break;
-    case Output::Exec:
+    case LinkerConfig::Exec:
       header->e_type = ET_EXEC;
       break;
     default:
-      llvm::errs() << "unspported output file type: " << pOutput.type() << ".\n";
+      llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
       header->e_type = ET_NONE;
-    }
-    header->e_machine   = pBackend.machine();
-    header->e_version   = header->e_ident[EI_VERSION];
-    header->e_entry     = getEntryPoint(pLDInfo, pLayout, pBackend, pOutput);
-    header->e_phoff     = sizeof(Elf64_Ehdr);
-    header->e_shoff     = getELF64LastStartOffset(pOutput);
-    header->e_flags     = pBackend.flags();
-    header->e_ehsize    = sizeof(Elf64_Ehdr);
-    header->e_phentsize = sizeof(Elf64_Phdr);
-    header->e_phnum     = pBackend.numOfSegments();
-    header->e_shentsize = sizeof(Elf64_Shdr);
-    header->e_shnum     = pOutput.context()->numOfSections();
-    header->e_shstrndx  = pOutput.context()->getSectionIdx(".shstrtab");
+  }
+  header->e_machine   = target().machine();
+  header->e_version   = header->e_ident[EI_VERSION];
+  header->e_entry     = getEntryPoint(pConfig, pModule);
+
+  if (LinkerConfig::Object != pConfig.codeGenType())
+    header->e_phoff   = sizeof(Elf64_Ehdr);
+  else
+    header->e_phoff   = 0x0;
+
+  header->e_shoff     = getELF64LastStartOffset(pModule);
+  header->e_flags     = target().flags();
+  header->e_ehsize    = sizeof(Elf64_Ehdr);
+  header->e_phentsize = sizeof(Elf64_Phdr);
+  header->e_phnum     = target().numOfSegments();
+  header->e_shentsize = sizeof(Elf64_Shdr);
+  header->e_shnum     = pModule.size();
+  header->e_shstrndx  = pModule.getSection(".shstrtab")->index();
 }
 
 /// getEntryPoint
-uint64_t ELFWriter::getEntryPoint(const MCLDInfo& pLDInfo,
-                                  const Layout& pLayout,
-                                  const GNULDBackend& pBackend,
-                                  const Output& pOutput) const
+uint64_t ELFWriter::getEntryPoint(const LinkerConfig& pConfig,
+                                  const Module& pModule) const
 {
 
   llvm::StringRef entry_name;
-  if (pLDInfo.options().hasEntry())
-    entry_name = pLDInfo.options().entry();
+  if (pConfig.options().hasEntry())
+    entry_name = pConfig.options().entry();
   else
-    entry_name = pBackend.entry();
-  
+    entry_name = target().entry();
+
   uint64_t result = 0x0;
 
-  bool issue_warning = (pLDInfo.options().hasEntry()
-                       && (pOutput.type() != Output::Object)
-                       && (pOutput.type() != Output::DynObj));
+  bool issue_warning = (pConfig.options().hasEntry() &&
+                        LinkerConfig::Object != pConfig.codeGenType() &&
+                        LinkerConfig::DynObj != pConfig.codeGenType());
 
-  const LDSymbol* entry_symbol = pLDInfo.getNamePool().findSymbol(entry_name);
+  const LDSymbol* entry_symbol = pModule.getNamePool().findSymbol(entry_name);
 
   // found the symbol
   if (NULL != entry_symbol) {
@@ -183,21 +189,21 @@
 
 /// emitELF32SectionHeader - emit Elf32_Shdr
 void
-ELFWriter::emitELF32SectionHeader(Output& pOutput, MCLinker& pLinker) const
+ELFWriter::emitELF32SectionHeader(const Module& pModule,
+                                  const LinkerConfig& pConfig,
+                                  MemoryArea& pOutput) const
 {
   // emit section header
-  unsigned int sectNum = pOutput.context()->numOfSections();
+  unsigned int sectNum = pModule.size();
   unsigned int header_size = sizeof(Elf32_Shdr) * sectNum;
-  MemoryRegion* region = pOutput.memArea()->request(
-                                   getELF32LastStartOffset(pOutput),
-                                   header_size);
+  MemoryRegion* region = pOutput.request(getELF32LastStartOffset(pModule), header_size);
   Elf32_Shdr* shdr = (Elf32_Shdr*)region->start();
 
   // Iterate the SectionTable in LDContext
   unsigned int sectIdx = 0;
   unsigned int shstridx = 0; // NULL section has empty name
   for (; sectIdx < sectNum; ++sectIdx) {
-    const LDSection *ld_sect = pOutput.context()->getSection(sectIdx);
+    const LDSection *ld_sect   = pModule.getSectionTable().at(sectIdx);
     shdr[sectIdx].sh_name      = shstridx;
     shdr[sectIdx].sh_type      = ld_sect->type();
     shdr[sectIdx].sh_flags     = ld_sect->flag();
@@ -206,8 +212,8 @@
     shdr[sectIdx].sh_size      = ld_sect->size();
     shdr[sectIdx].sh_addralign = ld_sect->align();
     shdr[sectIdx].sh_entsize   = getELF32SectEntrySize(*ld_sect);
-    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pOutput);
-    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect, pOutput);
+    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pConfig);
+    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect);
 
     // adjust strshidx
     shstridx += ld_sect->name().size() + 1;
@@ -216,34 +222,32 @@
 
 /// emitELF64SectionHeader - emit Elf64_Shdr
 void
-ELFWriter::emitELF64SectionHeader(Output& pOutput, MCLinker& pLinker) const
+ELFWriter::emitELF64SectionHeader(const Module& pModule,
+                                  const LinkerConfig& pConfig,
+                                  MemoryArea& pOutput) const
 {
   // emit section header
-  unsigned int sectNum = pOutput.context()->numOfSections();
+  unsigned int sectNum = pModule.size();
   unsigned int header_size = sizeof(Elf64_Shdr) * sectNum;
-  MemoryRegion* region = pOutput.memArea()->request(
-                                     getELF64LastStartOffset(pOutput),
-                                     header_size);
+  MemoryRegion* region = pOutput.request(getELF64LastStartOffset(pModule),
+                                         header_size);
   Elf64_Shdr* shdr = (Elf64_Shdr*)region->start();
 
   // Iterate the SectionTable in LDContext
   unsigned int sectIdx = 0;
   unsigned int shstridx = 0; // NULL section has empty name
   for (; sectIdx < sectNum; ++sectIdx) {
-    const LDSection *ld_sect = pOutput.context()->getSection(sectIdx);
+    const LDSection *ld_sect   = pModule.getSectionTable().at(sectIdx);
     shdr[sectIdx].sh_name      = shstridx;
     shdr[sectIdx].sh_type      = ld_sect->type();
     shdr[sectIdx].sh_flags     = ld_sect->flag();
     shdr[sectIdx].sh_addr      = ld_sect->addr();
     shdr[sectIdx].sh_offset    = ld_sect->offset();
     shdr[sectIdx].sh_size      = ld_sect->size();
-    shdr[sectIdx].sh_addralign = (ld_sect->hasSectionData())?
-                                   ld_sect->getSectionData()->getAlignment():
-                                   0x0;
-
+    shdr[sectIdx].sh_addralign = ld_sect->align();
     shdr[sectIdx].sh_entsize   = getELF64SectEntrySize(*ld_sect);
-    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pOutput);
-    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect, pOutput);
+    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pConfig);
+    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect);
 
     // adjust strshidx
     shstridx += ld_sect->name().size() + 1;
@@ -252,25 +256,22 @@
 
 
 /// emitELF32ProgramHeader - emit Elf32_Phdr
-void ELFWriter::emitELF32ProgramHeader(Output& pOutput,
-                                       const GNULDBackend& pBackend) const
+void ELFWriter::emitELF32ProgramHeader(MemoryArea& pOutput) const
 {
-  assert(pOutput.hasMemArea());
-
   uint64_t start_offset, phdr_size;
 
   start_offset = sizeof(Elf32_Ehdr);
   phdr_size = sizeof(Elf32_Phdr);
   // Program header must start directly after ELF header
-  MemoryRegion *region = pOutput.memArea()->request(start_offset,
-                                          pBackend.numOfSegments() * phdr_size);
+  MemoryRegion *region = pOutput.request(start_offset,
+                                         target().numOfSegments() * phdr_size);
 
   Elf32_Phdr* phdr = (Elf32_Phdr*)region->start();
 
   // Iterate the elf segment table in GNULDBackend
   size_t index = 0;
-  ELFSegmentFactory::const_iterator seg = pBackend.elfSegmentTable().begin(),
-                                 segEnd = pBackend.elfSegmentTable().end();
+  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();
@@ -284,24 +285,21 @@
 }
 
 /// emitELF64ProgramHeader - emit ElfR64Phdr
-void ELFWriter::emitELF64ProgramHeader(Output& pOutput,
-                                       const GNULDBackend& pBackend) const
+void ELFWriter::emitELF64ProgramHeader(MemoryArea& pOutput) const
 {
-  assert(pOutput.hasMemArea());
-
   uint64_t start_offset, phdr_size;
 
   start_offset = sizeof(Elf64_Ehdr);
   phdr_size = sizeof(Elf64_Phdr);
   // Program header must start directly after ELF header
-  MemoryRegion *region = pOutput.memArea()->request(start_offset,
-                                          pBackend.numOfSegments() * phdr_size);
+  MemoryRegion *region = pOutput.request(start_offset,
+                                         target().numOfSegments() * phdr_size);
   Elf64_Phdr* phdr = (Elf64_Phdr*)region->start();
 
   // Iterate the elf segment table in GNULDBackend
   size_t index = 0;
-  ELFSegmentFactory::const_iterator seg = pBackend.elfSegmentTable().begin(),
-                                 segEnd = pBackend.elfSegmentTable().end();
+  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();
@@ -314,174 +312,61 @@
   }
 }
 
-/// emitELF32ShStrTab - emit section string table
-void ELFWriter::emitELF32ShStrTab(Output& pOutput, MCLinker& pLinker) const
+/// emitELFShStrTab - emit section string table
+void
+ELFWriter::emitELFShStrTab(const LDSection& pShStrTab, const Module& pModule,
+                           MemoryArea& pOutput)
 {
-  uint64_t shstroffset = getELF32LastStartOffset(pOutput);
-
-  // get shstrtab
-  LDSection& shstrtab = pLinker.getOrCreateOutputSectHdr(".shstrtab",
-                                                         LDFileFormat::NamePool,
-                                                         SHT_STRTAB,
-                                                         0x0);
-  if (0 != shstrtab.size())
-    llvm::report_fatal_error(".shstrtab has been set.\n");
-
-  // compute size
-  unsigned int shstrsize = 0;
-  LDContext::const_sect_iterator section, sectEnd = pOutput.context()->sectEnd();
-  for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
-    shstrsize += (*section)->name().size() + 1;
-  }
-
-  shstrtab.setSize(shstrsize);
-  shstrtab.setOffset(shstroffset);
-
   // write out data
-  MemoryRegion* region = pOutput.memArea()->request(shstrtab.offset(),
-                                                    shstrtab.size());
+  MemoryRegion* region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
   unsigned char* data = region->start();
-  shstrsize = 0;
-  for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
-    strcpy((char*)(data + shstrsize), (*section)->name().c_str());
+  size_t shstrsize = 0;
+  Module::const_iterator section, sectEnd = pModule.end();
+  for (section = pModule.begin(); section != sectEnd; ++section) {
+    strcpy((char*)(data + shstrsize), (*section)->name().data());
     shstrsize += (*section)->name().size() + 1;
   }
-
-  shstrtab.setKind(LDFileFormat::NamePool);
-  shstrtab.setType(llvm::ELF::SHT_STRTAB);
-  shstrtab.setFlag(0x0);
-  shstrtab.setAddr(0x0);
-}
-
-
-/// emitELF64ShStrTab - emit section string table
-void ELFWriter::emitELF64ShStrTab(Output& pOutput, MCLinker& pLinker) const
-{
-  uint64_t shstroffset = getELF64LastStartOffset(pOutput);
-
-  // get shstrtab
-  LDSection& shstrtab = pLinker.getOrCreateOutputSectHdr(".shstrtab",
-                                                         LDFileFormat::NamePool,
-                                                         SHT_STRTAB,
-                                                         0x0);
-  if (0 != shstrtab.size())
-    llvm::report_fatal_error(".shstrtab has been set.\n");
-
-  // compute offset
-
-  // compute size
-  unsigned int shstrsize = 0;
-  LDContext::const_sect_iterator section, sectEnd = pOutput.context()->sectEnd();
-  for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
-    shstrsize += (*section)->name().size() + 1;
-  }
-
-  shstrtab.setSize(shstrsize);
-  shstrtab.setOffset(shstroffset);
-
-  // write out data
-  MemoryRegion* region = pOutput.memArea()->request(shstrtab.offset(),
-                                                    shstrtab.size());
-  unsigned char* data = region->start();
-  shstrsize = 0;
-  for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
-    strcpy((char*)(data + shstrsize), (*section)->name().c_str());
-    shstrsize += (*section)->name().size() + 1;
-  }
-
-  shstrtab.setKind(LDFileFormat::NamePool);
-  shstrtab.setType(llvm::ELF::SHT_STRTAB);
-  shstrtab.setFlag(0x0);
-  shstrtab.setAddr(0x0);
 }
 
 /// emitSectionData
 void
-ELFWriter::emitSectionData(const Layout& pLayout,
-                           const LDSection& pSection,
+ELFWriter::emitSectionData(const LDSection& pSection,
                            MemoryRegion& pRegion) const
 {
-  const SectionData* data = pSection.getSectionData();
-  SectionData::const_iterator fragIter, fragEnd = data->end();
-  size_t cur_offset = 0;
-  for (fragIter = data->begin(); fragIter != fragEnd; ++fragIter) {
-    size_t size = computeFragmentSize(pLayout, *fragIter);
-    switch(fragIter->getKind()) {
-      case Fragment::Region: {
-        const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
-        const uint8_t* from = region_frag.getRegion().start();
-        memcpy(pRegion.getBuffer(cur_offset), from, size);
-        break;
-      }
-      case Fragment::Alignment: {
-        // TODO: emit values with different sizes (> 1 byte), and emit nops
-        AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
-        uint64_t count = size / align_frag.getValueSize();
-        switch (align_frag.getValueSize()) {
-          case 1u:
-            std::memset(pRegion.getBuffer(cur_offset),
-                        align_frag.getValue(),
-                        count);
-            break;
-          default:
-            llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
-            break;
-        }
-        break;
-      }
-      case Fragment::Fillment: {
-        FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
-        if (0 == size ||
-            0 == fill_frag.getValueSize() ||
-            0 == fill_frag.getSize()) {
-          // ignore virtual fillment
-          break;
-        }
-
-        uint64_t num_tiles = fill_frag.getSize() / fill_frag.getValueSize();
-        for (uint64_t i = 0; i != num_tiles; ++i) {
-          std::memset(pRegion.getBuffer(cur_offset),
-                      fill_frag.getValue(),
-                      fill_frag.getValueSize());
-        }
-        break;
-      }
-      case Fragment::Relocation:
-        llvm::report_fatal_error("relocation fragment should not be in a regular section.\n");
-        break;
-      case Fragment::Target:
-        llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
-        break;
-      default:
-        llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
-        break;
-    }
-    cur_offset += size;
+  const SectionData* sd = NULL;
+  switch (pSection.kind()) {
+    case LDFileFormat::Relocation:
+      return;
+    case LDFileFormat::EhFrame:
+      sd = &pSection.getEhFrame()->getSectionData();
+      break;
+    default:
+      sd = pSection.getSectionData();
+      break;
   }
+  emitSectionData(*sd, pRegion);
 }
 
 /// emitRelocation
-void ELFWriter::emitRelocation(const Layout& pLayout,
-                               const Output& pOutput,
+void ELFWriter::emitRelocation(const LinkerConfig& pConfig,
                                const LDSection& pSection,
                                MemoryRegion& pRegion) const
 {
-  const SectionData* sect_data = pSection.getSectionData();
+  const RelocData* sect_data = pSection.getRelocData();
   assert(NULL != sect_data && "SectionData is NULL in emitRelocation!");
 
   if (pSection.type() == SHT_REL)
-    emitRel(pLayout, pOutput, *sect_data, pRegion);
+    emitRel(pConfig, *sect_data, pRegion);
   else if (pSection.type() == SHT_RELA)
-    emitRela(pLayout, pOutput, *sect_data, pRegion);
+    emitRela(pConfig, *sect_data, pRegion);
   else
     llvm::report_fatal_error("unsupported relocation section type!");
 }
 
 
 /// emitRel
-void ELFWriter::emitRel(const Layout& pLayout,
-                        const Output& pOutput,
-                        const SectionData& pSectionData,
+void ELFWriter::emitRel(const LinkerConfig& pConfig,
+                        const RelocData& pRelocData,
                         MemoryRegion& pRegion) const
 {
   Elf32_Rel* rel = reinterpret_cast<Elf32_Rel*>(pRegion.start());
@@ -489,23 +374,21 @@
   Relocation* relocation = 0;
   FragmentRef* frag_ref = 0;
 
-  for (SectionData::const_iterator it = pSectionData.begin(),
-       ie = pSectionData.end(); it != ie; ++it, ++rel) {
+  for (RelocData::const_iterator it = pRelocData.begin(),
+       ie = pRelocData.end(); it != ie; ++it, ++rel) {
 
     relocation = &(llvm::cast<Relocation>(*it));
     frag_ref = &(relocation->targetRef());
 
-    if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) {
+    if(LinkerConfig::DynObj == pConfig.codeGenType() ||
+       LinkerConfig::Exec == pConfig.codeGenType()) {
       rel->r_offset = static_cast<Elf32_Addr>(
                       frag_ref->frag()->getParent()->getSection().addr() +
-                      pLayout.getOutputOffset(*frag_ref));
+                      frag_ref->getOutputOffset());
     }
     else {
-      rel->r_offset = static_cast<Elf32_Addr>(
-                      frag_ref->frag()->getParent()->getSection().offset() +
-                      pLayout.getOutputOffset(*frag_ref));
+      rel->r_offset = static_cast<Elf32_Addr>(frag_ref->getOutputOffset());
     }
-
     Elf32_Word Index;
     if( relocation->symInfo() == NULL )
       Index = 0;
@@ -518,9 +401,8 @@
 }
 
 /// emitRela
-void ELFWriter::emitRela(const Layout& pLayout,
-                         const Output& pOutput,
-                         const SectionData& pSectionData,
+void ELFWriter::emitRela(const LinkerConfig& pConfig,
+                         const RelocData& pRelocData,
                          MemoryRegion& pRegion) const
 {
   Elf32_Rela* rel = reinterpret_cast<Elf32_Rela*>(pRegion.start());
@@ -528,21 +410,20 @@
   Relocation* relocation = 0;
   FragmentRef* frag_ref = 0;
 
-  for (SectionData::const_iterator it = pSectionData.begin(),
-       ie = pSectionData.end(); it != ie; ++it, ++rel) {
+  for (RelocData::const_iterator it = pRelocData.begin(),
+       ie = pRelocData.end(); it != ie; ++it, ++rel) {
 
     relocation = &(llvm::cast<Relocation>(*it));
     frag_ref = &(relocation->targetRef());
 
-    if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) {
+    if(LinkerConfig::DynObj == pConfig.codeGenType() ||
+       LinkerConfig::Exec == pConfig.codeGenType()) {
       rel->r_offset = static_cast<Elf32_Addr>(
                       frag_ref->frag()->getParent()->getSection().addr() +
-                      pLayout.getOutputOffset(*frag_ref));
+                      frag_ref->getOutputOffset());
     }
     else {
-      rel->r_offset = static_cast<Elf32_Addr>(
-                      frag_ref->frag()->getParent()->getSection().offset() +
-                      pLayout.getOutputOffset(*frag_ref));
+      rel->r_offset = static_cast<Elf32_Addr>(frag_ref->getOutputOffset());
     }
 
     Elf32_Word Index;
@@ -592,29 +473,32 @@
 }
 
 /// getSectLink - compute ElfXX_Shdr::sh_link
-uint64_t ELFWriter::getSectLink(const LDSection& pSection, const Output& pOutput) const
+uint64_t ELFWriter::getSectLink(const LDSection& pSection,
+                                const LinkerConfig& pConfig) const
 {
-  const LDContext* context = pOutput.context();
   if (llvm::ELF::SHT_SYMTAB == pSection.type())
-    return context->getSectionIdx(".strtab");
+    return target().getOutputFormat()->getStrTab().index();
   if (llvm::ELF::SHT_DYNSYM == pSection.type())
-    return context->getSectionIdx(".dynstr");
+    return target().getOutputFormat()->getDynStrTab().index();
   if (llvm::ELF::SHT_DYNAMIC == pSection.type())
-    return context->getSectionIdx(".dynstr");
+    return target().getOutputFormat()->getDynStrTab().index();
   if (llvm::ELF::SHT_HASH == pSection.type())
-    return context->getSectionIdx(".dynsym");
+    return target().getOutputFormat()->getDynSymTab().index();
   if (llvm::ELF::SHT_REL == pSection.type() ||
       llvm::ELF::SHT_RELA == pSection.type()) {
-    if (pOutput.type() == Output::Object)
-      return context->getSectionIdx(".symtab");
+    if (LinkerConfig::Object == pConfig.codeGenType())
+      return target().getOutputFormat()->getSymTab().index();
     else
-      return context->getSectionIdx(".dynsym");
+      return target().getOutputFormat()->getDynSymTab().index();
   }
+  // FIXME: currently we link ARM_EXIDX section to output text section here
+  if (llvm::ELF::SHT_ARM_EXIDX == pSection.type())
+    return target().getOutputFormat()->getText().index();
   return llvm::ELF::SHN_UNDEF;
 }
 
 /// getSectInfo - compute ElfXX_Shdr::sh_info
-uint64_t ELFWriter::getSectInfo(const LDSection& pSection, const Output& pOutput) const
+uint64_t ELFWriter::getSectInfo(const LDSection& pSection) const
 {
   const LDSection* info_link = pSection.getLink();
   if (NULL == info_link)
@@ -623,18 +507,89 @@
 }
 
 /// getELF32LastStartOffset
-uint64_t ELFWriter::getELF32LastStartOffset(const Output& pOutput) const
+uint64_t ELFWriter::getELF32LastStartOffset(const Module& pModule) const
 {
-  LDSection* lastSect = pOutput.context()->getSectionTable().back();
+  const LDSection* lastSect = pModule.back();
   assert(lastSect != NULL);
   return Align<32>(lastSect->offset() + lastSect->size());
 }
 
 /// getELF64LastStartOffset
-uint64_t ELFWriter::getELF64LastStartOffset(const Output& pOutput) const
+uint64_t ELFWriter::getELF64LastStartOffset(const Module& pModule) const
 {
-  LDSection* lastSect = pOutput.context()->getSectionTable().back();
+  const LDSection* lastSect = pModule.back();
   assert(lastSect != NULL);
   return Align<64>(lastSect->offset() + lastSect->size());
 }
 
+/// emitSectionData
+void
+ELFWriter::emitSectionData(const SectionData& pSD, MemoryRegion& pRegion) const
+{
+  SectionData::const_iterator fragIter, fragEnd = pSD.end();
+  size_t cur_offset = 0;
+  for (fragIter = pSD.begin(); fragIter != fragEnd; ++fragIter) {
+    size_t size = fragIter->size();
+    switch(fragIter->getKind()) {
+      case Fragment::Region: {
+        const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
+        const uint8_t* from = region_frag.getRegion().start();
+        memcpy(pRegion.getBuffer(cur_offset), from, size);
+        break;
+      }
+      case Fragment::Alignment: {
+        // TODO: emit values with different sizes (> 1 byte), and emit nops
+        AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
+        uint64_t count = size / align_frag.getValueSize();
+        switch (align_frag.getValueSize()) {
+          case 1u:
+            std::memset(pRegion.getBuffer(cur_offset),
+                        align_frag.getValue(),
+                        count);
+            break;
+          default:
+            llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
+            break;
+        }
+        break;
+      }
+      case Fragment::Fillment: {
+        FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
+        if (0 == size ||
+            0 == fill_frag.getValueSize() ||
+            0 == fill_frag.size()) {
+          // ignore virtual fillment
+          break;
+        }
+
+        uint64_t num_tiles = fill_frag.size() / fill_frag.getValueSize();
+        for (uint64_t i = 0; i != num_tiles; ++i) {
+          std::memset(pRegion.getBuffer(cur_offset),
+                      fill_frag.getValue(),
+                      fill_frag.getValueSize());
+        }
+        break;
+      }
+      case Fragment::Stub: {
+        Stub& stub_frag = llvm::cast<Stub>(*fragIter);
+        memcpy(pRegion.getBuffer(cur_offset), stub_frag.getContent(), size);
+        break;
+      }
+      case Fragment::Null: {
+        assert(0x0 == size);
+        break;
+      }
+      case Fragment::Relocation:
+        llvm::report_fatal_error("relocation fragment should not be in a regular section.\n");
+        break;
+      case Fragment::Target:
+        llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
+        break;
+      default:
+        llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
+        break;
+    }
+    cur_offset += size;
+  }
+}
+
diff --git a/lib/LD/EhFrame.cpp b/lib/LD/EhFrame.cpp
index bc5ed1d..df61c24 100644
--- a/lib/LD/EhFrame.cpp
+++ b/lib/LD/EhFrame.cpp
@@ -6,353 +6,83 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include <mcld/LD/EhFrame.h>
-
-#include <llvm/Support/Dwarf.h>
-#include <llvm/Support/Host.h>
-
-#include <mcld/MC/MCLinker.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Support/MsgHandling.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Object/ObjectBuilder.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
+// EhFrame::CIE
+//===----------------------------------------------------------------------===//
+EhFrame::CIE::CIE(MemoryRegion& pRegion)
+  : RegionFragment(pRegion) {
+}
+
+//===----------------------------------------------------------------------===//
+// EhFrame::FDE
+//===----------------------------------------------------------------------===//
+EhFrame::FDE::FDE(MemoryRegion& pRegion,
+                  const EhFrame::CIE& pCIE,
+                  uint32_t pDataStart)
+  : RegionFragment(pRegion),
+    m_CIE(pCIE),
+    m_DataStart(pDataStart) {
+}
+
+//===----------------------------------------------------------------------===//
 // EhFrame
-EhFrame::EhFrame()
- : m_fCanRecognizeAll(true) {
+//===----------------------------------------------------------------------===//
+EhFrame::EhFrame(LDSection& pSection)
+  : m_Section(pSection),
+    m_pSectionData(NULL) {
+  m_pSectionData = SectionData::Create(pSection);
 }
 
 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.
 }
 
-uint64_t EhFrame::readEhFrame(Layout& pLayout,
-                              const TargetLDBackend& pBackend,
-                              SectionData& pSD,
-                              const Input& pInput,
-                              LDSection& pSection,
-                              MemoryArea& pArea)
+void EhFrame::addFragment(RegionFragment& pFrag)
 {
-  MemoryRegion* region = pArea.request(
-                     pInput.fileOffset() + pSection.offset(), pSection.size());
-  // an empty .eh_frame
-  if (NULL == region) {
-    return 0;
-  }
+  uint32_t offset = 0;
+  if (!m_pSectionData->empty())
+    offset = m_pSectionData->back().getOffset() + m_pSectionData->back().size();
 
-  ConstAddress eh_start = region->start();
-  ConstAddress eh_end = region->end();
-  ConstAddress p = eh_start;
-
-  // read the Length filed
-  uint32_t len = readVal(p, pBackend.isLittleEndian());
-
-  // This CIE is a terminator if the Length field is 0, return 0 to handled it
-  // as an ordinary input.
-  if (0 == len) {
-    pArea.release(region);
-    return 0;
-  }
-
-  if (0xffffffff == len) {
-    debug(diag::debug_eh_unsupport) << pInput.name();
-    pArea.release(region);
-    m_fCanRecognizeAll = false;
-    return 0;
-  }
-
-  // record the order of the CIE and FDE fragments
-  FragListType frag_list;
-
-  while (p < eh_end) {
-
-    if (eh_end - p < 4) {
-      debug(diag::debug_eh_unsupport) << pInput.name();
-      m_fCanRecognizeAll = false;
-      break;
-    }
-    // read the Length field
-    len = readVal(p, pBackend.isLittleEndian());
-    p += 4;
-
-    // the zero length entry should be the end of the section
-    if (0 == len) {
-      if (p < eh_end) {
-        debug(diag::debug_eh_unsupport) << pInput.name();
-        m_fCanRecognizeAll = false;
-      }
-      break;
-    }
-    if (0xffffffff == len) {
-      debug(diag::debug_eh_unsupport) << pInput.name();
-      m_fCanRecognizeAll = false;
-      break;
-    }
-
-    if (eh_end - p < 4) {
-      debug(diag::debug_eh_unsupport) << pInput.name();
-      m_fCanRecognizeAll = false;
-      break;
-    }
-
-    // compute the section offset of this entry
-    uint32_t ent_offset = static_cast<uint32_t>(p - eh_start - 4);
-
-    // get the MemoryRegion for this entry
-    MemoryRegion* ent_region = pArea.request(
-                pInput.fileOffset() + pSection.offset() + ent_offset, len + 4);
-
-    // create and add a CIE or FDE entry
-    uint32_t id = readVal(p, pBackend.isLittleEndian());
-    // CIE
-    if (0 == id) {
-      if (!addCIE(*ent_region, pBackend, frag_list)) {
-        m_fCanRecognizeAll = false;
-        pArea.release(ent_region);
-        break;
-      }
-    }
-
-    // FDE
-    else {
-      if (!addFDE(*ent_region, pBackend, frag_list)) {
-        m_fCanRecognizeAll = false;
-        pArea.release(ent_region);
-        break;
-      }
-    }
-    p += len;
-  }
-
-  if (!m_fCanRecognizeAll) {
-    debug(diag::debug_eh_unsupport) << pInput.name();
-    pArea.release(region);
-    deleteFragments(frag_list, pArea);
-    return 0;
-  }
-
-  // append all CIE and FDE fragments to Layout after we successfully read
-  // this eh_frame
-  size_t section_size = 0;
-  for (FragListType::iterator it = frag_list.begin();
-         it != frag_list.end(); ++it)
-    section_size += pLayout.appendFragment(**it, pSD, pSection.align());
-
-  pArea.release(region);
-  return section_size;
+  m_pSectionData->getFragmentList().push_back(&pFrag);
+  pFrag.setOffset(offset);
 }
 
-bool EhFrame::addCIE(MemoryRegion& pRegion,
-                     const TargetLDBackend& pBackend,
-                     FragListType& pFragList)
+void EhFrame::addCIE(EhFrame::CIE& pCIE)
 {
-  ConstAddress cie_start = pRegion.start();
-  ConstAddress cie_end = pRegion.end();
-  ConstAddress p = cie_start;
-
-  // skip the Length (4 byte) and CIE ID (4 byte) fields
-  p += 8;
-
-  // the version should be 1
-  if (1 != *p) {
-    return false;
-  }
-  ++p;
-
-  // get the Augumentation String
-  ConstAddress aug_str = p;
-  ConstAddress aug_str_end = static_cast<ConstAddress>(
-                               memchr(p, '\0', cie_end - p));
-
-  // skip the Augumentation String field
-  p = aug_str_end + 1;
-
-  // skip the Code Alignment Factor
-  if (!skipLEB128(&p, cie_end)) {
-    return false;
-  }
-  // skip the Data Alignment Factor
-  if (!skipLEB128(&p, cie_end)) {
-    return false;
-  }
-  // skip the Return Address Register
-  if (cie_end - p < 1) {
-    return false;
-  }
-  ++p;
-
-  // the Augmentation String start with 'eh' is a CIE from gcc before 3.0,
-  // in LSB Core Spec 3.0RC1. We do not support it.
-  if (aug_str[0] == 'e' && aug_str[1] == 'h') {
-    return false;
-  }
-
-  // parse the Augmentation String to get the FDE encodeing if 'z' existed
-  std::string aug_str_data;
-  uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr;
-  if (*aug_str == 'z') {
-
-    aug_str_data += *aug_str;
-    ++aug_str;
-
-    // skip the Augumentation Data Length
-    if (!skipLEB128(&p, cie_end)) {
-      return false;
-    }
-
-    while (aug_str != aug_str_end) {
-      switch (*aug_str) {
-        default:
-          return false;
-
-        // LDSA encoding (1 byte)
-        case 'L':
-          if (cie_end - p < 1) {
-            return false;
-          }
-          ++p;
-          break;
-
-        // Two arguments, the first one represents the encoding of the second
-        // argument (1 byte). The second one is the address of personality
-        // routine.
-        case 'P': {
-          // the first argument
-          if (cie_end - p < 1) {
-            return false;
-          }
-          uint8_t per_encode = *p;
-          ++p;
-          // get the length of the second argument
-          uint32_t per_length = 0;
-          if (0x60 == (per_encode & 0x60)) {
-            return false;
-          }
-          switch (per_encode & 7) {
-            default:
-              return false;
-            case llvm::dwarf::DW_EH_PE_udata2:
-              per_length = 2;
-              break;
-            case llvm::dwarf::DW_EH_PE_udata4:
-              per_length = 4;
-              break;
-            case llvm::dwarf::DW_EH_PE_udata8:
-              per_length = 8;
-              break;
-            case llvm::dwarf::DW_EH_PE_absptr:
-              per_length = pBackend.bitclass() / 8;
-              break;
-          }
-          // skip the alignment
-          if (llvm::dwarf::DW_EH_PE_aligned == (per_encode & 0xf0)) {
-            uint32_t per_align = p - cie_end;
-            per_align += per_length - 1;
-            per_align &= ~(per_length -1);
-            if (static_cast<uint32_t>(cie_end - p) < per_align) {
-              return false;
-            }
-            p += per_align;
-          }
-          // skip the second argument
-          if (static_cast<uint32_t>(cie_end - p) < per_length) {
-            return false;
-          }
-          p += per_length;
-        }
-        break;
-
-        // FDE encoding (1 byte)
-        case 'R':
-          if (cie_end - p < 1) {
-            return false;
-          }
-          fde_encoding = *p;
-          switch (fde_encoding & 7) {
-            case llvm::dwarf::DW_EH_PE_udata2:
-            case llvm::dwarf::DW_EH_PE_udata4:
-            case llvm::dwarf::DW_EH_PE_udata8:
-            case llvm::dwarf::DW_EH_PE_absptr:
-              break;
-            default:
-              return false;
-          }
-          ++p;
-          break;
-      } // end switch
-      aug_str_data += *aug_str;
-      ++aug_str;
-    } // end while
-  }
-
-  note(diag::note_eh_cie) << pRegion.size()
-                          << aug_str_data
-                          << (fde_encoding & 7);
-
-  // create and push back the CIE entry
-  CIE* entry = new CIE(pRegion, fde_encoding);
-  m_CIEs.push_back(entry);
-  pFragList.push_back(static_cast<Fragment*>(entry));
-  return true;
+  m_CIEs.push_back(&pCIE);
+  addFragment(pCIE);
 }
 
-bool EhFrame::addFDE(MemoryRegion& pRegion,
-                     const TargetLDBackend& pBackend,
-                     FragListType& pFragList)
+void EhFrame::addFDE(EhFrame::FDE& pFDE)
 {
-  ConstAddress fde_start = pRegion.start();
-  ConstAddress fde_end = pRegion.end();
-  ConstAddress p = fde_start;
-
-  // skip the Length (4 byte) and CIE Pointer (4 byte) fields
-  p += 8;
-
-  // get the entry offset of the PC Begin
-  if (fde_end - p < 1) {
-    return false;
-  }
-  FDE::Offset pc_offset = static_cast<FDE::Offset>(p - fde_start);
-
-  note(diag::note_eh_fde) << pRegion.size() << pc_offset;
-  // create and push back the FDE entry
-  FDE* entry = new FDE(pRegion, **(m_CIEs.end() -1), pc_offset);
-  m_FDEs.push_back(entry);
-  pFragList.push_back(static_cast<Fragment*>(entry));
-  return true;
+  m_FDEs.push_back(&pFDE);
+  addFragment(pFDE);
 }
 
-uint32_t EhFrame::readVal(ConstAddress pAddr, bool pIsTargetLittleEndian)
+EhFrame& EhFrame::merge(EhFrame& pOther)
 {
-  const uint32_t* p = reinterpret_cast<const uint32_t*>(pAddr);
-  uint32_t val = *p;
+  ObjectBuilder::MoveSectionData(pOther.getSectionData(), *m_pSectionData);
 
-  // byte swapping if the host and target have different endian
-  if (llvm::sys::isLittleEndianHost() != pIsTargetLittleEndian)
-    val = bswap32(val);
-  return val;
-}
+  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);
 
-bool EhFrame::skipLEB128(ConstAddress* pp, ConstAddress pend)
-{
-  for (ConstAddress p = *pp; p < pend; ++p) {
-    if (0 == (*p & 0x80)) {
-      *pp = p + 1;
-      return true;
-    }
-  }
-  return false;
-}
+  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);
 
-void EhFrame::deleteFragments(FragListType& pList, MemoryArea& pArea)
-{
-  RegionFragment* frag = NULL;
-  for (FragListType::iterator it = pList.begin(); it != pList.end(); ++it) {
-    frag = static_cast<RegionFragment*>(*it);
-    pArea.release(&(frag->getRegion()));
-    delete *it;
-  }
-  pList.clear();
+  pOther.m_CIEs.clear();
+  pOther.m_FDEs.clear();
+  return *this;
 }
 
diff --git a/lib/LD/EhFrameHdr.cpp b/lib/LD/EhFrameHdr.cpp
index 8806af4..4c0d59c 100644
--- a/lib/LD/EhFrameHdr.cpp
+++ b/lib/LD/EhFrameHdr.cpp
@@ -8,17 +8,118 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/EhFrameHdr.h>
 
-using namespace mcld;
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/LDSection.h>
 
-//==========================
-// EhFrameHdr
-EhFrameHdr::EhFrameHdr(const EhFrame& pEhFrameData,
-                       const LDSection& pEhFrameSect,
-                       LDSection& pEhFrameHdrSect)
-  : m_EhFrameData(pEhFrameData),
-    m_EhFrameSect(pEhFrameSect),
-    m_EhFrameHdrSect(pEhFrameHdrSect)
+#include <llvm/Support/Dwarf.h>
+#include <llvm/Support/DataTypes.h>
+
+#include <algorithm>
+#include <cstring>
+
+using namespace mcld;
+using namespace llvm::dwarf;
+
+//===----------------------------------------------------------------------===//
+// Helper Function
+//===----------------------------------------------------------------------===//
+namespace bit32 {
+
+typedef std::pair<SizeTraits<32>::Address, SizeTraits<32>::Address> Entry;
+
+bool EntryCompare(const Entry& pX, const Entry& pY)
+{ return (pX.first < pY.first); }
+
+} // bit32 namespace
+
+//===----------------------------------------------------------------------===//
+// Template Specification Functions
+//===----------------------------------------------------------------------===//
+/// emitOutput<32> - write out eh_frame_hdr
+template<>
+void EhFrameHdr::emitOutput<32>(MemoryArea& pOutput)
 {
+  MemoryRegion* ehframehdr_region =
+    pOutput.request(m_EhFrameHdr.offset(), m_EhFrameHdr.size());
+
+  MemoryRegion* ehframe_region =
+    pOutput.request(m_EhFrame.offset(),
+                    m_EhFrame.size());
+
+  uint8_t* data = (uint8_t*)ehframehdr_region->start();
+  // version
+  data[0] = 1;
+  // eh_frame_ptr_enc
+  data[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
+
+  // eh_frame_ptr
+  uint32_t* eh_frame_ptr = (uint32_t*)(data + 4);
+  *eh_frame_ptr = m_EhFrame.addr() - (m_EhFrameHdr.addr() + 4);
+
+  // fde_count
+  uint32_t* fde_count = (uint32_t*)(data + 8);
+  if (m_EhFrame.hasEhFrame())
+    *fde_count = 0;
+  else
+    *fde_count = m_EhFrame.getEhFrame()->numOfFDEs();
+
+  if (0 != *fde_count) {
+    // fde_count_enc
+    data[2] = DW_EH_PE_udata4;
+    // table_enc
+    data[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
+
+  }
+  else {
+    // fde_count_enc
+    data[2] = DW_EH_PE_omit;
+    // table_enc
+    data[3] = DW_EH_PE_omit;
+  }
+
+  if (0 != *fde_count) {
+
+    // prepare the binary search table
+    typedef std::vector<bit32::Entry> SearchTableType;
+    SearchTableType search_table;
+    MemoryRegion* ehframe_region =
+      pOutput.request(m_EhFrame.offset(), m_EhFrame.size());
+    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));
+    }
+    pOutput.release(ehframe_region);
+
+    std::sort(search_table.begin(), search_table.end(), bit32::EntryCompare);
+
+    // write out the binary search table
+    uint32_t* bst = (uint32_t*)(data + 12);
+    SearchTableType::const_iterator entry, entry_end = search_table.end();
+    size_t id = 0;
+    for (entry = search_table.begin(); entry != entry_end; ++entry) {
+      bst[id++] = (*entry).first - m_EhFrameHdr.addr();
+      bst[id++] = (*entry).second - m_EhFrameHdr.addr();
+    }
+  }
+  pOutput.release(ehframehdr_region);
+  pOutput.release(ehframe_region);
+}
+
+//===----------------------------------------------------------------------===//
+// EhFrameHdr
+//===----------------------------------------------------------------------===//
+
+EhFrameHdr::EhFrameHdr(LDSection& pEhFrameHdr, const LDSection& pEhFrame)
+  : m_EhFrameHdr(pEhFrameHdr), m_EhFrame(pEhFrame) {
 }
 
 EhFrameHdr::~EhFrameHdr()
@@ -35,15 +136,69 @@
 /// uint32_t : fde_count
 /// __________________________ when fde_count > 0
 /// <uint32_t, uint32_t>+ : binary search table
-
 /// sizeOutput - base on the fde count to size output
 void EhFrameHdr::sizeOutput()
 {
   size_t size = 12;
-  if (m_EhFrameData.canRecognizeAllEhFrame()) {
-    size_t fde_count = m_EhFrameData.getFDECount();
-    size += 8 * fde_count;
-  }
-  m_EhFrameHdrSect.setSize(size);
+  if (m_EhFrame.hasEhFrame())
+    size += 8 * m_EhFrame.getEhFrame()->numOfFDEs();
+  m_EhFrameHdr.setSize(size);
 }
 
+/// computePCBegin - return the address of FDE's pc
+/// @ref binutils gold: ehframe.cc:222
+uint32_t EhFrameHdr::computePCBegin(const EhFrame::FDE& pFDE,
+                                    const MemoryRegion& pEhFrameRegion)
+{
+  uint8_t fde_encoding = pFDE.getCIE().getFDEEncode();
+  unsigned int eh_value = fde_encoding & 0x7;
+
+  // check the size to read in
+  if (eh_value == llvm::dwarf::DW_EH_PE_absptr) {
+    eh_value = DW_EH_PE_udata4;
+  }
+
+  size_t pc_size = 0x0;
+  switch (eh_value) {
+    case DW_EH_PE_udata2:
+      pc_size = 2;
+      break;
+    case DW_EH_PE_udata4:
+      pc_size = 4;
+      break;
+    case DW_EH_PE_udata8:
+      pc_size = 8;
+      break;
+    default:
+      // TODO
+      break;
+  }
+
+  SizeTraits<32>::Address pc = 0x0;
+  const uint8_t* offset = (const uint8_t*) pEhFrameRegion.start() +
+                          pFDE.getOffset() +
+                          pFDE.getDataStart();
+  std::memcpy(&pc, offset, pc_size);
+
+  // adjust the signed value
+  bool is_signed = (fde_encoding & llvm::dwarf::DW_EH_PE_signed) != 0x0;
+  if (DW_EH_PE_udata2 == eh_value && is_signed)
+    pc = (pc ^ 0x8000) - 0x8000;
+
+  // handle eh application
+  switch (fde_encoding & 0x70)
+  {
+    case DW_EH_PE_absptr:
+      break;
+    case DW_EH_PE_pcrel:
+      pc += m_EhFrame.addr() + pFDE.getOffset() + pFDE.getDataStart();
+      break;
+    case DW_EH_PE_datarel:
+      // TODO
+      break;
+    default:
+      // TODO
+      break;
+  }
+  return pc;
+}
diff --git a/lib/LD/EhFrameReader.cpp b/lib/LD/EhFrameReader.cpp
new file mode 100644
index 0000000..efcec5a
--- /dev/null
+++ b/lib/LD/EhFrameReader.cpp
@@ -0,0 +1,339 @@
+//===- EhFrameReader.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrameReader.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>
+
+using namespace mcld;
+using namespace llvm::dwarf;
+
+//===----------------------------------------------------------------------===//
+// Helper Functions
+//===----------------------------------------------------------------------===//
+/// skip_LEB128 - skip the first LEB128 encoded value from *pp, update *pp
+/// to the next character.
+/// @return - false if we ran off the end of the string.
+/// @ref - GNU gold 1.11, ehframe.h, Eh_frame::skip_leb128.
+static bool
+skip_LEB128(EhFrameReader::ConstAddress* pp, EhFrameReader::ConstAddress pend)
+{
+  for (EhFrameReader::ConstAddress p = *pp; p < pend; ++p) {
+    if (0x0 == (*p & 0x80)) {
+      *pp = p + 1;
+      return true;
+    }
+  }
+  return false;
+}
+
+//===----------------------------------------------------------------------===//
+// EhFrameReader
+//===----------------------------------------------------------------------===//
+template<> EhFrameReader::Token
+EhFrameReader::scan<true>(ConstAddress pHandler,
+                          uint64_t pOffset,
+                          const MemoryRegion& pData) const
+{
+  Token result;
+  result.file_off = pOffset;
+
+  const uint32_t* data = (const uint32_t*)pHandler;
+  size_t cur_idx = 0;
+
+  // Length Field
+  uint32_t length = data[cur_idx++];
+  if (0x0 == length) {
+    // terminator
+    result.kind = Terminator;
+    result.data_off = 4;
+    result.size = 4;
+    return result;
+  }
+
+  // Extended Field
+  uint64_t extended = 0x0;
+  if (0xFFFFFFFF == length) {
+    extended = data[cur_idx++];
+    extended <<= 32;
+    extended |= data[cur_idx++];
+    result.size = extended + 12;
+    result.data_off = 16;
+  }
+  else {
+    result.size = length + 4;
+    result.data_off = 8;
+  }
+
+  // ID Field
+  uint32_t ID = data[cur_idx++];
+  if (0x0 == ID)
+    result.kind = CIE;
+  else
+    result.kind = FDE;
+
+  return result;
+}
+
+template<>
+bool EhFrameReader::read<32, true>(Input& pInput, EhFrame& pEhFrame)
+{
+  // Alphabet:
+  //   {CIE, FDE, CIEt}
+  //
+  // Regular Expression:
+  //   (CIE FDE*)+ CIEt
+  //
+  // Autometa:
+  //   S = {Q0, Q1, Q2}, Start = Q0, Accept = Q2
+  //
+  //              FDE
+  //             +---+
+  //        CIE   \ /   CIEt
+  //   Q0 -------> Q1 -------> Q2
+  //    |         / \           ^
+  //    |        +---+          |
+  //    |         CIE           |
+  //    +-----------------------+
+  //              CIEt
+  const State autometa[NumOfStates][NumOfTokenKinds] = {
+  //     CIE     FDE    Term  Unknown
+    {     Q1, Reject, Accept, Reject }, // Q0
+    {     Q1,     Q1, Accept, Reject }, // Q1
+  };
+
+  const Action transition[NumOfStates][NumOfTokenKinds] = {
+   /*    CIE     FDE     Term Unknown */
+    { addCIE, reject, addTerm, reject}, // Q0
+    { addCIE, addFDE, addTerm, reject}, // Q1
+  };
+
+  // get file offset and address
+  LDSection& section = pEhFrame.getSection();
+  uint64_t file_off = pInput.fileOffset() + section.offset();
+  MemoryRegion* sect_reg =
+                       pInput.memArea()->request(file_off, section.size());
+  ConstAddress handler = (ConstAddress)sect_reg->start();
+
+  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);
+
+    if (!transition[cur_state][token.kind](pEhFrame, *entry, token)) {
+      // fail to scan
+      debug(diag::debug_cannot_scan_eh) << pInput.name();
+      return false;
+    }
+
+    file_off += token.size;
+    handler += token.size;
+
+    if (handler == sect_reg->end())
+      cur_state = Accept;
+    else if (handler > sect_reg->end()) {
+      cur_state = Reject;
+    }
+    else
+      cur_state = autometa[cur_state][token.kind];
+  } // end of while
+
+  if (Reject == cur_state) {
+    // fail to parse
+    debug(diag::debug_cannot_parse_eh) << pInput.name();
+    return false;
+  }
+  return true;
+}
+
+bool EhFrameReader::addCIE(EhFrame& pEhFrame,
+                           MemoryRegion& pRegion,
+                           const EhFrameReader::Token& pToken)
+{
+  // skip Length, Extended Length and CIE ID.
+  ConstAddress handler = pRegion.start() + pToken.data_off;
+  ConstAddress cie_end = pRegion.end();
+
+  // the version should be 1 or 3
+  uint8_t version = *handler++;
+  if (1 != version && 3 != version) {
+    return false;
+  }
+
+  // Set up the Augumentation String
+  ConstAddress aug_str_front = handler;
+  ConstAddress aug_str_back  = static_cast<ConstAddress>(
+                         memchr(aug_str_front, '\0', cie_end - aug_str_front));
+  if (NULL == aug_str_back) {
+    return false;
+  }
+
+  llvm::StringRef augment((const char*)aug_str_front);
+
+  // skip the Augumentation String field
+  handler = aug_str_back + 1;
+
+  // skip the Code Alignment Factor
+  if (!skip_LEB128(&handler, cie_end)) {
+    return false;
+  }
+  // skip the Data Alignment Factor
+  if (!skip_LEB128(&handler, cie_end)) {
+    return false;
+  }
+  // skip the Return Address Register
+  if (cie_end - handler < 1) {
+    return false;
+  }
+  ++handler;
+
+  // the Augmentation String start with 'eh' is a CIE from gcc before 3.0,
+  // in LSB Core Spec 3.0RC1. We do not support it.
+  if (augment[0] == 'e' && augment[1] == 'h') {
+    return false;
+  }
+
+  // parse the Augmentation String to get the FDE encodeing if 'z' existed
+  uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr;
+  if ('z' == augment[0]) {
+
+    // skip the Augumentation Data Length
+    if (!skip_LEB128(&handler, cie_end)) {
+      return false;
+    }
+
+    // parse the Augmentation String
+    for (size_t i = 1; i < augment.size(); ++i) {
+      switch (augment[i]) {
+        // LDSA encoding (1 byte)
+        case 'L': {
+          if (cie_end - handler < 1) {
+            return false;
+          }
+          ++handler;
+          break;
+        }
+        // Two arguments, the first one represents the encoding of the second
+        // argument (1 byte). The second one is the address of personality
+        // routine.
+        case 'P': {
+          // the first argument
+          if (cie_end - handler < 1) {
+            return false;
+          }
+          uint8_t per_encode = *handler;
+          ++handler;
+          // get the length of the second argument
+          uint32_t per_length = 0;
+          if (0x60 == (per_encode & 0x60)) {
+            return false;
+          }
+          switch (per_encode & 7) {
+            default:
+              return false;
+            case llvm::dwarf::DW_EH_PE_udata2:
+              per_length = 2;
+              break;
+            case llvm::dwarf::DW_EH_PE_udata4:
+              per_length = 4;
+              break;
+            case llvm::dwarf::DW_EH_PE_udata8:
+              per_length = 8;
+              break;
+            case llvm::dwarf::DW_EH_PE_absptr:
+              per_length = 4; // pPkg.bitclass / 8;
+              break;
+          }
+          // skip the alignment
+          if (llvm::dwarf::DW_EH_PE_aligned == (per_encode & 0xf0)) {
+            uint32_t per_align = handler - cie_end;
+            per_align += per_length - 1;
+            per_align &= ~(per_length -1);
+            if (static_cast<uint32_t>(cie_end - handler) < per_align) {
+              return false;
+            }
+            handler += per_align;
+          }
+          // skip the second argument
+          if (static_cast<uint32_t>(cie_end - handler) < per_length) {
+            return false;
+          }
+          handler += per_length;
+          break;
+        } // end of case 'P'
+
+        // FDE encoding (1 byte)
+        case 'R': {
+          if (cie_end - handler < 1) {
+            return false;
+          }
+          fde_encoding = *handler;
+          switch (fde_encoding & 7) {
+            case llvm::dwarf::DW_EH_PE_udata2:
+            case llvm::dwarf::DW_EH_PE_udata4:
+            case llvm::dwarf::DW_EH_PE_udata8:
+            case llvm::dwarf::DW_EH_PE_absptr:
+              break;
+            default:
+              return false;
+          }
+          ++handler;
+          break;
+        }
+        default:
+          return false;
+      } // end switch
+    } // the rest chars.
+  } // first char is 'z'
+
+  // create and push back the CIE entry
+  EhFrame::CIE* cie = new EhFrame::CIE(pRegion);
+  cie->setFDEEncode(fde_encoding);
+  pEhFrame.addCIE(*cie);
+  return true;
+}
+
+bool EhFrameReader::addFDE(EhFrame& pEhFrame,
+                           MemoryRegion& pRegion,
+                           const EhFrameReader::Token& pToken)
+{
+  if (pToken.data_off == pRegion.size())
+    return false;
+
+  // create and push back the FDE entry
+  EhFrame::FDE* fde = new EhFrame::FDE(pRegion,
+                                       pEhFrame.cie_back(),
+                                       pToken.data_off);
+  pEhFrame.addFDE(*fde);
+  return true;
+}
+
+bool EhFrameReader::addTerm(EhFrame& pEhFrame,
+                            MemoryRegion& pRegion,
+                            const EhFrameReader::Token& pToken)
+{
+  RegionFragment* frag = new RegionFragment(pRegion);
+  pEhFrame.addFragment(*frag);
+  return true;
+}
+
+bool EhFrameReader::reject(EhFrame& pEhFrame,
+                           MemoryRegion& pRegion,
+                           const EhFrameReader::Token& pToken)
+{
+  return true;
+}
+
diff --git a/lib/LD/FDE.cpp b/lib/LD/FDE.cpp
deleted file mode 100644
index 1aa196b..0000000
--- a/lib/LD/FDE.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- FDE.cpp ------------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <mcld/LD/FDE.h>
-#include <mcld/LD/EhFrame.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// FDE
-//===----------------------------------------------------------------------===//
-FDE::FDE(MemoryRegion& pRegion, const CIE& pCIE, Offset pPCBeginOffset)
-  : RegionFragment(pRegion), m_CIE(pCIE), m_PCBeginOffset(pPCBeginOffset) {
-}
-
-FDE::~FDE()
-{
-}
diff --git a/lib/LD/FragmentRef.cpp b/lib/LD/FragmentRef.cpp
deleted file mode 100644
index 9ae8e4d..0000000
--- a/lib/LD/FragmentRef.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-//===- FragmentRef.cpp --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <mcld/LD/FragmentRef.h>
-
-#include <cstring>
-#include <cassert>
-
-#include <llvm/Support/MathExtras.h>
-#include <llvm/Support/Casting.h>
-
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/LD/TargetFragment.h>
-#include <mcld/LD/Layout.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// Helper Functions
-//===----------------------------------------------------------------------===//
-/// compunteFragmentSize - compute the specific Fragment size
-uint64_t mcld::computeFragmentSize(const Layout& pLayout,
-                                   const Fragment& pFrag)
-{
-  switch (pFrag.getKind()) {
-    case Fragment::Fillment:
-      return static_cast<const FillFragment&>(pFrag).getSize();
-
-    case Fragment::Alignment: {
-      uint64_t offset = pLayout.getOutputOffset(pFrag);
-      const AlignFragment& align_frag = llvm::cast<AlignFragment>(pFrag);
-      uint64_t size = llvm::OffsetToAlignment(offset, align_frag.getAlignment());
-      if (size > align_frag.getMaxBytesToEmit())
-        return 0;
-      return size;
-    }
-
-    case Fragment::Region:
-      return llvm::cast<RegionFragment>(pFrag).getRegion().size();
-
-    case Fragment::Target:
-      return llvm::cast<TargetFragment>(pFrag).getSize();
-
-    case Fragment::Relocation:
-      assert(0 && "the size of FT_Reloc fragment is handled by backend");
-      return 0;
-
-    default:
-      assert(0 && "invalid fragment kind");
-      return 0;
-  }
-}
-
-//===----------------------------------------------------------------------===//
-// FragmentRef
-//===----------------------------------------------------------------------===//
-FragmentRef::FragmentRef()
-  : m_pFragment(NULL), m_Offset(0) {
-}
-
-FragmentRef::FragmentRef(Fragment& pFrag,
-                         FragmentRef::Offset pOffset)
-  : m_pFragment(&pFrag), m_Offset(pOffset) {
-}
-
-FragmentRef::~FragmentRef()
-{
-  m_pFragment = NULL;
-  m_Offset = 0;
-}
-
-FragmentRef& FragmentRef::assign(const FragmentRef& pCopy)
-{
-  m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment);
-  m_Offset = pCopy.m_Offset;
-  return *this;
-}
-
-FragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset)
-{
-  m_pFragment = &pFrag;
-  m_Offset = pOffset;
-  return *this;
-}
-
-void FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const
-{
-  // check if the offset is still in a legal range.
-  if (NULL == m_pFragment)
-    return;
-  unsigned int total_offset = m_Offset + pOffset;
-  switch(m_pFragment->getKind()) {
-    case Fragment::Region: {
-      RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment);
-      unsigned int total_length = region_frag->getRegion().size();
-      if (total_length < (total_offset+pNBytes))
-        pNBytes = total_length - total_offset;
-
-      std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes);
-      return;
-    }
-    case Fragment::Alignment:
-    case Fragment::Fillment:
-    default:
-      return;
-  }
-}
-
-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;
-}
-
diff --git a/lib/LD/GNUArchiveReader.cpp b/lib/LD/GNUArchiveReader.cpp
index 55c8c76..9aeaa6b 100644
--- a/lib/LD/GNUArchiveReader.cpp
+++ b/lib/LD/GNUArchiveReader.cpp
@@ -6,17 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/InputTree.h>
 #include <mcld/LD/GNUArchiveReader.h>
+
+#include <mcld/Module.h>
+#include <mcld/InputTree.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/MC/MCLDInput.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/MemoryAreaFactory.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/Path.h>
 #include <mcld/ADT/SizeTraits.h>
@@ -29,11 +30,9 @@
 
 using namespace mcld;
 
-GNUArchiveReader::GNUArchiveReader(MCLDInfo& pLDInfo,
-                                   MemoryAreaFactory& pMemAreaFactory,
+GNUArchiveReader::GNUArchiveReader(Module& pModule,
                                    ELFObjectReader& pELFObjectReader)
- : m_LDInfo(pLDInfo),
-   m_MemAreaFactory(pMemAreaFactory),
+ : m_Module(pModule),
    m_ELFObjectReader(pELFObjectReader)
 {
 }
@@ -90,6 +89,11 @@
 
 bool GNUArchiveReader::readArchive(Archive& pArchive)
 {
+  if (pArchive.getARFile().attribute()->isWholeArchive())
+    return includeAllMembers(pArchive);
+
+  // if this is the first time read this archive, setup symtab and strtab
+  if (pArchive.getSymbolTable().empty()) {
   // read the symtab of the archive
   readSymbolTable(pArchive);
 
@@ -100,6 +104,7 @@
   pArchive.addArchiveMember(pArchive.getARFile().name(),
                             pArchive.inputs().root(),
                             &InputTree::Downward);
+  }
 
   // include the needed members in the archive and build up the input tree
   bool willSymResolved;
@@ -123,56 +128,8 @@
         pArchive.setSymbolStatus(idx, status);
 
       if (Archive::Symbol::Include == status) {
-        Input* cur_archive = &(pArchive.getARFile());
-        Input* member = cur_archive;
-        uint32_t file_offset = pArchive.getObjFileOffset(idx);
-        while ((member != NULL) && (Input::Object != member->type())) {
-          uint32_t nested_offset = 0;
-          // use the file offset in current archive to find out the member we
-          // want to include
-          member = readMemberHeader(pArchive,
-                                    *cur_archive,
-                                    file_offset,
-                                    nested_offset);
-          assert(member != NULL);
-          // bypass if we get an archive that is already in the map
-          if (Input::Archive == member->type()) {
-              cur_archive = member;
-              file_offset = nested_offset;
-              continue;
-          }
-
-          // insert a node into the subtree of current archive.
-          Archive::ArchiveMember* parent =
-            pArchive.getArchiveMember(cur_archive->name());
-
-          assert(NULL != parent);
-          pArchive.inputs().insert(parent->lastPos, *(parent->move), *member);
-
-          // move the iterator to new created node, and also adjust the
-          // direction to Afterward for next insertion in this subtree
-          parent->move->move(parent->lastPos);
-          parent->move = &InputTree::Afterward;
-
-          if (m_ELFObjectReader.isMyFormat(*member)) {
-            member->setType(Input::Object);
-            pArchive.addObjectMember(pArchive.getObjFileOffset(idx),
-                                     parent->lastPos);
-            m_ELFObjectReader.readObject(*member);
-            m_ELFObjectReader.readSections(*member);
-            m_ELFObjectReader.readSymbols(*member);
-          }
-          else if (isMyFormat(*member)) {
-            member->setType(Input::Archive);
-            // when adding a new archive node, set the iterator to archive
-            // itself, and set the direction to Downward
-            pArchive.addArchiveMember(member->name(),
-                                      parent->lastPos,
-                                      &InputTree::Downward);
-            cur_archive = member;
-            file_offset = nested_offset;
-          }
-        } // end of while
+        // include the object member from the given offset
+        includeMember(pArchive, pArchive.getObjFileOffset(idx));
         willSymResolved = true;
       } // end of if
     } // end of for
@@ -189,10 +146,12 @@
 /// @param pArchiveFile  - the archive that contains the needed object
 /// @param pFileOffset   - file offset of the member header in the archive
 /// @param pNestedOffset - used when we find a nested archive
+/// @param pMemberSize   - the file size of this member
 Input* GNUArchiveReader::readMemberHeader(Archive& pArchiveRoot,
                                           Input& pArchiveFile,
                                           uint32_t pFileOffset,
-                                          uint32_t& pNestedOffset)
+                                          uint32_t& pNestedOffset,
+                                          size_t& pMemberSize)
 {
   assert(pArchiveFile.hasMemArea());
 
@@ -202,13 +161,13 @@
   const Archive::MemberHeader* header =
     reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
 
-  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
+  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
 
-  // int size = atoi(header->size);
+  pMemberSize = atoi(header->size);
 
   // parse the member name and nested offset if any
   std::string member_name;
-  llvm::StringRef name_field(header->name, 16);
+  llvm::StringRef name_field(header->name, sizeof(header->name));
   if ('/' != header->name[0]) {
     // this is an object file in an archive
     size_t pos = name_field.find_first_of('/');
@@ -230,24 +189,22 @@
     }
 
     // get the member name from the extended name table
+    assert(pArchiveRoot.hasStrTable());
     begin = name_offset;
     end = pArchiveRoot.getStrTable().find_first_of('\n', begin);
     member_name.assign(pArchiveRoot.getStrTable().substr(begin, end - begin -1));
   }
 
   Input* member = NULL;
-  if (!isThinArchive(pArchiveFile)) {
+  bool isThinAR = isThinArchive(pArchiveFile);
+  if (!isThinAR) {
     // this is an object file in an archive
-    member =
-      m_LDInfo.inputFactory().produce(member_name,
-                                      pArchiveFile.path(),
-                                      Input::Unknown,
-                                      (pFileOffset +
-                                       sizeof(Archive::MemberHeader)));
-    assert(member != NULL);
-    member->setMemArea(pArchiveFile.memArea());
-    LDContext *input_context = m_LDInfo.contextFactory().produce();
-    member->setContext(input_context);
+    member = pArchiveRoot.getMemberFile(pArchiveFile,
+                                        isThinAR,
+                                        member_name,
+                                        pArchiveFile.path(),
+                                        (pFileOffset +
+                                         sizeof(Archive::MemberHeader)));
   }
   else {
     // this is a member in a thin archive
@@ -265,21 +222,11 @@
       input_path.append(member_name);
     else
       input_path.assign(member_name);
-    member =
-      m_LDInfo.inputFactory().produce(member_name, input_path, Input::Unknown);
 
-    assert(member != NULL);
-    MemoryArea* input_memory =
-      m_MemAreaFactory.produce(member->path(), FileHandle::ReadOnly);
-    if (input_memory->handler()->isGood()) {
-      member->setMemArea(input_memory);
-    }
-    else {
-      error(diag::err_cannot_open_input) << member->name() << member->path();
-      return NULL;
-    }
-    LDContext *input_context = m_LDInfo.contextFactory().produce(input_path);
-    member->setContext(input_context);
+    member = pArchiveRoot.getMemberFile(pArchiveFile,
+                                        isThinAR,
+                                        member_name,
+                                        input_path);
   }
 
   pArchiveFile.memArea()->release(header_region);
@@ -297,42 +244,44 @@
                                             sizeof(Archive::MemberHeader));
   const Archive::MemberHeader* header =
     reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
-  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
+  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
 
   int symtab_size = atoi(header->size);
   pArchive.setSymTabSize(symtab_size);
 
-  MemoryRegion* symtab_region =
-    pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
+  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());
+    const uint32_t* data =
+      reinterpret_cast<const uint32_t*>(symtab_region->getBuffer());
 
-  // read the number of symbols
-  uint32_t number = 0;
-  if (llvm::sys::isLittleEndianHost())
-    number = bswap32(*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 (uint32_t i = 0; i < number; ++i) {
+    // read the number of symbols
+    uint32_t number = 0;
     if (llvm::sys::isLittleEndianHost())
-      pArchive.addSymbol(name, bswap32(*data));
+      number = bswap32(*data);
     else
-      pArchive.addSymbol(name, *data);
-    name += strlen(name) + 1;
-    ++data;
-  }
+      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 (uint32_t i = 0; i < number; ++i) {
+      if (llvm::sys::isLittleEndianHost())
+        pArchive.addSymbol(name, bswap32(*data));
+      else
+        pArchive.addSymbol(name, *data);
+      name += strlen(name) + 1;
+      ++data;
+    }
+    pArchive.getARFile().memArea()->release(symtab_region);
+  }
   pArchive.getARFile().memArea()->release(header_region);
-  pArchive.getARFile().memArea()->release(symtab_region);
   return true;
 }
 
@@ -355,22 +304,22 @@
   const Archive::MemberHeader* header =
     reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
 
-  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
+  assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
 
-  int strtab_size = atoi(header->size);
-
-  MemoryRegion* 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());
-
-  pArchive.getStrTable().assign(strtab, strtab_size);
-
+  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 =
+      pArchive.getARFile().memArea()->request(
+                                   (pArchive.getARFile().fileOffset() +
+                                    offset + sizeof(Archive::MemberHeader)),
+                                   strtab_size);
+    const char* strtab =
+      reinterpret_cast<const char*>(strtab_region->getBuffer());
+    pArchive.getStrTable().assign(strtab, strtab_size);
+    pArchive.getARFile().memArea()->release(strtab_region);
+  }
   pArchive.getARFile().memArea()->release(header_region);
-  pArchive.getARFile().memArea()->release(strtab_region);
   return true;
 }
 
@@ -380,7 +329,7 @@
 GNUArchiveReader::shouldIncludeSymbol(const llvm::StringRef& pSymName) const
 {
   // TODO: handle symbol version issue and user defined symbols
-  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pSymName);
+  const ResolveInfo* info = m_Module.getNamePool().findInfo(pSymName);
   if (NULL != info) {
     if (!info->isUndef())
       return Archive::Symbol::Exclude;
@@ -391,3 +340,107 @@
   return Archive::Symbol::Unknown;
 }
 
+/// includeMember - include the object member in the given file offset, and
+/// return the size of the object
+/// @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)
+{
+  Input* cur_archive = &(pArchive.getARFile());
+  Input* member = NULL;
+  uint32_t file_offset = pFileOffset;
+  size_t size = 0;
+  do {
+    uint32_t nested_offset = 0;
+    // use the file offset in current archive to find out the member we
+    // want to include
+    member = readMemberHeader(pArchive,
+                              *cur_archive,
+                              file_offset,
+                              nested_offset,
+                              size);
+    assert(member != NULL);
+    // bypass if we get an archive that is already in the map
+    if (Input::Archive == member->type()) {
+        cur_archive = member;
+        file_offset = nested_offset;
+        continue;
+    }
+
+    // insert a node into the subtree of current archive.
+    Archive::ArchiveMember* parent =
+      pArchive.getArchiveMember(cur_archive->name());
+
+    assert(NULL != parent);
+    pArchive.inputs().insert(parent->lastPos, *(parent->move), *member);
+
+    // move the iterator to new created node, and also adjust the
+    // direction to Afterward for next insertion in this subtree
+    parent->move->move(parent->lastPos);
+    parent->move = &InputTree::Afterward;
+
+    if (m_ELFObjectReader.isMyFormat(*member)) {
+      member->setType(Input::Object);
+      pArchive.addObjectMember(pFileOffset, parent->lastPos);
+      m_ELFObjectReader.readHeader(*member);
+      m_ELFObjectReader.readSections(*member);
+      m_ELFObjectReader.readSymbols(*member);
+      m_Module.getObjectList().push_back(member);
+    }
+    else if (isMyFormat(*member)) {
+      member->setType(Input::Archive);
+      // when adding a new archive node, set the iterator to archive
+      // itself, and set the direction to Downward
+      pArchive.addArchiveMember(member->name(),
+                                parent->lastPos,
+                                &InputTree::Downward);
+      cur_archive = member;
+      file_offset = nested_offset;
+    }
+  } 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)
+{
+  // read the symtab of the archive
+  readSymbolTable(pArchive);
+
+  // read the strtab of the archive
+  readStringTable(pArchive);
+
+  // add root archive to ArchiveMemberMap
+  pArchive.addArchiveMember(pArchive.getARFile().name(),
+                            pArchive.inputs().root(),
+                            &InputTree::Downward);
+
+  bool isThinAR = isThinArchive(pArchive.getARFile());
+  uint32_t begin_offset = pArchive.getARFile().fileOffset() +
+                          Archive::MAGIC_LEN +
+                          sizeof(Archive::MemberHeader) +
+                          pArchive.getSymTabSize();
+  if (pArchive.hasStrTable()) {
+    if (0x0 != (begin_offset & 1))
+      ++begin_offset;
+    begin_offset += sizeof(Archive::MemberHeader) +
+                    pArchive.getStrTable().size();
+  }
+  uint32_t end_offset = pArchive.getARFile().memArea()->handler()->size();
+  for (uint32_t offset = begin_offset;
+       offset < end_offset;
+       offset += sizeof(Archive::MemberHeader)) {
+
+    size_t size = includeMember(pArchive, offset);
+
+    if (!isThinAR) {
+      offset += size;
+    }
+
+    if (0x0 != (offset & 1))
+      ++offset;
+  }
+  return true;
+}
+
diff --git a/lib/LD/GroupReader.cpp b/lib/LD/GroupReader.cpp
new file mode 100644
index 0000000..91e79c0
--- /dev/null
+++ b/lib/LD/GroupReader.cpp
@@ -0,0 +1,138 @@
+//===- GroupReader.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/Archive.h>
+#include <mcld/LD/ArchiveReader.h>
+#include <mcld/LD/DynObjReader.h>
+#include <mcld/LD/GroupReader.h>
+#include <mcld/LD/ObjectReader.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+GroupReader::GroupReader(Module& pModule,
+                         ObjectReader& pObjectReader,
+                         DynObjReader& pDynObjReader,
+                         ArchiveReader& pArchiveReader)
+  : m_Module(pModule),
+    m_ObjectReader(pObjectReader),
+    m_DynObjReader(pDynObjReader),
+    m_ArchiveReader(pArchiveReader)
+{
+}
+
+GroupReader::~GroupReader()
+{
+}
+
+bool GroupReader::readGroup(Module::input_iterator pRoot,
+                            InputBuilder& pBuilder,
+                            const LinkerConfig& pConfig)
+{
+  // record the number of total objects included in this sub-tree
+  size_t cur_obj_cnt = 0;
+  size_t last_obj_cnt = 0;
+  size_t non_ar_obj_cnt = 0;
+
+  // record the archive files in this sub-tree
+  typedef std::vector<ArchiveListEntry*> ArchiveListType;
+  ArchiveListType ar_list;
+
+  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) {
+    // already got type - for example, bitcode or external OIR (object
+    // intermediate representation)
+    if ((*input)->type() == Input::Script ||
+        (*input)->type() == Input::Object ||
+        (*input)->type() == Input::DynObj  ||
+        (*input)->type() == Input::Archive ||
+        (*input)->type() == Input::External) {
+      ++input;
+      continue;
+    }
+
+    // is an archive
+    if (m_ArchiveReader.isMyFormat(**input)) {
+      (*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);
+      cur_obj_cnt += ar->numOfObjectMember();
+    }
+    // is a relocatable object file
+    else if (m_ObjectReader.isMyFormat(**input)) {
+      (*input)->setType(Input::Object);
+      m_ObjectReader.readHeader(**input);
+      m_ObjectReader.readSections(**input);
+      m_ObjectReader.readSymbols(**input);
+      m_Module.getObjectList().push_back(*input);
+      ++cur_obj_cnt;
+      ++non_ar_obj_cnt;
+    }
+    // is a shared object file
+    else if (m_DynObjReader.isMyFormat(**input)) {
+      (*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.triple().str();
+    }
+    ++input;
+  }
+
+  // after read in all the archives, traverse the archive list in a loop until
+  // there is no unresolved symbols added
+  ArchiveListType::iterator it = ar_list.begin();
+  ArchiveListType::iterator end = ar_list.end();
+  while (cur_obj_cnt != last_obj_cnt) {
+    last_obj_cnt = cur_obj_cnt;
+    cur_obj_cnt = non_ar_obj_cnt;
+    for (it = ar_list.begin(); it != end; ++it) {
+      Archive& ar = (*it)->archive;
+      // if --whole-archive is given to this archive, no need to read it again
+      if ( ar.getARFile().attribute()->isWholeArchive())
+        continue;
+      m_ArchiveReader.readArchive(ar);
+      cur_obj_cnt += ar.numOfObjectMember();
+    }
+  }
+
+  // after all needed member included, merge the archive sub-tree to main
+  // InputTree
+  for (it = ar_list.begin(); it != end; ++it) {
+    Archive& ar = (*it)->archive;
+    if (ar.numOfObjectMember() > 0) {
+      m_Module.getInputTree().merge<InputTree::Inclusive>((*it)->input,
+                                                          ar.inputs());
+    }
+  }
+
+  // cleanup ar_list
+  for (it = ar_list.begin(); it != end; ++it) {
+    delete &((*it)->archive);
+    delete (*it);
+  }
+  ar_list.clear();
+
+  return true;
+}
+
diff --git a/lib/LD/LDContext.cpp b/lib/LD/LDContext.cpp
index f6556f3..8607dfd 100644
--- a/lib/LD/LDContext.cpp
+++ b/lib/LD/LDContext.cpp
@@ -13,14 +13,16 @@
 
 using namespace mcld;
 
-//==========================
-// LDReader
-LDContext::LDContext()
+//===----------------------------------------------------------------------===//
+// LDContext
+//===----------------------------------------------------------------------===//
+LDContext& LDContext::appendSection(LDSection& pSection)
 {
-}
-
-LDContext::~LDContext()
-{
+  if (LDFileFormat::Relocation == pSection.kind())
+    m_RelocSections.push_back(&pSection);
+  pSection.setIndex(m_SectionTable.size());
+  m_SectionTable.push_back(&pSection);
+  return *this;
 }
 
 LDSection* LDContext::getSection(unsigned int pIdx)
diff --git a/lib/LD/LDFileFormat.cpp b/lib/LD/LDFileFormat.cpp
index c1ddb52..bb878b8 100644
--- a/lib/LD/LDFileFormat.cpp
+++ b/lib/LD/LDFileFormat.cpp
@@ -7,12 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/LDFileFormat.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // LDFileInfo
+//===----------------------------------------------------------------------===//
 LDFileFormat::LDFileFormat()
   : f_pTextSection(NULL),
     f_pDataSection(NULL),
@@ -24,9 +25,3 @@
 {
 }
 
-void LDFileFormat::initStdSections(MCLinker& pLinker)
-{
-  initObjectFormat(pLinker);
-  initObjectType(pLinker);
-}
-
diff --git a/lib/LD/LDSection.cpp b/lib/LD/LDSection.cpp
index 2aad917..30daee3 100644
--- a/lib/LD/LDSection.cpp
+++ b/lib/LD/LDSection.cpp
@@ -8,26 +8,102 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/LDSection.h>
 
+#include <mcld/Support/GCFactory.h>
+
+#include <llvm/Support/ManagedStatic.h>
+
 using namespace mcld;
 
+typedef GCFactory<LDSection, MCLD_SECTIONS_PER_INPUT> SectionFactory;
+
+static llvm::ManagedStatic<SectionFactory> g_SectFactory;
+
+//===----------------------------------------------------------------------===//
+// LDSection
+//===----------------------------------------------------------------------===//
+LDSection::LDSection()
+  : m_Name(),
+    m_Kind(LDFileFormat::Ignore),
+    m_Type(0x0),
+    m_Flag(0x0),
+    m_Size(0),
+    m_Offset(~uint64_t(0)),
+    m_Addr(0x0),
+    m_Align(0),
+    m_Info(0),
+    m_pLink(NULL),
+    m_Index(0) {
+  m_Data.sect_data = NULL;
+}
+
 LDSection::LDSection(const std::string& pName,
                      LDFileFormat::Kind pKind,
                      uint32_t pType,
                      uint32_t pFlag,
                      uint64_t pSize,
-                     uint64_t pOffset,
                      uint64_t pAddr)
   : m_Name(pName),
     m_Kind(pKind),
     m_Type(pType),
     m_Flag(pFlag),
     m_Size(pSize),
-    m_Offset(pOffset),
+    m_Offset(~uint64_t(0)),
     m_Addr(pAddr),
     m_Align(0),
     m_Info(0),
     m_pLink(NULL),
-    m_pSectionData(NULL),
     m_Index(0) {
+  m_Data.sect_data = NULL;
+}
+
+LDSection::~LDSection()
+{
+}
+
+bool LDSection::hasOffset() const
+{
+  return (m_Offset != ~uint64_t(0));
+}
+
+LDSection* LDSection::Create(const std::string& pName,
+                             LDFileFormat::Kind pKind,
+                             uint32_t pType,
+                             uint32_t pFlag,
+                             uint64_t pSize,
+                             uint64_t pAddr)
+{
+  LDSection* result = g_SectFactory->allocate();
+  new (result) LDSection(pName, pKind, pType, pFlag, pSize, pAddr);
+  return result;
+}
+
+void LDSection::Destroy(LDSection*& pSection)
+{
+  g_SectFactory->destroy(pSection);
+  g_SectFactory->deallocate(pSection);
+  pSection = NULL;
+}
+
+void LDSection::Clear()
+{
+  g_SectFactory->clear();
+}
+
+bool LDSection::hasSectionData() const
+{
+  assert(LDFileFormat::Relocation != kind() && LDFileFormat::EhFrame != kind());
+  return (NULL != m_Data.sect_data);
+}
+
+bool LDSection::hasRelocData() const
+{
+  assert(LDFileFormat::Relocation == kind());
+  return (NULL != m_Data.reloc_data);
+}
+
+bool LDSection::hasEhFrame() const
+{
+  assert(LDFileFormat::EhFrame == kind());
+  return (NULL != m_Data.eh_frame);
 }
 
diff --git a/lib/LD/LDSectionFactory.cpp b/lib/LD/LDSectionFactory.cpp
deleted file mode 100644
index a81c839..0000000
--- a/lib/LD/LDSectionFactory.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- LDSectionFactory.cpp -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/LD/LDSectionFactory.h>
-
-using namespace mcld;
-
-//==========================
-// LDSectionFactory
-LDSectionFactory::LDSectionFactory(size_t pNum)
-  : GCFactory<LDSection, 0>(pNum) {
-}
-
-LDSectionFactory::~LDSectionFactory()
-{
-}
-
-LDSection* LDSectionFactory::produce(const std::string& pName,
-                                   LDFileFormat::Kind pKind,
-                                   uint32_t pType,
-                                   uint32_t pFlag)
-{
-  // create a LDSection
-  LDSection* result = allocate();
-  new (result) LDSection(pName, pKind, pType, pFlag);
-  return result;
-}
-
-void LDSectionFactory::destroy(LDSection*& pSection)
-{
-  // do not recycle LDSection. HeaderFactory will do that job.
-  deallocate(pSection);
-}
-
-LDSection* LDSectionFactory::find(const std::string& pName)
-{
-  iterator sect_iter, sect_end = end();
-  for (sect_iter = begin(); sect_iter != sect_end; ++sect_iter)
-    if ((*sect_iter).name() == pName)
-      break;
-  if (sect_iter == sect_end)
-    return NULL;
-  return &(*sect_iter);
-}
diff --git a/lib/LD/LDSymbol.cpp b/lib/LD/LDSymbol.cpp
index f088b5c..c6fab43 100644
--- a/lib/LD/LDSymbol.cpp
+++ b/lib/LD/LDSymbol.cpp
@@ -6,13 +6,28 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include <mcld/LD/LDSymbol.h>
 
+#include <mcld/Config/Config.h>
+#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/Fragment/NullFragment.h>
+#include <mcld/Support/GCFactory.h>
+
 #include <cstring>
 
+#include <llvm/Support/ManagedStatic.h>
+
 using namespace mcld;
 
+static LDSymbol* g_NullSymbol = NULL;
+
+typedef GCFactory<LDSymbol, MCLD_SYMBOLS_PER_INPUT> LDSymbolFactory;
+
+static llvm::ManagedStatic<LDSymbolFactory> g_LDSymbolFactory;
+
+//===----------------------------------------------------------------------===//
+// LDSymbol
+//===----------------------------------------------------------------------===//
 LDSymbol::LDSymbol()
   : m_pResolveInfo(NULL), m_pFragRef(NULL), m_Value(0) {
 }
@@ -35,6 +50,38 @@
   return (*this);
 }
 
+LDSymbol* LDSymbol::Create(ResolveInfo& pResolveInfo)
+{
+  LDSymbol* result = g_LDSymbolFactory->allocate();
+  new (result) LDSymbol();
+  result->setResolveInfo(pResolveInfo);
+  return result;
+}
+
+void LDSymbol::Destroy(LDSymbol*& pSymbol)
+{
+  pSymbol->~LDSymbol();
+  g_LDSymbolFactory->deallocate(pSymbol);
+  pSymbol = NULL;
+}
+
+void LDSymbol::Clear()
+{
+  g_LDSymbolFactory->clear();
+}
+
+LDSymbol* LDSymbol::Null()
+{
+  if (NULL == g_NullSymbol) {
+    g_NullSymbol = new LDSymbol();
+    g_NullSymbol->setResolveInfo(*ResolveInfo::Null());
+    NullFragment* null_frag = new NullFragment();
+    g_NullSymbol->setFragmentRef(FragmentRef::Create(*null_frag, 0));
+    ResolveInfo::Null()->setSymPtr(g_NullSymbol);
+  }
+  return g_NullSymbol;
+}
+
 void LDSymbol::setFragmentRef(FragmentRef* pFragmentRef)
 {
   m_pFragRef = pFragmentRef;
@@ -45,3 +92,13 @@
   m_pResolveInfo = const_cast<ResolveInfo*>(&pInfo);
 }
 
+bool LDSymbol::isNull() const
+{
+  return (this == Null());
+}
+
+bool LDSymbol::hasFragRef() const
+{
+  return !m_pFragRef->isNull();
+}
+
diff --git a/lib/LD/Layout.cpp b/lib/LD/Layout.cpp
index 1650556..a2a1028 100644
--- a/lib/LD/Layout.cpp
+++ b/lib/LD/Layout.cpp
@@ -6,524 +6,35 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include <mcld/LD/Layout.h>
 
-#include <cassert>
-
-#include <llvm/ADT/Twine.h>
-
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/ADT/SizeTraits.h>
-#include <mcld/LD/LDContext.h>
 #include <mcld/LD/LDFileFormat.h>
 #include <mcld/LD/LDSection.h>
-#include <mcld/LD/Fragment.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCLDInfo.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Target/TargetLDBackend.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// Range
-//===----------------------------------------------------------------------===//
-Layout::Range::Range()
-  : header(NULL),
-    prevRear(NULL) {
-}
-
-Layout::Range::Range(const LDSection& pHdr)
-  : header(const_cast<LDSection*>(&pHdr)),
-    prevRear(NULL) {
-}
-
-Layout::Range::~Range()
-{
-}
-
-//===----------------------------------------------------------------------===//
 // Layout
 //===----------------------------------------------------------------------===//
-Layout::Layout()
-  : m_FragRefFactory(32) /** magic number **/ {
-}
-
-Layout::~Layout()
-{
-}
-
-void Layout::setFragmentLayoutOrder(Fragment* pFrag)
-{
-  if (NULL == pFrag)
-    return;
-
-  /// find the most-recent fragment whose order was set.
-  Fragment* first = pFrag;
-  while (!hasLayoutOrder(*first)) {
-    if (NULL == first->getPrevNode())
-      break;
-    first = first->getPrevNode();
-  }
-
-  /// set all layout order
-
-  // find the first fragment who has no order.
-  // find the last order of the fragment
-  unsigned int layout_order = 0;
-  Fragment* frag_not_set = NULL;
-  if (NULL == first->getPrevNode()) {
-    layout_order = 0;
-    frag_not_set = first;
-  }
-  else {
-    layout_order = first->getLayoutOrder();
-    frag_not_set = first->getNextNode();
-  }
-
-  // for all fragments that has no order, set up its order
-  while(NULL != frag_not_set) {
-    frag_not_set->setLayoutOrder(layout_order);
-    ++layout_order;
-    frag_not_set = frag_not_set->getNextNode();
-  }
-}
-
-/// setFragmentLayoutOffset - set the fragment's layout offset. This function
-/// also set up the layout offsets of all the fragments in the same range.
-/// If the offset of the fragment was set before, return immediately.
-void Layout::setFragmentLayoutOffset(Fragment* pFrag)
-{
-  if (NULL == pFrag)
-    return;
-
-  // find the most-recent fragment whose offset was set.
-  Fragment* first = pFrag;
-
-  while (!hasLayoutOffset(*first)) {
-    if (NULL == first->getPrevNode())
-      break;
-    first = first->getPrevNode();
-  }
-
-  // set all layout order
-  uint64_t offset = 0;
-  Fragment* frag_not_set = NULL;
-  if (NULL == first->getPrevNode()) {
-    offset = 0;
-    frag_not_set = first;
-  }
-  else {
-    offset = first->getOffset();
-    offset += computeFragmentSize(*this, *first);
-    frag_not_set = first->getNextNode();
-  }
-
-  while(NULL != frag_not_set) {
-    frag_not_set->setOffset(offset);
-    offset += computeFragmentSize(*this, *frag_not_set);
-    frag_not_set = frag_not_set->getNextNode();
-  }
-}
-
-/// addInputRange
-///   1. add a new range <pInputHdr, previous rear fragment>
-///   2. compute the layout order of all previous ranges.
-///   2. compute the layout offset of all previous ranges.
-void Layout::addInputRange(const SectionData& pSD,
-                           const LDSection& pInputHdr)
-{
-  RangeList* range_list = NULL;
-
-  // get or create the range_list
-  if (pSD.getFragmentList().empty() || 0 == m_SDRangeMap.count(&pSD)) {
-    range_list = new RangeList();
-    m_SDRangeMap[&pSD] = range_list;
-  }
-  else {
-    range_list = m_SDRangeMap[&pSD];
-  }
-
-  // make a range and push it into the range list
-  Range* range = new Range(pInputHdr);
-  range_list->push_back(range);
-
-  // set up previous rear of the range.
-  // FIXME: in current design, we can not add a range before finishing adding
-  // fragments in the previous range. If the limitation keeps, we can set
-  // prevRear to the last fragment in the SectionData simply.
-  //
-  // if the pSD's fragment list is empty, the range.prevRear keeps NULL.
-  if (!pSD.getFragmentList().empty()) {
-    range->prevRear =
-                  const_cast<Fragment*>(&pSD.getFragmentList().back());
-  }
-
-  // compute the layout order of the previous range.
-  if (!isFirstRange(*range)) {
-    setFragmentLayoutOrder(range->prevRear);
-    setFragmentLayoutOffset(range->prevRear);
-  }
-}
-
-/// appendFragment - append the given Fragment to the given SectionData,
-/// and insert a MCAlignFragment to preserve the required align constraint if
-/// needed
-uint64_t Layout::appendFragment(Fragment& pFrag,
-                                SectionData& pSD,
-                                uint32_t pAlignConstraint)
-{
-  // insert MCAlignFragment into SectionData first if needed
-  AlignFragment* align_frag = NULL;
-  if (pAlignConstraint > 1) {
-    align_frag = new AlignFragment(pAlignConstraint, // alignment
-                                   0x0, // the filled value
-                                   1u,  // the size of filled value
-                                   pAlignConstraint - 1, // max bytes to emit
-                                   &pSD);
-  }
-
-  // append the fragment to the SectionData
-  pFrag.setParent(&pSD);
-  pSD.getFragmentList().push_back(&pFrag);
-
-  // update the alignment of associated output LDSection if needed
-  LDSection* output_sect = getOutputLDSection(pFrag);
-  assert(NULL != output_sect);
-  if (pAlignConstraint > output_sect->align())
-    output_sect->setAlign(pAlignConstraint);
-
-  // compute the fragment order and offset
-  setFragmentLayoutOrder(&pFrag);
-  setFragmentLayoutOffset(&pFrag);
-
-  if (NULL != align_frag)
-    return pFrag.getOffset() - align_frag->getOffset() + computeFragmentSize(*this, pFrag);
-  else
-    return computeFragmentSize(*this, pFrag);
-}
-
-/// getInputLDSection - give a Fragment, return the corresponding input
-/// LDSection*
-LDSection*
-Layout::getInputLDSection(const Fragment& pFrag)
-{
-  const SectionData* sect_data = pFrag.getParent();
-  // check the SectionData
-  if (NULL == sect_data) {
-    llvm::report_fatal_error(llvm::Twine("the fragment does not belong to") +
-                             llvm::Twine(" any SectionData.\n"));
-  }
-
-  // check the SectionData's range list
-  if (0 == m_SDRangeMap.count(sect_data)) {
-    llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
-                             llvm::Twine("the input's SectionData is not ") +
-                             llvm::Twine("registered in the Layout.\nPlease ") +
-                             llvm::Twine("use MCLinker::getOrCreateSectData() ") +
-                             llvm::Twine("to get input's SectionData.\n"));
-  }
-
-  RangeList* range_list = m_SDRangeMap[sect_data];
-  // the fragment who has the layout order is not in the last range.
-  if (hasLayoutOrder(pFrag)) {
-    Range range = range_list->back();
-    if (isFirstRange(range)) {
-      return range.header;
-    }
-    while(range.prevRear->getLayoutOrder() > pFrag.getLayoutOrder()) {
-      if (NULL != range.getPrevNode())
-        range = *range.getPrevNode();
-      else
-        return NULL;
-    }
-    return range.header;
-  }
-  // the fragment who has no layout order should be in the last range
-  else {
-    if (range_list->empty())
-      return NULL;
-    return range_list->back().header;
-  }
-}
-
-/// getInputLDSection - give a Fragment, return the corresponding input
-/// LDSection*
-const LDSection*
-Layout::getInputLDSection(const Fragment& pFrag) const
-{
-  const SectionData* sect_data = pFrag.getParent();
-  // check the SectionData
-  if (NULL == sect_data) {
-    llvm::report_fatal_error(llvm::Twine("the fragment does not belong to") +
-                             llvm::Twine(" any SectionData.\n"));
-  }
-
-  // check the SectionData's range list
-  if (0 == m_SDRangeMap.count(sect_data)) {
-    llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
-                             llvm::Twine("the input's SectionData is not ") +
-                             llvm::Twine("registered in the Layout.\nPlease ") +
-                             llvm::Twine("use MCLinker::getOrCreateSectData() ") +
-                             llvm::Twine("to get input's SectionData.\n"));
-  }
-
-  SDRangeMap::const_iterator range_list_iter = m_SDRangeMap.find(sect_data);
-  const RangeList* range_list = range_list_iter->second;
-  // the fragment who has the layout order is not in the last range.
-  if (hasLayoutOrder(pFrag)) {
-    Range range = range_list->back();
-    if (isFirstRange(range)) {
-      return range.header;
-    }
-    while(range.prevRear->getLayoutOrder() > pFrag.getLayoutOrder()) {
-      if (NULL != range.getPrevNode())
-        range = *range.getPrevNode();
-      else
-        return NULL;
-    }
-    return range.header;
-  }
-  // the fragment who has no layout order should be in the last range
-  else {
-    if (range_list->empty())
-      return NULL;
-    return range_list->back().header;
-  }
-}
-
-/// getOutputLDSection
-LDSection* Layout::getOutputLDSection(const Fragment& pFrag)
-{
-  SectionData* sect_data = pFrag.getParent();
-  if (NULL == sect_data)
-    return NULL;
-
-  return const_cast<LDSection*>(&sect_data->getSection());
-}
-
-/// getOutputLDSection
-const LDSection* Layout::getOutputLDSection(const Fragment& pFrag) const
-{
-  const SectionData* sect_data = pFrag.getParent();
-  if (NULL == sect_data)
-    return NULL;
-
-  return &sect_data->getSection();
-}
-
-/// getFragmentRef - assume the ragne exist, find the fragment reference
-FragmentRef* Layout::getFragmentRef(Layout::Range& pRange, uint64_t pOffset)
-{
-  if (isEmptyRange(pRange))
-    return NULL;
-
-  Fragment* front = getFront(pRange);
-  if (NULL == front)
-    return NULL;
-
-  Fragment* rear = getRear(pRange);
-  if (NULL == rear)
-    return NULL;
-
-  return getFragmentRef(*front, *rear, pOffset);
-}
-
-// @param pFront is the first fragment in the range.
-// @param pRear is the last fragment in the range.
-// @pOffset is the offset started from pFront.
-FragmentRef*
-Layout::getFragmentRef(Fragment& pFront, Fragment& pRear, uint64_t pOffset)
-{
-  Fragment* front = &pFront;
-  Fragment* rear  = &pRear;
-
-  if (!hasLayoutOffset(*rear)) {
-    // compute layout order, offset
-    setFragmentLayoutOrder(rear);
-    setFragmentLayoutOffset(rear);
-  }
-
-  // compute the offset from overall start fragment.
-  uint64_t target_offset = pFront.getOffset() + pOffset;
-
-  // from front to rear, find the offset which is as large as possible
-  // but smaller than the target_offset.
-  while (front != rear) {
-    if (Fragment::Alignment == front->getKind()) {
-      // alignment fragments were not counted in target_offset.
-      // Count in the size of alignment fragmen in target_offset here.
-      uint64_t align_size = 0x0;
-      if (NULL == front->getNextNode()) {
-        // If the alignment fragment is the last fragment, increase
-        // the target_offset by the alignment fragment's size.
-        align_size = computeFragmentSize(*this, *front);
-      }
-      else {
-        // If the alignment fragment is not the last fragment, the alignment
-        // fragment's size is the distance between the two fragment.
-        align_size = front->getNextNode()->getOffset() - front->getOffset();
-      }
-      target_offset += align_size;
-      front = front->getNextNode();
-      continue;
-    }
-
-    if (target_offset >= front->getNextNode()->getOffset()) {
-      front = front->getNextNode();
-    }
-    else {
-      // found
-      FragmentRef* result = m_FragRefFactory.allocate();
-      new (result) FragmentRef(*front, target_offset - front->getOffset());
-      return result;
-    }
-  }
-
-  if (front == rear) {
-    if (Fragment::Alignment == front->getKind())
-      return NULL;
-
-    if (!isValidOffset(*front, target_offset))
-      return NULL;
-
-    FragmentRef* result = m_FragRefFactory.allocate();
-    new (result) FragmentRef(*front, target_offset - front->getOffset());
-    return result;
-  }
-  return NULL;
-}
-
-/// getFragmentRef - give a LDSection in input file and an offset, return
-/// the fragment reference.
-FragmentRef*
-Layout::getFragmentRef(const LDSection& pInputSection, uint64_t pOffset)
-{
-  // find out which SectionData covers the range of input section header
-  const SectionData* sect_data = pInputSection.getSectionData();
-
-  // check range list
-  if (0 == m_SDRangeMap.count(sect_data))
-    return NULL;
-
-  if (sect_data->getFragmentList().empty())
-    return NULL;
-
-  RangeList* range_list = m_SDRangeMap[sect_data];
-
-  // find out the specific part in SectionData range
-  RangeList::iterator range, rangeEnd = range_list->end();
-  for (range = range_list->begin(); range != rangeEnd; ++range) {
-    // found the range
-    if (&pInputSection == range->header) {
-      break;
-    }
-  }
-
-  // range not found
-  if (range == rangeEnd) {
-    fatal(diag::err_section_not_laid_out) << pInputSection.name();
-  }
-
-  return getFragmentRef(*range, pOffset);
-}
-
-/// getFragmentRef - give a fragment and a big offset, return the fragment
-/// reference in the section data.
-///
-/// @param pFrag - the given fragment
-/// @param pBigOffset - the offset, can be larger than the fragment, but can
-///                     not larger than this input section.
-/// @return if found, return the fragment. Otherwise, return NULL.
-FragmentRef*
-Layout::getFragmentRef(const Fragment& pFrag, uint64_t pBigOffset)
-{
-  if (!hasLayoutOffset(pFrag)) {
-    // compute layout order, offset
-    setFragmentLayoutOrder(const_cast<Fragment*>(&pFrag));
-    setFragmentLayoutOffset(const_cast<Fragment*>(&pFrag));
-  }
-
-  // find out which SectionData covers the range of input section header
-  const SectionData* sect_data = pFrag.getParent();
-
-  // check range list
-  if (0 == m_SDRangeMap.count(sect_data)) {
-    llvm::report_fatal_error(llvm::Twine("SectionData has no") +
-                             llvm::Twine(" correponding range list.\n"));
-  }
-
-  if (sect_data->getFragmentList().empty())
-    return NULL;
-
-  RangeList* range_list = m_SDRangeMap[sect_data];
-
-  // find out the specific part in SectionData range
-  uint64_t target_offset = pBigOffset + pFrag.getOffset();
-
-  RangeList::iterator range, rangeEnd = range_list->end();
-  for (range = range_list->begin(); range != rangeEnd; ++range) {
-    if (isEmptyRange(*range))
-      continue;
-    if (getRear(*range)->getOffset() >= target_offset) {
-      break;
-    }
-  }
-
-  // range not found
-  if (range == rangeEnd) {
-    llvm::report_fatal_error(llvm::Twine("the offset is too big that") +
-                             llvm::Twine(" never be in the range list.\n"));
-  }
-
-  return getFragmentRef(*range, pBigOffset);
-}
-
-uint64_t Layout::getOutputOffset(const Fragment& pFrag)
-{
-  if (!hasLayoutOffset(pFrag)) {
-    // compute layout order, offset
-    setFragmentLayoutOrder(const_cast<Fragment*>(&pFrag));
-    setFragmentLayoutOffset(const_cast<Fragment*>(&pFrag));
-  }
-  return pFrag.getOffset();
-}
-
-uint64_t Layout::getOutputOffset(const Fragment& pFrag) const
-{
-  if (!hasLayoutOffset(pFrag)) {
-    llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
-                             llvm::Twine("the function ") +
-                             llvm::Twine(__func__) +
-                             llvm::Twine(" can not be used before layout().\n"));
-  }
-  return pFrag.getOffset();
-}
-
-uint64_t Layout::getOutputOffset(const FragmentRef& pFragRef)
-{
-  return getOutputOffset(*(pFragRef.frag())) + pFragRef.offset();
-}
-
-uint64_t Layout::getOutputOffset(const FragmentRef& pFragRef) const
-{
-  return getOutputOffset(*(pFragRef.frag())) + pFragRef.offset();
-}
-
-void Layout::sortSectionOrder(const Output& pOutput,
-                              const TargetLDBackend& pBackend,
-                              const MCLDInfo& pInfo)
+void Layout::sortSectionOrder(const TargetLDBackend& pBackend,
+                              const LinkerConfig& pConfig)
 {
   typedef std::pair<LDSection*, unsigned int> SectOrder;
   typedef std::vector<SectOrder > SectListTy;
   SectListTy sect_list;
   // get section order from backend
-  for (size_t index = 0; index < m_SectionOrder.size(); ++index)
-    sect_list.push_back(std::make_pair(
+  for (size_t index = 0; index < m_SectionOrder.size(); ++index) {
+    sect_list.push_back(
+            std::make_pair(
                     m_SectionOrder[index],
-                    pBackend.getSectionOrder(pOutput, *m_SectionOrder[index], pInfo)));
+                    pBackend.getSectionOrder(*m_SectionOrder[index])
+            ));
+  }
 
   // simple insertion sort should be fine for general cases such as so and exec
   for (unsigned int i = 1; i < sect_list.size(); ++i) {
@@ -547,21 +58,24 @@
 ///   1. finalize fragment offset
 ///   2. compute section order
 ///   3. finalize section offset
-bool Layout::layout(Output& pOutput,
+bool Layout::layout(Module& pModule,
                     const TargetLDBackend& pBackend,
-                    const MCLDInfo& pInfo)
+                    const LinkerConfig& pConfig)
 {
   // determine what sections in output context will go into final output, and
   // push the needed sections into m_SectionOrder for later processing
-  assert(pOutput.hasContext());
-  LDContext& output_context = *pOutput.context();
-  LDContext::sect_iterator it, itEnd = output_context.sectEnd();
-  for (it = output_context.sectBegin(); it != itEnd; ++it) {
+  Module::iterator it, itEnd = pModule.end();
+  for (it = pModule.begin(); it != itEnd; ++it) {
     // calculate 1. all fragment offset, and 2. the section order
     LDSection* sect = *it;
 
     switch (sect->kind()) {
-      // ignore if there is no SectionData for certain section kinds
+      // take NULL and StackNote directly
+      case LDFileFormat::Null:
+      case LDFileFormat::StackNote:
+        m_SectionOrder.push_back(sect);
+        break;
+      // ignore if section size is 0
       case LDFileFormat::Regular:
       case LDFileFormat::Target:
       case LDFileFormat::MetaData:
@@ -569,31 +83,16 @@
       case LDFileFormat::Debug:
       case LDFileFormat::EhFrame:
       case LDFileFormat::GCCExceptTable:
-        if (0 != sect->size()) {
-          if (NULL != sect->getSectionData() &&
-              !sect->getSectionData()->getFragmentList().empty()) {
-            // make sure that all fragments are valid
-            Fragment& frag = sect->getSectionData()->getFragmentList().back();
-            setFragmentLayoutOrder(&frag);
-            setFragmentLayoutOffset(&frag);
-          }
-          m_SectionOrder.push_back(sect);
-        }
-        break;
-      // take NULL directly
-      case LDFileFormat::Null:
-        m_SectionOrder.push_back(sect);
-        break;
-      // ignore if section size is 0
       case LDFileFormat::NamePool:
       case LDFileFormat::Relocation:
       case LDFileFormat::Note:
       case LDFileFormat::EhFrameHdr:
-        if (0 != sect->size())
+        if (0 != sect->size()) {
           m_SectionOrder.push_back(sect);
+        }
         break;
       case LDFileFormat::Group:
-        if (MCLDFile::Object == pOutput.type()) {
+        if (LinkerConfig::Object == pConfig.codeGenType()) {
           //TODO: support incremental linking
           ;
         }
@@ -610,17 +109,19 @@
         }
         break;
     }
-  }
+  } // end of for
 
   // perform sorting on m_SectionOrder to get a ordering for final layout
-  sortSectionOrder(pOutput, pBackend, pInfo);
+  sortSectionOrder(pBackend, pConfig);
 
   // Backend defines the section start offset for section 1.
   uint64_t offset = pBackend.sectionStartOffset();
 
+  // compute the section offset and handle alignment also. And ignore section 0
+  // (NULL in ELF/COFF), and MachO starts from section 1.
+  // always set NULL section's offset to 0
+  m_SectionOrder[0]->setOffset(0);
   for (size_t index = 1; index < m_SectionOrder.size(); ++index) {
-    // compute the section offset and handle alignment also. And ignore section 0
-    // (NULL in ELF/COFF), and MachO starts from section 1.
 
     if (LDFileFormat::BSS != m_SectionOrder[index - 1]->kind()) {
       // we should not preserve file space for the BSS section.
@@ -633,24 +134,12 @@
 
   // FIXME: Currently Writer bases on the section table in output context to
   // write out sections, so we have to update its content..
-  output_context.getSectionTable().clear();
+  pModule.getSectionTable().clear();
   for (size_t index = 0; index < m_SectionOrder.size(); ++index) {
-    output_context.getSectionTable().push_back(m_SectionOrder[index]);
+    pModule.getSectionTable().push_back(m_SectionOrder[index]);
     // after sorting, update the correct output section indices
     m_SectionOrder[index]->setIndex(index);
   }
   return true;
 }
 
-bool Layout::isValidOffset(const Fragment& pFrag, uint64_t pTargetOffset) const
-{
-  uint64_t size = computeFragmentSize(*this, pFrag);
-  if (0x0 == size)
-    return (pTargetOffset == pFrag.getOffset());
-
-  if (NULL != pFrag.getNextNode())
-    return (pTargetOffset >= pFrag.getOffset() && pTargetOffset < pFrag.getNextNode()->getOffset());
-
-  return (pTargetOffset >= pFrag.getOffset() && pTargetOffset < (pFrag.getOffset() + size));
-}
-
diff --git a/lib/LD/NamePool.cpp b/lib/LD/NamePool.cpp
index 1247057..9e4755d 100644
--- a/lib/LD/NamePool.cpp
+++ b/lib/LD/NamePool.cpp
@@ -8,30 +8,32 @@
 //===----------------------------------------------------------------------===//
 #include <llvm/Support/raw_ostream.h>
 #include <mcld/LD/NamePool.h>
-#include <mcld/LD/Resolver.h>
+#include <mcld/LD/StaticResolver.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // NamePool
-NamePool::NamePool(const Resolver& pResolver, NamePool::size_type pSize)
-  : m_pResolver(&pResolver), m_Table(pSize) {
+//===----------------------------------------------------------------------===//
+NamePool::NamePool(NamePool::size_type pSize)
+  : m_pResolver(new StaticResolver()), m_Table(pSize) {
 }
 
 NamePool::~NamePool()
 {
+  delete m_pResolver;
 }
 
 /// createSymbol - create a symbol
 ResolveInfo* NamePool::createSymbol(const llvm::StringRef& pName,
-                                      bool pIsDyn,
-                                      ResolveInfo::Type pType,
-                                      ResolveInfo::Desc pDesc,
-                                      ResolveInfo::Binding pBinding,
-                                      ResolveInfo::SizeType pSize,
-                                      ResolveInfo::Visibility pVisibility)
+                                    bool pIsDyn,
+                                    ResolveInfo::Type pType,
+                                    ResolveInfo::Desc pDesc,
+                                    ResolveInfo::Binding pBinding,
+                                    ResolveInfo::SizeType pSize,
+                                    ResolveInfo::Visibility pVisibility)
 {
-  ResolveInfo* result = m_Table.getEntryFactory().produce(pName);
+  ResolveInfo* result = ResolveInfo::Create(pName);
   result->setIsSymbol(true);
   result->setSource(pIsDyn);
   result->setType(pType);
diff --git a/lib/LD/RelocData.cpp b/lib/LD/RelocData.cpp
new file mode 100644
index 0000000..92192e6
--- /dev/null
+++ b/lib/LD/RelocData.cpp
@@ -0,0 +1,39 @@
+//===- RelocData.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/RelocData.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// RelocData
+//===----------------------------------------------------------------------===//
+RelocData::RelocData()
+  : m_pSection(NULL) {
+}
+
+RelocData::RelocData(const LDSection &pSection)
+  : m_pSection(&pSection) {
+}
+
+RelocData* RelocData::Create(const LDSection& pSection)
+{
+  return new RelocData(pSection);
+}
+
+RelocData* RelocData::Create()
+{
+  return new RelocData();
+}
+
+void RelocData::Destroy(RelocData*& pSection)
+{
+  delete pSection;
+  pSection = NULL;
+}
+
diff --git a/lib/LD/RelocationFactory.cpp b/lib/LD/RelocationFactory.cpp
index 828acb2..6fb6cb2 100644
--- a/lib/LD/RelocationFactory.cpp
+++ b/lib/LD/RelocationFactory.cpp
@@ -24,7 +24,7 @@
 //===----------------------------------------------------------------------===//
 RelocationFactory::RelocationFactory(size_t pNum)
   : GCFactory<Relocation, 0>(pNum),
-    m_pLayout(NULL) {
+    m_pLinker(NULL) {
 }
 
 RelocationFactory::~RelocationFactory()
@@ -83,14 +83,19 @@
    /** GCFactory will recycle the relocation **/
 }
 
-void RelocationFactory::setLayout(const Layout& pLayout)
+void RelocationFactory::setFragmentLinker(const FragmentLinker& pLinker)
 {
-  m_pLayout = &pLayout;
+  m_pLinker = &pLinker;
 }
 
-const Layout& RelocationFactory::getLayout() const
+const FragmentLinker& RelocationFactory::getFragmentLinker() const
 {
-  assert(0 != m_pLayout);
-  return *m_pLayout;
+  assert(NULL != m_pLinker);
+  return *m_pLinker;
+}
+
+bool RelocationFactory::hasFragmentLinker() const
+{
+  return (NULL != m_pLinker);
 }
 
diff --git a/lib/LD/ResolveInfo.cpp b/lib/LD/ResolveInfo.cpp
index b931d19..00df6ae 100644
--- a/lib/LD/ResolveInfo.cpp
+++ b/lib/LD/ResolveInfo.cpp
@@ -6,13 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/LD/ResolveInfo.h"
+#include <mcld/LD/ResolveInfo.h>
+#include <cstdlib>
 #include <cstring>
 
 using namespace mcld;
 
-//==========================
+/// g_NullResolveInfo - a pointer to Null ResolveInfo.
+static ResolveInfo* g_NullResolveInfo = NULL;
+
+//===----------------------------------------------------------------------===//
 // ResolveInfo
+//===----------------------------------------------------------------------===//
 ResolveInfo::ResolveInfo()
   : m_Size(0), m_BitField(0) {
   m_Ptr.sym_ptr = 0;
@@ -128,6 +133,11 @@
     m_BitField &= ~symbol_flag;
 }
 
+bool ResolveInfo::isNull() const
+{
+  return (this == Null());
+}
+
 bool ResolveInfo::isDyn() const
 {
   return (dynamic_flag == (m_BitField & DYN_MASK));
@@ -226,3 +236,46 @@
   return (0 == std::memcmp(m_Name, pKey.data(), length));
 }
 
+//===----------------------------------------------------------------------===//
+// ResolveInfo Factory Methods
+//===----------------------------------------------------------------------===//
+ResolveInfo* ResolveInfo::Create(const ResolveInfo::key_type& pKey)
+{
+  ResolveInfo* result = static_cast<ResolveInfo*>(
+                          malloc(sizeof(ResolveInfo)+pKey.size()+1));
+  if (NULL == result)
+    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;
+}
+
+void ResolveInfo::Destroy(ResolveInfo*& pInfo)
+{
+  if (pInfo->isNull())
+    return;
+
+  if (NULL != pInfo) {
+    pInfo->~ResolveInfo();
+    free(pInfo);
+  }
+
+  pInfo = NULL;
+}
+
+ResolveInfo* ResolveInfo::Null()
+{
+  if (NULL == g_NullResolveInfo) {
+    g_NullResolveInfo = static_cast<ResolveInfo*>(
+                          malloc(sizeof(ResolveInfo) + 1));
+    new (g_NullResolveInfo) ResolveInfo();
+    g_NullResolveInfo->m_Name[0] = '\0';
+    g_NullResolveInfo->m_BitField = 0x0;
+  }
+  return g_NullResolveInfo;
+}
+
diff --git a/lib/LD/ResolveInfoFactory.cpp b/lib/LD/ResolveInfoFactory.cpp
deleted file mode 100644
index feb52a3..0000000
--- a/lib/LD/ResolveInfoFactory.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- ResolveInfoFactory.cpp ---------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/ResolveInfoFactory.h"
-#include <cstring>
-#include <cstdlib>
-
-using namespace mcld;
-
-//==========================
-// ResolveInfoFactory
-ResolveInfoFactory::entry_type*
-ResolveInfoFactory::produce(const ResolveInfoFactory::key_type& pKey)
-{
-  entry_type* result = static_cast<entry_type*>(
-                                    malloc(sizeof(entry_type)+pKey.size()+1));
-  if (NULL == result)
-    return NULL;
-
-  new (result) entry_type();
-  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;
-}
-
-void ResolveInfoFactory::destroy(ResolveInfoFactory::entry_type* pEntry)
-{
-  if (NULL != pEntry) {
-    pEntry->~entry_type();
-    free(pEntry);
-  }
-}
-
diff --git a/lib/LD/SectionData.cpp b/lib/LD/SectionData.cpp
index d1858ba..43800ff 100644
--- a/lib/LD/SectionData.cpp
+++ b/lib/LD/SectionData.cpp
@@ -7,13 +7,40 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/SectionData.h>
+
 #include <mcld/LD/LDSection.h>
+#include <mcld/Support/GCFactory.h>
+
+#include <llvm/Support/ManagedStatic.h>
 
 using namespace mcld;
 
+typedef GCFactory<SectionData, MCLD_SECTIONS_PER_INPUT> SectDataFactory;
+
+static llvm::ManagedStatic<SectDataFactory> g_SectDataFactory;
+
 //===----------------------------------------------------------------------===//
 // SectionData
 //===----------------------------------------------------------------------===//
-SectionData::SectionData(const LDSection &pSection)
-  : m_pSection(&pSection), m_Alignment(1) {
+SectionData::SectionData()
+  : m_pSection(NULL) {
 }
+
+SectionData::SectionData(LDSection &pSection)
+  : m_pSection(&pSection) {
+}
+
+SectionData* SectionData::Create(LDSection& pSection)
+{
+  SectionData* result = g_SectDataFactory->allocate();
+  new (result) SectionData(pSection);
+  return result;
+}
+
+void SectionData::Destroy(SectionData*& pSection)
+{
+  pSection->~SectionData();
+  g_SectDataFactory->deallocate(pSection);
+  pSection = NULL;
+}
+
diff --git a/lib/LD/SectionMap.cpp b/lib/LD/SectionMap.cpp
deleted file mode 100644
index 7bcd809..0000000
--- a/lib/LD/SectionMap.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-//===- SectionMap.cpp -----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <cassert>
-#include <cstring>
-#include <mcld/LD/SectionMap.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// SectionMap
-SectionMap::SectionMap()
-{
-}
-
-SectionMap::~SectionMap()
-{
-}
-
-const std::string& SectionMap::getOutputSectName(const std::string& pInput)
-{
-  iterator it;
-  for (it = begin(); it != end(); ++it) {
-    if (0 == strncmp(pInput.c_str(),
-                     (*it).inputSubStr.c_str(),
-                     (*it).inputSubStr.length()))
-      break;
-    // wildcard to a user-defined output section.
-    else if (0 == strcmp("*", (*it).inputSubStr.c_str()))
-      break;
-  }
-  // if still no matching, just let a output seciton has the same input name
-  if (it == end())
-    return pInput;
-  return (*it).outputStr;
-}
-
-bool SectionMap::push_back(const std::string& pInput,
-                           const std::string& pOutput)
-{
-  // Now only check if the mapping exists in the map already
-  // TODO: handle the cases such as overriding the exist mapping and drawing
-  //       exception from the given SECTIONS command
-  iterator it;
-  for (it = m_SectMap.begin(); it != m_SectMap.end(); ++it) {
-    if (pInput == (*it).inputSubStr)
-      return false;
-  }
-  struct Mapping mapping = {
-    pInput,
-    pOutput,
-  };
-  m_SectMap.push_back(mapping);
-  return true;
-}
-
-SectionMap::iterator SectionMap::find(const std::string& pInput)
-{
-  iterator it;
-  for (it = begin(); it != end(); ++it) {
-    if(pInput == (*it).inputSubStr)
-      break;
-  }
-  return it;
-}
-
-SectionMap::Mapping* SectionMap::at(const std::string& pInput)
-{
-  iterator it;
-  for (it = begin(); it != end(); ++it) {
-    if(pInput == (*it).inputSubStr)
-      break;
-  }
-  if (end() == it)
-    return NULL;
-  return &(*it);
-}
-
-// Common mappings of ELF and other formants. Now only ELF specific mappings are added
-const SectionMap::SectionNameMapping SectionMap::m_StdSectionMap[] =
-{
-  {".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"},
-  {".sdata", ".sdata"},
-  {".sbss", ".sbss"},
-  // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
-  // sections would be handled differently.
-  {".sdata2", ".sdata"},
-  {".sbss2", ".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.t", ".text"},
-  {".gnu.linkonce.r", ".rodata"},
-  {".gnu.linkonce.d", ".data"},
-  {".gnu.linkonce.b", ".bss"},
-  {".gnu.linkonce.s", ".sdata"},
-  {".gnu.linkonce.sb", ".sbss"},
-  {".gnu.linkonce.s2", ".sdata"},
-  {".gnu.linkonce.sb2", ".sbss"},
-  {".gnu.linkonce.wi", ".debug_info"},
-  {".gnu.linkonce.td", ".tdata"},
-  {".gnu.linkonce.tb", ".tbss"},
-  {".gnu.linkonce.lr", ".lrodata"},
-  {".gnu.linkonce.l", ".ldata"},
-  {".gnu.linkonce.lb", ".lbss"},
-};
-
-const int SectionMap::m_StdSectionMapSize =
-  (sizeof(SectionMap::m_StdSectionMap) / sizeof(SectionMap::m_StdSectionMap[0]));
-
-bool SectionMap::initStdSectionMap()
-{
-  for (int i = 0; i < m_StdSectionMapSize; ++i) {
-    struct Mapping mapping = { m_StdSectionMap[i].from, m_StdSectionMap[i].to};
-    m_SectMap.push_back(mapping);
-  }
-  return true;
-}
diff --git a/lib/LD/SectionMerger.cpp b/lib/LD/SectionMerger.cpp
deleted file mode 100644
index 1817e0b..0000000
--- a/lib/LD/SectionMerger.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- SectionMerger.cpp --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <cassert>
-#include <cstring>
-#include <mcld/LD/SectionMerger.h>
-
-using namespace mcld;
-
-//==========================
-// SectionMerger
-
-SectionMerger::SectionMerger(SectionMap& pSectionMap, LDContext& pContext)
-: m_SectionNameMap(pSectionMap),
-  m_Output(pContext),
-  m_LDSectionMap()
-{
-}
-
-SectionMerger::~SectionMerger()
-{
-}
-
-SectionMerger::iterator SectionMerger::find(const std::string& pName)
-{
-  if (empty())
-    initOutputSectMap();
-
-  iterator it;
-  for (it = begin(); it != end(); ++it) {
-    if (0 == strncmp(pName.c_str(),
-                     (*it).inputSubStr.c_str(),
-                     (*it).inputSubStr.length()))
-      break;
-    // wildcard to a user-defined output section.
-    else if(0 == strcmp("*", (*it).inputSubStr.c_str()))
-      break;
-  }
-  return it;
-}
-
-LDSection* SectionMerger::getOutputSectHdr(const std::string& pName)
-{
-  LDSection* section;
-  iterator it = find(pName);
-
-  // check if we can find a matched LDSection.
-  // If not, we need to find it in output context. But this should be rare.
-  if (it != end())
-    section = (*it).outputSection;
-  else
-    section = m_Output.getSection(pName);
-
-  assert(NULL != section);
-  return section;
-}
-
-SectionData* SectionMerger::getOutputSectData(const std::string& pName)
-{
-  return getOutputSectHdr(pName)->getSectionData();
-}
-
-bool SectionMerger::addMapping(const std::string& pName, LDSection* pSection)
-{
-  iterator it = find(pName);
-  if (it != end()) {
-    assert(NULL == (*it).outputSection);
-    (*it).outputSection = pSection;
-    return true;
-  }
-  // the mapping rule is not in SectionMap, and this is handled in getOutputSectHdr.
-  return false;
-}
-
-void SectionMerger::initOutputSectMap()
-{
-  // Based on SectionMap to initialize the map from a input substr to its 
-  // associated output LDSection*
-  SectionMap::iterator it;
-  for (it = m_SectionNameMap.begin(); it != m_SectionNameMap.end(); ++it) {
-    struct Mapping mapping = {
-      (*it).inputSubStr,
-      NULL,
-    };
-    m_LDSectionMap.push_back(mapping);
-  }
-  assert(m_SectionNameMap.size() == m_LDSectionMap.size());
-}
diff --git a/lib/LD/SectionRules.cpp b/lib/LD/SectionRules.cpp
new file mode 100644
index 0000000..08c3478
--- /dev/null
+++ b/lib/LD/SectionRules.cpp
@@ -0,0 +1,111 @@
+//===- SectionRules.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/SectionRules.h>
+
+#include <cassert>
+#include <cstring>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Object/SectionMap.h>
+#include <mcld/ADT/StringHash.h>
+
+using namespace mcld;
+
+namespace {
+  static StringHash<ES> hash_func;
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// SectionRules::Rule
+//===----------------------------------------------------------------------===//
+SectionRules::Rule::Rule(const std::string& pSubStr, LDSection* pSection)
+  : substr(pSubStr), target(pSection) {
+  hash = hash_func(pSubStr);
+}
+
+//===----------------------------------------------------------------------===//
+// SectionRules
+//===----------------------------------------------------------------------===//
+SectionRules::SectionRules(const LinkerConfig& pConfig, Module& pModule)
+  : m_SectionNameMap(pConfig.scripts().sectionMap()),
+    m_Module(pModule) {
+}
+
+SectionRules::~SectionRules()
+{
+}
+
+SectionRules::iterator SectionRules::find(const std::string& pName)
+{
+  uint32_t hash = hash_func(pName);
+  RuleList::iterator rule, rEnd = m_RuleList.end();
+  for (rule = m_RuleList.begin(); rule != rEnd; ++rule) {
+    if (pName.size() < rule->substr.size())
+      continue;
+    if (!StringHash<ES>::may_include(rule->hash, hash))
+      continue;
+
+    if (0 == strncmp(pName.c_str(), rule->substr.c_str(), rule->substr.size()))
+      return rule;
+  }
+  return rule;
+}
+
+SectionRules::const_iterator SectionRules::find(const std::string& pName) const
+{
+  uint32_t hash = hash_func(pName);
+  RuleList::const_iterator rule, rEnd = m_RuleList.end();
+  for (rule = m_RuleList.begin(); rule != rEnd; ++rule) {
+    if (pName.size() < rule->substr.size())
+      continue;
+    if (!StringHash<ES>::may_include(rule->hash, hash))
+      continue;
+
+    if (0 == strncmp(pName.c_str(), rule->substr.c_str(), rule->substr.size()))
+      return rule;
+  }
+  return rule;
+}
+
+LDSection* SectionRules::getMatchedSection(const std::string& pName) const
+{
+  LDSection* section;
+  const_iterator it = find(pName);
+
+  // check if we can find a matched LDSection.
+  // If not, we need to find it in output context. But this should be rare.
+  if (it != m_RuleList.end())
+    section = (*it).target;
+  else
+    section = m_Module.getSection(pName);
+
+  return section;
+}
+
+void SectionRules::append(const std::string& pName, LDSection& pSection)
+{
+  iterator it = find(pName);
+  if (it != m_RuleList.end()) {
+    assert(NULL == (*it).target);
+    (*it).target = &pSection;
+  }
+}
+
+void SectionRules::initOutputSectMap()
+{
+  // Based on SectionMap to initialize the map from a input substr to its 
+  // associated output LDSection*
+  SectionMap::const_iterator it;
+  for (it = m_SectionNameMap.begin(); it != m_SectionNameMap.end(); ++it) {
+    Rule rule(it->from, NULL);
+    m_RuleList.push_back(rule);
+  }
+  assert(m_SectionNameMap.size() == m_RuleList.size());
+}
diff --git a/lib/LD/SectionSymbolSet.cpp b/lib/LD/SectionSymbolSet.cpp
new file mode 100644
index 0000000..79f4d78
--- /dev/null
+++ b/lib/LD/SectionSymbolSet.cpp
@@ -0,0 +1,102 @@
+//===- SectionSymbolSet.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/SectionSymbolSet.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/NamePool.h>
+#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/LD/LDFileFormat.h>
+
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// SectionSymbolSet
+//===----------------------------------------------------------------------===//
+
+SectionSymbolSet::SectionSymbolSet()
+{
+  m_pSectionSymbolMap = new SectHashTableType(16);
+}
+
+SectionSymbolSet::~SectionSymbolSet()
+{
+  delete m_pSectionSymbolMap;
+}
+
+bool SectionSymbolSet::add(LDSection& pOutSect, NamePool& pNamePool)
+{
+  // create the resolveInfo for this section symbol
+  llvm::StringRef sym_name = llvm::StringRef(pOutSect.name());
+  ResolveInfo* sym_info = pNamePool.createSymbol(sym_name,
+                                                 false,
+                                                 ResolveInfo::Section,
+                                                 ResolveInfo::Define,
+                                                 ResolveInfo::Local,
+                                                 0x0, // size
+                                                 ResolveInfo::Default);
+
+  // create the output section symbol and set its fragRef to the first fragment
+  // of the section
+  LDSymbol* sym = LDSymbol::Create(*sym_info);
+  sym_info->setSymPtr(sym);
+
+  // insert the symbol to the Section to Symbol hash map
+  bool exist = false;
+  SectHashTableType::entry_type* entry =
+                            m_pSectionSymbolMap->insert(&pOutSect, exist);
+  assert(!exist);
+  entry->setValue(sym);
+
+  return true;
+}
+
+bool SectionSymbolSet::finalize(LDSection& pOutSect,
+                                SymbolTable& pSymTab)
+{
+  LDSymbol* sym = get(pOutSect);
+  assert(NULL != sym);
+  FragmentRef* frag_ref = NULL;
+  switch (pOutSect.kind()) {
+    case LDFileFormat::Relocation:
+      frag_ref = FragmentRef::Create(pOutSect.getRelocData()->front(), 0x0);
+      break;
+
+    case LDFileFormat::EhFrame:
+      frag_ref = FragmentRef::Create(
+                          pOutSect.getEhFrame()->getSectionData().front(), 0x0);
+      break;
+
+    default:
+      frag_ref = FragmentRef::Create(pOutSect.getSectionData()->front(), 0x0);
+      break;
+  }
+  sym->setFragmentRef(frag_ref);
+  // push symbol into output symbol table
+  pSymTab.add(*sym);
+
+  return true;
+}
+
+LDSymbol* SectionSymbolSet::get(const LDSection& pOutSect)
+{
+  SectHashTableType::iterator entry = m_pSectionSymbolMap->find(&pOutSect);
+  return entry.getEntry()->value();
+}
+
+const LDSymbol* SectionSymbolSet::get(const LDSection& pOutSect) const
+{
+  SectHashTableType::iterator entry = m_pSectionSymbolMap->find(&pOutSect);
+  return entry.getEntry()->value();
+}
+
diff --git a/lib/LD/StubFactory.cpp b/lib/LD/StubFactory.cpp
new file mode 100644
index 0000000..1fc43dd
--- /dev/null
+++ b/lib/LD/StubFactory.cpp
@@ -0,0 +1,128 @@
+//===- StubFactory.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/LD/StubFactory.h>
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/LD/BranchIsland.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Fragment/FragmentRef.h>
+
+#include <string>
+using namespace mcld;
+
+StubFactory::StubFactory()
+{
+}
+
+StubFactory::~StubFactory()
+{
+  for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
+       it != ie; ++it)
+    delete(*it);
+}
+
+/// addPrototype - register a stub prototype
+void StubFactory::addPrototype(Stub* pPrototype)
+{
+  m_StubPool.push_back(pPrototype);
+}
+
+/// create - create a stub if needed, otherwise return NULL
+Stub* StubFactory::create(Relocation& pReloc,
+                          uint64_t pTargetSymValue,
+                          FragmentLinker& pLinker,
+                          RelocationFactory& pRelocFactory,
+                          BranchIslandFactory& pBRIslandFactory)
+{
+  // find if there is a prototype stub for the input relocation
+  Stub* prototype = findPrototype(pReloc,
+                                  pReloc.place(),
+                                  pTargetSymValue);
+  if (NULL != prototype) {
+    // find the island for the input relocation
+    BranchIsland* island = pBRIslandFactory.find(*(pReloc.targetRef().frag()));
+    if (NULL == island) {
+      island = pBRIslandFactory.produce(*(pReloc.targetRef().frag()));
+    }
+
+    // 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!
+      pReloc.setSymInfo(stub->symInfo());
+    }
+    else {
+      // create a stub from the prototype
+      stub = prototype->clone();
+
+      // build a name for stub symbol
+      std::string name("__");
+      name.append(pReloc.symInfo()->name());
+      name.append("_");
+      name.append(stub->name());
+      name.append("@");
+      name.append(island->name());
+
+      // create LDSymbol for the stub
+      LDSymbol* symbol =
+        pLinker.defineSymbol<FragmentLinker::Force,
+                             FragmentLinker::Resolve>(name,
+                               false, // isDyn
+                               ResolveInfo::Function,
+                               ResolveInfo::Define,
+                               ResolveInfo::Local,
+                               stub->size(), // size
+                               stub->initSymValue(), // value
+                               FragmentRef::Create(*stub, stub->initSymValue()),
+                               ResolveInfo::Default);
+      stub->setSymInfo(symbol->resolveInfo());
+
+      // add relocations of this stub (i.e., set the branch target of the stub)
+      for (Stub::fixup_iterator it = stub->fixup_begin(),
+             ie = stub->fixup_end(); it != ie; ++it) {
+
+        Relocation* reloc = pRelocFactory.produce(
+                                 (*it)->type(),
+                                 *(FragmentRef::Create(*stub, (*it)->offset())),
+                                 (*it)->addend());
+        reloc->setSymInfo(pReloc.symInfo());
+        island->addRelocation(*reloc);
+      }
+
+      // add stub to the branch island
+      island->addStub(prototype, pReloc, *stub);
+
+      // reset the branch target of the input reloc to this stub instead!
+      pReloc.setSymInfo(stub->symInfo());
+      return stub;
+    }
+  }
+  return NULL;
+}
+
+/// findPrototype - find if there is a registered stub prototype for the given
+/// relocation
+Stub* StubFactory::findPrototype(const Relocation& pReloc,
+                                 uint64_t pSource,
+                                 uint64_t pTargetSymValue)
+{
+  for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
+       it != ie; ++it) {
+    if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue))
+      return (*it);
+  }
+  return NULL;
+}
+
diff --git a/lib/LD/TextDiagnosticPrinter.cpp b/lib/LD/TextDiagnosticPrinter.cpp
index 466d16d..8860099 100644
--- a/lib/LD/TextDiagnosticPrinter.cpp
+++ b/lib/LD/TextDiagnosticPrinter.cpp
@@ -7,7 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
 #include <llvm/Support/Signals.h>
 #include <string>
 
@@ -27,8 +27,8 @@
 //===----------------------------------------------------------------------===//
 // TextDiagnosticPrinter
 TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream& pOStream,
-                                             const MCLDInfo& pLDInfo)
-  : m_OStream(pOStream), m_LDInfo(pLDInfo), m_pInput(NULL) {
+                                             const LinkerConfig& pConfig)
+  : m_OStream(pOStream), m_Config(pConfig), m_pInput(NULL) {
 }
 
 TextDiagnosticPrinter::~TextDiagnosticPrinter()
@@ -77,7 +77,7 @@
     }
     case DiagnosticEngine::Debug: {
       // show debug message only if verbose >= 0
-      if (0 <= m_LDInfo.options().verbose()) {
+      if (0 <= m_Config.options().verbose()) {
         m_OStream.changeColor(DebugColor, true);
         m_OStream << "Debug: ";
         m_OStream.resetColor();
@@ -87,7 +87,7 @@
     }
     case DiagnosticEngine::Note: {
       // show ignored message only if verbose >= 1
-      if (1 <= m_LDInfo.options().verbose()) {
+      if (1 <= m_Config.options().verbose()) {
         m_OStream.changeColor(NoteColor, true);
         m_OStream << "Note: ";
         m_OStream.resetColor();
@@ -97,7 +97,7 @@
     }
     case DiagnosticEngine::Ignore: {
       // show ignored message only if verbose >= 2
-      if (2 <= m_LDInfo.options().verbose()) {
+      if (2 <= m_Config.options().verbose()) {
         m_OStream.changeColor(IgnoreColor, true);
         m_OStream << "Ignore: ";
         m_OStream.resetColor();
@@ -127,7 +127,7 @@
       break;
     }
     case DiagnosticEngine::Error: {
-      int16_t error_limit = m_LDInfo.options().maxErrorNum();
+      int16_t error_limit = m_Config.options().maxErrorNum();
       if ((error_limit != -1) &&
           (getNumErrors() > static_cast<unsigned>(error_limit))) {
         m_OStream << "\n\n";
@@ -140,7 +140,7 @@
       break;
     }
     case DiagnosticEngine::Warning: {
-      int16_t warning_limit = m_LDInfo.options().maxWarnNum();
+      int16_t warning_limit = m_Config.options().maxWarnNum();
       if ((warning_limit != -1) &&
           (getNumWarnings() > static_cast<unsigned>(warning_limit))) {
         m_OStream << "\n\n";
@@ -156,7 +156,7 @@
   }
 }
 
-void TextDiagnosticPrinter::beginInput(const Input& pInput, const MCLDInfo& pLDInfo)
+void TextDiagnosticPrinter::beginInput(const Input& pInput, const LinkerConfig& pConfig)
 {
   m_pInput = &pInput;
 }
diff --git a/lib/MC/Android.mk b/lib/MC/Android.mk
index 30ca202..0f8911b 100644
--- a/lib/MC/Android.mk
+++ b/lib/MC/Android.mk
@@ -1,19 +1,16 @@
 LOCAL_PATH:= $(call my-dir)
 
 mcld_mc_SRC_FILES := \
-  AttributeFactory.cpp  \
+  Attribute.cpp  \
+  AttributeSet.cpp  \
+  CommandAction.cpp  \
   ContextFactory.cpp  \
+  FileAction.cpp  \
+  InputAction.cpp  \
+  InputBuilder.cpp  \
   InputFactory.cpp  \
-  InputTree.cpp \
-  MCLDAttribute.cpp \
   MCLDDirectory.cpp \
-  MCLDDriver.cpp  \
-  MCLDFile.cpp  \
-  MCLDInfo.cpp  \
   MCLDInput.cpp \
-  MCLDOptions.cpp \
-  MCLDOutput.cpp  \
-  MCLinker.cpp  \
   SearchDirs.cpp  \
   SymbolCategory.cpp  \
   ZOption.cpp
diff --git a/lib/MC/MCLDAttribute.cpp b/lib/MC/Attribute.cpp
similarity index 75%
rename from lib/MC/MCLDAttribute.cpp
rename to lib/MC/Attribute.cpp
index f7b7e47..64782db 100644
--- a/lib/MC/MCLDAttribute.cpp
+++ b/lib/MC/Attribute.cpp
@@ -6,14 +6,15 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLDAttribute.h>
-#include <mcld/MC/AttributeFactory.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/MC/AttributeSet.h>
 #include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // AttrConstraint
+//===----------------------------------------------------------------------===//
 bool AttrConstraint::isLegal(const Attribute& pAttr) const
 {
   if (!isWholeArchive() && pAttr.isWholeArchive()) {
@@ -44,10 +45,13 @@
   return true;
 }
 
-//==========================
+//===----------------------------------------------------------------------===//
 // AttributeProxy
-AttributeProxy::AttributeProxy(AttributeFactory& pParent, Attribute& pBase)
-  : m_AttrPool(pParent), m_pBase(&pBase) {
+//===----------------------------------------------------------------------===//
+AttributeProxy::AttributeProxy(AttributeSet& pParent,
+                               const Attribute& pBase,
+                               const AttrConstraint& pConstraint)
+  : m_AttrPool(pParent), m_pBase(&pBase), m_Constraint(pConstraint) {
 }
 
 AttributeProxy::~AttributeProxy()
@@ -56,7 +60,7 @@
 
 bool AttributeProxy::isWholeArchive() const
 {
-  if (m_AttrPool.constraint().isWholeArchive())
+  if (m_Constraint.isWholeArchive())
     return m_pBase->isWholeArchive();
   else
     return false;
@@ -64,7 +68,7 @@
 
 bool AttributeProxy::isAsNeeded() const
 {
-  if (m_AttrPool.constraint().isAsNeeded())
+  if (m_Constraint.isAsNeeded())
     return m_pBase->isAsNeeded();
   else
     return false;
@@ -72,7 +76,7 @@
 
 bool AttributeProxy::isAddNeeded() const
 {
-  if (m_AttrPool.constraint().isAddNeeded())
+  if (m_Constraint.isAddNeeded())
     return m_pBase->isAddNeeded();
   else
     return false;
@@ -80,7 +84,7 @@
 
 bool AttributeProxy::isStatic() const
 {
-  if (m_AttrPool.constraint().isSharedSystem())
+  if (m_Constraint.isSharedSystem())
     return m_pBase->isStatic();
   else
     return true;
@@ -88,18 +92,18 @@
 
 bool AttributeProxy::isDynamic() const
 {
-  if (m_AttrPool.constraint().isSharedSystem())
+  if (m_Constraint.isSharedSystem())
     return m_pBase->isDynamic();
   else
     return false;
 }
 
-static inline void ReplaceOrRecord(AttributeFactory& pParent,
-                                   Attribute *&pBase,
+static inline void ReplaceOrRecord(AttributeSet& pParent,
+                                   const Attribute *&pBase,
                                    Attribute *&pCopy)
 {
   Attribute *result = pParent.exists(*pCopy);
-  if (0 == result) { // can not find
+  if (NULL == result) { // can not find
     pParent.record(*pCopy);
     pBase = pCopy;
   }
@@ -165,8 +169,9 @@
   ReplaceOrRecord(m_AttrPool, m_pBase, copy);
 }
 
-AttributeProxy* AttributeProxy::clone() const
+AttributeProxy& AttributeProxy::assign(Attribute* pBase)
 {
-  return new AttributeProxy(m_AttrPool, *m_pBase);
+  m_pBase = pBase;
+  return *this;
 }
 
diff --git a/lib/MC/AttributeFactory.cpp b/lib/MC/AttributeFactory.cpp
deleted file mode 100644
index f6f4428..0000000
--- a/lib/MC/AttributeFactory.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-//===- AttributeFactory.cpp -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDAttribute.h"
-#include "mcld/MC/AttributeFactory.h"
-
-using namespace mcld;
-
-//==========================
-// AttributeFactory
-AttributeFactory::AttributeFactory()
-  : m_AttrSet() {
-  m_AttrSet.push_back(new mcld::Attribute());
-  m_pLast = new AttributeProxy(*this, *m_AttrSet.front());
-}
-
-AttributeFactory::AttributeFactory(size_t pNum)
-  : m_AttrSet() {
-  m_AttrSet.reserve(pNum);
-  m_AttrSet.push_back(new mcld::Attribute());
-  m_pLast = new AttributeProxy(*this, *m_AttrSet.front());
-}
-
-AttributeFactory::~AttributeFactory()
-{
-  iterator cur = m_AttrSet.begin();
-  iterator aEnd = m_AttrSet.end();
-  while(cur != aEnd) {
-    delete (*cur);
-    ++cur;
-  }
-  m_AttrSet.clear();
-  delete m_pLast;
-}
-
-void AttributeFactory::reserve(size_t pNum)
-{
-  m_AttrSet.reserve(pNum);
-}
-
-Attribute &AttributeFactory::predefined()
-{
-  return *m_AttrSet.front();
-}
-
-const Attribute &AttributeFactory::predefined() const
-{
-  return *m_AttrSet.front();
-}
-
-AttributeProxy* AttributeFactory::produce()
-{
-  m_pLast->change(m_AttrSet.front());
-  return m_pLast->clone();
-}
-
-AttributeProxy& AttributeFactory::last()
-{
-  return *m_pLast;
-}
-
-const AttributeProxy& AttributeFactory::last() const
-{
-  return *m_pLast;
-}
-
-Attribute* AttributeFactory::exists(const Attribute& pAttr) const
-{
-  const_iterator cur = m_AttrSet.begin();
-  const_iterator aEnd = m_AttrSet.end();
-  while(cur != aEnd) {
-    if (*(*cur) == pAttr) {
-      m_pLast->change(*cur);
-      return *cur;
-    }
-    ++cur;
-  }
-  return 0;
-}
-
-void AttributeFactory::record(mcld::Attribute &pAttr)
-{
-  m_AttrSet.push_back(&pAttr);
-  m_pLast->change(m_AttrSet.back());
-}
-
diff --git a/lib/MC/AttributeSet.cpp b/lib/MC/AttributeSet.cpp
new file mode 100644
index 0000000..e657207
--- /dev/null
+++ b/lib/MC/AttributeSet.cpp
@@ -0,0 +1,54 @@
+//===- AttributeSet.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/Attribute.h>
+#include <mcld/MC/AttributeSet.h>
+#include <cstddef>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// AttributeSet
+//===----------------------------------------------------------------------===//
+AttributeSet::AttributeSet(unsigned int pNum, const Attribute& pPredefined)
+  : m_AttrSet(), m_Predefined(pPredefined) {
+  m_AttrSet.reserve(pNum);
+}
+
+AttributeSet::~AttributeSet()
+{
+  iterator cur = m_AttrSet.begin();
+  iterator aEnd = m_AttrSet.end();
+
+  while(cur != aEnd) {
+    delete (*cur);
+    ++cur;
+  }
+}
+
+Attribute* AttributeSet::exists(const Attribute& pAttr) const
+{
+  if (m_Predefined == pAttr)
+    return const_cast<Attribute*>(&m_Predefined);
+
+  const_iterator cur = m_AttrSet.begin();
+  const_iterator aEnd = m_AttrSet.end();
+  while(cur != aEnd) {
+    if (*(*cur) == pAttr) {
+      return *cur;
+    }
+    ++cur;
+  }
+  return NULL;
+}
+
+void AttributeSet::record(mcld::Attribute &pAttr)
+{
+  m_AttrSet.push_back(&pAttr);
+}
+
diff --git a/lib/MC/CommandAction.cpp b/lib/MC/CommandAction.cpp
new file mode 100644
index 0000000..91b5904
--- /dev/null
+++ b/lib/MC/CommandAction.cpp
@@ -0,0 +1,220 @@
+//===- CommandAction.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/CommandAction.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/SearchDirs.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Derived Positional Option
+//===----------------------------------------------------------------------===//
+// InputFileAction
+//===----------------------------------------------------------------------===//
+InputFileAction::InputFileAction(unsigned int pPosition,
+                                 const sys::fs::Path &pPath)
+  : InputAction(pPosition), m_Path(pPath) {
+}
+
+bool InputFileAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.createNode<InputTree::Positional>(path().stem().native(), path());
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// NamespecAction
+//===----------------------------------------------------------------------===//
+NamespecAction::NamespecAction(unsigned int pPosition,
+                               const std::string &pNamespec,
+                               SearchDirs& pSearchDirs)
+  : InputAction(pPosition), m_Namespec(pNamespec), m_SearchDirs(pSearchDirs) {
+}
+
+bool NamespecAction::activate(InputBuilder& pBuilder) 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
+    // and shared object.
+
+    if (pBuilder.getAttributes().isStatic()) {
+      // with --static, we must search an archive.
+      path = m_SearchDirs.find(namespec(), Input::Archive);
+    }
+    else {
+      // otherwise, with --Bdynamic, we can find either an archive or a
+      // shared object.
+      path = m_SearchDirs.find(namespec(), Input::DynObj);
+    }
+  }
+  else {
+    // In the system without shared object support, we only look for an archive
+    path = m_SearchDirs.find(namespec(), Input::Archive);
+  }
+
+  if (NULL == path) {
+    fatal(diag::err_cannot_find_namespec) << namespec();
+    return false;
+  }
+
+  pBuilder.createNode<InputTree::Positional>(namespec(), *path);
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// BitcodeAction
+//===----------------------------------------------------------------------===//
+BitcodeAction::BitcodeAction(unsigned int pPosition, const sys::fs::Path &pPath)
+  : InputAction(pPosition), m_Path(pPath) {
+}
+
+bool BitcodeAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.createNode<InputTree::Positional>("bitcode", path(), Input::External);
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// StartGroupAction
+//===----------------------------------------------------------------------===//
+StartGroupAction::StartGroupAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool StartGroupAction::activate(InputBuilder& pBuilder) const
+{
+  if (pBuilder.isInGroup()) {
+    fatal(diag::fatal_forbid_nest_group);
+    return false;
+  }
+  pBuilder.enterGroup();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// EndGroupAction
+//===----------------------------------------------------------------------===//
+EndGroupAction::EndGroupAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool EndGroupAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.exitGroup();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// WholeArchiveAction
+//===----------------------------------------------------------------------===//
+WholeArchiveAction::WholeArchiveAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool WholeArchiveAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.getAttributes().setWholeArchive();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// NoWholeArchiveAction
+//===----------------------------------------------------------------------===//
+NoWholeArchiveAction::NoWholeArchiveAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool NoWholeArchiveAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.getAttributes().unsetWholeArchive();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// AsNeededAction
+//===----------------------------------------------------------------------===//
+AsNeededAction::AsNeededAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool AsNeededAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.getAttributes().setAsNeeded();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// NoAsNeededAction
+//===----------------------------------------------------------------------===//
+NoAsNeededAction::NoAsNeededAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool NoAsNeededAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.getAttributes().unsetAsNeeded();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// AddNeededAction
+//===----------------------------------------------------------------------===//
+AddNeededAction::AddNeededAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool AddNeededAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.getAttributes().setAddNeeded();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// NoAddNeededAction
+//===----------------------------------------------------------------------===//
+NoAddNeededAction::NoAddNeededAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool NoAddNeededAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.getAttributes().unsetAddNeeded();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// BDynamicAction
+//===----------------------------------------------------------------------===//
+BDynamicAction::BDynamicAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool BDynamicAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.getAttributes().setDynamic();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// BStaticAction
+//===----------------------------------------------------------------------===//
+BStaticAction::BStaticAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool BStaticAction::activate(InputBuilder& pBuilder) const
+{
+  pBuilder.getAttributes().setStatic();
+  return true;
+}
+
diff --git a/lib/MC/FileAction.cpp b/lib/MC/FileAction.cpp
new file mode 100644
index 0000000..8660558
--- /dev/null
+++ b/lib/MC/FileAction.cpp
@@ -0,0 +1,66 @@
+//===- FileAction.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/FileAction.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/ContextFactory.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ContextAction
+//===----------------------------------------------------------------------===//
+ContextAction::ContextAction(unsigned int pPosition)
+  : InputAction(pPosition) {
+}
+
+bool ContextAction::activate(InputBuilder& pBuilder) const
+{
+  Input* input = *pBuilder.getCurrentNode();
+
+  if (input->hasContext())
+    return false;
+
+  // already got type - for example, bitcode
+  if (input->type() == Input::Script ||
+      input->type() == Input::Object ||
+      input->type() == Input::DynObj  ||
+      input->type() == Input::Archive)
+    return false;
+
+  return pBuilder.setContext(*input);
+}
+
+//===----------------------------------------------------------------------===//
+// MemoryAreaAction 
+//===----------------------------------------------------------------------===//
+MemoryAreaAction::MemoryAreaAction(unsigned int pPosition,
+                                   FileHandle::OpenMode pMode,
+                                   FileHandle::Permission pPerm)
+  : InputAction(pPosition), m_Mode(pMode), m_Permission(pPerm) {
+}
+
+bool MemoryAreaAction::activate(InputBuilder& pBuilder) const
+{
+  Input* input = *pBuilder.getCurrentNode();
+
+  if (input->hasMemArea())
+    return false;
+
+  // already got type - for example, bitcode
+  if (input->type() == Input::Script ||
+      input->type() == Input::Object ||
+      input->type() == Input::DynObj  ||
+      input->type() == Input::Archive)
+    return false;
+
+  return pBuilder.setMemory(*input, m_Mode, m_Permission);
+}
+
diff --git a/lib/LD/CIE.cpp b/lib/MC/InputAction.cpp
similarity index 64%
rename from lib/LD/CIE.cpp
rename to lib/MC/InputAction.cpp
index 5ddb166..f9078c6 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/MC/InputAction.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- InputAction.cpp ----------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,18 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/MC/InputAction.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// CIE
+// Base Positional Option
 //===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
-  : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+InputAction::InputAction(unsigned int pPosition)
+  : m_Position(pPosition) {
 }
 
-CIE::~CIE()
+InputAction::~InputAction()
 {
 }
+
diff --git a/lib/MC/InputBuilder.cpp b/lib/MC/InputBuilder.cpp
new file mode 100644
index 0000000..9142801
--- /dev/null
+++ b/lib/MC/InputBuilder.cpp
@@ -0,0 +1,163 @@
+//===- InputBuilder.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/InputBuilder.h>
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/Config/Config.h>
+#include <mcld/Support/Path.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/MC/ContextFactory.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+
+using namespace mcld;
+
+InputBuilder::InputBuilder(const LinkerConfig& pConfig)
+  : m_Config(pConfig),
+    m_pCurrentTree(NULL), m_pMove(NULL), m_Root(),
+    m_bOwnFactory(true) {
+
+    m_pInputFactory = new InputFactory(MCLD_NUM_OF_INPUTS, pConfig);
+    m_pContextFactory = new ContextFactory(MCLD_NUM_OF_INPUTS);
+    m_pMemFactory = new MemoryAreaFactory(MCLD_NUM_OF_INPUTS);
+}
+
+InputBuilder::InputBuilder(const LinkerConfig& pConfig,
+                           InputFactory& pInputFactory,
+                           ContextFactory& pContextFactory,
+                           MemoryAreaFactory& pMemoryFactory,
+                           bool pDelegate)
+  : m_Config(pConfig),
+    m_pInputFactory(&pInputFactory),
+    m_pMemFactory(&pMemoryFactory),
+    m_pContextFactory(&pContextFactory),
+    m_pCurrentTree(NULL), m_pMove(NULL), m_Root(),
+    m_bOwnFactory(pDelegate) {
+
+}
+
+InputBuilder::~InputBuilder()
+{
+  if (m_bOwnFactory) {
+    delete m_pInputFactory;
+    delete m_pContextFactory;
+    delete m_pMemFactory;
+  }
+}
+
+Input* InputBuilder::createInput(const std::string& pName,
+                                 const sys::fs::Path& pPath,
+                                 unsigned int pType,
+                                 off_t pFileOffset)
+{
+  return m_pInputFactory->produce(pName, pPath, pType, pFileOffset);
+}
+
+InputTree& InputBuilder::enterGroup()
+{
+  assert(NULL != m_pCurrentTree && NULL != m_pMove);
+
+  m_pCurrentTree->enterGroup(m_Root, *m_pMove);
+  m_pMove->move(m_Root);
+  m_ReturnStack.push(m_Root);
+  m_pMove = &InputTree::Downward;
+
+  return *m_pCurrentTree;
+}
+
+InputTree& InputBuilder::exitGroup()
+{
+  assert(NULL != m_pCurrentTree && NULL != m_pMove);
+
+  m_Root = m_ReturnStack.top();
+  m_ReturnStack.pop();
+  m_pMove = &InputTree::Afterward;
+
+  return *m_pCurrentTree;
+}
+
+bool InputBuilder::isInGroup() const
+{
+  return !m_ReturnStack.empty();
+}
+
+const InputTree& InputBuilder::getCurrentTree() const
+{
+  assert(NULL != m_pCurrentTree && NULL != m_pMove);
+  return *m_pCurrentTree;
+}
+
+InputTree& InputBuilder::getCurrentTree()
+{
+  assert(NULL != m_pCurrentTree && NULL != m_pMove);
+  return *m_pCurrentTree;
+}
+
+void InputBuilder::setCurrentTree(InputTree& pInputTree)
+{
+  m_pCurrentTree = &pInputTree;
+  m_Root = m_pCurrentTree->root();
+  m_pMove = &InputTree::Downward;
+}
+
+bool InputBuilder::setContext(Input& pInput, bool pCheck)
+{
+  // The object files in an archive have common path. Every object files in an
+  // archive needs a individual context. We identify the object files in an
+  // archive by its file offset. Their file offsets are not zero.
+  LDContext* context = NULL;
+  if (0 != pInput.fileOffset() || !pCheck) {
+    // pInput is an object in an archive file. Produce a new context in this
+    // case.
+    context = m_pContextFactory->produce();
+  }
+  else {
+    // Using pInput.path() to avoid from creating context for identical file
+    // twice.
+    context = m_pContextFactory->produce(pInput.path());
+  }
+
+  pInput.setContext(context);
+  return true;
+}
+
+bool InputBuilder::setMemory(Input& pInput,
+                             FileHandle::OpenMode pMode,
+                             FileHandle::Permission pPerm)
+{
+  MemoryArea *memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm);
+
+  if (!memory->handler()->isGood())
+    return false;
+
+  pInput.setMemArea(memory);
+  return true;
+}
+
+bool InputBuilder::setMemory(Input& pInput, void* pMemBuffer, size_t pSize)
+{
+  MemoryArea *memory = m_pMemFactory->produce(pMemBuffer, pSize);
+  pInput.setMemArea(memory);
+  return true;
+}
+
+const AttrConstraint& InputBuilder::getConstraint() const
+{
+  return m_Config.attribute().constraint();
+}
+
+const AttributeProxy& InputBuilder::getAttributes() const
+{
+  return m_pInputFactory->attr();
+}
+
+AttributeProxy& InputBuilder::getAttributes()
+{
+  return m_pInputFactory->attr();
+}
+
diff --git a/lib/MC/InputFactory.cpp b/lib/MC/InputFactory.cpp
index d4d9cc2..b0b7aaa 100644
--- a/lib/MC/InputFactory.cpp
+++ b/lib/MC/InputFactory.cpp
@@ -6,19 +6,29 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/InputFactory.h"
-#include "mcld/MC/AttributeFactory.h"
+#include <mcld/MC/InputFactory.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/AttributeSet.h>
+#include <mcld/AttributeOption.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
 // InputFactory
-InputFactory::InputFactory(size_t pNum, AttributeFactory& pAttrFactory)
-  : GCFactory<Input,0>(pNum), m_AttrFactory(pAttrFactory) {
+//===----------------------------------------------------------------------===//
+InputFactory::InputFactory(size_t pNum, const LinkerConfig& pConfig)
+  : GCFactory<Input,0>(pNum) {
+
+  m_pAttrSet = new AttributeSet(16, pConfig.attribute().predefined());
+  m_pLast = new AttributeProxy(*m_pAttrSet,
+                               pConfig.attribute().predefined(),
+                               pConfig.attribute().constraint());
 }
 
 InputFactory::~InputFactory()
 {
+  delete m_pAttrSet;
+  delete m_pLast;
 }
 
 Input* InputFactory::produce(llvm::StringRef pName,
@@ -26,8 +36,8 @@
                              unsigned int pType,
                              off_t pFileOffset)
 {
-  mcld::Input* result = Alloc::allocate();
-  new (result) mcld::Input(pName, pPath, m_AttrFactory.last(), pType, pFileOffset);
+  Input* result = Alloc::allocate();
+  new (result) Input(pName, pPath, *m_pLast, pType, pFileOffset);
   return result;
 }
 
diff --git a/lib/MC/MCLDDriver.cpp b/lib/MC/MCLDDriver.cpp
deleted file mode 100644
index a1af124..0000000
--- a/lib/MC/MCLDDriver.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-//===- MCLDDriver.cpp -----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/ArchiveReader.h>
-#include <mcld/LD/ObjectReader.h>
-#include <mcld/LD/DynObjReader.h>
-#include <mcld/LD/ObjectWriter.h>
-#include <mcld/LD/DynObjWriter.h>
-#include <mcld/LD/ExecWriter.h>
-#include <mcld/LD/ResolveInfo.h>
-#include <mcld/Support/RealPath.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/LD/Archive.h>
-
-using namespace llvm;
-using namespace mcld;
-
-MCLDDriver::MCLDDriver(MCLDInfo& pLDInfo,
-                       TargetLDBackend& pLDBackend,
-                       MemoryAreaFactory& pAreaFactory)
-  : m_LDInfo(pLDInfo),
-    m_LDBackend(pLDBackend),
-    m_pLinker(NULL),
-    m_AreaFactory(pAreaFactory) {
-
-}
-
-MCLDDriver::~MCLDDriver()
-{
-  if (NULL != m_pLinker)
-    delete m_pLinker;
-}
-
-/// initMCLinker - initialize MCLinker
-///  Connect all components with MCLinker
-bool MCLDDriver::initMCLinker()
-{
-  if (0 == m_pLinker)
-    m_pLinker = new MCLinker(m_LDBackend,
-                             m_LDInfo,
-                             m_SectionMap);
-
-  // initialize the readers and writers
-  // Because constructor can not be failed, we initalize all readers and
-  // writers outside the MCLinker constructors.
-  if (!m_LDBackend.initObjectReader(*m_pLinker) ||
-      !m_LDBackend.initArchiveReader(*m_pLinker, m_LDInfo, m_AreaFactory) ||
-      !m_LDBackend.initObjectReader(*m_pLinker) ||
-      !m_LDBackend.initDynObjReader(*m_pLinker) ||
-      !m_LDBackend.initObjectWriter(*m_pLinker) ||
-      !m_LDBackend.initDynObjWriter(*m_pLinker) ||
-      !m_LDBackend.initExecWriter(*m_pLinker))
-    return false;
-
-  // initialize RelocationFactory
-  m_LDBackend.initRelocFactory(*m_pLinker);
-  return true;
-}
-
-/// initStdSections - initialize standard sections
-bool MCLDDriver::initStdSections()
-{
-  /// initialize section mapping for standard format, target-dependent section,
-  /// (and user-defined mapping)
-  if (!m_SectionMap.initStdSectionMap() ||
-      !m_LDBackend.initTargetSectionMap(m_SectionMap))
-    return false;
-
-  /// A technical debt. We need to initialize section map here because
-  /// we do not separate output file and temporary data structure. So far,
-  /// MCLinker directly use output file's LDContext as the temporary data
-  /// structure. We will create a new data structure mcld::Module to collect
-  /// all temporary data structures togather.
-  m_pLinker->initSectionMap();
-
-  // initialize standard sections
-  switch (m_LDInfo.output().type()) {
-    case Output::DynObj: {
-      // intialize standard and target-dependent sections
-      if (!m_LDBackend.initDynObjSections(*m_pLinker))
-        return false;
-      break;
-    }
-    case Output::Exec: {
-      // intialize standard and target-dependent sections
-      if (!m_LDBackend.initExecSections(*m_pLinker))
-        return false;
-      break;
-    }
-    case Output::Object: {
-      llvm::report_fatal_error(llvm::Twine("output type is not implemented yet. file: `") +
-                               m_LDInfo.output().name() +
-                               llvm::Twine("'."));
-      return false;
-    }
-    default: {
-      llvm::report_fatal_error(llvm::Twine("unknown output type of file `") +
-                               m_LDInfo.output().name() +
-                               llvm::Twine("'."));
-       return false;
-    }
-  } // end of switch
-
-  // initialize target-dependent sections
-  m_LDBackend.initTargetSections(*m_pLinker);
-
-  return true;
-}
-
-void MCLDDriver::normalize()
-{
-  // -----  set up inputs  ----- //
-  InputTree::iterator input, inEnd = m_LDInfo.inputs().end();
-  for (input = m_LDInfo.inputs().begin(); input!=inEnd; ++input) {
-    // already got type - for example, bitcode or external OIR (object
-    // intermediate representation)
-    if ((*input)->type() == Input::Script ||
-        (*input)->type() == Input::Object ||
-        (*input)->type() == Input::DynObj  ||
-        (*input)->type() == Input::Archive ||
-        (*input)->type() == Input::External)
-      continue;
-
-    // is a relocatable object file
-    if (m_LDBackend.getObjectReader()->isMyFormat(**input)) {
-      (*input)->setType(Input::Object);
-      m_LDBackend.getObjectReader()->readObject(**input);
-      m_LDBackend.getObjectReader()->readSections(**input);
-      m_LDBackend.getObjectReader()->readSymbols(**input);
-    }
-    // is a shared object file
-    else if (m_LDBackend.getDynObjReader()->isMyFormat(**input)) {
-      (*input)->setType(Input::DynObj);
-      m_LDBackend.getDynObjReader()->readDSO(**input);
-      m_LDBackend.getDynObjReader()->readSymbols(**input);
-    }
-    // is an archive
-    else if (m_LDBackend.getArchiveReader()->isMyFormat(**input)) {
-      (*input)->setType(Input::Archive);
-      Archive archive(**input, m_LDInfo.inputFactory());
-      m_LDBackend.getArchiveReader()->readArchive(archive);
-      if(archive.numOfObjectMember() > 0) {
-        m_LDInfo.inputs().merge<InputTree::Inclusive>(input, archive.inputs());
-      }
-    }
-    else {
-      fatal(diag::err_unrecognized_input_file) << (*input)->path()
-                                               << m_LDInfo.triple().str();
-    }
-  } // end of for
-}
-
-bool MCLDDriver::linkable() const
-{
-  // check we have input and output files
-  if (m_LDInfo.inputs().empty()) {
-    error(diag::err_no_inputs);
-    return false;
-  }
-
-  // check all attributes are legal
-  mcld::AttributeFactory::const_iterator attr, attrEnd = m_LDInfo.attrFactory().end();
-  for (attr=m_LDInfo.attrFactory().begin(); attr!=attrEnd; ++attr) {
-    if (!m_LDInfo.attrFactory().constraint().isLegal((**attr))) {
-      return false;
-    }
-  }
-
-  // can not mix -static with shared objects
-  mcld::InputTree::const_bfs_iterator input, inEnd = m_LDInfo.inputs().bfs_end();
-  for (input=m_LDInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
-    if ((*input)->type() == mcld::Input::DynObj) {
-      if((*input)->attribute()->isStatic()) {
-        error(diag::err_mixed_shared_static_objects)
-                                        << (*input)->name() << (*input)->path();
-        return false;
-      }
-    }
-  }
-
-  // can not mix -r with shared objects
-  return true;
-}
-
-/// mergeSections - put allinput sections into output sections
-bool MCLDDriver::mergeSections()
-{
-  // TODO: when MCLinker can read other object files, we have to merge
-  // sections
-  return true;
-}
-
-/// addStandardSymbols - shared object and executable files need some
-/// standard symbols
-///   @return if there are some input symbols with the same name to the
-///   standard symbols, return false
-bool MCLDDriver::addStandardSymbols()
-{
-  return m_LDBackend.initStandardSymbols(*m_pLinker, m_LDInfo.output());
-}
-
-/// addTargetSymbols - some targets, such as MIPS and ARM, need some
-/// target-dependent symbols
-///   @return if there are some input symbols with the same name to the
-///   target symbols, return false
-bool MCLDDriver::addTargetSymbols()
-{
-  m_LDBackend.initTargetSymbols(*m_pLinker, m_LDInfo.output());
-  return true;
-}
-
-/// readRelocations - read all relocation entries
-///
-/// All symbols should be read and resolved before this function.
-bool MCLDDriver::readRelocations()
-{
-  // Bitcode is read by the other path. This function reads relocation sections
-  // in object files.
-  mcld::InputTree::bfs_iterator input, inEnd = m_LDInfo.inputs().bfs_end();
-  for (input=m_LDInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
-    if ((*input)->type() == Input::Object) {
-      if (!m_LDBackend.getObjectReader()->readRelocations(**input))
-        return false;
-    }
-    // ignore the other kinds of files.
-  }
-  return true;
-}
-
-/// prelayout - help backend to do some modification before layout
-bool MCLDDriver::prelayout()
-{
-  m_LDBackend.preLayout(m_LDInfo.output(),
-                        m_LDInfo,
-                        *m_pLinker);
-
-  m_LDBackend.allocateCommonSymbols(m_LDInfo, *m_pLinker);
-
-  /// check program interpreter - computer the name size of the runtime dyld
-  /// FIXME: check if we are doing static linking!
-  if (m_LDInfo.output().type() == Output::Exec)
-    m_LDBackend.sizeInterp(m_LDInfo.output(), m_LDInfo);
-
-  /// measure NamePools - compute the size of name pool sections
-  /// In ELF, will compute  the size of.symtab, .strtab, .dynsym, .dynstr,
-  /// and .hash sections.
-  ///
-  /// dump all symbols and strings from MCLinker and build the format-dependent
-  /// hash table.
-  m_LDBackend.sizeNamePools(m_LDInfo.output(), m_pLinker->getOutputSymbols(), m_LDInfo);
-
-  return true;
-}
-
-/// layout - linearly layout all output sections and reserve some space
-/// for GOT/PLT
-///   Because we do not support instruction relaxing in this early version,
-///   if there is a branch can not jump to its target, we return false
-///   directly
-bool MCLDDriver::layout()
-{
-  return m_pLinker->layout();
-}
-
-/// prelayout - help backend to do some modification after layout
-bool MCLDDriver::postlayout()
-{
-  m_LDBackend.postLayout(m_LDInfo.output(),
-                         m_LDInfo,
-                         *m_pLinker);
-  return true;
-}
-
-/// finalizeSymbolValue - finalize the resolved symbol value.
-///   Before relocate(), after layout(), MCLinker should correct value of all
-///   symbol.
-bool MCLDDriver::finalizeSymbolValue()
-{
-  return m_pLinker->finalizeSymbols();
-}
-
-/// relocate - applying relocation entries and create relocation
-/// section in the output files
-/// Create relocation section, asking TargetLDBackend to
-/// read the relocation information into RelocationEntry
-/// and push_back into the relocation section
-bool MCLDDriver::relocation()
-{
-  return m_pLinker->applyRelocations();
-}
-
-/// emitOutput - emit the output file.
-bool MCLDDriver::emitOutput()
-{
-  switch(m_LDInfo.output().type()) {
-    case Output::Object:
-      m_LDBackend.getObjectWriter()->writeObject(m_LDInfo.output());
-      return true;
-    case Output::DynObj:
-      m_LDBackend.getDynObjWriter()->writeDynObj(m_LDInfo.output());
-      return true;
-    case Output::Exec:
-      m_LDBackend.getExecWriter()->writeExecutable(m_LDInfo.output());
-      return true;
-  }
-  return false;
-}
-
-/// postProcessing - do modification after all processes
-bool MCLDDriver::postProcessing()
-{
-  m_pLinker->syncRelocationResult();
-
-  m_LDBackend.postProcessing(m_LDInfo.output(),
-                             m_LDInfo,
-                             *m_pLinker);
-  return true;
-}
diff --git a/lib/MC/MCLDFile.cpp b/lib/MC/MCLDFile.cpp
deleted file mode 100644
index e6bbbc4..0000000
--- a/lib/MC/MCLDFile.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- MCLDFile.cpp -------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDFile.h"
-#include "mcld/LD/LDContext.h"
-#include "mcld/Support/FileSystem.h"
-#include "mcld/Support/MemoryArea.h"
-#include <cstring>
-#include <cstdlib>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// MCLDFile
-MCLDFile::MCLDFile()
-  : m_Type(Unknown), m_pContext(0), m_Path(), m_Name(), m_pMemArea(0) {
-}
-
-MCLDFile::MCLDFile(llvm::StringRef pName)
-  : m_Type(Unknown), m_pContext(0), m_Path(), m_Name(pName.data()), m_pMemArea(0) {
-}
-
-MCLDFile::MCLDFile(llvm::StringRef pName,
-                   const sys::fs::Path& pPath,
-                   unsigned int pType)
-  : m_Type(pType), m_pContext(0), m_Path(pPath), m_Name(pName.data()), m_pMemArea(0) {
-}
-
-MCLDFile::~MCLDFile()
-{
-}
-
-void MCLDFile::setSOName(const std::string& pName)
-{
-  size_t pos = pName.find_last_of(sys::fs::separator);
-  if (std::string::npos == pos)
-    m_Name = pName;
-  else
-    m_Name = pName.substr(pos + 1);
-}
-
diff --git a/lib/MC/MCLDInfo.cpp b/lib/MC/MCLDInfo.cpp
deleted file mode 100644
index 7ac154c..0000000
--- a/lib/MC/MCLDInfo.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- MCLDInfo.cpp -------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Config/Config.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/InputFactory.h>
-#include <mcld/MC/AttributeFactory.h>
-#include <mcld/MC/ContextFactory.h>
-#include <mcld/LD/NamePool.h>
-#include <mcld/LD/StaticResolver.h>
-#include <mcld/Support/FileSystem.h>
-#include <string>
-
-using namespace mcld;
-
-//==========================
-// MCLDInfo
-MCLDInfo::MCLDInfo(const std::string& pTripleString,
-                   size_t pAttrNum,
-                   size_t pInputNum)
-  : m_Options(),
-    m_Scripts(),
-    m_pBitcode(NULL),
-    m_Triple(pTripleString)
-{
-  m_pAttrFactory = new AttributeFactory(pAttrNum);
-  m_pCntxtFactory = new ContextFactory(pInputNum);
-  m_pInputFactory = new InputFactory(pInputNum, *m_pAttrFactory);
-  m_pInputTree = new InputTree(*m_pInputFactory);
-  m_pOutput = new mcld::Output();
-  m_pResolver = new StaticResolver();
-  m_pNamePool = new NamePool(*m_pResolver, 1024);
-}
-
-MCLDInfo::~MCLDInfo()
-{
-  delete m_pOutput;
-  delete m_pAttrFactory;
-  delete m_pCntxtFactory;
-  delete m_pInputFactory;
-  delete m_pInputTree;
-  delete m_pResolver;
-  delete m_pNamePool;
-}
-
-void MCLDInfo::setBitcode(const Input& pInput)
-{
-  m_pBitcode = const_cast<Input*>(&pInput);
-}
-
-Input& MCLDInfo::bitcode()
-{
-  assert((0 != m_pBitcode) && "default bitcode is not set");
-  return *m_pBitcode;
-}
-
-const Input& MCLDInfo::bitcode() const
-{
-  assert((0 != m_pBitcode) && "default bitcode is not set");
-  return *m_pBitcode;
-}
-
-const char* MCLDInfo::version()
-{
-  return MCLD_VERSION;
-}
diff --git a/lib/MC/MCLDInput.cpp b/lib/MC/MCLDInput.cpp
index 0803e00..1fc6cb5 100644
--- a/lib/MC/MCLDInput.cpp
+++ b/lib/MC/MCLDInput.cpp
@@ -6,18 +6,49 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInput.h"
-#include "mcld/MC/MCLDAttribute.h"
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/LD/LDContext.h>
 
 using namespace mcld;
 
-//==========================
-// MCInput
+//===----------------------------------------------------------------------===//
+// mcld::Input
+//===----------------------------------------------------------------------===//
+Input::Input(llvm::StringRef pName)
+  : m_Type(Unknown),
+    m_Name(pName.data()),
+    m_Path(),
+    m_pAttr(NULL),
+    m_bNeeded(false),
+    m_fileOffset(0),
+    m_pMemArea(NULL),
+    m_pContext(NULL) {
+}
+
 Input::Input(llvm::StringRef pName, const AttributeProxy& pProxy)
- : MCLDFile(pName),
-   m_pAttr(const_cast<Attribute*>(pProxy.attr())),
-   m_bNeeded(false),
-   m_fileOffset(0) {
+  : m_Type(Unknown),
+    m_Name(pName.data()),
+    m_Path(),
+    m_pAttr(const_cast<Attribute*>(pProxy.attr())),
+    m_bNeeded(false),
+    m_fileOffset(0),
+    m_pMemArea(NULL),
+    m_pContext(NULL) {
+}
+
+Input::Input(llvm::StringRef pName,
+        const sys::fs::Path& pPath,
+        unsigned int pType,
+        off_t pFileOffset)
+  : m_Type(pType),
+    m_Name(pName.data()),
+    m_Path(pPath),
+    m_pAttr(NULL),
+    m_bNeeded(false),
+    m_fileOffset(pFileOffset),
+    m_pMemArea(NULL),
+    m_pContext(NULL) {
 }
 
 Input::Input(llvm::StringRef pName,
@@ -25,14 +56,19 @@
         const AttributeProxy& pProxy,
         unsigned int pType,
         off_t pFileOffset)
-  : MCLDFile(pName, pPath, pType),
+  : m_Type(pType),
+    m_Name(pName.data()),
+    m_Path(pPath),
     m_pAttr(const_cast<Attribute*>(pProxy.attr())),
     m_bNeeded(false),
-    m_fileOffset(pFileOffset) {
+    m_fileOffset(pFileOffset),
+    m_pMemArea(NULL),
+    m_pContext(NULL) {
 }
 
 Input::~Input()
 {
-  // do nothing. Attribute is deleted by AttributeFactory
+  // Attribute is deleted by AttributeFactory
+  // MemoryArea is deleted by MemoryAreaFactory
 }
 
diff --git a/lib/MC/MCLDOutput.cpp b/lib/MC/MCLDOutput.cpp
deleted file mode 100644
index c27ee01..0000000
--- a/lib/MC/MCLDOutput.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===- MCLDOutput.cpp -----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDOutput.h"
-
-using namespace mcld;
-
-//==========================
-// MCLDOutput
-Output::Output()
-  : MCLDFile("") {
-}
-
-Output::Output(const sys::fs::Path& pRealPath,
-               Output::Type pType)
-  : MCLDFile("", pRealPath, pType) {
-}
-                  
-Output::~Output()
-{
-}
-
diff --git a/lib/MC/MCLinker.cpp b/lib/MC/MCLinker.cpp
deleted file mode 100644
index e9fb327..0000000
--- a/lib/MC/MCLinker.cpp
+++ /dev/null
@@ -1,718 +0,0 @@
-//===- MCLinker.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 MCLinker class
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLinker.h>
-
-#include <llvm/Support/Host.h>
-#include <llvm/Support/raw_ostream.h>
-
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/Resolver.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/LD/LDSectionFactory.h>
-#include <mcld/LD/SectionMap.h>
-#include <mcld/LD/RelocationFactory.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/EhFrameHdr.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Target/TargetLDBackend.h>
-
-using namespace mcld;
-
-/// Constructor
-MCLinker::MCLinker(TargetLDBackend& pBackend,
-                   MCLDInfo& pInfo,
-                   SectionMap& pSectionMap)
-: m_Backend(pBackend),
-  m_LDInfo(pInfo),
-  m_SectionMap(pSectionMap),
-  m_LDSymbolFactory(128),
-  m_LDSectHdrFactory(10), // the average number of sections. (assuming 10.)
-  m_LDSectDataFactory(10),
-  m_pSectionMerger(NULL)
-{
-}
-
-/// Destructor
-MCLinker::~MCLinker()
-{
-  if (NULL != m_pSectionMerger)
-    delete m_pSectionMerger;
-}
-
-//===----------------------------------------------------------------------===//
-// Symbol Operations
-//===----------------------------------------------------------------------===//
-/// addSymbolFromObject - add a symbol from object file and resolve it
-/// immediately
-LDSymbol* MCLinker::addSymbolFromObject(const llvm::StringRef& pName,
-                                        ResolveInfo::Type pType,
-                                        ResolveInfo::Desc pDesc,
-                                        ResolveInfo::Binding pBinding,
-                                        ResolveInfo::SizeType pSize,
-                                        LDSymbol::ValueType pValue,
-                                        FragmentRef* pFragmentRef,
-                                        ResolveInfo::Visibility pVisibility)
-{
-
-  // resolved_result is a triple <resolved_info, existent, override>
-  Resolver::Result resolved_result;
-  ResolveInfo old_info; // used for arrange output symbols
-
-  if (pBinding == ResolveInfo::Local) {
-    // if the symbol is a local symbol, create a LDSymbol for input, but do not
-    // resolve them.
-    resolved_result.info     = m_LDInfo.getNamePool().createSymbol(pName,
-                                                         false,
-                                                         pType,
-                                                         pDesc,
-                                                         pBinding,
-                                                         pSize,
-                                                         pVisibility);
-
-    // No matter if there is a symbol with the same name, insert the symbol
-    // into output symbol table. So, we let the existent false.
-    resolved_result.existent  = false;
-    resolved_result.overriden = true;
-  }
-  else {
-    // if the symbol is not local, insert and resolve it immediately
-    m_LDInfo.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
-                                        pSize, pVisibility,
-                                        &old_info, resolved_result);
-  }
-
-  // the return ResolveInfo should not NULL
-  assert(NULL != resolved_result.info);
-
-  // create a LDSymbol for the input file.
-  LDSymbol* input_sym = m_LDSymbolFactory.allocate();
-  new (input_sym) LDSymbol();
-
-  // set the relation between input LDSymbol and its ResolveInfo
-  input_sym->setResolveInfo(*resolved_result.info);
-
-  // set up input LDSymbol
-  input_sym->setFragmentRef(pFragmentRef);
-  input_sym->setValue(pValue);
-
-  LDSymbol* output_sym = resolved_result.info->outSymbol();
-  bool has_output_sym = (NULL != output_sym);
-  if (!resolved_result.existent || !has_output_sym) {
-    // it is a new symbol, the output_sym should be NULL.
-    assert(NULL == output_sym);
-
-    // if it is a new symbol, create a LDSymbol for the output
-    output_sym = m_LDSymbolFactory.allocate();
-    new (output_sym) LDSymbol();
-
-    // set up the relation between output LDSymbol and its ResolveInfo
-    output_sym->setResolveInfo(*resolved_result.info);
-    resolved_result.info->setSymPtr(output_sym);
-  }
-
-  if (resolved_result.overriden || !has_output_sym) {
-    // symbol can be overriden only if it exists.
-    assert(output_sym != NULL);
-
-    // should override output LDSymbol
-    output_sym->setFragmentRef(pFragmentRef);
-    output_sym->setValue(pValue);
-  }
-
-  // After symbol resolution, visibility is changed to the most restrict one.
-  // we need to arrange its position in the output symbol .
-  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_OutputSymbols.forceLocal(*output_sym);
-      else {
-        // the symbol should not be forcefully local.
-        m_OutputSymbols.add(*output_sym);
-      }
-    }
-    else if (resolved_result.overriden) {
-      if (!shouldForceLocal(old_info) ||
-          !shouldForceLocal(*resolved_result.info)) {
-        // 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_OutputSymbols.arrange(*output_sym, old_info);
-      }
-    }
-  }
-
-  return input_sym;
-}
-
-/// addSymbolFromDynObj - add a symbol from object file and resolve it
-/// immediately
-LDSymbol* MCLinker::addSymbolFromDynObj(const llvm::StringRef& pName,
-                                        ResolveInfo::Type pType,
-                                        ResolveInfo::Desc pDesc,
-                                        ResolveInfo::Binding pBinding,
-                                        ResolveInfo::SizeType pSize,
-                                        LDSymbol::ValueType pValue,
-                                        FragmentRef* pFragmentRef,
-                                        ResolveInfo::Visibility pVisibility)
-{
-  // We merge sections when reading them. So we do not need symbols with
-  // section type
-  if (pType == ResolveInfo::Section)
-    return NULL;
-
-  // ignore symbols with local binding or that have internal or hidden
-  // visibility
-  if (pBinding == ResolveInfo::Local ||
-      pVisibility == ResolveInfo::Internal ||
-      pVisibility == ResolveInfo::Hidden)
-    return NULL;
-
-  // A protected symbol in a shared library must be treated as a
-  // normal symbol when viewed from outside the shared library.
-  if (pVisibility == ResolveInfo::Protected)
-    pVisibility = ResolveInfo::Default;
-
-  // insert symbol and resolve it immediately
-  // resolved_result is a triple <resolved_info, existent, override>
-  Resolver::Result resolved_result;
-  m_LDInfo.getNamePool().insertSymbol(pName, true, pType, pDesc,
-                            pBinding, pSize, pVisibility,
-                            NULL, resolved_result);
-
-  // the return ResolveInfo should not NULL
-  assert(NULL != resolved_result.info);
-
-  // create a LDSymbol for the input file.
-  LDSymbol* input_sym = m_LDSymbolFactory.allocate();
-  new (input_sym) LDSymbol();
-
-  // set up the relation between input LDSymbol and its ResolveInfo
-  input_sym->setResolveInfo(*resolved_result.info);
-
-  // set up input LDSymbol
-  input_sym->setFragmentRef(pFragmentRef);
-  input_sym->setValue(pValue);
-
-  LDSymbol* output_sym = NULL;
-  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_OutputSymbols.forceLocal(*output_sym);
-    }
-  }
-
-  return input_sym;
-}
-
-/// defineSymbolForcefully - define an output symbol and override it immediately
-LDSymbol* MCLinker::defineSymbolForcefully(const llvm::StringRef& pName,
-                                           bool pIsDyn,
-                                           ResolveInfo::Type pType,
-                                           ResolveInfo::Desc pDesc,
-                                           ResolveInfo::Binding pBinding,
-                                           ResolveInfo::SizeType pSize,
-                                           LDSymbol::ValueType pValue,
-                                           FragmentRef* pFragmentRef,
-                                           ResolveInfo::Visibility pVisibility)
-{
-  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
-  LDSymbol* output_sym = NULL;
-  if (NULL == info) {
-    // the symbol is not in the pool, create a new one.
-    // create a ResolveInfo
-    Resolver::Result result;
-    m_LDInfo.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc,
-                                        pBinding, pSize, pVisibility,
-                                        NULL, result);
-    assert(!result.existent);
-
-    // create a output LDSymbol
-    output_sym = m_LDSymbolFactory.allocate();
-    new (output_sym) LDSymbol();
-
-    output_sym->setResolveInfo(*result.info);
-    result.info->setSymPtr(output_sym);
-
-    if (shouldForceLocal(*result.info))
-      m_OutputSymbols.forceLocal(*output_sym);
-    else
-      m_OutputSymbols.add(*output_sym);
-  }
-  else {
-    // the symbol is already in the pool, override it
-    ResolveInfo old_info;
-    old_info.override(*info);
-
-    info->setSource(pIsDyn);
-    info->setType(pType);
-    info->setDesc(pDesc);
-    info->setBinding(pBinding);
-    info->setVisibility(pVisibility);
-    info->setIsSymbol(true);
-    info->setSize(pSize);
-
-    output_sym = info->outSymbol();
-    if (NULL != output_sym)
-      m_OutputSymbols.arrange(*output_sym, old_info);
-    else {
-      // create a output LDSymbol
-      output_sym = m_LDSymbolFactory.allocate();
-      new (output_sym) LDSymbol();
-
-      output_sym->setResolveInfo(*info);
-      info->setSymPtr(output_sym);
-
-      m_OutputSymbols.add(*output_sym);
-    }
-  }
-
-  if (NULL != output_sym) {
-    output_sym->setFragmentRef(pFragmentRef);
-    output_sym->setValue(pValue);
-  }
-
-  return output_sym;
-}
-
-/// defineSymbolAsRefered - define an output symbol and override it immediately
-LDSymbol* MCLinker::defineSymbolAsRefered(const llvm::StringRef& pName,
-                                           bool pIsDyn,
-                                           ResolveInfo::Type pType,
-                                           ResolveInfo::Desc pDesc,
-                                           ResolveInfo::Binding pBinding,
-                                           ResolveInfo::SizeType pSize,
-                                           LDSymbol::ValueType pValue,
-                                           FragmentRef* pFragmentRef,
-                                           ResolveInfo::Visibility pVisibility)
-{
-  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
-
-  if (NULL == info || !(info->isUndef() || info->isDyn())) {
-    // only undefined symbol and dynamic symbol can make a reference.
-    return NULL;
-  }
-
-  // the symbol is already in the pool, override it
-  ResolveInfo old_info;
-  old_info.override(*info);
-
-  info->setSource(pIsDyn);
-  info->setType(pType);
-  info->setDesc(pDesc);
-  info->setBinding(pBinding);
-  info->setVisibility(pVisibility);
-  info->setIsSymbol(true);
-  info->setSize(pSize);
-
-  LDSymbol* output_sym = info->outSymbol();
-  if (NULL != output_sym) {
-    output_sym->setFragmentRef(pFragmentRef);
-    output_sym->setValue(pValue);
-    m_OutputSymbols.arrange(*output_sym, old_info);
-  }
-  else {
-    // create a output LDSymbol
-    output_sym = m_LDSymbolFactory.allocate();
-    new (output_sym) LDSymbol();
-
-    output_sym->setResolveInfo(*info);
-    info->setSymPtr(output_sym);
-
-    m_OutputSymbols.add(*output_sym);
-  }
-
-  return output_sym;
-}
-
-/// defineAndResolveSymbolForcefully - define an output symbol and resolve it
-/// immediately
-LDSymbol* MCLinker::defineAndResolveSymbolForcefully(const llvm::StringRef& pName,
-                                                     bool pIsDyn,
-                                                     ResolveInfo::Type pType,
-                                                     ResolveInfo::Desc pDesc,
-                                                     ResolveInfo::Binding pBinding,
-                                                     ResolveInfo::SizeType pSize,
-                                                     LDSymbol::ValueType pValue,
-                                                     FragmentRef* pFragmentRef,
-                                                     ResolveInfo::Visibility pVisibility)
-{
-  // Result is <info, existent, override>
-  Resolver::Result result;
-  ResolveInfo old_info;
-  m_LDInfo.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc, pBinding,
-                                      pSize, pVisibility,
-                                      &old_info, result);
-
-  LDSymbol* output_sym = result.info->outSymbol();
-  bool has_output_sym = (NULL != output_sym);
-
-  if (!result.existent || !has_output_sym) {
-    output_sym = m_LDSymbolFactory.allocate();
-    new (output_sym) LDSymbol();
-    output_sym->setResolveInfo(*result.info);
-    result.info->setSymPtr(output_sym);
-  }
-
-  if (result.overriden || !has_output_sym) {
-    output_sym->setFragmentRef(pFragmentRef);
-    output_sym->setValue(pValue);
-  }
-
-  // After symbol resolution, the visibility is changed to the most restrict.
-  // arrange the output position
-  if (shouldForceLocal(*result.info))
-    m_OutputSymbols.forceLocal(*output_sym);
-  else if (has_output_sym)
-    m_OutputSymbols.arrange(*output_sym, old_info);
-  else
-    m_OutputSymbols.add(*output_sym);
-
-  return output_sym;
-}
-
-/// defineAndResolveSymbolAsRefered - define an output symbol and resolve it
-/// immediately.
-LDSymbol* MCLinker::defineAndResolveSymbolAsRefered(const llvm::StringRef& pName,
-                                                    bool pIsDyn,
-                                                    ResolveInfo::Type pType,
-                                                    ResolveInfo::Desc pDesc,
-                                                    ResolveInfo::Binding pBinding,
-                                                    ResolveInfo::SizeType pSize,
-                                                    LDSymbol::ValueType pValue,
-                                                    FragmentRef* pFragmentRef,
-                                                    ResolveInfo::Visibility pVisibility)
-{
-  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
-
-  if (NULL == info || !(info->isUndef() || info->isDyn())) {
-    // only undefined symbol and dynamic symbol can make a reference.
-    return NULL;
-  }
-
-  return defineAndResolveSymbolForcefully(pName,
-                                          pIsDyn,
-                                          pType,
-                                          pDesc,
-                                          pBinding,
-                                          pSize,
-                                          pValue,
-                                          pFragmentRef,
-                                          pVisibility);
-}
-
-bool MCLinker::finalizeSymbols()
-{
-  SymbolCategory::iterator symbol, symEnd = m_OutputSymbols.end();
-  for (symbol = m_OutputSymbols.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)->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 = getLayout().getOutputOffset(*(*symbol)->fragRef());
-      assert(NULL != (*symbol)->fragRef()->frag());
-      uint64_t addr  = getLayout().getOutputLDSection(*(*symbol)->fragRef()->frag())->addr();
-      (*symbol)->setValue(value + addr);
-      continue;
-    }
-  }
-
-  // finialize target-dependent symbols
-  return m_Backend.finalizeSymbols(*this, m_LDInfo.output());
-}
-
-bool MCLinker::shouldForceLocal(const ResolveInfo& pInfo) const
-{
-  // forced local symbol matches all rules:
-  // 1. We are not doing incremental linking.
-  // 2. The symbol is with Hidden or Internal visibility.
-  // 3. The symbol should be global or weak. Otherwise, local symbol is local.
-  // 4. The symbol is defined or common
-  if (m_LDInfo.output().type() != Output::Object &&
-      (pInfo.visibility() == ResolveInfo::Hidden ||
-         pInfo.visibility() == ResolveInfo::Internal) &&
-      (pInfo.isGlobal() || pInfo.isWeak()) &&
-      (pInfo.isDefine() || pInfo.isCommon()))
-    return true;
-  return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Section Operations
-//===----------------------------------------------------------------------===//
-/// createSectHdr - create the input section header
-LDSection& MCLinker::createSectHdr(const std::string& pName,
-                                   LDFileFormat::Kind pKind,
-                                   uint32_t pType,
-                                   uint32_t pFlag)
-{
-  assert(m_LDInfo.output().hasContext());
-
-  // for user such as reader, standard/target fromat
-  LDSection* result =
-    m_LDSectHdrFactory.produce(pName, pKind, pType, pFlag);
-
-  // check if we need to create a output section for output LDContext
-  std::string sect_name = m_SectionMap.getOutputSectName(pName);
-  LDSection* output_sect = m_LDInfo.output().context()->getSection(sect_name);
-
-  if (NULL == output_sect) {
-  // create a output section and push it into output LDContext
-    output_sect =
-      m_LDSectHdrFactory.produce(sect_name, pKind, pType, pFlag);
-    m_LDInfo.output().context()->getSectionTable().push_back(output_sect);
-    m_pSectionMerger->addMapping(pName, output_sect);
-  }
-  return *result;
-}
-
-/// getOrCreateOutputSectHdr - for reader and standard/target format to get
-/// or create the output's section header
-LDSection& MCLinker::getOrCreateOutputSectHdr(const std::string& pName,
-                                              LDFileFormat::Kind pKind,
-                                              uint32_t pType,
-                                              uint32_t pFlag,
-                                              uint32_t pAlign)
-{
-  assert(m_LDInfo.output().hasContext());
-
-  // check if we need to create a output section for output LDContext
-  std::string sect_name = m_SectionMap.getOutputSectName(pName);
-  LDSection* output_sect = m_LDInfo.output().context()->getSection(sect_name);
-
-  if (NULL == output_sect) {
-  // create a output section and push it into output LDContext
-    output_sect =
-      m_LDSectHdrFactory.produce(sect_name, pKind, pType, pFlag);
-    output_sect->setAlign(pAlign);
-    m_LDInfo.output().context()->getSectionTable().push_back(output_sect);
-    m_pSectionMerger->addMapping(pName, output_sect);
-  }
-  return *output_sect;
-}
-
-/// getOrCreateSectData - get or create SectionData
-/// pSection is input LDSection
-SectionData& MCLinker::getOrCreateSectData(LDSection& pSection)
-{
-  // if there is already a section data pointed by section, return it.
-  SectionData* sect_data = pSection.getSectionData();
-  if (NULL != sect_data) {
-    m_Layout.addInputRange(*sect_data, pSection);
-    return *sect_data;
-  }
-
-  // try to get one from output LDSection
-  LDSection* output_sect =
-    m_pSectionMerger->getOutputSectHdr(pSection.name());
-
-  assert(NULL != output_sect);
-
-  sect_data = output_sect->getSectionData();
-
-  if (NULL != sect_data) {
-    pSection.setSectionData(sect_data);
-    m_Layout.addInputRange(*sect_data, pSection);
-    return *sect_data;
-  }
-
-  // if the output LDSection also has no SectionData, then create one.
-  sect_data = m_LDSectDataFactory.allocate();
-  new (sect_data) SectionData(*output_sect);
-  pSection.setSectionData(sect_data);
-  output_sect->setSectionData(sect_data);
-  m_Layout.addInputRange(*sect_data, pSection);
-  return *sect_data;
-}
-
-void MCLinker::initSectionMap()
-{
-  assert(m_LDInfo.output().hasContext());
-  if (NULL == m_pSectionMerger)
-    m_pSectionMerger = new SectionMerger(m_SectionMap, *m_LDInfo.output().context());
-}
-
-bool MCLinker::layout()
-{
-  return m_Layout.layout(m_LDInfo.output(), m_Backend, m_LDInfo);
-}
-
-//===----------------------------------------------------------------------===//
-// Relocation Operations
-//===----------------------------------------------------------------------===//
-/// addRelocation - add a relocation entry in MCLinker (only for object file)
-///
-/// All symbols should be read and resolved before calling this function.
-Relocation* MCLinker::addRelocation(Relocation::Type pType,
-                                    const LDSymbol& pSym,
-                                    ResolveInfo& pResolveInfo,
-                                    FragmentRef& pFragmentRef,
-                                    const LDSection& pSection,
-                                    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.
-  if (pSym.fragRef() == NULL &&
-      pResolveInfo.type() == ResolveInfo::Section &&
-      pResolveInfo.desc() == ResolveInfo::Undefined)
-    return NULL;
-
-  Relocation* relocation = m_Backend.getRelocFactory()->produce(pType,
-                                                                pFragmentRef,
-                                                                pAddend);
-
-  relocation->setSymInfo(&pResolveInfo);
-
-  m_RelocationList.push_back(relocation);
-
-  m_Backend.scanRelocation(*relocation, pSym, *this, m_LDInfo,
-                           m_LDInfo.output(), pSection);
-
-  if (pResolveInfo.isUndef() && !pResolveInfo.isDyn() && !pResolveInfo.isWeak())
-    fatal(diag::undefined_reference) << pResolveInfo.name();
-  return relocation;
-}
-
-bool MCLinker::applyRelocations()
-{
-  RelocationListType::iterator relocIter, relocEnd = m_RelocationList.end();
-
-  for (relocIter = m_RelocationList.begin(); relocIter != relocEnd; ++relocIter) {
-    Fragment* frag = (Fragment*)relocIter;
-    static_cast<Relocation*>(frag)->apply(*m_Backend.getRelocFactory(), m_LDInfo);
-  }
-  return true;
-}
-
-void MCLinker::syncRelocationResult()
-{
-
-  MemoryRegion* region = m_LDInfo.output().memArea()->request(0,
-                              m_LDInfo.output().memArea()->handler()->size());
-
-  uint8_t* data = region->getBuffer();
-
-  RelocationListType::iterator relocIter, relocEnd = m_RelocationList.end();
-  for (relocIter = m_RelocationList.begin(); relocIter != relocEnd; ++relocIter) {
-
-    Fragment* frag = (Fragment*)relocIter;
-    Relocation* reloc = static_cast<Relocation*>(frag);
-
-    // get output file offset
-    size_t out_offset = m_Layout.getOutputLDSection(*reloc->targetRef().frag())->offset() +
-                        m_Layout.getOutputOffset(reloc->targetRef());
-
-    uint8_t* target_addr = data + out_offset;
-    // byte swapping if target and host has different endian, and then write back
-    if(llvm::sys::isLittleEndianHost() != m_Backend.isLittleEndian()) {
-       uint64_t tmp_data = 0;
-
-       switch(m_Backend.bitclass()) {
-         case 32u:
-           tmp_data = bswap32(reloc->target());
-           std::memcpy(target_addr, &tmp_data, 4);
-           break;
-
-         case 64u:
-           tmp_data = bswap64(reloc->target());
-           std::memcpy(target_addr, &tmp_data, 8);
-           break;
-
-         default:
-           break;
-      }
-    }
-    else {
-      std::memcpy(target_addr, &reloc->target(), m_Backend.bitclass()/8);
-    }
-  } // end of for
-
-  m_LDInfo.output().memArea()->clear();
-}
-
-//===----------------------------------------------------------------------===//
-// Exception Handling Operations
-//===----------------------------------------------------------------------===//
-/// addEhFrame - add an exception handling section
-/// @param pSection - the input section
-/// @param pArea - the memory area which pSection is within.
-uint64_t MCLinker::addEhFrame(const Input& pInput,
-                              LDSection& pSection,
-                              MemoryArea& pArea)
-{
-  uint64_t size = 0;
-
-  // get the SectionData of this eh_frame
-  SectionData& sect_data = getOrCreateSectData(pSection);
-
-  // parse the eh_frame if the option --eh-frame-hdr is given
-  if (m_LDInfo.options().hasEhFrameHdr()) {
-    EhFrame* ehframe = m_Backend.getEhFrame();
-    assert(NULL != ehframe);
-    if (ehframe->canRecognizeAllEhFrame()) {
-      size = ehframe->readEhFrame(m_Layout, m_Backend, sect_data, pInput,
-                                    pSection, pArea);
-      // zero size indicate that this is an empty section or we can't recognize
-      // this eh_frame, handle it as a regular section.
-      if (0 != size)
-        return size;
-    }
-  }
-
-  // handle eh_frame as a regular section
-  MemoryRegion* region = pArea.request(pInput.fileOffset() + pSection.offset(),
-                                       pSection.size());
-
-  Fragment* frag = NULL;
-  if (NULL == region) {
-    // 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);
-
-  size = m_Layout.appendFragment(*frag, sect_data, pSection.align());
-  return size;
-}
-
diff --git a/lib/MC/SearchDirs.cpp b/lib/MC/SearchDirs.cpp
index 40d625b..12d08e2 100644
--- a/lib/MC/SearchDirs.cpp
+++ b/lib/MC/SearchDirs.cpp
@@ -14,7 +14,8 @@
 
 //===----------------------------------------------------------------------===//
 // Non-member functions
-static void SpecToFilename(const std::string& pSpec, std::string& pFile)
+//===----------------------------------------------------------------------===//
+static inline void SpecToFilename(const std::string& pSpec, std::string& pFile)
 {
   pFile = "lib";
   pFile += pSpec;
@@ -22,6 +23,7 @@
 
 //===----------------------------------------------------------------------===//
 // SearchDirs
+//===----------------------------------------------------------------------===//
 SearchDirs::SearchDirs()
 {
   // a magic number 8, no why.
@@ -29,6 +31,13 @@
   m_DirList.reserve(8);
 }
 
+SearchDirs::SearchDirs(const sys::fs::Path& pSysRoot)
+  : m_SysRoot(pSysRoot) {
+  // a magic number 8, no why.
+  // please prove it or change it
+  m_DirList.reserve(8);
+}
+
 SearchDirs::~SearchDirs()
 {
   iterator dir, dirEnd = end();
@@ -37,9 +46,22 @@
   }
 }
 
-void SearchDirs::add(const MCLDDirectory& pDirectory)
+bool SearchDirs::insert(const std::string& pPath)
 {
-  m_DirList.push_back(new MCLDDirectory(pDirectory));
+  MCLDDirectory* dir = new MCLDDirectory(pPath);
+  if (dir->isInSysroot())
+    dir->setSysroot(m_SysRoot);
+
+  if (exists(dir->path()) && is_directory(dir->path())) {
+    m_DirList.push_back(dir);
+    return true;
+  }
+  return false;
+}
+
+bool SearchDirs::insert(const sys::fs::Path& pPath)
+{
+  return insert(pPath.native());
 }
 
 mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec, mcld::Input::Type pType)
@@ -85,3 +107,46 @@
   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);
+
+  std::string file;
+  SpecToFilename(pNamespec, file);
+  // 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 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;
+        }
+      }
+      /** 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
+  return NULL;
+}
diff --git a/lib/MC/SymbolCategory.cpp b/lib/MC/SymbolCategory.cpp
index 4b5e0f7..f01083f 100644
--- a/lib/MC/SymbolCategory.cpp
+++ b/lib/MC/SymbolCategory.cpp
@@ -35,19 +35,22 @@
 {
   m_pFile   = new Category(Category::File);
   m_pLocal  = new Category(Category::Local);
+  m_pTLS    = new Category(Category::TLS);
   m_pCommon = new Category(Category::Common);
   m_pWeak   = new Category(Category::Weak);
   m_pGlobal = new Category(Category::Global);
 
   m_pFile->next   = m_pLocal;
-  m_pLocal->next  = m_pCommon;
+  m_pLocal->next  = m_pTLS;
+  m_pTLS->next    = m_pCommon;
   m_pCommon->next = m_pWeak;
   m_pWeak->next   = m_pGlobal;
 
   m_pGlobal->prev = m_pWeak;
   m_pWeak->prev   = m_pCommon;
-  m_pCommon->prev = m_pLocal;
-  m_pLocal->prev   = m_pFile;
+  m_pCommon->prev = m_pTLS;
+  m_pTLS->prev    = m_pLocal;
+  m_pLocal->prev  = m_pFile;
 }
 
 SymbolCategory::~SymbolCategory()
@@ -92,6 +95,8 @@
 {
   m_OutputSymbols.insert(localEnd(), &pSymbol);
   m_pLocal->end++;
+  m_pTLS->begin++;
+  m_pTLS->end++;
   m_pCommon->begin++;
   m_pCommon->end++;
   m_pWeak->begin++;
@@ -203,6 +208,27 @@
   return *this;
 }
 
+SymbolCategory& SymbolCategory::changeLocalToTLS(const LDSymbol& pSymbol)
+{
+  // find the position of pSymbol from local category
+  size_t pos = m_pLocal->begin;
+  while (pos != m_pLocal->end) {
+    if (m_OutputSymbols[pos] == &pSymbol)
+      break;
+    ++pos;
+  }
+
+  // if symbol is not in Local, then do nothing
+  if (m_pLocal->end == pos)
+    return *this;
+
+  // bubble sort downward to TLS
+  std::swap(m_OutputSymbols[pos], m_OutputSymbols[m_pLocal->end - 1]);
+  m_pLocal->end--;
+  m_pTLS->begin--;
+  return *this;
+}
+
 size_t SymbolCategory::numOfSymbols() const
 {
   return m_OutputSymbols.size();
@@ -210,7 +236,7 @@
 
 size_t SymbolCategory::numOfLocals() const
 {
-  return (m_pFile->size() + m_pLocal->size());
+  return (m_pFile->size() + m_pLocal->size() + m_pTLS->size());
 }
 
 size_t SymbolCategory::numOfCommons() const
@@ -232,7 +258,7 @@
 
 bool SymbolCategory::emptyLocals() const
 {
-  return (m_pFile->empty() && m_pLocal->empty());
+  return (m_pFile->empty() && m_pLocal->empty() && m_pTLS->empty());
 }
 
 bool SymbolCategory::emptyCommons() const
@@ -291,26 +317,50 @@
   return iter;
 }
 
-SymbolCategory::iterator SymbolCategory::commonBegin()
+SymbolCategory::iterator SymbolCategory::tlsBegin()
 {
   return localEnd();
 }
 
-SymbolCategory::iterator SymbolCategory::commonEnd()
+SymbolCategory::iterator SymbolCategory::tlsEnd()
 {
   iterator iter = localEnd();
+  iter += m_pTLS->size();
+  return iter;
+}
+
+SymbolCategory::const_iterator SymbolCategory::tlsBegin() const
+{
+  return localEnd();
+}
+
+SymbolCategory::const_iterator SymbolCategory::tlsEnd() const
+{
+  const_iterator iter = localEnd();
+  iter += m_pTLS->size();
+  return iter;
+}
+
+SymbolCategory::iterator SymbolCategory::commonBegin()
+{
+  return tlsEnd();
+}
+
+SymbolCategory::iterator SymbolCategory::commonEnd()
+{
+  iterator iter = tlsEnd();
   iter += m_pCommon->size();
   return iter;
 }
 
 SymbolCategory::const_iterator SymbolCategory::commonBegin() const
 {
-  return localEnd();
+  return tlsEnd();
 }
 
 SymbolCategory::const_iterator SymbolCategory::commonEnd() const
 {
-  const_iterator iter = localEnd();
+  const_iterator iter = tlsEnd();
   iter += m_pCommon->size();
   return iter;
 }
diff --git a/lib/Object/Android.mk b/lib/Object/Android.mk
new file mode 100644
index 0000000..56334f9
--- /dev/null
+++ b/lib/Object/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_object_SRC_FILES := \
+  ObjectBuilder.cpp \
+  ObjectLinker.cpp \
+  SectionMap.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_object_SRC_FILES)
+LOCAL_MODULE:= libmcldObject
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_object_SRC_FILES)
+LOCAL_MODULE:= libmcldObject
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/lib/Object/ObjectBuilder.cpp b/lib/Object/ObjectBuilder.cpp
new file mode 100644
index 0000000..ec09901
--- /dev/null
+++ b/lib/Object/ObjectBuilder.cpp
@@ -0,0 +1,181 @@
+//===- ObjectBuilder.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/Object/SectionMap.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/Fragment/AlignFragment.h>
+#include <mcld/Fragment/NullFragment.h>
+#include <mcld/Fragment/FillFragment.h>
+
+#include <llvm/Support/Casting.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ObjectBuilder
+//===----------------------------------------------------------------------===//
+ObjectBuilder::ObjectBuilder(const LinkerConfig& pConfig, Module& pTheModule)
+  : m_Config(pConfig), m_Module(pTheModule) {
+}
+
+/// CreateSection - create an output section.
+LDSection* ObjectBuilder::CreateSection(const std::string& pName,
+                                        LDFileFormat::Kind pKind,
+                                        uint32_t pType,
+                                        uint32_t pFlag,
+                                        uint32_t pAlign)
+{
+  // try to get one from output LDSection
+  const SectionMap::NamePair& pair = m_Config.scripts().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);
+  return output_sect;
+}
+
+/// MergeSection - merge the pInput section to the pOutput section
+bool ObjectBuilder::MergeSection(LDSection& pInputSection)
+{
+  const SectionMap::NamePair& pair =
+              m_Config.scripts().sectionMap().find(pInputSection.name());
+  std::string output_name = (pair.isNull())?pInputSection.name():pair.to;
+  LDSection* target = m_Module.getSection(output_name);
+
+  if (NULL == target) {
+    target = LDSection::Create(output_name,
+                               pInputSection.kind(),
+                               pInputSection.type(),
+                               pInputSection.flag());
+    target->setAlign(pInputSection.align());
+    m_Module.getSectionTable().push_back(target);
+  }
+
+  switch (target->kind()) {
+    // Some *OUTPUT sections should not be merged.
+    case LDFileFormat::Relocation:
+    case LDFileFormat::NamePool:
+      /** do nothing **/
+      return true;
+    case LDFileFormat::EhFrame: {
+      EhFrame* eh_frame = NULL;
+      if (target->hasEhFrame())
+        eh_frame = target->getEhFrame();
+      else
+        eh_frame = IRBuilder::CreateEhFrame(*target);
+
+      eh_frame->merge(*pInputSection.getEhFrame());
+      return true;
+    }
+    default: {
+      SectionData* data = NULL;
+      if (target->hasSectionData())
+        data = target->getSectionData();
+      else
+        data = IRBuilder::CreateSectionData(*target);
+
+      return MoveSectionData(*pInputSection.getSectionData(), *data);
+    }
+  }
+  return true;
+}
+
+/// MoveSectionData - move the fragments of pTO section data to pTo
+bool ObjectBuilder::MoveSectionData(SectionData& pFrom, SectionData& pTo)
+{
+  assert(&pFrom != &pTo && "Cannot move section data to itself!");
+
+  uint32_t offset = pTo.getSection().size();
+  AlignFragment* align = NULL;
+  if (pFrom.getSection().align() > 1) {
+    // if the align constraint is larger than 1, append an alignment
+    align = new AlignFragment(pFrom.getSection().align(), // alignment
+                              0x0, // the filled value
+                              1u,  // the size of filled value
+                              pFrom.getSection().align() - 1 // max bytes to emit
+                              );
+    align->setOffset(offset);
+    align->setParent(&pTo);
+    pTo.getFragmentList().push_back(align);
+    offset += align->size();
+  }
+
+  // move fragments from pFrom to pTO
+  SectionData::FragmentListType& from_list = pFrom.getFragmentList();
+  SectionData::FragmentListType& to_list = pTo.getFragmentList();
+  SectionData::FragmentListType::iterator frag, fragEnd = from_list.end();
+  for (frag = from_list.begin(); frag != fragEnd; ++frag) {
+    frag->setParent(&pTo);
+    frag->setOffset(offset);
+    offset += frag->size();
+  }
+  to_list.splice(to_list.end(), from_list);
+
+  // append the null fragment
+  NullFragment* null = new NullFragment();
+  null->setParent(&pTo);
+  null->setOffset(offset);
+  pTo.getFragmentList().push_back(null);
+
+  // set up pTo's header
+  pTo.getSection().setSize(offset);
+  if (pFrom.getSection().align() > pTo.getSection().align())
+    pTo.getSection().setAlign(pFrom.getSection().align());
+
+  return true;
+}
+
+/// AppendFragment - To append pFrag to the given SectionData pSD.
+uint64_t ObjectBuilder::AppendFragment(Fragment& pFrag,
+                                       SectionData& pSD,
+                                       uint32_t pAlignConstraint)
+{
+  // get initial offset.
+  uint32_t offset = 0;
+  if (!pSD.empty())
+    offset = pSD.back().getOffset() + pSD.back().size();
+
+  AlignFragment* align = NULL;
+  if (pAlignConstraint > 1) {
+    // if the align constraint is larger than 1, append an alignment
+    align = new AlignFragment(pAlignConstraint, // alignment
+                              0x0, // the filled value
+                              1u,  // the size of filled value
+                              pAlignConstraint - 1 // max bytes to emit
+                              );
+    align->setOffset(offset);
+    align->setParent(&pSD);
+    pSD.getFragmentList().push_back(align);
+    offset += align->size();
+  }
+
+  // append the fragment
+  pFrag.setParent(&pSD);
+  pFrag.setOffset(offset);
+  pSD.getFragmentList().push_back(&pFrag);
+
+  // append the null fragment
+  offset += pFrag.size();
+  NullFragment* null = new NullFragment(&pSD);
+  null->setOffset(offset);
+
+  if (NULL != align)
+    return align->size() + pFrag.size();
+  else
+    return pFrag.size();
+}
+
diff --git a/lib/Object/ObjectLinker.cpp b/lib/Object/ObjectLinker.cpp
new file mode 100644
index 0000000..93fdb20
--- /dev/null
+++ b/lib/Object/ObjectLinker.cpp
@@ -0,0 +1,442 @@
+//===- ObjectLinker.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Object/ObjectLinker.h>
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/Module.h>
+#include <mcld/InputTree.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/LD/Archive.h>
+#include <mcld/LD/ArchiveReader.h>
+#include <mcld/LD/ObjectReader.h>
+#include <mcld/LD/DynObjReader.h>
+#include <mcld/LD/GroupReader.h>
+#include <mcld/LD/ObjectWriter.h>
+#include <mcld/LD/DynObjWriter.h>
+#include <mcld/LD/ExecWriter.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/Layout.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/Support/RealPath.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <llvm/Support/Casting.h>
+
+using namespace llvm;
+using namespace mcld;
+
+ObjectLinker::ObjectLinker(const LinkerConfig& pConfig,
+                           Module& pModule,
+                           InputBuilder& pInputBuilder,
+                           TargetLDBackend& pLDBackend)
+  : m_Config(pConfig),
+    m_Module(pModule),
+    m_InputBuilder(pInputBuilder),
+    m_pLinker(NULL),
+    m_LDBackend(pLDBackend),
+    m_pObjectReader(NULL),
+    m_pDynObjReader(NULL),
+    m_pArchiveReader(NULL),
+    m_pObjectWriter(NULL),
+    m_pDynObjWriter(NULL),
+    m_pExecWriter(NULL),
+    m_pGroupReader(NULL)
+{
+  // set up soname
+  if (!m_Config.options().soname().empty()) {
+    m_Module.setName(m_Config.options().soname());
+  }
+}
+
+ObjectLinker::~ObjectLinker()
+{
+  delete m_pLinker;
+  delete m_pObjectReader;
+  delete m_pDynObjReader;
+  delete m_pArchiveReader;
+  delete m_pObjectWriter;
+  delete m_pDynObjWriter;
+  delete m_pExecWriter;
+  delete m_pGroupReader;
+}
+
+/// initFragmentLinker - initialize FragmentLinker
+///  Connect all components with FragmentLinker
+bool ObjectLinker::initFragmentLinker()
+{
+  if (NULL == m_pLinker) {
+    m_pLinker = new FragmentLinker(m_Config,
+                                   m_Module,
+                                   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_pLinker);
+  m_pArchiveReader = m_LDBackend.createArchiveReader(m_Module);
+  m_pDynObjReader  = m_LDBackend.createDynObjReader(*m_pLinker);
+  m_pObjectWriter  = m_LDBackend.createObjectWriter(*m_pLinker);
+  m_pDynObjWriter  = m_LDBackend.createDynObjWriter(*m_pLinker);
+  m_pExecWriter    = m_LDBackend.createExecWriter(*m_pLinker);
+  m_pGroupReader   = new GroupReader(m_Module, *m_pObjectReader,
+                                     *m_pDynObjReader, *m_pArchiveReader);
+
+  // initialize RelocationFactory
+  m_LDBackend.initRelocFactory(*m_pLinker);
+
+  // initialize BranchIslandFactory
+  m_LDBackend.initBRIslandFactory();
+
+  // initialize StubFactory
+  m_LDBackend.initStubFactory();
+
+  // initialize target stubs
+  m_LDBackend.initTargetStubs(*m_pLinker);
+  return true;
+}
+
+/// initStdSections - initialize standard sections
+bool ObjectLinker::initStdSections()
+{
+  ObjectBuilder builder(m_Config, m_Module);
+
+  // initialize standard sections
+  if (!m_LDBackend.initStdSections(builder))
+    return false;
+
+  // initialize target-dependent sections
+  m_LDBackend.initTargetSections(m_Module, builder);
+
+  return true;
+}
+
+void ObjectLinker::normalize()
+{
+  // -----  set up inputs  ----- //
+  Module::input_iterator input, inEnd = m_Module.input_end();
+  for (input = m_Module.input_begin(); input!=inEnd; ++input) {
+    // is a group node
+    if (isGroup(input)) {
+      getGroupReader()->readGroup(input, m_InputBuilder, m_Config);
+      continue;
+    }
+
+    // already got type - for example, bitcode or external OIR (object
+    // intermediate representation)
+    if ((*input)->type() == Input::Script ||
+        (*input)->type() == Input::Archive ||
+        (*input)->type() == Input::External)
+      continue;
+
+    if (Input::Object == (*input)->type()) {
+      m_Module.getObjectList().push_back(*input);
+      continue;
+    }
+
+    if (Input::DynObj == (*input)->type()) {
+      m_Module.getLibraryList().push_back(*input);
+      continue;
+    }
+
+    // is a relocatable object file
+    if (getObjectReader()->isMyFormat(**input)) {
+      (*input)->setType(Input::Object);
+      getObjectReader()->readHeader(**input);
+      getObjectReader()->readSections(**input);
+      getObjectReader()->readSymbols(**input);
+      m_Module.getObjectList().push_back(*input);
+    }
+    // is a shared object file
+    else if (getDynObjReader()->isMyFormat(**input)) {
+      (*input)->setType(Input::DynObj);
+      getDynObjReader()->readHeader(**input);
+      getDynObjReader()->readSymbols(**input);
+      m_Module.getLibraryList().push_back(*input);
+    }
+    // is an archive
+    else if (getArchiveReader()->isMyFormat(**input)) {
+      (*input)->setType(Input::Archive);
+      Archive archive(**input, m_InputBuilder);
+      getArchiveReader()->readArchive(archive);
+      if(archive.numOfObjectMember() > 0) {
+        m_Module.getInputTree().merge<InputTree::Inclusive>(input,
+                                                            archive.inputs());
+      }
+    }
+    else {
+      fatal(diag::err_unrecognized_input_file) << (*input)->path()
+                                               << m_Config.triple().str();
+    }
+  } // end of for
+}
+
+bool ObjectLinker::linkable() const
+{
+  // check we have input and output files
+  if (m_Module.getInputTree().empty()) {
+    error(diag::err_no_inputs);
+    return false;
+  }
+
+  // can not mix -static with shared objects
+  Module::const_lib_iterator lib, libEnd = m_Module.lib_end();
+  for (lib = m_Module.lib_begin(); lib != libEnd; ++lib) {
+    if((*lib)->attribute()->isStatic()) {
+      error(diag::err_mixed_shared_static_objects)
+                                      << (*lib)->name() << (*lib)->path();
+      return false;
+    }
+  }
+
+  // can not mix -r with shared objects
+  return true;
+}
+
+/// readRelocations - read all relocation entries
+///
+/// All symbols should be read and resolved before this function.
+bool ObjectLinker::readRelocations()
+{
+  // Bitcode is read by the other path. This function reads relocation sections
+  // in object files.
+  mcld::InputTree::bfs_iterator input, inEnd = m_Module.getInputTree().bfs_end();
+  for (input=m_Module.getInputTree().bfs_begin(); input!=inEnd; ++input) {
+    if ((*input)->type() == Input::Object && (*input)->hasMemArea()) {
+      if (!getObjectReader()->readRelocations(**input))
+        return false;
+    }
+    // ignore the other kinds of files.
+  }
+  return true;
+}
+
+/// mergeSections - put allinput sections into output sections
+bool ObjectLinker::mergeSections()
+{
+  ObjectBuilder builder(m_Config, m_Module);
+  Module::obj_iterator obj, objEnd = m_Module.obj_end();
+  for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
+    LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
+    for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
+      switch ((*sect)->kind()) {
+        // 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::Target:
+          if (!m_LDBackend.mergeSection(m_Module, **sect)) {
+            error(diag::err_cannot_merge_section) << (*sect)->name()
+                                                  << (*obj)->name();
+            return false;
+          }
+          break;
+        case LDFileFormat::EhFrame: {
+          if (!(*sect)->hasEhFrame())
+            continue; // skip
+
+          if (!builder.MergeSection(**sect)) {
+            error(diag::err_cannot_merge_section) << (*sect)->name()
+                                                  << (*obj)->name();
+            return false;
+          }
+          break;
+        }
+        default: {
+          if (!(*sect)->hasSectionData())
+            continue; // skip
+
+          if (!builder.MergeSection(**sect)) {
+            error(diag::err_cannot_merge_section) << (*sect)->name()
+                                                  << (*obj)->name();
+            return false;
+          }
+          break;
+        }
+      } // end of switch
+    } // for each section
+  } // for each obj
+  return true;
+}
+
+/// addStandardSymbols - shared object and executable files need some
+/// standard symbols
+///   @return if there are some input symbols with the same name to the
+///   standard symbols, return false
+bool ObjectLinker::addStandardSymbols()
+{
+  // create and add section symbols for each output section
+  Module::iterator iter, iterEnd = m_Module.end();
+  for (iter = m_Module.begin(); iter != iterEnd; ++iter) {
+    m_Module.getSectionSymbolSet().add(**iter, m_Module.getNamePool());
+  }
+
+  return m_LDBackend.initStandardSymbols(*m_pLinker, m_Module);
+}
+
+/// addTargetSymbols - some targets, such as MIPS and ARM, need some
+/// target-dependent symbols
+///   @return if there are some input symbols with the same name to the
+///   target symbols, return false
+bool ObjectLinker::addTargetSymbols()
+{
+  m_LDBackend.initTargetSymbols(*m_pLinker);
+  return true;
+}
+
+bool ObjectLinker::scanRelocations()
+{
+  // apply all relocations of all inputs
+  Module::obj_iterator input, inEnd = m_Module.obj_end();
+  for (input = m_Module.obj_begin(); input != inEnd; ++input) {
+    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);
+        // scan relocation
+        if (LinkerConfig::Object != m_Config.codeGenType()) {
+          m_LDBackend.scanRelocation(*relocation,
+                                     *m_pLinker,
+                                     m_Module,
+                                     *(*rs)->getLink());
+        }
+        else {
+          m_LDBackend.partialScanRelocation(*relocation,
+                                     *m_pLinker,
+                                     m_Module,
+                                     *(*rs)->getLink());
+        }
+      } // for all relocations
+    } // for all relocation section
+  } // for all inputs
+  return true;
+}
+
+/// prelayout - help backend to do some modification before layout
+bool ObjectLinker::prelayout()
+{
+  // finalize the section symbols, set their fragment reference and push them
+  // into output symbol table
+  Module::iterator iter, iterEnd = m_Module.end();
+  for (iter = m_Module.begin(); iter != iterEnd; ++iter) {
+    LDSection* section = *iter;
+    if (0x0 == section->size() || LDFileFormat::Relocation == section->kind())
+      continue;
+    m_Module.getSectionSymbolSet().finalize(
+                                           *section, m_Module.getSymbolTable());
+  }
+
+  m_LDBackend.preLayout(m_Module, *m_pLinker);
+
+  m_LDBackend.allocateCommonSymbols(m_Module);
+
+  /// check program interpreter - computer the name size of the runtime dyld
+  if (!m_pLinker->isStaticLink() &&
+      (LinkerConfig::Exec == m_Config.codeGenType() ||
+       m_Config.options().isPIE() ||
+       m_Config.options().hasDyld()))
+    m_LDBackend.sizeInterp();
+
+  /// measure NamePools - compute the size of name pool sections
+  /// 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
+  /// hash table.
+  m_LDBackend.sizeNamePools(m_Module, m_pLinker->isStaticLink());
+
+  return true;
+}
+
+/// layout - linearly layout all output sections and reserve some space
+/// for GOT/PLT
+///   Because we do not support instruction relaxing in this early version,
+///   if there is a branch can not jump to its target, we return false
+///   directly
+bool ObjectLinker::layout()
+{
+  Layout layout;
+  return layout.layout(m_Module, m_LDBackend, m_Config);
+}
+
+/// prelayout - help backend to do some modification after layout
+bool ObjectLinker::postlayout()
+{
+  m_LDBackend.postLayout(m_Module, *m_pLinker);
+  return true;
+}
+
+/// finalizeSymbolValue - finalize the resolved symbol value.
+///   Before relocate(), after layout(), FragmentLinker should correct value of all
+///   symbol.
+bool ObjectLinker::finalizeSymbolValue()
+{
+  return m_pLinker->finalizeSymbols();
+}
+
+/// relocate - applying relocation entries and create relocation
+/// section in the output files
+/// Create relocation section, asking TargetLDBackend to
+/// read the relocation information into RelocationEntry
+/// and push_back into the relocation section
+bool ObjectLinker::relocation()
+{
+  return m_pLinker->applyRelocations();
+}
+
+/// emitOutput - emit the output file.
+bool ObjectLinker::emitOutput(MemoryArea& pOutput)
+{
+  switch(m_Config.codeGenType()) {
+    case LinkerConfig::Object:
+      getObjectWriter()->writeObject(m_Module, pOutput);
+      return true;
+    case LinkerConfig::DynObj:
+      getDynObjWriter()->writeDynObj(m_Module, pOutput);
+      return true;
+    case LinkerConfig::Exec:
+      getExecWriter()->writeExecutable(m_Module, pOutput);
+      return true;
+    default:
+      fatal(diag::unrecognized_output_file) << m_Config.codeGenType();
+  }
+  return false;
+}
+
+/// postProcessing - do modification after all processes
+bool ObjectLinker::postProcessing(MemoryArea& pOutput)
+{
+  m_pLinker->syncRelocationResult(pOutput);
+
+  // emit .eh_frame_hdr
+  // eh_frame_hdr should be emitted after syncRelocation, because eh_frame_hdr
+  // needs FDE PC value, which will be corrected at syncRelocation
+  m_LDBackend.postProcessing(*m_pLinker, pOutput);
+  return true;
+}
+
diff --git a/lib/Object/SectionMap.cpp b/lib/Object/SectionMap.cpp
new file mode 100644
index 0000000..ce987e3
--- /dev/null
+++ b/lib/Object/SectionMap.cpp
@@ -0,0 +1,118 @@
+//===- SectionMap.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Object/SectionMap.h>
+#include <mcld/ADT/StringHash.h>
+#include <cassert>
+#include <cstring>
+
+using namespace mcld;
+
+
+SectionMap::NamePair SectionMap::NullName;
+
+//===----------------------------------------------------------------------===//
+// SectionMap::NamePair
+//===----------------------------------------------------------------------===//
+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
+{
+  return (&NullName == this);
+}
+
+//===----------------------------------------------------------------------===//
+// SectionMap
+//===----------------------------------------------------------------------===//
+const SectionMap::NamePair& SectionMap::find(const std::string& pFrom) const
+{
+  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;
+    }
+  }
+  return NullName;
+}
+
+SectionMap::NamePair&
+SectionMap::find(const std::string& pFrom, unsigned int pHash)
+{
+  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;
+    }
+  }
+  return NullName;
+}
+
+SectionMap::NamePair& SectionMap::append(const std::string &pFrom,
+                                         const std::string &pTo,
+                                         bool &pExist)
+{
+  NamePair& result = find(pFrom);
+  if (!result.isNull()) {
+    pExist = true;
+    return result;
+  }
+
+  pExist = false;
+  NamePair entry(pFrom, pTo);
+  m_NamePairList.push_back(entry);
+  return m_NamePairList.back();
+}
+
+bool SectionMap::matched(const NamePair& pNamePair,
+                         const std::string& pInput,
+                         unsigned int pHashValue) const
+{
+  if ('*' == pNamePair.from[0])
+    return true;
+
+  if (pNamePair.from.size() > pInput.size())
+    return false;
+
+  if (!StringHash<ES>::may_include(pNamePair.hash, pHashValue))
+    return false;
+
+  if (0 == strncmp(pInput.c_str(),
+                   pNamePair.from.c_str(),
+                   pNamePair.from.size())) {
+    return true;
+  }
+
+  return false;
+}
+
+unsigned int SectionMap::hash(const std::string& pString)
+{
+  static StringHash<ES> hash_func;
+  return hash_func(pString);
+}
+
diff --git a/lib/Support/Android.mk b/lib/Support/Android.mk
index 8e5a7ca..b503a3d 100644
--- a/lib/Support/Android.mk
+++ b/lib/Support/Android.mk
@@ -17,6 +17,8 @@
   Space.cpp \
   SystemUtils.cpp \
   TargetRegistry.cpp  \
+  ToolOutputFile.cpp  \
+  raw_mem_ostream.cpp \
   raw_ostream.cpp
 
 # For the host
diff --git a/lib/Support/FileHandle.cpp b/lib/Support/FileHandle.cpp
index 6d43a4c..4800bfa 100644
--- a/lib/Support/FileHandle.cpp
+++ b/lib/Support/FileHandle.cpp
@@ -9,10 +9,31 @@
 #include <mcld/Support/FileHandle.h>
 #include <mcld/Support/FileSystem.h>
 #include <errno.h>
-#include <fcntl.h>
+
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+#if defined(HAVE_FCNTL_H)
+# include <fcntl.h>
+#endif
+
 #include <sys/stat.h>
 #include <sys/mman.h>
 
+#if defined(_MSC_VER)
+#include <io.h>
+#include <fcntl.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 mcld;
 
 //===----------------------------------------------------------------------===//
@@ -39,18 +60,18 @@
 
   if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
     result |= O_RDWR;
-  else if (pMode & FileHandle::ReadOnly)
+  else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly))
     result |= O_RDONLY;
-  else if (pMode & FileHandle::WriteOnly)
+  else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly))
     result |= O_WRONLY;
 
-  if (pMode & FileHandle::Append)
+  if (FileHandle::Append == (pMode & FileHandle::Append))
     result |= O_APPEND;
 
-  if (pMode & FileHandle::Create)
+  if (FileHandle::Create == (pMode & FileHandle::Create))
     result |= O_CREAT;
 
-  if (pMode & FileHandle::Truncate)
+  if (FileHandle::Truncate == (pMode & FileHandle::Truncate))
     result |= O_TRUNC;
 
   return result;
@@ -68,31 +89,6 @@
 }
 
 bool FileHandle::open(const sys::fs::Path& pPath,
-                      FileHandle::OpenMode pMode)
-{
-  if (isOpened() || Unknown == pMode) {
-    setState(BadBit);
-    return false;
-  }
-
-  m_OpenMode = pMode;
-  m_Handler = ::open(pPath.native().c_str(), oflag(pMode));
-  m_Path = pPath;
-  if (-1 == m_Handler) {
-    m_OpenMode = NotOpen;
-    setState(FailBit);
-    return false;
-  }
-
-  if (!get_size(m_Handler, m_Size)) {
-    setState(FailBit);
-    return false;
-  }
-
-  return true;
-}
-
-bool FileHandle::open(const sys::fs::Path& pPath,
                       FileHandle::OpenMode pMode,
                       FileHandle::Permission pPerm)
 {
@@ -102,7 +98,11 @@
   }
 
   m_OpenMode = pMode;
-  m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
+  if (System == pPerm)
+    m_Handler = sys::fs::detail::open(pPath, oflag(pMode));
+  else
+    m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
+
   m_Path = pPath;
   if (-1 == m_Handler) {
     m_OpenMode = NotOpen;
diff --git a/lib/Support/MemoryArea.cpp b/lib/Support/MemoryArea.cpp
index 844d8f6..3a3fa0c 100644
--- a/lib/Support/MemoryArea.cpp
+++ b/lib/Support/MemoryArea.cpp
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/Support/RegionFactory.h>
 #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>
@@ -17,21 +17,26 @@
 //===--------------------------------------------------------------------===//
 // 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(RegionFactory& pRegionFactory, Space& pUniverse)
-  : m_RegionFactory(pRegionFactory), m_pFileHandle(NULL) {
-  m_SpaceList.push_back(&pUniverse);
+MemoryArea::MemoryArea(Space& pUniverse)
+  : m_pFileHandle(NULL) {
+  m_SpaceMap.insert(std::make_pair(Key(pUniverse.start(), pUniverse.size()),
+                                   &pUniverse));
 }
 
-MemoryArea::MemoryArea(RegionFactory& pRegionFactory, FileHandle& pFileHandle)
-  : m_RegionFactory(pRegionFactory), m_pFileHandle(&pFileHandle) {
+MemoryArea::MemoryArea(FileHandle& pFileHandle)
+  : m_pFileHandle(&pFileHandle) {
 }
 
 MemoryArea::~MemoryArea()
 {
+  SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
+  for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
+    if (space->second != NULL)
+      Space::Destroy(space->second);
+  }
 }
 
 // The layout of MemorySpace in the virtual memory space
@@ -62,8 +67,8 @@
       unreachable(diag::err_out_of_range_region) << pOffset << pLength;
     }
 
-    space = Space::createSpace(*m_pFileHandle, pOffset, pLength);
-    m_SpaceList.push_back(space);
+    space = Space::Create(*m_pFileHandle, pOffset, pLength);
+    m_SpaceMap.insert(std::make_pair(Key(pOffset, pLength), space));
   }
 
   // adjust r_start
@@ -71,7 +76,7 @@
   void* r_start = space->memory() + distance;
 
   // now, we have a legal space to hold the new MemoryRegion
-  return m_RegionFactory.produce(*space, r_start, pLength);
+  return MemoryRegion::Create(r_start, pLength, *space);
 }
 
 // release - release a MemoryRegion
@@ -81,7 +86,7 @@
     return;
 
   Space *space = pRegion->parent();
-  m_RegionFactory.destruct(pRegion);
+  MemoryRegion::Destroy(pRegion);
 
   if (0 == space->numOfRegions()) {
 
@@ -91,10 +96,10 @@
       // Space.
       if (m_pFileHandle->isWritable()) {
         // synchronize writable space before we release it.
-        Space::syncSpace(space, *m_pFileHandle);
+        Space::Sync(space, *m_pFileHandle);
       }
-      Space::releaseSpace(space, *m_pFileHandle);
-      m_SpaceList.erase(space);
+      m_SpaceMap.erase(Key(space->start(), space->size()));
+      Space::Release(space, *m_pFileHandle);
     }
   }
 }
@@ -106,46 +111,44 @@
     return;
 
   if (m_pFileHandle->isWritable()) {
-    SpaceList::iterator space, sEnd = m_SpaceList.end();
-    for (space = m_SpaceList.begin(); space != sEnd; ++space) {
-      Space::syncSpace(space, *m_pFileHandle);
-      Space::releaseSpace(space, *m_pFileHandle);
+    SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
+    for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
+      Space::Sync(space->second, *m_pFileHandle);
+      Space::Release(space->second, *m_pFileHandle);
     }
   }
   else {
-    SpaceList::iterator space, sEnd = m_SpaceList.end();
-    for (space = m_SpaceList.begin(); space != sEnd; ++space)
-      Space::releaseSpace(space, *m_pFileHandle);
+    SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
+    for (space = m_SpaceMap.begin(); space != sEnd; ++space)
+      Space::Release(space->second, *m_pFileHandle);
   }
 
-  m_SpaceList.clear();
+  for (SpaceMapType::iterator space = m_SpaceMap.begin(),
+         sEnd = m_SpaceMap.end(); space != sEnd; ++space) {
+    if (space->second != NULL)
+      Space::Destroy(space->second);
+  }
+  m_SpaceMap.clear();
 }
 
 //===--------------------------------------------------------------------===//
 // SpaceList methods
+//===--------------------------------------------------------------------===//
 Space* MemoryArea::find(size_t pOffset, size_t pLength)
 {
-  SpaceList::iterator sIter, sEnd = m_SpaceList.end();
-  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
-    if (sIter->start() <= pOffset &&
-       (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
-      // within
-      return sIter;
-    }
-  }
+  SpaceMapType::iterator it = m_SpaceMap.find(Key(pOffset, pLength));
+  if (it != m_SpaceMap.end())
+    return it->second;
+
   return NULL;
 }
 
 const Space* MemoryArea::find(size_t pOffset, size_t pLength) const
 {
-  SpaceList::const_iterator sIter, sEnd = m_SpaceList.end();
-  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
-    if (sIter->start() <= pOffset &&
-       (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
-      // within
-      return sIter;
-    }
-  }
+  SpaceMapType::const_iterator it = m_SpaceMap.find(Key(pOffset, pLength));
+  if (it != m_SpaceMap.end())
+    return it->second;
+
   return NULL;
 }
 
diff --git a/lib/Support/MemoryAreaFactory.cpp b/lib/Support/MemoryAreaFactory.cpp
index 3da07d5..224e0a6 100644
--- a/lib/Support/MemoryAreaFactory.cpp
+++ b/lib/Support/MemoryAreaFactory.cpp
@@ -8,7 +8,6 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/Support/MemoryAreaFactory.h>
 #include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/RegionFactory.h>
 #include <mcld/Support/SystemUtils.h>
 #include <mcld/Support/Space.h>
 
@@ -16,12 +15,9 @@
 
 //===----------------------------------------------------------------------===//
 // MemoryAreaFactory
+//===----------------------------------------------------------------------===//
 MemoryAreaFactory::MemoryAreaFactory(size_t pNum)
   : GCFactory<MemoryArea, 0>(pNum) {
-  // For each loaded file, MCLinker must load ELF header, section header,
-  // symbol table, and string table. So, we set the size of chunk quadruple
-  // larger than the number of input files.
-  m_pRegionFactory = new RegionFactory(pNum*4);
 }
 
 MemoryAreaFactory::~MemoryAreaFactory()
@@ -33,8 +29,6 @@
     }
     delete rec->handle;
   }
-
-  delete m_pRegionFactory;
 }
 
 MemoryArea*
@@ -51,7 +45,7 @@
     }
 
     MemoryArea* result = allocate();
-    new (result) MemoryArea(*m_pRegionFactory, *handler);
+    new (result) MemoryArea(*handler);
 
     m_HandleToArea.push_back(handler, result);
     return result;
@@ -75,7 +69,7 @@
     }
 
     MemoryArea* result = allocate();
-    new (result) MemoryArea(*m_pRegionFactory, *handler);
+    new (result) MemoryArea(*handler);
 
     m_HandleToArea.push_back(handler, result);
     return result;
@@ -84,6 +78,26 @@
   return map_result.area;
 }
 
+MemoryArea* MemoryAreaFactory::produce(void* pMemBuffer, size_t pSize)
+{
+  Space* space = Space::Create(pMemBuffer, pSize);
+  MemoryArea* result = allocate();
+  new (result) MemoryArea(*space);
+  return result;
+}
+
+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;
+}
+
 void MemoryAreaFactory::destruct(MemoryArea* pArea)
 {
   m_HandleToArea.erase(pArea);
@@ -93,24 +107,3 @@
   deallocate(pArea);
 }
 
-MemoryArea*
-MemoryAreaFactory::create(void* pMemBuffer, size_t pSize)
-{
-  Space* space = new Space(Space::EXTERNAL, pMemBuffer, pSize);
-  MemoryArea* result = allocate();
-  new (result) MemoryArea(*m_pRegionFactory, *space);
-  return result;
-}
-
-MemoryArea*
-MemoryAreaFactory::create(int pFD, FileHandle::OpenMode pMode)
-{
-  FileHandle* handler = new FileHandle();
-  handler->delegate(pFD, pMode);
-  
-  MemoryArea* result = allocate();
-  new (result) MemoryArea(*m_pRegionFactory, *handler);
-
-  return result;
-}
-
diff --git a/lib/Support/MemoryRegion.cpp b/lib/Support/MemoryRegion.cpp
index 32e790b..410500a 100644
--- a/lib/Support/MemoryRegion.cpp
+++ b/lib/Support/MemoryRegion.cpp
@@ -7,18 +7,51 @@
 //
 //===----------------------------------------------------------------------===//
 #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(Space& pParent,
-                           MemoryRegion::Address pVMAStart,
-                           size_t pSize)
-  : m_Parent(pParent), m_VMAStart(pVMAStart), m_Length(pSize) {
+//===----------------------------------------------------------------------===//
+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/MsgHandling.cpp b/lib/Support/MsgHandling.cpp
index d7611d2..fdcf13f 100644
--- a/lib/Support/MsgHandling.cpp
+++ b/lib/Support/MsgHandling.cpp
@@ -9,10 +9,16 @@
 #include <mcld/LD/DiagnosticEngine.h>
 #include <mcld/LD/DiagnosticLineInfo.h>
 #include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/TextDiagnosticPrinter.h>
 #include <mcld/LD/MsgHandler.h>
 #include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/raw_ostream.h>
+
 #include <llvm/Support/ManagedStatic.h>
 #include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/Signals.h>
+
+#include <cstdlib>
 
 using namespace mcld;
 
@@ -22,18 +28,14 @@
 static llvm::ManagedStatic<DiagnosticEngine> g_pEngine;
 
 void
-mcld::InitializeDiagnosticEngine(const mcld::MCLDInfo& pLDInfo,
-                                 DiagnosticLineInfo* pLineInfo,
+mcld::InitializeDiagnosticEngine(const mcld::LinkerConfig& pConfig,
                                  DiagnosticPrinter* pPrinter)
 {
-  g_pEngine->reset(pLDInfo);
-  if (NULL != pLineInfo)
-    g_pEngine->setLineInfo(*pLineInfo);
-
+  g_pEngine->reset(pConfig);
   if (NULL != pPrinter)
     g_pEngine->setPrinter(*pPrinter, false);
   else {
-    DiagnosticPrinter* printer = new DiagnosticPrinter();
+    DiagnosticPrinter* printer = new TextDiagnosticPrinter(mcld::errs(), pConfig);
     g_pEngine->setPrinter(*printer, true);
   }
 }
@@ -43,3 +45,21 @@
   return *g_pEngine;
 }
 
+bool mcld::Diagnose()
+{
+  if (g_pEngine->getPrinter()->getNumErrors() > 0) {
+    // If we reached here, we are failing ungracefully. Run the interrupt handlers
+    // to make sure any special cleanups get done, in particular that we remove
+    // files registered with RemoveFileOnSignal.
+    llvm::sys::RunInterruptHandlers();
+    g_pEngine->getPrinter()->finish();
+    return false;
+  }
+  return true;
+}
+
+void mcld::FinalizeDiagnosticEngine()
+{
+  g_pEngine->getPrinter()->finish();
+}
+
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index 7f516f6..d359162 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -148,6 +148,16 @@
   return Path();
 }
 
+Path Path::filename() const
+{
+  size_t pos = m_PathName.find_last_of(separator);
+  if (pos != StringType::npos) {
+    ++pos;
+    return Path(m_PathName.substr(pos));
+  }
+  return Path(*this);
+}
+
 Path Path::stem() const
 {
   size_t begin_pos = m_PathName.find_last_of(separator)+1;
diff --git a/lib/Support/RegionFactory.cpp b/lib/Support/RegionFactory.cpp
index ddce433..7ed87f1 100644
--- a/lib/Support/RegionFactory.cpp
+++ b/lib/Support/RegionFactory.cpp
@@ -7,34 +7,23 @@
 //
 //===----------------------------------------------------------------------===//
 #include <mcld/Support/RegionFactory.h>
-#include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/Space.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // RegionFactory
-RegionFactory::RegionFactory(size_t pNum)
-  : GCFactory<MemoryRegion, 0>(pNum) {
-}
-
-RegionFactory::~RegionFactory()
-{
-}
-
-MemoryRegion* RegionFactory::produce(Space& pSpace, void* pVMAStart, size_t pSize)
+//===----------------------------------------------------------------------===//
+MemoryRegion*
+RegionFactory::produce(Address pVMAStart, size_t pSize)
 {
   MemoryRegion* result = Alloc::allocate();
-  new (result) MemoryRegion(pSpace,
-                            static_cast<const MemoryRegion::Address>(pVMAStart),
-                            pSize);
-  pSpace.addRegion(*result);
+  new (result) MemoryRegion(pVMAStart, pSize);
   return result;
 }
 
 void RegionFactory::destruct(MemoryRegion* pRegion)
 {
-  pRegion->parent()->removeRegion(*pRegion);
   destroy(pRegion);
   deallocate(pRegion);
 }
diff --git a/lib/Support/Space.cpp b/lib/Support/Space.cpp
index 4024da1..6ec2c53 100644
--- a/lib/Support/Space.cpp
+++ b/lib/Support/Space.cpp
@@ -20,11 +20,12 @@
 
 //===----------------------------------------------------------------------===//
 // 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)
@@ -46,6 +47,7 @@
 
 //===----------------------------------------------------------------------===//
 // Space
+//===----------------------------------------------------------------------===//
 Space::Space()
   : m_Data(NULL), m_StartOffset(0), m_Size(0),
     m_RegionCount(0), m_Type(UNALLOCATED) {
@@ -62,13 +64,18 @@
   // do nothing. m_Data is deleted by @ref releaseSpace
 }
 
-Space* Space::createSpace(FileHandle& pHandler,
-                          size_t pStart, size_t pSize)
+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;
+  void* memory = NULL;
   Space* result = NULL;
-  size_t start, size = 0, total_offset;
+  size_t start = 0, size = 0, total_offset;
   switch(type = policy(pStart, pSize)) {
     case ALLOCATED_ARRAY: {
       // adjust total_offset, start and size
@@ -134,7 +141,13 @@
   return result;
 }
 
-void Space::releaseSpace(Space* pSpace, FileHandle& pHandler)
+void Space::Destroy(Space*& pSpace)
+{
+  delete pSpace;
+  pSpace = NULL;
+}
+
+void Space::Release(Space* pSpace, FileHandle& pHandler)
 {
   if (NULL == pSpace)
     return;
@@ -152,7 +165,7 @@
   } // end of switch
 }
 
-void Space::syncSpace(Space* pSpace, FileHandle& pHandler)
+void Space::Sync(Space* pSpace, FileHandle& pHandler)
 {
   if (NULL == pSpace || !pHandler.isWritable())
     return;
diff --git a/lib/Support/ToolOutputFile.cpp b/lib/Support/ToolOutputFile.cpp
new file mode 100644
index 0000000..80bae12
--- /dev/null
+++ b/lib/Support/ToolOutputFile.cpp
@@ -0,0 +1,108 @@
+//===- ToolOutputFile.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/ToolOutputFile.h>
+
+#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;
+
+//===----------------------------------------------------------------------===//
+// CleanupInstaller
+//===----------------------------------------------------------------------===//
+ToolOutputFile::CleanupInstaller::CleanupInstaller(const std::string& pName)
+  : Keep(false), m_Filename(pName) {
+  // Arrange for the file to be deleted if the process is killed.
+  if (m_Filename != "-")
+    llvm::sys::RemoveFileOnSignal(llvm::sys::Path(m_Filename));
+}
+
+ToolOutputFile::CleanupInstaller::~CleanupInstaller()
+{
+  // Delete the file if the client hasn't told us not to.
+  if (!Keep && m_Filename != "-")
+    llvm::sys::Path(m_Filename).eraseFromDisk();
+
+  // Ok, the file is successfully written and closed, or deleted. There's no
+  // further need to clean it up on signals.
+  if (m_Filename != "-")
+    llvm::sys::DontRemoveFileOnSignal(llvm::sys::Path(m_Filename));
+}
+
+//===----------------------------------------------------------------------===//
+// ToolOutputFile
+//===----------------------------------------------------------------------===//
+ToolOutputFile::ToolOutputFile(const sys::fs::Path& pPath,
+                               FileHandle::OpenMode pMode,
+                               FileHandle::Permission pPermission)
+  : m_Installer(pPath.native()),
+    m_pMemoryArea(NULL),
+    m_pOStream(NULL),
+    m_pFOStream(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());
+    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;
+}
+
+void ToolOutputFile::keep()
+{
+  m_Installer.Keep = true;
+}
+
+/// mem_os - Return the contained raw_mem_ostream.
+raw_mem_ostream& ToolOutputFile::mem_os()
+{
+  assert(NULL != m_pOStream);
+  return *m_pOStream;
+}
+
+/// formatted_os - Return the containeed formatted_raw_ostream.
+/// Since formatted_os is rarely used, we lazily initialize it.
+llvm::formatted_raw_ostream& ToolOutputFile::formatted_os()
+{
+  if (NULL == m_pFOStream) {
+    assert(NULL != m_pOStream);
+    m_pFOStream = new llvm::formatted_raw_ostream(*m_pOStream);
+  }
+
+  return *m_pFOStream;
+}
+
+/// memory - Return the contained MemoryArea.
+MemoryArea& ToolOutputFile::memory()
+{
+  assert(NULL != m_pOStream);
+  return m_pOStream->getMemoryArea();
+}
+
diff --git a/lib/Support/raw_mem_ostream.cpp b/lib/Support/raw_mem_ostream.cpp
new file mode 100644
index 0000000..c3066dd
--- /dev/null
+++ b/lib/Support/raw_mem_ostream.cpp
@@ -0,0 +1,46 @@
+//===- 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/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index 2453c2c..e294bc3 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -8,31 +8,52 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/Support/raw_ostream.h>
 
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined(_MSC_VER)
+#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 mcld;
 
 //===----------------------------------------------------------------------===//
 // raw_ostream
+//===----------------------------------------------------------------------===//
 mcld::raw_fd_ostream::raw_fd_ostream(const char *pFilename,
-                               std::string &pErrorInfo,
-                               unsigned int pFlags,
-                               const MCLDInfo* pLDInfo)
-  : llvm::raw_fd_ostream(pFilename, pErrorInfo, pFlags), m_pLDInfo(pLDInfo) {
+                                     std::string &pErrorInfo,
+                                     unsigned int pFlags)
+  : llvm::raw_fd_ostream(pFilename, pErrorInfo, pFlags),
+    m_bConfigColor(false),
+    m_bSetColor(false) {
 }
 
 mcld::raw_fd_ostream::raw_fd_ostream(int pFD,
                                bool pShouldClose,
-                               bool pUnbuffered,
-                               const MCLDInfo* pLDInfo)
-  : llvm::raw_fd_ostream(pFD, pShouldClose, pUnbuffered), m_pLDInfo(pLDInfo) {
+                               bool pUnbuffered)
+  : llvm::raw_fd_ostream(pFD, pShouldClose, pUnbuffered),
+    m_bConfigColor(false),
+    m_bSetColor(false) {
 }
 
 mcld::raw_fd_ostream::~raw_fd_ostream()
 {
 }
 
-void mcld::raw_fd_ostream::setLDInfo(const MCLDInfo& pLDInfo)
+void mcld::raw_fd_ostream::setColor(bool pEnable)
 {
-  m_pLDInfo = &pLDInfo;
+  m_bConfigColor = true;
+  m_bSetColor = pEnable;
 }
 
 llvm::raw_ostream &
@@ -52,22 +73,19 @@
   return llvm::raw_fd_ostream::resetColor();
 }
 
-// FIXME: migrate to newer LLVM
-/**
 llvm::raw_ostream& mcld::raw_fd_ostream::reverseColor()
 {
   if (!is_displayed())
     return *this;
   return llvm::raw_ostream::reverseColor();
 }
-**/
 
 bool mcld::raw_fd_ostream::is_displayed() const
 {
-  if (NULL == m_pLDInfo)
-    return llvm::raw_fd_ostream::is_displayed();
+  if (m_bConfigColor)
+    return m_bSetColor;
 
-  return m_pLDInfo->options().color();
+  return llvm::raw_fd_ostream::is_displayed();
 }
 
 //===----------------------------------------------------------------------===//
@@ -77,19 +95,13 @@
   // Set buffer settings to model stdout behavior.
   // Delete the file descriptor when the program exists, forcing error
   // detection. If you don't want this behavior, don't use outs().
-  static mcld::raw_fd_ostream S(STDOUT_FILENO, true, NULL);
+  static mcld::raw_fd_ostream S(STDOUT_FILENO, true);
   return S;
 }
 
 mcld::raw_fd_ostream& mcld::errs() {
   // Set standard error to be unbuffered by default.
-  static mcld::raw_fd_ostream S(STDERR_FILENO, false, true, NULL);
+  static mcld::raw_fd_ostream S(STDERR_FILENO, false, true);
   return S;
 }
 
-void mcld::InitializeOStreams(const MCLDInfo& pLDInfo)
-{
-  outs().setLDInfo(pLDInfo);
-  errs().setLDInfo(pLDInfo);
-}
-
diff --git a/lib/Target/ARM/ARMDiagnostic.cpp b/lib/Target/ARM/ARMDiagnostic.cpp
index d6f3988..b63a192 100644
--- a/lib/Target/ARM/ARMDiagnostic.cpp
+++ b/lib/Target/ARM/ARMDiagnostic.cpp
@@ -31,7 +31,7 @@
 
 //==========================
 // InitializeARMDiagnostic
-extern "C" void LLVMInitializeARMDiagnosticLineInfo() {
+extern "C" void MCLDInitializeARMDiagnosticLineInfo() {
   // Register the linker frontend
   mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheARMTarget, createARMDiagLineInfo);
   mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheThumbTarget, createARMDiagLineInfo);
diff --git a/lib/Target/ARM/ARMELFMCLinker.cpp b/lib/Target/ARM/ARMELFMCLinker.cpp
new file mode 100644
index 0000000..daccc84
--- /dev/null
+++ b/lib/Target/ARM/ARMELFMCLinker.cpp
@@ -0,0 +1,25 @@
+//===- ARMELFMCLinker.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#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) {
+}
+
+ARMELFMCLinker::~ARMELFMCLinker()
+{
+}
+
diff --git a/lib/Target/ARM/ARMELFMCLinker.h b/lib/Target/ARM/ARMELFMCLinker.h
new file mode 100644
index 0000000..91f297f
--- /dev/null
+++ b/lib/Target/ARM/ARMELFMCLinker.h
@@ -0,0 +1,37 @@
+//===- ARMELFMCLinker.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ARM_ELF_SECTION_LINKER_H
+#define ARM_ELF_SECTION_LINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/ELFMCLinker.h>
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+
+/** \class ARMELFMCLinker
+ *  \brief ARMELFMCLinker sets up the environment for linking.
+ */
+class ARMELFMCLinker : public ELFMCLinker
+{
+public:
+  ARMELFMCLinker(LinkerConfig& pConfig,
+                 mcld::Module& pModule,
+                 MemoryArea& pOutput);
+
+  ~ARMELFMCLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMELFSectLinker.cpp b/lib/Target/ARM/ARMELFSectLinker.cpp
deleted file mode 100644
index 0395606..0000000
--- a/lib/Target/ARM/ARMELFSectLinker.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- ARMELFSectLinker.cpp -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "ARMELFSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-ARMELFSectLinker::ARMELFSectLinker(SectLinkerOption &pOption,
-                                   TargetLDBackend &pLDBackend)
-  : SectLinker(pOption,
-               pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attributes
-  info.attrFactory().constraint().enableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().setWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-
-}
-
-ARMELFSectLinker::~ARMELFSectLinker()
-{
-}
-
diff --git a/lib/Target/ARM/ARMELFSectLinker.h b/lib/Target/ARM/ARMELFSectLinker.h
deleted file mode 100644
index ab626b9..0000000
--- a/lib/Target/ARM/ARMELFSectLinker.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- ARMELFSectLinker.h -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef ARM_ELF_SECTION_LINKER_H
-#define ARM_ELF_SECTION_LINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/CodeGen/SectLinker.h>
-
-namespace mcld
-{
-
-/** \class ARMELFSectLinker
- *  \brief ARMELFSectLinker sets up the environment for linking.
- *
- *  \see
- */
-class ARMELFSectLinker : public SectLinker
-{
-public:
-  ARMELFSectLinker(SectLinkerOption &pOption,
-                   mcld::TargetLDBackend &pLDBackend);
-
-  ~ARMELFSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/ARM/ARMEmulation.cpp b/lib/Target/ARM/ARMEmulation.cpp
new file mode 100644
index 0000000..875d229
--- /dev/null
+++ b/lib/Target/ARM/ARMEmulation.cpp
@@ -0,0 +1,69 @@
+//===- ARMEmulation.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARM.h"
+#include <mcld/LinkerConfig.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/Support/TargetRegistry.h>
+
+namespace mcld {
+
+static bool MCLDEmulateARMELF(LinkerConfig& pConfig)
+{
+  if (!MCLDEmulateELF(pConfig))
+    return false;
+
+  // set up target-dependent constraints of attributes
+  pConfig.attribute().constraint().enableWholeArchive();
+  pConfig.attribute().constraint().enableAsNeeded();
+  pConfig.attribute().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  pConfig.attribute().predefined().unsetWholeArchive();
+  pConfig.attribute().predefined().unsetAsNeeded();
+  pConfig.attribute().predefined().setDynamic();
+
+  // set up section map
+  if (pConfig.codeGenType() != LinkerConfig::Object) {
+    bool exist = false;
+    pConfig.scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
+    pConfig.scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
+    pConfig.scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
+  }
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// emulateARMLD - the help function to emulate ARM ld
+//===----------------------------------------------------------------------===//
+bool emulateARMLD(const std::string& pTriple, LinkerConfig& pConfig)
+{
+  llvm::Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+    return false;
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+    return false;
+  }
+
+  return MCLDEmulateARMELF(pConfig);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// ARMEmulation
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeARMEmulation() {
+  // Register the emulation
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheARMTarget, mcld::emulateARMLD);
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheThumbTarget, mcld::emulateARMLD);
+}
+
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
index 200bcb5..3d2d07a 100644
--- a/lib/Target/ARM/ARMGOT.cpp
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -12,172 +12,134 @@
 
 #include <llvm/Support/Casting.h>
 
+#include <mcld/LD/LDSection.h>
 #include <mcld/LD/LDFileFormat.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 
 namespace {
   const size_t ARMGOTEntrySize = 4;
+  const unsigned int ARMGOT0Num = 3;
 } // end of anonymous namespace
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
 // ARMGOT
-ARMGOT::ARMGOT(LDSection& pSection, SectionData& pSectionData)
-             : GOT(pSection, pSectionData, ARMGOTEntrySize),
-               m_NormalGOTIterator(), m_GOTPLTIterator(),
-               m_GOTPLTBegin(), m_GOTPLTEnd()
+ARMGOT::ARMGOT(LDSection& pSection)
+  : GOT(pSection, ARMGOTEntrySize)
 {
-  GOTEntry* Entry = 0;
-
   // Create GOT0 entries.
-  for (int i = 0; i < 3; i++) {
-    Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
-                                        &m_SectionData);
-
-    if (!Entry)
-      fatal(diag::fail_allocate_memory_got);
-
-    m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
-  }
+  reserve(ARMGOT0Num);
 
   // Skip GOT0 entries.
-  iterator it = m_SectionData.begin();
-
-  for (int i = 1; i < ARMGOT0Num; ++i) {
-    assert((it != m_SectionData.end()) && "Generation of GOT0 entries is incomplete!");
-    ++it;
+  for (unsigned int i = 0; i < ARMGOT0Num; ++i) {
+    consume();
   }
-
-  m_NormalGOTIterator = it;
-  m_GOTPLTIterator = it;
-
-  m_GOTPLTBegin = it;
-  m_GOTPLTEnd = it;
 }
 
 ARMGOT::~ARMGOT()
 {
 }
 
-void ARMGOT::reserveEntry(size_t pNum)
+bool ARMGOT::hasGOT1() const
 {
-  GOTEntry* Entry = 0;
+  return (m_SectionData->size() > ARMGOT0Num);
+}
 
-  for (size_t i = 0; i < pNum; i++) {
-    Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
-                                        &m_SectionData);
-
-    if (!Entry)
-      fatal(diag::fail_allocate_memory_got);
-
-    m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
+void ARMGOT::reserveGOTPLT()
+{
+  Entry* entry = new Entry(0, getEntrySize(), 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<GOT::Entry>(m_GOT.front->getNextNode());
+    }
+  }
+  else {
+    // GOTPLT is not empty
+    if (NULL != m_GOT.front)
+      m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode());
   }
 }
 
-void ARMGOT::reserveGOTPLTEntry()
+void ARMGOT::reserveGOT()
 {
-    GOTEntry* got_entry = 0;
-
-    got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
-
-    if (!got_entry)
-      fatal(diag::fail_allocate_memory_got);
-
-    m_Section.setSize(m_Section.size() + getEntrySize());
-
-    ++m_GOTPLTEnd;
-    ++m_NormalGOTIterator;
+  Entry* entry = new Entry(0, getEntrySize(), 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;
+  }
 }
 
-GOTEntry* ARMGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
+GOT::Entry* ARMGOT::consumeGOTPLT()
 {
-  GOTEntry *&Entry = m_NormalGOTMap[&pInfo];
-  pExist = 1;
+  assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!");
 
-  if (!Entry) {
-    pExist = 0;
-
-    ++m_NormalGOTIterator;
-    assert(m_NormalGOTIterator != m_SectionData.getFragmentList().end()
-           && "The number of GOT Entries and ResolveInfo doesn't match!");
-
-    Entry = llvm::cast<GOTEntry>(&(*m_NormalGOTIterator));
+  if (NULL == m_GOTPLT.last_used) {
+    m_GOTPLT.last_used = m_GOTPLT.front;
   }
+  else {
+    m_GOTPLT.last_used = llvm::cast<GOT::Entry>(m_GOTPLT.last_used->getNextNode());
+    assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!");
+  }
+  return m_GOTPLT.last_used;
+}
 
-  return Entry;
+GOT::Entry* 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<GOT::Entry>(m_GOT.last_used->getNextNode());
+    assert(m_GOT.last_used != NULL && "No GOTn entry to consume!");
+  }
+  return m_GOT.last_used;
 }
 
 void ARMGOT::applyGOT0(uint64_t pAddress)
 {
-  llvm::cast<GOTEntry>
-    (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
+  llvm::cast<Entry>
+    (*(m_SectionData->getFragmentList().begin())).setContent(pAddress);
 }
 
-void ARMGOT::applyAllGOTPLT(uint64_t pPLTBase)
+void ARMGOT::applyGOTPLT(uint64_t pPLTBase)
 {
-  iterator begin = getGOTPLTBegin();
-  iterator end = getGOTPLTEnd();
+  if (NULL == m_GOTPLT.front)
+    return;
 
-  for (;begin != end ;++begin)
-    llvm::cast<GOTEntry>(*begin).setContent(pPLTBase);
-}
+  SectionData::iterator entry(m_GOTPLT.front);
+  SectionData::iterator e_end;
+  if (NULL == m_GOT.front)
+    e_end = m_SectionData->end();
+  else
+    e_end = SectionData::iterator(m_GOT.front);
 
-GOTEntry*& ARMGOT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
-{
-  return m_GOTPLTMap[&pSymbol];
-}
-
-ARMGOT::iterator ARMGOT::begin()
-{
-  return m_SectionData.getFragmentList().begin();
-}
-
-ARMGOT::const_iterator ARMGOT::begin() const
-{
-  return m_SectionData.getFragmentList().begin();
-}
-
-ARMGOT::iterator ARMGOT::end()
-{
-  return m_SectionData.getFragmentList().end();
-}
-
-ARMGOT::const_iterator ARMGOT::end() const
-{
-  return m_SectionData.getFragmentList().end();
-}
-
-ARMGOT::iterator ARMGOT::getNextGOTPLTEntry()
-{
-  return ++m_GOTPLTIterator;
-}
-
-ARMGOT::iterator ARMGOT::getGOTPLTBegin()
-{
-  // Move to the first GOTPLT entry from last GOT0 entry.
-  iterator begin = m_GOTPLTBegin;
-  return ++begin;
-}
-
-const ARMGOT::iterator ARMGOT::getGOTPLTEnd()
-{
-  // Move to end or the first normal GOT entry from the last GOTPLT entry.
-  iterator end = m_GOTPLTEnd;
-  return ++end;
+  while (entry != e_end) {
+    llvm::cast<GOT::Entry>(entry)->setContent(pPLTBase);
+    ++entry;
+  }
 }
 
 uint64_t ARMGOT::emit(MemoryRegion& pRegion)
 {
   uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
 
-  GOTEntry* got = 0;
+  Entry* got = 0;
   unsigned int entry_size = getEntrySize();
   uint64_t result = 0x0;
-  for (iterator it = begin(), ie = end();
-       it != ie; ++it, ++buffer) {
-      got = &(llvm::cast<GOTEntry>((*it)));
+  for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
+      got = &(llvm::cast<Entry>((*it)));
       *buffer = static_cast<uint32_t>(got->getContent());
       result += entry_size;
   }
diff --git a/lib/Target/ARM/ARMGOT.h b/lib/Target/ARM/ARMGOT.h
index 13d3424..1e8f383 100644
--- a/lib/Target/ARM/ARMGOT.h
+++ b/lib/Target/ARM/ARMGOT.h
@@ -15,78 +15,66 @@
 #include <llvm/ADT/DenseMap.h>
 
 #include <mcld/Target/GOT.h>
-#include <mcld/LD/SectionData.h>
 
-namespace mcld
-{
+namespace mcld {
+
 class LDSection;
 class MemoryRegion;
 
 /** \class ARMGOT
  *  \brief ARM Global Offset Table.
+ *
+ *  ARM GOT integrates traditional .got.plt and .got sections into one.
+ *  Traditional .got.plt is placed in the front part of GOT (PLTGOT), and
+ *  traditional .got is placed in the rear part of GOT (GOT).
+ *
+ *  ARM .got
+ *            +--------------+
+ *            |    GOT0      |
+ *            +--------------+
+ *            |    GOTPLT    |
+ *            +--------------+
+ *            |    GOT       |
+ *            +--------------+
+ *
  */
 class ARMGOT : public GOT
 {
-  typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
-
 public:
-  typedef SectionData::iterator iterator;
-  typedef SectionData::const_iterator const_iterator;
-
-  enum {
-    ARMGOT0Num = 3
-  };
-
-public:
-  ARMGOT(LDSection &pSection, SectionData& pSectionData);
+  ARMGOT(LDSection &pSection);
 
   ~ARMGOT();
 
-  iterator begin();
+  void reserveGOTPLT();
 
-  const_iterator begin() const;
+  void reserveGOT();
 
-  iterator end();
+  GOT::Entry* consumeGOT();
 
-  const_iterator end() const;
+  GOT::Entry* consumeGOTPLT();
 
   uint64_t emit(MemoryRegion& pRegion);
-// For GOT0
-public:
+
   void applyGOT0(uint64_t pAddress);
 
-// For normal GOT
-public:
-  // Reserve normal GOT entries.
-  void reserveEntry(size_t pNum = 1);
+  void applyGOTPLT(uint64_t pPLTBase);
 
-  GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
-
-// For GOTPLT
-public:
-  void reserveGOTPLTEntry();
-
-  void applyAllGOTPLT(uint64_t pPLTBase);
-
-  GOTEntry*& lookupGOTPLTMap(const ResolveInfo& pSymbol);
-
-  iterator getNextGOTPLTEntry();
-
-  iterator getGOTPLTBegin();
-
-  const iterator getGOTPLTEnd();
+  bool hasGOT1() const;
 
 private:
-  // For normal GOT entries
-  iterator m_NormalGOTIterator;
-  SymbolIndexMapType m_NormalGOTMap;
+  struct Part {
+  public:
+    Part() : front(NULL), last_used(NULL) { }
 
-  // For GOTPLT entries
-  iterator m_GOTPLTIterator;
-  SymbolIndexMapType m_GOTPLTMap;
+  public:
+    GOT::Entry* front;
+    GOT::Entry* last_used;
+  };
 
-  iterator m_GOTPLTBegin;
-  iterator m_GOTPLTEnd;
+private:
+  Part m_GOTPLT;
+  Part m_GOT;
+
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index a44f1da..a90ae63 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -10,6 +10,10 @@
 #include "ARMELFDynamic.h"
 #include "ARMLDBackend.h"
 #include "ARMRelocationFactory.h"
+#include "ARMToARMStub.h"
+#include "ARMToTHMStub.h"
+#include "THMToTHMStub.h"
+#include "THMToARMStub.h"
 
 #include <cstring>
 
@@ -18,30 +22,39 @@
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Casting.h>
 
-#include <mcld/LD/SectionMap.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/AlignFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MsgHandling.h>
 #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>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
 // ARMGNULDBackend
 //===----------------------------------------------------------------------===//
-ARMGNULDBackend::ARMGNULDBackend()
-  : m_pRelocFactory(NULL),
+ARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig)
+  : GNULDBackend(pConfig),
+    m_pRelocFactory(NULL),
     m_pGOT(NULL),
     m_pPLT(NULL),
     m_pRelDyn(NULL),
     m_pRelPLT(NULL),
     m_pDynamic(NULL),
     m_pGOTSymbol(NULL),
+    m_pEXIDXStart(NULL),
+    m_pEXIDXEnd(NULL),
     m_pEXIDX(NULL),
     m_pEXTAB(NULL),
     m_pAttributes(NULL) {
@@ -49,25 +62,19 @@
 
 ARMGNULDBackend::~ARMGNULDBackend()
 {
-  if (NULL != m_pRelocFactory)
-    delete m_pRelocFactory;
-  if (NULL != m_pGOT)
-    delete m_pGOT;
-  if (NULL != m_pPLT)
-    delete m_pPLT;
-  if (NULL != m_pRelDyn)
-    delete m_pRelDyn;
-  if (NULL != m_pRelPLT)
-    delete m_pRelPLT;
-  if (NULL != m_pDynamic)
-    delete m_pDynamic;
+  delete m_pRelocFactory;
+  delete m_pGOT;
+  delete m_pPLT;
+  delete m_pRelDyn;
+  delete m_pRelPLT;
+  delete m_pDynamic;
 }
 
-bool ARMGNULDBackend::initRelocFactory(const MCLinker& pLinker)
+bool ARMGNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
 {
   if (NULL == m_pRelocFactory) {
     m_pRelocFactory = new ARMRelocationFactory(1024, *this);
-    m_pRelocFactory->setLayout(pLinker.getLayout());
+    m_pRelocFactory->setFragmentLinker(pLinker);
   }
   return true;
 }
@@ -78,41 +85,58 @@
   return m_pRelocFactory;
 }
 
-bool ARMGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
-{
-  if (!pSectionMap.push_back(".ARM.exidx", ".ARM.exidx") ||
-      !pSectionMap.push_back(".ARM.extab", ".ARM.extab") ||
-      !pSectionMap.push_back(".ARM.attributes", ".ARM.attributes"))
-    return false;
-  return true;
-}
-
-void ARMGNULDBackend::initTargetSections(MCLinker& pLinker)
+void ARMGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
 {
  // FIXME: Currently we set exidx and extab to "Exception" and directly emit
  // them from input
-  m_pEXIDX        = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx",
-                                                      LDFileFormat::Target,
-                                                      llvm::ELF::SHT_ARM_EXIDX,
-                                                      llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
-                                                      bitclass() / 8);
-  m_pEXTAB        = &pLinker.getOrCreateOutputSectHdr(".ARM.extab",
-                                                      LDFileFormat::Target,
-                                                      llvm::ELF::SHT_PROGBITS,
-                                                      llvm::ELF::SHF_ALLOC,
-                                                      0x1);
-  m_pAttributes   = &pLinker.getOrCreateOutputSectHdr(".ARM.attributes",
-                                                      LDFileFormat::Target,
-                                                      llvm::ELF::SHT_ARM_ATTRIBUTES,
-                                                      0x0,
-                                                      0x1);
+  m_pEXIDX        = pBuilder.CreateSection(".ARM.exidx",
+                                           LDFileFormat::Target,
+                                           llvm::ELF::SHT_ARM_EXIDX,
+                                           llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
+                                           bitclass() / 8);
+  m_pEXTAB        = pBuilder.CreateSection(".ARM.extab",
+                                           LDFileFormat::Target,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC,
+                                           0x1);
+  m_pAttributes   = pBuilder.CreateSection(".ARM.attributes",
+                                           LDFileFormat::Target,
+                                           llvm::ELF::SHT_ARM_ATTRIBUTES,
+                                           0x0,
+                                           0x1);
+
+  if (LinkerConfig::Object != config().codeGenType()) {
+    ELFFileFormat* file_format = getOutputFormat();
+
+    // initialize .got
+    LDSection& got = file_format->getGOT();
+    m_pGOT = new ARMGOT(got);
+
+    // initialize .plt
+    LDSection& plt = file_format->getPLT();
+    m_pPLT = new ARMPLT(plt, *m_pGOT);
+
+    // initialize .rel.plt
+    LDSection& relplt = file_format->getRelPlt();
+    relplt.setLink(&plt);
+    // create SectionData and ARMRelDynSection
+    m_pRelPLT = new OutputRelocSection(pModule,
+                                       relplt,
+                                       getRelEntrySize());
+
+    // initialize .rel.dyn
+    LDSection& reldyn = file_format->getRelDyn();
+    m_pRelDyn = new OutputRelocSection(pModule,
+                                       reldyn,
+                                       getRelEntrySize());
+  }
 }
 
-void ARMGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+void ARMGNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
-  m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
+  m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
                    "_GLOBAL_OFFSET_TABLE_",
                    false,
                    ResolveInfo::Object,
@@ -120,25 +144,76 @@
                    ResolveInfo::Local,
                    0x0,  // size
                    0x0,  // value
-                   NULL, // FragRef
+                   FragmentRef::Null(), // FragRef
                    ResolveInfo::Hidden);
+
+  FragmentRef* exidx_start = NULL;
+  FragmentRef* exidx_end = NULL;
+  ResolveInfo::Desc desc = ResolveInfo::Undefined;
+  if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
+    exidx_start = FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0);
+    exidx_end = FragmentRef::Create(m_pEXIDX->getSectionData()->back(), 0x0);
+    desc = ResolveInfo::Define;
+  }
+  else {
+    exidx_start = FragmentRef::Null();
+    exidx_end = FragmentRef::Null();
+  }
+  m_pEXIDXStart =
+    pLinker.defineSymbol<FragmentLinker::Force,
+                         FragmentLinker::Resolve>("__exidx_start",
+                                                  false,
+                                                  ResolveInfo::NoType,
+                                                  desc, // ResolveInfo::Desc
+                                                  ResolveInfo::Global,
+                                                  0x0,  // size
+                                                  0x0,  // value
+                                                  exidx_start, // FragRef
+                                                  ResolveInfo::Hidden);
+
+  m_pEXIDXEnd =
+    pLinker.defineSymbol<FragmentLinker::Force,
+                         FragmentLinker::Resolve>("__exidx_end",
+                                                  false,
+                                                  ResolveInfo::NoType,
+                                                  desc, //ResolveInfo::Desc
+                                                  ResolveInfo::Global,
+                                                  0x0,  // size
+                                                  0x0,  // value
+                                                  exidx_end, // FragRef
+                                                  ResolveInfo::Hidden);
 }
 
-void ARMGNULDBackend::doPreLayout(const Output& pOutput,
-                                  const MCLDInfo& pInfo,
-                                  MCLinker& pLinker)
+void ARMGNULDBackend::doPreLayout(FragmentLinker& pLinker)
 {
-  // when building shared object, the .got section is must.
-  if (pOutput.type() == Output::DynObj && (NULL == m_pGOT)) {
-      createARMGOT(pLinker, pOutput);
+  // set .got size
+  // when building shared object, the .got section is must
+  if (LinkerConfig::Object != config().codeGenType()) {
+    if (LinkerConfig::DynObj == config().codeGenType() ||
+        m_pGOT->hasGOT1() ||
+        NULL != m_pGOTSymbol) {
+      m_pGOT->finalizeSectionSize();
+      defineGOTSymbol(pLinker);
+    }
+
+    // set .plt size
+    if (m_pPLT->hasPLT1())
+      m_pPLT->finalizeSectionSize();
+
+    // set .rel.dyn size
+    if (!m_pRelDyn->empty())
+      m_pRelDyn->finalizeSectionSize();
+
+    // set .rel.plt size
+    if (!m_pRelPLT->empty())
+      m_pRelPLT->finalizeSectionSize();
   }
 }
 
-void ARMGNULDBackend::doPostLayout(const Output& pOutput,
-                                   const MCLDInfo& pInfo,
-                                   MCLinker& pLinker)
+void ARMGNULDBackend::doPostLayout(Module& pModule,
+                                   FragmentLinker& pLinker)
 {
-  const ELFFileFormat *file_format = getOutputFormat(pOutput);
+  const ELFFileFormat *file_format = getOutputFormat();
 
   // apply PLT
   if (file_format->hasPLT()) {
@@ -153,7 +228,7 @@
   if (file_format->hasGOT()) {
     // Since we already have the size of GOT, m_pGOT should not be NULL.
     assert(NULL != m_pGOT);
-    if (pOutput.type() == Output::DynObj)
+    if (LinkerConfig::DynObj == config().codeGenType())
       m_pGOT->applyGOT0(file_format->getDynamic().addr());
     else {
       // executable file and object file? should fill with zero.
@@ -180,17 +255,11 @@
   return *m_pDynamic;
 }
 
-void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput)
+void ARMGNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
 {
-  // get .got LDSection and create SectionData
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  LDSection& got = file_format->getGOT();
-  m_pGOT = new ARMGOT(got, pLinker.getOrCreateSectData(got));
-
   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
   if (m_pGOTSymbol != NULL) {
-    pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
+    pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
                      ResolveInfo::Object,
@@ -198,11 +267,11 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     FragmentRef::Create(*(m_pGOT->begin()), 0x0),
                      ResolveInfo::Hidden);
   }
   else {
-    m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+    m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
                      ResolveInfo::Object,
@@ -210,80 +279,44 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     FragmentRef::Create(*(m_pGOT->begin()), 0x0),
                      ResolveInfo::Hidden);
   }
 
 }
 
-void ARMGNULDBackend::createARMPLTandRelPLT(MCLinker& pLinker,
-                                            const Output& pOutput)
-{
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  // get .plt and .rel.plt LDSection
-  LDSection& plt = file_format->getPLT();
-  LDSection& relplt = file_format->getRelPlt();
-  // create SectionData and ARMPLT
-  m_pPLT = new ARMPLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT);
-  // set info of .rel.plt to .plt
-  relplt.setLink(&plt);
-  // create SectionData and ARMRelDynSection
-  m_pRelPLT = new OutputRelocSection(relplt,
-                                     pLinker.getOrCreateSectData(relplt),
-                                     8);
-}
-
-void ARMGNULDBackend::createARMRelDyn(MCLinker& pLinker,
-                                      const Output& pOutput)
-{
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  // get .rel.dyn LDSection and create SectionData
-  LDSection& reldyn = file_format->getRelDyn();
-  // create SectionData and ARMRelDynSection
-  m_pRelDyn = new OutputRelocSection(reldyn,
-                                     pLinker.getOrCreateSectData(reldyn),
-                                     8);
-}
-
 void ARMGNULDBackend::addCopyReloc(ResolveInfo& pSym)
 {
-  bool exist;
-  Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
+  Relocation& rel_entry = *m_pRelDyn->consumeEntry();
   rel_entry.setType(llvm::ELF::R_ARM_COPY);
   assert(pSym.outSymbol()->hasFragRef());
   rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
   rel_entry.setSymInfo(&pSym);
 }
 
-LDSymbol& ARMGNULDBackend::defineSymbolforCopyReloc(MCLinker& pLinker,
-                                                    const ResolveInfo& pSym)
+/// defineSymbolForCopyReloc
+/// For a symbol needing copy relocation, define a copy symbol in the BSS
+/// section and all other reference to this symbol should refer to this
+/// copy.
+/// This is executed at scan relocation stage.
+LDSymbol&
+ARMGNULDBackend::defineSymbolforCopyReloc(FragmentLinker& pLinker,
+                                          const ResolveInfo& pSym)
 {
-  // For a symbol needing copy relocation, define a copy symbol in the BSS
-  // section and all other reference to this symbol should refer to this
-  // copy.
-
   // get or create corresponding BSS LDSection
   LDSection* bss_sect_hdr = NULL;
-  if (ResolveInfo::ThreadLocal == pSym.type()) {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
-                                   ".tbss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
-  else {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
+  ELFFileFormat* file_format = getOutputFormat();
+  if (ResolveInfo::ThreadLocal == pSym.type())
+    bss_sect_hdr = &file_format->getTBSS();
+  else
+    bss_sect_hdr = &file_format->getBSS();
 
   // get or create corresponding BSS SectionData
-  assert(NULL != bss_sect_hdr);
-  SectionData& bss_section = pLinker.getOrCreateSectData(
-                                     *bss_sect_hdr);
+  SectionData* bss_data = NULL;
+  if (bss_sect_hdr->hasSectionData())
+    bss_data = bss_sect_hdr->getSectionData();
+  else
+    bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr);
 
   // Determine the alignment by the symbol value
   // FIXME: here we use the largest alignment
@@ -291,9 +324,9 @@
 
   // allocate space in BSS for the copy symbol
   Fragment* frag = new FillFragment(0x0, 1, pSym.size());
-  uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                     bss_section,
-                                                     addralign);
+  uint64_t size = ObjectBuilder::AppendFragment(*frag,
+                                                *bss_data,
+                                                addralign);
   bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
 
   // change symbol binding to Global if it's a weak symbol
@@ -302,7 +335,7 @@
     binding = ResolveInfo::Global;
 
   // Define the copy symbol in the bss section and resolve it
-  LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+  LDSymbol* cpy_sym = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
                       pSym.name(),
                       false,
                       (ResolveInfo::Type)pSym.type(),
@@ -310,7 +343,7 @@
                       binding,
                       pSym.size(),  // size
                       0x0,          // value
-                      pLinker.getLayout().getFragmentRef(*frag, 0x0),
+                      FragmentRef::Create(*frag, 0x0),
                       (ResolveInfo::Visibility)pSym.other());
 
   return *cpy_sym;
@@ -319,11 +352,10 @@
 /// checkValidReloc - When we attempt to generate a dynamic relocation for
 /// ouput file, check if the relocation is supported by dynamic linker.
 void ARMGNULDBackend::checkValidReloc(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
-                                      const Output& pOutput) const
+                                      const FragmentLinker& pLinker) const
 {
-  // If not building a PIC object, no relocation type is invalid
-  if (!isOutputPIC(pOutput, pLDInfo))
+  // If not PIC object, no relocation type is invalid
+  if (!pLinker.isOutputPIC())
     return;
 
   switch(pReloc.type()) {
@@ -346,28 +378,12 @@
   }
 }
 
-void ARMGNULDBackend::updateAddend(Relocation& pReloc,
-                                   const LDSymbol& pInputSym,
-                                   const Layout& pLayout) const
-{
-  // Update value keep in addend if we meet a section symbol
-  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
-    pReloc.setAddend(pLayout.getOutputOffset(
-                     *pInputSym.fragRef()) + pReloc.addend());
-  }
-}
-
 void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc,
-                                     const LDSymbol& pInputSym,
-                                     MCLinker& pLinker,
-                                     const MCLDInfo& pLDInfo,
-                                     const Output& pOutput)
+                                     FragmentLinker& pLinker)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
 
-  updateAddend(pReloc, pInputSym, pLinker.getLayout());
-
   switch(pReloc.type()){
 
     // Set R_ARM_TARGET1 to R_ARM_ABS32
@@ -381,10 +397,7 @@
       // 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 (isOutputPIC(pOutput, pLDInfo)) {
-        //create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createARMRelDyn(pLinker, pOutput);
+      if (pLinker.isOutputPIC()) {
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set Rel bit
         rsym->setReserved(rsym->reserved() | ReserveRel);
@@ -402,7 +415,7 @@
     case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
     case llvm::ELF::R_ARM_THM_MOVT_ABS: {
       // PIC code should not contain these kinds of relocation
-      if (isOutputPIC(pOutput, pLDInfo)) {
+      if (pLinker.isOutputPIC()) {
         error(diag::non_pic_relocation) << (int)pReloc.type()
                                         << pReloc.symInfo()->name();
       }
@@ -410,9 +423,7 @@
     }
     case llvm::ELF::R_ARM_GOTOFF32:
     case llvm::ELF::R_ARM_GOTOFF12: {
-      // A GOT section is needed
-      if (NULL == m_pGOT)
-        createARMGOT(pLinker, pOutput);
+      // FIXME: A GOT section is needed
       return;
     }
 
@@ -427,16 +438,12 @@
       // return if we already create GOT for this symbol
       if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if (NULL == m_pGOT)
-        createARMGOT(pLinker, pOutput);
-      m_pGOT->reserveEntry();
+      m_pGOT->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 (isOutputPIC(pOutput, pLDInfo)) {
+      if (pLinker.isOutputPIC()) {
         // create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
         rsym->setReserved(rsym->reserved() | 0x4u);
@@ -471,10 +478,7 @@
 }
 
 void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc,
-                                      const LDSymbol& pInputSym,
-                                      MCLinker& pLinker,
-                                      const MCLDInfo& pLDInfo,
-                                      const Output& pOutput)
+                                      FragmentLinker& pLinker)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
@@ -500,15 +504,9 @@
     case llvm::ELF::R_ARM_ABS32_NOI: {
       // Absolute relocation type, symbol may needs PLT entry or
       // dynamic relocation entry
-      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+      if (symbolNeedsPLT(pLinker, *rsym)) {
         // create plt for this symbol if it does not have one
         if (!(rsym->reserved() & ReservePLT)){
-          // Create .got section if it doesn't exist
-          if (NULL == m_pGOT)
-            createARMGOT(pLinker, pOutput);
-          // create .plt and .rel.plt if not exist
-          if (NULL == m_pPLT)
-            createARMPLTandRelPLT(pLinker, pOutput);
           // 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
@@ -520,20 +518,16 @@
         }
       }
 
-      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
-                            pLDInfo, pOutput, true)) {
+      if (symbolNeedsDynRel(
+                      pLinker, *rsym, (rsym->reserved() & ReservePLT), true)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
-        // create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
-                          pOutput)) {
+        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
         }
         else {
-          checkValidReloc(pReloc, pLDInfo, pOutput);
+          checkValidReloc(pReloc, pLinker);
           // set Rel bit
           rsym->setReserved(rsym->reserved() | ReserveRel);
         }
@@ -543,9 +537,7 @@
 
     case llvm::ELF::R_ARM_GOTOFF32:
     case llvm::ELF::R_ARM_GOTOFF12: {
-      // A GOT section is needed
-      if (NULL == m_pGOT)
-        createARMGOT(pLinker, pOutput);
+      // FIXME: A GOT section is needed
       return;
     }
 
@@ -601,20 +593,16 @@
     case llvm::ELF::R_ARM_MOVT_BREL:
     case llvm::ELF::R_ARM_MOVW_BREL: {
       // Relative addressing relocation, may needs dynamic relocation
-      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
-                            pLDInfo, pOutput, false)) {
+      if (symbolNeedsDynRel(
+                     pLinker, *rsym, (rsym->reserved() & ReservePLT), false)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
-        // create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
-                          pOutput)) {
+        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
         }
         else {
-          checkValidReloc(pReloc, pLDInfo, pOutput);
+          checkValidReloc(pReloc, pLinker);
           // set Rel bit
           rsym->setReserved(rsym->reserved() | ReserveRel);
         }
@@ -640,20 +628,17 @@
       if (rsym->reserved() & ReservePLT)
         return;
 
+      // if the symbol's value can be decided at link time, then no need plt
+      if (symbolFinalValueIsKnown(pLinker, *rsym))
+        return;
+
       // if symbol is defined in the ouput file and it's not
       // preemptible, no need plt
       if (rsym->isDefine() && !rsym->isDyn() &&
-         !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
+          !isSymbolPreemptible(*rsym)) {
         return;
       }
 
-      // Create .got section if it doesn't exist
-      if (NULL == m_pGOT)
-        createARMGOT(pLinker, pOutput);
-
-      // create .plt and .rel.plt if not exist
-      if (NULL == m_pPLT)
-         createARMPLTandRelPLT(pLinker, pOutput);
       // 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
@@ -677,16 +662,10 @@
       // return if we already create GOT for this symbol
       if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if (NULL == m_pGOT)
-        createARMGOT(pLinker, pOutput);
-      m_pGOT->reserveEntry();
-      // 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 (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
-        // create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createARMRelDyn(pLinker, pOutput);
+      m_pGOT->reserveGOT();
+      // if the symbol cannot be fully resolved at link time, then we need a
+      // dynamic relocation
+      if (!symbolFinalValueIsKnown(pLinker, *rsym)) {
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
         rsym->setReserved(rsym->reserved() | GOTRel);
@@ -713,56 +692,47 @@
 }
 
 void ARMGNULDBackend::scanRelocation(Relocation& pReloc,
-                                     const LDSymbol& pInputSym,
-                                     MCLinker& pLinker,
-                                     const MCLDInfo& pLDInfo,
-                                     const Output& pOutput,
+                                     FragmentLinker& pLinker,
+                                     Module& pModule,
                                      const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
 
-  assert(NULL != pSection.getLink());
-  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
-    if (rsym->isLocal()) {
-      updateAddend(pReloc, pInputSym, pLinker.getLayout());
-    }
+  pReloc.updateAddend();
+  if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
     return;
-  }
 
   // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
   // entries should be created.
-  // FIXME: Below judgements concern only .so is generated as output
   // FIXME: Below judgements concern nothing about TLS related relocation
 
-  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section
-  // is needed
-  if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
-    if (rsym == m_pGOTSymbol->resolveInfo()) {
-      createARMGOT(pLinker, pOutput);
-    }
-  }
-
   // rsym is local
   if (rsym->isLocal())
-    scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+    scanLocalReloc(pReloc, pLinker);
 
   // rsym is external
   else
-    scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+    scanGlobalReloc(pReloc, pLinker);
 
+  // check if we shoule issue undefined reference for the relocation target
+  // symbol
+  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+    fatal(diag::undefined_reference) << rsym->name();
+
+  if ((rsym->reserved() & ReserveRel) != 0x0) {
+    // set hasTextRelSection if needed
+    checkAndSetHasTextRel(pSection);
+  }
 }
 
-uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput,
-                                          const LDSection& pSection,
-                                          const MCLDInfo& pInfo,
-                                          const Layout& pLayout,
+uint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection,
                                           MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  const ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat();
 
   if (&pSection == m_pAttributes ||
       &pSection == m_pEXIDX ||
@@ -773,8 +743,19 @@
     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 = computeFragmentSize(pLayout, *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);
@@ -796,6 +777,10 @@
           } // end switch
           break;
         }
+        case Fragment::Null: {
+          assert(0x0 == size);
+          break;
+        }
         default:
           llvm::report_fatal_error("unsupported fragment type.\n");
           break;
@@ -823,48 +808,63 @@
 }
 
 /// finalizeSymbol - finalize the symbol value
-bool ARMGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+bool ARMGNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
 {
+  if (NULL != m_pEXIDXStart) {
+    if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size())
+      m_pEXIDXStart->setValue(m_pEXIDX->addr());
+  }
+
+  if (NULL != m_pEXIDXEnd) {
+    if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size())
+      m_pEXIDXEnd->setValue(m_pEXIDX->addr() + m_pEXIDX->size());
+  }
   return true;
 }
 
-bool ARMGNULDBackend::readSection(Input& pInput,
-                                  MCLinker& pLinker,
-                                  LDSection& pInputSectHdr)
+bool ARMGNULDBackend::mergeSection(Module& pModule, LDSection& pSection)
 {
-  LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
-                                                         pInputSectHdr.kind(),
-                                                         pInputSectHdr.type(),
-                                                         pInputSectHdr.flag());
-  // FIXME: (Luba)
-  // Handle ARM attributes in the right way.
-  // In current milestone, MCLinker 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 == out_sect.name().compare(".ARM.attributes")) &&
-      (0 != out_sect.size()))
-    return true;
+  switch (pSection.type()) {
+    case llvm::ELF::SHT_ARM_ATTRIBUTES: {
+      // FIXME: (Luba)
+      // Handle ARM attributes in the right way.
+      // In current milestone, FragmentLinker 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;
 
-  MemoryRegion* region = pInput.memArea()->request(
-          pInput.fileOffset() + pInputSectHdr.offset(), pInputSectHdr.size());
+      // First time we meet a ARM attributes section.
+      SectionData* sd = IRBuilder::CreateSectionData(*m_pAttributes);
+      ObjectBuilder::MoveSectionData(*pSection.getSectionData(), *sd);
+      return true;
+    }
+    default: {
+      ObjectBuilder builder(config(), pModule);
+      return builder.MergeSection(pSection);
+    }
+  } // end of switch
+  return true;
+}
 
-  SectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
-
+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) {
     // 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
+  else {
     frag = new RegionFragment(*region);
+  }
 
-  uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                     sect_data,
-                                                     pInputSectHdr.align());
-
-  out_sect.setSize(out_sect.size() + size);
+  ObjectBuilder::AppendFragment(*frag, pSD);
   return true;
 }
 
@@ -917,14 +917,12 @@
 }
 
 unsigned int
-ARMGNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr,
-                                       const MCLDInfo& pInfo) const
+ARMGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
 {
-  const ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat();
 
   if (&pSectHdr == &file_format->getGOT()) {
-    if (pInfo.options().hasNow())
+    if (config().options().hasNow())
       return SHO_RELRO_LAST;
     return SHO_DATA;
   }
@@ -940,16 +938,148 @@
   return SHO_UNDEFINED;
 }
 
+/// doRelax
+bool ARMGNULDBackend::doRelax(Module& pModule, FragmentLinker& pLinker, bool& pFinished)
+{
+  assert(NULL != getStubFactory() && NULL != getBRIslandFactory());
+
+  bool isRelaxed = false;
+  ELFFileFormat* file_format = getOutputFormat();
+  // check branch relocs and create the related stubs if needed
+  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) {
+      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);
+
+        switch (relocation->type()) {
+          case llvm::ELF::R_ARM_CALL:
+          case llvm::ELF::R_ARM_JUMP24:
+          case llvm::ELF::R_ARM_PLT32:
+          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: {
+            // calculate the possible symbol value
+            uint64_t sym_value = 0x0;
+            LDSymbol* symbol = relocation->symInfo()->outSymbol();
+            if (symbol->hasFragRef()) {
+              uint64_t value = symbol->fragRef()->getOutputOffset();
+              uint64_t addr =
+                symbol->fragRef()->frag()->getParent()->getSection().addr();
+              sym_value = addr + value;
+            }
+            if (relocation->symInfo()->isGlobal() &&
+                (relocation->symInfo()->reserved() & ReservePLT) != 0x0) {
+              // FIXME: we need to find out the address of the specific plt entry
+              assert(file_format->hasPLT());
+              sym_value = file_format->getPLT().addr();
+            }
+
+            Stub* stub = getStubFactory()->create(*relocation, // relocation
+                                                  sym_value, // symbol value
+                                                  pLinker,
+                                                  *getRelocFactory(),
+                                                  *getBRIslandFactory());
+            if (NULL != stub) {
+              assert(NULL != stub->symInfo());
+              // increase the size of .symtab and .strtab
+              LDSection& symtab = file_format->getSymTab();
+              LDSection& strtab = file_format->getStrTab();
+              if (32 == bitclass())
+                symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
+              else
+                symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym));
+              strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
+
+              isRelaxed = true;
+            }
+            break;
+          }
+          default:
+            break;
+        } // end of switch
+
+      } // for all relocations
+    } // for all relocation section
+  } // for all inputs
+
+  // find the first fragment w/ invalid offset due to stub insertion
+  Fragment* invalid = NULL;
+  pFinished = true;
+  for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
+       island_end = getBRIslandFactory()->end(); island != island_end; ++island) {
+    if ((*island).end() == file_format->getText().getSectionData()->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) {
+    file_format->getText().setSize(
+      file_format->getText().getSectionData()->back().getOffset() +
+      file_format->getText().getSectionData()->back().size());
+  }
+  return isRelaxed;
+}
+
+/// initTargetStubs
+bool ARMGNULDBackend::initTargetStubs(FragmentLinker& pLinker)
+{
+  if (NULL != getStubFactory()) {
+    getStubFactory()->addPrototype(new ARMToARMStub(pLinker.isOutputPIC()));
+    getStubFactory()->addPrototype(new ARMToTHMStub(pLinker.isOutputPIC()));
+    getStubFactory()->addPrototype(new THMToTHMStub(pLinker.isOutputPIC()));
+    getStubFactory()->addPrototype(new THMToARMStub(pLinker.isOutputPIC()));
+    return true;
+  }
+  return false;
+}
+
+/// doCreateProgramHdrs - backend can implement this function to create the
+/// target-dependent segments
+void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule,
+                                          const FragmentLinker& pLinker)
+{
+   if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
+     // make PT_ARM_EXIDX
+     // FIXME: once we have a patch for llvm/Support/ELF.h, we can refine this
+     enum {
+      PT_ARM_EXIDX = 0x70000001
+     };
+     ELFSegment* exidx_seg = elfSegmentTable().produce(PT_ARM_EXIDX,
+                                                       llvm::ELF::PF_R);
+     exidx_seg->addSection(m_pEXIDX);
+   }
+}
+
 namespace mcld {
 
 //===----------------------------------------------------------------------===//
 /// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
 ///
 TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget,
-                                    const std::string& pTriple)
+                                    const LinkerConfig& pConfig)
 {
-  Triple theTriple(pTriple);
-  if (theTriple.isOSDarwin()) {
+  if (pConfig.triple().isOSDarwin()) {
     assert(0 && "MachO linker is not supported yet");
     /**
     return new ARMMachOLDBackend(createARMMachOArchiveReader,
@@ -957,7 +1087,7 @@
                                createARMMachOObjectWriter);
     **/
   }
-  if (theTriple.isOSWindows()) {
+  if (pConfig.triple().isOSWindows()) {
     assert(0 && "COFF linker is not supported yet");
     /**
     return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
@@ -965,14 +1095,15 @@
                                createARMCOFFObjectWriter);
     **/
   }
-  return new ARMGNULDBackend();
+  return new ARMGNULDBackend(pConfig);
 }
 
 } // namespace of mcld
 
-//=============================
+//===----------------------------------------------------------------------===//
 // Force static initialization.
-extern "C" void LLVMInitializeARMLDBackend() {
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeARMLDBackend() {
   // Register the linker backend
   mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend);
   mcld::TargetRegistry::RegisterTargetLDBackend(TheThumbTarget, createARMLDBackend);
diff --git a/lib/Target/ARM/ARMLDBackend.h b/lib/Target/ARM/ARMLDBackend.h
index 981228e..6cf531b 100644
--- a/lib/Target/ARM/ARMLDBackend.h
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -18,20 +18,29 @@
 
 namespace mcld {
 
-class MCLDInfo;
-class MCLinker;
-class Output;
+class LinkerConfig;
+class FragmentLinker;
 class SectionMap;
 
-
 //===----------------------------------------------------------------------===//
 /// ARMGNULDBackend - linker backend of ARM target of GNU ELF format
 ///
 class ARMGNULDBackend : public GNULDBackend
 {
 public:
-  ARMGNULDBackend();
+  // max branch offsets for ARM, THUMB, and THUMB2
+  // @ref gold/arm.cc:99
+  static const int32_t ARM_MAX_FWD_BRANCH_OFFSET = ((((1 << 23) - 1) << 2) + 8);
+  static const int32_t ARM_MAX_BWD_BRANCH_OFFSET = ((-((1 << 23) << 2)) + 8);
+  static const int32_t THM_MAX_FWD_BRANCH_OFFSET = ((1 << 22) -2 + 4);
+  static const int32_t THM_MAX_BWD_BRANCH_OFFSET = (-(1 << 22) + 4);
+  static const int32_t THM2_MAX_FWD_BRANCH_OFFSET = (((1 << 24) - 2) + 4);
+  static const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4);
+
+public:
+  ARMGNULDBackend(const LinkerConfig& pConfig);
   ~ARMGNULDBackend();
+
 public:
   typedef std::vector<llvm::ELF::Elf32_Dyn*> ELF32DynList;
 
@@ -79,17 +88,14 @@
   };
 
 public:
-  /// initTargetSectionMap - initialize target dependent section mapping
-  bool initTargetSectionMap(SectionMap& pSectionMap);
-
   /// initTargetSections - initialize target dependent sections in output.
-  void initTargetSections(MCLinker& pLinker);
+  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
 
   /// initTargetSymbols - initialize target dependent symbols in output.
-  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+  void initTargetSymbols(FragmentLinker& pLinker);
 
   /// initRelocFactory - create and initialize RelocationFactory
-  bool initRelocFactory(const MCLinker& pLinker);
+  bool initRelocFactory(const FragmentLinker& pLinker);
 
   /// getRelocFactory
   RelocationFactory* getRelocFactory();
@@ -101,10 +107,8 @@
   /// - PLT entry (for .plt section)
   /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
   void scanRelocation(Relocation& pReloc,
-                      const LDSymbol& pInputSym,
-                      MCLinker& pLinker,
-                      const MCLDInfo& pLDInfo,
-                      const Output& pOutput,
+                      FragmentLinker& pLinker,
+                      Module& pModule,
                       const LDSection& pSection);
 
   uint32_t machine() const
@@ -132,14 +136,10 @@
   { return 0x8000; }
 
   /// doPreLayout - Backend can do any needed modification before layout
-  void doPreLayout(const Output& pOutput,
-                   const MCLDInfo& pInfo,
-                   MCLinker& pLinker);
+  void doPreLayout(FragmentLinker& pLinker);
 
   /// doPostLayout -Backend can do any needed modification after layout
-  void doPostLayout(const Output& pOutput,
-                    const MCLDInfo& pInfo,
-                    MCLinker& pLinker);
+  void doPostLayout(Module& pModule, FragmentLinker& pLinker);
 
   /// dynamic - the dynamic section of the target machine.
   /// Use co-variant return type to return its own dynamic section.
@@ -161,16 +161,11 @@
   ///  - backend can maintain its own map<LDSection, table> to get the table
   /// from given LDSection.
   ///
-  /// @param pOutput - the output file
   /// @param pSection - the given LDSection
-  /// @param pInfo - all options in the command line.
-  /// @param pLayout - for comouting the size of fragment
+  /// @param pConfig - all options in the command line.
   /// @param pRegion - the region to write out data
   /// @return the size of the table in the file.
-  uint64_t emitSectionData(const Output& pOutput,
-                           const LDSection& pSection,
-                           const MCLDInfo& pInfo,
-                           const Layout& pLayout,
+  uint64_t emitSectionData(const LDSection& pSection,
                            MemoryRegion& pRegion) const;
 
   ARMGOT& getGOT();
@@ -190,34 +185,24 @@
   const OutputRelocSection& getRelPLT() const;
 
   /// getTargetSectionOrder - compute the layout order of ARM target sections
-  unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr,
-                                     const MCLDInfo& pInfo) const;
+  unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
 
   /// finalizeTargetSymbols - finalize the symbol value
-  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+  bool finalizeTargetSymbols(FragmentLinker& pLinker);
+
+  /// mergeSection - merge target dependent sections
+  bool mergeSection(Module& pModule, LDSection& pSection);
 
   /// readSection - read target dependent sections
-  bool readSection(Input& pInput,
-                   MCLinker& pLinker,
-                   LDSection& pInputSectHdr);
+  bool readSection(Input& pInput, SectionData& pSD);
 
 private:
-  void scanLocalReloc(Relocation& pReloc,
-                      const LDSymbol& pInputSym,
-                      MCLinker& pLinker,
-                      const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+  void scanLocalReloc(Relocation& pReloc, FragmentLinker& pLinker);
 
-  void scanGlobalReloc(Relocation& pReloc,
-                       const LDSymbol& pInputSym,
-                       MCLinker& pLinker,
-                       const MCLDInfo& pLDInfo,
-                       const Output& pOutput);
+  void scanGlobalReloc(Relocation& pReloc, FragmentLinker& pLinker);
 
   void checkValidReloc(Relocation& pReloc,
-                       const MCLDInfo& pLDInfo,
-                       const Output& pOutput) const;
+                       const FragmentLinker& pLinker) const;
 
   /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
   /// @param pSym - A resolved copy symbol that defined in BSS section
@@ -226,25 +211,39 @@
   /// 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(MCLinker& pLinker,
+  LDSymbol& defineSymbolforCopyReloc(FragmentLinker& pLinker,
                                      const ResolveInfo& pSym);
 
-  /// updateAddend - update addend value of the relocation if the
-  /// the target symbol is a section symbol. Addend is the offset
-  /// in the section. This value should be updated after section
-  /// merged.
-  void updateAddend(Relocation& pReloc,
-                    const LDSymbol& pInputSym,
-                    const Layout& pLayout) const;
+  void defineGOTSymbol(FragmentLinker& pLinker);
 
-  void createARMGOT(MCLinker& pLinker, const Output& pOutput);
+  /// maxBranchOffset
+  /// FIXME: if we can handle arm attributes, we may refine this!
+  uint64_t maxBranchOffset() { return THM_MAX_FWD_BRANCH_OFFSET; }
 
-  /// createARMPLTandRelPLT - create PLT and RELPLT sections.
-  /// Because in ELF sh_info in .rel.plt is the shndx of .plt, these two
-  /// sections should be create together.
-  void createARMPLTandRelPLT(MCLinker& pLinker, const Output& pOutput);
+  /// mayRelax - Backends should override this function if they need relaxation
+  bool mayRelax() { return true; }
 
-  void createARMRelDyn(MCLinker& pLinker, const Output& pOutput);
+  /// 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, FragmentLinker& pLinker, bool& pFinished);
+
+  /// initTargetStubs
+  bool initTargetStubs(FragmentLinker& pLinker);
+
+  /// 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()
+  { assert(0 && "ARM backend with Rela type relocation\n"); return 12; }
+
+  /// doCreateProgramHdrs - backend can implement this function to create the
+  /// target-dependent segments
+  virtual void doCreateProgramHdrs(Module& pModule,
+                                   const FragmentLinker& pLinker);
 
 private:
   RelocationFactory* m_pRelocFactory;
@@ -257,6 +256,8 @@
 
   ARMELFDynamic* m_pDynamic;
   LDSymbol* m_pGOTSymbol;
+  LDSymbol* m_pEXIDXStart;
+  LDSymbol* m_pEXIDXEnd;
 
   //     variable name           :  ELF
   LDSection* m_pEXIDX;           // .ARM.exidx
diff --git a/lib/Target/ARM/ARMMCLinker.cpp b/lib/Target/ARM/ARMMCLinker.cpp
new file mode 100644
index 0000000..cc9486e
--- /dev/null
+++ b/lib/Target/ARM/ARMMCLinker.cpp
@@ -0,0 +1,50 @@
+//===- ARMMCLinker.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMELFMCLinker.h"
+
+#include "ARM.h"
+#include <llvm/ADT/Triple.h>
+#include <mcld/Module.h>
+#include <mcld/Support/TargetRegistry.h>
+
+using namespace mcld;
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createARMMCLinker - the help function to create corresponding ARMMCLinker
+//===----------------------------------------------------------------------===//
+MCLinker* createARMMCLinker(const std::string& pTriple,
+                            LinkerConfig& pConfig,
+                            mcld::Module& pModule,
+                            MemoryArea& pOutput)
+{
+  Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+    return NULL;
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+    return NULL;
+  }
+
+  return new ARMELFMCLinker(pConfig, pModule, pOutput);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// ARMMCLinker
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeARMMCLinker() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterMCLinker(TheARMTarget, createARMMCLinker);
+  mcld::TargetRegistry::RegisterMCLinker(TheThumbTarget, createARMMCLinker);
+}
+
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
index c9bc333..a5f4733 100644
--- a/lib/Target/ARM/ARMPLT.cpp
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -13,6 +13,7 @@
 
 #include <llvm/Support/Casting.h>
 
+#include <mcld/LD/LDSection.h>
 #include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/MsgHandling.h>
 
@@ -36,106 +37,73 @@
 
 using namespace mcld;
 
-ARMPLT0::ARMPLT0(SectionData* pParent)
-  : PLTEntry(sizeof(arm_plt0), pParent) {}
+ARMPLT0::ARMPLT0(SectionData& pParent)
+  : PLT::Entry(sizeof(arm_plt0), pParent) {}
 
-ARMPLT1::ARMPLT1(SectionData* pParent)
-  : PLTEntry(sizeof(arm_plt1), pParent) {}
+ARMPLT1::ARMPLT1(SectionData& pParent)
+  : PLT::Entry(sizeof(arm_plt1), pParent) {}
 
 //===----------------------------------------------------------------------===//
 // ARMPLT
 
 ARMPLT::ARMPLT(LDSection& pSection,
-               SectionData& pSectionData,
                ARMGOT &pGOTPLT)
-  : PLT(pSection, pSectionData), m_GOT(pGOTPLT), m_PLTEntryIterator() {
-  ARMPLT0* plt0_entry = new ARMPLT0(&m_SectionData);
-
-  m_Section.setSize(m_Section.size() + plt0_entry->getEntrySize());
-
-  m_PLTEntryIterator = pSectionData.begin();
+  : PLT(pSection), m_GOT(pGOTPLT), m_PLTEntryIterator() {
+  new ARMPLT0(*m_SectionData);
+  m_PLTEntryIterator = m_SectionData->begin();
 }
 
 ARMPLT::~ARMPLT()
 {
 }
 
+bool ARMPLT::hasPLT1() const
+{
+  return (m_SectionData->size() > 1);
+}
+
+void ARMPLT::finalizeSectionSize()
+{
+  uint64_t size = (m_SectionData->size() - 1) * sizeof(arm_plt1) +
+                     sizeof(arm_plt0);
+  m_Section.setSize(size);
+
+  uint32_t offset = 0;
+  SectionData::iterator frag, fragEnd = m_SectionData->end();
+  for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
+    frag->setOffset(offset);
+    offset += frag->size();
+  }
+}
+
 void ARMPLT::reserveEntry(size_t pNum)
 {
   ARMPLT1* plt1_entry = 0;
 
   for (size_t i = 0; i < pNum; ++i) {
-    plt1_entry = new (std::nothrow) ARMPLT1(&m_SectionData);
+    plt1_entry = new (std::nothrow) ARMPLT1(*m_SectionData);
 
     if (!plt1_entry)
       fatal(diag::fail_allocate_memory_plt);
 
-    m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
-
-    m_GOT.reserveGOTPLTEntry();
+    m_GOT.reserveGOTPLT();
   }
 }
 
-PLTEntry* ARMPLT::getPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+ARMPLT1* ARMPLT::consume()
 {
-   ARMPLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
+  ++m_PLTEntryIterator;
+  assert(m_PLTEntryIterator != m_SectionData->end() &&
+         "The number of PLT Entries and ResolveInfo doesn't match");
 
-   pExist = 1;
-
-   if (!PLTEntry) {
-     GOTEntry *&GOTPLTEntry = m_GOT.lookupGOTPLTMap(pSymbol);
-     assert(!GOTPLTEntry && "PLT entry and got.plt entry doesn't match!");
-
-     pExist = 0;
-
-     // This will skip PLT0.
-     ++m_PLTEntryIterator;
-     assert(m_PLTEntryIterator != m_SectionData.end() &&
-            "The number of PLT Entries and ResolveInfo doesn't match");
-
-     ARMGOT::iterator got_it = m_GOT.getNextGOTPLTEntry();
-     assert(got_it != m_GOT.getGOTPLTEnd() && "The number of GOTPLT and PLT doesn't match");
-
-     PLTEntry = llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
-     GOTPLTEntry = llvm::cast<GOTEntry>(&(*got_it));
-   }
-
-   return PLTEntry;
-}
-
-GOTEntry* ARMPLT::getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
-{
-   GOTEntry *&GOTPLTEntry = m_GOT.lookupGOTPLTMap(pSymbol);
-
-   pExist = 1;
-
-   if (!GOTPLTEntry) {
-     ARMPLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
-     assert(!PLTEntry && "PLT entry and got.plt entry doesn't match!");
-
-     pExist = 0;
-
-     // This will skip PLT0.
-     ++m_PLTEntryIterator;
-     assert(m_PLTEntryIterator != m_SectionData.end() &&
-            "The number of PLT Entries and ResolveInfo doesn't match");
-
-     ARMGOT::iterator got_it = m_GOT.getNextGOTPLTEntry();
-     assert(got_it != m_GOT.getGOTPLTEnd() &&
-            "The number of GOTPLT and PLT doesn't match");
-
-     PLTEntry = llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
-     GOTPLTEntry = llvm::cast<GOTEntry>(&(*got_it));
-   }
-
-   return GOTPLTEntry;
+  return llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
 }
 
 ARMPLT0* ARMPLT::getPLT0() const {
 
-  iterator first = m_SectionData.getFragmentList().begin();
+  iterator first = m_SectionData->getFragmentList().begin();
 
-  assert(first != m_SectionData.getFragmentList().end() &&
+  assert(first != m_SectionData->getFragmentList().end() &&
          "FragmentList is empty, getPLT0 failed!");
 
   ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
@@ -148,7 +116,7 @@
   uint64_t plt_base = m_Section.addr();
   assert(plt_base && ".plt base address is NULL!");
 
-  uint64_t got_base = m_GOT.getSection().addr();
+  uint64_t got_base = m_GOT.addr();
   assert(got_base && ".got base address is NULL!");
 
   uint32_t offset = 0;
@@ -158,9 +126,9 @@
   else
     offset = (plt_base + 16) - got_base;
 
-  iterator first = m_SectionData.getFragmentList().begin();
+  iterator first = m_SectionData->getFragmentList().begin();
 
-  assert(first != m_SectionData.getFragmentList().end() &&
+  assert(first != m_SectionData->getFragmentList().end() &&
          "FragmentList is empty, applyPLT0 failed!");
 
   ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
@@ -182,11 +150,11 @@
   uint64_t plt_base = m_Section.addr();
   assert(plt_base && ".plt base address is NULL!");
 
-  uint64_t got_base = m_GOT.getSection().addr();
+  uint64_t got_base = m_GOT.addr();
   assert(got_base && ".got base address is NULL!");
 
-  ARMPLT::iterator it = m_SectionData.begin();
-  ARMPLT::iterator ie = m_SectionData.end();
+  ARMPLT::iterator it = m_SectionData->begin();
+  ARMPLT::iterator ie = m_SectionData->end();
   assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
 
   uint32_t GOTEntrySize = m_GOT.getEntrySize();
@@ -223,7 +191,7 @@
     PLTEntryAddress += PLT1EntrySize;
   }
 
-  m_GOT.applyAllGOTPLT(plt_base);
+  m_GOT.applyGOTPLT(plt_base);
 }
 
 uint64_t ARMPLT::emit(MemoryRegion& pRegion)
diff --git a/lib/Target/ARM/ARMPLT.h b/lib/Target/ARM/ARMPLT.h
index db36563..67b6f4e 100644
--- a/lib/Target/ARM/ARMPLT.h
+++ b/lib/Target/ARM/ARMPLT.h
@@ -9,23 +9,22 @@
 #ifndef MCLD_ARM_PLT_H
 #define MCLD_ARM_PLT_H
 
-#include <mcld/LD/SectionData.h>
+#include <mcld/Target/GOT.h>
 #include <mcld/Target/PLT.h>
 
 namespace mcld {
 
 class ARMGOT;
-class GOTEntry;
 class MemoryRegion;
 
-class ARMPLT0 : public PLTEntry {
+class ARMPLT0 : public PLT::Entry {
 public:
-  ARMPLT0(SectionData* pParent);
+  ARMPLT0(SectionData& pParent);
 };
 
-class ARMPLT1 : public PLTEntry {
+class ARMPLT1 : public PLT::Entry {
 public:
-  ARMPLT1(SectionData* pParent);
+  ARMPLT1(SectionData& pParent);
 };
 
 /** \class ARMPLT
@@ -33,34 +32,19 @@
  */
 class ARMPLT : public PLT
 {
-  typedef llvm::DenseMap<const ResolveInfo*, ARMPLT1*> SymbolIndexType;
-
 public:
-  typedef SectionData::iterator iterator;
-  typedef SectionData::const_iterator const_iterator;
-
-public:
-  ARMPLT(LDSection& pSection, SectionData& pSectionData, ARMGOT& pGOTPLT);
+  ARMPLT(LDSection& pSection, ARMGOT& pGOTPLT);
   ~ARMPLT();
 
-// Override virtual function.
-public:
+  // finalizeSectionSize - set LDSection size
+  void finalizeSectionSize();
 
-  // reserveEntry is ARMGOT friend function.
+  // hasPLT1 - return if this plt section has any plt1 entry
+  bool hasPLT1() const;
+
   void reserveEntry(size_t pNum = 1) ;
 
-  PLTEntry* getPLTEntry(const ResolveInfo& pSymbol, bool& pExist) ;
-
-  GOTEntry* getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist);
-
-public:
-  iterator begin() { return m_SectionData.begin(); }
-
-  const_iterator begin() const { return m_SectionData.begin(); }
-
-  iterator end() { return m_SectionData.end(); }
-
-  const_iterator end() const { return m_SectionData.end(); }
+  ARMPLT1* consume();
 
   ARMPLT0* getPLT0() const;
 
@@ -73,11 +57,8 @@
 private:
   ARMGOT& m_GOT;
 
-  // Used by getEntry() for mapping a ResolveInfo
-  // instance to a PLT1 Entry.
+  // Used by getEntry() for mapping a ResolveInfo instance to a PLT1 Entry.
   iterator m_PLTEntryIterator;
-
-  SymbolIndexType m_PLTEntryMap;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMRelocationFactory.cpp b/lib/Target/ARM/ARMRelocationFactory.cpp
index cc561db..d668fc5 100644
--- a/lib/Target/ARM/ARMRelocationFactory.cpp
+++ b/lib/Target/ARM/ARMRelocationFactory.cpp
@@ -11,10 +11,9 @@
 #include <llvm/Support/DataTypes.h>
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Host.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Support/MsgHandling.h>
-
 #include "ARMRelocationFactory.h"
 #include "ARMRelocationFunctions.h"
 
@@ -28,7 +27,6 @@
 /// the prototype of applying function
 typedef RelocationFactory::Result (*ApplyFunctionType)(
                                                Relocation& pReloc,
-                                               const MCLDInfo& pLDInfo,
                                                ARMRelocationFactory& pParent);
 
 // the table entry of applying functions
@@ -58,17 +56,14 @@
 }
 
 RelocationFactory::Result
-ARMRelocationFactory::applyRelocation(Relocation& pRelocation,
-                                      const MCLDInfo& pLDInfo)
+ARMRelocationFactory::applyRelocation(Relocation& pRelocation)
 {
   Relocation::Type type = pRelocation.type();
   if (type > 130) { // 131-255 doesn't noted in ARM spec
-    fatal(diag::unknown_relocation) << (int)type
-                                    << pRelocation.symInfo()->name();
     return RelocationFactory::Unknown;
   }
 
-  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
+  return ApplyFunctions[type].func(pRelocation, *this);
 }
 
 const char* ARMRelocationFactory::getName(RelocationFactory::Type pType) const
@@ -117,117 +112,114 @@
 // Check if symbol can use relocation R_ARM_RELATIVE
 static bool
 helper_use_relative_reloc(const ResolveInfo& pSym,
-                          const MCLDInfo& pLDInfo,
                           const ARMRelocationFactory& pFactory)
 {
   // if symbol is dynamic or undefine or preemptible
   if (pSym.isDyn() ||
       pSym.isUndef() ||
-      pFactory.getTarget().isSymbolPreemptible(pSym,
-                                               pLDInfo,
-                                               pLDInfo.output()))
+      pFactory.getTarget().isSymbolPreemptible(pSym))
     return false;
   return true;
 }
 
 static
-GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
-                                  const MCLDInfo& pLDInfo,
-                                  ARMRelocationFactory& pParent)
+GOT::Entry& helper_get_GOT_and_init(Relocation& pReloc,
+                                    ARMRelocationFactory& pParent)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   ARMGNULDBackend& ld_backend = pParent.getTarget();
 
-  bool exist;
-  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
-  if (!exist) {
+  GOT::Entry* 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() & ARMGNULDBackend::ReserveGOT) {
       // No corresponding dynamic relocation, initialize to the symbol value.
-      got_entry.setContent(pReloc.symValue());
+      got_entry->setContent(pReloc.symValue());
     }
     else if (rsym->reserved() & ARMGNULDBackend::GOTRel) {
 
       // Initialize corresponding dynamic relocation.
-      Relocation& rel_entry =
-        *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
-      assert(!exist && "GOT entry not exist, but DynRel entry exist!");
+      Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
       if ( rsym->isLocal() ||
-          helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+          helper_use_relative_reloc(*rsym, pParent)) {
         // Initialize got entry to target symbol address
-        got_entry.setContent(pReloc.symValue());
+        got_entry->setContent(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.setContent(0);
+        got_entry->setContent(0);
         rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
         rel_entry.setSymInfo(rsym);
       }
-      rel_entry.targetRef().assign(got_entry);
+      rel_entry.targetRef().assign(*got_entry);
     }
     else {
       fatal(diag::reserve_entry_number_mismatch_got);
     }
   }
-  return got_entry;
+  return *got_entry;
 }
 
 static
 ARMRelocationFactory::Address helper_GOT_ORG(ARMRelocationFactory& pParent)
 {
-  return pParent.getTarget().getGOT().getSection().addr();
+  return pParent.getTarget().getGOT().addr();
 }
 
 
 static
 ARMRelocationFactory::Address helper_GOT(Relocation& pReloc,
-                                         const MCLDInfo& pLDInfo,
                                          ARMRelocationFactory& pParent)
 {
-  GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo, pParent);
-  return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry);
+  GOT::Entry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
+  return helper_GOT_ORG(pParent) + got_entry.getOffset();
 }
 
 
 static
-PLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
-                                  ARMRelocationFactory& pParent)
+PLT::Entry& helper_get_PLT_and_init(Relocation& pReloc,
+                                    ARMRelocationFactory& pParent)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   ARMGNULDBackend& ld_backend = pParent.getTarget();
 
-  bool exist;
-  PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
-  if (!exist) {
-    // If we first get this PLT entry, we should initialize it.
-    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
-      GOTEntry& gotplt_entry =
-        *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
-      // Initialize corresponding dynamic relocation.
-      Relocation& rel_entry =
-        *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
-      assert(!exist && "PLT entry not exist, but DynRel entry exist!");
-      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);
-    }
+  PLT::Entry* 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() & ARMGNULDBackend::ReservePLT) {
+    GOT::Entry* 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);
   }
-  return plt_entry;
+  else {
+    fatal(diag::reserve_entry_number_mismatch_plt);
+  }
+
+  return *plt_entry;
 }
 
-
-
 static
 ARMRelocationFactory::Address helper_PLT_ORG(ARMRelocationFactory& pParent)
 {
-  return pParent.getTarget().getPLT().getSection().addr();
+  return pParent.getTarget().getPLT().addr();
 }
 
 
@@ -235,8 +227,8 @@
 ARMRelocationFactory::Address helper_PLT(Relocation& pReloc,
                                          ARMRelocationFactory& pParent)
 {
-  PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
-  return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry);
+  PLT::Entry& 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,
@@ -249,10 +241,8 @@
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   ARMGNULDBackend& ld_backend = pParent.getTarget();
-  bool exist;
 
-  Relocation& rel_entry =
-    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
+  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
   rel_entry.setType(pType);
   rel_entry.targetRef() = pReloc.targetRef();
 
@@ -282,39 +272,27 @@
 }
 
 static ARMRelocationFactory::DWord
-helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
+helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pValue)
 {
-  // Consider the endianness problem, get the target data value from lower
-  // and upper 16 bits
-  ARMRelocationFactory::DWord val =
-    (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) |
-    *(reinterpret_cast<uint16_t*>(&pTarget) + 1);
-
   // imm16: [19-16][26][14-12][7-0]
-  return helper_sign_extend((((val >> 4) & 0xf000U) |
-                             ((val >> 15) & 0x0800U) |
-                             ((val >> 4) & 0x0700U) |
-                             (val & 0x00ffU)),
+  return helper_sign_extend((((pValue >> 4) & 0xf000U) |
+                             ((pValue >> 15) & 0x0800U) |
+                             ((pValue >> 4) & 0x0700U) |
+                             (pValue& 0x00ffU)),
                             16);
 }
 
 static ARMRelocationFactory::DWord
-helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
+helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pValue,
                                        ARMRelocationFactory::DWord pImm)
 {
-  ARMRelocationFactory::DWord val;
   // imm16: [19-16][26][14-12][7-0]
-  pTarget &= 0xfbf08f00U;
-  pTarget |= (pImm & 0xf000U) << 4;
-  pTarget |= (pImm & 0x0800U) << 15;
-  pTarget |= (pImm & 0x0700U) << 4;
-  pTarget |= (pImm & 0x00ffU);
-
-  // Consider the endianness problem, write back data from lower and
-  // upper 16 bits
-  val = (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) |
-        *(reinterpret_cast<uint16_t*>(&pTarget) + 1);
-  return val;
+  pValue &= 0xfbf08f00U;
+  pValue |= (pImm & 0xf000U) << 4;
+  pValue |= (pImm & 0x0800U) << 15;
+  pValue |= (pImm & 0x0700U) << 4;
+  pValue |= (pImm & 0x00ffU);
+  return pValue;
 }
 
 static ARMRelocationFactory::DWord
@@ -377,7 +355,6 @@
 
 // R_ARM_NONE
 ARMRelocationFactory::Result none(Relocation& pReloc,
-                                  const MCLDInfo& pLDInfo,
                                   ARMRelocationFactory& pParent)
 {
   return ARMRelocationFactory::OK;
@@ -385,7 +362,6 @@
 
 // R_ARM_ABS32: (S + A) | T
 ARMRelocationFactory::Result abs32(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
                                    ARMRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
@@ -393,13 +369,11 @@
   ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   ARMRelocationFactory::DWord S = pReloc.symValue();
 
-  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                  *(pReloc.targetRef().frag()));
-  assert(NULL != target_sect);
+  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 & target_sect.flag())) {
     pReloc.target() = (S + A) | T;
     return ARMRelocationFactory::OK;
   }
@@ -416,13 +390,12 @@
     if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
       T = 0 ; // PLT is not thumb
-      pReloc.target() = (S + A) | T;
     }
     // 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() & ARMGNULDBackend::ReserveRel) {
-      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+      if (helper_use_relative_reloc(*rsym, pParent)) {
         helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
       }
       else {
@@ -440,31 +413,39 @@
 
 // R_ARM_REL32: ((S + A) | T) - P
 ARMRelocationFactory::Result rel32(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
                                    ARMRelocationFactory& pParent)
 {
   // perform static relocation
-  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
-  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
-  pReloc.target() = ((pReloc.symValue() + A) | T)
-      - pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord   T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord   A = pReloc.target() + pReloc.addend();
+
+  // An external symbol may need PLT (this reloc is from stub)
+  if (!pReloc.symInfo()->isLocal()) {
+    if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+      T = 0;  // PLT is not thumb.
+    }
+  }
+
+  // perform relocation
+  pReloc.target() = ((S + A) | T) - pReloc.place();
+
   return ARMRelocationFactory::OK;
 }
 
 // R_ARM_BASE_PREL: B(S) + A - P
 ARMRelocationFactory::Result base_prel(Relocation& pReloc,
-                                       const MCLDInfo& pLDInfo,
                                        ARMRelocationFactory& pParent)
 {
   // perform static relocation
   ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
-  pReloc.target() = pReloc.symValue() + A - pReloc.place(pParent.getLayout());
+  pReloc.target() = pReloc.symValue() + A - pReloc.place();
   return ARMRelocationFactory::OK;
 }
 
 // R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG
 ARMRelocationFactory::Result gotoff32(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
@@ -478,14 +459,13 @@
 
 // R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
 ARMRelocationFactory::Result got_brel(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
   if (!(pReloc.symInfo()->reserved() &
       (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
     return ARMRelocationFactory::BadReloc;
   }
-  ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
+  ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pParent);
   ARMRelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
   ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
   // Apply relocation.
@@ -495,16 +475,16 @@
 
 // R_ARM_GOT_PREL: GOT(S) + A - P
 ARMRelocationFactory::Result got_prel(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
   if (!(pReloc.symInfo()->reserved() &
       (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
     return ARMRelocationFactory::BadReloc;
   }
-  ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
+  ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pParent);
   ARMRelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
-  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::Address P = pReloc.place();
+
   // Apply relocation.
   pReloc.target() = GOT_S + A - P;
   return ARMRelocationFactory::OK;
@@ -514,13 +494,8 @@
 // R_ARM_JUMP24: ((S + A) | T) - P
 // R_ARM_CALL: ((S + A) | T) - P
 ARMRelocationFactory::Result call(Relocation& pReloc,
-                                  const MCLDInfo& pLDInfo,
                                   ARMRelocationFactory& pParent)
 {
-  // TODO: Some issue have not been considered:
-  // 1. Add stub when switching mode or jump target too far
-  // 2. We assume the blx is available
-
   // If target is undefined weak symbol, we only need to jump to the
   // next instruction unless it has PLT entry. Rewrite instruction
   // to NOP.
@@ -538,7 +513,7 @@
   ARMRelocationFactory::DWord   A =
     helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26)
     + pReloc.addend();
-  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::Address P = pReloc.place();
 
   S = pReloc.symValue();
   if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
@@ -546,12 +521,15 @@
     T = 0;  // PLT is not thumb.
   }
 
-  // If the jump target is thumb instruction, switch mode is needed, rewrite
-  // the instruction to BLX
+  // At this moment (after relaxation), if the jump target is thumb instruction,
+  // switch mode is needed, rewrite the instruction to BLX
+  // FIXME: check if we can use BLX instruction (check from .ARM.attribute
+  // CPU ARCH TAG, which should be ARMv5 or above)
   if (T != 0) {
-    // cannot rewrite R_ARM_JUMP24 instruction to blx
-    assert((pReloc.type() != llvm::ELF::R_ARM_JUMP24)&&
-      "Invalid instruction to rewrite to blx for switching mode.");
+    // cannot rewrite to blx for R_ARM_JUMP24
+    if (pReloc.type() == llvm::ELF::R_ARM_JUMP24)
+      return ARMRelocationFactory::BadReloc;
+
     pReloc.target() = (pReloc.target() & 0xffffff) |
                       0xfa000000 |
                       (((S + A - P) & 2) << 23);
@@ -569,7 +547,6 @@
 // R_ARM_THM_CALL: ((S + A) | T) - P
 // R_ARM_THM_JUMP24: (((S + A) | T) - P)
 ARMRelocationFactory::Result thm_call(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
   // If target is undefined weak symbol, we only need to jump to the
@@ -584,13 +561,13 @@
   }
 
   // get lower and upper 16 bit instructions from relocation targetData
-  uint16_t upper16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
-  uint16_t lower16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
+  uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+  uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
 
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
-  ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper16,
-                                                               lower16);
-  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper_inst,
+                                                               lower_inst);
+  ARMRelocationFactory::Address P = pReloc.place();
   ARMRelocationFactory::Address S;
 
   // if symbol has plt
@@ -604,45 +581,44 @@
 
   S = S + A;
 
+  // At this moment (after relaxation), if the jump target is arm
+  // instruction, switch mode is needed, rewrite the instruction to BLX
   // FIXME: check if we can use BLX instruction (check from .ARM.attribute
   // CPU ARCH TAG, which should be ARMv5 or above)
-
-  // If the jump target is not thumb, switch mode is needed, rewrite
-  // instruction to BLX
   if (T == 0) {
+    // cannot rewrite to blx for R_ARM_THM_JUMP24
+    if (pReloc.type() == llvm::ELF::R_ARM_THM_JUMP24)
+      return ARMRelocationFactory::BadReloc;
+
     // for BLX, select bit 1 from relocation base address to jump target
     // address
     S = helper_bit_select(S, P, 0x2);
     // rewrite instruction to BLX
-    lower16 &= ~0x1000U;
+    lower_inst &= ~0x1000U;
   }
   else {
     // otherwise, the instruction should be BL
-    lower16 |= 0x1000U;
+    lower_inst |= 0x1000U;
   }
 
   ARMRelocationFactory::DWord X = (S | T) - P;
 
-  // TODO: check if we need stub when building non-shared object,
-  // overflow or switch-mode.
-
   // FIXME: Check bit size is 24(thumb2) or 22?
   if (helper_check_signed_overflow(X, 25)) {
     return ARMRelocationFactory::Overflow;
   }
 
-  upper16 = helper_thumb32_branch_upper(upper16, X);
-  lower16 = helper_thumb32_branch_lower(lower16, X);
+  upper_inst = helper_thumb32_branch_upper(upper_inst, X);
+  lower_inst = helper_thumb32_branch_lower(lower_inst, X);
 
- *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper16;
- *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower16;
+  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
 
- return ARMRelocationFactory::OK;
+  return ARMRelocationFactory::OK;
 }
 
 // R_ARM_MOVW_ABS_NC: (S + A) | T
 ARMRelocationFactory::Result movw_abs_nc(Relocation& pReloc,
-                                         const MCLDInfo& pLDInfo,
                                          ARMRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
@@ -652,12 +628,11 @@
       helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                 *(pReloc.targetRef().frag()));
-  assert(NULL != target_sect);
+  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 & target_sect.flag())) {
     // use plt
     if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
@@ -674,12 +649,11 @@
 
 // R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
 ARMRelocationFactory::Result movw_prel_nc(Relocation& pReloc,
-                                          const MCLDInfo& pLDInfo,
                                           ARMRelocationFactory& pParent)
 {
   ARMRelocationFactory::Address S = pReloc.symValue();
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
-  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord P = pReloc.place();
   ARMRelocationFactory::DWord A =
       helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
@@ -696,7 +670,6 @@
 
 // R_ARM_MOVT_ABS: S + A
 ARMRelocationFactory::Result movt_abs(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
@@ -705,12 +678,11 @@
     helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                  *(pReloc.targetRef().frag()));
-  assert(NULL != target_sect);
+  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 & target_sect.flag())) {
     // use plt
     if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
@@ -726,13 +698,12 @@
 
 // R_ARM_MOVT_PREL: S + A - P
 ARMRelocationFactory::Result movt_prel(Relocation& pReloc,
-                                       const MCLDInfo& pLDInfo,
                                        ARMRelocationFactory& pParent)
 {
   ARMRelocationFactory::Address S = pReloc.symValue();
-  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord P = pReloc.place();
   ARMRelocationFactory::DWord A =
-      helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
+            helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
   X = S + A - P;
@@ -744,22 +715,24 @@
 
 // R_ARM_THM_MOVW_ABS_NC: (S + A) | T
 ARMRelocationFactory::Result thm_movw_abs_nc(Relocation& pReloc,
-                                             const MCLDInfo& pLDInfo,
                                              ARMRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   ARMRelocationFactory::Address S = pReloc.symValue();
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+
+  // 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);
+  ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
   ARMRelocationFactory::DWord A =
-      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+      helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                  *(pReloc.targetRef().frag()));
-  assert(NULL != target_sect);
+  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 & target_sect.flag())) {
     // use plt
     if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
@@ -767,69 +740,84 @@
     }
   }
   X = (S + A) | T;
-  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                           X);
+
+  val = helper_insert_val_thumb_movw_movt_inst(val, X);
+  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
   return ARMRelocationFactory::OK;
 }
 
 // R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
 ARMRelocationFactory::Result thm_movw_prel_nc(Relocation& pReloc,
-                                              const MCLDInfo& pLDInfo,
                                               ARMRelocationFactory& pParent)
 {
   ARMRelocationFactory::Address S = pReloc.symValue();
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
-  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord P = pReloc.place();
+
+  // 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);
+  ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
   ARMRelocationFactory::DWord A =
-      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+      helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
   X = ((S + A) | T) - P;
 
-  // check 16-bit overflow
-  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                           X);
+  val = helper_insert_val_thumb_movw_movt_inst(val, X);
+  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
   return ARMRelocationFactory::OK;
 }
 
 // R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
 // R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
 ARMRelocationFactory::Result thm_movw_brel(Relocation& pReloc,
-                                              const MCLDInfo& pLDInfo,
                                               ARMRelocationFactory& pParent)
 {
   ARMRelocationFactory::Address S = pReloc.symValue();
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
-  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord P = pReloc.place();
+
+  // 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);
+  ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
   ARMRelocationFactory::DWord A =
-      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+      helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
   X = ((S + A) | T) - P;
 
-  // check 16-bit overflow
-  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                           X);
+  val = helper_insert_val_thumb_movw_movt_inst(val, X);
+  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
   return ARMRelocationFactory::OK;
 }
 
 // R_ARM_THM_MOVT_ABS: S + A
 ARMRelocationFactory::Result thm_movt_abs(Relocation& pReloc,
-                                          const MCLDInfo& pLDInfo,
                                           ARMRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   ARMRelocationFactory::Address S = pReloc.symValue();
+
+  // 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);
+  ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
   ARMRelocationFactory::DWord A =
-      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+      helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                  *(pReloc.targetRef().frag()));
-  assert(NULL != target_sect);
+  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 & target_sect.flag())) {
     // use plt
     if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
@@ -843,8 +831,9 @@
   if (helper_check_signed_overflow(X, 16)) {
     return ARMRelocationFactory::Overflow;
   } else {
-    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                             X);
+    val = helper_insert_val_thumb_movw_movt_inst(val, X);
+    *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+    *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
     return ARMRelocationFactory::OK;
   }
 }
@@ -852,31 +841,38 @@
 // R_ARM_THM_MOVT_PREL: S + A - P
 // R_ARM_THM_MOVT_BREL: S + A - B(S)
 ARMRelocationFactory::Result thm_movt_prel(Relocation& pReloc,
-                                           const MCLDInfo& pLDInfo,
                                            ARMRelocationFactory& pParent)
 {
   ARMRelocationFactory::Address S = pReloc.symValue();
-  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord P = pReloc.place();
+
+  // 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);
+  ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
   ARMRelocationFactory::DWord A =
-      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+      helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
   X = S + A - P;
   X >>= 16;
-  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                             X);
+
+  val = helper_insert_val_thumb_movw_movt_inst(val, X);
+  *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+  *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
   return ARMRelocationFactory::OK;
 }
 
-// R_ARM_PREL31: (S + A) | T
+// R_ARM_PREL31: ((S + A) | T) - P
 ARMRelocationFactory::Result prel31(Relocation& pReloc,
-                                    const MCLDInfo& pLDInfo,
                                     ARMRelocationFactory& pParent)
 {
   ARMRelocationFactory::DWord target = pReloc.target();
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
   ARMRelocationFactory::DWord A = helper_sign_extend(target, 31) +
                                   pReloc.addend();
+  ARMRelocationFactory::DWord P = pReloc.place();
   ARMRelocationFactory::Address S;
 
   S = pReloc.symValue();
@@ -886,7 +882,7 @@
     T = 0;  // PLT is not thumb.
   }
 
-  ARMRelocationFactory::DWord X = (S + A) | T ;
+  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
   pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
   if (helper_check_signed_overflow(X, 31))
     return ARMRelocationFactory::Overflow;
@@ -897,14 +893,12 @@
 // R_ARM_TLS_IE32: GOT(S) + A - P
 // R_ARM_TLS_LE32: S + A - tp
 ARMRelocationFactory::Result tls(Relocation& pReloc,
-                                 const MCLDInfo& pLDInfo,
                                  ARMRelocationFactory& pParent)
 {
   return ARMRelocationFactory::Unsupport;
 }
 
 ARMRelocationFactory::Result unsupport(Relocation& pReloc,
-                                       const MCLDInfo& pLDInfo,
                                        ARMRelocationFactory& pParent)
 {
   return ARMRelocationFactory::Unsupport;
diff --git a/lib/Target/ARM/ARMRelocationFactory.h b/lib/Target/ARM/ARMRelocationFactory.h
index b0b3483..25135ed 100644
--- a/lib/Target/ARM/ARMRelocationFactory.h
+++ b/lib/Target/ARM/ARMRelocationFactory.h
@@ -14,10 +14,10 @@
 
 #include <mcld/LD/RelocationFactory.h>
 #include <mcld/Target/GOT.h>
+#include <mcld/Target/SymbolEntryMap.h>
 #include "ARMLDBackend.h"
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class ARMRelocationFactory
  *  \brief ARMRelocationFactory creates and destroys the ARM relocations.
@@ -26,10 +26,14 @@
 class ARMRelocationFactory : public RelocationFactory
 {
 public:
+  typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
+  typedef SymbolEntryMap<PLT::Entry> SymPLTMap;
+
+public:
   ARMRelocationFactory(size_t pNum, ARMGNULDBackend& pParent);
   ~ARMRelocationFactory();
 
-  Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+  Result applyRelocation(Relocation& pRelocation);
 
   ARMGNULDBackend& getTarget()
   { return m_Target; }
@@ -39,8 +43,20 @@
 
   const char* getName(Relocation::Type pType) const;
 
+  const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
+  SymGOTMap&       getSymGOTMap()       { return m_SymGOTMap; }
+
+  const SymPLTMap& getSymPLTMap() const { return m_SymPLTMap; }
+  SymPLTMap&       getSymPLTMap()       { return m_SymPLTMap; }
+
+  const SymGOTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
+  SymGOTMap&       getSymGOTPLTMap()       { return m_SymGOTPLTMap; }
+
 private:
   ARMGNULDBackend& m_Target;
+  SymGOTMap m_SymGOTMap;
+  SymPLTMap m_SymPLTMap;
+  SymGOTMap m_SymGOTPLTMap;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMRelocationFunctions.h b/lib/Target/ARM/ARMRelocationFunctions.h
index bb6e727..3f8b90e 100644
--- a/lib/Target/ARM/ARMRelocationFunctions.h
+++ b/lib/Target/ARM/ARMRelocationFunctions.h
@@ -9,7 +9,6 @@
 
 #define DECL_ARM_APPLY_RELOC_FUNC(Name) \
 static ARMRelocationFactory::Result Name    (Relocation& pEntry, \
-                                             const MCLDInfo& pLDInfo, \
                                              ARMRelocationFactory& pParent);
 
 #define DECL_ARM_APPLY_RELOC_FUNCS \
diff --git a/lib/Target/ARM/ARMSectLinker.cpp b/lib/Target/ARM/ARMSectLinker.cpp
deleted file mode 100644
index 52a00e3..0000000
--- a/lib/Target/ARM/ARMSectLinker.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- ARMSectLinker.cpp --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <llvm/ADT/Triple.h>
-#include <mcld/Support/TargetRegistry.h>
-#include "ARM.h"
-#include "ARMELFSectLinker.h"
-
-
-using namespace mcld;
-
-namespace mcld {
-//===----------------------------------------------------------------------===//
-// createARMSectLinker - the help function to create corresponding ARMSectLinker
-//
-SectLinker* createARMSectLinker(const std::string &pTriple,
-                                SectLinkerOption &pOption,
-                                mcld::TargetLDBackend &pLDBackend)
-{
-  Triple theTriple(pTriple);
-  if (theTriple.isOSDarwin()) {
-    assert(0 && "MachO linker has not supported yet");
-    return NULL;
-  }
-  if (theTriple.isOSWindows()) {
-    assert(0 && "COFF linker has not supported yet");
-    return NULL;
-  }
-
-  // For now, use Android SectLinker directly
-  return new ARMELFSectLinker(pOption, pLDBackend);
-}
-
-} // namespace of mcld
-
-//==========================
-// ARMSectLinker
-extern "C" void LLVMInitializeARMSectLinker() {
-  // Register the linker frontend
-  mcld::TargetRegistry::RegisterSectLinker(TheARMTarget, createARMSectLinker);
-  mcld::TargetRegistry::RegisterSectLinker(TheThumbTarget, createARMSectLinker);
-}
-
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index 54e1b3d..7062f31 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -7,28 +7,26 @@
 //
 //===----------------------------------------------------------------------===//
 #include "ARMTargetMachine.h"
-
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/MC/MCLDInfo.h"
 #include "ARM.h"
 
-extern "C" void LLVMInitializeARMLDTarget() {
-  // Register createTargetMachine function pointer to mcld::Target
-  mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> X(mcld::TheARMTarget);
-  mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> Y(mcld::TheThumbTarget);
-}
+#include <mcld/Support/TargetRegistry.h>
 
 mcld::ARMBaseTargetMachine::ARMBaseTargetMachine(llvm::TargetMachine& pPM,
                                                  const mcld::Target &pTarget,
                                                  const std::string& pTriple)
-  : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
-  // arg1 - the number of total attributes
-  // arg2 - the most possible number of input files
-  m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+  : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
 }
 
 mcld::ARMBaseTargetMachine::~ARMBaseTargetMachine()
 {
-  delete m_pLDInfo;
+}
+
+//===----------------------------------------------------------------------===//
+// Initialize MCLDTargetMachine
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeARMLDTarget() {
+  // Register createTargetMachine function pointer to mcld::Target
+  mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> X(mcld::TheARMTarget);
+  mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> Y(mcld::TheThumbTarget);
 }
 
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index 19f8aa2..94a7866 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -8,30 +8,20 @@
 //===----------------------------------------------------------------------===//
 #ifndef MCLD_ARM_TARGET_MACHINE_H
 #define MCLD_ARM_TARGET_MACHINE_H
-#include "mcld/Target/TargetMachine.h"
+
 #include "ARM.h"
+#include <mcld/Target/TargetMachine.h>
 
-namespace mcld
+namespace mcld {
+
+class ARMBaseTargetMachine : public MCLDTargetMachine
 {
-
-class ARMBaseTargetMachine : public LLVMTargetMachine
-{
-protected:
-  MCLDInfo *m_pLDInfo;
-
 public:
   ARMBaseTargetMachine(llvm::TargetMachine &pTM,
                        const mcld::Target &pTarget,
                        const std::string &pTriple);
 
   virtual ~ARMBaseTargetMachine();
-
-  mcld::MCLDInfo& getLDInfo()
-  { return *m_pLDInfo; }
-
-  const mcld::MCLDInfo& getLDInfo() const
-  { return *m_pLDInfo; }
-
 };
 
 } // namespace of mcld
diff --git a/lib/Target/ARM/ARMToARMStub.cpp b/lib/Target/ARM/ARMToARMStub.cpp
new file mode 100644
index 0000000..9bc26cd
--- /dev/null
+++ b/lib/Target/ARM/ARMToARMStub.cpp
@@ -0,0 +1,115 @@
+//===- ARMToARMStub.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMToARMStub.h"
+#include "ARMLDBackend.h"
+
+#include <llvm/Support/ELF.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ARMToARMStub
+//===----------------------------------------------------------------------===//
+const uint32_t ARMToARMStub::PIC_TEMPLATE[] = {
+  0xe59fc000, // ldr   r12, [pc]
+  0xe08ff00c, // add   pc, pc, ip
+  0x0         // dcd   R_ARM_REL32(X-4)
+};
+
+const uint32_t ARMToARMStub::TEMPLATE[] = {
+  0xe51ff004, // ldr   pc, [pc, #-4]
+  0x0         // dcd   R_ARM_ABS32(X)
+};
+
+ARMToARMStub::ARMToARMStub(bool pIsOutputPIC)
+ : Stub(), m_Name("A2A_prototype"), m_pData(NULL), m_Size(0x0)
+{
+  if (pIsOutputPIC) {
+    m_pData = PIC_TEMPLATE;
+    m_Size = sizeof(PIC_TEMPLATE);
+    addFixup(8u, -4, llvm::ELF::R_ARM_REL32);
+  }
+  else {
+    m_pData = TEMPLATE;
+    m_Size = sizeof(TEMPLATE);
+    addFixup(4u, 0x0, llvm::ELF::R_ARM_ABS32);
+  }
+}
+
+/// for doClone
+ARMToARMStub::ARMToARMStub(const uint32_t* pData,
+                           size_t pSize,
+                           const_fixup_iterator pBegin,
+                           const_fixup_iterator pEnd)
+ : Stub(), m_Name("A2A_veneer"), m_pData(pData), m_Size(pSize)
+{
+  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+    addFixup(**it);
+}
+
+ARMToARMStub::~ARMToARMStub()
+{
+}
+
+bool ARMToARMStub::isMyDuty(const class Relocation& pReloc,
+                            uint64_t pSource,
+                            uint64_t pTargetSymValue) const
+{
+  bool result = false;
+  // Check if the branch target is ARM
+  if ((pTargetSymValue & 0x1) == 0x0) {
+    switch (pReloc.type()) {
+      case llvm::ELF::R_ARM_CALL:
+      case llvm::ELF::R_ARM_JUMP24:
+      case llvm::ELF::R_ARM_PLT32: {
+        // Check if the branch target is too far
+        uint64_t dest = pTargetSymValue + pReloc.addend() + 8u;
+        int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
+        if ((branch_offset > ARMGNULDBackend::ARM_MAX_FWD_BRANCH_OFFSET) ||
+            (branch_offset < ARMGNULDBackend::ARM_MAX_BWD_BRANCH_OFFSET)) {
+          result =  true;
+        }
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  return result;
+}
+
+const std::string& ARMToARMStub::name() const
+{
+  return m_Name;
+}
+
+const uint8_t* ARMToARMStub::getContent() const
+{
+  return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t ARMToARMStub::size() const
+{
+  return m_Size;
+}
+
+size_t ARMToARMStub::alignment() const
+{
+  return 4u;
+}
+
+Stub* ARMToARMStub::doClone()
+{
+  return new ARMToARMStub(m_pData, m_Size, fixup_begin(), fixup_end());
+}
+
diff --git a/lib/Target/ARM/ARMToARMStub.h b/lib/Target/ARM/ARMToARMStub.h
new file mode 100644
index 0000000..107f172
--- /dev/null
+++ b/lib/Target/ARM/ARMToARMStub.h
@@ -0,0 +1,76 @@
+//===- ARMToARMStub.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_ARM_ARMTOARMSTUB_H
+#define MCLD_ARM_ARMTOARMSTUB_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+/** \class ARMToARMStub
+ *  \brief ARM stub for long call from ARM source to ARM target
+ *
+ */
+class ARMToARMStub : public Stub
+{
+public:
+  ARMToARMStub(bool pIsOutputPIC);
+
+  ~ARMToARMStub();
+
+  // isMyDuty
+  bool isMyDuty(const class Relocation& pReloc,
+                uint64_t pSource,
+                uint64_t pTargetSymValue) const;
+
+  // observers
+  const std::string& name() const;
+
+  const uint8_t* getContent() const;
+
+  size_t size() const;
+
+  size_t alignment() const;
+
+private:
+  ARMToARMStub(const ARMToARMStub&);
+
+  ARMToARMStub& operator=(const ARMToARMStub&);
+
+  /// for doClone
+  ARMToARMStub(const uint32_t* pData,
+               size_t pSize,
+               const_fixup_iterator pBegin,
+               const_fixup_iterator pEnd);
+
+  /// doClone
+  Stub* doClone();
+
+private:
+  std::string m_Name;
+  static const uint32_t PIC_TEMPLATE[];
+  static const uint32_t TEMPLATE[];
+  const uint32_t* m_pData;
+  size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/ARMToTHMStub.cpp b/lib/Target/ARM/ARMToTHMStub.cpp
new file mode 100644
index 0000000..8c25c86
--- /dev/null
+++ b/lib/Target/ARM/ARMToTHMStub.cpp
@@ -0,0 +1,123 @@
+//===- ARMToTHMStub.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMToTHMStub.h"
+#include "ARMLDBackend.h"
+
+#include <llvm/Support/ELF.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ARMToTHMStub
+//===----------------------------------------------------------------------===//
+const uint32_t ARMToTHMStub::PIC_TEMPLATE[] = {
+  0xe59fc004, // ldr   r12, [pc, #4]
+  0xe08fc00c, // add   ip, pc, ip
+  0xe12fff1c, // bx    ip
+  0x0         // dcd   R_ARM_REL32(X)
+};
+
+const uint32_t ARMToTHMStub::TEMPLATE[] = {
+  0xe59fc000, // ldr   ip, [pc, #0]
+  0xe12fff1c, // bx    ip
+  0x0         // dcd   R_ARM_ABS32(X)
+};
+
+ARMToTHMStub::ARMToTHMStub(bool pIsOutputPIC)
+ : Stub(), m_Name("A2T_prototype"), m_pData(NULL), m_Size(0x0)
+{
+  if (pIsOutputPIC) {
+    m_pData = PIC_TEMPLATE;
+    m_Size = sizeof(PIC_TEMPLATE);
+    addFixup(12u, 0x0, llvm::ELF::R_ARM_REL32);
+  }
+  else {
+    m_pData = TEMPLATE;
+    m_Size = sizeof(TEMPLATE);
+    addFixup(8u, 0x0, llvm::ELF::R_ARM_ABS32);
+  }
+}
+
+/// for doClone
+ARMToTHMStub::ARMToTHMStub(const uint32_t* pData,
+                           size_t pSize,
+                           const_fixup_iterator pBegin,
+                           const_fixup_iterator pEnd)
+ : Stub(), m_Name("A2T_veneer"), m_pData(pData), m_Size(pSize)
+{
+  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+    addFixup(**it);
+}
+
+ARMToTHMStub::~ARMToTHMStub()
+{
+}
+
+bool ARMToTHMStub::isMyDuty(const class Relocation& pReloc,
+                            uint64_t pSource,
+                            uint64_t pTargetSymValue) const
+{
+  bool result = false;
+  // Check if the branch target is THUMB
+  if ((pTargetSymValue & 0x1) != 0x0) {
+    switch (pReloc.type()) {
+      case llvm::ELF::R_ARM_CALL: {
+        // FIXME: Assuming blx is available (i.e., target is armv5 or above!)
+        // then, we do not need a stub unless the branch target is too far.
+        uint64_t dest = pTargetSymValue + pReloc.addend() + 8u;
+        int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
+        if ((branch_offset > ARMGNULDBackend::ARM_MAX_FWD_BRANCH_OFFSET) ||
+            (branch_offset < ARMGNULDBackend::ARM_MAX_BWD_BRANCH_OFFSET)) {
+          result = true;
+          break;
+        }
+        break;
+      }
+      case llvm::ELF::R_ARM_JUMP24:
+      case llvm::ELF::R_ARM_PLT32: {
+        // always need a stub to switch mode
+        result = true;
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  return result;
+}
+
+const std::string& ARMToTHMStub::name() const
+{
+  return m_Name;
+}
+
+const uint8_t* ARMToTHMStub::getContent() const
+{
+  return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t ARMToTHMStub::size() const
+{
+  return m_Size;
+}
+
+size_t ARMToTHMStub::alignment() const
+{
+  return 4u;
+}
+
+Stub* ARMToTHMStub::doClone()
+{
+  return new ARMToTHMStub(m_pData, m_Size, fixup_begin(), fixup_end());
+}
+
diff --git a/lib/Target/ARM/ARMToTHMStub.h b/lib/Target/ARM/ARMToTHMStub.h
new file mode 100644
index 0000000..b38303e
--- /dev/null
+++ b/lib/Target/ARM/ARMToTHMStub.h
@@ -0,0 +1,76 @@
+//===- ARMToTHMStub.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_ARM_ARMToTHMStub_H
+#define MCLD_ARM_ARMToTHMStub_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+/** \class ARMToTHMStub
+ *  \brief ARM stub for long call from ARM source to ARM target
+ *
+ */
+class ARMToTHMStub : public Stub
+{
+public:
+  ARMToTHMStub(bool pIsOutputPIC);
+
+  ~ARMToTHMStub();
+
+  // isMyDuty
+  bool isMyDuty(const class Relocation& pReloc,
+                uint64_t pSource,
+                uint64_t pTargetSymValue) const;
+
+  // observers
+  const std::string& name() const;
+
+  const uint8_t* getContent() const;
+
+  size_t size() const;
+
+  size_t alignment() const;
+
+private:
+  ARMToTHMStub(const ARMToTHMStub&);
+
+  ARMToTHMStub& operator=(const ARMToTHMStub&);
+
+  /// for doClone
+  ARMToTHMStub(const uint32_t* pData,
+               size_t pSize,
+               const_fixup_iterator pBegin,
+               const_fixup_iterator pEnd);
+
+  /// doClone
+  Stub* doClone();
+
+private:
+  std::string m_Name;
+  static const uint32_t PIC_TEMPLATE[];
+  static const uint32_t TEMPLATE[];
+  const uint32_t* m_pData;
+  size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/Android.mk b/lib/Target/ARM/Android.mk
index 114f2dc..f9cb356 100644
--- a/lib/Target/ARM/Android.mk
+++ b/lib/Target/ARM/Android.mk
@@ -3,13 +3,18 @@
 mcld_arm_target_SRC_FILES := \
   ARMDiagnostic.cpp \
   ARMELFDynamic.cpp \
-  ARMELFSectLinker.cpp  \
+  ARMELFMCLinker.cpp \
+  ARMEmulation.cpp \
   ARMGOT.cpp  \
   ARMLDBackend.cpp  \
+  ARMMCLinker.cpp  \
   ARMPLT.cpp  \
   ARMRelocationFactory.cpp  \
-  ARMSectLinker.cpp \
-  ARMTargetMachine.cpp
+  ARMTargetMachine.cpp \
+  ARMToARMStub.cpp \
+  ARMToTHMStub.cpp \
+  THMToARMStub.cpp \
+  THMToTHMStub.cpp
 
 # For the host
 # =====================================================
diff --git a/lib/Target/ARM/THMToARMStub.cpp b/lib/Target/ARM/THMToARMStub.cpp
new file mode 100644
index 0000000..e32222e
--- /dev/null
+++ b/lib/Target/ARM/THMToARMStub.cpp
@@ -0,0 +1,126 @@
+//===- THMToARMStub.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "THMToARMStub.h"
+#include "ARMLDBackend.h"
+
+#include <llvm/Support/ELF.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// THMToARMStub
+//===----------------------------------------------------------------------===//
+const uint32_t THMToARMStub::PIC_TEMPLATE[] = {
+  0x46c04778, // bx    pc ... nop
+  0xe59fc000, // ldr   ip, [pc, #0]
+  0xe08cf00f, // add   pc, ip, pc
+  0x0         // dcd   R_ARM_REL32(X)
+};
+
+const uint32_t THMToARMStub::TEMPLATE[] = {
+  0x46c04778, // bx    pc ... nop
+  0xe51ff004, // ldr   pc, [pc, #-4]
+  0x0         // dcd   R_ARM_ABS32(X)
+};
+
+THMToARMStub::THMToARMStub(bool pIsOutputPIC)
+ : Stub(), m_Name("T2A_prototype"), m_pData(NULL), m_Size(0x0)
+{
+  if (pIsOutputPIC) {
+    m_pData = PIC_TEMPLATE;
+    m_Size = sizeof(PIC_TEMPLATE);
+    addFixup(12u, -4, llvm::ELF::R_ARM_REL32);
+  }
+  else {
+    m_pData = TEMPLATE;
+    m_Size = sizeof(TEMPLATE);
+    addFixup(8u, 0x0, llvm::ELF::R_ARM_ABS32);
+  }
+}
+
+/// for doClone
+THMToARMStub::THMToARMStub(const uint32_t* pData,
+                           size_t pSize,
+                           const_fixup_iterator pBegin,
+                           const_fixup_iterator pEnd)
+ : Stub(), m_Name("T2A_veneer"), m_pData(pData), m_Size(pSize)
+{
+  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+    addFixup(**it);
+}
+
+THMToARMStub::~THMToARMStub()
+{
+}
+
+bool THMToARMStub::isMyDuty(const class Relocation& pReloc,
+                            uint64_t pSource,
+                            uint64_t pTargetSymValue) const
+{
+  bool result = false;
+  // Check if the branch target is ARM
+  if ((pTargetSymValue & 0x1) == 0x0) {
+    switch (pReloc.type()) {
+      case llvm::ELF::R_ARM_THM_CALL: {
+        // FIXME: Assuming blx is available (i.e., target is armv5 or above!)
+        // then, we do not need a stub unless the branch target is too far.
+        uint64_t dest = pTargetSymValue + pReloc.addend() + 4u;
+        int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
+        if ((branch_offset > ARMGNULDBackend::THM_MAX_FWD_BRANCH_OFFSET) ||
+            (branch_offset < ARMGNULDBackend::THM_MAX_BWD_BRANCH_OFFSET))
+          result = true;
+        break;
+      }
+      case llvm::ELF::R_ARM_THM_JUMP24: {
+        // always need a stub to switch mode
+        result = true;
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  return result;
+}
+
+const std::string& THMToARMStub::name() const
+{
+  return m_Name;
+}
+
+const uint8_t* THMToARMStub::getContent() const
+{
+  return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t THMToARMStub::size() const
+{
+  return m_Size;
+}
+
+size_t THMToARMStub::alignment() const
+{
+  return 4u;
+}
+
+// for T bit of this stub
+uint64_t THMToARMStub::initSymValue() const
+{
+  return 0x1;
+}
+
+Stub* THMToARMStub::doClone()
+{
+  return new THMToARMStub(m_pData, m_Size, fixup_begin(), fixup_end());
+}
+
diff --git a/lib/Target/ARM/THMToARMStub.h b/lib/Target/ARM/THMToARMStub.h
new file mode 100644
index 0000000..994cc23
--- /dev/null
+++ b/lib/Target/ARM/THMToARMStub.h
@@ -0,0 +1,79 @@
+//===- THMToARMStub.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_ARM_THMToARMStub_H
+#define MCLD_ARM_THMToARMStub_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+/** \class THMToARMStub
+ *  \brief ARM stub for long call from ARM source to ARM target
+ *
+ */
+class THMToARMStub : public Stub
+{
+public:
+  THMToARMStub(bool pIsOutputPIC);
+
+  ~THMToARMStub();
+
+  // isMyDuty
+  bool isMyDuty(const class Relocation& pReloc,
+                uint64_t pSource,
+                uint64_t pTargetSymValue) const;
+
+  // observers
+  const std::string& name() const;
+
+  const uint8_t* getContent() const;
+
+  size_t size() const;
+
+  size_t alignment() const;
+
+  // for T bit of this stub
+  uint64_t initSymValue() const;
+
+private:
+  THMToARMStub(const THMToARMStub&);
+
+  THMToARMStub& operator=(const THMToARMStub&);
+
+  /// for doClone
+  THMToARMStub(const uint32_t* pData,
+               size_t pSize,
+               const_fixup_iterator pBegin,
+               const_fixup_iterator pEnd);
+
+  /// doClone
+  Stub* doClone();
+
+private:
+  std::string m_Name;
+  static const uint32_t PIC_TEMPLATE[];
+  static const uint32_t TEMPLATE[];
+  const uint32_t* m_pData;
+  size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/THMToTHMStub.cpp b/lib/Target/ARM/THMToTHMStub.cpp
new file mode 100644
index 0000000..b58de77
--- /dev/null
+++ b/lib/Target/ARM/THMToTHMStub.cpp
@@ -0,0 +1,122 @@
+//===- THMToTHMStub.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "THMToTHMStub.h"
+#include "ARMLDBackend.h"
+
+#include <llvm/Support/ELF.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// THMToTHMStub
+//===----------------------------------------------------------------------===//
+const uint32_t THMToTHMStub::PIC_TEMPLATE[] = {
+  0x46c04778, // bx    pc ... nop
+  0xe59fc004, // ldr   r12, [pc, #4]
+  0xe08fc00c, // add   ip, pc, ip
+  0xe12fff1c, // bx    ip
+  0x0         // dcd   R_ARM_REL32(X)
+};
+
+const uint32_t THMToTHMStub::TEMPLATE[] = {
+  0x46c04778, // bx    pc ... nop
+  0xe59fc000, // ldr   ip, [pc, #0]
+  0xe12fff1c, // bx    ip
+  0x0         // dcd   R_ARM_ABS32(X)
+};
+
+THMToTHMStub::THMToTHMStub(bool pIsOutputPIC)
+ : Stub(), m_Name("T2T_prototype"), m_pData(NULL), m_Size(0x0)
+{
+  if (pIsOutputPIC) {
+    m_pData = PIC_TEMPLATE;
+    m_Size = sizeof(PIC_TEMPLATE);
+    addFixup(16u, 0x0, llvm::ELF::R_ARM_REL32);
+  }
+  else {
+    m_pData = TEMPLATE;
+    m_Size = sizeof(TEMPLATE);
+    addFixup(12u, 0x0, llvm::ELF::R_ARM_ABS32);
+  }
+}
+
+/// for doClone
+THMToTHMStub::THMToTHMStub(const uint32_t* pData,
+                           size_t pSize,
+                           const_fixup_iterator pBegin,
+                           const_fixup_iterator pEnd)
+ : Stub(), m_Name("T2T_veneer"), m_pData(pData), m_Size(pSize)
+{
+  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+    addFixup(**it);
+}
+
+THMToTHMStub::~THMToTHMStub()
+{
+}
+
+bool THMToTHMStub::isMyDuty(const class Relocation& pReloc,
+                            uint64_t pSource,
+                            uint64_t pTargetSymValue) const
+{
+  bool result = false;
+  // Check if the branch target is THUMB
+  if ((pTargetSymValue & 0x1) != 0x0) {
+    switch (pReloc.type()) {
+      case llvm::ELF::R_ARM_THM_CALL:
+      case llvm::ELF::R_ARM_THM_JUMP24: {
+        // Check if the branch target is too far
+        uint64_t dest = pTargetSymValue + pReloc.addend() + 4u;
+        int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
+        if ((branch_offset > ARMGNULDBackend::THM_MAX_FWD_BRANCH_OFFSET) ||
+            (branch_offset < ARMGNULDBackend::THM_MAX_BWD_BRANCH_OFFSET))
+          result =  true;
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  return result;
+}
+
+const std::string& THMToTHMStub::name() const
+{
+  return m_Name;
+}
+
+const uint8_t* THMToTHMStub::getContent() const
+{
+  return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t THMToTHMStub::size() const
+{
+  return m_Size;
+}
+
+size_t THMToTHMStub::alignment() const
+{
+  return 4u;
+}
+
+uint64_t THMToTHMStub::initSymValue() const
+{
+  return 0x1;
+}
+
+Stub* THMToTHMStub::doClone()
+{
+  return new THMToTHMStub(m_pData, m_Size, fixup_begin(), fixup_end());
+}
+
diff --git a/lib/Target/ARM/THMToTHMStub.h b/lib/Target/ARM/THMToTHMStub.h
new file mode 100644
index 0000000..f8d6009
--- /dev/null
+++ b/lib/Target/ARM/THMToTHMStub.h
@@ -0,0 +1,79 @@
+//===- THMToTHMStub.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_ARM_THMToTHMStub_H
+#define MCLD_ARM_THMToTHMStub_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+/** \class THMToTHMStub
+ *  \brief ARM stub for long call from ARM source to ARM target
+ *
+ */
+class THMToTHMStub : public Stub
+{
+public:
+  THMToTHMStub(bool pIsOutputPIC);
+
+  ~THMToTHMStub();
+
+  // isMyDuty
+  bool isMyDuty(const class Relocation& pReloc,
+                uint64_t pSource,
+                uint64_t pTargetSymValue) const;
+
+  // observers
+  const std::string& name() const;
+
+  const uint8_t* getContent() const;
+
+  size_t size() const;
+
+  size_t alignment() const;
+
+  // for T bit of this stub
+  uint64_t initSymValue() const;
+
+private:
+  THMToTHMStub(const THMToTHMStub&);
+
+  THMToTHMStub& operator=(const THMToTHMStub&);
+
+  /// for doClone
+  THMToTHMStub(const uint32_t* pData,
+               size_t pSize,
+               const_fixup_iterator pBegin,
+               const_fixup_iterator pEnd);
+
+  /// doClone
+  Stub* doClone();
+
+private:
+  std::string m_Name;
+  static const uint32_t PIC_TEMPLATE[];
+  static const uint32_t TEMPLATE[];
+  const uint32_t* m_pData;
+  size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
index 4f2f815..fd00641 100644
--- a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
+++ b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
@@ -14,7 +14,7 @@
 mcld::Target TheARMTarget;
 mcld::Target TheThumbTarget;
 
-extern "C" void LLVMInitializeARMLDTargetInfo() {
+extern "C" void MCLDInitializeARMLDTargetInfo() {
   // register into mcld::TargetRegistry
   mcld::RegisterTarget X(TheARMTarget, "arm" );
   mcld::RegisterTarget Y(TheThumbTarget, "thumb" );
diff --git a/lib/Target/Android.mk b/lib/Target/Android.mk
index abcc876..e70b467 100644
--- a/lib/Target/Android.mk
+++ b/lib/Target/Android.mk
@@ -2,12 +2,12 @@
 
 mcld_target_SRC_FILES := \
   ELFDynamic.cpp  \
-  ELFSectLinker.cpp \
+  ELFEmulation.cpp  \
+  ELFMCLinker.cpp  \
   GNULDBackend.cpp  \
   GOT.cpp \
   OutputRelocSection.cpp  \
   PLT.cpp \
-  Stub.cpp  \
   Target.cpp  \
   TargetLDBackend.cpp
 
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
index cb7c435..25b21f0 100644
--- a/lib/Target/ELFDynamic.cpp
+++ b/lib/Target/ELFDynamic.cpp
@@ -11,8 +11,9 @@
 #include <mcld/Target/ELFDynamic.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/LD/ELFFileFormat.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 using namespace elf_dynamic;
@@ -30,7 +31,7 @@
 //===----------------------------------------------------------------------===//
 // ELFDynamic
 ELFDynamic::ELFDynamic(const GNULDBackend& pParent)
-  : m_pEntryFactory(NULL), m_Idx(0) {
+  : m_pEntryFactory(NULL), m_Backend(pParent), m_Idx(0) {
   if (32 == pParent.bitclass() && pParent.isLittleEndian()) {
     m_pEntryFactory = new Entry<32, true>();
   }
@@ -85,13 +86,13 @@
 }
 
 /// reserveEntries - reserve entries
-void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo,
+void ELFDynamic::reserveEntries(const LinkerConfig& pConfig,
                                 const ELFFileFormat& pFormat)
 {
-  if (pLDInfo.output().type() == Output::DynObj) {
+  if (LinkerConfig::DynObj == pConfig.codeGenType()) {
     reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
 
-    if (pLDInfo.options().Bsymbolic())
+    if (pConfig.options().Bsymbolic())
       reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
   }
 
@@ -146,24 +147,29 @@
     reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
   }
 
-  if (pLDInfo.options().hasOrigin() ||
-      pLDInfo.options().Bsymbolic() ||
-      pLDInfo.options().hasNow()) {
-    // TODO: add checks for DF_TEXTREL and DF_STATIC_TLS
+  if (pConfig.options().hasOrigin() ||
+      pConfig.options().Bsymbolic() ||
+      pConfig.options().hasNow()    ||
+      m_Backend.hasTextRel()        ||
+      (m_Backend.hasStaticTLS() &&
+        (LinkerConfig::DynObj == pConfig.codeGenType()))) {
     reserveOne(llvm::ELF::DT_FLAGS); // DT_FLAGS
   }
 
-  if (pLDInfo.options().hasNow()          ||
-      pLDInfo.options().hasLoadFltr()     ||
-      pLDInfo.options().hasOrigin()       ||
-      pLDInfo.options().hasInterPose()    ||
-      pLDInfo.options().hasNoDefaultLib() ||
-      pLDInfo.options().hasNoDump()       ||
-      pLDInfo.options().Bgroup()          ||
-      ((pLDInfo.output().type() == Output::DynObj) &&
-       (pLDInfo.options().hasNoDelete()  ||
-        pLDInfo.options().hasInitFirst() ||
-        pLDInfo.options().hasNoDLOpen()))) {
+  if (m_Backend.hasTextRel())
+    reserveOne(llvm::ELF::DT_TEXTREL); // DT_TEXTREL
+
+  if (pConfig.options().hasNow()          ||
+      pConfig.options().hasLoadFltr()     ||
+      pConfig.options().hasOrigin()       ||
+      pConfig.options().hasInterPose()    ||
+      pConfig.options().hasNoDefaultLib() ||
+      pConfig.options().hasNoDump()       ||
+      pConfig.options().Bgroup()          ||
+      ((LinkerConfig::DynObj == pConfig.codeGenType()) &&
+       (pConfig.options().hasNoDelete()  ||
+        pConfig.options().hasInitFirst() ||
+        pConfig.options().hasNoDLOpen()))) {
     reserveOne(llvm::ELF::DT_FLAGS_1); // DT_FLAGS_1
   }
 
@@ -171,11 +177,11 @@
 }
 
 /// applyEntries - apply entries
-void ELFDynamic::applyEntries(const MCLDInfo& pInfo,
+void ELFDynamic::applyEntries(const LinkerConfig& pConfig,
                               const ELFFileFormat& pFormat)
 {
-  if (pInfo.output().type() == Output::DynObj &&
-      pInfo.options().Bsymbolic()) {
+  if (LinkerConfig::DynObj == pConfig.codeGenType() &&
+      pConfig.options().Bsymbolic()) {
       applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
   }
 
@@ -238,39 +244,51 @@
     applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
   }
 
+  if (m_Backend.hasTextRel()) {
+    applyOne(llvm::ELF::DT_TEXTREL, 0x0); // DT_TEXTREL
+
+    if (pConfig.options().warnSharedTextrel() &&
+        LinkerConfig::DynObj == pConfig.codeGenType())
+      mcld::warning(mcld::diag::warn_shared_textrel);
+  }
+
   uint64_t dt_flags = 0x0;
-  if (pInfo.options().hasOrigin())
+  if (pConfig.options().hasOrigin())
     dt_flags |= llvm::ELF::DF_ORIGIN;
-  if (pInfo.options().Bsymbolic())
+  if (pConfig.options().Bsymbolic())
     dt_flags |= llvm::ELF::DF_SYMBOLIC;
-  if (pInfo.options().hasNow())
+  if (pConfig.options().hasNow())
     dt_flags |= llvm::ELF::DF_BIND_NOW;
-  // TODO: add checks for DF_TEXTREL and DF_STATIC_TLS
+  if (m_Backend.hasTextRel())
+    dt_flags |= llvm::ELF::DF_TEXTREL;
+  if (m_Backend.hasStaticTLS() &&
+      (LinkerConfig::DynObj == pConfig.codeGenType()))
+    dt_flags |= llvm::ELF::DF_STATIC_TLS;
   if (0x0 != dt_flags) {
     applyOne(llvm::ELF::DT_FLAGS, dt_flags); // DT_FLAGS
   }
 
   uint64_t dt_flags_1 = 0x0;
-  if (pInfo.options().hasNow())
+  if (pConfig.options().hasNow())
     dt_flags_1 |= llvm::ELF::DF_1_NOW;
-  if (pInfo.options().hasLoadFltr())
+  if (pConfig.options().hasLoadFltr())
     dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
-  if (pInfo.options().hasOrigin())
+  if (pConfig.options().hasOrigin())
     dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
-  if (pInfo.options().hasInterPose())
+  if (pConfig.options().hasInterPose())
     dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
-  if (pInfo.options().hasNoDefaultLib())
+  if (pConfig.options().hasNoDefaultLib())
     dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
-  if (pInfo.options().hasNoDump())
+  if (pConfig.options().hasNoDump())
     dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
-  if (pInfo.options().Bgroup())
+  if (pConfig.options().Bgroup())
     dt_flags_1 |= llvm::ELF::DF_1_GROUP;
-  if (pInfo.output().type() == Output::DynObj) {
-    if (pInfo.options().hasNoDelete())
+  if (LinkerConfig::DynObj == pConfig.codeGenType()) {
+    if (pConfig.options().hasNoDelete())
       dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
-    if (pInfo.options().hasInitFirst())
+    if (pConfig.options().hasInitFirst())
       dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
-    if (pInfo.options().hasNoDLOpen())
+    if (pConfig.options().hasNoDLOpen())
       dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
   }
   if (0x0 != dt_flags_1)
diff --git a/lib/LD/ELFSectionMap.cpp b/lib/Target/ELFEmulation.cpp
similarity index 66%
copy from lib/LD/ELFSectionMap.cpp
copy to lib/Target/ELFEmulation.cpp
index 9d433d7..3bd2094 100644
--- a/lib/LD/ELFSectionMap.cpp
+++ b/lib/Target/ELFEmulation.cpp
@@ -1,4 +1,4 @@
-//===- ELFSectionMap.cpp --------------------------------------------------===//
+//===- ELFEmulation.cpp ---------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,18 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/LD/ELFSectionMap.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/LinkerConfig.h>
 
 using namespace mcld;
 
 struct NameMap {
-  const char* from;
-  const char* to;
+  const char* from; ///< the prefix of the input string. (match FROM*)
+  const char* to;   ///< the output string.
 };
 
-// Common mappings of ELF and other formants. Now only ELF specific mappings
-// are added
 static const NameMap map[] =
 {
   {".text", ".text"},
@@ -33,55 +31,45 @@
   // TODO: Support DT_INIT_ARRAY for all constructors?
   {".ctors", ".ctors"},
   {".dtors", ".dtors"},
-  {".sdata", ".sdata"},
-  {".sbss", ".sbss"},
   // 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.t", ".text"},
   {".gnu.linkonce.r", ".rodata"},
   {".gnu.linkonce.d", ".data"},
   {".gnu.linkonce.b", ".bss"},
-  {".gnu.linkonce.s", ".sdata"},
+  {".gnu.linkonce.sb2", ".sbss"},
   {".gnu.linkonce.sb", ".sbss"},
   {".gnu.linkonce.s2", ".sdata"},
-  {".gnu.linkonce.sb2", ".sbss"},
+  {".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.l", ".ldata"},
   {".gnu.linkonce.lb", ".lbss"},
+  {".gnu.linkonce.l", ".ldata"},
 };
 
-static const int map_size = (sizeof(map) / sizeof(map[0]));
-
-ELFSectionMap::ELFSectionMap()
+bool mcld::MCLDEmulateELF(LinkerConfig& pConfig)
 {
-}
-
-ELFSectionMap::~ELFSectionMap()
-{
-}
-
-void ELFSectionMap::initStandardMaps()
-{
-  for (unsigned int i = 0; i < map_size; ++i) {
-    bool exist = false;
-    NamePair& pair = append(map[i].from, map[i].to, exist);
-    if (exist) {
-      warning(diag::warn_duplicate_std_sectmap) << map[i].from
-                                                << map[i].to
-                                                << pair.from
-                                                << pair.to;
+  if (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;
+      pConfig.scripts().sectionMap().append(map[i].from, map[i].to, exist);
+      if (exist)
+        return false;
     }
   }
+  return true;
 }
 
diff --git a/lib/LD/ELFSectionMap.cpp b/lib/Target/ELFMCLinker.cpp
similarity index 67%
rename from lib/LD/ELFSectionMap.cpp
rename to lib/Target/ELFMCLinker.cpp
index 9d433d7..0c4d98f 100644
--- a/lib/LD/ELFSectionMap.cpp
+++ b/lib/Target/ELFMCLinker.cpp
@@ -1,4 +1,4 @@
-//===- ELFSectionMap.cpp --------------------------------------------------===//
+//===- ELFMCLinker.cpp ----------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,18 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/Target/ELFMCLinker.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Object/SectionMap.h>
 #include <mcld/Support/MsgHandling.h>
-#include <mcld/LD/ELFSectionMap.h>
 
 using namespace mcld;
 
 struct NameMap {
-  const char* from;
-  const char* to;
+  const char* from; ///< the prefix of the input string. (match FROM*)
+  const char* to;   ///< the output string.
 };
 
-// Common mappings of ELF and other formants. Now only ELF specific mappings
-// are added
 static const NameMap map[] =
 {
   {".text", ".text"},
@@ -33,55 +33,46 @@
   // TODO: Support DT_INIT_ARRAY for all constructors?
   {".ctors", ".ctors"},
   {".dtors", ".dtors"},
-  {".sdata", ".sdata"},
-  {".sbss", ".sbss"},
   // 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.t", ".text"},
   {".gnu.linkonce.r", ".rodata"},
   {".gnu.linkonce.d", ".data"},
   {".gnu.linkonce.b", ".bss"},
-  {".gnu.linkonce.s", ".sdata"},
+  {".gnu.linkonce.sb2", ".sbss"},
   {".gnu.linkonce.sb", ".sbss"},
   {".gnu.linkonce.s2", ".sdata"},
-  {".gnu.linkonce.sb2", ".sbss"},
+  {".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.l", ".ldata"},
   {".gnu.linkonce.lb", ".lbss"},
+  {".gnu.linkonce.l", ".ldata"},
 };
 
-static const int map_size = (sizeof(map) / sizeof(map[0]));
+//===----------------------------------------------------------------------===//
+// ELFMCLinker
+//===----------------------------------------------------------------------===//
+ELFMCLinker::ELFMCLinker(LinkerConfig& pConfig,
+                         mcld::Module& pModule,
+                         MemoryArea& pOutput)
+  : MCLinker(pConfig, pModule, pOutput) {
 
-ELFSectionMap::ELFSectionMap()
-{
 }
 
-ELFSectionMap::~ELFSectionMap()
+ELFMCLinker::~ELFMCLinker()
 {
-}
-
-void ELFSectionMap::initStandardMaps()
-{
-  for (unsigned int i = 0; i < map_size; ++i) {
-    bool exist = false;
-    NamePair& pair = append(map[i].from, map[i].to, exist);
-    if (exist) {
-      warning(diag::warn_duplicate_std_sectmap) << map[i].from
-                                                << map[i].to
-                                                << pair.from
-                                                << pair.to;
-    }
-  }
+  // MCLinker will delete m_pLDBackend and m_pLDDriver;
 }
 
diff --git a/lib/Target/ELFSectLinker.cpp b/lib/Target/ELFSectLinker.cpp
deleted file mode 100644
index b95ed0b..0000000
--- a/lib/Target/ELFSectLinker.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- ELFSectLinker.cpp ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Target/ELFSectLinker.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-//==========================
-// ELFSectLinker
-ELFSectLinker::ELFSectLinker(SectLinkerOption &pOption,
-                             TargetLDBackend &pLDBackend)
-  : SectLinker(pOption, pLDBackend) {
-}
-
-ELFSectLinker::~ELFSectLinker()
-{
-  // SectLinker will delete m_pLDBackend and m_pLDDriver;
-}
-
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
index f81133f..950ac43 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -6,45 +6,65 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include <mcld/Target/GNULDBackend.h>
 
 #include <string>
 #include <cstring>
 #include <cassert>
 
-#include <llvm/Support/ELF.h>
-
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/InputTree.h>
 #include <mcld/ADT/SizeTraits.h>
 #include <mcld/LD/LDSymbol.h>
-#include <mcld/LD/Layout.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/SymbolCategory.h>
-#include <mcld/MC/MCLinker.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/MC/Attribute.h>
+#include <mcld/Fragment/FragmentLinker.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/StubFactory.h>
+#include <mcld/Object/ObjectBuilder.h>
 
 using namespace mcld;
 
+//===--------------------------------------------------------------------===//
+// non-member functions
+//===----------------------------------------------------------------------===//
+
+/// isCIdentifier - return if the pName is a valid C identifier
+static bool isCIdentifier(const std::string& pName)
+{
+  std::string ident = "0123456789"
+                      "ABCDEFGHIJKLMNOPWRSTUVWXYZ"
+                      "abcdefghijklmnopqrstuvwxyz"
+                      "_";
+  return (pName.find_first_not_of(ident) > pName.length());
+}
+
 //===----------------------------------------------------------------------===//
 // GNULDBackend
 //===----------------------------------------------------------------------===//
-GNULDBackend::GNULDBackend()
-  : m_pArchiveReader(NULL),
+GNULDBackend::GNULDBackend(const LinkerConfig& pConfig)
+  : TargetLDBackend(pConfig),
     m_pObjectReader(NULL),
-    m_pDynObjReader(NULL),
-    m_pObjectWriter(NULL),
-    m_pDynObjWriter(NULL),
-    m_pExecWriter(NULL),
     m_pDynObjFileFormat(NULL),
     m_pExecFileFormat(NULL),
+    m_pObjectFileFormat(NULL),
     m_ELFSegmentTable(9), // magic number
+    m_pBRIslandFactory(NULL),
+    m_pStubFactory(NULL),
+    m_pEhFrame(NULL),
     m_pEhFrameHdr(NULL),
+    m_bHasTextRel(false),
+    m_bHasStaticTLS(false),
     f_pPreInitArrayStart(NULL),
     f_pPreInitArrayEnd(NULL),
     f_pInitArrayStart(NULL),
@@ -52,6 +72,9 @@
     f_pFiniArrayStart(NULL),
     f_pFiniArrayEnd(NULL),
     f_pStack(NULL),
+    f_pDynamic(NULL),
+    f_pTDATA(NULL),
+    f_pTBSS(NULL),
     f_pExecutableStart(NULL),
     f_pEText(NULL),
     f_p_EText(NULL),
@@ -66,26 +89,16 @@
 
 GNULDBackend::~GNULDBackend()
 {
-  if (NULL != m_pArchiveReader)
-    delete m_pArchiveReader;
-  if (NULL != m_pObjectReader)
-    delete m_pObjectReader;
-  if (NULL != m_pDynObjReader)
-    delete m_pDynObjReader;
-  if (NULL != m_pObjectWriter)
-    delete m_pObjectWriter;
-  if (NULL != m_pDynObjWriter)
-    delete m_pDynObjWriter;
-  if (NULL != m_pExecWriter)
-    delete m_pExecWriter;
-  if (NULL != m_pDynObjFileFormat)
-    delete m_pDynObjFileFormat;
-  if (NULL != m_pExecFileFormat)
-    delete m_pExecFileFormat;
-  if (NULL != m_pSymIndexMap)
-    delete m_pSymIndexMap;
-  if (NULL != m_pEhFrameHdr)
-    delete m_pEhFrameHdr;
+  delete m_pDynObjFileFormat;
+  delete m_pExecFileFormat;
+  delete m_pSymIndexMap;
+  delete m_pEhFrame;
+  delete m_pEhFrameHdr;
+
+  if (NULL != m_pBRIslandFactory)
+    delete m_pBRIslandFactory;
+  if (NULL != m_pStubFactory)
+    delete m_pStubFactory;
 }
 
 size_t GNULDBackend::sectionStartOffset() const
@@ -94,98 +107,153 @@
   return sizeof(llvm::ELF::Elf64_Ehdr)+10*sizeof(llvm::ELF::Elf64_Phdr);
 }
 
-uint64_t GNULDBackend::segmentStartAddr(const Output& pOutput,
-                                        const MCLDInfo& pInfo) const
+uint64_t GNULDBackend::segmentStartAddr(const FragmentLinker& pLinker) const
 {
-  // TODO: handle the user option: -TText=
-  if (isOutputPIC(pOutput, pInfo))
+  ScriptOptions::AddressMap::const_iterator mapping =
+    config().scripts().addressMap().find(".text");
+  if (mapping != config().scripts().addressMap().end())
+    return mapping.getEntry()->value();
+  else if (pLinker.isOutputPIC())
     return 0x0;
   else
     return defaultTextSegmentAddr();
 }
 
-bool GNULDBackend::initArchiveReader(MCLinker& pLinker,
-                                     MCLDInfo& pInfo,
-                                     MemoryAreaFactory& pMemAreaFactory)
+GNUArchiveReader*
+GNULDBackend::createArchiveReader(Module& pModule)
 {
-  if (NULL == m_pArchiveReader) {
-    assert(NULL != m_pObjectReader);
-    m_pArchiveReader = new GNUArchiveReader(pInfo,
-                                            pMemAreaFactory,
-                                            *m_pObjectReader);
+  assert(NULL != m_pObjectReader);
+  return new GNUArchiveReader(pModule, *m_pObjectReader);
+}
+
+ELFObjectReader* GNULDBackend::createObjectReader(FragmentLinker& pLinker)
+{
+  m_pObjectReader = new ELFObjectReader(*this, pLinker);
+  return m_pObjectReader;
+}
+
+ELFDynObjReader* GNULDBackend::createDynObjReader(FragmentLinker& pLinker)
+{
+  return new ELFDynObjReader(*this, pLinker);
+}
+
+ELFObjectWriter* GNULDBackend::createObjectWriter(FragmentLinker& pLinker)
+{
+  return new ELFObjectWriter(*this, pLinker);
+}
+
+ELFDynObjWriter* GNULDBackend::createDynObjWriter(FragmentLinker& pLinker)
+{
+  return new ELFDynObjWriter(*this, pLinker);
+}
+
+ELFExecWriter* GNULDBackend::createExecWriter(FragmentLinker& pLinker)
+{
+  return new ELFExecWriter(*this, pLinker);
+}
+
+bool GNULDBackend::initStdSections(ObjectBuilder& pBuilder)
+{
+  switch (config().codeGenType()) {
+    case LinkerConfig::DynObj: {
+      if (NULL == m_pDynObjFileFormat)
+        m_pDynObjFileFormat = new ELFDynObjFileFormat();
+      m_pDynObjFileFormat->initStdSections(pBuilder, bitclass());
+      return true;
+    }
+    case LinkerConfig::Exec: {
+      if (NULL == m_pExecFileFormat)
+        m_pExecFileFormat = new ELFExecFileFormat();
+      m_pExecFileFormat->initStdSections(pBuilder, bitclass());
+      return true;
+    }
+    case LinkerConfig::Object: {
+      if (NULL == m_pObjectFileFormat)
+        m_pObjectFileFormat = new ELFObjectFileFormat();
+      m_pObjectFileFormat->initStdSections(pBuilder, bitclass());
+      return true;
+    }
+    default:
+      fatal(diag::unrecognized_output_file) << config().codeGenType();
+      return false;
   }
-  return true;
 }
 
-bool GNULDBackend::initObjectReader(MCLinker& pLinker)
+/// initStandardSymbols - define and initialize standard symbols.
+/// This function is called after section merging but before read relocations.
+bool GNULDBackend::initStandardSymbols(FragmentLinker& pLinker,
+                                       Module& pModule)
 {
-  if (NULL == m_pObjectReader)
-    m_pObjectReader = new ELFObjectReader(*this, pLinker);
-  return true;
-}
+  if (LinkerConfig::Object == config().codeGenType())
+    return true;
 
-bool GNULDBackend::initDynObjReader(MCLinker& pLinker)
-{
-  if (NULL == m_pDynObjReader)
-    m_pDynObjReader = new ELFDynObjReader(*this, pLinker);
-  return true;
-}
+  // GNU extension: define __start and __stop symbols for the sections whose
+  // name can be presented as C symbol
+  // ref: GNU gold, Layout::define_section_symbols
+  Module::iterator iter, iterEnd = pModule.end();
+  for (iter = pModule.begin(); iter != iterEnd; ++iter) {
+    LDSection* section = *iter;
 
-bool GNULDBackend::initObjectWriter(MCLinker&)
-{
-  // TODO
-  return true;
-}
+    switch (section->kind()) {
+      case LDFileFormat::Relocation:
+        continue;
+      case LDFileFormat::EhFrame:
+        if (!section->hasEhFrame())
+          continue;
+        break;
+      default:
+        if (!section->hasSectionData())
+          continue;
+        break;
+    } // end of switch
 
-bool GNULDBackend::initDynObjWriter(MCLinker& pLinker)
-{
-  if (NULL == m_pDynObjWriter)
-    m_pDynObjWriter = new ELFDynObjWriter(*this, pLinker);
-  return true;
-}
+    if (isCIdentifier(section->name())) {
+      llvm::StringRef start_name = llvm::StringRef("__start_" + section->name());
+      FragmentRef* start_fragref = FragmentRef::Create(
+                                       section->getSectionData()->front(), 0x0);
+      pLinker.defineSymbol<FragmentLinker::AsRefered,
+                           FragmentLinker::Resolve>(start_name,
+                                                    false, // isDyn
+                                                    ResolveInfo::NoType,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Global,
+                                                    0x0, // size
+                                                    0x0, // value
+                                                    start_fragref, // FragRef
+                                                    ResolveInfo::Default);
 
-bool GNULDBackend::initExecWriter(MCLinker& pLinker)
-{
-  if (NULL == m_pExecWriter)
-    m_pExecWriter = new ELFExecWriter(*this, pLinker);
-  return true;
-}
+      llvm::StringRef stop_name = llvm::StringRef("__stop_" + section->name());
+      FragmentRef* stop_fragref = FragmentRef::Create(
+                           section->getSectionData()->front(), section->size());
+      pLinker.defineSymbol<FragmentLinker::AsRefered,
+                           FragmentLinker::Resolve>(stop_name,
+                                                    false, // isDyn
+                                                    ResolveInfo::NoType,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Global,
+                                                    0x0, // size
+                                                    0x0, // value
+                                                    stop_fragref, // FragRef
+                                                    ResolveInfo::Default);
+    }
+  }
 
-bool GNULDBackend::initExecSections(MCLinker& pMCLinker)
-{
-  if (NULL == m_pExecFileFormat)
-    m_pExecFileFormat = new ELFExecFileFormat(*this);
-
-  // initialize standard sections
-  m_pExecFileFormat->initStdSections(pMCLinker);
-  return true;
-}
-
-bool GNULDBackend::initDynObjSections(MCLinker& pMCLinker)
-{
-  if (NULL == m_pDynObjFileFormat)
-    m_pDynObjFileFormat = new ELFDynObjFileFormat(*this);
-
-  // initialize standard sections
-  m_pDynObjFileFormat->initStdSections(pMCLinker);
-  return true;
-}
-
-bool GNULDBackend::initStandardSymbols(MCLinker& pLinker, const Output& pOutput)
-{
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  ELFFileFormat* file_format = getOutputFormat();
 
   // -----  section symbols  ----- //
   // .preinit_array
   FragmentRef* preinit_array = NULL;
   if (file_format->hasPreInitArray()) {
-    preinit_array = pLinker.getLayout().getFragmentRef(
-                   *(file_format->getPreInitArray().getSectionData()->begin()),
+    preinit_array = FragmentRef::Create(
+                   file_format->getPreInitArray().getSectionData()->front(),
                    0x0);
   }
+  else {
+    preinit_array = FragmentRef::Null();
+  }
   f_pPreInitArrayStart =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__preinit_array_start",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__preinit_array_start",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
@@ -195,28 +263,31 @@
                                              preinit_array, // FragRef
                                              ResolveInfo::Hidden);
   f_pPreInitArrayEnd =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__preinit_array_end",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__preinit_array_end",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Global,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Hidden);
 
   // .init_array
   FragmentRef* init_array = NULL;
   if (file_format->hasInitArray()) {
-    init_array = pLinker.getLayout().getFragmentRef(
-                      *(file_format->getInitArray().getSectionData()->begin()),
+    init_array = FragmentRef::Create(
+                      file_format->getInitArray().getSectionData()->front(),
                       0x0);
   }
+  else {
+    init_array = FragmentRef::Null();
+  }
 
   f_pInitArrayStart =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__init_array_start",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__init_array_start",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
@@ -226,8 +297,8 @@
                                              init_array, // FragRef
                                              ResolveInfo::Hidden);
   f_pInitArrayEnd =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__init_array_end",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__init_array_end",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
@@ -240,14 +311,17 @@
   // .fini_array
   FragmentRef* fini_array = NULL;
   if (file_format->hasFiniArray()) {
-    fini_array = pLinker.getLayout().getFragmentRef(
-                     *(file_format->getFiniArray().getSectionData()->begin()),
+    fini_array = FragmentRef::Create(
+                     file_format->getFiniArray().getSectionData()->front(),
                      0x0);
   }
+  else {
+    fini_array = FragmentRef::Null();
+  }
 
   f_pFiniArrayStart =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__fini_array_start",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__fini_array_start",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
@@ -257,8 +331,8 @@
                                              fini_array, // FragRef
                                              ResolveInfo::Hidden);
   f_pFiniArrayEnd =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__fini_array_end",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__fini_array_end",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
@@ -271,13 +345,17 @@
   // .stack
   FragmentRef* stack = NULL;
   if (file_format->hasStack()) {
-    stack = pLinker.getLayout().getFragmentRef(
-                          *(file_format->getStack().getSectionData()->begin()),
+    stack = FragmentRef::Create(
+                          file_format->getStack().getSectionData()->front(),
                           0x0);
   }
+  else {
+    stack = FragmentRef::Null();
+  }
+
   f_pStack =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__stack",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__stack",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
@@ -287,124 +365,142 @@
                                              stack, // FragRef
                                              ResolveInfo::Hidden);
 
+  // _DYNAMIC
+  // TODO: add SectionData for .dynamic section, and then we can get the correct
+  // symbol section index for _DYNAMIC. Now it will be ABS.
+  f_pDynamic =
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("_DYNAMIC",
+                                                   false, // isDyn
+                                                   ResolveInfo::Object,
+                                                   ResolveInfo::Define,
+                                                   ResolveInfo::Local,
+                                                   0x0, // size
+                                                   0x0, // value
+                                                   FragmentRef::Null(), // FragRef
+                                                   ResolveInfo::Hidden);
+
   // -----  segment symbols  ----- //
   f_pExecutableStart =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__executable_start",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__executable_start",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
   f_pEText =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("etext",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("etext",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
   f_p_EText =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("_etext",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("_etext",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
   f_p__EText =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("__etext",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("__etext",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
   f_pEData =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("edata",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("edata",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
 
   f_pEnd =
-     pLinker.defineSymbol<MCLinker::AsRefered,
-                          MCLinker::Resolve>("end",
+     pLinker.defineSymbol<FragmentLinker::AsRefered,
+                          FragmentLinker::Resolve>("end",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
 
   // _edata is defined forcefully.
   // @ref Google gold linker: defstd.cc: 186
   f_p_EData =
-     pLinker.defineSymbol<MCLinker::Force,
-                          MCLinker::Resolve>("_edata",
+     pLinker.defineSymbol<FragmentLinker::Force,
+                          FragmentLinker::Resolve>("_edata",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
 
   // __bss_start is defined forcefully.
   // @ref Google gold linker: defstd.cc: 214
   f_pBSSStart =
-     pLinker.defineSymbol<MCLinker::Force,
-                          MCLinker::Resolve>("__bss_start",
+     pLinker.defineSymbol<FragmentLinker::Force,
+                          FragmentLinker::Resolve>("__bss_start",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
 
   // _end is defined forcefully.
   // @ref Google gold linker: defstd.cc: 228
   f_p_End =
-     pLinker.defineSymbol<MCLinker::Force,
-                          MCLinker::Resolve>("_end",
+     pLinker.defineSymbol<FragmentLinker::Force,
+                          FragmentLinker::Resolve>("_end",
                                              false, // isDyn
                                              ResolveInfo::NoType,
                                              ResolveInfo::Define,
                                              ResolveInfo::Absolute,
                                              0x0, // size
                                              0x0, // value
-                                             NULL, // FragRef
+                                             FragmentRef::Null(), // FragRef
                                              ResolveInfo::Default);
 
   return true;
 }
 
 bool
-GNULDBackend::finalizeStandardSymbols(MCLinker& pLinker, const Output& pOutput)
+GNULDBackend::finalizeStandardSymbols(FragmentLinker& pLinker)
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  if (LinkerConfig::Object == config().codeGenType())
+    return true;
+
+  ELFFileFormat* file_format = getOutputFormat();
 
   // -----  section symbols  ----- //
   if (NULL != f_pPreInitArrayStart) {
@@ -468,6 +564,12 @@
     }
   }
 
+  if (NULL != f_pDynamic) {
+    f_pDynamic->resolveInfo()->setBinding(ResolveInfo::Local);
+    f_pDynamic->setValue(file_format->getDynamic().addr());
+    f_pDynamic->setSize(file_format->getDynamic().size());
+  }
+
   // -----  segment symbols  ----- //
   if (NULL != f_pExecutableStart) {
     ELFSegment* exec_start = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD, 0x0, 0x0);
@@ -563,200 +665,185 @@
   return true;
 }
 
-GNUArchiveReader *GNULDBackend::getArchiveReader()
+bool GNULDBackend::finalizeTLSSymbol(LDSymbol& pSymbol)
 {
-  assert(NULL != m_pArchiveReader);
-  return m_pArchiveReader;
+  // ignore if symbol has no fragRef
+  if (!pSymbol.hasFragRef())
+    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);
+  uint64_t value = pSymbol.fragRef()->getOutputOffset();
+  uint64_t addr  = pSymbol.fragRef()->frag()->getParent()->getSection().addr();
+  pSymbol.setValue(value + addr - tls_seg->vaddr());
+  return true;
 }
 
-const GNUArchiveReader *GNULDBackend::getArchiveReader() const
+ELFFileFormat* GNULDBackend::getOutputFormat()
 {
-  assert(NULL != m_pArchiveReader);
-  return m_pArchiveReader;
-}
-
-ELFObjectReader *GNULDBackend::getObjectReader()
-{
-  assert(NULL != m_pObjectReader);
-  return m_pObjectReader;
-}
-
-const ELFObjectReader *GNULDBackend::getObjectReader() const
-{
-  assert(NULL != m_pObjectReader);
-  return m_pObjectReader;
-}
-
-ELFDynObjReader *GNULDBackend::getDynObjReader()
-{
-  assert(NULL != m_pDynObjReader);
-  return m_pDynObjReader;
-}
-
-const ELFDynObjReader *GNULDBackend::getDynObjReader() const
-{
-  assert(NULL != m_pDynObjReader);
-  return m_pDynObjReader;
-}
-
-ELFObjectWriter *GNULDBackend::getObjectWriter()
-{
-  // TODO
-  return NULL;
-}
-
-const ELFObjectWriter *GNULDBackend::getObjectWriter() const
-{
-  // TODO
-  return NULL;
-}
-
-ELFDynObjWriter *GNULDBackend::getDynObjWriter()
-{
-  assert(NULL != m_pDynObjWriter);
-  return m_pDynObjWriter;
-}
-
-const ELFDynObjWriter *GNULDBackend::getDynObjWriter() const
-{
-  assert(NULL != m_pDynObjWriter);
-  return m_pDynObjWriter;
-}
-
-ELFExecWriter *GNULDBackend::getExecWriter()
-{
-  assert(NULL != m_pExecWriter);
-  return m_pExecWriter;
-}
-
-const ELFExecWriter *GNULDBackend::getExecWriter() const
-{
-  assert(NULL != m_pExecWriter);
-  return m_pExecWriter;
-}
-
-ELFFileFormat* GNULDBackend::getOutputFormat(const Output& pOutput)
-{
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      return getDynObjFileFormat();
-    case Output::Exec:
-      return getExecFileFormat();
-    // FIXME: We do not support building .o now
-    case Output::Object:
+  switch (config().codeGenType()) {
+    case LinkerConfig::DynObj:
+      assert(NULL != m_pDynObjFileFormat);
+      return m_pDynObjFileFormat;
+    case LinkerConfig::Exec:
+      assert(NULL != m_pExecFileFormat);
+      return m_pExecFileFormat;
+    case LinkerConfig::Object:
+      assert(NULL != m_pObjectFileFormat);
+      return m_pObjectFileFormat;
     default:
-      fatal(diag::unrecognized_output_file) << pOutput.type();
+      fatal(diag::unrecognized_output_file) << config().codeGenType();
       return NULL;
   }
 }
 
-const ELFFileFormat* GNULDBackend::getOutputFormat(const Output& pOutput) const
+const ELFFileFormat* GNULDBackend::getOutputFormat() const
 {
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      return getDynObjFileFormat();
-    case Output::Exec:
-      return getExecFileFormat();
-    // FIXME: We do not support building .o now
-    case Output::Object:
+  switch (config().codeGenType()) {
+    case LinkerConfig::DynObj:
+      assert(NULL != m_pDynObjFileFormat);
+      return m_pDynObjFileFormat;
+    case LinkerConfig::Exec:
+      assert(NULL != m_pExecFileFormat);
+      return m_pExecFileFormat;
+    case LinkerConfig::Object:
+      assert(NULL != m_pObjectFileFormat);
+      return m_pObjectFileFormat;
     default:
-      fatal(diag::unrecognized_output_file) << pOutput.type();
+      fatal(diag::unrecognized_output_file) << config().codeGenType();
       return NULL;
   }
 }
 
-ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat()
+void GNULDBackend::partialScanRelocation(Relocation& pReloc,
+                                         FragmentLinker& pLinker,
+                                         Module& pModule,
+                                         const LDSection& pSection)
 {
-  assert(NULL != m_pDynObjFileFormat);
-  return m_pDynObjFileFormat;
-}
+  // if we meet a section symbol
+  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
+    LDSymbol* input_sym = pReloc.symInfo()->outSymbol();
 
-const ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat() const
-{
-  assert(NULL != m_pDynObjFileFormat);
-  return m_pDynObjFileFormat;
-}
+    // 1. update the relocation target offset
+    assert(input_sym->hasFragRef());
+    uint64_t offset = input_sym->fragRef()->getOutputOffset();
+    pReloc.target() += offset;
 
-ELFExecFileFormat* GNULDBackend::getExecFileFormat()
-{
-  assert(NULL != m_pExecFileFormat);
-  return m_pExecFileFormat;
-}
-
-const ELFExecFileFormat* GNULDBackend::getExecFileFormat() const
-{
-  assert(NULL != m_pExecFileFormat);
-  return m_pExecFileFormat;
+    // 2. get output section symbol
+    // 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();
+    // set relocation target symbol to the output section symbol's resolveInfo
+    pReloc.setSymInfo(sym_info);
+  }
 }
 
 /// sizeNamePools - compute the size of regular name pools
 /// In ELF executable files, regular name pools are .symtab, .strtab,
-/// .dynsym, .dynstr, and .hash
+/// .dynsym, .dynstr, .hash and .shstrtab.
 void
-GNULDBackend::sizeNamePools(const Output& pOutput,
-                            const SymbolCategory& pSymbols,
-                            const MCLDInfo& pLDInfo)
+GNULDBackend::sizeNamePools(const Module& pModule, bool pIsStaticLink)
 {
-  // size of string tables starts from 1 to hold the null character in their
-  // first byte
-  size_t symtab = 1;
-  size_t dynsym = 1;
   // number of entries in symbol tables starts from 1 to hold the special entry
   // at index 0 (STN_UNDEF). See ELF Spec Book I, p1-21.
+  size_t symtab = 1;
+  size_t dynsym = pIsStaticLink ? 0 : 1;
+
+  // size of string tables starts from 1 to hold the null character in their
+  // first byte
   size_t strtab = 1;
-  size_t dynstr = 1;
+  size_t dynstr = pIsStaticLink ? 0 : 1;
+  size_t shstrtab = 1;
   size_t hash   = 0;
 
-  // compute size of .symtab, .dynsym and .strtab
-  SymbolCategory::const_iterator symbol;
-  SymbolCategory::const_iterator symEnd = pSymbols.end();
-  for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
-    size_t str_size = (*symbol)->nameSize() + 1;
-    if (isDynamicSymbol(**symbol, pOutput)) {
+  /// compute the size of .symtab, .dynsym and .strtab
+  /// @{
+  Module::const_sym_iterator symbol;
+  const Module::SymbolTable& symbols = pModule.getSymbolTable();
+  size_t str_size = 0;
+  // compute the size of symbols in Local and File category
+  Module::const_sym_iterator symEnd = symbols.localEnd();
+  for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
+    str_size = (*symbol)->nameSize() + 1;
+    if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
       ++dynsym;
-      dynstr += str_size;
+      if (ResolveInfo::Section != (*symbol)->type())
+        dynstr += str_size;
     }
     ++symtab;
-    strtab += str_size;
+    if (ResolveInfo::Section != (*symbol)->type())
+      strtab += str_size;
+  }
+  // compute the size of symbols in TLS category
+  symEnd = symbols.tlsEnd();
+  for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+    str_size = (*symbol)->nameSize() + 1;
+    if (!pIsStaticLink) {
+      ++dynsym;
+      if (ResolveInfo::Section != (*symbol)->type())
+        dynstr += str_size;
+    }
+    ++symtab;
+    if (ResolveInfo::Section != (*symbol)->type())
+      strtab += str_size;
+  }
+  // compute the size of the reset of symbols
+  symEnd = pModule.sym_end();
+  for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
+    str_size = (*symbol)->nameSize() + 1;
+    if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
+      ++dynsym;
+      if (ResolveInfo::Section != (*symbol)->type())
+        dynstr += str_size;
+    }
+    ++symtab;
+    if (ResolveInfo::Section != (*symbol)->type())
+      strtab += str_size;
   }
 
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  ELFFileFormat* file_format = getOutputFormat();
 
-  switch(pOutput.type()) {
+  switch(config().codeGenType()) {
     // compute size of .dynstr and .hash
-    case Output::DynObj:
-    case Output::Exec: {
+    case LinkerConfig::DynObj: {
+      // soname
+      if (!pIsStaticLink)
+        dynstr += pModule.name().size() + 1;
+    }
+    /** fall through **/
+    case LinkerConfig::Exec: {
       // add DT_NEED strings into .dynstr and .dynamic
       // Rules:
       //   1. ignore --no-add-needed
       //   2. force count in --no-as-needed
       //   3. judge --as-needed
-      InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
-      for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
-        if (Input::DynObj == (*input)->type()) {
+      if (!pIsStaticLink) {
+        Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+        for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
           // --add-needed
-          if ((*input)->attribute()->isAddNeeded()) {
+          if ((*lib)->attribute()->isAddNeeded()) {
             // --no-as-needed
-            if (!(*input)->attribute()->isAsNeeded()) {
-              dynstr += (*input)->name().size() + 1;
+            if (!(*lib)->attribute()->isAsNeeded()) {
+              dynstr += (*lib)->name().size() + 1;
               dynamic().reserveNeedEntry();
             }
             // --as-needed
-            else if ((*input)->isNeeded()) {
-              dynstr += (*input)->name().size() + 1;
+            else if ((*lib)->isNeeded()) {
+              dynstr += (*lib)->name().size() + 1;
               dynamic().reserveNeedEntry();
             }
           }
         }
-      } // for
 
-      // compute .hash
-      // Both Elf32_Word and Elf64_Word are 4 bytes
-      hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
-             sizeof(llvm::ELF::Elf32_Word);
+        // compute .hash
+        // Both Elf32_Word and Elf64_Word are 4 bytes
+        hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
+               sizeof(llvm::ELF::Elf32_Word);
+      }
 
       // set size
-      dynstr += pOutput.name().size() + 1;
       if (32 == bitclass())
         file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf32_Sym));
       else
@@ -766,7 +853,7 @@
 
     }
     /* fall through */
-    case Output::Object: {
+    case LinkerConfig::Object: {
       if (32 == bitclass())
         file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf32_Sym));
       else
@@ -774,50 +861,97 @@
       file_format->getStrTab().setSize(strtab);
       break;
     }
+    default:
+      fatal(diag::fatal_illegal_codegen_type) << pModule.name();
+      break;
   } // end of switch
+  /// @}
 
-  // reserve fixed entries in the .dynamic section.
-  if (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type()) {
+  /// reserve fixed entries in the .dynamic section.
+  /// @{
+  if (LinkerConfig::DynObj == config().codeGenType() ||
+      LinkerConfig::Exec == config().codeGenType()) {
     // Because some entries in .dynamic section need information of .dynsym,
     // .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
     // entries until we get the size of the sections mentioned above
-    dynamic().reserveEntries(pLDInfo, *file_format);
+    if (!pIsStaticLink)
+      dynamic().reserveEntries(config(), *file_format);
     file_format->getDynamic().setSize(dynamic().numOfBytes());
   }
+  /// @}
+
+  /// compute the size of .shstrtab section.
+  /// @{
+  Module::const_iterator sect, sectEnd = pModule.end();
+  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+    // StackNote sections will always be in output!
+    if (0 != (*sect)->size() || LDFileFormat::StackNote == (*sect)->kind()) {
+      shstrtab += ((*sect)->name().size() + 1);
+    }
+  }
+  shstrtab += (strlen(".shstrtab") + 1);
+  file_format->getShStrTab().setSize(shstrtab);
+  /// @}
+}
+
+/// emitSymbol32 - emit an ELF32 symbol
+void GNULDBackend::emitSymbol32(llvm::ELF::Elf32_Sym& pSym,
+                                LDSymbol& pSymbol,
+                                char* pStrtab,
+                                size_t pStrtabsize,
+                                size_t pSymtabIdx)
+{
+   // FIXME: check the endian between host and target
+   // write out symbol
+   if (ResolveInfo::Section != pSymbol.type()) {
+     pSym.st_name  = pStrtabsize;
+     strcpy((pStrtab + pStrtabsize), pSymbol.name());
+   }
+   else {
+     pSym.st_name  = 0;
+   }
+   pSym.st_value = pSymbol.value();
+   pSym.st_size  = getSymbolSize(pSymbol);
+   pSym.st_info  = getSymbolInfo(pSymbol);
+   pSym.st_other = pSymbol.visibility();
+   pSym.st_shndx = getSymbolShndx(pSymbol);
+}
+
+/// emitSymbol64 - emit an ELF64 symbol
+void GNULDBackend::emitSymbol64(llvm::ELF::Elf64_Sym& pSym,
+                                LDSymbol& pSymbol,
+                                char* pStrtab,
+                                size_t pStrtabsize,
+                                size_t pSymtabIdx)
+{
+   // FIXME: check the endian between host and target
+   // write out symbol
+   pSym.st_name  = pStrtabsize;
+   pSym.st_value = pSymbol.value();
+   pSym.st_size  = getSymbolSize(pSymbol);
+   pSym.st_info  = getSymbolInfo(pSymbol);
+   pSym.st_other = pSymbol.visibility();
+   pSym.st_shndx = getSymbolShndx(pSymbol);
+   // write out string
+   strcpy((pStrtab + pStrtabsize), pSymbol.name());
 }
 
 /// emitRegNamePools - emit regular name pools - .symtab, .strtab
 ///
 /// the size of these tables should be computed before layout
 /// layout should computes the start offset of these tables
-void GNULDBackend::emitRegNamePools(Output& pOutput,
-                                    SymbolCategory& pSymbols,
-                                    const Layout& pLayout,
-                                    const MCLDInfo& pLDInfo)
+void GNULDBackend::emitRegNamePools(const Module& pModule,
+                                    MemoryArea& pOutput)
 {
-
-  assert(pOutput.hasMemArea());
-
-  bool sym_exist = false;
-  HashTableType::entry_type* entry = 0;
-
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-  if (pOutput.type() == Output::Object) {
-    // add first symbol into m_pSymIndexMap
-    entry = m_pSymIndexMap->insert(NULL, sym_exist);
-    entry->setValue(0);
-
-    // TODO: not support yet
-    return;
-  }
+  ELFFileFormat* file_format = getOutputFormat();
 
   LDSection& symtab_sect = file_format->getSymTab();
   LDSection& strtab_sect = file_format->getStrTab();
 
-  MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
-                                                           symtab_sect.size());
-  MemoryRegion* strtab_region = pOutput.memArea()->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;
@@ -852,58 +986,52 @@
     symtab64[0].st_shndx = 0;
   }
 
+  bool sym_exist = false;
+  HashTableType::entry_type* entry = NULL;
+  if (LinkerConfig::Object == config().codeGenType()) {
+    entry = m_pSymIndexMap->insert(NULL, sym_exist);
+    entry->setValue(0);
+  }
+
   size_t symtabIdx = 1;
   size_t strtabsize = 1;
   // compute size of .symtab, .dynsym and .strtab
-  SymbolCategory::iterator symbol;
-  SymbolCategory::iterator symEnd = pSymbols.end();
-  for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
-
-     // maintain output's symbol and index map if building .o file
-    if (Output::Object == pOutput.type()) {
-      entry = m_pSymIndexMap->insert(NULL, sym_exist);
+  Module::const_sym_iterator symbol;
+  Module::const_sym_iterator symEnd = pModule.sym_end();
+  for (symbol = pModule.sym_begin(); symbol != symEnd; ++symbol) {
+    // maintain output's symbol and index map if building .o file
+    if (LinkerConfig::Object == config().codeGenType()) {
+      entry = m_pSymIndexMap->insert(*symbol, sym_exist);
       entry->setValue(symtabIdx);
     }
 
-    // FIXME: check the endian between host and target
-    // write out symbol
-    if (32 == bitclass()) {
-      symtab32[symtabIdx].st_name  = strtabsize;
-      symtab32[symtabIdx].st_value = getSymbolValue(**symbol);
-      symtab32[symtabIdx].st_size  = getSymbolSize(**symbol);
-      symtab32[symtabIdx].st_info  = getSymbolInfo(**symbol);
-      symtab32[symtabIdx].st_other = (*symbol)->visibility();
-      symtab32[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
-    }
-    else { // must 64
-      symtab64[symtabIdx].st_name  = strtabsize;
-      symtab64[symtabIdx].st_value = getSymbolValue(**symbol);
-      symtab64[symtabIdx].st_size  = getSymbolSize(**symbol);
-      symtab64[symtabIdx].st_info  = getSymbolInfo(**symbol);
-      symtab64[symtabIdx].st_other = (*symbol)->visibility();
-      symtab64[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
-    }
-    // write out string
-    strcpy((strtab + strtabsize), (*symbol)->name());
+    if (32 == bitclass())
+      emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+    else
+      emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
 
-    // write out
     // sum up counters
     ++symtabIdx;
-    strtabsize += (*symbol)->nameSize() + 1;
+    if (ResolveInfo::Section != (*symbol)->type())
+      strtabsize += (*symbol)->nameSize() + 1;
   }
 }
 
-/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
+/// emitDynNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
 ///
 /// the size of these tables should be computed before layout
 /// layout should computes the start offset of these tables
-void GNULDBackend::emitDynNamePools(Output& pOutput,
-                                    SymbolCategory& pSymbols,
-                                    const Layout& pLayout,
-                                    const MCLDInfo& pLDInfo)
+void GNULDBackend::emitDynNamePools(const Module& pModule,
+                                    MemoryArea& pOutput)
 {
-  assert(pOutput.hasMemArea());
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  ELFFileFormat* file_format = getOutputFormat();
+  if (!file_format->hasDynSymTab() ||
+      !file_format->hasDynStrTab() ||
+      !file_format->hasHashTab()   ||
+      !file_format->hasDynamic())
+    return;
 
   bool sym_exist = false;
   HashTableType::entry_type* entry = 0;
@@ -913,14 +1041,14 @@
   LDSection& hash_sect   = file_format->getHashTab();
   LDSection& dyn_sect    = file_format->getDynamic();
 
-  MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
-                                                           symtab_sect.size());
-  MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
-                                                           strtab_sect.size());
-  MemoryRegion* hash_region = pOutput.memArea()->request(hash_sect.offset(),
-                                                         hash_sect.size());
-  MemoryRegion* dyn_region = pOutput.memArea()->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* hash_region   = pOutput.request(hash_sect.offset(),
+                                                hash_sect.size());
+  MemoryRegion* dyn_region    = pOutput.request(dyn_sect.offset(),
+                                                dyn_sect.size());
   // set up symtab_region
   llvm::ELF::Elf32_Sym* symtab32 = NULL;
   llvm::ELF::Elf64_Sym* symtab64 = NULL;
@@ -962,40 +1090,69 @@
   size_t strtabsize = 1;
 
   // emit of .dynsym, and .dynstr
-  SymbolCategory::iterator symbol;
-  SymbolCategory::iterator symEnd = pSymbols.end();
-  for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
-    if (!isDynamicSymbol(**symbol, pOutput))
+  Module::const_sym_iterator symbol;
+  const Module::SymbolTable& symbols = pModule.getSymbolTable();
+  // emit symbol in File and Local category if it's dynamic symbol
+  Module::const_sym_iterator symEnd = symbols.localEnd();
+  for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
+    if (!isDynamicSymbol(**symbol))
       continue;
 
+    if (32 == bitclass())
+      emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+    else
+      emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+
     // maintain output's symbol and index map
     entry = m_pSymIndexMap->insert(*symbol, sym_exist);
     entry->setValue(symtabIdx);
-
-    // FIXME: check the endian between host and target
-    // write out symbol
-    if (32 == bitclass()) {
-      symtab32[symtabIdx].st_name  = strtabsize;
-      symtab32[symtabIdx].st_value = (*symbol)->value();
-      symtab32[symtabIdx].st_size  = getSymbolSize(**symbol);
-      symtab32[symtabIdx].st_info  = getSymbolInfo(**symbol);
-      symtab32[symtabIdx].st_other = (*symbol)->visibility();
-      symtab32[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
-    }
-    else { // must 64
-      symtab64[symtabIdx].st_name  = strtabsize;
-      symtab64[symtabIdx].st_value = (*symbol)->value();
-      symtab64[symtabIdx].st_size  = getSymbolSize(**symbol);
-      symtab64[symtabIdx].st_info  = getSymbolInfo(**symbol);
-      symtab64[symtabIdx].st_other = (*symbol)->visibility();
-      symtab64[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
-    }
-    // write out string
-    strcpy((strtab + strtabsize), (*symbol)->name());
-
     // sum up counters
     ++symtabIdx;
-    strtabsize += (*symbol)->nameSize() + 1;
+    if (ResolveInfo::Section != (*symbol)->type())
+      strtabsize += (*symbol)->nameSize() + 1;
+  }
+
+  // emit symbols in TLS category, all symbols in TLS category shold be emitited
+  symEnd = symbols.tlsEnd();
+  for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+    if (32 == bitclass())
+      emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+    else
+      emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+
+    // maintain output's symbol and index map
+    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+    entry->setValue(symtabIdx);
+    // sum up counters
+    ++symtabIdx;
+    if (ResolveInfo::Section != (*symbol)->type())
+      strtabsize += (*symbol)->nameSize() + 1;
+  }
+
+  // emit the reset of the symbols if the symbol is dynamic symbol
+  symEnd = pModule.sym_end();
+  for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
+    if (!isDynamicSymbol(**symbol))
+      continue;
+
+    if (32 == bitclass())
+      emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+    else
+      emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+
+    // maintain output's symbol and index map
+    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+    entry->setValue(symtabIdx);
+    // sum up counters
+    ++symtabIdx;
+    if (ResolveInfo::Section != (*symbol)->type())
+      strtabsize += (*symbol)->nameSize() + 1;
   }
 
   // emit DT_NEED
@@ -1005,39 +1162,40 @@
   //   2. force count in --no-as-needed
   //   3. judge --as-needed
   ELFDynamic::iterator dt_need = dynamic().needBegin();
-  InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
-  for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
-    if (Input::DynObj == (*input)->type()) {
-      // --add-needed
-      if ((*input)->attribute()->isAddNeeded()) {
-        // --no-as-needed
-        if (!(*input)->attribute()->isAsNeeded()) {
-          strcpy((strtab + strtabsize), (*input)->name().c_str());
-          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
-          strtabsize += (*input)->name().size() + 1;
-          ++dt_need;
-        }
-        // --as-needed
-        else if ((*input)->isNeeded()) {
-          strcpy((strtab + strtabsize), (*input)->name().c_str());
-          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
-          strtabsize += (*input)->name().size() + 1;
-          ++dt_need;
-        }
+  Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+  for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
+    // --add-needed
+    if ((*lib)->attribute()->isAddNeeded()) {
+      // --no-as-needed
+      if (!(*lib)->attribute()->isAsNeeded()) {
+        strcpy((strtab + strtabsize), (*lib)->name().c_str());
+        (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+        strtabsize += (*lib)->name().size() + 1;
+        ++dt_need;
+      }
+      // --as-needed
+      else if ((*lib)->isNeeded()) {
+        strcpy((strtab + strtabsize), (*lib)->name().c_str());
+        (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+        strtabsize += (*lib)->name().size() + 1;
+        ++dt_need;
       }
     }
-  } // for
+  }
 
-  // emit soname
   // initialize value of ELF .dynamic section
-  if (Output::DynObj == pOutput.type())
+  if (LinkerConfig::DynObj == config().codeGenType()) {
+    // set pointer to SONAME entry in dynamic string table.
     dynamic().applySoname(strtabsize);
-  dynamic().applyEntries(pLDInfo, *file_format);
+  }
+  dynamic().applyEntries(config(), *file_format);
   dynamic().emit(dyn_sect, *dyn_region);
 
-  strcpy((strtab + strtabsize), pOutput.name().c_str());
-  strtabsize += pOutput.name().size() + 1;
-
+  // emit soname
+  if (LinkerConfig::DynObj == config().codeGenType()) {
+    strcpy((strtab + strtabsize), pModule.name().c_str());
+    strtabsize += pModule.name().size() + 1;
+  }
   // emit hash table
   // FIXME: this verion only emit SVR4 hash section.
   //        Please add GNU new hash section
@@ -1078,56 +1236,52 @@
 }
 
 /// sizeInterp - compute the size of the .interp section
-void GNULDBackend::sizeInterp(const Output& pOutput, const MCLDInfo& pLDInfo)
+void GNULDBackend::sizeInterp()
 {
-  assert(pOutput.type() == Output::Exec);
-
   const char* dyld_name;
-  if (pLDInfo.options().hasDyld())
-    dyld_name = pLDInfo.options().dyld().c_str();
+  if (config().options().hasDyld())
+    dyld_name = config().options().dyld().c_str();
   else
     dyld_name = dyld();
 
-  LDSection& interp = getExecFileFormat()->getInterp();
+  LDSection& interp = getOutputFormat()->getInterp();
   interp.setSize(std::strlen(dyld_name) + 1);
 }
 
 /// emitInterp - emit the .interp
-void GNULDBackend::emitInterp(Output& pOutput, const MCLDInfo& pLDInfo)
+void GNULDBackend::emitInterp(MemoryArea& pOutput)
 {
-  assert(pOutput.type() == Output::Exec &&
-         getExecFileFormat()->hasInterp() &&
-         pOutput.hasMemArea());
+  if (getOutputFormat()->hasInterp()) {
+    const LDSection& interp = getOutputFormat()->getInterp();
+    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 = dyld();
 
-  const LDSection& interp = getExecFileFormat()->getInterp();
-  MemoryRegion *region = pOutput.memArea()->request(
-                                              interp.offset(), interp.size());
-  const char* dyld_name;
-  if (pLDInfo.options().hasDyld())
-    dyld_name = pLDInfo.options().dyld().c_str();
-  else
-    dyld_name = dyld();
-
-  std::memcpy(region->start(), dyld_name, interp.size());
+    std::memcpy(region->start(), dyld_name, interp.size());
+  }
 }
 
 /// getSectionOrder
-unsigned int GNULDBackend::getSectionOrder(const Output& pOutput,
-                                           const LDSection& pSectHdr,
-                                           const MCLDInfo& pInfo) const
+unsigned int GNULDBackend::getSectionOrder(const LDSection& pSectHdr) const
 {
+  const ELFFileFormat* file_format = getOutputFormat();
+
   // NULL section should be the "1st" section
   if (LDFileFormat::Null == pSectHdr.kind())
     return 0;
 
+  if (&pSectHdr == &file_format->getStrTab())
+    return SHO_STRTAB;
+
   // if the section is not ALLOC, lay it out until the last possible moment
   if (0 == (pSectHdr.flag() & llvm::ELF::SHF_ALLOC))
     return SHO_UNDEFINED;
 
   bool is_write = (pSectHdr.flag() & llvm::ELF::SHF_WRITE) != 0;
   bool is_exec = (pSectHdr.flag() & llvm::ELF::SHF_EXECINSTR) != 0;
-  const ELFFileFormat* file_format = getOutputFormat(pOutput);
-
   // TODO: need to take care other possible output sections
   switch (pSectHdr.kind()) {
     case LDFileFormat::Regular:
@@ -1140,10 +1294,10 @@
       } else if (!is_write) {
         return SHO_RO;
       } else {
-        if (pInfo.options().hasRelro()) {
-          if (pSectHdr.type() == llvm::ELF::SHT_PREINIT_ARRAY ||
-              pSectHdr.type() == llvm::ELF::SHT_INIT_ARRAY ||
-              pSectHdr.type() == llvm::ELF::SHT_FINI_ARRAY ||
+        if (config().options().hasRelro()) {
+          if (&pSectHdr == &file_format->getPreInitArray() ||
+              &pSectHdr == &file_format->getInitArray() ||
+              &pSectHdr == &file_format->getFiniArray() ||
               &pSectHdr == &file_format->getCtors() ||
               &pSectHdr == &file_format->getDtors() ||
               &pSectHdr == &file_format->getJCR() ||
@@ -1152,17 +1306,22 @@
           if (0 == pSectHdr.name().compare(".data.rel.ro.local"))
             return SHO_RELRO_LOCAL;
         }
+        if ((pSectHdr.flag() & llvm::ELF::SHF_TLS) != 0x0) {
+          return SHO_TLS_DATA;
+        }
         return SHO_DATA;
       }
 
     case LDFileFormat::BSS:
+      if ((pSectHdr.flag() & llvm::ELF::SHF_TLS) != 0x0)
+        return SHO_TLS_BSS;
       return SHO_BSS;
 
-    case LDFileFormat::NamePool:
+    case LDFileFormat::NamePool: {
       if (&pSectHdr == &file_format->getDynamic())
         return SHO_RELRO;
       return SHO_NAMEPOOL;
-
+    }
     case LDFileFormat::Relocation:
       if (&pSectHdr == &file_format->getRelPlt() ||
           &pSectHdr == &file_format->getRelaPlt())
@@ -1171,7 +1330,7 @@
 
     // get the order from target for target specific sections
     case LDFileFormat::Target:
-      return getTargetSectionOrder(pOutput, pSectHdr, pInfo);
+      return getTargetSectionOrder(pSectHdr);
 
     // handle .interp
     case LDFileFormat::Note:
@@ -1238,7 +1397,7 @@
 
 /// getSymbolShndx - this function is called after layout()
 uint64_t
-GNULDBackend::getSymbolShndx(const LDSymbol& pSymbol, const Layout& pLayout) const
+GNULDBackend::getSymbolShndx(const LDSymbol& pSymbol) const
 {
   if (pSymbol.resolveInfo()->isAbsolute())
     return llvm::ELF::SHN_ABS;
@@ -1255,8 +1414,11 @@
     }
   }
 
+  if (pSymbol.resolveInfo()->isDefine() && !pSymbol.hasFragRef())
+    return llvm::ELF::SHN_ABS;
+
   assert(pSymbol.hasFragRef() && "symbols must have fragment reference to get its index");
-  return pLayout.getOutputLDSection(*pSymbol.fragRef()->frag())->index();
+  return pSymbol.fragRef()->frag()->getParent()->getSection().index();
 }
 
 /// getSymbolIdx - called by emitRelocation to get the ouput symbol table index
@@ -1267,12 +1429,12 @@
 }
 
 /// allocateCommonSymbols - allocate common symbols in the corresponding
-/// sections.
+/// sections. This is executed at pre-layout stage.
 /// @refer Google gold linker: common.cc: 214
 bool
-GNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
+GNULDBackend::allocateCommonSymbols(Module& pModule)
 {
-  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
+  SymbolCategory& symbol_list = pModule.getSymbolTable();
 
   if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
     return true;
@@ -1282,27 +1444,27 @@
   // FIXME: If the order of common symbols is defined, then sort common symbols
   // std::sort(com_sym, com_end, some kind of order);
 
-  // get or create corresponding BSS LDSection
-  LDSection* bss_sect = &pLinker.getOrCreateOutputSectHdr(".bss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-
-  LDSection* tbss_sect = &pLinker.getOrCreateOutputSectHdr(
-                                   ".tbss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-
-  assert(NULL != bss_sect && NULL !=tbss_sect);
+  // get corresponding BSS LDSection
+  ELFFileFormat* file_format = getOutputFormat();
+  LDSection& bss_sect = file_format->getBSS();
+  LDSection& tbss_sect = file_format->getTBSS();
 
   // get or create corresponding BSS SectionData
-  SectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
-  SectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
+  SectionData* bss_sect_data = NULL;
+  if (bss_sect.hasSectionData())
+    bss_sect_data = bss_sect.getSectionData();
+  else
+    bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
+
+  SectionData* tbss_sect_data = NULL;
+  if (tbss_sect.hasSectionData())
+    tbss_sect_data = tbss_sect.getSectionData();
+  else
+    tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
 
   // remember original BSS size
-  uint64_t bss_offset  = bss_sect->size();
-  uint64_t tbss_offset = tbss_sect->size();
+  uint64_t bss_offset  = bss_sect.size();
+  uint64_t tbss_offset = tbss_sect.size();
 
   // allocate all local common symbols
   com_end = symbol_list.localEnd();
@@ -1316,18 +1478,18 @@
       // description here.
       (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
       Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
       if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
         // allocate TLS common symbol in tbss section
-        tbss_offset += pLinker.getLayout().appendFragment(*frag,
-                                                          tbss_sect_data,
-                                                          (*com_sym)->value());
+        tbss_offset += ObjectBuilder::AppendFragment(*frag,
+                                                     *tbss_sect_data,
+                                                     (*com_sym)->value());
       }
       else {
-        bss_offset += pLinker.getLayout().appendFragment(*frag,
-                                                         bss_sect_data,
-                                                         (*com_sym)->value());
+        bss_offset += ObjectBuilder::AppendFragment(*frag,
+                                                    *bss_sect_data,
+                                                    (*com_sym)->value());
       }
     }
   }
@@ -1342,33 +1504,33 @@
     // description here.
     (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
     Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
+    (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
     if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
       // allocate TLS common symbol in tbss section
-      tbss_offset += pLinker.getLayout().appendFragment(*frag,
-                                                        tbss_sect_data,
-                                                        (*com_sym)->value());
+      tbss_offset += ObjectBuilder::AppendFragment(*frag,
+                                                   *tbss_sect_data,
+                                                   (*com_sym)->value());
     }
     else {
-      bss_offset += pLinker.getLayout().appendFragment(*frag,
-                                                       bss_sect_data,
-                                                       (*com_sym)->value());
+      bss_offset += ObjectBuilder::AppendFragment(*frag,
+                                                  *bss_sect_data,
+                                                  (*com_sym)->value());
     }
   }
 
-  bss_sect->setSize(bss_offset);
-  tbss_sect->setSize(tbss_offset);
+  bss_sect.setSize(bss_offset);
+  tbss_sect.setSize(tbss_offset);
   symbol_list.changeCommonsToGlobal();
   return true;
 }
 
 
 /// createProgramHdrs - base on output sections to create the program headers
-void GNULDBackend::createProgramHdrs(Output& pOutput, const MCLDInfo& pInfo)
+void GNULDBackend::createProgramHdrs(Module& pModule,
+                                     const FragmentLinker& pLinker)
 {
-  assert(pOutput.hasContext());
-  ELFFileFormat *file_format = getOutputFormat(pOutput);
+  ELFFileFormat *file_format = getOutputFormat();
 
   // make PT_PHDR
   m_ELFSegmentTable.produce(llvm::ELF::PT_PHDR);
@@ -1379,75 +1541,57 @@
     interp_seg->addSection(&file_format->getInterp());
   }
 
-  // FIXME: Should we consider -z relro here?
-  if (pInfo.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
-    LDContext::SectionTable& sect_table = pOutput.context()->getSectionTable();
-
-    size_t idx;
-    for (idx = 0; idx < pOutput.context()->numOfSections(); ++idx) {
-      // find the first non-relro section
-      if (getSectionOrder(pOutput, *sect_table[idx], pInfo) > SHO_RELRO_LAST) {
-        break;
-      }
-    }
-
-    // align the first non-relro section to page boundary
-    uint64_t offset = sect_table[idx]->offset();
-    alignAddress(offset, commonPageSize(pInfo));
-    sect_table[idx]->setOffset(offset);
-
-    // set up remaining section's offset
-    for (++idx; idx < pOutput.context()->numOfSections(); ++idx) {
-      uint64_t offset;
-      size_t prev_idx = idx - 1;
-      if (LDFileFormat::BSS == sect_table[prev_idx]->kind())
-        offset = sect_table[prev_idx]->offset();
-      else
-        offset = sect_table[prev_idx]->offset() + sect_table[prev_idx]->size();
-
-      alignAddress(offset, sect_table[idx]->align());
-      sect_table[idx]->setOffset(offset);
-    }
-  } // relro
-
-  uint32_t cur_seg_flag, prev_seg_flag = getSegmentFlag(0);
-  uint64_t padding = 0;
+  uint32_t cur_flag, prev_flag = getSegmentFlag(0);
   ELFSegment* load_seg = NULL;
   // make possible PT_LOAD segments
-  LDContext::sect_iterator sect, sect_end = pOutput.context()->sectEnd();
-  for (sect = pOutput.context()->sectBegin(); sect != sect_end; ++sect) {
+  Module::iterator sect, sect_end = pModule.end();
+  for (sect = pModule.begin(); sect != sect_end; ++sect) {
 
     if (0 == ((*sect)->flag() & llvm::ELF::SHF_ALLOC) &&
         LDFileFormat::Null != (*sect)->kind())
       continue;
 
-    // FIXME: Now only separate writable and non-writable PT_LOAD
-    cur_seg_flag = getSegmentFlag((*sect)->flag());
-    if ((prev_seg_flag & llvm::ELF::PF_W) ^ (cur_seg_flag & llvm::ELF::PF_W) ||
-         LDFileFormat::Null == (*sect)->kind()) {
-      // create new PT_LOAD segment
-      load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD);
-      load_seg->setAlign(abiPageSize(pInfo));
+    cur_flag = getSegmentFlag((*sect)->flag());
+    bool createPT_LOAD = false;
+    if (LDFileFormat::Null == (*sect)->kind()) {
+      // 1. create text segment
+      createPT_LOAD = true;
+    }
+    else if (!config().options().omagic() &&
+             (prev_flag & llvm::ELF::PF_W) ^ (cur_flag & llvm::ELF::PF_W)) {
+      // 2. create data segment if w/o omagic set
+      createPT_LOAD = true;
+    }
+    else if ((*sect)->kind() == LDFileFormat::BSS &&
+             load_seg->isDataSegment() &&
+             config().scripts().addressMap().find(".bss") !=
+             (config().scripts().addressMap().end())) {
+      // 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())) &&
+          (config().scripts().addressMap().find((*sect)->name()) !=
+           config().scripts().addressMap().end()))
+        // 4. create PT_LOAD for sections in address map except for text, data,
+        // and bss
+        createPT_LOAD = true;
+    }
 
-      // check if this segment needs padding
-      padding = 0;
-      if (((*sect)->offset() & (abiPageSize(pInfo) - 1)) != 0)
-        padding = abiPageSize(pInfo);
+    if (createPT_LOAD) {
+      // create new PT_LOAD segment
+      load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD, cur_flag);
+      load_seg->setAlign(abiPageSize());
     }
 
     assert(NULL != load_seg);
     load_seg->addSection((*sect));
-    if (cur_seg_flag != prev_seg_flag)
-      load_seg->updateFlag(cur_seg_flag);
+    if (cur_flag != prev_flag)
+      load_seg->updateFlag(cur_flag);
 
-    if (LDFileFormat::Null != (*sect)->kind())
-      (*sect)->setAddr(segmentStartAddr(pOutput, pInfo) +
-                       (*sect)->offset() +
-                       padding);
-
-    prev_seg_flag = cur_seg_flag;
+    prev_flag = cur_flag;
   }
 
   // make PT_DYNAMIC
@@ -1458,16 +1602,22 @@
     dyn_seg->addSection(&file_format->getDynamic());
   }
 
-  if (pInfo.options().hasRelro()) {
+  if (config().options().hasRelro()) {
     // make PT_GNU_RELRO
     ELFSegment* relro_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_RELRO);
-    for (LDContext::sect_iterator sect = pOutput.context()->sectBegin();
-         sect != pOutput.context()->sectEnd(); ++sect) {
-      unsigned int order = getSectionOrder(pOutput, **sect, pInfo);
-      if (SHO_RELRO_LOCAL == order ||
-          SHO_RELRO == order ||
-          SHO_RELRO_LAST == order) {
-        relro_seg->addSection(*sect);
+    for (ELFSegmentFactory::iterator seg = elfSegmentTable().begin(),
+         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) {
+        unsigned int order = getSectionOrder(**sect);
+        if (SHO_RELRO_LOCAL == order ||
+            SHO_RELRO == order ||
+            SHO_RELRO_LAST == order) {
+          relro_seg->addSection(*sect);
+        }
       }
     }
   }
@@ -1477,10 +1627,30 @@
     ELFSegment* eh_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_EH_FRAME);
     eh_seg->addSection(&file_format->getEhFrameHdr());
   }
+
+  // make PT_TLS
+  if (file_format->hasTData() || file_format->hasTBSS()) {
+    ELFSegment* tls_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_TLS);
+    if (file_format->hasTData())
+      tls_seg->addSection(&file_format->getTData());
+    if (file_format->hasTBSS())
+      tls_seg->addSection(&file_format->getTBSS());
+  }
+
+  // make PT_GNU_STACK
+  if (file_format->hasStackNote()) {
+    m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_STACK,
+                              llvm::ELF::PF_R |
+                              llvm::ELF::PF_W |
+                              getSegmentFlag(file_format->getStackNote().flag()));
+  }
+
+  // create target dependent segments
+  doCreateProgramHdrs(pModule, pLinker);
 }
 
 /// setupProgramHdrs - set up the attributes of segments
-void GNULDBackend:: setupProgramHdrs(const Output& pOutput, const MCLDInfo& pInfo)
+void GNULDBackend::setupProgramHdrs(const FragmentLinker& pLinker)
 {
   // update segment info
   ELFSegmentFactory::iterator seg, seg_end = m_ELFSegmentTable.end();
@@ -1499,7 +1669,7 @@
         phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
       }
       segment.setOffset(offset);
-      segment.setVaddr(segmentStartAddr(pOutput, pInfo) + offset);
+      segment.setVaddr(segmentStartAddr(pLinker) + offset);
       segment.setPaddr(segment.vaddr());
       segment.setFilesz(numOfSegments() * phdr_size);
       segment.setMemsz(numOfSegments() * phdr_size);
@@ -1511,15 +1681,15 @@
     if (segment.numOfSections() == 0)
       continue;
 
-    segment.setOffset(segment.getFirstSection()->offset());
+    segment.setOffset(segment.front()->offset());
     if (llvm::ELF::PT_LOAD == segment.type() &&
-        LDFileFormat::Null == segment.getFirstSection()->kind())
-      segment.setVaddr(segmentStartAddr(pOutput, pInfo));
+        LDFileFormat::Null == segment.front()->kind())
+      segment.setVaddr(segmentStartAddr(pLinker));
     else
-      segment.setVaddr(segment.getFirstSection()->addr());
+      segment.setVaddr(segment.front()->addr());
     segment.setPaddr(segment.vaddr());
 
-    const LDSection* last_sect = segment.getLastSection();
+    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())
@@ -1530,33 +1700,32 @@
   }
 }
 
-/// createGNUStackInfo - create an output GNU stack section or segment if needed
+/// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
 /// @ref gold linker: layout.cc:2608
-void GNULDBackend::createGNUStackInfo(const Output& pOutput,
-                                      const MCLDInfo& pInfo,
-                                      MCLinker& pLinker)
+void GNULDBackend::setupGNUStackInfo(Module& pModule, FragmentLinker& pLinker)
 {
   uint32_t flag = 0x0;
-  if (pInfo.options().hasStackSet()) {
+  if (config().options().hasStackSet()) {
     // 1. check the command line option (-z execstack or -z noexecstack)
-    if (pInfo.options().hasExecStack())
+    if (config().options().hasExecStack())
       flag = llvm::ELF::SHF_EXECINSTR;
-  } else {
+  }
+  else {
     // 2. check the stack info from the input objects
+    // FIXME: since we alway emit .note.GNU-stack in output now, we may be able
+    // to check this from the output .note.GNU-stack directly after section
+    // merging is done
     size_t object_count = 0, stack_note_count = 0;
-    mcld::InputTree::const_bfs_iterator input, inEnd = pInfo.inputs().bfs_end();
-    for (input=pInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
-      if ((*input)->type() == Input::Object) {
-        ++object_count;
-        const LDSection* sect = (*input)->context()->getSection(
-                                                             ".note.GNU-stack");
-        if (NULL != sect) {
-          ++stack_note_count;
-          // 2.1 found a stack note that is set as executable
-          if (0 != (llvm::ELF::SHF_EXECINSTR & sect->flag())) {
-            flag = llvm::ELF::SHF_EXECINSTR;
-            break;
-          }
+    Module::const_obj_iterator obj, objEnd = pModule.obj_end();
+    for (obj = pModule.obj_begin(); obj != objEnd; ++obj) {
+      ++object_count;
+      const LDSection* sect = (*obj)->context()->getSection(".note.GNU-stack");
+      if (NULL != sect) {
+        ++stack_note_count;
+        // 2.1 found a stack note that is set as executable
+        if (0 != (llvm::ELF::SHF_EXECINSTR & sect->flag())) {
+          flag = llvm::ELF::SHF_EXECINSTR;
+          break;
         }
       }
     }
@@ -1572,69 +1741,294 @@
         flag = llvm::ELF::SHF_EXECINSTR;
   }
 
-  if (pOutput.type() != Output::Object)
-    m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_STACK,
-                              llvm::ELF::PF_R |
-                              llvm::ELF::PF_W |
-                              getSegmentFlag(flag));
+  if (getOutputFormat()->hasStackNote()) {
+    getOutputFormat()->getStackNote().setFlag(flag);
+  }
+}
+
+/// setupRelro - setup the offset constraint of PT_RELRO
+void GNULDBackend::setupRelro(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
-    pLinker.getOrCreateOutputSectHdr(".note.GNU-stack",
-                                     LDFileFormat::Note,
-                                     llvm::ELF::SHT_PROGBITS,
-                                     flag);
+    ++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(FragmentLinker& pLinker,
+                                           Module& pModule,
+                                           Module::iterator pSectBegin,
+                                           Module::iterator pSectEnd)
+{
+  if (pSectBegin == pModule.end())
+    return;
+
+  assert(pSectEnd == pModule.end() ||
+         (pSectEnd != pModule.end() &&
+          (*pSectBegin)->index() <= (*pSectEnd)->index()));
+
+  for (ELFSegmentFactory::iterator seg = elfSegmentTable().begin(),
+         segEnd = elfSegmentTable().end(), prev = elfSegmentTable().end();
+       seg != segEnd; prev = seg, ++seg) {
+    if (llvm::ELF::PT_LOAD != (*seg).type())
+      continue;
+
+    uint64_t start_addr = 0x0;
+    ScriptOptions::AddressMap::const_iterator mapping;
+    if ((*seg).front()->kind() == LDFileFormat::Null)
+      mapping = config().scripts().addressMap().find(".text");
+    else if ((*seg).isDataSegment())
+      mapping = config().scripts().addressMap().find(".data");
+    else if ((*seg).isBssSegment())
+      mapping = config().scripts().addressMap().find(".bss");
+    else
+      mapping = config().scripts().addressMap().find((*seg).front()->name());
+
+    if (mapping != config().scripts().addressMap().end()) {
+      // check address mapping
+      start_addr = mapping.getEntry()->value();
+      const uint64_t remainder = start_addr % abiPageSize();
+      if (remainder != (*seg).front()->offset() % abiPageSize()) {
+        uint64_t padding = abiPageSize() + remainder -
+                           (*seg).front()->offset() % abiPageSize();
+        setOutputSectionOffset(pModule,
+                               pModule.begin() + (*seg).front()->index(),
+                               pModule.end(),
+                               (*seg).front()->offset() + padding);
+        if (config().options().hasRelro())
+          setupRelro(pModule);
+      }
+    }
+    else {
+      if ((*seg).front()->kind() == LDFileFormat::Null) {
+        // 1st PT_LOAD
+        start_addr = segmentStartAddr(pLinker);
+      }
+      else if ((*prev).front()->kind() == LDFileFormat::Null) {
+        // prev segment is 1st PT_LOAD
+        start_addr = segmentStartAddr(pLinker) + (*seg).front()->offset();
+      }
+      else {
+        // Others
+        start_addr = (*prev).front()->addr() + (*seg).front()->offset();
+      }
+
+      // padding
+      if (((*seg).front()->offset() & (abiPageSize() - 1)) != 0)
+        start_addr += abiPageSize();
+    }
+
+    for (ELFSegment::sect_iterator sect = (*seg).begin(),
+           sectEnd = (*seg).end(); sect != sectEnd; ++sect) {
+      if ((*sect)->index() < (*pSectBegin)->index())
+        continue;
+
+      if (LDFileFormat::Null == (*sect)->kind())
+        continue;
+
+      if (sect == pSectEnd)
+        return;
+
+      if (sect != (*seg).begin())
+        (*sect)->setAddr(start_addr + (*sect)->offset() -
+                         (*seg).front()->offset());
+      else
+        (*sect)->setAddr(start_addr);
+    }
+  }
 }
 
 /// preLayout - Backend can do any needed modification before layout
-void GNULDBackend::preLayout(const Output& pOutput,
-                             const MCLDInfo& pLDInfo,
-                             MCLinker& pLinker)
+void GNULDBackend::preLayout(Module& pModule, FragmentLinker& pLinker)
 {
   // prelayout target first
-  doPreLayout(pOutput, pLDInfo, pLinker);
+  doPreLayout(pLinker);
 
-  if (pLDInfo.options().hasEhFrameHdr()) {
+  if (config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
     // init EhFrameHdr and size the output section
-    ELFFileFormat* format = getOutputFormat(pOutput);
-    assert(NULL != getEhFrame());
-    m_pEhFrameHdr = new EhFrameHdr(*getEhFrame(),
-                                   format->getEhFrame(),
-                                   format->getEhFrameHdr());
+    ELFFileFormat* format = getOutputFormat();
+    m_pEhFrameHdr = new EhFrameHdr(format->getEhFrameHdr(),
+                                   format->getEhFrame());
     m_pEhFrameHdr->sizeOutput();
   }
+
+  // change .tbss and .tdata section symbol from Local to TLS category
+  if (NULL != f_pTDATA)
+    pModule.getSymbolTable().changeLocalToTLS(*f_pTDATA);
+
+  if (NULL != f_pTBSS)
+    pModule.getSymbolTable().changeLocalToTLS(*f_pTBSS);
+
+  // To merge input's relocation sections into output's relocation sections.
+  //
+  // If we are generating relocatables (-r), move input relocation sections
+  // to corresponding output relocation sections.
+  if (LinkerConfig::Object == config().codeGenType()) {
+    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) {
+
+        // get the output relocation LDSection with identical name.
+        LDSection* output_sect = pModule.getSection((*rs)->name());
+        if (NULL == output_sect) {
+          output_sect = LDSection::Create((*rs)->name(),
+                                          (*rs)->kind(),
+                                          (*rs)->type(),
+                                          (*rs)->flag());
+
+          output_sect->setAlign((*rs)->align());
+          pModule.getSectionTable().push_back(output_sect);
+        }
+
+        // set output relocation section link
+        const LDSection* input_link = (*rs)->getLink();
+        assert(NULL != input_link && "Illegal input relocation section.");
+
+        // get the linked output section
+        LDSection* output_link = pModule.getSection(input_link->name());
+        assert(NULL != output_link);
+
+        output_sect->setLink(output_link);
+
+        // get output relcoationData, create one if not exist
+        if (!output_sect->hasRelocData())
+          IRBuilder::CreateRelocData(*output_sect);
+
+        RelocData* out_reloc_data = output_sect->getRelocData();
+
+        // move relocations from input's to output's RelcoationData
+        RelocData::FragmentListType& out_list =
+                                             out_reloc_data->getFragmentList();
+        RelocData::FragmentListType& in_list =
+                                      (*rs)->getRelocData()->getFragmentList();
+        out_list.splice(out_list.end(), in_list);
+
+        // size output
+        if (llvm::ELF::SHT_REL == output_sect->type())
+          output_sect->setSize(out_reloc_data->size() * getRelEntrySize());
+        else if (llvm::ELF::SHT_RELA == output_sect->type())
+          output_sect->setSize(out_reloc_data->size() * getRelaEntrySize());
+        else {
+          fatal(diag::unknown_reloc_section_type) << output_sect->type()
+                                                  << output_sect->name();
+        }
+      } // end of for each relocation section
+    } // end of for each input
+  } // end of if
+
+  // set up the section flag of .note.GNU-stack section
+  setupGNUStackInfo(pModule, pLinker);
 }
 
 /// postLayout - Backend can do any needed modification after layout
-void GNULDBackend::postLayout(const Output& pOutput,
-                              const MCLDInfo& pInfo,
-                              MCLinker& pLinker)
+void GNULDBackend::postLayout(Module& pModule,
+                              FragmentLinker& pLinker)
 {
   // 1. emit program headers
-  if (pOutput.type() != Output::Object) {
+  if (LinkerConfig::Object != config().codeGenType()) {
     // 1.1 create program headers
-    createProgramHdrs(pLinker.getLDInfo().output(), pInfo);
+    createProgramHdrs(pModule, pLinker);
   }
 
-  // 1.2 create special GNU Stack note section or segment
-  createGNUStackInfo(pOutput, pInfo, pLinker);
+  if (LinkerConfig::Object != config().codeGenType()) {
+    if (config().options().hasRelro()) {
+      // 1.2 set up the offset constraint of PT_RELRO
+      setupRelro(pModule);
+    }
 
-  if (pOutput.type() != Output::Object) {
-    // 1.3 set up the attributes of program headers
-    setupProgramHdrs(pOutput, pInfo);
+    // 1.3 set up the output sections' address
+    setOutputSectionAddress(pLinker, pModule, pModule.begin(), pModule.end());
+
+    // 1.4 do relaxation
+    relax(pModule, pLinker);
+
+    // 1.5 set up the attributes of program headers
+    setupProgramHdrs(pLinker);
   }
 
   // 2. target specific post layout
-  doPostLayout(pOutput, pInfo, pLinker);
+  doPostLayout(pModule, pLinker);
 }
 
-void GNULDBackend::postProcessing(const Output& pOutput,
-                                  const MCLDInfo& pInfo,
-                                  MCLinker& pLinker)
+void GNULDBackend::postProcessing(FragmentLinker& pLinker, MemoryArea& pOutput)
 {
-  if (pInfo.options().hasEhFrameHdr()) {
+  if (config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
     // emit eh_frame_hdr
     if (bitclass() == 32)
-      m_pEhFrameHdr->emitOutput<32>(pLinker.getLDInfo().output(),
-                                    pLinker);
+      m_pEhFrameHdr->emitOutput<32>(pOutput);
   }
 }
 
@@ -1666,8 +2060,7 @@
 
 /// isDynamicSymbol
 /// @ref Google gold linker: symtab.cc:311
-bool GNULDBackend::isDynamicSymbol(const LDSymbol& pSymbol,
-                                   const Output& pOutput)
+bool GNULDBackend::isDynamicSymbol(const LDSymbol& pSymbol)
 {
   // If a local symbol is in the LDContext's symbol table, it's a real local
   // symbol. We should not add it
@@ -1676,78 +2069,123 @@
 
   // If we are building shared object, and the visibility is external, we
   // need to add it.
-  if (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type())
+  if (LinkerConfig::DynObj == config().codeGenType() ||
+      LinkerConfig::Exec == config().codeGenType()) {
     if (pSymbol.resolveInfo()->visibility() == ResolveInfo::Default ||
-        pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected)
+        pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected) {
       return true;
+    }
+  }
+  return false;
+}
+
+/// isDynamicSymbol
+/// @ref Google gold linker: symtab.cc:311
+bool GNULDBackend::isDynamicSymbol(const ResolveInfo& pResolveInfo)
+{
+  // If a local symbol is in the LDContext's symbol table, it's a real local
+  // symbol. We should not add it
+  if (pResolveInfo.binding() == ResolveInfo::Local)
+    return false;
+
+  // If we are building shared object, and the visibility is external, we
+  // need to add it.
+  if (LinkerConfig::DynObj == config().codeGenType() ||
+      LinkerConfig::Exec == config().codeGenType()) {
+    if (pResolveInfo.visibility() == ResolveInfo::Default ||
+        pResolveInfo.visibility() == ResolveInfo::Protected) {
+      return true;
+    }
+  }
   return false;
 }
 
 /// commonPageSize - the common page size of the target machine.
 /// @ref gold linker: target.h:135
-uint64_t GNULDBackend::commonPageSize(const MCLDInfo& pInfo) const
+uint64_t GNULDBackend::commonPageSize() const
 {
-  if (pInfo.options().commPageSize() > 0)
-    return std::min(pInfo.options().commPageSize(), abiPageSize(pInfo));
+  if (config().options().commPageSize() > 0)
+    return std::min(config().options().commPageSize(), abiPageSize());
   else
-    return std::min(static_cast<uint64_t>(0x1000), abiPageSize(pInfo));
+    return std::min(static_cast<uint64_t>(0x1000), abiPageSize());
 }
 
 /// abiPageSize - the abi page size of the target machine.
 /// @ref gold linker: target.h:125
-uint64_t GNULDBackend::abiPageSize(const MCLDInfo& pInfo) const
+uint64_t GNULDBackend::abiPageSize() const
 {
-  if (pInfo.options().maxPageSize() > 0)
-    return pInfo.options().maxPageSize();
+  if (config().options().maxPageSize() > 0)
+    return config().options().maxPageSize();
   else
     return static_cast<uint64_t>(0x1000);
 }
 
-/// isOutputPIC - return whether the output is position-independent
-bool GNULDBackend::isOutputPIC(const Output& pOutput,
-                               const MCLDInfo& pInfo) const
-{
-  if (Output::DynObj == pOutput.type() || pInfo.options().isPIE())
-    return true;
-  return false;
-}
-
-/// isStaticLink - return whether we're doing static link
-bool GNULDBackend::isStaticLink(const Output& pOutput,
-                                const MCLDInfo& pInfo) const
-{
-  InputTree::const_iterator it = pInfo.inputs().begin();
-  if (!isOutputPIC(pOutput, pInfo) && (*it)->attribute()->isStatic())
-    return true;
-  return false;
-}
-
 /// isSymbolPreemtible - whether the symbol can be preemted by other
 /// link unit
 /// @ref Google gold linker, symtab.h:551
-bool GNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
-                                       const MCLDInfo& pLDInfo,
-                                       const Output& pOutput) const
+bool GNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym) const
 {
   if (pSym.other() != ResolveInfo::Default)
     return false;
 
-  if (Output::DynObj != pOutput.type())
+  // This is because the codeGenType of pie is DynObj. And gold linker check
+  // the "shared" option instead.
+  if (config().options().isPIE())
     return false;
 
-  if (pLDInfo.options().Bsymbolic())
+  if (LinkerConfig::DynObj != config().codeGenType())
+    return false;
+
+  if (config().options().Bsymbolic())
+    return false;
+
+  // A local defined symbol should be non-preemptible.
+  // This issue is found when linking libstdc++ on freebsd. A R_386_GOT32
+  // relocation refers to a local defined symbol, and we should generate a
+  // relative dynamic relocation when applying the relocation.
+  if (pSym.isDefine() && pSym.binding() == ResolveInfo::Local)
     return false;
 
   return true;
 }
 
+/// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
+/// @ref Google gold linker, symtab.h:645
+bool GNULDBackend::symbolNeedsDynRel(const FragmentLinker& pLinker,
+                                     const ResolveInfo& pSym,
+                                     bool pSymHasPLT,
+                                     bool isAbsReloc) const
+{
+  // an undefined reference in the executables should be statically
+  // resolved to 0 and no need a dynamic relocation
+  if (pSym.isUndef() &&
+      !pSym.isDyn() &&
+      LinkerConfig::Exec == config().codeGenType())
+    return false;
+
+  if (pSym.isAbsolute())
+    return false;
+  if (pLinker.isOutputPIC() && isAbsReloc)
+    return true;
+  if (pSymHasPLT && ResolveInfo::Function == pSym.type())
+    return false;
+  if (!pLinker.isOutputPIC() && pSymHasPLT)
+    return false;
+  if (pSym.isDyn() || pSym.isUndef() ||
+      isSymbolPreemptible(pSym))
+    return true;
+
+  return false;
+}
+
 /// symbolNeedsPLT - return whether the symbol needs a PLT entry
 /// @ref Google gold linker, symtab.h:596
-bool GNULDBackend::symbolNeedsPLT(const ResolveInfo& pSym,
-                                  const MCLDInfo& pLDInfo,
-                                  const Output& pOutput) const
+bool GNULDBackend::symbolNeedsPLT(const FragmentLinker& pLinker,
+                                  const ResolveInfo& pSym) const
 {
-  if (pSym.isUndef() && !pSym.isDyn() && pOutput.type() != Output::DynObj)
+  if (pSym.isUndef() &&
+      !pSym.isDyn() &&
+      LinkerConfig::DynObj != config().codeGenType())
     return false;
 
   // An IndirectFunc symbol (i.e., STT_GNU_IFUNC) always needs a plt entry
@@ -1757,66 +2195,148 @@
   if (pSym.type() != ResolveInfo::Function)
     return false;
 
-  if (isStaticLink(pOutput, pLDInfo) || pLDInfo.options().isPIE())
+  if (pLinker.isStaticLink() && !pLinker.isOutputPIC())
+    return false;
+
+  if (config().options().isPIE())
     return false;
 
   return (pSym.isDyn() ||
           pSym.isUndef() ||
-          isSymbolPreemptible(pSym, pLDInfo, pOutput));
+          isSymbolPreemptible(pSym));
 }
 
-/// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
-/// @ref Google gold linker, symtab.h:645
-bool GNULDBackend::symbolNeedsDynRel(const ResolveInfo& pSym,
-                                     bool pSymHasPLT,
-                                     const MCLDInfo& pLDInfo,
-                                     const Output& pOutput,
-                                     bool isAbsReloc) const
+/// symbolHasFinalValue - return true if the symbol's value can be decided at
+/// link time
+/// @ref Google gold linker, Symbol::final_value_is_known
+bool GNULDBackend::symbolFinalValueIsKnown(const FragmentLinker& pLinker,
+                                           const ResolveInfo& pSym) const
 {
-  // an undefined reference in the executables should be statically
-  // resolved to 0 and no need a dynamic relocation
-  if (pSym.isUndef() && !pSym.isDyn() && (Output::Exec == pOutput.type()))
+  // if the output is pic code or if not executables, symbols' value may change
+  // at runtime
+  if (pLinker.isOutputPIC() || LinkerConfig::Exec != config().codeGenType())
     return false;
-  if (pSym.isAbsolute())
+
+  // if the symbol is from dynamic object, then its value is unknown
+  if (pSym.isDyn())
     return false;
-  if (isOutputPIC(pOutput, pLDInfo) && isAbsReloc)
-    return true;
-  if (pSymHasPLT && ResolveInfo::Function == pSym.type())
-    return false;
-  if (!isOutputPIC(pOutput, pLDInfo) && pSymHasPLT)
-    return false;
-  if (pSym.isDyn() || pSym.isUndef() ||
-      isSymbolPreemptible(pSym, pLDInfo, pOutput))
+
+  // if the symbol is not in dynamic object and is not undefined, then its value
+  // is known
+  if (!pSym.isUndef())
     return true;
 
-  return false;
+  // if the symbol is undefined and not in dynamic objects, for example, a weak
+  // undefined symbol, then whether the symbol's final value can be known
+  // depends on whrther we're doing static link
+  return pLinker.isStaticLink();
 }
 
 /// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
-bool GNULDBackend::symbolNeedsCopyReloc(const Layout& pLayout,
+bool GNULDBackend::symbolNeedsCopyReloc(const FragmentLinker& pLinker,
                                         const Relocation& pReloc,
-                                        const ResolveInfo& pSym,
-                                        const MCLDInfo& pLDInfo,
-                                        const Output& pOutput) const
+                                        const ResolveInfo& pSym) const
 {
   // only the reference from dynamic executable to non-function symbol in
   // the dynamic objects may need copy relocation
-  if (isOutputPIC(pOutput, pLDInfo) ||
+  if (pLinker.isOutputPIC() ||
       !pSym.isDyn() ||
       pSym.type() == ResolveInfo::Function ||
       pSym.size() == 0)
     return false;
 
   // check if the option -z nocopyreloc is given
-  if (pLDInfo.options().hasNoCopyReloc())
+  if (config().options().hasNoCopyReloc())
     return false;
 
   // TODO: Is this check necessary?
   // if relocation target place is readonly, a copy relocation is needed
-  if ((pLayout.getOutputLDSection(*pReloc.targetRef().frag())->flag() &
-      llvm::ELF::SHF_WRITE) == 0)
+  uint32_t flag = pReloc.targetRef().frag()->getParent()->getSection().flag();
+  if (0 == (flag & llvm::ELF::SHF_WRITE))
     return true;
 
   return false;
 }
 
+LDSymbol& GNULDBackend::getTDATASymbol()
+{
+  assert(NULL != f_pTDATA);
+  return *f_pTDATA;
+}
+
+const LDSymbol& GNULDBackend::getTDATASymbol() const
+{
+  assert(NULL != f_pTDATA);
+  return *f_pTDATA;
+}
+
+LDSymbol& GNULDBackend::getTBSSSymbol()
+{
+  assert(NULL != f_pTBSS);
+  return *f_pTBSS;
+}
+
+const LDSymbol& GNULDBackend::getTBSSSymbol() const
+{
+  assert(NULL != f_pTBSS);
+  return *f_pTBSS;
+}
+
+void GNULDBackend::checkAndSetHasTextRel(const LDSection& pSection)
+{
+  if (m_bHasTextRel)
+    return;
+
+  // if the target section of the dynamic relocation is ALLOCATE but is not
+  // writable, than we should set DF_TEXTREL
+  const uint32_t flag = pSection.flag();
+  if (0 == (flag & llvm::ELF::SHF_WRITE) && (flag & llvm::ELF::SHF_ALLOC))
+    m_bHasTextRel = true;
+
+  return;
+}
+
+/// initBRIslandFactory - initialize the branch island factory for relaxation
+bool GNULDBackend::initBRIslandFactory()
+{
+  if (NULL == m_pBRIslandFactory) {
+    m_pBRIslandFactory = new BranchIslandFactory(maxBranchOffset());
+  }
+  return true;
+}
+
+/// initStubFactory - initialize the stub factory for relaxation
+bool GNULDBackend::initStubFactory()
+{
+  if (NULL == m_pStubFactory) {
+    m_pStubFactory = new StubFactory();
+  }
+  return true;
+}
+
+bool GNULDBackend::relax(Module& pModule, FragmentLinker& pLinker)
+{
+  if (!mayRelax())
+    return true;
+
+  bool finished = true;
+  do {
+    if (doRelax(pModule, pLinker, 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(pLinker, pModule, pModule.begin(), pModule.end());
+    }
+  } while (!finished);
+
+  return true;
+}
+
diff --git a/lib/Target/GOT.cpp b/lib/Target/GOT.cpp
index f9e7b91..32afdff 100644
--- a/lib/Target/GOT.cpp
+++ b/lib/Target/GOT.cpp
@@ -6,8 +6,12 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <llvm/Support/Casting.h>
 
+#include <mcld/LD/LDSection.h>
 #include <mcld/Target/GOT.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/IRBuilder.h>
 
 #include <cstring>
 #include <cstdlib>
@@ -15,26 +19,26 @@
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// GOTEntry
+// GOT::Entry
 //===----------------------------------------------------------------------===//
-GOTEntry::GOTEntry(uint64_t pContent, size_t pEntrySize, SectionData* pParent)
+GOT::Entry::Entry(uint64_t pContent, size_t pEntrySize, SectionData* pParent)
   : TargetFragment(Fragment::Target, pParent),
-    f_Content(pContent), m_EntrySize(pEntrySize) {
+    f_Content(pContent),
+    m_EntrySize(pEntrySize) {
 }
 
-GOTEntry::~GOTEntry()
+GOT::Entry::~Entry()
 {
 }
 
 //===----------------------------------------------------------------------===//
 // GOT
 //===----------------------------------------------------------------------===//
-GOT::GOT(LDSection& pSection,
-         SectionData& pSectionData,
-         size_t pEntrySize)
+GOT::GOT(LDSection& pSection, size_t pEntrySize)
   : m_Section(pSection),
-    m_SectionData(pSectionData),
-    f_EntrySize(pEntrySize) {
+    f_EntrySize(pEntrySize),
+    m_pLast(NULL) {
+  m_SectionData = IRBuilder::CreateSectionData(pSection);
 }
 
 GOT::~GOT()
@@ -46,3 +50,34 @@
   return f_EntrySize;
 }
 
+void GOT::reserve(size_t pNum)
+{
+  for (size_t i = 0; i < pNum; i++) {
+    new Entry(0, f_EntrySize, m_SectionData);
+  }
+}
+
+GOT::Entry* GOT::consume()
+{
+  if (NULL == m_pLast) {
+    assert(!empty() && "Consume empty GOT entry!");
+    m_pLast = llvm::cast<Entry>(&m_SectionData->front());
+    return m_pLast;
+  }
+
+  m_pLast = llvm::cast<Entry>(m_pLast->getNextNode());
+  return m_pLast;
+}
+
+void GOT::finalizeSectionSize()
+{
+  m_Section.setSize(m_SectionData->size() * f_EntrySize);
+
+  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();
+  }
+}
+
diff --git a/lib/Target/Mips/Android.mk b/lib/Target/Mips/Android.mk
index 4707c4b..dd3905d 100644
--- a/lib/Target/Mips/Android.mk
+++ b/lib/Target/Mips/Android.mk
@@ -3,11 +3,12 @@
 mcld_mips_target_SRC_FILES := \
   MipsDiagnostic.cpp  \
   MipsELFDynamic.cpp  \
-  MipsELFSectLinker.cpp \
+  MipsELFMCLinker.cpp  \
+  MipsEmulation.cpp \
   MipsGOT.cpp \
   MipsLDBackend.cpp \
+  MipsMCLinker.cpp \
   MipsRelocationFactory.cpp \
-  MipsSectLinker.cpp  \
   MipsTargetMachine.cpp
 
 # For the host
diff --git a/lib/Target/Mips/MipsDiagnostic.cpp b/lib/Target/Mips/MipsDiagnostic.cpp
index f6b6339..2d5b7d9 100644
--- a/lib/Target/Mips/MipsDiagnostic.cpp
+++ b/lib/Target/Mips/MipsDiagnostic.cpp
@@ -28,7 +28,7 @@
 
 //==========================
 // InitializeMipsDiagnostic
-extern "C" void LLVMInitializeMipsDiagnosticLineInfo() {
+extern "C" void MCLDInitializeMipsDiagnosticLineInfo() {
   // Register the linker frontend
   mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheMipselTarget, createMipsDiagLineInfo);
 }
diff --git a/lib/Target/Mips/MipsELFDynamic.cpp b/lib/Target/Mips/MipsELFDynamic.cpp
index cd692ac..fd779f3 100644
--- a/lib/Target/Mips/MipsELFDynamic.cpp
+++ b/lib/Target/Mips/MipsELFDynamic.cpp
@@ -21,7 +21,7 @@
   MIPS_BASE_ADDRESS = 0x70000006,
   MIPS_LOCAL_GOTNO  = 0x7000000a,
   MIPS_SYMTABNO     = 0x70000011,
-  MIPS_GOTSYM       = 0x70000013,
+  MIPS_GOTSYM       = 0x70000013
 };
 
 MipsELFDynamic::MipsELFDynamic(const MipsGNULDBackend& pParent)
diff --git a/lib/Target/Mips/MipsELFMCLinker.cpp b/lib/Target/Mips/MipsELFMCLinker.cpp
new file mode 100644
index 0000000..3964ee8
--- /dev/null
+++ b/lib/Target/Mips/MipsELFMCLinker.cpp
@@ -0,0 +1,23 @@
+//===- MipsELFMCLinker.cpp ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "MipsELFMCLinker.h"
+#include <mcld/LinkerConfig.h>
+
+using namespace mcld;
+
+MipsELFMCLinker::MipsELFMCLinker(LinkerConfig& pConfig,
+                                 mcld::Module& pModule,
+                                 MemoryArea& pOutput)
+  : ELFMCLinker(pConfig, pModule, pOutput) {
+}
+
+MipsELFMCLinker::~MipsELFMCLinker()
+{
+}
+
diff --git a/lib/Target/Mips/MipsELFMCLinker.h b/lib/Target/Mips/MipsELFMCLinker.h
new file mode 100644
index 0000000..2c240ad
--- /dev/null
+++ b/lib/Target/Mips/MipsELFMCLinker.h
@@ -0,0 +1,37 @@
+//===- MipsELFMCLinker.h --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MIPS_ELF_SECTION_LINKER_H
+#define MIPS_ELF_SECTION_LINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/ELFMCLinker.h>
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+
+/** \class MipsELFMCLinker
+ *  \brief MipsELFMCLinker sets up the environment for linking.
+ */
+class MipsELFMCLinker : public ELFMCLinker
+{
+public:
+  MipsELFMCLinker(LinkerConfig& pConfig,
+                  mcld::Module& pModule,
+                  MemoryArea& pOutput);
+
+  ~MipsELFMCLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Mips/MipsELFSectLinker.cpp b/lib/Target/Mips/MipsELFSectLinker.cpp
deleted file mode 100644
index dedf505..0000000
--- a/lib/Target/Mips/MipsELFSectLinker.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- MipsELFSectLinker.cpp ----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "MipsELFSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-MipsELFSectLinker::MipsELFSectLinker(SectLinkerOption &pOption,
-                                     TargetLDBackend &pLDBackend)
-  : SectLinker(pOption,
-               pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attibutes
-  info.attrFactory().constraint().enableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().setWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-}
-
-MipsELFSectLinker::~MipsELFSectLinker()
-{
-}
-
diff --git a/lib/Target/Mips/MipsELFSectLinker.h b/lib/Target/Mips/MipsELFSectLinker.h
deleted file mode 100644
index 1aacfef..0000000
--- a/lib/Target/Mips/MipsELFSectLinker.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- MipsELFSectLinker.h ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MIPS_ELF_SECTION_LINKER_H
-#define MIPS_ELF_SECTION_LINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/CodeGen/SectLinker.h>
-
-namespace mcld
-{
-
-/** \class MipsELFSectLinker
- *  \brief MipsELFSectLinker sets up the environment for linking.
- */
-class MipsELFSectLinker : public SectLinker
-{
-public:
-  MipsELFSectLinker(SectLinkerOption &pOption,
-                    mcld::TargetLDBackend &pLDBackend);
-
-  ~MipsELFSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/Mips/MipsEmulation.cpp b/lib/Target/Mips/MipsEmulation.cpp
new file mode 100644
index 0000000..74f2637
--- /dev/null
+++ b/lib/Target/Mips/MipsEmulation.cpp
@@ -0,0 +1,60 @@
+//===- MipsEmulation.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Mips.h"
+#include <mcld/LinkerConfig.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/Support/TargetRegistry.h>
+
+namespace mcld {
+
+static bool MCLDEmulateMipsELF(LinkerConfig& pConfig)
+{
+  if (!MCLDEmulateELF(pConfig))
+    return false;
+
+  // set up target-dependent constraints of attributes
+  pConfig.attribute().constraint().enableWholeArchive();
+  pConfig.attribute().constraint().enableAsNeeded();
+  pConfig.attribute().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  pConfig.attribute().predefined().unsetWholeArchive();
+  pConfig.attribute().predefined().unsetAsNeeded();
+  pConfig.attribute().predefined().setDynamic();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// emulateMipsLD - the help function to emulate Mips ld
+//===----------------------------------------------------------------------===//
+bool emulateMipsLD(const std::string& pTriple, LinkerConfig& pConfig)
+{
+  llvm::Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+    return false;
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+    return false;
+  }
+
+  return MCLDEmulateMipsELF(pConfig);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// MipsEmulation
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeMipsEmulation() {
+  // Register the emulation
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheMipselTarget, mcld::emulateMipsLD);
+}
+
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
index 42ef972..b4eb1cd 100644
--- a/lib/Target/Mips/MipsGOT.cpp
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -24,26 +24,19 @@
 
 //===----------------------------------------------------------------------===//
 // MipsGOT
-MipsGOT::MipsGOT(LDSection& pSection, SectionData& pSectionData)
-  : GOT(pSection, pSectionData, MipsGOTEntrySize),
+//===----------------------------------------------------------------------===//
+MipsGOT::MipsGOT(LDSection& pSection)
+  : GOT(pSection, MipsGOTEntrySize),
     m_pLocalNum(0)
 {
   // Create GOT0 entries.
-  for (size_t i = 0; i < MipsGOT0Num; ++i) {
-    GOTEntry* entry =
-      new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
-
-    if (NULL == entry)
-      fatal(diag::fail_allocate_memory_got);
-
-    m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
-  }
+  reserve(MipsGOT0Num);
 
   // Skip GOT0 entries.
-  iterator it = m_SectionData.begin();
+  iterator it = m_SectionData->begin();
 
   for (size_t i = 1; i < MipsGOT0Num; ++i) {
-    assert((it != m_SectionData.end()) &&
+    assert((it != m_SectionData->end()) &&
            "Generation of GOT0 entries is incomplete!");
 
     ++it;
@@ -54,24 +47,9 @@
   m_pLocalNum = MipsGOT0Num;
 }
 
-MipsGOT::iterator MipsGOT::begin()
+bool MipsGOT::hasGOT1() const
 {
-  return m_SectionData.getFragmentList().begin();
-}
-
-MipsGOT::iterator MipsGOT::end()
-{
-  return m_SectionData.getFragmentList().end();
-}
-
-MipsGOT::const_iterator MipsGOT::begin() const
-{
-  return m_SectionData.getFragmentList().begin();
-}
-
-MipsGOT::const_iterator MipsGOT::end() const
-{
-  return m_SectionData.getFragmentList().end();
+  return (m_SectionData->size() > MipsGOT0Num);
 }
 
 uint64_t MipsGOT::emit(MemoryRegion& pRegion)
@@ -83,29 +61,16 @@
   uint64_t result = 0;
   for (iterator it = begin(), ie = end();
        it != ie; ++it, ++buffer) {
-    GOTEntry* got = &(llvm::cast<GOTEntry>((*it)));
+    GOT::Entry* got = &(llvm::cast<GOT::Entry>((*it)));
     *buffer = static_cast<uint32_t>(got->getContent());
     result += entry_size;
   }
   return result;
 }
 
-void MipsGOT::reserveEntry(size_t pNum)
-{
-  for (size_t i = 0; i < pNum; ++i) {
-    GOTEntry* entry =
-      new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
-
-    if (NULL == entry)
-      fatal(diag::fail_allocate_memory_got);
-
-    m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
-  }
-}
-
 void MipsGOT::reserveLocalEntry()
 {
-  reserveEntry(1);
+  reserve(1);
   ++m_pLocalNum;
 
   // Move global entries iterator forward.
@@ -115,42 +80,30 @@
 
 void MipsGOT::reserveGlobalEntry()
 {
-  reserveEntry(1);
+  reserve(1);
 }
 
-GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
+GOT::Entry* MipsGOT::consumeLocal()
 {
-  if (isLocal(&pInfo) && pInfo.type() == ResolveInfo::Section) {
-    pExist = false;
-    iterator& it = m_LocalGOTIterator;
-    ++it;
-    assert(it != m_SectionData.getFragmentList().end() &&
-           "The number of GOT Entries and ResolveInfo doesn't match");
-    GOTEntry* entry = llvm::cast<GOTEntry>(&(*it));
-    return entry;
-  }
+  iterator& it = m_LocalGOTIterator;
+  ++it;
+  assert(it != m_SectionData->getFragmentList().end() &&
+         "The number of GOT Entries and ResolveInfo doesn't match");
+  return llvm::cast<GOT::Entry>(&(*it));
+}
 
-  GOTEntry*& entry = m_GeneralGOTMap[&pInfo];
-
-  pExist = NULL != entry;
-
-  if (!pExist) {
-    iterator& it = isLocal(&pInfo)  ? m_LocalGOTIterator : m_GlobalGOTIterator;
-
-    ++it;
-
-    assert(it != m_SectionData.getFragmentList().end() &&
-           "The number of GOT Entries and ResolveInfo doesn't match");
-
-    entry = llvm::cast<GOTEntry>(&(*it));
-  }
-
-  return entry;
+GOT::Entry* MipsGOT::consumeGlobal()
+{
+  iterator& it = m_GlobalGOTIterator;
+  ++it;
+  assert(it != m_SectionData->getFragmentList().end() &&
+         "The number of GOT Entries and ResolveInfo doesn't match");
+  return llvm::cast<GOT::Entry>(&(*it));
 }
 
 size_t MipsGOT::getTotalNum() const
 {
-  return m_SectionData.getFragmentList().size();
+  return m_SectionData->getFragmentList().size();
 }
 
 size_t MipsGOT::getLocalNum() const
diff --git a/lib/Target/Mips/MipsGOT.h b/lib/Target/Mips/MipsGOT.h
index 23a3ded..6ec4926 100644
--- a/lib/Target/Mips/MipsGOT.h
+++ b/lib/Target/Mips/MipsGOT.h
@@ -15,7 +15,6 @@
 #include <llvm/ADT/DenseMap.h>
 
 #include <mcld/Target/GOT.h>
-#include <mcld/LD/SectionData.h>
 
 namespace mcld
 {
@@ -27,33 +26,20 @@
  */
 class MipsGOT : public GOT
 {
-private:
-  typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
-  typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolTypeMapType;
-
 public:
-  typedef SectionData::iterator iterator;
-  typedef SectionData::const_iterator const_iterator;
-
-public:
-  MipsGOT(LDSection& pSection, SectionData& pSectionData);
-
-  iterator begin();
-  iterator end();
-
-  const_iterator begin() const;
-  const_iterator end() const;
+  MipsGOT(LDSection& pSection);
 
   uint64_t emit(MemoryRegion& pRegion);
 
   void reserveLocalEntry();
   void reserveGlobalEntry();
 
-  GOTEntry* getEntry(const ResolveInfo& pInfo, bool& pExist);
-
   size_t getTotalNum() const;
   size_t getLocalNum() const;
 
+  GOT::Entry* consumeLocal();
+  GOT::Entry* consumeGlobal();
+
   void setLocal(const ResolveInfo* pInfo) {
     m_GOTTypeMap[pInfo] = false;
   }
@@ -70,17 +56,18 @@
     return m_GOTTypeMap[pInfo] == true;
   }
 
+  /// hasGOT1 - return if this got section has any GOT1 entry
+  bool hasGOT1() const;
+
 private:
-  SymbolIndexMapType m_GeneralGOTMap; // Map ResolveInfo* to GOTEntry *.
+  typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolTypeMapType;
+
+private:
   SymbolTypeMapType m_GOTTypeMap;
 
   iterator m_LocalGOTIterator;  // last local GOT entries
   iterator m_GlobalGOTIterator; // last global GOT entries
   size_t m_pLocalNum;
-
-private:
-  // Use reserveLocalEntry()/reserveGlobalEntry() instead of this routine.
-  void reserveEntry(size_t pNum = 1);
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
index e8b68ea..da2399e 100644
--- a/lib/Target/Mips/MipsLDBackend.cpp
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -6,7 +6,6 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include "Mips.h"
 #include "MipsELFDynamic.h"
 #include "MipsLDBackend.h"
@@ -15,14 +14,18 @@
 #include <llvm/ADT/Triple.h>
 #include <llvm/Support/ELF.h>
 
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/SectionMap.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/Target/OutputRelocSection.h>
+#include <mcld/Object/ObjectBuilder.h>
 
 enum {
   // The original o32 abi.
@@ -35,10 +38,14 @@
   E_MIPS_ABI_EABI64 = 0x00004000
 };
 
-namespace mcld {
+using namespace mcld;
 
-MipsGNULDBackend::MipsGNULDBackend()
-  : m_pRelocFactory(NULL),
+//===----------------------------------------------------------------------===//
+// MipsGNULDBackend
+//===----------------------------------------------------------------------===//
+MipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig)
+  : GNULDBackend(pConfig),
+    m_pRelocFactory(NULL),
     m_pGOT(NULL),
     m_pRelDyn(NULL),
     m_pDynamic(NULL),
@@ -49,32 +56,34 @@
 
 MipsGNULDBackend::~MipsGNULDBackend()
 {
-  if (NULL != m_pRelocFactory)
-    delete m_pRelocFactory;
-  if (NULL != m_pGOT)
-    delete m_pGOT;
-  if (NULL != m_pRelDyn)
-    delete m_pRelDyn;
-  if (NULL != m_pDynamic)
-    delete m_pDynamic;
+  delete m_pRelocFactory;
+  delete m_pGOT;
+  delete m_pRelDyn;
+  delete m_pDynamic;
 }
 
-bool MipsGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
+void MipsGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
 {
-  // Nothing to do because we do not support
-  // any MIPS specific sections now.
-  return true;
+  if (LinkerConfig::Object != config().codeGenType()) {
+    ELFFileFormat* file_format = getOutputFormat();
+
+    // initialize .got
+    LDSection& got = file_format->getGOT();
+    m_pGOT = new MipsGOT(got);
+
+    // initialize .rel.dyn
+    LDSection& reldyn = file_format->getRelDyn();
+    m_pRelDyn = new OutputRelocSection(pModule,
+                                       reldyn,
+                                       getRelEntrySize());
+  }
 }
 
-void MipsGNULDBackend::initTargetSections(MCLinker& pLinker)
-{
-}
-
-void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+void MipsGNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
-  m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
+  m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
                    "_GLOBAL_OFFSET_TABLE_",
                    false,
                    ResolveInfo::Object,
@@ -82,10 +91,10 @@
                    ResolveInfo::Local,
                    0x0,  // size
                    0x0,  // value
-                   NULL, // FragRef
+                   FragmentRef::Null(), // FragRef
                    ResolveInfo::Hidden);
 
-  m_pGpDispSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
+  m_pGpDispSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
                    "_gp_disp",
                    false,
                    ResolveInfo::Section,
@@ -93,7 +102,7 @@
                    ResolveInfo::Absolute,
                    0x0,  // size
                    0x0,  // value
-                   NULL, // FragRef
+                   FragmentRef::Null(), // FragRef
                    ResolveInfo::Default);
 
   if (NULL != m_pGpDispSymbol) {
@@ -101,11 +110,11 @@
   }
 }
 
-bool MipsGNULDBackend::initRelocFactory(const MCLinker& pLinker)
+bool MipsGNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
 {
   if (NULL == m_pRelocFactory) {
     m_pRelocFactory = new MipsRelocationFactory(1024, *this);
-    m_pRelocFactory->setLayout(pLinker.getLayout());
+    m_pRelocFactory->setFragmentLinker(pLinker);
   }
   return true;
 }
@@ -117,44 +126,43 @@
 }
 
 void MipsGNULDBackend::scanRelocation(Relocation& pReloc,
-                                      const LDSymbol& pInputSym,
-                                      MCLinker& pLinker,
-                                      const MCLDInfo& pLDInfo,
-                                      const Output& pOutput,
+                                      FragmentLinker& pLinker,
+                                      Module& pModule,
                                       const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
 
-  assert(NULL != pSection.getLink());
-  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
-    if (rsym->isLocal()) {
-      updateAddend(pReloc, pInputSym, pLinker.getLayout());
-    }
-    return;
-  }
-
-  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies
-  // that a .got section is needed.
-  if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
-    if (rsym == m_pGOTSymbol->resolveInfo()) {
-      createGOT(pLinker, pOutput);
-    }
-  }
-
   // Skip relocation against _gp_disp
-  if (strcmp("_gp_disp", pInputSym.name()) == 0)
+  if (NULL != m_pGpDispSymbol) {
+    if (pReloc.symInfo() == m_pGpDispSymbol->resolveInfo())
+      return;
+  }
+
+  pReloc.updateAddend();
+
+  if (0 == (pSection.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() || !isDynamicSymbol(pInputSym, pOutput) ||
+  if ((rsym->isLocal() || !isDynamicSymbol(*rsym) ||
       !rsym->isDyn()) && !rsym->isUndef())
-    scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+    scanLocalReloc(pReloc, pLinker);
   else
-    scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+    scanGlobalReloc(pReloc, pLinker);
+
+  // check if we shoule issue undefined reference for the relocation target
+  // symbol
+  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+    fatal(diag::undefined_reference) << rsym->name();
+
+  if ((rsym->reserved() & ReserveRel) != 0x0) {
+    // set hasTextRelSection if needed
+    checkAndSetHasTextRel(pSection);
+  }
 }
 
 uint32_t MipsGNULDBackend::machine() const
@@ -199,27 +207,33 @@
   return 0x80000;
 }
 
-uint64_t MipsGNULDBackend::abiPageSize(const MCLDInfo& pInfo) const
+uint64_t MipsGNULDBackend::abiPageSize() const
 {
-  if (pInfo.options().maxPageSize() > 0)
-    return pInfo.options().maxPageSize();
+  if (config().options().maxPageSize() > 0)
+    return config().options().maxPageSize();
   else
     return static_cast<uint64_t>(0x10000);
 }
 
-void MipsGNULDBackend::doPreLayout(const Output& pOutput,
-                                   const MCLDInfo& pInfo,
-                                   MCLinker& pLinker)
+void MipsGNULDBackend::doPreLayout(FragmentLinker& pLinker)
 {
+  // set .got size
   // when building shared object, the .got section is must.
-  if (pOutput.type() == Output::DynObj && NULL == m_pGOT) {
-      createGOT(pLinker, pOutput);
+  if (LinkerConfig::Object != config().codeGenType()) {
+    if (LinkerConfig::DynObj == config().codeGenType() ||
+        m_pGOT->hasGOT1() ||
+        NULL != m_pGOTSymbol) {
+      m_pGOT->finalizeSectionSize();
+      defineGOTSymbol(pLinker);
+    }
+
+    // set .rel.dyn size
+    if (!m_pRelDyn->empty())
+      m_pRelDyn->finalizeSectionSize();
   }
 }
-
-void MipsGNULDBackend::doPostLayout(const Output& pOutput,
-                                    const MCLDInfo& pInfo,
-                                    MCLinker& pLinker)
+void MipsGNULDBackend::doPostLayout(Module& pModule,
+                                    FragmentLinker& pLinker)
 {
 }
 
@@ -241,15 +255,12 @@
   return *m_pDynamic;
 }
 
-uint64_t MipsGNULDBackend::emitSectionData(const Output& pOutput,
-                                           const LDSection& pSection,
-                                           const MCLDInfo& pInfo,
-                                           const Layout& pLayout,
+uint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection,
                                            MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  const ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat();
 
   if (&pSection == &(file_format->getGOT())) {
     assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
@@ -269,58 +280,212 @@
                    m_GlobalGOTSyms.end(), &pSymbol) != m_GlobalGOTSyms.end();
 }
 
-/// emitDynamicSymbol - emit dynamic symbol.
-void MipsGNULDBackend::emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
-                                         Output& pOutput,
-                                         LDSymbol& pSymbol,
-                                         const Layout& pLayout,
-                                         char* strtab,
-                                         size_t strtabsize,
-                                         size_t symtabIdx)
+/// sizeNamePools - compute the size of regular name pools
+/// In ELF executable files, regular name pools are .symtab, .strtab,
+/// .dynsym, .dynstr, .hash and .shstrtab.
+void
+MipsGNULDBackend::sizeNamePools(const Module& pModule, bool pIsStaticLink)
 {
-  // maintain output's symbol and index map
-  bool sym_exist = false;
-  HashTableType::entry_type* entry = 0;
-  entry = m_pSymIndexMap->insert(&pSymbol, sym_exist);
-  entry->setValue(symtabIdx);
+  // number of entries in symbol tables starts from 1 to hold the special entry
+  // at index 0 (STN_UNDEF). See ELF Spec Book I, p1-21.
+  size_t symtab = 1;
+  size_t dynsym = pIsStaticLink ? 0 : 1;
 
-  // FIXME: check the endian between host and target
-  // write out symbol
-  sym32.st_name  = strtabsize;
-  sym32.st_value = pSymbol.value();
-  sym32.st_size  = getSymbolSize(pSymbol);
-  sym32.st_info  = getSymbolInfo(pSymbol);
-  sym32.st_other = pSymbol.visibility();
-  sym32.st_shndx = getSymbolShndx(pSymbol, pLayout);
-  // write out string
-  strcpy((strtab + strtabsize), pSymbol.name());
+  // size of string tables starts from 1 to hold the null character in their
+  // first byte
+  size_t strtab = 1;
+  size_t dynstr = pIsStaticLink ? 0 : 1;
+  size_t shstrtab = 1;
+  size_t hash   = 0;
+
+  /// compute the size of .symtab, .dynsym and .strtab
+  /// @{
+  Module::const_sym_iterator symbol;
+  const Module::SymbolTable& symbols = pModule.getSymbolTable();
+  size_t str_size = 0;
+  // compute the size of symbols in Local and File category
+  Module::const_sym_iterator symEnd = symbols.localEnd();
+  for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
+    str_size = (*symbol)->nameSize() + 1;
+    if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
+      ++dynsym;
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+        dynstr += str_size;
+    }
+    ++symtab;
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+      strtab += str_size;
+  }
+  // compute the size of symbols in TLS category
+  symEnd = symbols.tlsEnd();
+  for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+    str_size = (*symbol)->nameSize() + 1;
+    if (!pIsStaticLink) {
+      ++dynsym;
+      if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+        dynstr += str_size;
+    }
+    ++symtab;
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+      strtab += str_size;
+  }
+  // compute the size of the reset of symbols
+  symEnd = pModule.sym_end();
+  for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
+    str_size = (*symbol)->nameSize() + 1;
+    if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
+      ++dynsym;
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+        dynstr += str_size;
+    }
+    ++symtab;
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+      strtab += str_size;
+  }
+
+  ELFFileFormat* file_format = getOutputFormat();
+
+  switch(config().codeGenType()) {
+    // compute size of .dynstr and .hash
+    case LinkerConfig::DynObj: {
+      // soname
+      if (!pIsStaticLink)
+        dynstr += pModule.name().size() + 1;
+    }
+    /** fall through **/
+    case LinkerConfig::Exec: {
+      // add DT_NEED strings into .dynstr and .dynamic
+      // Rules:
+      //   1. ignore --no-add-needed
+      //   2. force count in --no-as-needed
+      //   3. judge --as-needed
+      if (!pIsStaticLink) {
+        Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+        for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
+          // --add-needed
+          if ((*lib)->attribute()->isAddNeeded()) {
+            // --no-as-needed
+            if (!(*lib)->attribute()->isAsNeeded()) {
+              dynstr += (*lib)->name().size() + 1;
+              dynamic().reserveNeedEntry();
+            }
+            // --as-needed
+            else if ((*lib)->isNeeded()) {
+              dynstr += (*lib)->name().size() + 1;
+              dynamic().reserveNeedEntry();
+            }
+          }
+        }
+
+        // compute .hash
+        // Both Elf32_Word and Elf64_Word are 4 bytes
+        hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
+               sizeof(llvm::ELF::Elf32_Word);
+      }
+
+      // set size
+      if (32 == bitclass())
+        file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf32_Sym));
+      else
+        file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf64_Sym));
+      file_format->getDynStrTab().setSize(dynstr);
+      file_format->getHashTab().setSize(hash);
+
+    }
+    /* fall through */
+    case LinkerConfig::Object: {
+      if (32 == bitclass())
+        file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf32_Sym));
+      else
+        file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf64_Sym));
+      file_format->getStrTab().setSize(strtab);
+      break;
+    }
+    default: {
+      fatal(diag::fatal_illegal_codegen_type) << pModule.name();
+      break;
+    }
+  } // end of switch
+  /// @}
+
+  /// reserve fixed entries in the .dynamic section.
+  /// @{
+  if (LinkerConfig::DynObj == config().codeGenType() ||
+      LinkerConfig::Exec == config().codeGenType()) {
+    // Because some entries in .dynamic section need information of .dynsym,
+    // .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
+    // entries until we get the size of the sections mentioned above
+    dynamic().reserveEntries(config(), *file_format);
+    file_format->getDynamic().setSize(dynamic().numOfBytes());
+  }
+  /// @}
+
+  /// compute the size of .shstrtab section.
+  /// @{
+  Module::const_iterator sect, sectEnd = pModule.end();
+  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+    // StackNote sections will always be in output!
+    if (0 != (*sect)->size() || LDFileFormat::StackNote == (*sect)->kind()) {
+      shstrtab += ((*sect)->name().size() + 1);
+    }
+  }
+  shstrtab += (strlen(".shstrtab") + 1);
+  file_format->getShStrTab().setSize(shstrtab);
+  /// @}
+}
+
+/// emitSymbol32 - emit an ELF32 symbol
+void MipsGNULDBackend::emitSymbol32(llvm::ELF::Elf32_Sym& pSym,
+                                    LDSymbol& pSymbol,
+                                    char* pStrtab,
+                                    size_t pStrtabsize,
+                                    size_t pSymtabIdx)
+{
+   // FIXME: check the endian between host and target
+   // write out symbol
+    if (ResolveInfo::Section != pSymbol.type() ||
+          &pSymbol == m_pGpDispSymbol) {
+     pSym.st_name  = pStrtabsize;
+     strcpy((pStrtab + pStrtabsize), pSymbol.name());
+   }
+   else {
+     pSym.st_name  = 0;
+   }
+   pSym.st_value = pSymbol.value();
+   pSym.st_size  = getSymbolSize(pSymbol);
+   pSym.st_info  = getSymbolInfo(pSymbol);
+   pSym.st_other = pSymbol.visibility();
+   pSym.st_shndx = getSymbolShndx(pSymbol);
 }
 
 /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
 ///
 /// the size of these tables should be computed before layout
 /// layout should computes the start offset of these tables
-void MipsGNULDBackend::emitDynNamePools(Output& pOutput,
-                                        SymbolCategory& pSymbols,
-                                        const Layout& pLayout,
-                                        const MCLDInfo& pLDInfo)
+void MipsGNULDBackend::emitDynNamePools(const Module& pModule,
+                                        MemoryArea& pOutput)
 {
-  assert(pOutput.hasMemArea());
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  ELFFileFormat* file_format = getOutputFormat();
+  if (!file_format->hasDynSymTab() ||
+      !file_format->hasDynStrTab() ||
+      !file_format->hasHashTab()   ||
+      !file_format->hasDynamic())
+    return;
 
   LDSection& symtab_sect = file_format->getDynSymTab();
   LDSection& strtab_sect = file_format->getDynStrTab();
   LDSection& hash_sect   = file_format->getHashTab();
   LDSection& dyn_sect    = file_format->getDynamic();
 
-  MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
-                                                           symtab_sect.size());
-  MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
-                                                           strtab_sect.size());
-  MemoryRegion* hash_region = pOutput.memArea()->request(hash_sect.offset(),
-                                                         hash_sect.size());
-  MemoryRegion* dyn_region = pOutput.memArea()->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* hash_region   = pOutput.request(hash_sect.offset(),
+                                                hash_sect.size());
+  MemoryRegion* dyn_region    = pOutput.request(dyn_sect.offset(),
+                                                dyn_sect.size());
+
   // set up symtab_region
   llvm::ELF::Elf32_Sym* symtab32 = NULL;
   symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
@@ -347,20 +512,67 @@
   size_t strtabsize = 1;
 
   // emit of .dynsym, and .dynstr except GOT entries
-  for (SymbolCategory::iterator symbol = pSymbols.begin(),
-       sym_end = pSymbols.end(); symbol != sym_end; ++symbol) {
-    if (!isDynamicSymbol(**symbol, pOutput))
+  Module::const_sym_iterator symbol;
+  const Module::SymbolTable& symbols = pModule.getSymbolTable();
+  // emit symbol in File and Local category if it's dynamic symbol
+  Module::const_sym_iterator symEnd = symbols.localEnd();
+  for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
+    if (!isDynamicSymbol(**symbol))
       continue;
 
     if (isGlobalGOTSymbol(**symbol))
       continue;
 
-    emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
-                      strtabsize, symtabIdx);
+    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
 
+    // maintain output's symbol and index map
+    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+    entry->setValue(symtabIdx);
     // sum up counters
     ++symtabIdx;
-    strtabsize += (*symbol)->nameSize() + 1;
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+      strtabsize += (*symbol)->nameSize() + 1;
+  }
+
+  // emit symbols in TLS category, all symbols in TLS category shold be emitited
+  // directly, except GOT entries
+  symEnd = symbols.tlsEnd();
+  for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+    if (isGlobalGOTSymbol(**symbol))
+      continue;
+
+    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+
+    // maintain output's symbol and index map
+    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+    entry->setValue(symtabIdx);
+    // sum up counters
+    ++symtabIdx;
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+      strtabsize += (*symbol)->nameSize() + 1;
+  }
+
+  // emit the reset of the symbols if the symbol is dynamic symbol
+  symEnd = pModule.sym_end();
+  for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
+    if (!isDynamicSymbol(**symbol))
+      continue;
+
+    if (isGlobalGOTSymbol(**symbol))
+      continue;
+
+    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+
+    // maintain output's symbol and index map
+    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+    entry->setValue(symtabIdx);
+    // sum up counters
+    ++symtabIdx;
+    if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+      strtabsize += (*symbol)->nameSize() + 1;
   }
 
   // emit global GOT
@@ -371,15 +583,19 @@
     // Make sure this golbal GOT entry is a dynamic symbol.
     // If not, something is wrong earlier when putting this symbol into
     //  global GOT.
-    if (!isDynamicSymbol(**symbol, pOutput))
+    if (!isDynamicSymbol(**symbol))
       fatal(diag::mips_got_symbol) << (*symbol)->name();
 
-    emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
-                      strtabsize, symtabIdx);
+    emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+                   symtabIdx);
+    // maintain output's symbol and index map
+    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+    entry->setValue(symtabIdx);
 
     // sum up counters
     ++symtabIdx;
-    strtabsize += (*symbol)->nameSize() + 1;
+    if (ResolveInfo::Section != (*symbol)->type())
+      strtabsize += (*symbol)->nameSize() + 1;
   }
 
   // emit DT_NEED
@@ -389,38 +605,36 @@
   //   2. force count in --no-as-needed
   //   3. judge --as-needed
   ELFDynamic::iterator dt_need = dynamic().needBegin();
-  InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
-  for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
-    if (Input::DynObj == (*input)->type()) {
-      // --add-needed
-      if ((*input)->attribute()->isAddNeeded()) {
-        // --no-as-needed
-        if (!(*input)->attribute()->isAsNeeded()) {
-          strcpy((strtab + strtabsize), (*input)->name().c_str());
-          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
-          strtabsize += (*input)->name().size() + 1;
-          ++dt_need;
-        }
-        // --as-needed
-        else if ((*input)->isNeeded()) {
-          strcpy((strtab + strtabsize), (*input)->name().c_str());
-          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
-          strtabsize += (*input)->name().size() + 1;
-          ++dt_need;
-        }
+  Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+  for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
+    // --add-needed
+    if ((*lib)->attribute()->isAddNeeded()) {
+      // --no-as-needed
+      if (!(*lib)->attribute()->isAsNeeded()) {
+        strcpy((strtab + strtabsize), (*lib)->name().c_str());
+        (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+        strtabsize += (*lib)->name().size() + 1;
+        ++dt_need;
+      }
+      // --as-needed
+      else if ((*lib)->isNeeded()) {
+        strcpy((strtab + strtabsize), (*lib)->name().c_str());
+        (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+        strtabsize += (*lib)->name().size() + 1;
+        ++dt_need;
       }
     }
   } // for
 
   // emit soname
   // initialize value of ELF .dynamic section
-  if (Output::DynObj == pOutput.type())
+  if (LinkerConfig::DynObj == config().codeGenType())
     dynamic().applySoname(strtabsize);
-  dynamic().applyEntries(pLDInfo, *file_format);
+  dynamic().applyEntries(config(), *file_format);
   dynamic().emit(dyn_sect, *dyn_region);
 
-  strcpy((strtab + strtabsize), pOutput.name().c_str());
-  strtabsize += pOutput.name().size() + 1;
+  strcpy((strtab + strtabsize), pModule.name().c_str());
+  strtabsize += pModule.name().size() + 1;
 
   // emit hash table
   // FIXME: this verion only emit SVR4 hash section.
@@ -477,11 +691,9 @@
 }
 
 unsigned int
-MipsGNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                        const LDSection& pSectHdr,
-                                        const MCLDInfo& pInfo) const
+MipsGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
 {
-  const ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat();
 
   if (&pSectHdr == &file_format->getGOT())
     return SHO_DATA;
@@ -490,21 +702,20 @@
 }
 
 /// finalizeSymbol - finalize the symbol value
-bool MipsGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+bool MipsGNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
 {
   if (NULL != m_pGpDispSymbol)
-    m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
+    m_pGpDispSymbol->setValue(m_pGOT->addr() + 0x7FF0);
   return true;
 }
 
 /// allocateCommonSymbols - allocate common symbols in the corresponding
-/// sections.
+/// sections. This is called at pre-layout stage.
 /// @refer Google gold linker: common.cc: 214
 /// FIXME: Mips needs to allocate small common symbol
-bool
-MipsGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
+bool MipsGNULDBackend::allocateCommonSymbols(Module& pModule)
 {
-  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
+  SymbolCategory& symbol_list = pModule.getSymbolTable();
 
   if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
     return true;
@@ -514,44 +725,27 @@
   // FIXME: If the order of common symbols is defined, then sort common symbols
   // std::sort(com_sym, com_end, some kind of order);
 
-  // get or create corresponding BSS LDSection
-  LDSection* bss_sect = &pLinker.getOrCreateOutputSectHdr(".bss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-
-  LDSection* tbss_sect = &pLinker.getOrCreateOutputSectHdr(
-                                   ".tbss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-
-  // FIXME: .sbss amd .lbss currently unused.
-  /*
-  LDSection* sbss_sect = &pLinker.getOrCreateOutputSectHdr(
-                                   ".sbss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC |
-                                   llvm::ELF::SHF_MIPS_GPREL);
-
-  LDSection* lbss_sect = &pLinker.getOrCreateOutputSectHdr(
-                                   ".lbss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC |
-                                   llvm::ELF::SHF_MIPS_LOCAL);
-  */
-
-  assert(NULL != bss_sect && NULL != tbss_sect);
+  // get corresponding BSS LDSection
+  ELFFileFormat* file_format = getOutputFormat();
+  LDSection& bss_sect = file_format->getBSS();
+  LDSection& tbss_sect = file_format->getTBSS();
 
   // get or create corresponding BSS SectionData
-  SectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
-  SectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
+  SectionData* bss_sect_data = NULL;
+  if (bss_sect.hasSectionData())
+    bss_sect_data = bss_sect.getSectionData();
+  else
+    bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
+
+  SectionData* tbss_sect_data = NULL;
+  if (tbss_sect.hasSectionData())
+    tbss_sect_data = tbss_sect.getSectionData();
+  else
+    tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
 
   // remember original BSS size
-  uint64_t bss_offset  = bss_sect->size();
-  uint64_t tbss_offset = tbss_sect->size();
+  uint64_t bss_offset  = bss_sect.size();
+  uint64_t tbss_offset = tbss_sect.size();
 
   // allocate all local common symbols
   com_end = symbol_list.localEnd();
@@ -565,19 +759,19 @@
       // description here.
       (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
       Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
+      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
       if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
         // allocate TLS common symbol in tbss section
-        tbss_offset += pLinker.getLayout().appendFragment(*frag,
-                                                          tbss_sect_data,
-                                                          (*com_sym)->value());
+        tbss_offset += ObjectBuilder::AppendFragment(*frag,
+                                                     *tbss_sect_data,
+                                                     (*com_sym)->value());
       }
       // FIXME: how to identify small and large common symbols?
       else {
-        bss_offset += pLinker.getLayout().appendFragment(*frag,
-                                                         bss_sect_data,
-                                                         (*com_sym)->value());
+        bss_offset += ObjectBuilder::AppendFragment(*frag,
+                                                    *bss_sect_data,
+                                                    (*com_sym)->value());
       }
     }
   }
@@ -592,69 +786,48 @@
     // description here.
     (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
     Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
+    (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
 
     if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
       // allocate TLS common symbol in tbss section
-      tbss_offset += pLinker.getLayout().appendFragment(*frag,
-                                                        tbss_sect_data,
-                                                        (*com_sym)->value());
+      tbss_offset += ObjectBuilder::AppendFragment(*frag,
+                                                   *tbss_sect_data,
+                                                   (*com_sym)->value());
     }
     // FIXME: how to identify small and large common symbols?
     else {
-      bss_offset += pLinker.getLayout().appendFragment(*frag,
-                                                       bss_sect_data,
-                                                       (*com_sym)->value());
+      bss_offset += ObjectBuilder::AppendFragment(*frag,
+                                                  *bss_sect_data,
+                                                  (*com_sym)->value());
     }
   }
 
-  bss_sect->setSize(bss_offset);
-  tbss_sect->setSize(tbss_offset);
+  bss_sect.setSize(bss_offset);
+  tbss_sect.setSize(tbss_offset);
   symbol_list.changeCommonsToGlobal();
   return true;
 }
 
-void MipsGNULDBackend::updateAddend(Relocation& pReloc,
-                                   const LDSymbol& pInputSym,
-                                   const Layout& pLayout) const
-{
-  // Update value keep in addend if we meet a section symbol
-  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
-    pReloc.setAddend(pLayout.getOutputOffset(
-                     *pInputSym.fragRef()) + pReloc.addend());
-  }
-}
-
 void MipsGNULDBackend::scanLocalReloc(Relocation& pReloc,
-                                      const LDSymbol& pInputSym,
-                                      MCLinker& pLinker,
-                                      const MCLDInfo& pLDInfo,
-                                      const Output& pOutput)
+                                      FragmentLinker& pLinker)
 {
   ResolveInfo* rsym = pReloc.symInfo();
 
-  updateAddend(pReloc, pInputSym, pLinker.getLayout());
-
   switch (pReloc.type()){
     case llvm::ELF::R_MIPS_NONE:
     case llvm::ELF::R_MIPS_16:
       break;
     case llvm::ELF::R_MIPS_32:
-      if (Output::DynObj == pOutput.type()) {
+      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.
         // 1. Find the reason of this condition.
         // 2. Check this condition here.
-        if (NULL == m_pRelDyn)
-          createRelDyn(pLinker, pOutput);
-
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         rsym->setReserved(rsym->reserved() | ReserveRel);
 
         // Remeber this rsym is a local GOT entry (as if it needs an entry).
         // Actually we don't allocate an GOT entry.
-        if (NULL == m_pGOT)
-          createGOT(pLinker, pOutput);
         m_pGOT->setLocal(rsym);
       }
       break;
@@ -686,9 +859,6 @@
       break;
     case llvm::ELF::R_MIPS_GOT16:
     case llvm::ELF::R_MIPS_CALL16:
-      if (NULL == m_pGOT)
-        createGOT(pLinker, pOutput);
-
       // For got16 section based relocations, we need to reserve got entries.
       if (rsym->type() == ResolveInfo::Section) {
         m_pGOT->reserveLocalEntry();
@@ -735,10 +905,7 @@
 }
 
 void MipsGNULDBackend::scanGlobalReloc(Relocation& pReloc,
-                                       const LDSymbol& pInputSym,
-                                       MCLinker& pLinker,
-                                       const MCLDInfo& pLDInfo,
-                                       const Output& pOutput)
+                                       FragmentLinker& pLinker)
 {
   ResolveInfo* rsym = pReloc.symInfo();
 
@@ -759,17 +926,12 @@
     case llvm::ELF::R_MIPS_64:
     case llvm::ELF::R_MIPS_HI16:
     case llvm::ELF::R_MIPS_LO16:
-      if (symbolNeedsDynRel(*rsym, false, pLDInfo, pOutput, true)) {
-        if (NULL == m_pRelDyn)
-          createRelDyn(pLinker, pOutput);
-
+      if (symbolNeedsDynRel(pLinker, *rsym, false, true)) {
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         rsym->setReserved(rsym->reserved() | ReserveRel);
 
         // Remeber this rsym is a global GOT entry (as if it needs an entry).
         // Actually we don't allocate an GOT entry.
-        if (NULL == m_pGOT)
-          createGOT(pLinker, pOutput);
         m_pGOT->setGlobal(rsym);
       }
       break;
@@ -782,9 +944,6 @@
     case llvm::ELF::R_MIPS_CALL_LO16:
     case llvm::ELF::R_MIPS_GOT_PAGE:
     case llvm::ELF::R_MIPS_GOT_OFST:
-      if (NULL == m_pGOT)
-        createGOT(pLinker, pOutput);
-
       if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
         m_pGOT->reserveGlobalEntry();
         rsym->setReserved(rsym->reserved() | ReserveGot);
@@ -836,16 +995,11 @@
   }
 }
 
-void MipsGNULDBackend::createGOT(MCLinker& pLinker, const Output& pOutput)
+void MipsGNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  LDSection& got = file_format->getGOT();
-  m_pGOT = new MipsGOT(got, pLinker.getOrCreateSectData(got));
-
-  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
+  // define symbol _GLOBAL_OFFSET_TABLE_
   if ( m_pGOTSymbol != NULL ) {
-    pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
+    pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
                      ResolveInfo::Object,
@@ -853,11 +1007,11 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     FragmentRef::Create(*(m_pGOT->begin()), 0x0),
                      ResolveInfo::Hidden);
   }
   else {
-    m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+    m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
                      ResolveInfo::Object,
@@ -865,45 +1019,40 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     FragmentRef::Create(*(m_pGOT->begin()), 0x0),
                      ResolveInfo::Hidden);
   }
 }
 
-void MipsGNULDBackend::createRelDyn(MCLinker& pLinker, const Output& pOutput)
+/// doCreateProgramHdrs - backend can implement this function to create the
+/// target-dependent segments
+void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule,
+                                           const FragmentLinker& pLinker)
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  // get .rel.dyn LDSection and create SectionData
-  LDSection& reldyn = file_format->getRelDyn();
-  // create SectionData and ARMRelDynSection
-  m_pRelDyn = new OutputRelocSection(reldyn,
-                                     pLinker.getOrCreateSectData(reldyn),
-                                     8);
+  // TODO
 }
 
 //===----------------------------------------------------------------------===//
 /// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
 ///
 static TargetLDBackend* createMipsLDBackend(const llvm::Target& pTarget,
-                                            const std::string& pTriple)
+                                            const LinkerConfig& pConfig)
 {
-  llvm::Triple theTriple(pTriple);
-  if (theTriple.isOSDarwin()) {
+  if (pConfig.triple().isOSDarwin()) {
     assert(0 && "MachO linker is not supported yet");
   }
-  if (theTriple.isOSWindows()) {
+  if (pConfig.triple().isOSWindows()) {
     assert(0 && "COFF linker is not supported yet");
   }
-  return new MipsGNULDBackend();
+  return new MipsGNULDBackend(pConfig);
 }
 
-} // namespace of mcld
-
-//=============================
+//===----------------------------------------------------------------------===//
 // Force static initialization.
-extern "C" void LLVMInitializeMipsLDBackend() {
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeMipsLDBackend() {
   // Register the linker backend
   mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
-                                                mcld::createMipsLDBackend);
+                                                createMipsLDBackend);
 }
+
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
index 84f2277..b6adb93 100644
--- a/lib/Target/Mips/MipsLDBackend.h
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -8,15 +8,17 @@
 //===----------------------------------------------------------------------===//
 #ifndef MIPS_LDBACKEND_H
 #define MIPS_LDBACKEND_H
-#include "mcld/Target/GNULDBackend.h"
+#include <mcld/Target/GNULDBackend.h>
 #include "MipsELFDynamic.h"
 #include "MipsGOT.h"
 
 namespace mcld {
 
-class MCLinker;
+class LinkerConfig;
+class FragmentLinker;
 class OutputRelocSection;
 class SectionMap;
+class MemoryArea;
 
 //===----------------------------------------------------------------------===//
 /// MipsGNULDBackend - linker backend of Mips target of GNU ELF format
@@ -32,21 +34,18 @@
   };
 
 public:
-  MipsGNULDBackend();
+  MipsGNULDBackend(const LinkerConfig& pConfig);
   ~MipsGNULDBackend();
 
 public:
-  /// initTargetSectionMap - initialize target dependent section mapping.
-  bool initTargetSectionMap(SectionMap& pSectionMap);
-
   /// initTargetSections - initialize target dependent sections in output
-  void initTargetSections(MCLinker& pLinker);
+  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
 
   /// initTargetSymbols - initialize target dependent symbols in output.
-  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+  void initTargetSymbols(FragmentLinker& pLinker);
 
   /// initRelocFactory - create and initialize RelocationFactory.
-  bool initRelocFactory(const MCLinker& pLinker);
+  bool initRelocFactory(const FragmentLinker& pLinker);
 
   /// getRelocFactory - return relocation factory.
   RelocationFactory* getRelocFactory();
@@ -55,10 +54,8 @@
   /// create the empty entries if needed.
   /// For Mips, the GOT, GP, and dynamic relocation entries are check to create.
   void scanRelocation(Relocation& pReloc,
-                      const LDSymbol& pInputSym,
-                      MCLinker& pLinker,
-                      const MCLDInfo& pLDInfo,
-                      const Output& pOutput,
+                      FragmentLinker& pLinker,
+                      Module& pModule,
                       const LDSection& pSection);
 
   uint32_t machine() const;
@@ -79,17 +76,13 @@
   uint64_t defaultTextSegmentAddr() const;
 
   /// abiPageSize - the abi page size of the target machine
-  uint64_t abiPageSize(const MCLDInfo& pInfo) const;
+  uint64_t abiPageSize() const;
 
   /// preLayout - Backend can do any needed modification before layout
-  void doPreLayout(const Output& pOutput,
-                   const MCLDInfo& pInfo,
-                   MCLinker& pLinker);
+  void doPreLayout(FragmentLinker& pLinker);
 
   /// postLayout -Backend can do any needed modification after layout
-  void doPostLayout(const Output& pOutput,
-                    const MCLDInfo& pInfo,
-                    MCLinker& pLinker);
+  void doPostLayout(Module& pModule, FragmentLinker& pLinker);
 
   /// dynamic - the dynamic section of the target machine.
   /// Use co-variant return type to return its own dynamic section.
@@ -110,23 +103,17 @@
   ///  - backend can maintain its own map<LDSection, table> to get the table
   /// from given LDSection.
   ///
-  /// @param pOutput - the output file
   /// @param pSection - the given LDSection
-  /// @param pInfo - all options in the command line.
-  /// @param pLayout - for comouting the size of fragment
   /// @param pRegion - the region to write out data
   /// @return the size of the table in the file.
-  uint64_t emitSectionData(const Output& pOutput,
-                           const LDSection& pSection,
-                           const MCLDInfo& pInfo,
-                           const Layout& pLayout,
+  uint64_t emitSectionData(const LDSection& pSection,
                            MemoryRegion& pRegion) const;
 
+  void sizeNamePools(const Module& pModule, bool pIsStaticLink);
+
   /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
-  virtual void emitDynNamePools(Output& pOutput,
-                                SymbolCategory& pSymbols,
-                                const Layout& pLayout,
-                                const MCLDInfo& pLDInfo);
+  void emitDynNamePools(const Module& pModule, MemoryArea& pOut);
+
 
   MipsGOT& getGOT();
   const MipsGOT& getGOT() const;
@@ -135,40 +122,41 @@
   const OutputRelocSection& getRelDyn() const;
 
   /// getTargetSectionOrder - compute the layout order of ARM target sections
-  unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr,
-                                     const MCLDInfo& pInfo) const;
+  unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
 
   /// finalizeSymbol - finalize the symbol value
-  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+  bool finalizeTargetSymbols(FragmentLinker& pLinker);
 
   /// allocateCommonSymbols - allocate common symbols in the corresponding
   /// sections.
-  bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
+  bool allocateCommonSymbols(Module& pModule);
 
 private:
-  void scanLocalReloc(Relocation& pReloc,
-                      const LDSymbol& pInputSym,
-                      MCLinker& pLinker,
-                      const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+  void scanLocalReloc(Relocation& pReloc, FragmentLinker& pLinker);
 
-  void scanGlobalReloc(Relocation& pReloc,
-                      const LDSymbol& pInputSym,
-                      MCLinker& pLinker,
-                      const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+  void scanGlobalReloc(Relocation& pReloc, FragmentLinker& pLinker);
 
-  void createGOT(MCLinker& pLinker, const Output& pOutput);
-  void createRelDyn(MCLinker& pLinker, const Output& pOutput);
+  void defineGOTSymbol(FragmentLinker& pLinker);
 
-  /// updateAddend - update addend value of the relocation if the
-  /// the target symbol is a section symbol. Addend is the offset
-  /// in the section. This value should be updated after section
-  /// merged.
-  void updateAddend(Relocation& pReloc,
-                    const LDSymbol& pInputSym,
-                    const Layout& pLayout) const;
+  /// emitSymbol32 - emit an ELF32 symbol, override parent's function
+  void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32,
+                    LDSymbol& pSymbol,
+                    char* pStrtab,
+                    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
+  virtual void doCreateProgramHdrs(Module& pModule,
+                                   const FragmentLinker& pLinker);
 
 private:
   RelocationFactory* m_pRelocFactory;
@@ -185,14 +173,7 @@
 private:
   /// isGlobalGOTSymbol - return true if the symbol is the global GOT entry.
   bool isGlobalGOTSymbol(const LDSymbol& pSymbol) const;
-  /// emitDynamicSymbol - emit dynamic symbol.
-  void emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
-                         Output& pOutput,
-                         LDSymbol& pSymbol,
-                         const Layout& pLayout,
-                         char* strtab,
-                         size_t strtabsize,
-                         size_t symtabIdx);
+
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/MipsMCLinker.cpp b/lib/Target/Mips/MipsMCLinker.cpp
new file mode 100644
index 0000000..5805f12
--- /dev/null
+++ b/lib/Target/Mips/MipsMCLinker.cpp
@@ -0,0 +1,50 @@
+//===- MipsMCLinker.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "MipsELFMCLinker.h"
+
+#include "Mips.h"
+#include <llvm/ADT/Triple.h>
+#include <mcld/Module.h>
+#include <mcld/Support/TargetRegistry.h>
+
+using namespace mcld;
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+/// createMipsMCLinker - the help funtion to create
+//===----------------------------------------------------------------------===//
+/// corresponding MipsMCLinker
+///
+MCLinker* createMipsMCLinker(const std::string &pTriple,
+                             LinkerConfig& pConfig,
+                             mcld::Module& pModule,
+                             MemoryArea& pOutput)
+{
+  llvm::Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+    return NULL;
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+    return NULL;
+  }
+
+  return new MipsELFMCLinker(pConfig, pModule, pOutput);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// MipsMCLinker
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeMipsMCLinker() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterMCLinker(TheMipselTarget, createMipsMCLinker);
+}
diff --git a/lib/Target/Mips/MipsRelocationFactory.cpp b/lib/Target/Mips/MipsRelocationFactory.cpp
index a9a34b2..09041be 100644
--- a/lib/Target/Mips/MipsRelocationFactory.cpp
+++ b/lib/Target/Mips/MipsRelocationFactory.cpp
@@ -9,9 +9,9 @@
 
 #include <llvm/ADT/Twine.h>
 #include <llvm/Support/ELF.h>
-#include <mcld/LD/Layout.h>
-#include <mcld/Target/OutputRelocSection.h>
+#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/OutputRelocSection.h>
 
 #include "MipsRelocationFactory.h"
 #include "MipsRelocationFunctions.h"
@@ -25,7 +25,6 @@
 
 /// the prototype of applying function
 typedef RelocationFactory::Result (*ApplyFunctionType)(Relocation&,
-                                                       const MCLDInfo& pLDInfo,
                                                        MipsRelocationFactory&);
 
 // the table entry of applying functions
@@ -53,20 +52,17 @@
 }
 
 RelocationFactory::Result
-MipsRelocationFactory::applyRelocation(Relocation& pRelocation,
-                                       const MCLDInfo& pLDInfo)
+MipsRelocationFactory::applyRelocation(Relocation& pRelocation)
 
 {
   Relocation::Type type = pRelocation.type();
 
   if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) {
-    fatal(diag::unknown_relocation) << (int)type
-                                    << pRelocation.symInfo()->name();
     return Unknown;
   }
 
   // apply the relocation
-  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
+  return ApplyFunctions[type].func(pRelocation, *this);
 }
 
 const char* MipsRelocationFactory::getName(Relocation::Type pType) const
@@ -107,11 +103,11 @@
 static
 RelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent)
 {
-  return pParent.getTarget().getGOT().getSection().addr() + 0x7FF0;
+  return pParent.getTarget().getGOT().addr() + 0x7FF0;
 }
 
 static
-GOTEntry& helper_GetGOTEntry(Relocation& pReloc,
+GOT::Entry& helper_GetGOTEntry(Relocation& pReloc,
                              MipsRelocationFactory& pParent,
                              bool& pExist, int32_t value)
 {
@@ -120,22 +116,34 @@
   MipsGNULDBackend& ld_backend = pParent.getTarget();
   MipsGOT& got = ld_backend.getGOT();
 
-  GOTEntry& got_entry = *got.getEntry(*rsym, pExist);
-
-  if (pExist)
-    return got_entry;
-
-  // If we first get this GOT entry, we should initialize it.
-  if (!(got.isLocal(rsym) && rsym->type() == ResolveInfo::Section)) {
-    if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
-      got_entry.setContent(pReloc.symValue());
-    }
-    else {
-      fatal(diag::reserve_entry_number_mismatch_got);
-    }
+  if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) {
+    // Local section symbols consume local got entries.
+    return *got.consumeLocal();
   }
 
-  return got_entry;
+  GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*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();
+
+  pParent.getSymGOTMap().record(*rsym, *got_entry);
+
+  // If we first get this GOT entry, we should initialize it.
+  if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
+    got_entry->setContent(pReloc.symValue());
+  }
+  else {
+    fatal(diag::reserve_entry_number_mismatch_got);
+  }
+
+  return *got_entry;
 }
 
 static
@@ -143,8 +151,8 @@
                                                MipsRelocationFactory& pParent)
 {
   bool exist;
-  GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
-  return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
+  GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
+  return got_entry.getOffset() - 0x7FF0;
 }
 
 static
@@ -160,7 +168,8 @@
 
   int32_t AHI = pHiReloc.target();
   int32_t ALO = pLoReloc.target();
-  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + pLoReloc.addend();
+  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) +
+                 pLoReloc.addend();
   return AHL;
 }
 
@@ -172,9 +181,7 @@
   MipsGNULDBackend& ld_backend = pParent.getTarget();
   MipsGOT& got = ld_backend.getGOT();
 
-  bool exist;
-  Relocation& rel_entry =
-    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
+  Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
 
   rel_entry.setType(llvm::ELF::R_MIPS_REL32);
   rel_entry.targetRef() = pReloc.targetRef();
@@ -200,7 +207,6 @@
 // R_MIPS_NONE and those unsupported/deprecated relocation type
 static
 MipsRelocationFactory::Result none(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
                                    MipsRelocationFactory& pParent)
 {
   return MipsRelocationFactory::OK;
@@ -209,7 +215,6 @@
 // R_MIPS_32: S + A
 static
 MipsRelocationFactory::Result abs32(Relocation& pReloc,
-                                    const MCLDInfo& pLDInfo,
                                     MipsRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
@@ -217,12 +222,10 @@
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   RelocationFactory::DWord S = pReloc.symValue();
 
-  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                  *(pReloc.targetRef().frag()));
-  assert(NULL != target_sect);
+  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 & target_sect.flag())) {
     pReloc.target() = S + A;
     return MipsRelocationFactory::OK;
   }
@@ -243,7 +246,6 @@
 //   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
 static
 MipsRelocationFactory::Result hi16(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
                                    MipsRelocationFactory& pParent)
 {
   Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
@@ -255,7 +257,7 @@
   pParent.setAHL(AHL);
 
   if (helper_isGpDisp(pReloc)) {
-    int32_t P = pReloc.place(pParent.getLayout());
+    int32_t P = pReloc.place();
     int32_t GP = helper_GetGP(pParent);
     res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
   }
@@ -275,13 +277,12 @@
 //   _gp_disp      : AHL + GP - P + 4
 static
 MipsRelocationFactory::Result lo16(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
                                    MipsRelocationFactory& pParent)
 {
   int32_t res = 0;
 
   if (helper_isGpDisp(pReloc)) {
-    int32_t P = pReloc.place(pParent.getLayout());
+    int32_t P = pReloc.place();
     int32_t GP = helper_GetGP(pParent);
     int32_t AHL = pParent.getAHL();
     res = AHL + GP - P + 4;
@@ -306,7 +307,6 @@
 //   external: G
 static
 MipsRelocationFactory::Result got16(Relocation& pReloc,
-                                    const MCLDInfo& pLDInfo,
                                     MipsRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
@@ -323,10 +323,10 @@
 
     int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
     bool exist;
-    GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
+    GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
 
     got_entry.setContent(res);
-    G = pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
+    G = got_entry.getOffset() - 0x7FF0;
   }
   else {
     G = helper_GetGOTOffset(pReloc, pParent);
@@ -341,7 +341,6 @@
 // R_MIPS_CALL16: G
 static
 MipsRelocationFactory::Result call16(Relocation& pReloc,
-                                     const MCLDInfo& pLDInfo,
                                      MipsRelocationFactory& pParent)
 {
   RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
@@ -355,7 +354,6 @@
 // R_MIPS_GPREL32: A + S + GP0 - GP
 static
 MipsRelocationFactory::Result gprel32(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
                                       MipsRelocationFactory& pParent)
 {
   // Remember to add the section offset to A.
diff --git a/lib/Target/Mips/MipsRelocationFactory.h b/lib/Target/Mips/MipsRelocationFactory.h
index a1c7b5d..6076416 100644
--- a/lib/Target/Mips/MipsRelocationFactory.h
+++ b/lib/Target/Mips/MipsRelocationFactory.h
@@ -14,10 +14,10 @@
 
 #include <mcld/LD/RelocationFactory.h>
 #include <mcld/Support/GCFactory.h>
+#include <mcld/Target/SymbolEntryMap.h>
 #include "MipsLDBackend.h"
 
-namespace mcld
-{
+namespace mcld {
 
 /** \class MipsRelocationFactory
  *  \brief MipsRelocationFactory creates and destroys the Mips relocations.
@@ -25,9 +25,12 @@
 class MipsRelocationFactory : public RelocationFactory
 {
 public:
+  typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
+
+public:
   MipsRelocationFactory(size_t pNum, MipsGNULDBackend& pParent);
 
-  Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+  Result applyRelocation(Relocation& pRelocation);
 
   MipsGNULDBackend& getTarget()
   { return m_Target; }
@@ -45,9 +48,13 @@
 
   const char* getName(Relocation::Type pType) const;
 
+  const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
+  SymGOTMap&       getSymGOTMap()       { return m_SymGOTMap; }
+
 private:
   MipsGNULDBackend& m_Target;
   int32_t m_AHL;
+  SymGOTMap m_SymGOTMap;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/MipsRelocationFunctions.h b/lib/Target/Mips/MipsRelocationFunctions.h
index 4b60d10..adff43f 100644
--- a/lib/Target/Mips/MipsRelocationFunctions.h
+++ b/lib/Target/Mips/MipsRelocationFunctions.h
@@ -9,7 +9,6 @@
 
 #define DECL_MIPS_APPLY_RELOC_FUNC(Name) \
 static MipsRelocationFactory::Result Name(Relocation& pEntry, \
-                                          const MCLDInfo& pLDInfo, \
                                           MipsRelocationFactory& pParent);
 
 #define DECL_MIPS_APPLY_RELOC_FUNCS \
diff --git a/lib/Target/Mips/MipsSectLinker.cpp b/lib/Target/Mips/MipsSectLinker.cpp
deleted file mode 100644
index ed04edd..0000000
--- a/lib/Target/Mips/MipsSectLinker.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- MipsSectLinker.cpp -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <llvm/ADT/Triple.h>
-#include <mcld/Support/TargetRegistry.h>
-#include "Mips.h"
-#include "MipsELFSectLinker.h"
-
-using namespace mcld;
-
-namespace mcld {
-//===----------------------------------------------------------------------===//
-/// createMipsSectLinker - the help funtion to create
-/// corresponding MipsSectLinker
-///
-SectLinker* createMipsSectLinker(const std::string &pTriple,
-                                 SectLinkerOption &pOption,
-                                 mcld::TargetLDBackend &pLDBackend)
-{
-  llvm::Triple theTriple(pTriple);
-  if (theTriple.isOSDarwin()) {
-    assert(0 && "MachO linker has not supported yet");
-    return NULL;
-  }
-  if (theTriple.isOSWindows()) {
-    assert(0 && "COFF linker has not supported yet");
-    return NULL;
-  }
-
-  return new MipsELFSectLinker(pOption, pLDBackend);
-}
-
-} // namespace of mcld
-
-//==========================
-// MipsSectLinker
-extern "C" void LLVMInitializeMipsSectLinker() {
-  // Register the linker frontend
-  mcld::TargetRegistry::RegisterSectLinker(TheMipselTarget,
-                                           createMipsSectLinker);
-}
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 0987585..03db780 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -6,14 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include "MipsTargetMachine.h"
-#include "mcld/Target/TargetMachine.h"
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/MC/MCLDInfo.h"
-#include "Mips.h"
 
-extern "C" void LLVMInitializeMipsLDTarget() {
+#include "Mips.h"
+#include <mcld/Target/TargetMachine.h>
+#include <mcld/Support/TargetRegistry.h>
+
+extern "C" void MCLDInitializeMipsLDTarget() {
   // Register createTargetMachine function pointer to mcld::Target
   mcld::RegisterTargetMachine<mcld::MipsBaseTargetMachine>
         X(mcld::TheMipselTarget);
@@ -22,13 +21,9 @@
 mcld::MipsBaseTargetMachine::MipsBaseTargetMachine(llvm::TargetMachine& pPM,
                                                    const mcld::Target &pTarget,
                                                    const std::string& pTriple)
-  : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
-  // arg1 - the number of total attributes
-  // arg2 - the most possible number of input files
-  m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+  : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
 }
 
 mcld::MipsBaseTargetMachine::~MipsBaseTargetMachine()
 {
-  delete m_pLDInfo;
 }
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index e9bd5da..6cfae73 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -8,29 +8,20 @@
 //===----------------------------------------------------------------------===//
 #ifndef MIPS_TARGET_MACHINE_H
 #define MIPS_TARGET_MACHINE_H
-#include "mcld/Target/TargetMachine.h"
+
 #include "Mips.h"
+#include <mcld/Target/TargetMachine.h>
 
-namespace mcld
+namespace mcld {
+
+class MipsBaseTargetMachine : public MCLDTargetMachine
 {
-
-class MipsBaseTargetMachine : public LLVMTargetMachine
-{
-protected:
-  MCLDInfo *m_pLDInfo;
-
 public:
   MipsBaseTargetMachine(llvm::TargetMachine &pTM,
                         const mcld::Target &pTarget,
                         const std::string &pTriple);
 
   virtual ~MipsBaseTargetMachine();
-
-  mcld::MCLDInfo& getLDInfo()
-  { return *m_pLDInfo; }
-
-  const mcld::MCLDInfo& getLDInfo() const
-  { return *m_pLDInfo; }
 };
 
 } // namespace of mcld
diff --git a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
index 0889973..3991c45 100644
--- a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
+++ b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
@@ -13,7 +13,7 @@
 
 mcld::Target TheMipselTarget;
 
-extern "C" void LLVMInitializeMipsLDTargetInfo() {
+extern "C" void MCLDInitializeMipsLDTargetInfo() {
   // register into mcld::TargetRegistry
   mcld::RegisterTarget X(TheMipselTarget, "mipsel");
 }
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
index c5bb9a8..593bdb9 100644
--- a/lib/Target/OutputRelocSection.cpp
+++ b/lib/Target/OutputRelocSection.cpp
@@ -7,26 +7,31 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <mcld/Target/OutputRelocSection.h>
-
 #include <llvm/Support/Casting.h>
 
 #include <mcld/LD/LDSection.h>
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/Module.h>
 #include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/OutputRelocSection.h>
+#include <mcld/IRBuilder.h>
 
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
 // OutputRelocSection
 //===----------------------------------------------------------------------===//
-OutputRelocSection::OutputRelocSection(LDSection& pSection,
-                                       SectionData& pSectionData,
+OutputRelocSection::OutputRelocSection(Module& pModule,
+                                       LDSection& pSection,
                                        unsigned int pEntrySize)
-  : m_pSection(&pSection),
-    m_pSectionData(&pSectionData),
+  : m_Module(pModule),
+    m_pSection(&pSection),
+    m_pRelocData(NULL),
     m_EntryBytes(pEntrySize),
     m_isVisit(false),
     m_ValidEntryIterator(){
+  assert(!pSection.hasRelocData() && "Given section is not a relocation section");
+  m_pRelocData = IRBuilder::CreateRelocData(pSection);
 }
 
 OutputRelocSection::~OutputRelocSection()
@@ -37,52 +42,45 @@
                                       size_t pNum)
 {
   for(size_t i=0; i<pNum; i++) {
-    m_pSectionData->getFragmentList().push_back(pRelFactory.produceEmptyEntry());
+    m_pRelocData->getFragmentList().push_back(
+                                              pRelFactory.produceEmptyEntry());
     // update section size
     m_pSection->setSize(m_pSection->size() + m_EntryBytes);
   }
 }
 
-Relocation* OutputRelocSection::getEntry(const ResolveInfo& pSymbol,
-                                         bool isForGOT,
-                                         bool& pExist)
+Relocation* OutputRelocSection::consumeEntry()
 {
   // first time visit this function, set m_ValidEntryIterator to
   // Fragments.begin()
   if(!m_isVisit) {
-    assert( !m_pSectionData->getFragmentList().empty() &&
+    assert(!m_pRelocData->getFragmentList().empty() &&
              "DynRelSection contains no entries.");
-    m_ValidEntryIterator = m_pSectionData->getFragmentList().begin();
+    m_ValidEntryIterator = m_pRelocData->getFragmentList().begin();
     m_isVisit = true;
   }
-
-  assert(m_ValidEntryIterator != m_pSectionData->end() &&
-         "No empty relocation entry for the incoming symbol.");
-
-  // if this relocation is used to relocate GOT (.got or .got.plt),
-  // check if we've gotten an entry for this symbol before. If yes,
-  // return the found entry in map.
-  // Otherwise, this relocation is used to relocate general section
-  // (data or text section), return an empty entry directly.
-  Relocation* result;
-
-  if(isForGOT) {
-    // get or create entry in m_SymRelMap
-    Relocation *&entry = m_SymRelMap[&pSymbol];
-    pExist = true;
-
-    if(NULL == entry) {
-      pExist = false;
-      entry = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
-      ++m_ValidEntryIterator;
-    }
-    result = entry;
-  }
   else {
-    pExist = false;
-    result = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
+    // Add m_ValidEntryIterator here instead of at the end of this function.
+    // We may reserve an entry and then consume it immediately, e.g. for COPY
+    // relocation, so we need to avoid setting this iterator to
+    // RelocData->end() in any case, or when reserve and consume again,
+    // ++m_ValidEntryIterator will still be RelocData->end().
     ++m_ValidEntryIterator;
   }
+  assert(m_ValidEntryIterator != m_pRelocData->end() &&
+         "No empty relocation entry for the incoming symbol.");
+
+  Relocation* result = &llvm::cast<Relocation>(*m_ValidEntryIterator);
   return result;
 }
 
+void OutputRelocSection::finalizeSectionSize()
+{
+  m_pSection->setSize(m_pRelocData->size() * m_EntryBytes);
+}
+
+bool OutputRelocSection::addSymbolToDynSym(LDSymbol& pSymbol)
+{
+  m_Module.getSymbolTable().changeLocalToTLS(pSymbol);
+  return true;
+}
diff --git a/lib/Target/PLT.cpp b/lib/Target/PLT.cpp
index 782d974..a8b515c 100644
--- a/lib/Target/PLT.cpp
+++ b/lib/Target/PLT.cpp
@@ -8,21 +8,22 @@
 //===----------------------------------------------------------------------===//
 
 #include <mcld/Target/PLT.h>
+#include <mcld/IRBuilder.h>
 
 using namespace mcld;
 
 class GOT;
 
 //===----------------------------------------------------------------------===//
-// PLTEntry
+// PLT::Entry
 //===----------------------------------------------------------------------===//
-PLTEntry::PLTEntry(size_t pSize, SectionData* pParent)
-   : TargetFragment(Fragment::Target, pParent),
-     m_EntrySize(pSize), m_pContent(NULL)
+PLT::Entry::Entry(size_t pSize, SectionData& pParent)
+  : TargetFragment(Fragment::Target, &pParent),
+    m_EntrySize(pSize), m_pContent(NULL)
 {
 }
 
-PLTEntry::~PLTEntry()
+PLT::Entry::~Entry()
 {
   if (m_pContent) {
     free(m_pContent);
@@ -33,10 +34,10 @@
 //===----------------------------------------------------------------------===//
 // PLT
 //===----------------------------------------------------------------------===//
-PLT::PLT(LDSection& pSection, SectionData& pSectionData)
-  :m_Section(pSection),
-   m_SectionData(pSectionData)
+PLT::PLT(LDSection& pSection)
+  :m_Section(pSection)
 {
+  m_SectionData = IRBuilder::CreateSectionData(pSection);
 }
 
 PLT::~PLT()
diff --git a/lib/Target/Stub.cpp b/lib/Target/Stub.cpp
deleted file mode 100644
index 4b59acf..0000000
--- a/lib/Target/Stub.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-//===- Stub.cpp -----------------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/Target/Stub.h"
-
-using namespace mcld;
-
-//==========================
-// Stub
-
diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp
index ec8dc87..ba69e03 100644
--- a/lib/Target/Target.cpp
+++ b/lib/Target/Target.cpp
@@ -15,7 +15,7 @@
 
 mcld::Target::Target()
   : TargetMachineCtorFn(NULL),
-    SectLinkerCtorFn(NULL),
+    MCLinkerCtorFn(NULL),
     TargetLDBackendCtorFn(NULL),
     DiagnosticLineInfoCtorFn(NULL),
     m_pT(NULL)
diff --git a/lib/Target/TargetLDBackend.cpp b/lib/Target/TargetLDBackend.cpp
index 4eda0a6..e955916 100644
--- a/lib/Target/TargetLDBackend.cpp
+++ b/lib/Target/TargetLDBackend.cpp
@@ -6,32 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/LD/Relocation.h"
-#include "mcld/LD/Layout.h"
-#include "mcld/Target/TargetLDBackend.h"
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/LinkerConfig.h>
 
 using namespace mcld;
 
-/* ** */
-TargetLDBackend::TargetLDBackend()
-  : m_pEhFrame(NULL) {
+TargetLDBackend::TargetLDBackend(const LinkerConfig& pConfig)
+  : m_Config(pConfig) {
 }
 
 TargetLDBackend::~TargetLDBackend()
 {
-  if (NULL != m_pEhFrame)
-    delete m_pEhFrame;
 }
 
-EhFrame* TargetLDBackend::getEhFrame()
-{
-  if (NULL == m_pEhFrame)
-    m_pEhFrame = new EhFrame();
-  return m_pEhFrame;
-}
-
-const EhFrame* TargetLDBackend::getEhFrame() const
-{
-  assert(NULL == m_pEhFrame);
-  return m_pEhFrame;
-}
diff --git a/lib/Target/X86/Android.mk b/lib/Target/X86/Android.mk
index 2272632..cf7ea17 100644
--- a/lib/Target/X86/Android.mk
+++ b/lib/Target/X86/Android.mk
@@ -3,13 +3,14 @@
 mcld_x86_target_SRC_FILES := \
   X86Diagnostic.cpp \
   X86ELFDynamic.cpp \
-  X86ELFSectLinker.cpp  \
+  X86ELFMCLinker.cpp \
+  X86Emulation.cpp  \
   X86GOT.cpp  \
   X86GOTPLT.cpp  \
   X86LDBackend.cpp  \
+  X86MCLinker.cpp  \
   X86PLT.cpp  \
   X86RelocationFactory.cpp  \
-  X86SectLinker.cpp \
   X86TargetMachine.cpp
 
 # For the host
diff --git a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
index afe349e..0985c02 100644
--- a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
+++ b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
@@ -13,7 +13,7 @@
 
 mcld::Target TheX86Target;
 
-extern "C" void LLVMInitializeX86LDTargetInfo() {
+extern "C" void MCLDInitializeX86LDTargetInfo() {
   // register into mcld::TargetRegistry
   mcld::RegisterTarget X(TheX86Target, "x86");
 }
diff --git a/lib/Target/X86/X86Diagnostic.cpp b/lib/Target/X86/X86Diagnostic.cpp
index 98f0234..7191596 100644
--- a/lib/Target/X86/X86Diagnostic.cpp
+++ b/lib/Target/X86/X86Diagnostic.cpp
@@ -31,7 +31,7 @@
 
 //==========================
 // InitializeX86Diagnostic
-extern "C" void LLVMInitializeX86DiagnosticLineInfo() {
+extern "C" void MCLDInitializeX86DiagnosticLineInfo() {
   // Register the linker frontend
   mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheX86Target, createX86DiagLineInfo);
 }
diff --git a/lib/Target/X86/X86ELFMCLinker.cpp b/lib/Target/X86/X86ELFMCLinker.cpp
new file mode 100644
index 0000000..868d61c
--- /dev/null
+++ b/lib/Target/X86/X86ELFMCLinker.cpp
@@ -0,0 +1,23 @@
+//===- X86ELFMCLinker.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86ELFMCLinker.h"
+#include <mcld/LinkerConfig.h>
+
+using namespace mcld;
+
+X86ELFMCLinker::X86ELFMCLinker(LinkerConfig& pConfig,
+                               mcld::Module& pModule,
+                               MemoryArea& pOutput)
+  : ELFMCLinker(pConfig, pModule, pOutput) {
+}
+
+X86ELFMCLinker::~X86ELFMCLinker()
+{
+}
+
diff --git a/lib/Target/X86/X86ELFMCLinker.h b/lib/Target/X86/X86ELFMCLinker.h
new file mode 100644
index 0000000..173f7dc
--- /dev/null
+++ b/lib/Target/X86/X86ELFMCLinker.h
@@ -0,0 +1,39 @@
+//===- X86ELFMCLinker.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef X86_ELFSECTLINKER_H
+#define X86_ELFSECTLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/ELFMCLinker.h>
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+
+/** \class X86ELFMCLinker
+ *  \brief X86ELFMCLinker sets up the environment for linking.
+ *
+ *  \see
+ */
+class X86ELFMCLinker : public ELFMCLinker
+{
+public:
+  X86ELFMCLinker(LinkerConfig& pConfig,
+                 mcld::Module& pModule,
+                 MemoryArea& pOutput);
+
+  ~X86ELFMCLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86ELFSectLinker.cpp b/lib/Target/X86/X86ELFSectLinker.cpp
deleted file mode 100644
index 009293c..0000000
--- a/lib/Target/X86/X86ELFSectLinker.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- X86ELFSectLinker.cpp -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "X86ELFSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-X86ELFSectLinker::X86ELFSectLinker(SectLinkerOption &pOption,
-                                   TargetLDBackend &pLDBackend)
-  : SectLinker(pOption,
-               pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attibutes
-  info.attrFactory().constraint().enableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().setWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-
-}
-
-X86ELFSectLinker::~X86ELFSectLinker()
-{
-}
-
diff --git a/lib/Target/X86/X86ELFSectLinker.h b/lib/Target/X86/X86ELFSectLinker.h
deleted file mode 100644
index 5e7abfd..0000000
--- a/lib/Target/X86/X86ELFSectLinker.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- X86ELFSectLinker.h -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef X86_ELFSECTLINKER_H
-#define X86_ELFSECTLINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/CodeGen/SectLinker.h>
-
-namespace mcld
-{
-
-/** \class X86ELFSectLinker
- *  \brief X86ELFSectLinker sets up the environment for linking.
- *
- *  \see
- */
-class X86ELFSectLinker : public SectLinker
-{
-public:
-  X86ELFSectLinker(SectLinkerOption &pOption,
-                   mcld::TargetLDBackend &pLDBackend);
-
-  ~X86ELFSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/X86/X86Emulation.cpp b/lib/Target/X86/X86Emulation.cpp
new file mode 100644
index 0000000..74b7e47
--- /dev/null
+++ b/lib/Target/X86/X86Emulation.cpp
@@ -0,0 +1,60 @@
+//===- X86Emulation.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86.h"
+#include <mcld/LinkerConfig.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/Support/TargetRegistry.h>
+
+namespace mcld {
+
+static bool MCLDEmulateX86ELF(LinkerConfig& pConfig)
+{
+  if (!MCLDEmulateELF(pConfig))
+    return false;
+
+  // set up target-dependent constraints of attributes
+  pConfig.attribute().constraint().enableWholeArchive();
+  pConfig.attribute().constraint().enableAsNeeded();
+  pConfig.attribute().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  pConfig.attribute().predefined().unsetWholeArchive();
+  pConfig.attribute().predefined().unsetAsNeeded();
+  pConfig.attribute().predefined().setDynamic();
+  return true;
+}
+
+//===----------------------------------------------------------------------===//
+// emulateX86LD - the help function to emulate X86 ld
+//===----------------------------------------------------------------------===//
+bool emulateX86LD(const std::string& pTriple, LinkerConfig& pConfig)
+{
+  llvm::Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+    return false;
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+    return false;
+  }
+
+  return MCLDEmulateX86ELF(pConfig);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// X86Emulation
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeX86Emulation() {
+  // Register the emulation
+  mcld::TargetRegistry::RegisterEmulation(mcld::TheX86Target, mcld::emulateX86LD);
+}
+
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
index 518cc36..ae28ea7 100644
--- a/lib/Target/X86/X86GOT.cpp
+++ b/lib/Target/X86/X86GOT.cpp
@@ -8,13 +8,8 @@
 //===----------------------------------------------------------------------===//
 #include "X86GOT.h"
 
-#include <new>
-
-#include <llvm/Support/Casting.h>
-
 #include <mcld/LD/LDFileFormat.h>
 #include <mcld/LD/SectionData.h>
-#include <mcld/Support/MsgHandling.h>
 
 namespace {
   const size_t X86GOTEntrySize = 4;
@@ -25,9 +20,8 @@
 //===----------------------------------------------------------------------===//
 // X86GOT
 //===----------------------------------------------------------------------===//
-X86GOT::X86GOT(LDSection& pSection, SectionData& pSectionData)
-             : GOT(pSection, pSectionData, X86GOTEntrySize),
-               m_GOTIterator(), m_fIsVisit(false)
+X86GOT::X86GOT(LDSection& pSection)
+             : GOT(pSection, X86GOTEntrySize)
 {
 }
 
@@ -35,63 +29,3 @@
 {
 }
 
-void X86GOT::reserveEntry(size_t pNum)
-{
-  GOTEntry* Entry = 0;
-
-  for (size_t i = 0; i < pNum; i++) {
-    Entry = new (std::nothrow) GOTEntry(0, X86GOTEntrySize,
-                                        &m_SectionData);
-
-    if (!Entry)
-      fatal(diag::fail_allocate_memory_got);
-
-    m_Section.setSize(m_Section.size() + X86GOTEntrySize);
-  }
-}
-
-
-GOTEntry* X86GOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
-{
-  // first time visit this function, set m_GOTIterator
-  if(!m_fIsVisit) {
-    assert( !m_SectionData.getFragmentList().empty() &&
-             "DynRelSection contains no entries.");
-    m_GOTIterator = m_SectionData.getFragmentList().begin();
-    m_fIsVisit = true;
-  }
-
-
-  GOTEntry *&Entry = m_GOTMap[&pInfo];
-  pExist = 1;
-
-  if (!Entry) {
-    pExist = 0;
-    assert(m_GOTIterator != m_SectionData.getFragmentList().end()
-             && "The number of GOT Entries and ResolveInfo doesn't match!");
-    Entry = llvm::cast<GOTEntry>(&(*m_GOTIterator));
-    ++m_GOTIterator;
-  }
-  return Entry;
-}
-
-X86GOT::iterator X86GOT::begin()
-{
-  return m_SectionData.getFragmentList().begin();
-}
-
-X86GOT::const_iterator X86GOT::begin() const
-{
-  return m_SectionData.getFragmentList().begin();
-}
-
-X86GOT::iterator X86GOT::end()
-{
-  return m_SectionData.getFragmentList().end();
-}
-
-X86GOT::const_iterator X86GOT::end() const
-{
-  return m_SectionData.getFragmentList().end();
-}
-
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
index 91cc3e8..a027dc7 100644
--- a/lib/Target/X86/X86GOT.h
+++ b/lib/Target/X86/X86GOT.h
@@ -12,14 +12,12 @@
 #include <gtest.h>
 #endif
 
-#include "X86PLT.h"
-
 #include <mcld/Target/GOT.h>
-#include <mcld/LD/SectionData.h>
 
-namespace mcld
-{
+namespace mcld {
+
 class LDSection;
+class SectionData;
 
 /** \class X86GOT
  *  \brief X86 Global Offset Table.
@@ -27,38 +25,10 @@
 
 class X86GOT : public GOT
 {
-  typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
-
 public:
-  typedef SectionData::iterator iterator;
-  typedef SectionData::const_iterator const_iterator;
-
-public:
-  X86GOT(LDSection& pSection, SectionData& pSectionData);
+  X86GOT(LDSection& pSection);
 
   ~X86GOT();
-
-  //Reserve general GOT entries.
-  void reserveEntry(size_t pNum = 1);
-
-  GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
-
-  iterator begin();
-
-  const_iterator begin() const;
-
-  iterator end();
-
-  const_iterator end() const;
-
-private:
-  /// m_GOTIterator - point to the first valid entry in GOT list
-  iterator m_GOTIterator;
-
-  /// m_fIsVisit - first time visit the function getEntry() or not
-  bool m_fIsVisit;
-
-  SymbolIndexMapType m_GOTMap;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index 49f3449..b4e0ffe 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -6,13 +6,14 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include "X86GOTPLT.h"
+#include "X86PLT.h"
 
 #include <new>
 
 #include <llvm/Support/Casting.h>
 
+#include <mcld/LD/LDSection.h>
 #include <mcld/LD/LDFileFormat.h>
 #include <mcld/Support/MsgHandling.h>
 
@@ -25,114 +26,45 @@
 //===----------------------------------------------------------------------===//
 // X86GOTPLT
 //===----------------------------------------------------------------------===//
-X86GOTPLT::X86GOTPLT(LDSection& pSection, SectionData& pSectionData)
-  : GOT(pSection, pSectionData, X86GOTPLTEntrySize), m_GOTPLTIterator()
+X86GOTPLT::X86GOTPLT(LDSection& pSection)
+  : GOT(pSection, X86GOTPLTEntrySize)
 {
-  GOTEntry* Entry = 0;
+  // Create GOT0 entries
+  reserve(X86GOTPLT0Num);
 
-  // Create GOT0 entries.
-  for (size_t i = 0; i < X86GOTPLT0Num; i++) {
-    Entry = new (std::nothrow) GOTEntry(0, X86GOTPLTEntrySize,
-                                        &m_SectionData);
-
-    if (!Entry)
-      fatal(diag::fail_allocate_memory_got);
-
-    m_Section.setSize(m_Section.size() + X86GOTPLTEntrySize);
+  // Skip GOT0 entries
+  for (size_t i = 0; i < X86GOTPLT0Num; ++i) {
+    consume();
   }
-
-  // Skip GOT0 entries.
-  iterator it = m_SectionData.begin();
-
-  for (size_t i = 1; i < X86GOTPLT0Num; ++i) {
-    assert((it != m_SectionData.end()) &&
-           "Generation of GOT0 entries is incomplete!");
-
-    ++it;
-  }
-
-  m_GOTPLTIterator = it;
 }
 
 X86GOTPLT::~X86GOTPLT()
 {
 }
 
-X86GOTPLT::iterator X86GOTPLT::begin()
+bool X86GOTPLT::hasGOT1() const
 {
-  return m_SectionData.begin();
-}
-
-X86GOTPLT::const_iterator X86GOTPLT::begin() const
-{
-  return m_SectionData.begin();
-}
-
-X86GOTPLT::iterator X86GOTPLT::end()
-{
-  return m_SectionData.end();
-}
-
-X86GOTPLT::const_iterator X86GOTPLT::end() const
-{
-  return m_SectionData.end();
+  return (m_SectionData->size() > X86GOTPLT0Num);
 }
 
 void X86GOTPLT::applyGOT0(uint64_t pAddress)
 {
-  llvm::cast<GOTEntry>
-    (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
+  llvm::cast<Entry>
+    (*(m_SectionData->getFragmentList().begin())).setContent(pAddress);
 }
 
-void X86GOTPLT::reserveEntry(size_t pNum)
-{
-  GOTEntry* got_entry = NULL;
-  for (size_t i = 0; i < pNum; ++i) {
-    got_entry = new GOTEntry(0, getEntrySize(),&(getSectionData()));
-    if (!got_entry)
-      fatal(diag::fail_allocate_memory_got);
-
-    m_Section.setSize(m_Section.size() + getEntrySize());
-  }
-}
-
-void X86GOTPLT::applyAllGOTPLT(uint64_t pPLTBase,
-                               unsigned int pPLT0Size,
-                               unsigned int pPLT1Size)
+void X86GOTPLT::applyAllGOTPLT(const X86PLT& pPLT)
 {
   iterator it = begin();
   // skip GOT0
   for (size_t i = 0; i < X86GOTPLT0Num; ++i)
     ++it;
   // address of corresponding plt entry
-  uint64_t plt_addr = pPLTBase + pPLT0Size;
+  uint64_t plt_addr = pPLT.addr() + pPLT.getPLT0Size();
   for (; it != end() ; ++it) {
-    llvm::cast<GOTEntry>(*it).setContent(plt_addr + 6);
-    plt_addr += pPLT1Size;
+    llvm::cast<Entry>(*it).setContent(plt_addr + 6);
+    plt_addr += pPLT.getPLT1Size();
   }
 }
 
-GOTEntry*& X86GOTPLT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
-{
-  return m_GOTPLTMap[&pSymbol];
-}
-
-GOTEntry* X86GOTPLT::getEntry(const ResolveInfo& pInfo, bool& pExist)
-{
-  GOTEntry *&Entry = m_GOTPLTMap[&pInfo];
-  pExist = 1;
-
-  if (!Entry) {
-    pExist = 0;
-
-    ++m_GOTPLTIterator;
-    assert(m_GOTPLTIterator != m_SectionData.getFragmentList().end()
-           && "The number of GOT Entries and ResolveInfo doesn't match!");
-
-    Entry = llvm::cast<GOTEntry>(&(*m_GOTPLTIterator));
-  }
-
-  return Entry;
-}
-
 } //end mcld namespace
diff --git a/lib/Target/X86/X86GOTPLT.h b/lib/Target/X86/X86GOTPLT.h
index 7ca695b..b2fa65a 100644
--- a/lib/Target/X86/X86GOTPLT.h
+++ b/lib/Target/X86/X86GOTPLT.h
@@ -15,10 +15,10 @@
 #include <llvm/ADT/DenseMap.h>
 
 #include <mcld/Target/GOT.h>
-#include <mcld/LD/SectionData.h>
 
-namespace mcld
-{
+namespace mcld {
+
+class X86PLT;
 class LDSection;
 
 const unsigned int X86GOTPLT0Num = 3;
@@ -28,44 +28,17 @@
  */
 class X86GOTPLT : public GOT
 {
-  typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
-
 public:
-  typedef SectionData::iterator iterator;
-  typedef SectionData::const_iterator const_iterator;
-
-public:
-  X86GOTPLT(LDSection &pSection, SectionData& pSectionData);
+  X86GOTPLT(LDSection &pSection);
 
   ~X86GOTPLT();
 
-  iterator begin();
+  // hasGOT1 - return if this section has any GOT1 entry
+  bool hasGOT1() const;
 
-  const_iterator begin() const;
-
-  iterator end();
-
-  const_iterator end() const;
-
-// For GOT0
-public:
   void applyGOT0(uint64_t pAddress);
 
-// For GOTPLT
-public:
-  void reserveEntry(size_t pNum = 1);
-
-  GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
-
-  void applyAllGOTPLT(uint64_t pPLTBase,
-                      unsigned int pPLT0Size,
-                      unsigned int pPLT1Size);
-
-  GOTEntry*& lookupGOTPLTMap(const ResolveInfo& pSymbol);
-
-private:
-  iterator m_GOTPLTIterator;
-  SymbolIndexMapType m_GOTPLTMap;
+  void applyAllGOTPLT(const X86PLT& pPLT);
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index d02e621..987daec 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -6,7 +6,6 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include "X86.h"
 #include "X86ELFDynamic.h"
 #include "X86LDBackend.h"
@@ -15,22 +14,26 @@
 #include <llvm/ADT/Triple.h>
 #include <llvm/Support/Casting.h>
 
-#include <mcld/LD/SectionMap.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.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 <cstring>
 
 using namespace mcld;
 
-X86GNULDBackend::X86GNULDBackend()
-  : m_pRelocFactory(NULL),
+//===----------------------------------------------------------------------===//
+// X86GNULDBackend
+//===----------------------------------------------------------------------===//
+X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig)
+  : GNULDBackend(pConfig),
+    m_pRelocFactory(NULL),
     m_pGOT(NULL),
     m_pPLT(NULL),
     m_pGOTPLT(NULL),
@@ -42,20 +45,13 @@
 
 X86GNULDBackend::~X86GNULDBackend()
 {
-  if (NULL != m_pRelocFactory)
-    delete m_pRelocFactory;
-  if (NULL != m_pGOT)
-    delete m_pGOT;
-  if (NULL != m_pPLT)
-    delete m_pPLT;
-  if (NULL != m_pGOTPLT)
-    delete m_pGOTPLT;
-  if (NULL !=m_pRelDyn)
-    delete m_pRelDyn;
-  if (NULL != m_pRelPLT)
-    delete m_pRelPLT;
-  if (NULL != m_pDynamic)
-    delete m_pDynamic;
+  delete m_pRelocFactory;
+  delete m_pGOT;
+  delete m_pPLT;
+  delete m_pGOTPLT;
+  delete m_pRelDyn;
+  delete m_pRelPLT;
+  delete m_pDynamic;
 }
 
 RelocationFactory* X86GNULDBackend::getRelocFactory()
@@ -64,28 +60,47 @@
   return m_pRelocFactory;
 }
 
-bool X86GNULDBackend::initRelocFactory(const MCLinker& pLinker)
+bool X86GNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
 {
   if (NULL == m_pRelocFactory) {
     m_pRelocFactory = new X86RelocationFactory(1024, *this);
-    m_pRelocFactory->setLayout(pLinker.getLayout());
+    m_pRelocFactory->setFragmentLinker(pLinker);
   }
   return true;
 }
 
-void X86GNULDBackend::doPreLayout(const Output& pOutput,
-                                  const MCLDInfo& pInfo,
-                                  MCLinker& pLinker)
+void X86GNULDBackend::doPreLayout(FragmentLinker& pLinker)
 {
-  // when building shared object, the .got section is needed
-  if (Output::DynObj == pOutput.type() && (NULL == m_pGOTPLT)) {
-    createX86GOTPLT(pLinker, pOutput);
+  // set .got.plt size
+  // when building shared object, the .got section is must
+  if (LinkerConfig::Object != config().codeGenType()) {
+    if (LinkerConfig::DynObj == config().codeGenType() ||
+        m_pGOTPLT->hasGOT1() ||
+        NULL != m_pGOTSymbol) {
+      m_pGOTPLT->finalizeSectionSize();
+      defineGOTSymbol(pLinker);
+    }
+
+    // set .got size
+    if (!m_pGOT->empty())
+      m_pGOT->finalizeSectionSize();
+
+    // set .plt size
+    if (m_pPLT->hasPLT1())
+      m_pPLT->finalizeSectionSize();
+
+    // set .rel.dyn size
+    if (!m_pRelDyn->empty())
+      m_pRelDyn->finalizeSectionSize();
+
+    // set .rel.plt size
+    if (!m_pRelPLT->empty())
+      m_pRelPLT->finalizeSectionSize();
   }
 }
 
-void X86GNULDBackend::doPostLayout(const Output& pOutput,
-                                   const MCLDInfo& pInfo,
-                                   MCLinker& pLinker)
+void X86GNULDBackend::doPostLayout(Module& pModule,
+                                   FragmentLinker& pLinker)
 {
 }
 
@@ -107,26 +122,11 @@
   return *m_pDynamic;
 }
 
-void X86GNULDBackend::createX86GOT(MCLinker& pLinker, const Output& pOutput)
+void X86GNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
 {
-  // get .got LDSection and create SectionData
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  LDSection& got = file_format->getGOT();
-  m_pGOT = new X86GOT(got, pLinker.getOrCreateSectData(got));
-}
-
-void X86GNULDBackend::createX86GOTPLT(MCLinker& pLinker, const Output& pOutput)
-{
-  // get .got.plt LDSection and create SectionData
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  LDSection& gotplt = file_format->getGOTPLT();
-  m_pGOTPLT = new X86GOTPLT(gotplt, pLinker.getOrCreateSectData(gotplt));
-
-  // define symbol _GLOBAL_OFFSET_TABLE_ when .got.plt create
+  // define symbol _GLOBAL_OFFSET_TABLE_
   if (m_pGOTSymbol != NULL) {
-    pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
+    pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
                      ResolveInfo::Object,
@@ -134,12 +134,11 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
-                                                         0x0),
+                     FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
                      ResolveInfo::Hidden);
   }
   else {
-    m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+    m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
                      ResolveInfo::Object,
@@ -147,81 +146,43 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
-                                                          0x0),
+                     FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
                      ResolveInfo::Hidden);
   }
 }
 
-void X86GNULDBackend::createX86PLTandRelPLT(MCLinker& pLinker,
-                                            const Output& pOutput)
-{
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  LDSection& plt = file_format->getPLT();
-  LDSection& relplt = file_format->getRelPlt();
-  assert(m_pGOTPLT != NULL);
-  // create SectionData and X86PLT
-  m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOTPLT, pOutput);
-
-  // set info of .rel.plt to .plt
-  relplt.setLink(&plt);
-  // create SectionData and X86RelDynSection
-  m_pRelPLT = new OutputRelocSection(relplt,
-                                     pLinker.getOrCreateSectData(relplt),
-                                     8);
-}
-
-void X86GNULDBackend::createX86RelDyn(MCLinker& pLinker,
-                                      const Output& pOutput)
-{
-  // get .rel.dyn LDSection and create SectionData
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
-
-  LDSection& reldyn = file_format->getRelDyn();
-  // create SectionData and X86RelDynSection
-  m_pRelDyn = new OutputRelocSection(reldyn,
-                                     pLinker.getOrCreateSectData(reldyn),
-                                     8);
-}
-
 void X86GNULDBackend::addCopyReloc(ResolveInfo& pSym)
 {
-  bool exist;
-  Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
+  Relocation& rel_entry = *m_pRelDyn->consumeEntry();
   rel_entry.setType(llvm::ELF::R_386_COPY);
   assert(pSym.outSymbol()->hasFragRef());
   rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
   rel_entry.setSymInfo(&pSym);
 }
 
-LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(MCLinker& pLinker,
+/// defineSymbolforCopyReloc
+/// For a symbol needing copy relocation, define a copy symbol in the BSS
+/// section and all other reference to this symbol should refer to this
+/// copy.
+/// @note This is executed at `scan relocation' stage.
+LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(FragmentLinker& pLinker,
                                                     const ResolveInfo& pSym)
 {
-  // For a symbol needing copy relocation, define a copy symbol in the BSS
-  // section and all other reference to this symbol should refer to this
-  // copy.
-
   // get or create corresponding BSS LDSection
   LDSection* bss_sect_hdr = NULL;
-  if (ResolveInfo::ThreadLocal == pSym.type()) {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
-                                   ".tbss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
-  else {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
+  ELFFileFormat* file_format = getOutputFormat();
+  if (ResolveInfo::ThreadLocal == pSym.type())
+    bss_sect_hdr = &file_format->getTBSS();
+  else
+    bss_sect_hdr = &file_format->getBSS();
 
   // get or create corresponding BSS SectionData
   assert(NULL != bss_sect_hdr);
-  SectionData& bss_section = pLinker.getOrCreateSectData(
-                                     *bss_sect_hdr);
+  SectionData* bss_section = NULL;
+  if (bss_sect_hdr->hasSectionData())
+    bss_section = bss_sect_hdr->getSectionData();
+  else
+    bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr);
 
   // Determine the alignment by the symbol value
   // FIXME: here we use the largest alignment
@@ -229,9 +190,9 @@
 
   // allocate space in BSS for the copy symbol
   Fragment* frag = new FillFragment(0x0, 1, pSym.size());
-  uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                     bss_section,
-                                                     addralign);
+  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
@@ -240,7 +201,8 @@
     binding = ResolveInfo::Global;
 
   // Define the copy symbol in the bss section and resolve it
-  LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+  LDSymbol* cpy_sym =
+           pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
                       pSym.name(),
                       false,
                       (ResolveInfo::Type)pSym.type(),
@@ -248,44 +210,29 @@
                       binding,
                       pSym.size(),  // size
                       0x0,          // value
-                      pLinker.getLayout().getFragmentRef(*frag, 0x0),
+                      FragmentRef::Create(*frag, 0x0),
                       (ResolveInfo::Visibility)pSym.other());
 
   return *cpy_sym;
 }
 
-void X86GNULDBackend::updateAddend(Relocation& pReloc,
-                                   const LDSymbol& pInputSym,
-                                   const Layout& pLayout) const
-{
-  // Update value keep in addend if we meet a section symbol
-  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
-    pReloc.setAddend(pLayout.getOutputOffset(
-                     *pInputSym.fragRef()) + pReloc.addend());
-  }
-}
-
 void X86GNULDBackend::scanLocalReloc(Relocation& pReloc,
-                                     const LDSymbol& pInputSym,
-                                     MCLinker& pLinker,
-                                     const MCLDInfo& pLDInfo,
-                                     const Output& pOutput)
+                                     FragmentLinker& pLinker,
+                                     Module& pModule,
+                                     const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
 
-  updateAddend(pReloc, pInputSym, pLinker.getLayout());
-
   switch(pReloc.type()){
 
     case llvm::ELF::R_386_32:
+    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 (isOutputPIC(pOutput, pLDInfo)) {
-        // create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createX86RelDyn(pLinker, pOutput);
+      if (pLinker.isOutputPIC()) {
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set Rel bit
         rsym->setReserved(rsym->reserved() | ReserveRel);
@@ -294,12 +241,112 @@
 
     case llvm::ELF::R_386_GOTOFF:
     case llvm::ELF::R_386_GOTPC:
-      // A GOT section is needed
-      if (NULL == m_pGOT)
-        createX86GOT(pLinker, pOutput);
+      // FIXME: A GOT section is needed
+      return;
+
+    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))
+        return;
+      // FIXME: check STT_GNU_IFUNC symbol
+      m_pGOT->reserve();
+      // 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()) {
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set GOTRel bit
+        rsym->setReserved(rsym->reserved() | GOTRel);
+        return;
+      }
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
 
     case llvm::ELF::R_386_PC32:
+    case llvm::ELF::R_386_PC16:
+    case llvm::ELF::R_386_PC8:
+      return;
+
+    case llvm::ELF::R_386_TLS_GD: {
+      // FIXME: no linker optimization for TLS relocation
+      if (rsym->reserved() & GOTRel)
+        return;
+      m_pGOT->reserve(2);
+      // reserve an rel entry
+      m_pRelDyn->reserveEntry(*m_pRelocFactory);
+      // 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
+      // need to define that section symbol here
+      ELFFileFormat* file_format = getOutputFormat();
+      const LDSection* sym_sect =
+               &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
+      if (&file_format->getTData() == sym_sect) {
+        if (NULL == f_pTDATA)
+          f_pTDATA = pModule.getSectionSymbolSet().get(*sym_sect);
+      }
+      else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) {
+        if (NULL == f_pTBSS)
+          f_pTBSS = pModule.getSectionSymbolSet().get(*sym_sect);
+      }
+      else
+        error(diag::invalid_tls) << rsym->name() << sym_sect->name();
+      return;
+    }
+
+    case llvm::ELF::R_386_TLS_LDM:
+      getTLSModuleID();
+      return;
+
+    case llvm::ELF::R_386_TLS_LDO_32:
+      return;
+
+    case llvm::ELF::R_386_TLS_IE:
+      setHasStaticTLS();
+      // if buildint shared object, a RELATIVE dynamic relocation is needed
+      if (LinkerConfig::DynObj == config().codeGenType()) {
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+      }
+      if (rsym->reserved() & GOTRel)
+        return;
+      // reserve got and dyn relocation entries for tp-relative offset
+      m_pGOT->reserve();
+      m_pRelDyn->reserveEntry(*m_pRelocFactory);
+      // set GOTRel bit
+      rsym->setReserved(rsym->reserved() | GOTRel);
+      m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
+      return;
+
+    case llvm::ELF::R_386_TLS_GOTIE:
+      setHasStaticTLS();
+      if (rsym->reserved() & GOTRel)
+        return;
+      // reserve got and dyn relocation entries for tp-relative offset
+      m_pGOT->reserve();
+      m_pRelDyn->reserveEntry(*m_pRelocFactory);
+      // set GOTRel bit
+      rsym->setReserved(rsym->reserved() | GOTRel);
+      m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
+      return;
+
+    case llvm::ELF::R_386_TLS_LE:
+    case llvm::ELF::R_386_TLS_LE_32:
+      setHasStaticTLS();
+      // if buildint shared object, a dynamic relocation is needed
+      if (LinkerConfig::DynObj == config().codeGenType()) {
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+        // the target symbol of the dynamic relocation is rsym, so we need to
+        // emit it into .dynsym
+        assert(NULL != rsym->outSymbol());
+        m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
+      }
       return;
 
     default:
@@ -310,47 +357,39 @@
 }
 
 void X86GNULDBackend::scanGlobalReloc(Relocation& pReloc,
-                                      const LDSymbol& pInputSym,
-                                      MCLinker& pLinker,
-                                      const MCLDInfo& pLDInfo,
-                                      const Output& pOutput)
+                                      FragmentLinker& pLinker,
+                                      Module& pModule,
+                                      const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
 
   switch(pReloc.type()) {
     case llvm::ELF::R_386_32:
+    case llvm::ELF::R_386_16:
+    case llvm::ELF::R_386_8:
       // Absolute relocation type, symbol may needs PLT entry or
       // dynamic relocation entry
-      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+      if (symbolNeedsPLT(pLinker, *rsym)) {
         // create plt for this symbol if it does not have one
         if (!(rsym->reserved() & ReservePLT)){
-          // Create .got section if it dosen't exist
-          if (NULL == m_pGOTPLT)
-            createX86GOTPLT(pLinker, pOutput);
-          // create .plt and .rel.plt if not exist
-          if (NULL == m_pPLT)
-            createX86PLTandRelPLT(pLinker, pOutput);
           // Symbol needs PLT entry, we need to reserve a PLT entry
           // and the corresponding GOT and dynamic relocation entry
           // in .got and .rel.plt. (GOT entry will be reserved simultaneously
           // when calling X86PLT->reserveEntry())
           m_pPLT->reserveEntry();
+          m_pGOTPLT->reserve();
           m_pRelPLT->reserveEntry(*m_pRelocFactory);
           // set PLT bit
           rsym->setReserved(rsym->reserved() | ReservePLT);
         }
       }
 
-      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
-                            pLDInfo, pOutput, true)) {
+      if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
+                                                                       true)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
-        // create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createX86RelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
-                          pOutput)) {
+        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
         }
@@ -363,9 +402,7 @@
 
     case llvm::ELF::R_386_GOTOFF:
     case llvm::ELF::R_386_GOTPC: {
-      // A GOT section is needed
-      if (NULL == m_pGOT)
-        createX86GOT(pLinker, pOutput);
+      // FIXME: A GOT section is needed
       return;
     }
 
@@ -376,24 +413,23 @@
       if (rsym->reserved() & ReservePLT)
         return;
 
+      // if the symbol's value can be decided at link time, then no need plt
+      if (symbolFinalValueIsKnown(pLinker, *rsym))
+        return;
+
       // if symbol is defined in the ouput file and it's not
       // preemptible, no need plt
       if (rsym->isDefine() && !rsym->isDyn() &&
-         !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
+         !isSymbolPreemptible(*rsym)) {
         return;
       }
 
-      // Create .got section if it dosen't exist
-      if (NULL == m_pGOTPLT)
-         createX86GOTPLT(pLinker, pOutput);
-      // create .plt and .rel.plt if not exist
-      if (NULL == m_pPLT)
-         createX86PLTandRelPLT(pLinker, pOutput);
       // Symbol needs PLT entry, we need to reserve a PLT entry
       // and the corresponding GOT and dynamic relocation entry
       // in .got and .rel.plt. (GOT entry will be reserved simultaneously
       // when calling X86PLT->reserveEntry())
       m_pPLT->reserveEntry();
+      m_pGOTPLT->reserve();
       m_pRelPLT->reserveEntry(*m_pRelocFactory);
       // set PLT bit
       rsym->setReserved(rsym->reserved() | ReservePLT);
@@ -404,16 +440,12 @@
       // return if we already create GOT for this symbol
       if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if (NULL == m_pGOT)
-        createX86GOT(pLinker, pOutput);
-      m_pGOT->reserveEntry();
+      m_pGOT->reserve();
       // 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 (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
-        // create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createX86RelDyn(pLinker, pOutput);
+      if (LinkerConfig::DynObj ==
+                   config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
         rsym->setReserved(rsym->reserved() | GOTRel);
@@ -424,37 +456,30 @@
       return;
 
     case llvm::ELF::R_386_PC32:
+    case llvm::ELF::R_386_PC16:
+    case llvm::ELF::R_386_PC8:
 
-      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput) &&
-          pOutput.type() != Output::DynObj) {
+      if (symbolNeedsPLT(pLinker, *rsym) &&
+                               LinkerConfig::DynObj != config().codeGenType()) {
         // create plt for this symbol if it does not have one
         if (!(rsym->reserved() & ReservePLT)){
-          // Create .got section if it dosen't exist
-          if (NULL == m_pGOTPLT)
-            createX86GOTPLT(pLinker, pOutput);
-          // create .plt and .rel.plt if not exist
-          if (NULL == m_pPLT)
-            createX86PLTandRelPLT(pLinker, pOutput);
           // Symbol needs PLT entry, we need to reserve a PLT entry
           // and the corresponding GOT and dynamic relocation entry
           // in .got and .rel.plt. (GOT entry will be reserved simultaneously
           // when calling X86PLT->reserveEntry())
           m_pPLT->reserveEntry();
+          m_pGOTPLT->reserve();
           m_pRelPLT->reserveEntry(*m_pRelocFactory);
           // set PLT bit
           rsym->setReserved(rsym->reserved() | ReservePLT);
         }
       }
 
-      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
-                            pLDInfo, pOutput, false)) {
+      if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
+                                                                      false)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
-        // create .rel.dyn section if not exist
-        if (NULL == m_pRelDyn)
-          createX86RelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
-                          pOutput)) {
+        if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
           LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
           addCopyReloc(*cpy_sym.resolveInfo());
         }
@@ -464,6 +489,63 @@
         }
       }
       return;
+
+    case llvm::ELF::R_386_TLS_GD: {
+      // FIXME: no linker optimization for TLS relocation
+      if (rsym->reserved() & GOTRel)
+        return;
+      // reserve two pairs of got entry and dynamic relocation
+      m_pGOT->reserve(2);
+      m_pRelDyn->reserveEntry(*m_pRelocFactory, 2);
+      // set GOTRel bit
+      rsym->setReserved(rsym->reserved() | GOTRel);
+      return;
+    }
+
+    case llvm::ELF::R_386_TLS_LDM:
+      getTLSModuleID();
+      return;
+
+    case llvm::ELF::R_386_TLS_LDO_32:
+      return;
+
+    case llvm::ELF::R_386_TLS_IE:
+      setHasStaticTLS();
+      // if buildint shared object, a RELATIVE dynamic relocation is needed
+      if (LinkerConfig::DynObj == config().codeGenType()) {
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+      }
+      if (rsym->reserved() & GOTRel)
+        return;
+      // reserve got and dyn relocation entries for tp-relative offset
+      m_pGOT->reserve();
+      m_pRelDyn->reserveEntry(*m_pRelocFactory);
+      // set GOTRel bit
+      rsym->setReserved(rsym->reserved() | GOTRel);
+      return;
+
+    case llvm::ELF::R_386_TLS_GOTIE:
+      setHasStaticTLS();
+      if (rsym->reserved() & GOTRel)
+        return;
+      // reserve got and dyn relocation entries for tp-relative offset
+      m_pGOT->reserve();
+      m_pRelDyn->reserveEntry(*m_pRelocFactory);
+      // set GOTRel bit
+      rsym->setReserved(rsym->reserved() | GOTRel);
+      return;
+
+    case llvm::ELF::R_386_TLS_LE:
+    case llvm::ELF::R_386_TLS_LE_32:
+      setHasStaticTLS();
+      // if buildint shared object, a dynamic relocation is needed
+      if (LinkerConfig::DynObj == config().codeGenType()) {
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+      }
+      return;
+
     default: {
       fatal(diag::unsupported_relocation) << (int)pReloc.type()
                                           << "mclinker@googlegroups.com";
@@ -473,56 +555,45 @@
 }
 
 void X86GNULDBackend::scanRelocation(Relocation& pReloc,
-                                     const LDSymbol& pInputSym,
-                                     MCLinker& pLinker,
-                                     const MCLDInfo& pLDInfo,
-                                     const Output& pOutput,
+                                     FragmentLinker& pLinker,
+                                     Module& pModule,
                                      const LDSection& pSection)
 {
+  if (LinkerConfig::Object == config().codeGenType())
+    return;
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
-  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
+  assert(NULL != rsym &&
+         "ResolveInfo of relocation not set while scanRelocation");
 
-  assert(NULL != pSection.getLink());
-  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
-    if (rsym->isLocal()) {
-      updateAddend(pReloc, pInputSym, pLinker.getLayout());
-    }
+  pReloc.updateAddend();
+  if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
     return;
-  }
 
-  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
+  // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation
   // entries should be created.
-  // FIXME: Below judgements concern only .so is generated as output
-  // FIXME: Below judgements concren nothing about TLS related relocation
+  if (rsym->isLocal()) // rsym is local
+    scanLocalReloc(pReloc, pLinker, pModule, pSection);
+  else // rsym is external
+    scanGlobalReloc(pReloc, pLinker, pModule, pSection);
 
-  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got.plt
-  // section is needed
-  if (NULL == m_pGOTPLT && NULL != m_pGOTSymbol) {
-    if (rsym == m_pGOTSymbol->resolveInfo()) {
-      createX86GOTPLT(pLinker, pOutput);
-    }
+  // check if we shoule issue undefined reference for the relocation target
+  // symbol
+  if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+    fatal(diag::undefined_reference) << rsym->name();
+
+  if ((rsym->reserved() & ReserveRel) != 0x0) {
+    // set hasTextRelSection if needed
+    checkAndSetHasTextRel(pSection);
   }
-
-  // rsym is local
-  if (rsym->isLocal())
-    scanLocalReloc(pReloc, pInputSym,  pLinker, pLDInfo, pOutput);
-
-  // rsym is external
-  else
-    scanGlobalReloc(pReloc, pInputSym ,pLinker, pLDInfo, pOutput);
-
 }
 
-uint64_t X86GNULDBackend::emitSectionData(const Output& pOutput,
-                                          const LDSection& pSection,
-                                          const MCLDInfo& pInfo,
-                                          const Layout& pLayout,
+uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
                                           MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  const ELFFileFormat* FileFormat = getOutputFormat(pOutput);
+  const ELFFileFormat* FileFormat = getOutputFormat();
   assert(FileFormat &&
          "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
 
@@ -536,7 +607,6 @@
 
     m_pPLT->applyPLT0();
     m_pPLT->applyPLT1();
-
     X86PLT::iterator it = m_pPLT->begin();
     unsigned int plt0_size = llvm::cast<X86PLT0>((*it)).getEntrySize();
 
@@ -560,12 +630,12 @@
 
     uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
 
-    GOTEntry* got = 0;
+    GOT::Entry* got = 0;
     EntrySize = m_pGOT->getEntrySize();
 
     for (X86GOT::iterator it = m_pGOT->begin(),
          ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
-      got = &(llvm::cast<GOTEntry>((*it)));
+      got = &(llvm::cast<GOT::Entry>((*it)));
       *buffer = static_cast<uint32_t>(got->getContent());
       RegionSize += EntrySize;
     }
@@ -574,15 +644,16 @@
   else if (&pSection == &(FileFormat->getGOTPLT())) {
     assert(m_pGOTPLT && "emitSectionData failed, m_pGOTPLT is NULL!");
     m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
+    m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
 
     uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
 
-    GOTEntry* got = 0;
+    GOT::Entry* got = 0;
     EntrySize = m_pGOTPLT->getEntrySize();
 
     for (X86GOTPLT::iterator it = m_pGOTPLT->begin(),
          ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
-      got = &(llvm::cast<GOTEntry>((*it)));
+      got = &(llvm::cast<GOT::Entry>((*it)));
       *buffer = static_cast<uint32_t>(got->getContent());
       RegionSize += EntrySize;
     }
@@ -595,6 +666,7 @@
   }
   return RegionSize;
 }
+
 uint32_t X86GNULDBackend::machine() const
 {
   return llvm::ELF::EM_386;
@@ -648,6 +720,27 @@
   return *m_pRelDyn;
 }
 
+// Create a GOT entry for the TLS module index
+GOT::Entry& X86GNULDBackend::getTLSModuleID()
+{
+  static GOT::Entry* got_entry = NULL;
+  if (NULL != got_entry)
+    return *got_entry;
+
+  // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
+  m_pGOT->reserve(2);
+  got_entry = m_pGOT->consume();
+  m_pGOT->consume()->setContent(0x0);
+
+  m_pRelDyn->reserveEntry(*m_pRelocFactory);
+  Relocation* rel_entry = m_pRelDyn->consumeEntry();
+  rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32);
+  rel_entry->targetRef().assign(*got_entry, 0x0);
+  rel_entry->setSymInfo(NULL);
+
+  return *got_entry;
+}
+
 OutputRelocSection& X86GNULDBackend::getRelPLT()
 {
   assert(NULL != m_pRelPLT && ".rel.plt section not exist");
@@ -661,20 +754,18 @@
 }
 
 unsigned int
-X86GNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr,
-                                       const MCLDInfo& pInfo) const
+X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
 {
-  const ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat();
 
   if (&pSectHdr == &file_format->getGOT()) {
-    if (pInfo.options().hasNow())
+    if (config().options().hasNow())
       return SHO_RELRO;
     return SHO_RELRO_LAST;
   }
 
   if (&pSectHdr == &file_format->getGOTPLT()) {
-    if (pInfo.options().hasNow())
+    if (config().options().hasNow())
       return SHO_RELRO;
     return SHO_NON_RELRO_FIRST;
   }
@@ -690,47 +781,80 @@
   return 32;
 }
 
-bool X86GNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
+void X86GNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
 {
-  return true;
+  if (LinkerConfig::Object != config().codeGenType()) {
+    ELFFileFormat* file_format = getOutputFormat();
+    // initialize .got
+    LDSection& got = file_format->getGOT();
+    m_pGOT = new X86GOT(got);
+
+    // initialize .got.plt
+    LDSection& gotplt = file_format->getGOTPLT();
+    m_pGOTPLT = new X86GOTPLT(gotplt);
+
+    // initialize .plt
+    LDSection& plt = file_format->getPLT();
+    m_pPLT = new X86PLT(plt,
+                        *m_pGOTPLT,
+                        config());
+
+    // initialize .rel.plt
+    LDSection& relplt = file_format->getRelPlt();
+    relplt.setLink(&plt);
+    m_pRelPLT = new OutputRelocSection(pModule,
+                                       relplt,
+                                       getRelEntrySize());
+    // initialize .rel.dyn
+    LDSection& reldyn = file_format->getRelDyn();
+    m_pRelDyn = new OutputRelocSection(pModule,
+                                       reldyn,
+                                       getRelEntrySize());
+  }
 }
 
-void X86GNULDBackend::initTargetSections(MCLinker& pLinker)
+void X86GNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
 {
-}
-
-void X86GNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
-{
-  // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
-  // same name in input
-  m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
-                   "_GLOBAL_OFFSET_TABLE_",
-                   false,
-                   ResolveInfo::Object,
-                   ResolveInfo::Define,
-                   ResolveInfo::Local,
-                   0x0,  // size
-                   0x0,  // value
-                   NULL, // FragRef
-                   ResolveInfo::Hidden);
+  if (LinkerConfig::Object != config().codeGenType()) {
+    // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
+    // same name in input
+    m_pGOTSymbol =
+      pLinker.defineSymbol<FragmentLinker::AsRefered,
+                           FragmentLinker::Resolve>("_GLOBAL_OFFSET_TABLE_",
+                                                    false,
+                                                    ResolveInfo::Object,
+                                                    ResolveInfo::Define,
+                                                    ResolveInfo::Local,
+                                                    0x0,  // size
+                                                    0x0,  // value
+                                                    FragmentRef::Null(), // FragRef
+                                                    ResolveInfo::Hidden);
+  }
 }
 
 /// finalizeSymbol - finalize the symbol value
-bool X86GNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+bool X86GNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
 {
   return true;
 }
 
+/// doCreateProgramHdrs - backend can implement this function to create the
+/// target-dependent segments
+void X86GNULDBackend::doCreateProgramHdrs(Module& pModule,
+                                          const FragmentLinker& pLinker)
+{
+  // TODO
+}
+
 namespace mcld {
 
 //===----------------------------------------------------------------------===//
 /// createX86LDBackend - the help funtion to create corresponding X86LDBackend
 ///
 TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget,
-                                    const std::string& pTriple)
+                                    const LinkerConfig& pConfig)
 {
-  Triple theTriple(pTriple);
-  if (theTriple.isOSDarwin()) {
+  if (pConfig.triple().isOSDarwin()) {
     assert(0 && "MachO linker is not supported yet");
     /**
     return new X86MachOLDBackend(createX86MachOArchiveReader,
@@ -738,7 +862,7 @@
                                createX86MachOObjectWriter);
     **/
   }
-  if (theTriple.isOSWindows()) {
+  if (pConfig.triple().isOSWindows()) {
     assert(0 && "COFF linker is not supported yet");
     /**
     return new X86COFFLDBackend(createX86COFFArchiveReader,
@@ -746,14 +870,15 @@
                                createX86COFFObjectWriter);
     **/
   }
-  return new X86GNULDBackend();
+  return new X86GNULDBackend(pConfig);
 }
 
 } // namespace of mcld
 
-//=============================
+//===----------------------------------------------------------------------===//
 // Force static initialization.
-extern "C" void LLVMInitializeX86LDBackend() {
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeX86LDBackend() {
   // Register the linker backend
   mcld::TargetRegistry::RegisterTargetLDBackend(TheX86Target, createX86LDBackend);
 }
diff --git a/lib/Target/X86/X86LDBackend.h b/lib/Target/X86/X86LDBackend.h
index 7264c40..fb3aa6b 100644
--- a/lib/Target/X86/X86LDBackend.h
+++ b/lib/Target/X86/X86LDBackend.h
@@ -19,6 +19,8 @@
 
 namespace mcld {
 
+class LinkerConfig;
+
 //===----------------------------------------------------------------------===//
 /// X86GNULDBackend - linker backend of X86 target of GNU ELF format
 ///
@@ -68,7 +70,8 @@
     PLTandRel    = 9
   };
 
-  X86GNULDBackend();
+public:
+  X86GNULDBackend(const LinkerConfig& pConfig);
 
   ~X86GNULDBackend();
 
@@ -91,17 +94,15 @@
 
   const X86PLT& getPLT() const;
 
+  GOT::Entry& getTLSModuleID();
+
   unsigned int bitclass() const;
 
   /// preLayout - Backend can do any needed modification before layout
-  void doPreLayout(const Output& pOutput,
-                   const MCLDInfo& pInfo,
-                   MCLinker& pLinker);
+  void doPreLayout(FragmentLinker& pLinker);
 
   /// postLayout -Backend can do any needed modification after layout
-  void doPostLayout(const Output& pOutput,
-                    const MCLDInfo& pInfo,
-                    MCLinker& pLinker);
+  void doPostLayout(Module& pModule, FragmentLinker& pLinker);
 
   /// dynamic - the dynamic section of the target machine.
   /// Use co-variant return type to return its own dynamic section.
@@ -122,16 +123,11 @@
   ///  - backend can maintain its own map<LDSection, table> to get the table
   /// from given LDSection.
   ///
-  /// @param pOutput - the output file
   /// @param pSection - the given LDSection
-  /// @param pInfo - all options in the command line.
   /// @param pLayout - for comouting the size of fragment
   /// @param pRegion - the region to write out data
   /// @return the size of the table in the file.
-  uint64_t emitSectionData(const Output& pOutput,
-                           const LDSection& pSection,
-                           const MCLDInfo& pInfo,
-                           const Layout& pLayout,
+  uint64_t emitSectionData(const LDSection& pSection,
                            MemoryRegion& pRegion) const;
 
   /// OSABI - the value of e_ident[EI_OSABI]
@@ -152,15 +148,12 @@
   uint64_t defaultTextSegmentAddr() const
   { return 0x08048000; }
 
-  /// initTargetSectionMap - initialize target dependent section mapping
-  bool initTargetSectionMap(SectionMap& pSectionMap);
-
   // initRelocFactory - create and initialize RelocationFactory
-  bool initRelocFactory(const MCLinker& pLinker);
+  bool initRelocFactory(const FragmentLinker& pLinker);
 
-  void initTargetSections(MCLinker& pLinker);
+  void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
 
-  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+  void initTargetSymbols(FragmentLinker& pLinker);
 
   /// scanRelocation - determine the empty entries are needed or not and create
   /// the empty entries if needed.
@@ -169,10 +162,8 @@
   /// - PLT entry (for .plt section)
   /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
   void scanRelocation(Relocation& pReloc,
-                      const LDSymbol& pInputSym,
-                      MCLinker& pLinker,
-                      const MCLDInfo& pLDInfo,
-                      const Output& pOutput,
+                      FragmentLinker& pLinker,
+                      Module& pModule,
                       const LDSection& pSection);
 
   OutputRelocSection& getRelDyn();
@@ -184,25 +175,21 @@
   const OutputRelocSection& getRelPLT() const;
 
   /// getTargetSectionOrder - compute the layout order of X86 target sections
-  unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr,
-                                     const MCLDInfo& pInfo) const;
+  unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
 
   /// finalizeTargetSymbols - finalize the symbol value
-  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+  bool finalizeTargetSymbols(FragmentLinker& pLinker);
 
 private:
   void scanLocalReloc(Relocation& pReloc,
-                      const LDSymbol& pInputSym,
-                      MCLinker& pLinker,
-                      const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+                      FragmentLinker& pLinker,
+                      Module& pModule,
+                      const LDSection& pSection);
 
   void scanGlobalReloc(Relocation& pReloc,
-                       const LDSymbol& pInputSym,
-                       MCLinker& pLinker,
-                       const MCLDInfo& pLDInfo,
-                       const Output& pOutput);
+                       FragmentLinker& pLinker,
+                       Module& pModule,
+                       const LDSection& pSection);
 
   /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
   /// @param pSym - A resolved copy symbol that defined in BSS section
@@ -211,17 +198,23 @@
   /// 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(MCLinker& pLinker,
+  LDSymbol& defineSymbolforCopyReloc(FragmentLinker& pLinker,
                                      const ResolveInfo& pSym);
 
-  void updateAddend(Relocation& pReloc,
-                    const LDSymbol& pInputSym,
-                    const Layout& pLayout) const;
+  void defineGOTSymbol(FragmentLinker& pLinker);
 
-  void createX86GOT(MCLinker& pLinker, const Output& pOutput);
-  void createX86GOTPLT(MCLinker& pLinker, const Output& pOutput);
-  void createX86PLTandRelPLT(MCLinker& pLinker, const Output& pOutput);
-  void createX86RelDyn(MCLinker& pLinker, const Output& pOutput);
+  /// 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
+  virtual void doCreateProgramHdrs(Module& pModule,
+                                   const FragmentLinker& pLinker);
 
 private:
   RelocationFactory* m_pRelocFactory;
diff --git a/lib/Target/X86/X86MCLinker.cpp b/lib/Target/X86/X86MCLinker.cpp
new file mode 100644
index 0000000..e55add3
--- /dev/null
+++ b/lib/Target/X86/X86MCLinker.cpp
@@ -0,0 +1,53 @@
+//===- X86MCLinker.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86.h"
+#include "X86ELFMCLinker.h"
+#include <mcld/Module.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <llvm/ADT/Triple.h>
+
+using namespace mcld;
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+/// createX86MCLinker - the help funtion to create corresponding X86MCLinker
+//===----------------------------------------------------------------------===//
+MCLinker* createX86MCLinker(const std::string &pTriple,
+                            LinkerConfig& pConfig,
+                            mcld::Module& pModule,
+                            MemoryArea& pOutput)
+{
+  Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+    return NULL;
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+    return NULL;
+  }
+
+  if (theTriple.isArch32Bit())
+    return new X86ELFMCLinker(pConfig, pModule, pOutput);
+
+  assert(0 && "X86_64 has not supported yet");
+  return NULL;
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// X86MCLinker
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeX86MCLinker() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterMCLinker(TheX86Target, createX86MCLinker);
+}
+
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index cbdb568..5b5ac58 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -9,12 +9,11 @@
 #include "X86GOTPLT.h"
 #include "X86PLT.h"
 
-#include <new>
-
 #include <llvm/Support/ELF.h>
 #include <llvm/Support/Casting.h>
 
-#include <mcld/MC/MCLDOutput.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Support/MsgHandling.h>
 
 //===----------------------------------------------------------------------===//
@@ -50,26 +49,26 @@
 
 namespace mcld {
 
-X86PLT0::X86PLT0(SectionData* pParent, unsigned int pSize)
-  : PLTEntry(pSize, pParent) { }
+X86PLT0::X86PLT0(SectionData& pParent, unsigned int pSize)
+  : PLT::Entry(pSize, pParent) { }
 
-X86PLT1::X86PLT1(SectionData* pParent, unsigned int pSize)
-  : PLTEntry(pSize, pParent) { }
+X86PLT1::X86PLT1(SectionData& pParent, unsigned int pSize)
+  : PLT::Entry(pSize, pParent) { }
 
 //===----------------------------------------------------------------------===//
 // X86PLT
 //===----------------------------------------------------------------------===//
 X86PLT::X86PLT(LDSection& pSection,
-               SectionData& pSectionData,
                X86GOTPLT &pGOTPLT,
-               const Output& pOutput)
-  : PLT(pSection, pSectionData),
+               const LinkerConfig& pConfig)
+  : PLT(pSection),
     m_GOTPLT(pGOTPLT),
-    m_PLTEntryIterator(),
-    m_Output(pOutput)
+    m_Config(pConfig)
 {
-  assert (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type());
-  if (Output::DynObj == pOutput.type()) {
+  assert(LinkerConfig::DynObj == m_Config.codeGenType() ||
+         LinkerConfig::Exec == m_Config.codeGenType());
+
+  if (LinkerConfig::DynObj == m_Config.codeGenType()) {
       m_PLT0 = x86_dyn_plt0;
       m_PLT1 = x86_dyn_plt1;
       m_PLT0Size = sizeof (x86_dyn_plt0);
@@ -81,62 +80,71 @@
       m_PLT0Size = sizeof (x86_exec_plt0);
       m_PLT1Size = sizeof (x86_exec_plt1);
   }
-  X86PLT0* plt0_entry = new X86PLT0(&m_SectionData, m_PLT0Size);
+  new X86PLT0(*m_SectionData, m_PLT0Size);
 
-  m_Section.setSize(m_Section.size() + plt0_entry->getEntrySize());
-
-  m_PLTEntryIterator = pSectionData.begin();
+  m_Last = m_SectionData->begin();
 }
 
 X86PLT::~X86PLT()
 {
 }
 
+void X86PLT::finalizeSectionSize()
+{
+  uint64_t size = 0;
+  // plt0 size
+  size = getPLT0()->getEntrySize();
+
+  // get first plt1 entry
+  X86PLT::iterator it = begin();
+  ++it;
+  if (end() != it) {
+    // plt1 size
+    X86PLT1* plt1 = &(llvm::cast<X86PLT1>(*it));
+    size += (m_SectionData->size() - 1) * plt1->getEntrySize();
+  }
+  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 X86PLT::hasPLT1() const
+{
+  return (m_SectionData->size() > 1);
+}
+
 void X86PLT::reserveEntry(size_t pNum)
 {
   X86PLT1* plt1_entry = 0;
 
   for (size_t i = 0; i < pNum; ++i) {
-    plt1_entry = new (std::nothrow) X86PLT1(&m_SectionData, m_PLT1Size);
+    plt1_entry = new (std::nothrow) X86PLT1(*m_SectionData, m_PLT1Size);
 
     if (!plt1_entry)
       fatal(diag::fail_allocate_memory_plt);
-
-    m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
-
-    // reserve corresponding entry in .got.plt
-    m_GOTPLT.reserveEntry(pNum);
   }
 }
 
-PLTEntry* X86PLT::getPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+PLT::Entry* X86PLT::consume()
 {
-   X86PLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
-
-   pExist = 1;
-
-   if (!PLTEntry) {
-     pExist = 0;
-
-     // This will skip PLT0.
-     ++m_PLTEntryIterator;
-     assert(m_PLTEntryIterator != m_SectionData.end() &&
-            "The number of PLT Entries and ResolveInfo doesn't match");
-     PLTEntry = llvm::cast<X86PLT1>(&(*m_PLTEntryIterator));
-   }
-   return PLTEntry;
+  // 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<X86PLT1>(&(*m_Last));
 }
 
-GOTEntry* X86PLT::getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+X86PLT0* X86PLT::getPLT0() const
 {
-   return m_GOTPLT.getEntry(pSymbol, pExist);
-}
 
-X86PLT0* X86PLT::getPLT0() const {
+  iterator first = m_SectionData->getFragmentList().begin();
 
-  iterator first = m_SectionData.getFragmentList().begin();
-
-  assert(first != m_SectionData.getFragmentList().end() &&
+  assert(first != m_SectionData->getFragmentList().end() &&
          "FragmentList is empty, getPLT0 failed!");
 
   X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
@@ -145,14 +153,9 @@
 }
 
 // FIXME: It only works on little endian machine.
-void X86PLT::applyPLT0() {
-
-  iterator first = m_SectionData.getFragmentList().begin();
-
-  assert(first != m_SectionData.getFragmentList().end() &&
-         "FragmentList is empty, applyPLT0 failed!");
-
-  X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
+void X86PLT::applyPLT0()
+{
+  X86PLT0* plt0 = getPLT0();
 
   unsigned char* data = 0;
   data = static_cast<unsigned char*>(malloc(plt0->getEntrySize()));
@@ -163,34 +166,30 @@
   memcpy(data, m_PLT0, plt0->getEntrySize());
 
   if (m_PLT0 == x86_exec_plt0) {
-    uint64_t got_base = m_GOTPLT.getSection().addr();
-    assert(got_base && ".got base address is NULL!");
     uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
-    *offset = got_base + 4;
+    *offset = m_GOTPLT.addr() + 4;
     offset = reinterpret_cast<uint32_t*>(data + 8);
-    *offset = got_base + 8;
+    *offset = m_GOTPLT.addr() + 8;
   }
 
   plt0->setContent(data);
 }
 
 // FIXME: It only works on little endian machine.
-void X86PLT::applyPLT1() {
+void X86PLT::applyPLT1()
+{
+  assert(m_Section.addr() && ".plt base address is NULL!");
 
-  uint64_t plt_base = m_Section.addr();
-  assert(plt_base && ".plt base address is NULL!");
-
-  uint64_t got_base = m_GOTPLT.getSection().addr();
-  assert(got_base && ".got base address is NULL!");
-
-  X86PLT::iterator it = m_SectionData.begin();
-  X86PLT::iterator ie = m_SectionData.end();
+  X86PLT::iterator it = m_SectionData->begin();
+  X86PLT::iterator ie = m_SectionData->end();
   assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
 
   uint64_t GOTEntrySize = m_GOTPLT.getEntrySize();
 
   // Skip GOT0
   uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
+  if (LinkerConfig::Exec == m_Config.codeGenType())
+    GOTEntryOffset += m_GOTPLT.addr();
 
   //skip PLT0
   uint64_t PLTEntryOffset = m_PLT0Size;
@@ -213,12 +212,7 @@
     uint32_t* offset;
 
     offset = reinterpret_cast<uint32_t*>(data + 2);
-    if (m_Output.type() == Output::DynObj) {
-      *offset = GOTEntryOffset;
-    } else {
-      // Exec
-      *offset = got_base + GOTEntryOffset;
-    }
+    *offset = GOTEntryOffset;
     GOTEntryOffset += GOTEntrySize;
 
     offset = reinterpret_cast<uint32_t*>(data + 7);
@@ -232,9 +226,6 @@
     plt1->setContent(data);
     ++it;
   }
-
-  // apply .got.plt
-  m_GOTPLT.applyAllGOTPLT(plt_base, m_PLT0Size, m_PLT1Size);
 }
 
 } // end namespace mcld
diff --git a/lib/Target/X86/X86PLT.h b/lib/Target/X86/X86PLT.h
index 1669a49..5e8b45f 100644
--- a/lib/Target/X86/X86PLT.h
+++ b/lib/Target/X86/X86PLT.h
@@ -9,27 +9,24 @@
 #ifndef MCLD_TARGET_X86_PLT_H
 #define MCLD_TARGET_X86_PLT_H
 
-#include <llvm/ADT/DenseMap.h>
-
 #include <mcld/Target/PLT.h>
-#include <mcld/LD/SectionData.h>
 
 namespace mcld {
 
 class X86GOTPLT;
 class GOTEntry;
-class Output;
+class LinkerConfig;
 
-class X86PLT0 : public PLTEntry
+class X86PLT0 : public PLT::Entry
 {
 public:
-  X86PLT0(SectionData* pParent, unsigned int pSize);
+  X86PLT0(SectionData& pParent, unsigned int pSize);
 };
 
-class X86PLT1 : public PLTEntry
+class X86PLT1 : public PLT::Entry
 {
 public:
-  X86PLT1(SectionData* pParent, unsigned int pSize);
+  X86PLT1(SectionData& pParent, unsigned int pSize);
 };
 
 /** \class X86PLT
@@ -37,60 +34,44 @@
  */
 class X86PLT : public PLT
 {
-  typedef llvm::DenseMap<const ResolveInfo*, X86PLT1*> SymbolIndexType;
-
-public:
-  typedef SectionData::iterator iterator;
-  typedef SectionData::const_iterator const_iterator;
-
 public:
   X86PLT(LDSection& pSection,
-         SectionData& pSectionData,
          X86GOTPLT& pGOTPLT,
-         const Output& pOutput);
+         const LinkerConfig& pConfig);
   ~X86PLT();
 
-// Override virtual function.
-public:
+  // finalizeSectionSize - set LDSection size
+  void finalizeSectionSize();
 
-  // reserveEntry is X86GOT friend function.
+  // hasPLT1 - return if this PLT has any PLT1 entry
+  bool hasPLT1() const;
+
   void reserveEntry(size_t pNum = 1) ;
 
-  PLTEntry* getPLTEntry(const ResolveInfo& pSymbol, bool& pExist) ;
-
-  GOTEntry* getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist);
-
-public:
-
-  iterator begin() { return m_SectionData.begin(); }
-
-  const_iterator begin() const { return m_SectionData.begin(); }
-
-  iterator end() { return m_SectionData.end(); }
-
-  const_iterator end() const { return m_SectionData.end(); }
-
-  X86PLT0* getPLT0() const;
+  PLT::Entry* consume();
 
   void applyPLT0();
 
   void applyPLT1();
 
+  unsigned int getPLT0Size() const { return m_PLT0Size; }
+  unsigned int getPLT1Size() const { return m_PLT1Size; }
+
+private:
+  X86PLT0* getPLT0() const;
+
 private:
   X86GOTPLT& m_GOTPLT;
 
-  // Used by getEntry() for mapping a ResolveInfo
-  // instance to a PLT1 Entry.
-  iterator m_PLTEntryIterator;
-
-  SymbolIndexType m_PLTEntryMap;
+  // the last consumed entry.
+  SectionData::iterator m_Last;
 
   const uint8_t *m_PLT0;
   const uint8_t *m_PLT1;
   unsigned int m_PLT0Size;
   unsigned int m_PLT1Size;
 
-  const Output& m_Output;
+  const LinkerConfig& m_Config;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86RelocationFactory.cpp b/lib/Target/X86/X86RelocationFactory.cpp
index f603b6e..d7cfe09 100644
--- a/lib/Target/X86/X86RelocationFactory.cpp
+++ b/lib/Target/X86/X86RelocationFactory.cpp
@@ -10,8 +10,8 @@
 #include <llvm/ADT/Twine.h>
 #include <llvm/Support/DataTypes.h>
 #include <llvm/Support/ELF.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Support/MsgHandling.h>
 
 #include "X86RelocationFactory.h"
@@ -27,7 +27,6 @@
 /// the prototype of applying function
 typedef RelocationFactory::Result
                           (*ApplyFunctionType)(Relocation& pReloc,
-                                               const MCLDInfo& pLDInfo,
                                                X86RelocationFactory& pParent);
 
 // the table entry of applying functions
@@ -57,19 +56,16 @@
 }
 
 RelocationFactory::Result
-X86RelocationFactory::applyRelocation(Relocation& pRelocation,
-                                           const MCLDInfo& pLDInfo)
+X86RelocationFactory::applyRelocation(Relocation& pRelocation)
 {
   Relocation::Type type = pRelocation.type();
 
   if (type >= sizeof (ApplyFunctions) / sizeof (ApplyFunctions[0]) ) {
-    fatal(diag::unknown_relocation) << (int)type <<
-                                       pRelocation.symInfo()->name();
     return Unknown;
   }
 
   // apply the relocation
-  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
+  return ApplyFunctions[type].func(pRelocation, *this);
 }
 
 const char* X86RelocationFactory::getName(Relocation::Type pType) const
@@ -81,119 +77,137 @@
 // Relocation helper function
 //===--------------------------------------------------------------------===//
 
-// Check if symbol can use relocation R_386_RELATIVE
+/// helper_DynRel - Get an relocation entry in .rel.dyn
+static
+Relocation& helper_DynRel(ResolveInfo* pSym,
+                          Fragment& pFrag,
+                          uint64_t pOffset,
+                          X86RelocationFactory::Type pType,
+                          X86RelocationFactory& pParent)
+{
+  X86GNULDBackend& 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 MCLDInfo& pLDInfo,
                           const X86RelocationFactory& pFactory)
 
 {
   // if symbol is dynamic or undefine or preemptible
   if (pSym.isDyn() ||
-     pSym.isUndef() ||
-     pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output()))
+      pSym.isUndef() ||
+      pFactory.getTarget().isSymbolPreemptible(pSym))
     return false;
   return true;
 }
 
 static
-GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
-                                  const MCLDInfo& pLDInfo,
-                                  X86RelocationFactory& pParent)
+GOT::Entry& helper_get_GOT_and_init(Relocation& pReloc,
+                                    X86RelocationFactory& pParent)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   X86GNULDBackend& ld_backend = pParent.getTarget();
 
-  bool exist;
-  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
-  if (!exist) {
-    // If we first get this GOT entry, we should initialize it.
-    if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
-      // No corresponding dynamic relocation, initialize to the symbol value.
-      got_entry.setContent(pReloc.symValue());
-    }
-    else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
-      // Initialize corresponding dynamic relocation.
-      Relocation& rel_entry =
-        *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
-      assert(!exist && "GOT entry not exist, but DynRel entry exist!");
-      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
-        // Initialize got entry to target symbol address
-        got_entry.setContent(pReloc.symValue());
-        rel_entry.setType(llvm::ELF::R_386_RELATIVE);
-        rel_entry.setSymInfo(0);
-      }
-      else {
-        got_entry.setContent(0);
-        rel_entry.setType(llvm::ELF::R_386_GLOB_DAT);
-        rel_entry.setSymInfo(rsym);
-      }
-      rel_entry.targetRef().assign(got_entry);
+  GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+  if (NULL != got_entry)
+    return *got_entry;
+
+  // not found
+  got_entry = ld_backend.getGOT().consume();
+  pParent.getSymGOTMap().record(*rsym, *got_entry);
+
+  // If we first get this GOT entry, we should initialize it.
+  if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
+    // No corresponding dynamic relocation, initialize to the symbol value.
+    got_entry->setContent(pReloc.symValue());
+  }
+  else if (rsym->reserved() & X86GNULDBackend::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->setContent(pReloc.symValue());
     }
     else {
-      fatal(diag::reserve_entry_number_mismatch_got);
+      helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent);
+      got_entry->setContent(0);
     }
   }
-  return got_entry;
+  else {
+    fatal(diag::reserve_entry_number_mismatch_got);
+  }
+  return *got_entry;
 }
 
 
 static
 X86RelocationFactory::Address helper_GOT_ORG(X86RelocationFactory& pParent)
 {
-  return pParent.getTarget().getGOTPLT().getSection().addr();
+  return pParent.getTarget().getGOTPLT().addr();
 }
 
 
 static
 X86RelocationFactory::Address helper_GOT(Relocation& pReloc,
-                                         const MCLDInfo& pLDInfo,
                                          X86RelocationFactory& pParent)
 {
-  GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo,  pParent);
-  X86RelocationFactory::Address got_addr =
-    pParent.getTarget().getGOT().getSection().addr();
-  return got_addr + pParent.getLayout().getOutputOffset(got_entry);
+  GOT::Entry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
+  X86RelocationFactory::Address got_addr = pParent.getTarget().getGOT().addr();
+  return got_addr + got_entry.getOffset();
 }
 
 
 static
-PLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
-                                  X86RelocationFactory& pParent)
+PLT::Entry& helper_get_PLT_and_init(Relocation& pReloc,
+                                    X86RelocationFactory& pParent)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   X86GNULDBackend& ld_backend = pParent.getTarget();
 
-  bool exist;
-  PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
-  if (!exist) {
-    // If we first get this PLT entry, we should initialize it.
-    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
-      GOTEntry& gotplt_entry =
-        *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
-      // Initialize corresponding dynamic relocation.
-      Relocation& rel_entry =
-        *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
-      assert(!exist && "PLT entry not exist, but DynRel entry exist!");
-      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;
-}
+  PLT::Entry* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
+  if (NULL != plt_entry)
+    return *plt_entry;
 
+  // not found
+  plt_entry = ld_backend.getPLT().consume();
+  pParent.getSymPLTMap().record(*rsym, *plt_entry);
+  // If we first get this PLT entry, we should initialize it.
+  if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
+    GOT::Entry* 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
 X86RelocationFactory::Address helper_PLT_ORG(X86RelocationFactory& pParent)
 {
-  return pParent.getTarget().getPLT().getSection().addr();
+  return pParent.getTarget().getPLT().addr();
 }
 
 
@@ -201,31 +215,8 @@
 X86RelocationFactory::Address helper_PLT(Relocation& pReloc,
                                          X86RelocationFactory& pParent)
 {
-  PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
-  return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(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(Relocation& pReloc,
-                   X86RelocationFactory::Type pType,
-                   X86RelocationFactory& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  X86GNULDBackend& ld_backend = pParent.getTarget();
-  bool exist;
-
-  Relocation& rel_entry =
-    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
-  rel_entry.setType(pType);
-  rel_entry.targetRef() = pReloc.targetRef();
-
-  if (pType == llvm::ELF::R_386_RELATIVE)
-    rel_entry.setSymInfo(0);
-  else
-    rel_entry.setSymInfo(rsym);
+  PLT::Entry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
+  return helper_PLT_ORG(pParent) + plt_entry.getOffset();
 }
 
 
@@ -235,37 +226,46 @@
 
 // R_386_NONE
 X86RelocationFactory::Result none(Relocation& pReloc,
-                                  const MCLDInfo& pLDInfo,
                                   X86RelocationFactory& pParent)
 {
   return X86RelocationFactory::OK;
 }
 
 // R_386_32: S + A
-X86RelocationFactory::Result abs32(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
-                                   X86RelocationFactory& pParent)
+// R_386_16
+// R_386_8
+X86RelocationFactory::Result abs(Relocation& pReloc,
+                                 X86RelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   RelocationFactory::DWord S = pReloc.symValue();
   bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
-                       *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT),
-                       pLDInfo, pLDInfo.output(), true);
+                              pParent.getFragmentLinker(),
+                              *rsym,
+                              (rsym->reserved() & X86GNULDBackend::ReservePLT),
+                              true);
 
-  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                  *(pReloc.targetRef().frag()));
-  assert(NULL != target_sect);
+  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 & target_sect.flag())) {
     pReloc.target() = S + A;
     return X86RelocationFactory::OK;
   }
 
   // A local symbol may need REL Type dynamic relocation
   if (rsym->isLocal() && has_dyn_rel) {
-    helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+    if (llvm::ELF::R_386_32 == pReloc.type()) {
+      helper_DynRel(rsym, *pReloc.targetRef().frag(),
+                    pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE,
+                    pParent);
+    }
+    else {
+      // FIXME: check Section symbol
+      helper_DynRel(rsym, *pReloc.targetRef().frag(),
+                    pReloc.targetRef().offset(), pReloc.type(), pParent);
+    }
     pReloc.target() = S + A;
     return X86RelocationFactory::OK;
   }
@@ -274,17 +274,19 @@
   if (!rsym->isLocal()) {
     if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
-      pReloc.target() = S + A;
     }
     // 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 (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
-        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+      if (llvm::ELF::R_386_32 == pReloc.type() &&
+          helper_use_relative_reloc(*rsym, pParent)) {
+        helper_DynRel(rsym, *pReloc.targetRef().frag(),
+              pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
       }
       else {
-        helper_DynRel(pReloc, pReloc.type(), pParent);
+        helper_DynRel(rsym, *pReloc.targetRef().frag(),
+                          pReloc.targetRef().offset(), pReloc.type(), pParent);
         return X86RelocationFactory::OK;
       }
     }
@@ -296,21 +298,20 @@
 }
 
 // R_386_PC32: S + A - P
-X86RelocationFactory::Result rel32(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
-                                   X86RelocationFactory& pParent)
+// R_386_PC16
+// R_386_PC8
+X86RelocationFactory::Result rel(Relocation& pReloc,
+                                 X86RelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   RelocationFactory::DWord S = pReloc.symValue();
-  RelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  RelocationFactory::DWord P = pReloc.place();
 
-  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                  *(pReloc.targetRef().frag()));
-  assert(NULL != target_sect);
+  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 & target_sect.flag())) {
     pReloc.target() = S + A - P;
     return X86RelocationFactory::OK;
   }
@@ -322,13 +323,17 @@
        pReloc.target() = S + A - P;
     }
     if (pParent.getTarget().symbolNeedsDynRel(
-          *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo,
-                  pLDInfo.output(), false)) {
-      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
-        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+                              pParent.getFragmentLinker(),
+                              *rsym,
+                              (rsym->reserved() & X86GNULDBackend::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(pReloc, pReloc.type(), pParent);
+        helper_DynRel(rsym, *pReloc.targetRef().frag(),
+                          pReloc.targetRef().offset(), pReloc.type(), pParent);
           return X86RelocationFactory::OK;
       }
     }
@@ -341,10 +346,9 @@
 
 // R_386_GOTOFF: S + A - GOT_ORG
 X86RelocationFactory::Result gotoff32(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
                                       X86RelocationFactory& pParent)
 {
-  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  RelocationFactory::DWord      A = pReloc.target() + pReloc.addend();
   X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
   X86RelocationFactory::Address S = pReloc.symValue();
 
@@ -354,27 +358,25 @@
 
 // R_386_GOTPC: GOT_ORG + A - P
 X86RelocationFactory::Result gotpc32(Relocation& pReloc,
-                                     const MCLDInfo& pLDInfo,
                                      X86RelocationFactory& pParent)
 {
-  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
+  RelocationFactory::DWord      A       = pReloc.target() + pReloc.addend();
   X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
   // Apply relocation.
-  pReloc.target() = GOT_ORG + A - pReloc.place(pParent.getLayout());
+  pReloc.target() = GOT_ORG + A - pReloc.place();
   return X86RelocationFactory::OK;
 }
 
 // R_386_GOT32: GOT(S) + A - GOT_ORG
 X86RelocationFactory::Result got32(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
                                    X86RelocationFactory& pParent)
 {
   if (!(pReloc.symInfo()->reserved()
        & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
     return X86RelocationFactory::BadReloc;
   }
-  X86RelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
-  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
+  X86RelocationFactory::Address GOT_S   = helper_GOT(pReloc, pParent);
+  RelocationFactory::DWord      A       = pReloc.target() + pReloc.addend();
   X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
   // Apply relocation.
   pReloc.target() = GOT_S + A - GOT_ORG;
@@ -383,7 +385,6 @@
 
 // R_386_PLT32: PLT(S) + A - P
 X86RelocationFactory::Result plt32(Relocation& pReloc,
-                                   const MCLDInfo& pLDInfo,
                                    X86RelocationFactory& pParent)
 {
   // PLT_S depends on if there is a PLT entry.
@@ -392,8 +393,204 @@
     PLT_S = helper_PLT(pReloc, pParent);
   else
     PLT_S = pReloc.symValue();
-  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
-  X86RelocationFactory::Address P = pReloc.place(pParent.getLayout());
+  RelocationFactory::DWord      A = pReloc.target() + pReloc.addend();
+  X86RelocationFactory::Address P = pReloc.place();
   pReloc.target() = PLT_S + A - P;
   return X86RelocationFactory::OK;
 }
+
+// R_386_TLS_GD:
+X86RelocationFactory::Result tls_gd(Relocation& pReloc,
+                                    X86RelocationFactory& pParent)
+{
+  // global-dynamic
+  ResolveInfo* rsym = pReloc.symInfo();
+  // must reserve two pairs of got and dynamic relocation
+  if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
+     return X86RelocationFactory::BadReloc;
+  }
+
+  X86GNULDBackend& 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
+  GOT::Entry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
+
+  if (NULL == got_entry1) {
+    // get and init two got entries if not exist
+    got_entry1 = ld_backend.getGOT().consume();
+    pParent.getSymGOTMap().record(*rsym, *got_entry1);
+    GOT::Entry* got_entry2 = ld_backend.getGOT().consume();
+    got_entry1->setContent(0x0);
+    got_entry2->setContent(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->setContent(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);
+    }
+  }
+
+  // perform relocation to the first got entry
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the
+  // .got.plt section)
+  X86RelocationFactory::Address GOT_OFF =
+     file_format->getGOT().addr() +
+     got_entry1->getOffset() -
+     file_format->getGOTPLT().addr();
+  pReloc.target() = GOT_OFF + A;
+  return X86RelocationFactory::OK;
+}
+
+// R_386_TLS_LDM
+X86RelocationFactory::Result tls_ldm(Relocation& pReloc,
+                                     X86RelocationFactory& pParent)
+{
+  // FIXME: no linker optimization for TLS relocation
+  const GOT::Entry& got_entry = pParent.getTarget().getTLSModuleID();
+
+  // All GOT offsets are relative to the end of the GOT.
+  X86RelocationFactory::SWord GOT_S = got_entry.getOffset() -
+                                      (pParent.getTarget().getGOTPLT().addr() -
+                                       pParent.getTarget().getGOT().addr());
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  pReloc.target() = GOT_S + A;
+
+  return X86RelocationFactory::OK;
+}
+
+// R_386_TLS_LDO_32
+X86RelocationFactory::Result tls_ldo_32(Relocation& pReloc,
+                                        X86RelocationFactory& pParent)
+{
+  // FIXME: no linker optimization for TLS relocation
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  X86RelocationFactory::Address S = pReloc.symValue();
+  pReloc.target() = S + A;
+  return X86RelocationFactory::OK;
+}
+
+// R_X86_TLS_IE
+X86RelocationFactory::Result tls_ie(Relocation& pReloc,
+                                    X86RelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
+     return X86RelocationFactory::BadReloc;
+  }
+
+  if (rsym->reserved() & X86GNULDBackend::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
+  GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+  if (NULL == got_entry) {
+    // set got entry
+    X86GNULDBackend& ld_backend = pParent.getTarget();
+    got_entry = ld_backend.getGOT().consume();
+    pParent.getSymGOTMap().record(*rsym, *got_entry);
+    got_entry->setContent(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);
+  }
+
+  // perform relocation to the absolute address of got_entry
+  X86RelocationFactory::Address GOT_S =
+                 pParent.getTarget().getGOT().addr() + got_entry->getOffset();
+
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  pReloc.target() = GOT_S + A;
+
+  return X86RelocationFactory::OK;
+}
+
+// R_386_TLS_GOTIE
+X86RelocationFactory::Result tls_gotie(Relocation& pReloc,
+                                       X86RelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
+     return X86RelocationFactory::BadReloc;
+  }
+
+  // set up the got and dynamic relocation entries if not exist
+  GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+  if (NULL == got_entry) {
+    // set got entry
+    X86GNULDBackend& ld_backend = pParent.getTarget();
+    got_entry = ld_backend.getGOT().consume();
+    pParent.getSymGOTMap().record(*rsym, *got_entry);
+    got_entry->setContent(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);
+  }
+
+  // All GOT offsets are relative to the end of the GOT.
+  X86RelocationFactory::SWord GOT_S = got_entry->getOffset() -
+    (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr());
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  pReloc.target() = GOT_S + A;
+
+  return X86RelocationFactory::OK;
+}
+
+// R_X86_TLS_LE
+X86RelocationFactory::Result tls_le(Relocation& pReloc,
+                                    X86RelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  if (pReloc.symInfo()->reserved() & X86GNULDBackend::ReserveRel) {
+    helper_DynRel(rsym,
+                  *pReloc.targetRef().frag(),
+                  pReloc.targetRef().offset(),
+                  llvm::ELF::R_386_TLS_TPOFF,
+                  pParent);
+    return X86RelocationFactory::OK;
+  }
+
+  // perform static relocation
+  // get TLS segment
+  ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find(
+                                       llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  X86RelocationFactory::Address S = pReloc.symValue();
+  pReloc.target() = S + A - tls_seg->memsz();
+  return X86RelocationFactory::OK;
+}
+
+X86RelocationFactory::Result unsupport(Relocation& pReloc,
+                                       X86RelocationFactory& pParent)
+{
+  return X86RelocationFactory::Unsupport;
+}
+
diff --git a/lib/Target/X86/X86RelocationFactory.h b/lib/Target/X86/X86RelocationFactory.h
index 4b413d7..92119f1 100644
--- a/lib/Target/X86/X86RelocationFactory.h
+++ b/lib/Target/X86/X86RelocationFactory.h
@@ -14,10 +14,13 @@
 
 #include <mcld/LD/RelocationFactory.h>
 #include <mcld/Target/GOT.h>
+#include <mcld/Target/PLT.h>
+#include <mcld/Target/SymbolEntryMap.h>
 #include "X86LDBackend.h"
 
-namespace mcld
-{
+namespace mcld {
+
+class ResolveInfo;
 
 /** \class X86RelocationFactory
  *  \brief X86RelocationFactory creates and destroys the X86 relocations.
@@ -26,10 +29,14 @@
 class X86RelocationFactory : public RelocationFactory
 {
 public:
+  typedef SymbolEntryMap<PLT::Entry> SymPLTMap;
+  typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
+
+public:
   X86RelocationFactory(size_t pNum, X86GNULDBackend& pParent);
   ~X86RelocationFactory();
 
-  Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+  Result applyRelocation(Relocation& pRelocation);
 
   X86GNULDBackend& getTarget()
   { return m_Target; }
@@ -39,8 +46,20 @@
 
   const char* getName(Relocation::Type pType) const;
 
+  const SymPLTMap& getSymPLTMap() const { return m_SymPLTMap; }
+  SymPLTMap&       getSymPLTMap()       { return m_SymPLTMap; }
+
+  const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
+  SymGOTMap&       getSymGOTMap()       { return m_SymGOTMap; }
+
+  const SymGOTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
+  SymGOTMap&       getSymGOTPLTMap()       { return m_SymGOTPLTMap; }
+
 private:
   X86GNULDBackend& m_Target;
+  SymPLTMap m_SymPLTMap;
+  SymGOTMap m_SymGOTMap;
+  SymGOTMap m_SymGOTPLTMap;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86RelocationFunctions.h b/lib/Target/X86/X86RelocationFunctions.h
index 46d4f34..9b82739 100644
--- a/lib/Target/X86/X86RelocationFunctions.h
+++ b/lib/Target/X86/X86RelocationFunctions.h
@@ -9,23 +9,29 @@
 
 #define DECL_X86_APPLY_RELOC_FUNC(Name) \
 static X86RelocationFactory::Result Name    (Relocation& pEntry, \
-					     const MCLDInfo& pLDInfo, \
 					     X86RelocationFactory& pParent);
 
 #define DECL_X86_APPLY_RELOC_FUNCS \
 DECL_X86_APPLY_RELOC_FUNC(none)             \
-DECL_X86_APPLY_RELOC_FUNC(abs32)            \
-DECL_X86_APPLY_RELOC_FUNC(rel32)            \
+DECL_X86_APPLY_RELOC_FUNC(abs)              \
+DECL_X86_APPLY_RELOC_FUNC(rel)              \
 DECL_X86_APPLY_RELOC_FUNC(plt32)            \
 DECL_X86_APPLY_RELOC_FUNC(got32)            \
-DECL_X86_APPLY_RELOC_FUNC(gotoff32)	    \
-DECL_X86_APPLY_RELOC_FUNC(gotpc32)
+DECL_X86_APPLY_RELOC_FUNC(gotoff32)	        \
+DECL_X86_APPLY_RELOC_FUNC(gotpc32)          \
+DECL_X86_APPLY_RELOC_FUNC(tls_gd)           \
+DECL_X86_APPLY_RELOC_FUNC(tls_ie)           \
+DECL_X86_APPLY_RELOC_FUNC(tls_gotie)        \
+DECL_X86_APPLY_RELOC_FUNC(tls_le)           \
+DECL_X86_APPLY_RELOC_FUNC(tls_ldm)          \
+DECL_X86_APPLY_RELOC_FUNC(tls_ldo_32)       \
+DECL_X86_APPLY_RELOC_FUNC(unsupport)
 
 
 #define DECL_X86_APPLY_RELOC_FUNC_PTRS \
   { &none,               0, "R_386_NONE"              },  \
-  { &abs32,              1, "R_386_32"                },  \
-  { &rel32,              2, "R_386_PC32"              },  \
+  { &abs,                1, "R_386_32"                },  \
+  { &rel,                2, "R_386_PC32"              },  \
   { &got32,              3, "R_386_GOT32"             },  \
   { &plt32,              4, "R_386_PLT32"             },  \
   { &none,               5, "R_386_COPY"              },  \
@@ -33,4 +39,37 @@
   { &none,               7, "R_386_JMP_SLOT"          },  \
   { &none,               8, "R_386_RELATIVE"          },  \
   { &gotoff32,           9, "R_386_GOTOFF"            },  \
-  { &gotpc32,           10, "R_386_GOTPC"             }
+  { &gotpc32,           10, "R_386_GOTPC"             },  \
+  { &unsupport,         11, "R_386_32PLT"             },  \
+  { &unsupport,         12, ""                        },  \
+  { &unsupport,         13, ""                        },  \
+  { &unsupport,         14, "R_386_TLS_TPOFF"         },  \
+  { &tls_ie,            15, "R_386_TLS_IE"            },  \
+  { &tls_gotie,         16, "R_386_TLS_GOTIE"         },  \
+  { &tls_le,            17, "R_386_TLS_LE"            },  \
+  { &tls_gd,            18, "R_386_TLS_GD"            },  \
+  { &tls_ldm,           19, "R_386_TLS_LDM"           },  \
+  { &abs,               20, "R_386_16"                },  \
+  { &rel,               21, "R_386_PC16"              },  \
+  { &abs,               22, "R_386_8"                 },  \
+  { &rel,               23, "R_386_PC8"               },  \
+  { &unsupport,         24, "R_386_TLS_GD_32"         },  \
+  { &unsupport,         25, "R_386_TLS_GD_PUSH"       },  \
+  { &unsupport,         26, "R_386_TLS_GD_CALL"       },  \
+  { &unsupport,         27, "R_386_TLS_GD_POP"        },  \
+  { &unsupport,         28, "R_386_TLS_LDM_32"        },  \
+  { &unsupport,         29, "R_386_TLS_LDM_PUSH"      },  \
+  { &unsupport,         30, "R_386_TLS_LDM_CALL"      },  \
+  { &unsupport,         31, "R_386_TLS_LDM_POP"       },  \
+  { &tls_ldo_32,        32, "R_386_TLS_LDO_32"        },  \
+  { &unsupport,         33, "R_386_TLS_IE_32"         },  \
+  { &unsupport,         34, "R_386_TLS_LE_32"         },  \
+  { &unsupport,         35, "R_386_TLS_DTPMOD32"      },  \
+  { &unsupport,         36, "R_386_TLS_DTPOFF32"      },  \
+  { &unsupport,         37, "R_386_TLS_TPOFF32"       },  \
+  { &unsupport,         38, ""                        },  \
+  { &unsupport,         39, "R_386_TLS_GOTDESC"       },  \
+  { &unsupport,         40, "R_386_TLS_DESC_CALL"     },  \
+  { &unsupport,         41, "R_386_TLS_DESC"          },  \
+  { &unsupport,         42, "R_386_IRELATIVE"         },  \
+  { &unsupport,         43,  "R_386_NUM"              }
diff --git a/lib/Target/X86/X86SectLinker.cpp b/lib/Target/X86/X86SectLinker.cpp
deleted file mode 100644
index 2954d1f..0000000
--- a/lib/Target/X86/X86SectLinker.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//===- X86SectLinker.cpp --------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <llvm/ADT/Triple.h>
-#include <mcld/Support/TargetRegistry.h>
-
-#include "X86.h"
-#include "X86ELFSectLinker.h"
-
-using namespace mcld;
-
-namespace mcld {
-//===----------------------------------------------------------------------===//
-/// createX86SectLinker - the help funtion to create corresponding X86SectLinker
-///
-SectLinker* createX86SectLinker(const std::string &pTriple,
-                                SectLinkerOption &pOption,
-                                mcld::TargetLDBackend &pLDBackend)
-{
-  Triple theTriple(pTriple);
-  if (theTriple.isOSDarwin()) {
-    assert(0 && "MachO linker has not supported yet");
-    return NULL;
-  }
-  if (theTriple.isOSWindows()) {
-    assert(0 && "COFF linker has not supported yet");
-    return NULL;
-  }
-
-  if (theTriple.isArch32Bit())
-    return new X86ELFSectLinker(pOption, pLDBackend);
-
-  assert(0 && "X86_64 has not supported yet");
-  return NULL;
-}
-
-} // namespace of mcld
-
-//==========================
-// X86SectLinker
-extern "C" void LLVMInitializeX86SectLinker() {
-  // Register the linker frontend
-  mcld::TargetRegistry::RegisterSectLinker(TheX86Target, createX86SectLinker);
-}
-
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index b036137..9b5a24e 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -8,12 +8,11 @@
 //===----------------------------------------------------------------------===//
 #include "X86TargetMachine.h"
 
-#include "mcld/Target/TargetMachine.h"
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/MC/MCLDInfo.h"
 #include "X86.h"
+#include <mcld/Target/TargetMachine.h>
+#include <mcld/Support/TargetRegistry.h>
 
-extern "C" void LLVMInitializeX86LDTarget() {
+extern "C" void MCLDInitializeX86LDTarget() {
   // Register createTargetMachine function pointer to mcld::Target
   mcld::RegisterTargetMachine<mcld::X86TargetMachine> X(mcld::TheX86Target);
 }
@@ -21,14 +20,10 @@
 mcld::X86TargetMachine::X86TargetMachine(llvm::TargetMachine& pPM,
                                          const mcld::Target &pTarget,
                                          const std::string& pTriple)
-  : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
-  // arg1 - the number of total attributes
-  // arg2 - the most possible number of input files
-  m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+  : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
 }
 
 mcld::X86TargetMachine::~X86TargetMachine()
 {
-  delete m_pLDInfo;
 }
 
diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h
index 3ba9e59..9034741 100644
--- a/lib/Target/X86/X86TargetMachine.h
+++ b/lib/Target/X86/X86TargetMachine.h
@@ -8,30 +8,19 @@
 //===----------------------------------------------------------------------===//
 #ifndef MCLD_X86_TARGET_MACHINE_H
 #define MCLD_X86_TARGET_MACHINE_H
-#include "mcld/Target/TargetMachine.h"
 #include "X86.h"
+#include <mcld/Target/TargetMachine.h>
 
-namespace mcld
+namespace mcld {
+
+class X86TargetMachine : public MCLDTargetMachine
 {
-
-class X86TargetMachine : public LLVMTargetMachine
-{
-protected:
-  MCLDInfo *m_pLDInfo;
-
 public:
   X86TargetMachine(llvm::TargetMachine &pTM,
-                       const mcld::Target &pTarget,
-                       const std::string &pTriple);
+                   const mcld::Target &pTarget,
+                   const std::string &pTriple);
 
   virtual ~X86TargetMachine();
-
-  mcld::MCLDInfo& getLDInfo()
-  { return *m_pLDInfo; }
-
-  const mcld::MCLDInfo& getLDInfo() const
-  { return *m_pLDInfo; }
-
 };
 
 } // namespace of mcld
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index f4201d2..28a18c6 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -6,20 +6,21 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Target/TargetMachine.h>
 #include <mcld/Support/TargetSelect.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/Support/CommandLine.h>
-#include <mcld/Support/DerivedPositionDependentOptions.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/ToolOutputFile.h>
 #include <mcld/LD/DiagnosticLineInfo.h>
 #include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
 
 #include <llvm/Module.h>
 #include <llvm/PassManager.h>
@@ -36,11 +37,28 @@
 #include <llvm/Support/Signals.h>
 #include <llvm/Support/TargetRegistry.h>
 #include <llvm/Support/TargetSelect.h>
-#include <llvm/Support/ToolOutputFile.h>
 #include <llvm/Support/Process.h>
 #include <llvm/Target/TargetData.h>
 #include <llvm/Target/TargetMachine.h>
 
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined(_MSC_VER)
+#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
@@ -230,19 +248,25 @@
 //===----------------------------------------------------------------------===//
 // 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. attribute of inputs, (describing the attributes of inputs, such as
-//      --as-needed and --whole-archive. usually be positional.)
-//   3. scripting options, (represent a subset of link scripting language, such
-//      as --defsym.)
-//   4. 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)
 //===----------------------------------------------------------------------===//
-// General 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 cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
 ArgOutputFilename("o",
                cl::desc("Output filename"),
@@ -259,7 +283,7 @@
            cl::value_desc("directory"),
            cl::ValueRequired);
 
-static cl::list<mcld::MCLDDirectory, bool, llvm::cl::parser<mcld::MCLDDirectory> >
+static cl::list<std::string>
 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."),
@@ -379,6 +403,16 @@
        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"),
@@ -401,6 +435,7 @@
 
 static cl::opt<std::string>
 ArgDyld("dynamic-linker",
+        cl::ZeroOrMore,
         cl::desc("Set the name of the dynamic linker."),
         cl::value_desc("Program"));
 
@@ -426,114 +461,154 @@
       "surround result strings only if the output is a tty"),
     clEnumValEnd));
 
-//===----------------------------------------------------------------------===//
-// Inputs
-static cl::list<mcld::sys::fs::Path>
-ArgInputObjectFiles(cl::Positional,
-                    cl::desc("[input object files]"),
-                    cl::ZeroOrMore);
+/// @{
+/// @name FIXME: begin of unsupported options
+/// @}
+static cl::opt<bool>
+ArgGCSections("gc-sections",
+              cl::desc("Enable garbage collection of unused input sections."),
+              cl::init(false));
+
+static cl::opt<bool>
+ArgNoGCSections("no-gc-sections",
+              cl::desc("disable garbage collection of unused input sections."),
+              cl::init(false));
+
+namespace icf {
+enum Mode {
+  None,
+  All,
+  Safe
+};
+} // namespace of icf
+
+static cl::opt<icf::Mode>
+ArgICF("icf",
+       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));
+
+// 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 cl::opt<bool>
+ArgDiscardLocals("discard-locals",
+                 cl::desc("Delete all temporary local symbols."),
+                 cl::init(false));
+
+static cl::alias
+ArgDiscardLocalsAlias("X",
+                      cl::desc("alias for --discard-locals"),
+                      cl::aliasopt(ArgDiscardLocals));
+
+static cl::opt<bool>
+ArgDiscardAll("discard-all",
+              cl::desc("Delete all local symbols."),
+              cl::init(false));
+
+static cl::alias
+ArgDiscardAllAlias("x",
+                   cl::desc("alias for --discard-all"),
+                   cl::aliasopt(ArgDiscardAll));
+
+static cl::opt<bool>
+ArgNMagic("nmagic",
+          cl::desc("Do not page align data"),
+          cl::init(false));
+
+static cl::alias
+ArgNMagicAlias("n",
+               cl::desc("alias for --nmagic"),
+               cl::aliasopt(ArgNMagic));
+
+static cl::opt<bool>
+ArgOMagic("omagic",
+          cl::desc("Do not page align data, do not make text readonly"),
+          cl::init(false));
+
+static cl::alias
+ArgOMagicAlias("N",
+               cl::desc("alias for --omagic"),
+               cl::aliasopt(ArgOMagic));
+
+static cl::opt<bool>
+ArgStripDebug("strip-debug",
+              cl::desc("Omit debugger symbol information from the output file."),
+              cl::init(false));
+
+static cl::alias
+ArgStripDebugAlias("S",
+                   cl::desc("alias for --strip-debug"),
+                   cl::aliasopt(ArgStripDebug));
+
+static cl::opt<bool>
+ArgExportDynamic("export-dynamic",
+                 cl::desc("Export all dynamic symbols"),
+                 cl::init(false));
+
+static cl::alias
+ArgExportDynamicAlias("E",
+                      cl::desc("alias for --export-dynamic"),
+                      cl::aliasopt(ArgExportDynamic));
+
+static cl::opt<std::string>
+ArgEmulation("m",
+             cl::desc("Set GNU linker emulation"),
+             cl::value_desc("emulation"));
+
+static cl::opt<std::string>
+ArgRuntimePath("rpath",
+               cl::desc("Add a directory to the runtime library search path"),
+               cl::value_desc("dir"));
+
+static cl::opt<std::string>
+ArgRuntimePathLink("rpath-link",
+                   cl::desc("Add a directory to the link time library search path"),
+                   cl::value_desc("dir"));
 
 static cl::list<std::string>
-ArgNameSpecList("l",
-            cl::ZeroOrMore,
-            cl::desc("Add the archive or object file specified by namespec to the list of files to link."),
-            cl::value_desc("namespec"),
-            cl::Prefix);
+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"));
+
+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
-ArgNameSpecListAlias("library",
-                 cl::desc("alias for -l"),
-                 cl::aliasopt(ArgNameSpecList));
+ArgForceUndefinedAlias("undefined",
+                       cl::desc("alias for -u"),
+                       cl::aliasopt(ArgForceUndefined));
 
-static cl::list<bool>
-ArgStartGroupList("start-group",
-                  cl::ValueDisallowed,
-                  cl::desc("start to record a group of archives"));
+/// @{
+/// @name FIXME: end of unsupported options
+/// @}
 
-static cl::alias
-ArgStartGroupListAlias("(",
-                       cl::desc("alias for --start-group"),
-                       cl::aliasopt(ArgStartGroupList));
-
-static cl::list<bool>
-ArgEndGroupList("end-group",
-                cl::ValueDisallowed,
-                cl::desc("stop recording a group of archives"));
-
-static cl::alias
-ArgEndGroupListAlias(")",
-                     cl::desc("alias for --end-group"),
-                     cl::aliasopt(ArgEndGroupList));
-
-//===----------------------------------------------------------------------===//
-// Attributes of Inputs
-static cl::list<bool>
-ArgWholeArchiveList("whole-archive",
-                    cl::ValueDisallowed,
-                    cl::desc("For each archive mentioned on the command line after the --whole-archive option, include all object files in the archive."));
-
-static cl::list<bool>
-ArgNoWholeArchiveList("no-whole-archive",
-                    cl::ValueDisallowed,
-                    cl::desc("Turn off the effect of the --whole-archive option for subsequent archive files."));
-
-static cl::list<bool>
-ArgAsNeededList("as-needed",
-                cl::ValueDisallowed,
-                cl::desc("This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the --as-needed option."));
-
-static cl::list<bool>
-ArgNoAsNeededList("no-as-needed",
-                cl::ValueDisallowed,
-                cl::desc("Turn off the effect of the --as-needed option for subsequent dynamic libraries"));
-
-static cl::list<bool>
-ArgAddNeededList("add-needed",
-                cl::ValueDisallowed,
-                cl::desc("--add-needed causes DT_NEEDED tags are always emitted for those libraries from DT_NEEDED tags. This is the default behavior."));
-
-static cl::list<bool>
-ArgNoAddNeededList("no-add-needed",
-                cl::ValueDisallowed,
-                cl::desc("--no-add-needed causes DT_NEEDED tags will never be emitted for those libraries from DT_NEEDED tags"));
-
-static cl::list<bool>
-ArgBDynamicList("Bdynamic",
-                cl::ValueDisallowed,
-                cl::desc("Link against dynamic library"));
-
-static cl::alias
-ArgBDynamicListAlias1("dy",
-                     cl::desc("alias for --Bdynamic"),
-                     cl::aliasopt(ArgBDynamicList));
-
-static cl::alias
-ArgBDynamicListAlias2("call_shared",
-                     cl::desc("alias for --Bdynamic"),
-                     cl::aliasopt(ArgBDynamicList));
-
-static cl::list<bool>
-ArgBStaticList("Bstatic",
-                cl::ValueDisallowed,
-                cl::desc("Link against static library"));
-
-static cl::alias
-ArgBStaticListAlias1("dn",
-                     cl::desc("alias for --Bstatic"),
-                     cl::aliasopt(ArgBStaticList));
-
-static cl::alias
-ArgBStaticListAlias2("static",
-                     cl::desc("alias for --Bstatic"),
-                     cl::aliasopt(ArgBStaticList));
-
-static cl::alias
-ArgBStaticListAlias3("non_shared",
-                     cl::desc("alias for --Bstatic"),
-                     cl::aliasopt(ArgBStaticList));
+static cl::opt<bool>
+ArgWarnSharedTextrel("warn-shared-textrel",
+                     cl::desc("Warn if adding DT_TEXTREL in a shared object."),
+                     cl::init(false));
 
 //===----------------------------------------------------------------------===//
 // Scripting Options
+//===----------------------------------------------------------------------===//
 static cl::list<std::string>
 ArgWrapList("wrap",
             cl::ZeroOrMore,
@@ -546,15 +621,37 @@
             cl::desc("Use a portable function fo symbol."),
             cl::value_desc("symbol"));
 
-//===----------------------------------------------------------------------===//
-/// non-member functions
+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));
+
+//===----------------------------------------------------------------------===//
+// non-member functions
+//===----------------------------------------------------------------------===//
 /// GetOutputStream - get the output stream.
-static tool_output_file *GetOutputStream(const char* pTargetName,
-                                         Triple::OSType pOSType,
-                                         mcld::CodeGenFileType pFileType,
-                                         const mcld::sys::fs::Path& pInputFilename,
-                                         mcld::sys::fs::Path& pOutputFilename)
+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("-"))
@@ -589,6 +686,19 @@
       }
       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("-"))
@@ -623,31 +733,28 @@
     } // end of ! pInputFilename == "-"
   } // end of if empty pOutputFilename
 
-  // Decide if we need "binary" output.
-  unsigned int fd_flags = 0x0;
+  mcld::FileHandle::Permission permission;
   switch (pFileType) {
   default: assert(0 && "Unknown file type");
   case mcld::CGFT_ASMFile:
-    break;
   case mcld::CGFT_OBJFile:
+  case mcld::CGFT_PARTIAL:
+    permission = 0644;
+    break;
   case mcld::CGFT_DSOFile:
   case mcld::CGFT_EXEFile:
   case mcld::CGFT_NULLFile:
-    fd_flags |= raw_fd_ostream::F_Binary;
+    permission = 0755;
     break;
   }
 
   // Open the file.
-  std::string err_mesg;
-  tool_output_file *result_output =
-                            new tool_output_file(pOutputFilename.c_str(),
-                                                 err_mesg,
-                                                 fd_flags);
-  if (!err_mesg.empty()) {
-    errs() << err_mesg << '\n';
-    delete result_output;
-    return NULL;
-  }
+  mcld::ToolOutputFile* result_output =
+                      new mcld::ToolOutputFile(pOutputFilename,
+                                                 mcld::FileHandle::ReadWrite |
+                                                 mcld::FileHandle::Create |
+                                                 mcld::FileHandle::Truncate,
+                                               permission);
 
   return result_output;
 }
@@ -658,46 +765,79 @@
    return term && (0 != strcmp(term, "dumb"));
 }
 
-static bool ProcessLinkerOptionsFromCommand(mcld::MCLDInfo& pLDInfo) {
+static bool ProcessLinkerOptionsFromCommand(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
-  pLDInfo.output().setSOName(ArgSOName);
+  pConfig.options().setSOName(ArgSOName);
+
+  // -shared or -pie
+  if (true == ArgShared || true == ArgPIE) {
+    ArgFileType = mcld::CGFT_DSOFile;
+  }
+  else if (true == ArgRelocatable) {
+    ArgFileType = mcld::CGFT_PARTIAL;
+  }
+
+  // -V
+  if (ArgVersion) {
+    mcld::outs() << "MCLinker - "
+                 << mcld::LinkerConfig::version()
+                 << "\n";
+  }
 
   // set up sysroot
   if (!ArgSysRoot.empty()) {
     if (exists(ArgSysRoot) && is_directory(ArgSysRoot))
-      pLDInfo.options().setSysroot(ArgSysRoot);
+      pConfig.options().setSysroot(ArgSysRoot);
   }
 
   // add all search directories
-  cl::list<mcld::MCLDDirectory>::iterator sd;
-  cl::list<mcld::MCLDDirectory>::iterator sdEnd = ArgSearchDirList.end();
+  cl::list<std::string>::iterator sd;
+  cl::list<std::string>::iterator sdEnd = ArgSearchDirList.end();
   for (sd=ArgSearchDirList.begin(); sd!=sdEnd; ++sd) {
-    if (sd->isInSysroot())
-      sd->setSysroot(pLDInfo.options().sysroot());
-    if (exists(sd->path()) && is_directory(sd->path())) {
-      pLDInfo.options().directories().add(*sd);
-    }
-    else {
+    if (!pConfig.options().directories().insert(*sd)) {
       // FIXME: need a warning function
       errs() << "WARNING: can not open search directory `-L"
-             << sd->name()
+             << *sd
              << "'.\n";
     }
   }
 
-  pLDInfo.options().setPIE(ArgPIE);
-  pLDInfo.options().setTrace(ArgTrace);
-  pLDInfo.options().setVerbose(ArgVerbose);
-  pLDInfo.options().setMaxErrorNum(ArgMaxErrorNum);
-  pLDInfo.options().setMaxWarnNum(ArgMaxWarnNum);
-  pLDInfo.options().setEntry(ArgEntry);
-  pLDInfo.options().setBsymbolic(ArgBsymbolic);
-  pLDInfo.options().setBgroup(ArgBgroup);
-  pLDInfo.options().setDyld(ArgDyld);
-  pLDInfo.options().setNoUndefined(ArgNoUndefined);
-  pLDInfo.options().setMulDefs(ArgAllowMulDefs);
-  pLDInfo.options().setEhFrameHdr(ArgEhFrameHdr);
+  pConfig.options().setPIE(ArgPIE);
+  pConfig.options().setTrace(ArgTrace);
+  pConfig.options().setVerbose(ArgVerbose);
+  pConfig.options().setMaxErrorNum(ArgMaxErrorNum);
+  pConfig.options().setMaxWarnNum(ArgMaxWarnNum);
+  pConfig.options().setEntry(ArgEntry);
+  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);
+  pConfig.options().setExportDynamic(ArgExportDynamic);
+  pConfig.options().setWarnSharedTextrel(ArgWarnSharedTextrel);
 
   // set up rename map, for --wrap
   cl::list<std::string>::iterator wname;
@@ -707,7 +847,7 @@
 
     // add wname -> __wrap_wname
     mcld::StringEntry<llvm::StringRef>* to_wrap =
-                    pLDInfo.scripts().renameMap().insert(*wname, exist);
+                    pConfig.scripts().renameMap().insert(*wname, exist);
 
     std::string to_wrap_str = "__wrap_" + *wname;
     to_wrap->setValue(to_wrap_str);
@@ -718,7 +858,7 @@
     // add __real_wname -> wname
     std::string from_real_str = "__real_" + *wname;
     mcld::StringEntry<llvm::StringRef>* from_real =
-             pLDInfo.scripts().renameMap().insert(from_real_str, exist);
+             pConfig.scripts().renameMap().insert(from_real_str, exist);
     from_real->setValue(*wname);
     if (exist)
       mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
@@ -732,7 +872,7 @@
 
     // add pname -> pname_portable
     mcld::StringEntry<llvm::StringRef>* to_port =
-                  pLDInfo.scripts().renameMap().insert(*pname, exist);
+                  pConfig.scripts().renameMap().insert(*pname, exist);
 
     std::string to_port_str = *pname + "_portable";
     to_port->setValue(to_port_str);
@@ -743,154 +883,88 @@
     // add __real_pname -> pname
     std::string from_real_str = "__real_" + *pname;
     mcld::StringEntry<llvm::StringRef>* from_real =
-             pLDInfo.scripts().renameMap().insert(from_real_str, exist);
+             pConfig.scripts().renameMap().insert(from_real_str, exist);
 
     from_real->setValue(*pname);
     if (exist)
       mcld::warning(mcld::diag::rewrap) << *pname << from_real_str;
   } // end of for
 
-  // set up colorize
-  switch (ArgColor) {
-    case color::Never:
-      pLDInfo.options().setColor(false);
-    break;
-    case color::Always:
-      pLDInfo.options().setColor(true);
-    break;
-    case color::Auto:
-      bool color_option = ShouldColorize() &&
-                 llvm::sys::Process::FileDescriptorIsDisplayed(STDOUT_FILENO);
-      pLDInfo.options().setColor(color_option);
-    break;
-  }
-
   // add -z options
   cl::list<mcld::ZOption>::iterator zOpt;
   cl::list<mcld::ZOption>::iterator zOptEnd = ArgZOptionList.end();
   for (zOpt = ArgZOptionList.begin(); zOpt != zOptEnd; ++zOpt) {
-    pLDInfo.options().addZOption(*zOpt);
+    pConfig.options().addZOption(*zOpt);
   }
 
-  // -----  Set up Script Options  ----- //
-
-  return true;
-}
-
-static bool ProcessLinkerInputsFromCommand(mcld::SectLinkerOption &pOption) {
-  // -----  Set up Inputs  ----- //
-  // add all start-group
-  cl::list<bool>::iterator sg;
-  cl::list<bool>::iterator sgEnd = ArgStartGroupList.end();
-  for (sg=ArgStartGroupList.begin(); sg!=sgEnd; ++sg) {
-    // calculate position
-    pOption.appendOption(new mcld::StartGroupOption(
-                                    ArgStartGroupList.getPosition(sg-ArgStartGroupList.begin())));
+  if (ArgGCSections) {
+    mcld::warning(mcld::diag::warn_unsupported_option) << ArgGCSections.ArgStr;
   }
 
-  // add all end-group
-  cl::list<bool>::iterator eg;
-  cl::list<bool>::iterator egEnd = ArgEndGroupList.end();
-  for (eg=ArgEndGroupList.begin(); eg!=egEnd; ++eg) {
-    // calculate position
-    pOption.appendOption(new mcld::EndGroupOption(
-                                    ArgEndGroupList.getPosition(eg-ArgEndGroupList.begin())));
+  // 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;
   }
 
-  // add all namespecs
-  cl::list<std::string>::iterator ns;
-  cl::list<std::string>::iterator nsEnd = ArgNameSpecList.end();
-  for (ns=ArgNameSpecList.begin(); ns!=nsEnd; ++ns) {
-    // calculate position
-    pOption.appendOption(new mcld::NamespecOption(
-                                    ArgNameSpecList.getPosition(ns-ArgNameSpecList.begin()),
-                                    *ns));
+  if (ArgFIXCA8) {
+    mcld::warning(mcld::diag::warn_unsupported_option) << ArgFIXCA8.ArgStr;
   }
 
-  // add all object files
-  cl::list<mcld::sys::fs::Path>::iterator obj;
-  cl::list<mcld::sys::fs::Path>::iterator objEnd = ArgInputObjectFiles.end();
-  for (obj=ArgInputObjectFiles.begin(); obj!=objEnd; ++obj) {
-    // calculate position
-    pOption.appendOption(new mcld::InputFileOption(
-                                    ArgInputObjectFiles.getPosition(obj-ArgInputObjectFiles.begin()),
-                                    *obj));
+  if (ArgDiscardLocals) {
+    mcld::warning(mcld::diag::warn_unsupported_option) << ArgDiscardLocals.ArgStr;
   }
 
-  // -----  Set up Attributes of Inputs  ----- //
-  // --whole-archive
-  cl::list<bool>::iterator attr = ArgWholeArchiveList.begin();
-  cl::list<bool>::iterator attrEnd = ArgWholeArchiveList.end();
-  for (; attr!=attrEnd; ++attr) {
-    pOption.appendOption(new mcld::WholeArchiveOption(
-                                    ArgWholeArchiveList.getPosition(attr-ArgWholeArchiveList.begin())));
+  if (ArgDiscardAll) {
+    mcld::warning(mcld::diag::warn_unsupported_option) << ArgDiscardAll.ArgStr;
   }
 
-  // --no-whole-archive
-  attr = ArgNoWholeArchiveList.begin();
-  attrEnd = ArgNoWholeArchiveList.end();
-  for (; attr!=attrEnd; ++attr) {
-    pOption.appendOption(new mcld::NoWholeArchiveOption(
-                                    ArgNoWholeArchiveList.getPosition(attr-ArgNoWholeArchiveList.begin())));
+  // add address mappings
+  // -Ttext
+  if (-1U != ArgTextSegAddr) {
+    bool exist = false;
+    mcld::StringEntry<uint64_t>* text_mapping =
+      pConfig.scripts().addressMap().insert(".text", exist);
+    text_mapping->setValue(ArgTextSegAddr);
   }
-
-  // --as-needed
-  attr = ArgAsNeededList.begin();
-  attrEnd = ArgAsNeededList.end();
-  while(attr != attrEnd) {
-    pOption.appendOption(new mcld::AsNeededOption(
-                                    ArgAsNeededList.getPosition(attr-ArgAsNeededList.begin())));
-    ++attr;
+  // -Tdata
+  if (-1U != ArgDataSegAddr) {
+    bool exist = false;
+    mcld::StringEntry<uint64_t>* data_mapping =
+      pConfig.scripts().addressMap().insert(".data", exist);
+    data_mapping->setValue(ArgDataSegAddr);
   }
-
-  // --no-as-needed
-  attr = ArgNoAsNeededList.begin();
-  attrEnd = ArgNoAsNeededList.end();
-  while(attr != attrEnd) {
-    pOption.appendOption(new mcld::NoAsNeededOption(
-                                    ArgNoAsNeededList.getPosition(attr-ArgNoAsNeededList.begin())));
-    ++attr;
+  // -Tbss
+  if (-1U != ArgBssSegAddr) {
+    bool exist = false;
+    mcld::StringEntry<uint64_t>* bss_mapping =
+      pConfig.scripts().addressMap().insert(".bss", exist);
+    bss_mapping->setValue(ArgBssSegAddr);
   }
-
-  // --add-needed
-  attr = ArgAddNeededList.begin();
-  attrEnd = ArgAddNeededList.end();
-  while(attr != attrEnd) {
-    pOption.appendOption(new mcld::AddNeededOption(
-                                    ArgAddNeededList.getPosition(attr-ArgAddNeededList.begin())));
-    ++attr;
-  }
-
-  // --no-add-needed
-  attr = ArgNoAddNeededList.begin();
-  attrEnd = ArgNoAddNeededList.end();
-  while(attr != attrEnd) {
-    pOption.appendOption(new mcld::NoAddNeededOption(
-                                    ArgNoAddNeededList.getPosition(attr-ArgNoAddNeededList.begin())));
-    ++attr;
-  }
-
-  // -Bdynamic
-  attr = ArgBDynamicList.begin();
-  attrEnd = ArgBDynamicList.end();
-  while(attr != attrEnd) {
-    pOption.appendOption(new mcld::BDynamicOption(
-                                    ArgBDynamicList.getPosition(attr-ArgBDynamicList.begin())));
-  }
-
-  // -Bstatic
-  attr = ArgBStaticList.begin();
-  attrEnd = ArgBStaticList.end();
-  while(attr != attrEnd) {
-    pOption.appendOption(new mcld::BStaticOption(
-                                    ArgBStaticList.getPosition(attr-ArgBStaticList.begin())));
-    ++attr;
+  // --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 =
+      pConfig.scripts().addressMap().insert(script.substr(0, pos), exist);
+    addr_mapping->setValue(address);
   }
 
   return true;
 }
 
-int main( int argc, char* argv[] )
+int main(int argc, char* argv[])
 {
   LLVMContext &Context = getGlobalContext();
   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
@@ -909,26 +983,27 @@
   InitializeAllTargetMCs();
   mcld::InitializeAllTargets();
   mcld::InitializeAllLinkers();
+  mcld::InitializeAllEmulations();
   mcld::InitializeAllDiagnostics();
 
   // Load the module to be compiled...
-  std::auto_ptr<Module> M;
+  std::auto_ptr<llvm::Module> M;
 
-  // -shared
-  if (true == ArgShared) {
-    ArgFileType = mcld::CGFT_DSOFile;
-  }
+  // Load the module to be linked...
+  mcld::Module LDIRModule;
 
-  // -V
-  if (ArgVersion) {
-    outs() << "MCLinker - ";
-    outs() << mcld::MCLDInfo::version();
-    outs() << "\n";
+  mcld::LinkerConfig LDConfig;
+
+  // Process the linker input from the command line
+  if (!ProcessLinkerOptionsFromCommand(LDConfig)) {
+    errs() << argv[0] << ": failed to process linker options from command line!\n";
+    return 1;
   }
 
   if (ArgBitcodeFilename.empty() &&
       (mcld::CGFT_DSOFile != ArgFileType &&
-       mcld::CGFT_EXEFile != ArgFileType)) {
+       mcld::CGFT_EXEFile != ArgFileType &&
+       mcld::CGFT_PARTIAL != 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"
@@ -1011,6 +1086,8 @@
       return 1;
     }
   }
+  // Set up mcld::LinkerConfig
+  LDConfig.setTriple(TheTriple);
 
   // Package up features to be passed to target/subtarget
   std::string FeaturesStr;
@@ -1060,34 +1137,26 @@
   Options.TrapFuncName = TrapFuncName;
   Options.EnableSegmentedStacks = SegmentedStacks;
 
-  std::auto_ptr<mcld::LLVMTargetMachine> target_machine(
+  std::auto_ptr<mcld::MCLDTargetMachine> target_machine(
           TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr, Options,
                                          ArgRelocModel, CMModel, OLvl));
   assert(target_machine.get() && "Could not allocate target machine!");
-  mcld::LLVMTargetMachine &TheTargetMachine = *target_machine.get();
+  mcld::MCLDTargetMachine &TheTargetMachine = *target_machine.get();
 
   TheTargetMachine.getTM().setMCUseLoc(false);
   TheTargetMachine.getTM().setMCUseCFI(false);
 
-  // Set up mcld::outs() and mcld::errs()
-  InitializeOStreams(TheTargetMachine.getLDInfo());
-
-  // Set up MsgHandler
+  // FIXME: Move the initialization of LineInfo to mcld::Linker when we
+  // finish LineInfo's implementation.
   OwningPtr<mcld::DiagnosticLineInfo>
     diag_line_info(TheTarget->createDiagnosticLineInfo(*TheTarget,
                                                        TheTriple.getTriple()));
-  OwningPtr<mcld::DiagnosticPrinter>
-    diag_printer(new mcld::TextDiagnosticPrinter(mcld::errs(),
-                                                TheTargetMachine.getLDInfo()));
 
-  mcld::InitializeDiagnosticEngine(TheTargetMachine.getLDInfo(),
-                                   diag_line_info.take(),
-                                   diag_printer.get());
-
+  mcld::getDiagnosticEngine().setLineInfo(*diag_line_info.take());
 
   // Figure out where we are going to send the output...
-  OwningPtr<tool_output_file>
+  OwningPtr<mcld::ToolOutputFile>
   Out(GetOutputStream(TheTarget->get()->getName(),
                       TheTriple.getOS(),
                       ArgFileType,
@@ -1110,30 +1179,14 @@
   // Override default to generate verbose assembly.
   TheTargetMachine.getTM().setAsmVerbosityDefault(true);
 
-  // Process the linker input from the command line
-  mcld::SectLinkerOption *LinkerOpt =
-      new mcld::SectLinkerOption(TheTargetMachine.getLDInfo());
-
-  if (!ProcessLinkerOptionsFromCommand(TheTargetMachine.getLDInfo())) {
-    errs() << argv[0] << ": failed to process linker options from command line!\n";
-    return 1;
-  }
-
-  if (!ProcessLinkerInputsFromCommand(*LinkerOpt)) {
-    errs() << argv[0] << ": failed to process inputs from command line!\n";
-    return 1;
-  }
-
   {
-    formatted_raw_ostream FOS(Out->os());
-
     // Ask the target to add backend passes as necessary.
     if( TheTargetMachine.addPassesToEmitFile(PM,
-                                             FOS,
-                                             ArgOutputFilename.native(),
+                                             *Out,
                                              ArgFileType,
                                              OLvl,
-                                             LinkerOpt,
+                                             LDIRModule,
+                                             LDConfig,
                                              NoVerify)) {
       errs() << argv[0] << ": target does not support generation of this"
              << " file type!\n";
@@ -1148,20 +1201,6 @@
 
   // Declare success.
   Out->keep();
-
-  // clean up
-  delete LinkerOpt;
-
-  if (0 != diag_printer->getNumErrors()) {
-    // If we reached here, we are failing ungracefully. Run the interrupt handlers
-    // to make sure any special cleanups get done, in particular that we remove
-    // files registered with RemoveFileOnSignal.
-    llvm::sys::RunInterruptHandlers();
-    diag_printer->finish();
-    exit(1);
-  }
-
-  diag_printer->finish();
   return 0;
 }
 
diff --git a/tools/mcld/include/alone/Linker.h b/tools/mcld/include/alone/Linker.h
index 9321e94..b0bdc5e 100644
--- a/tools/mcld/include/alone/Linker.h
+++ b/tools/mcld/include/alone/Linker.h
@@ -14,12 +14,17 @@
 
 namespace mcld {
 
+class Module;
 class TargetLDBackend;
-class MCLDDriver;
-class MemoryFactory;
-class MCLDInfo;
+class ObjectLinker;
+class ContextFactory;
+class LinkerConfig;
 class TreeIteratorBase;
 class Input;
+class InputFactory;
+class InputBuilder;
+class MemoryArea;
+class MemoryAreaFactory;
 
 namespace sys { namespace fs {
 
@@ -31,7 +36,6 @@
 
 namespace alone {
 
-class MemoryFactory;
 class LinkerConfig;
 
 class Linker {
@@ -50,19 +54,23 @@
     kReadSections,
     kReadSymbols,
     kAddAdditionalSymbols,
-    kMaxErrorCode,
+    kMaxErrorCode
   };
 
   static const char *GetErrorString(enum ErrorCode pErrCode);
 
 private:
+  const mcld::LinkerConfig *mLDConfig;
+  mcld::Module *mModule;
   mcld::TargetLDBackend *mBackend;
-  mcld::MCLDDriver *mDriver;
-  MemoryFactory *mMemAreaFactory;
-  mcld::MCLDInfo *mLDInfo;
+  mcld::ObjectLinker *mObjLinker;
+  mcld::InputFactory *mInputFactory;
+  mcld::MemoryAreaFactory *mMemAreaFactory;
+  mcld::ContextFactory *mContextFactory;
+  mcld::InputBuilder *mBuilder;
   mcld::TreeIteratorBase *mRoot;
-  bool mShared;
   std::string mSOName;
+  mcld::MemoryArea* mOutput;
 
 public:
   Linker();
diff --git a/tools/mcld/include/alone/Support/LinkerConfig.h b/tools/mcld/include/alone/Support/LinkerConfig.h
index f29e557..0aa3277 100644
--- a/tools/mcld/include/alone/Support/LinkerConfig.h
+++ b/tools/mcld/include/alone/Support/LinkerConfig.h
@@ -12,7 +12,7 @@
 
 #include <string>
 
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/LD/DiagnosticLineInfo.h>
 #include <mcld/LD/DiagnosticPrinter.h>
@@ -25,7 +25,6 @@
   // Available Configurations
   //===--------------------------------------------------------------------===//
   const std::string mTriple;
-  bool mShared;
   std::string mSOName;
 
 private:
@@ -35,7 +34,7 @@
   const mcld::Target *mTarget;
   bool initializeTarget();
 
-  mcld::MCLDInfo *mLDInfo;
+  mcld::LinkerConfig *mLDConfig;
   bool initializeLDInfo();
 
   mcld::DiagnosticLineInfo *mDiagLineInfo;
@@ -43,6 +42,26 @@
   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
   //===--------------------------------------------------------------------===//
@@ -52,14 +71,13 @@
   inline const mcld::Target *getTarget() const
   { return mTarget; }
 
-  inline mcld::MCLDInfo* getLDInfo()
-  { return mLDInfo; }
+  inline mcld::LinkerConfig* getLDConfig()
+  { return mLDConfig; }
 
-  inline const mcld::MCLDInfo* getLDInfo() const
-  { return mLDInfo; }
+  inline const mcld::LinkerConfig* getLDConfig() const
+  { return mLDConfig; }
 
-  inline bool isShared() const
-  { return mShared; }
+  bool isShared() const;
 
   inline std::string getSOName() const
   { return mSOName; }
@@ -74,6 +92,8 @@
 
   void setSysRoot(const std::string &pSysRoot);
 
+  void setZOption(unsigned int pOptions);
+
   void addWrap(const std::string &pWrapSymbol);
 
   void addPortable(const std::string &pPortableSymbol);
diff --git a/tools/mcld/include/alone/Support/MemoryFactory.h b/tools/mcld/include/alone/Support/MemoryFactory.h
deleted file mode 100644
index 132d20f..0000000
--- a/tools/mcld/include/alone/Support/MemoryFactory.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- MemoryFactory.h ----------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALONE_SUPPORT_MEMORY_FACTORY_H
-#define ALONE_SUPPORT_MEMORY_FACTORY_H
-
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-
-namespace mcld {
-class MemoryArea;
-} // end namespace mcld
-
-namespace alone {
-
-class MemoryFactory : public mcld::MemoryAreaFactory {
-public:
-  MemoryFactory() : mcld::MemoryAreaFactory(32) { }
-
-  ~MemoryFactory() { }
-
-  using mcld::MemoryAreaFactory::produce;
-
-  mcld::MemoryArea* produce(void *pMemBuffer, size_t pSize)
-  { return mcld::MemoryAreaFactory::create(pMemBuffer, pSize); }
-
-  mcld::MemoryArea* produce(int pFD)
-  { return mcld::MemoryAreaFactory::create(pFD, mcld::FileHandle::Unknown); }
-};
-
-} // end namespace alone
-
-#endif // ALONE_SUPPORT_MEMORY_FACTORY_H
diff --git a/tools/mcld/include/alone/Support/TargetLinkerConfigs.h b/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
index 40bc812..3bb6b7b 100644
--- a/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
+++ b/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
@@ -74,6 +74,16 @@
 #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
index a9ebc1f..d3f1450 100644
--- a/tools/mcld/lib/Core/Linker.cpp
+++ b/tools/mcld/lib/Core/Linker.cpp
@@ -9,15 +9,18 @@
 
 #include "alone/Linker.h"
 #include "alone/Support/LinkerConfig.h"
-#include "alone/Support/MemoryFactory.h"
 #include "alone/Support/Log.h"
 
 #include <llvm/Support/ELF.h>
 
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/InputTree.h>
+#include <mcld/Module.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/InputTree.h>
+#include <mcld/Object/ObjectLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/MC/ContextFactory.h>
+#include <mcld/MC/InputBuilder.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/LDContext.h>
 #include <mcld/Target/TargetLDBackend.h>
@@ -72,13 +75,15 @@
 // Linker
 //===----------------------------------------------------------------------===//
 Linker::Linker()
-  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
-    mRoot(NULL), mShared(false) {
+  : mLDConfig(NULL), mModule(NULL), mBackend(NULL), mObjLinker(NULL),
+    mInputFactory(NULL), mMemAreaFactory(NULL), mContextFactory(NULL),
+    mBuilder(NULL), mRoot(NULL), mOutput(NULL) {
 }
 
 Linker::Linker(const LinkerConfig& pConfig)
-  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
-    mRoot(NULL), mShared(false) {
+  : mLDConfig(NULL), mModule(NULL), mBackend(NULL), mObjLinker(NULL),
+    mInputFactory(NULL), mMemAreaFactory(NULL), mContextFactory(NULL),
+    mBuilder(NULL), mRoot(NULL), mOutput(NULL) {
 
   const std::string &triple = pConfig.getTriple();
 
@@ -92,42 +97,57 @@
 }
 
 Linker::~Linker() {
-  delete mDriver;
+  delete mModule;
+  delete mObjLinker;
+  // FIXME: current implementation can not change the order of deleting
+  // ObjectLinker and TargetLDBackend. Because the deletion of relocation list
+  // in FragmentLinker (FragmentLinker is deleted by ObjectLinker) depends on
+  // RelocationFactory in TargetLDBackend
   delete mBackend;
-  delete mMemAreaFactory;
+  delete mBuilder;
   delete mRoot;
 }
 
 enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
-  mLDInfo = const_cast<mcld::MCLDInfo*>(pConfig.getLDInfo());
-  if (mLDInfo == NULL) {
+  mLDConfig = pConfig.getLDConfig();
+  if (mLDConfig == NULL) {
     return kDelegateLDInfo;
   }
-
-  mRoot = new mcld::InputTree::iterator(mLDInfo->inputs().root());
-  mShared = pConfig.isShared();
-  mSOName = pConfig.getSOName();
-
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
-  if (mLDInfo != NULL) {
+  if (mLDConfig != NULL) {
     return kDoubleConfig;
   }
 
   extractFiles(pConfig);
 
-  mBackend = pConfig.getTarget()->createLDBackend(pConfig.getTriple());
+  mBackend = pConfig.getTarget()->createLDBackend(*mLDConfig);
   if (mBackend == NULL) {
     return kCreateBackend;
   }
 
-  mMemAreaFactory = new MemoryFactory();
+  mInputFactory = new mcld::InputFactory(32, *mLDConfig);
 
-  mDriver = new mcld::MCLDDriver(*mLDInfo, *mBackend, *mMemAreaFactory);
+  mContextFactory = new mcld::ContextFactory(32);
+    /* 32 is a magic number, the estimated number of input files **/
 
-  mDriver->initMCLinker();
+  mMemAreaFactory = new mcld::MemoryAreaFactory(32);
+
+  mBuilder = new mcld::InputBuilder(*mLDConfig,
+                                    *mInputFactory,
+                                    *mContextFactory,
+                                    *mMemAreaFactory,
+                                    true); // delegated
+
+  mModule = new mcld::Module(mLDConfig->options().soname());
+
+  mRoot = new mcld::InputTree::iterator(mModule->getInputTree().root());
+
+  mObjLinker = new mcld::ObjectLinker(*mLDConfig, *mModule, *mBuilder, *mBackend);
+
+  mObjLinker->initFragmentLinker();
 
   return kSuccess;
 }
@@ -153,43 +173,42 @@
     return pCode;
   }
 
-  mcld::LDContext *input_context = mLDInfo->contextFactory().produce(pPath);
-  pInput.setContext(input_context);
+  mBuilder->setContext(pInput);
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
-  mcld::sys::fs::Path* path = NULL;
+  const mcld::sys::fs::Path* path = NULL;
   // find out the real path of the namespec.
-  if (mLDInfo->attrFactory().constraint().isSharedSystem()) {
+  if (mLDConfig->attribute().constraint().isSharedSystem()) {
     // In the system with shared object support, we can find both archive
     // and shared object.
 
-    if (mLDInfo->attrFactory().last().isStatic()) {
+    if (mInputFactory->attr().isStatic()) {
       // with --static, we must search an archive.
-      path = mLDInfo->options().directories().find(pNameSpec,
-                                                   mcld::Input::Archive);
+      path = mLDConfig->options().directories().find(pNameSpec,
+                                                     mcld::Input::Archive);
     }
     else {
       // otherwise, with --Bdynamic, we can find either an archive or a
       // shared object.
-      path = mLDInfo->options().directories().find(pNameSpec,
-                                                   mcld::Input::DynObj);
+      path = mLDConfig->options().directories().find(pNameSpec,
+                                                     mcld::Input::DynObj);
     }
   }
   else {
     // In the system without shared object support, we only look for an
     // archive.
-    path = mLDInfo->options().directories().find(pNameSpec,
+    path = mLDConfig->options().directories().find(pNameSpec,
                                                  mcld::Input::Archive);
   }
 
   if (NULL == path)
     return kFindNameSpec;
 
-  mcld::Input* input = mLDInfo->inputFactory().produce(pNameSpec, *path,
-                                                       mcld::Input::Unknown);
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
+  mcld::Input* input = mInputFactory->produce(pNameSpec, *path,
+                                              mcld::Input::Unknown);
+  mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
 
   advanceRoot();
 
@@ -198,11 +217,11 @@
 
 /// addObject - Add a object file by the filename.
 enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
-  mcld::Input* input = mLDInfo->inputFactory().produce(pObjectPath,
-                                                       pObjectPath,
-                                                       mcld::Input::Unknown);
+  mcld::Input* input = mInputFactory->produce(pObjectPath,
+                                              pObjectPath,
+                                              mcld::Input::Unknown);
 
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
+  mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
 
   advanceRoot();
 
@@ -212,165 +231,120 @@
 /// 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 = mLDInfo->inputFactory().produce("memory object",
-                                                       "NAN",
-                                                       mcld::Input::Unknown);
+  mcld::Input* input = mInputFactory->produce("memory object", "NAN",
+                                              mcld::Input::Unknown);
 
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
+  mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
 
   advanceRoot();
 
   mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
   input->setMemArea(input_memory);
 
-  mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
+  mcld::LDContext *input_context = mContextFactory->produce();
   input->setContext(input_context);
 
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
-  mcld::Input* input = mLDInfo->inputFactory().produce("code object",
-                                                       "NAN",
-                                                       mcld::Input::External);
+  mcld::Input* input = mInputFactory->produce("code object", "NAN",
+                                              mcld::Input::External);
 
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
+  mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
 
   advanceRoot();
 
   mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
   input->setMemArea(input_memory);
 
-  mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
+  mcld::LDContext *input_context = mContextFactory->produce();
   input->setContext(input_context);
 
-  // FIXME: So far, MCLinker must set up output before add input files.
+  // FIXME: So far, FragmentLinker must set up output before add input files.
   // set up LDContext
-  if (mDriver->hasInitLinker()) {
+  if (mObjLinker->hasInitLinker()) {
     return kNotConfig;
   }
 
-  if (!mLDInfo->output().hasContext()) {
-    return kNotSetUpOutput;
-  }
-
   // create NULL section
-  mcld::LDSection& null =
-      mDriver->getLinker()->createSectHdr("",
-                                          mcld::LDFileFormat::Null,
-                                          llvm::ELF::SHT_NULL,
-                                          0);
-
-  null.setSize(0);
-  null.setOffset(0);
-  null.setIndex(0);
-  null.setInfo(0);
-  null.setAlign(0);
-
-  input_context->getSectionTable().push_back(&null);
+  mcld::LDSection* null = mcld::IRBuilder::CreateELFHeader(*input, "",
+                              llvm::ELF::SHT_NULL, 0, 0);
+  null->setSize(0);
+  null->setOffset(0);
+  null->setInfo(0);
 
   // create .text section
-  mcld::LDSection& text = mDriver->getLinker()->createSectHdr(".text",
-                              mcld::LDFileFormat::Regular,
+  mcld::LDSection* text = mcld::IRBuilder::CreateELFHeader(*input, ".text",
                               llvm::ELF::SHT_PROGBITS,
-                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR);
+                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
+                              1);
 
-  text.setSize(pSize);
-  text.setOffset(0x0);
-  text.setIndex(1);
-  text.setInfo(0);
-  text.setAlign(1);
-
-  input_context->getSectionTable().push_back(&text);
+  text->setSize(pSize);
+  text->setOffset(0x0);
+  text->setInfo(0);
 
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
-  if (mLDInfo->output().hasContext()) {
-    return kDoubleConfig;
-  }
-
   // -----  initialize output file  ----- //
-
   mcld::FileHandle::Permission perm = 0755;
 
-  mcld::MemoryArea* out_area = mMemAreaFactory->produce(
+  mOutput = mMemAreaFactory->produce(
                       pPath,
                       mcld::FileHandle::ReadWrite |
                         mcld::FileHandle::Truncate |
                         mcld::FileHandle::Create,
                       perm);
 
-  if (!out_area->handler()->isGood()) {
+  if (!mOutput->handler()->isGood()) {
     return kOpenOutput;
   }
 
-  if (mShared) {
-    mLDInfo->output().setType(mcld::Output::DynObj);
-  } else {
-    mLDInfo->output().setType(mcld::Output::Exec);
-  }
-
-  mLDInfo->output().setSOName(mSOName);
-  mLDInfo->output().setMemArea(out_area);
-  mLDInfo->output().setContext(mLDInfo->contextFactory().produce(pPath));
-
-  // FIXME: We must initialize MCLinker before setOutput, and initialize
-  // standard sections here. This is because we have to build the section
-  // map before input files using it.
-  if (!mDriver->hasInitLinker()) {
-    return kNotConfig;
-  }
-
-  mDriver->initStdSections();
-
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
-  if (mLDInfo->output().hasContext()) {
-    return kDoubleConfig;
+  mOutput = mMemAreaFactory->produce(pFileHandler, mcld::FileHandle::ReadWrite);
+
+  if (!mOutput->handler()->isGood()) {
+    return kOpenOutput;
   }
 
-  // -----  initialize output file  ----- //
-  mcld::MemoryArea* out_area = mMemAreaFactory->produce(pFileHandler);
-
-  mLDInfo->output().setType(mcld::Output::DynObj);
-  mLDInfo->output().setMemArea(out_area);
-  mLDInfo->output().setContext(mLDInfo->contextFactory().produce());
-
-  // FIXME: We must initialize MCLinker before setOutput, and initialize
-  // standard sections here. This is because we have to build the section
-  // map before input files using it.
-  if (!mDriver->hasInitLinker()) {
-    return kNotConfig;
-  }
-
-  mDriver->initStdSections();
-
   return kSuccess;
 }
 
 enum Linker::ErrorCode Linker::link() {
-  mDriver->normalize();
+  if (NULL == mOutput)
+    return kNotSetUpOutput;
 
-  if (!mDriver->mergeSections()) {
-    return kReadSections;
+  if (!mObjLinker->hasInitLinker()) {
+    return kNotConfig;
   }
 
-  if (!mDriver->addStandardSymbols() || !mDriver->addTargetSymbols()) {
+  mObjLinker->initStdSections();
+
+  mObjLinker->normalize();
+
+  if (!mObjLinker->readRelocations())
+    return kReadSections;
+
+  if (!mObjLinker->mergeSections())
+    return kReadSections;
+
+  if (!mObjLinker->addStandardSymbols() || !mObjLinker->addTargetSymbols()) {
     return kAddAdditionalSymbols;
   }
 
-  mDriver->readRelocations();
-  mDriver->prelayout();
-  mDriver->layout();
-  mDriver->postlayout();
-  mDriver->finalizeSymbolValue();
-  mDriver->relocation();
-  mDriver->emitOutput();
-  mDriver->postProcessing();
+  mObjLinker->scanRelocations();
+  mObjLinker->prelayout();
+  mObjLinker->layout();
+  mObjLinker->postlayout();
+  mObjLinker->finalizeSymbolValue();
+  mObjLinker->relocation();
+  mObjLinker->emitOutput(*mOutput);
+  mObjLinker->postProcessing(*mOutput);
 
   return kSuccess;
 }
diff --git a/tools/mcld/lib/Support/Initialization.cpp b/tools/mcld/lib/Support/Initialization.cpp
index 9a95f74..71bd57d 100644
--- a/tools/mcld/lib/Support/Initialization.cpp
+++ b/tools/mcld/lib/Support/Initialization.cpp
@@ -48,10 +48,10 @@
   LLVMInitializeARMTargetMC();
   LLVMInitializeARMTargetInfo();
   LLVMInitializeARMTarget();
-  LLVMInitializeARMLDTargetInfo();
-  LLVMInitializeARMLDTarget();
-  LLVMInitializeARMLDBackend();
-  LLVMInitializeARMDiagnosticLineInfo();
+  MCLDInitializeARMLDTargetInfo();
+  MCLDInitializeARMLDTarget();
+  MCLDInitializeARMLDBackend();
+  MCLDInitializeARMDiagnosticLineInfo();
 #endif
 
 #if defined(PROVIDE_MIPS_CODEGEN)
@@ -62,10 +62,10 @@
   LLVMInitializeMipsTargetMC();
   LLVMInitializeMipsTargetInfo();
   LLVMInitializeMipsTarget();
-  LLVMInitializeMipsLDTargetInfo();
-  LLVMInitializeMipsLDTarget();
-  LLVMInitializeMipsLDBackend();
-  LLVMInitializeMipsDiagnosticLineInfo();
+  MCLDInitializeMipsLDTargetInfo();
+  MCLDInitializeMipsLDTarget();
+  MCLDInitializeMipsLDBackend();
+  MCLDInitializeMipsDiagnosticLineInfo();
 #endif
 
 #if defined(PROVIDE_X86_CODEGEN)
@@ -76,10 +76,10 @@
   LLVMInitializeX86TargetMC();
   LLVMInitializeX86TargetInfo();
   LLVMInitializeX86Target();
-  LLVMInitializeX86LDTargetInfo();
-  LLVMInitializeX86LDTarget();
-  LLVMInitializeX86LDBackend();
-  LLVMInitializeX86DiagnosticLineInfo();
+  MCLDInitializeX86LDTargetInfo();
+  MCLDInitializeX86LDTarget();
+  MCLDInitializeX86LDBackend();
+  MCLDInitializeX86DiagnosticLineInfo();
 #endif
 
   is_initialized = true;
diff --git a/tools/mcld/lib/Support/LinkerConfig.cpp b/tools/mcld/lib/Support/LinkerConfig.cpp
index ea30e69..3a53ae1 100644
--- a/tools/mcld/lib/Support/LinkerConfig.cpp
+++ b/tools/mcld/lib/Support/LinkerConfig.cpp
@@ -12,9 +12,9 @@
 
 #include <llvm/Support/Signals.h>
 
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDFile.h>
+#include <mcld/LinkerConfig.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>
@@ -23,7 +23,7 @@
 using namespace alone;
 
 LinkerConfig::LinkerConfig(const std::string &pTriple)
-  : mTriple(pTriple), mShared(false), mSOName(), mTarget(NULL), mLDInfo(NULL),
+  : mTriple(pTriple), mSOName(), mTarget(NULL), mLDConfig(NULL),
     mDiagLineInfo(NULL), mDiagPrinter(NULL) {
 
   initializeTarget();
@@ -32,7 +32,7 @@
 }
 
 LinkerConfig::~LinkerConfig() {
-  delete mLDInfo;
+  delete mLDConfig;
 
   if (mDiagPrinter->getNumErrors() != 0) {
     // If here, the program failed ungracefully. Run the interrupt handlers to
@@ -59,58 +59,219 @@
 }
 
 bool LinkerConfig::initializeLDInfo() {
-  if (NULL != mLDInfo) {
+  if (NULL != mLDConfig) {
     ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
           mTriple.c_str());
     return false;
   }
 
-  mLDInfo = new mcld::MCLDInfo(getTriple(), 1, 32);
+  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;
+      mLDConfig->scripts().sectionMap().append(map[i].from,
+                                               map[i].to,
+                                               exist);
+    }
+  }
   return true;
 }
 
 bool LinkerConfig::initializeDiagnostic() {
   // Set up MsgHandler.
+  mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDConfig);
+
+  mcld::InitializeDiagnosticEngine(*mLDConfig, mDiagPrinter);
+
   mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
 
-  mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDInfo);
-
-  mcld::InitializeDiagnosticEngine(*mLDInfo, mDiagLineInfo, mDiagPrinter);
-
+  mcld::getDiagnosticEngine().setLineInfo(*mDiagLineInfo);
   return true;
 }
 
+bool LinkerConfig::isShared() const {
+  return (mcld::LinkerConfig::DynObj == mLDConfig->codeGenType());
+}
+
 void LinkerConfig::setShared(bool pEnable) {
-  mShared = pEnable;
+  if (pEnable)
+    mLDConfig->setCodeGenType(mcld::LinkerConfig::DynObj);
+  else
+    mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
   return;
 }
 
 void LinkerConfig::setBsymbolic(bool pEnable) {
-  mLDInfo->options().setBsymbolic(pEnable);
+  mLDConfig->options().setBsymbolic(pEnable);
   return;
 }
 
 void LinkerConfig::setSOName(const std::string &pSOName) {
-  mSOName = pSOName;
+  mLDConfig->options().setSOName(pSOName);
   return;
 }
 
 void LinkerConfig::setDyld(const std::string &pDyld) {
-  mLDInfo->options().setDyld(pDyld);
+  mLDConfig->options().setDyld(pDyld);
   return;
 }
 
 void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
-  mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
+  mLDConfig->options().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 =
-               mLDInfo->scripts().renameMap().insert(pWrapSymbol, exist);
+               mLDConfig->scripts().renameMap().insert(pWrapSymbol, exist);
 
   std::string to_wrap_str = "__wrap_" + pWrapSymbol;
   to_wrap->setValue(to_wrap_str);
@@ -122,7 +283,7 @@
   // Add __real_wname -> wname.
   std::string from_real_str = "__real_" + pWrapSymbol;
   mcld::StringEntry<llvm::StringRef>* from_real =
-             mLDInfo->scripts().renameMap().insert(from_real_str, exist);
+             mLDConfig->scripts().renameMap().insert(from_real_str, exist);
   from_real->setValue(pWrapSymbol);
 
   if (exist) {
@@ -137,7 +298,7 @@
 
   // Add pname -> pname_portable.
   mcld::StringEntry<llvm::StringRef>* to_port =
-                mLDInfo->scripts().renameMap().insert(pPortableSymbol, exist);
+                mLDConfig->scripts().renameMap().insert(pPortableSymbol, exist);
 
   std::string to_port_str = pPortableSymbol + "_portable";
   to_port->setValue(to_port_str);
@@ -149,7 +310,7 @@
   // Add __real_pname -> pname.
   std::string from_real_str = "__real_" + pPortableSymbol;
   mcld::StringEntry<llvm::StringRef>* from_real =
-           mLDInfo->scripts().renameMap().insert(from_real_str, exist);
+           mLDConfig->scripts().renameMap().insert(from_real_str, exist);
 
   from_real->setValue(pPortableSymbol);
 
@@ -162,17 +323,7 @@
 
 void LinkerConfig::addSearchDir(const std::string &pDirPath) {
   // SearchDirs will remove the created MCLDDirectory.
-  mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
-
-  if (sd->isInSysroot()) {
-    sd->setSysroot(mLDInfo->options().sysroot());
+  if (!mLDConfig->options().directories().insert(pDirPath)) {
+    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
   }
-
-  if (exists(sd->path()) && is_directory(sd->path())) {
-    mLDInfo->options().directories().add(*sd);
-  } else {
-    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
-  }
-
-  return;
 }
diff --git a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
index f2ddd6f..0382c2a 100644
--- a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
+++ b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
@@ -10,6 +10,8 @@
 #include "alone/Config/Config.h"
 #include "alone/Support/TargetLinkerConfigs.h"
 
+#include <mcld/MC/InputFactory.h>
+
 using namespace alone;
 
 #ifdef TARGET_BUILD
@@ -27,21 +29,29 @@
 ARMLinkerConfig::ARMLinkerConfig() : LinkerConfig(DEFAULT_ARM_TRIPLE_STRING) {
 
   // set up target-dependent constraints of attributes
-  getLDInfo()->attrFactory().constraint().enableWholeArchive();
-  getLDInfo()->attrFactory().constraint().disableAsNeeded();
-  getLDInfo()->attrFactory().constraint().setSharedSystem();
+  getLDConfig()->attribute().constraint().enableWholeArchive();
+  getLDConfig()->attribute().constraint().disableAsNeeded();
+  getLDConfig()->attribute().constraint().setSharedSystem();
 
   // set up the predefined attributes
-  getLDInfo()->attrFactory().predefined().setWholeArchive();
-  getLDInfo()->attrFactory().predefined().setDynamic();
+  getLDConfig()->attribute().predefined().unsetWholeArchive();
+  getLDConfig()->attribute().predefined().setDynamic();
 
   // set up target dependent options
-  if (getLDInfo()->options().sysroot().empty()) {
-    getLDInfo()->options().setSysroot(gDefaultSysroot);
+  if (getLDConfig()->options().sysroot().empty()) {
+    getLDConfig()->options().setSysroot(gDefaultSysroot);
   }
 
-  if (!getLDInfo()->options().hasDyld()) {
-    getLDInfo()->options().setDyld(gDefaultDyld);
+  if (!getLDConfig()->options().hasDyld()) {
+    getLDConfig()->options().setDyld(gDefaultDyld);
+  }
+
+  // set up section map
+  if (getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
+    bool exist = false;
+    getLDConfig()->scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
+    getLDConfig()->scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
+    getLDConfig()->scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
   }
 }
 #endif // defined(PROVIDE_ARM_CODEGEN)
@@ -54,21 +64,21 @@
   : LinkerConfig(DEFAULT_MIPS_TRIPLE_STRING) {
 
   // set up target-dependent constraints of attibutes
-  getLDInfo()->attrFactory().constraint().enableWholeArchive();
-  getLDInfo()->attrFactory().constraint().disableAsNeeded();
-  getLDInfo()->attrFactory().constraint().setSharedSystem();
+  getLDConfig()->attribute().constraint().enableWholeArchive();
+  getLDConfig()->attribute().constraint().disableAsNeeded();
+  getLDConfig()->attribute().constraint().setSharedSystem();
 
   // set up the predefined attributes
-  getLDInfo()->attrFactory().predefined().setWholeArchive();
-  getLDInfo()->attrFactory().predefined().setDynamic();
+  getLDConfig()->attribute().predefined().unsetWholeArchive();
+  getLDConfig()->attribute().predefined().setDynamic();
 
   // set up target dependent options
-  if (getLDInfo()->options().sysroot().empty()) {
-    getLDInfo()->options().setSysroot(gDefaultSysroot);
+  if (getLDConfig()->options().sysroot().empty()) {
+    getLDConfig()->options().setSysroot(gDefaultSysroot);
   }
 
-  if (!getLDInfo()->options().hasDyld()) {
-    getLDInfo()->options().setDyld(gDefaultDyld);
+  if (!getLDConfig()->options().hasDyld()) {
+    getLDConfig()->options().setDyld(gDefaultDyld);
   }
 }
 #endif // defined(PROVIDE_MIPS_CODEGEN)
@@ -80,21 +90,21 @@
 X86FamilyLinkerConfigBase::X86FamilyLinkerConfigBase(const std::string& pTriple)
   : LinkerConfig(pTriple) {
   // set up target-dependent constraints of attibutes
-  getLDInfo()->attrFactory().constraint().enableWholeArchive();
-  getLDInfo()->attrFactory().constraint().disableAsNeeded();
-  getLDInfo()->attrFactory().constraint().setSharedSystem();
+  getLDConfig()->attribute().constraint().enableWholeArchive();
+  getLDConfig()->attribute().constraint().disableAsNeeded();
+  getLDConfig()->attribute().constraint().setSharedSystem();
 
   // set up the predefined attributes
-  getLDInfo()->attrFactory().predefined().setWholeArchive();
-  getLDInfo()->attrFactory().predefined().setDynamic();
+  getLDConfig()->attribute().predefined().unsetWholeArchive();
+  getLDConfig()->attribute().predefined().setDynamic();
 
   // set up target dependent options
-  if (getLDInfo()->options().sysroot().empty()) {
-    getLDInfo()->options().setSysroot(gDefaultSysroot);
+  if (getLDConfig()->options().sysroot().empty()) {
+    getLDConfig()->options().setSysroot(gDefaultSysroot);
   }
 
-  if (!getLDInfo()->options().hasDyld()) {
-    getLDInfo()->options().setDyld(gDefaultDyld);
+  if (!getLDConfig()->options().hasDyld()) {
+    getLDConfig()->options().setDyld(gDefaultDyld);
   }
 }
 
@@ -106,3 +116,29 @@
   : 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 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()->triple().getArch() &&
+      getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
+    bool exist = false;
+    getLDConfig()->scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
+    getLDConfig()->scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
+    getLDConfig()->scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
+  }
+}
+#endif // defined(TARGET_BUILD)
diff --git a/tools/mcld/main.cpp b/tools/mcld/main.cpp
index ef525f5..a66fb7c 100644
--- a/tools/mcld/main.cpp
+++ b/tools/mcld/main.cpp
@@ -182,7 +182,7 @@
 #ifdef TARGET_BUILD
   config = new (std::nothrow) DefaultLinkerConfig();
 #else
-  config = new (std::nothrow) LinkerConfig(OptTargetTriple);
+  config = new (std::nothrow) GeneralLinkerConfig(OptTargetTriple);
 #endif
   if (config == NULL) {
     llvm::errs() << "Out of memory when create the linker configuration!\n";
diff --git a/unittests/BinTreeTest.cpp b/unittests/BinTreeTest.cpp
index fdf2bd1..5d2cd0a 100644
--- a/unittests/BinTreeTest.cpp
+++ b/unittests/BinTreeTest.cpp
@@ -8,8 +8,8 @@
 //===----------------------------------------------------------------------===//
 #include "BinTreeTest.h"
 
-#include "mcld/ADT/TypeTraits.h"
-#include "mcld/MC/InputTree.h"
+#include <mcld/ADT/TypeTraits.h>
+#include <mcld/InputTree.h>
 #include <string>
 
 using namespace mcld;
@@ -44,8 +44,8 @@
 //
 
 
-/// General 
-TEST_F( BinTreeTest,Two_non_null_tree_merge) 
+/// General
+TEST_F( BinTreeTest,Two_non_null_tree_merge)
 {
   BinaryTree<int>::iterator pos = m_pTestee->root();
   m_pTestee->join<TreeIteratorBase::Rightward>(pos,0);
@@ -63,16 +63,16 @@
   mergeTree->join<TreeIteratorBase::Rightward>(pos2,1);
   mergeTree->join<TreeIteratorBase::Leftward>(pos2,1);
 
-  m_pTestee->merge<TreeIteratorBase::Rightward>(pos,*mergeTree); 
+  m_pTestee->merge<TreeIteratorBase::Rightward>(pos,*mergeTree);
   delete mergeTree;
   EXPECT_TRUE(m_pTestee->size()==8);
 }
 
 /// ---- TEST - 2 ----
-TEST_F( BinTreeTest, A_null_tree_merge_a_non_null_tree) 
-{ 
+TEST_F( BinTreeTest, A_null_tree_merge_a_non_null_tree)
+{
   BinaryTree<int>::iterator pos = m_pTestee->root();
- 
+
   BinaryTree<int> *mergeTree = new BinaryTree<int>;
   mergeTree->join<TreeIteratorBase::Rightward>(pos,0);
   --pos;
@@ -82,14 +82,14 @@
   mergeTree->join<TreeIteratorBase::Rightward>(pos,2);
   mergeTree->join<TreeIteratorBase::Leftward>(pos,2);
 
-  m_pTestee->merge<TreeIteratorBase::Rightward>(pos,*mergeTree); 
+  m_pTestee->merge<TreeIteratorBase::Rightward>(pos,*mergeTree);
 
   delete mergeTree;
   EXPECT_TRUE(m_pTestee->size()==5);
 }
 
-TEST_F( BinTreeTest, A_non_null_tree_merge_a_null_tree) 
-{ 
+TEST_F( BinTreeTest, A_non_null_tree_merge_a_null_tree)
+{
   BinaryTree<int>::iterator pos = m_pTestee->root();
   m_pTestee->join<TreeIteratorBase::Rightward>(pos,0);
   --pos;
@@ -98,24 +98,24 @@
   --pos;
   m_pTestee->join<TreeIteratorBase::Rightward>(pos,2);
   m_pTestee->join<TreeIteratorBase::Leftward>(pos,2);
-  
+
   BinaryTree<int> *mergeTree = new BinaryTree<int>;
-  BinaryTree<int>::iterator pos2 = mergeTree->root(); 
-  mergeTree->merge<TreeIteratorBase::Rightward>(pos2,*m_pTestee); 
+  BinaryTree<int>::iterator pos2 = mergeTree->root();
+  mergeTree->merge<TreeIteratorBase::Rightward>(pos2,*m_pTestee);
 
   //delete m_pTestee;
   EXPECT_TRUE(mergeTree->size()==5);
   delete mergeTree;
 }
 
-TEST_F( BinTreeTest, Two_null_tree_merge) 
-{ 
+TEST_F( BinTreeTest, Two_null_tree_merge)
+{
   BinaryTree<int>::iterator pos = m_pTestee->root();
- 
-  BinaryTree<int> *mergeTree = new BinaryTree<int>;
-  BinaryTree<int>::iterator pos2 = mergeTree->root(); 
 
-  mergeTree->merge<TreeIteratorBase::Rightward>(pos2,*m_pTestee); 
+  BinaryTree<int> *mergeTree = new BinaryTree<int>;
+  BinaryTree<int>::iterator pos2 = mergeTree->root();
+
+  mergeTree->merge<TreeIteratorBase::Rightward>(pos2,*m_pTestee);
 
   //delete m_pTestee;
   EXPECT_TRUE(mergeTree->size()==0);
@@ -126,7 +126,7 @@
 {
   int a = 111;
   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);
@@ -134,9 +134,9 @@
   pos.move<InputTree::Inclusive>();
   m_pTestee->join<InputTree::Positional>(pos,8);
   m_pTestee->join<InputTree::Inclusive>(pos,7);
-  
-  BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin(); 
-  BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end(); 
+
+  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;
@@ -149,8 +149,8 @@
   ASSERT_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(); 
+  BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
+  BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
 }
 
 TEST_F( BinTreeTest, DFSIterator_RightMostTree)
@@ -165,9 +165,9 @@
   m_pTestee->join<InputTree::Positional>(pos,3);
   pos.move<InputTree::Positional>();
   m_pTestee->join<InputTree::Positional>(pos,4);
-  
-  BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin(); 
-  BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end(); 
+
+  BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
+  BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
 
   ASSERT_EQ(0, **dfs_it);
   ++dfs_it;
@@ -187,8 +187,8 @@
 {
   BinaryTree<int>::iterator pos = m_pTestee->root();
   m_pTestee->join<InputTree::Inclusive>(pos,0);
-  BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin(); 
-  BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end(); 
+  BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
+  BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
   int counter = 0;
   while( dfs_it != dfs_end ) {
     ++counter;
@@ -201,7 +201,7 @@
 {
   int a = 111;
   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);
@@ -209,9 +209,9 @@
   pos.move<InputTree::Inclusive>();
   m_pTestee->join<InputTree::Positional>(pos,8);
   m_pTestee->join<InputTree::Inclusive>(pos,7);
-  
-  BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin(); 
-  BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end(); 
+
+  BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
+  BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
 
   ASSERT_EQ(111, **bfs_it);
   ++bfs_it;
@@ -224,8 +224,8 @@
   ASSERT_EQ(7, **bfs_it);
   ++bfs_it;
   ASSERT_TRUE(bfs_it ==  bfs_end);
-  bfs_it = m_pTestee->bfs_begin(); 
-  bfs_end = m_pTestee->bfs_end(); 
+  bfs_it = m_pTestee->bfs_begin();
+  bfs_end = m_pTestee->bfs_end();
 }
 
 TEST_F( BinTreeTest, BFSIterator_RightMostTree)
@@ -240,9 +240,9 @@
   m_pTestee->join<InputTree::Positional>(pos,3);
   pos.move<InputTree::Positional>();
   m_pTestee->join<InputTree::Positional>(pos,4);
-  
-  BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin(); 
-  BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end(); 
+
+  BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
+  BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
 
   ASSERT_EQ(0, **bfs_it);
   ++bfs_it;
@@ -262,8 +262,8 @@
 {
   BinaryTree<int>::iterator pos = m_pTestee->root();
   m_pTestee->join<InputTree::Inclusive>(pos,0);
-  BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin(); 
-  BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end(); 
+  BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
+  BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
   int counter = 0;
   while( bfs_it != bfs_end ) {
     ++counter;
@@ -272,4 +272,40 @@
   ASSERT_EQ(1, counter);
 }
 
+TEST_F( BinTreeTest, TreeIterator)
+{
+  BinaryTree<int>::iterator pos = m_pTestee->root();
+  m_pTestee->join<InputTree::Inclusive>(pos,0);
+  pos.move<InputTree::Inclusive>();
+  m_pTestee->join<InputTree::Positional>(pos,1);
+  pos.move<InputTree::Positional>();
+  m_pTestee->join<InputTree::Inclusive>(pos,2);
+  m_pTestee->join<InputTree::Positional>(pos,5);
+  pos.move<InputTree::Inclusive>();
+  m_pTestee->join<InputTree::Positional>(pos,3);
+  pos.move<InputTree::Positional>();
+  m_pTestee->join<InputTree::Positional>(pos,4);
+
+  BinaryTree<int>::iterator it = m_pTestee->begin();
+  BinaryTree<int>::iterator end = m_pTestee->end();
+
+  ASSERT_EQ(0, **it);
+  ++it;
+  ASSERT_EQ(1, **it);
+  --it;
+  ASSERT_EQ(2, **it);
+  ++it;
+  ASSERT_EQ(3, **it);
+  ++it;
+  ASSERT_EQ(4, **it);
+  ++it;
+  ASSERT_TRUE(it == end);
+
+  it = m_pTestee->begin();
+  ++it;
+  ++it;
+  ASSERT_EQ(5, **it);
+  ++it;
+  ASSERT_TRUE(it == end);
+}
 
diff --git a/unittests/FileHandleTest.cpp b/unittests/FileHandleTest.cpp
index 993b07c..db6f25f 100644
--- a/unittests/FileHandleTest.cpp
+++ b/unittests/FileHandleTest.cpp
@@ -41,9 +41,7 @@
 
 //===----------------------------------------------------------------------===//
 // Testcases
-#include <iostream>
-using namespace std;
-
+//===----------------------------------------------------------------------===//
 TEST_F(FileHandleTest, open_close) {
   mcld::sys::fs::Path path(TOPDIR);
   path.append("unittests/test.txt");
@@ -51,13 +49,13 @@
   ASSERT_TRUE(m_pTestee->isOpened());
   ASSERT_TRUE(m_pTestee->isGood());
 
-  ASSERT_EQ(27, m_pTestee->size());
+  ASSERT_TRUE(27 == m_pTestee->size());
 
   ASSERT_TRUE(m_pTestee->close());
   ASSERT_FALSE(m_pTestee->isOpened());
   ASSERT_TRUE(m_pTestee->isGood());
 
-  ASSERT_EQ(0, m_pTestee->size());
+  ASSERT_TRUE(0 == m_pTestee->size());
 }
 
 TEST_F(FileHandleTest, delegate_close) {
@@ -70,13 +68,13 @@
   ASSERT_TRUE(m_pTestee->isOpened());
   ASSERT_TRUE(m_pTestee->isGood());
 
-  ASSERT_EQ(27, m_pTestee->size());
+  ASSERT_TRUE(27 == m_pTestee->size());
 
   ASSERT_TRUE(m_pTestee->close());
   ASSERT_FALSE(m_pTestee->isOpened());
   ASSERT_TRUE(m_pTestee->isGood());
 
-  ASSERT_EQ(0, m_pTestee->size());
+  ASSERT_TRUE(0 == m_pTestee->size());
 
   int close_result = ::close(fd);
   int close_err = errno;
@@ -91,7 +89,7 @@
   ASSERT_TRUE(m_pTestee->isOpened());
   ASSERT_TRUE(m_pTestee->isGood());
 
-  ASSERT_EQ(27, m_pTestee->size());
+  ASSERT_TRUE(27 == m_pTestee->size());
 
   int close_result = ::close(m_pTestee->handler());
   ASSERT_EQ(0, close_result);
diff --git a/unittests/FragmentRefTest.cpp b/unittests/FragmentRefTest.cpp
index d64d52b..599289d 100644
--- a/unittests/FragmentRefTest.cpp
+++ b/unittests/FragmentRefTest.cpp
@@ -8,15 +8,15 @@
 //===----------------------------------------------------------------------===//
 #include "FragmentRefTest.h"
 
-#include <mcld/LD/FragmentRef.h>
-#include <mcld/LD/RegionFragment.h>
+#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/Fragment/RegionFragment.h>
 #include <mcld/Support/MemoryAreaFactory.h>
 #include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MemoryRegion.h>
 #include <mcld/Support/Path.h>
 
 using namespace mcld;
 using namespace mcld::sys::fs;
-using namespace mcld::sys::fs::detail;
 using namespace mcldtest;
 
 // Constructor can do set-up work for all test here.
@@ -50,20 +50,19 @@
 
   MemoryRegion* region = area->request(0, 4096);
   RegionFragment *frag = new RegionFragment(*region);
-  FragmentRef *ref = new FragmentRef(*frag);
+  FragmentRef *ref = FragmentRef::Create(*frag, 0x0);
 
   ASSERT_EQ('H', region->getBuffer()[0]);
-  ASSERT_EQ(4096, region->size());
+  ASSERT_TRUE(4096 == region->size());
   ASSERT_EQ('H', frag->getRegion().getBuffer()[0]);
-  ASSERT_EQ(4096, frag->getRegion().size());
+  ASSERT_TRUE(4096 == frag->getRegion().size());
   ASSERT_EQ(frag, ref->frag());
   ASSERT_EQ('H', static_cast<RegionFragment*>(ref->frag())->getRegion().getBuffer()[0]);
-  ASSERT_EQ(4096, static_cast<RegionFragment*>(ref->frag())->getRegion().size());
+  ASSERT_TRUE(4096 == static_cast<RegionFragment*>(ref->frag())->getRegion().size());
   ASSERT_EQ('H', ref->deref()[0]);
 
   ASSERT_TRUE(RegionFragment::classof(frag));
 
-  delete ref;
   delete frag;
   delete areaFactory;
 }
diff --git a/unittests/FragmentTest.cpp b/unittests/FragmentTest.cpp
index 5186ea8..9713f48 100644
--- a/unittests/FragmentTest.cpp
+++ b/unittests/FragmentTest.cpp
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include "FragmentTest.h"
 
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
 #include <mcld/LD/SectionData.h>
 #include <mcld/LD/LDSection.h>
 
@@ -40,40 +40,36 @@
 // Testcases
  
 TEST_F( FragmentTest, Fragment_constructor ) {
-  LDSection test("test", LDFileFormat::Null, 0, 0);
-  SectionData* s = new SectionData(test);
-  Fragment* f1 = new Fragment(Fragment::Alignment, s);
+  LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
+  SectionData* s = SectionData::Create(*test);
+  new Fragment(Fragment::Alignment, s);
   EXPECT_TRUE(1 == s->size());
-  Fragment* f2 = new Fragment(Fragment::Alignment, s);
-  Fragment* f3 = new Fragment(Fragment::Region, s);
-  Fragment* f4 = new Fragment(Fragment::Fillment, s);
-  Fragment* f5 = new Fragment(Fragment::Relocation, s);
-  Fragment* f6 = new Fragment(Fragment::Target, s);
+  new Fragment(Fragment::Alignment, s);
+  new Fragment(Fragment::Region, s);
+  new Fragment(Fragment::Fillment, s);
+  new Fragment(Fragment::Relocation, s);
+  new Fragment(Fragment::Target, s);
   EXPECT_TRUE(6 == s->size());
 
-  delete s;
+  LDSection::Destroy(test);
+//  SectionData::Destroy(s);
 }
 
 TEST_F( FragmentTest, Fragment_trivial_function ) {
-  LDSection test("test", LDFileFormat::Null, 0, 0);
-  SectionData* s = new SectionData(test);
+  LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
+  SectionData* s = SectionData::Create(*test);
   Fragment* f = new Fragment(Fragment::Alignment, s);
   
   EXPECT_TRUE(Fragment::Alignment == f->getKind());
 
-  EXPECT_TRUE(~uint64_t(0) == f->getOffset());
-  EXPECT_TRUE(~(0U) == f->getLayoutOrder());
-
   f->setOffset(5566);
   EXPECT_TRUE(5566 == f->getOffset());
 
-  f->setLayoutOrder(5566);
-  EXPECT_TRUE(5566 == f->getLayoutOrder());
-  
   //always return true
   EXPECT_TRUE(f->classof(new Fragment(Fragment::Region, s)) );
   
-  delete s;
+  LDSection::Destroy(test);
+//  SectionData::Destroy(s);
 }
 
 
diff --git a/unittests/GCFactoryListTraitsTest.cpp b/unittests/GCFactoryListTraitsTest.cpp
index e99d42c..db8842c 100644
--- a/unittests/GCFactoryListTraitsTest.cpp
+++ b/unittests/GCFactoryListTraitsTest.cpp
@@ -58,7 +58,7 @@
 //
 
 #define CHECK_NODE_VALUE(v_) do {  \
-  ASSERT_EQ(v_, it->getValue()); \
+  ASSERT_TRUE(v_ == it->getValue()); \
   it++; \
 } while (false)
 
@@ -77,26 +77,26 @@
 } while (false)
 
 TEST_F( GCFactoryListTraitsTest, Basic) {
-  ASSERT_EQ(10, m_pNodeList.size());
+  ASSERT_TRUE(10 == m_pNodeList.size());
   CHECK_LIST_VALUE(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
 }
 
 TEST_F( GCFactoryListTraitsTest, BasicAgain) {
-  ASSERT_EQ(10, m_pNodeList.size());
+  ASSERT_TRUE(10 == m_pNodeList.size());
   CHECK_LIST_VALUE(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
 }
 
 TEST_F( GCFactoryListTraitsTest, Clear) {
   m_pNodeList.clear();
-  ASSERT_EQ(0, m_pNodeList.size());
+  ASSERT_TRUE(0 == m_pNodeList.size());
 }
 
 TEST_F( GCFactoryListTraitsTest, PushThenPop) {
   Node *NewNode = m_NodeFactory.produce(11);
   m_pNodeList.push_back(NewNode);
-  ASSERT_EQ(11, m_pNodeList.size());
+  ASSERT_TRUE(11 == m_pNodeList.size());
   m_pNodeList.pop_back();
-  ASSERT_EQ(10, m_pNodeList.size());
+  ASSERT_TRUE(10 == m_pNodeList.size());
 }
 
 TEST_F( GCFactoryListTraitsTest, CodeIterator) {
diff --git a/unittests/GCFactoryListTraitsTest.h b/unittests/GCFactoryListTraitsTest.h
index 7067907..a551848 100644
--- a/unittests/GCFactoryListTraitsTest.h
+++ b/unittests/GCFactoryListTraitsTest.h
@@ -41,10 +41,11 @@
     unsigned m_Init;
     unsigned m_Value;
 
-  private:
+  public:
+    Node() : m_Init(0), m_Value(0) { }
+
     Node(unsigned pInit) : m_Init(pInit), m_Value(pInit) { }
 
-  public:
     unsigned getInitialValue() const {
       return m_Init;
     }
diff --git a/unittests/HashTableTest.cpp b/unittests/HashTableTest.cpp
index 4106641..532c307 100644
--- a/unittests/HashTableTest.cpp
+++ b/unittests/HashTableTest.cpp
@@ -97,9 +97,9 @@
 TEST_F( HashTableTest, constructor ) {
   typedef HashEntry<int, int, IntCompare> HashEntryType;
   HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > hashTable(16);
-  EXPECT_EQ(17, hashTable.numOfBuckets());
+  EXPECT_TRUE(17 == hashTable.numOfBuckets());
   EXPECT_TRUE(hashTable.empty());
-  EXPECT_EQ(0, hashTable.numOfEntries());
+  EXPECT_TRUE(0 == hashTable.numOfEntries());
 }
 
 TEST_F( HashTableTest, allocattion ) {
@@ -126,18 +126,18 @@
 
   bool exist;
   HashTableTy::entry_type* entry = 0;
-  for (unsigned int key=0; key<100; ++key) {
+  for (int key=0; key<100; ++key) {
     entry = hashTable->insert(key, exist);
     EXPECT_FALSE(hashTable->empty());
     EXPECT_FALSE(exist);
     EXPECT_FALSE(NULL == entry);
-    EXPECT_EQ(key, entry->key());
+    EXPECT_TRUE(key == entry->key());
     entry->setValue(key+10);
   }
 
   EXPECT_FALSE(hashTable->empty());
-  EXPECT_EQ(100, hashTable->numOfEntries());
-  EXPECT_EQ(197, hashTable->numOfBuckets());
+  EXPECT_TRUE(100 == hashTable->numOfEntries());
+  EXPECT_TRUE(197 == hashTable->numOfBuckets());
   delete hashTable;
 }
 
@@ -179,7 +179,6 @@
 
   hashTable->clear();
 
-  int count;
   HashTableTy::iterator iter;
   for (unsigned int key=0; key<100; ++key) {
     iter = hashTable->find(key);
@@ -210,7 +209,7 @@
     iter = hashTable->find(key);
     EXPECT_TRUE(iter == hashTable->end());
   }
-  EXPECT_EQ(80, hashTable->numOfEntries());
+  EXPECT_TRUE(80 == hashTable->numOfEntries());
 
   for (unsigned int key=20; key<100; ++key) {
     iter = hashTable->find(key);
@@ -220,8 +219,8 @@
   for (unsigned int key=0; key<20; ++key) {
     entry = hashTable->insert(key, exist);
   }
-  EXPECT_EQ(100, hashTable->numOfEntries());
-  EXPECT_EQ(197, hashTable->numOfBuckets());
+  EXPECT_TRUE(100 == hashTable->numOfEntries());
+  EXPECT_TRUE(197 == hashTable->numOfBuckets());
 
   delete hashTable;
 }
@@ -239,7 +238,7 @@
   }
 
   HashTableTy::iterator iter;
-  for (unsigned int key=0; key<400000; ++key) {
+  for (int key=0; key<400000; ++key) {
     iter = hashTable->find(key);
     EXPECT_EQ((key+10), iter.getEntry()->value());
   }
@@ -260,7 +259,7 @@
   }
 
   HashTableTy::iterator iter, iEnd = hashTable->end();
-  unsigned int counter = 0;
+  int counter = 0;
   for (iter = hashTable->begin(); iter != iEnd; ++iter) {
     EXPECT_EQ(iter.getEntry()->key()+10, iter.getEntry()->value());
     ++counter;
@@ -277,12 +276,12 @@
 
   bool exist;
   HashTableTy::entry_type* entry = 0;
-  for (unsigned int key=0; key<16; ++key) {
+  for (int key=0; key<16; ++key) {
     entry = hashTable->insert(key*37, exist);
     entry->setValue(key+10);
   }
-  for (unsigned int key=0; key<16; ++key) {
-    unsigned int counter = 0;
+  for (int key=0; key<16; ++key) {
+    int counter = 0;
     HashTableTy::chain_iterator iter, iEnd = hashTable->end(key*37);
     for (iter = hashTable->begin(key*37); iter != iEnd; ++iter) {
       EXPECT_EQ(key+10, iter.getEntry()->value());
@@ -313,11 +312,11 @@
     ASSERT_FALSE(exist);
     entry->setValue(key);
   }
-  ASSERT_EQ(16, hashTable->numOfEntries());
-  ASSERT_EQ(37, hashTable->numOfBuckets());
+  ASSERT_TRUE(16 == hashTable->numOfEntries());
+  ASSERT_TRUE(37 == hashTable->numOfBuckets());
 
   unsigned int key = 0;
-  unsigned int count = 0;
+  int count = 0;
   HashTableTy::chain_iterator iter, iEnd = hashTable->end(key);
   for (iter = hashTable->begin(key); iter != iEnd; ++iter) {
     count++;
diff --git a/unittests/InputTreeTest.cpp b/unittests/InputTreeTest.cpp
index 0013601..1b1e061 100644
--- a/unittests/InputTreeTest.cpp
+++ b/unittests/InputTreeTest.cpp
@@ -6,29 +6,45 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/InputTree.h"
-#include "mcld/MC/MCLDInfo.h"
-#include <InputTreeTest.h>
+#include "InputTreeTest.h"
+
+#include <vector>
+#include <iostream>
+
+#include <mcld/InputTree.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/FileAction.h>
+#include <mcld/MC/CommandAction.h>
 
 using namespace mcld;
-using namespace mcldtest;
+using namespace mcld::test;
 
 
 // Constructor can do set-up work for all test here.
 InputTreeTest::InputTreeTest()
-{
-	// create testee. modify it if need
-	m_pAttr = new mcld::AttributeFactory(2);
-        m_pAlloc = new mcld::InputFactory(10, *m_pAttr);
-	m_pTestee = new InputTree(*m_pAlloc);
+  : m_MemFactory(10), m_ContextFactory(4) {
+
+  // create testee. modify it if need
+  m_pConfig = new mcld::LinkerConfig("arm-none-linux-gnueabi");
+  m_pAlloc  = new mcld::InputFactory(10, *m_pConfig);
+  m_pBuilder = new mcld::InputBuilder(*m_pConfig,
+                                      *m_pAlloc,
+                                      m_ContextFactory, 
+                                      m_MemFactory,
+                                      false);
+  m_pTestee = new mcld::InputTree();
+  m_pBuilder->setCurrentTree(*m_pTestee);
 }
 
 // Destructor can do clean-up work that doesn't throw exceptions here.
 InputTreeTest::~InputTreeTest()
 {
-	delete m_pTestee;
-	delete m_pAlloc;
-	delete m_pAttr;
+  delete m_pTestee;
+  delete m_pAlloc;
+  delete m_pBuilder;
+  delete m_pConfig;
 }
 
 // SetUp() will be called immediately before each test.
@@ -41,19 +57,33 @@
 {
 }
 
-//==========================================================================//
+//===----------------------------------------------------------------------===//
 // Testcases
 //
 TEST_F( InputTreeTest, Basic_operation ) {
-  InputTree::iterator node = m_pTestee->root();
-  m_pTestee->insert<InputTree::Inclusive>(node, "FileSpec", "path1");
 
+  std::vector<InputAction*> actions;
+
+  size_t position = 0;
+  actions.push_back(new StartGroupAction(position++));
+  actions.push_back(new InputFileAction(position++, "path1"));
+  actions.push_back(new EndGroupAction(position++));
+
+  std::vector<InputAction*>::iterator action;
+  for (action = actions.begin(); action != actions.end(); ++action) {
+    (*action)->activate(*m_pBuilder);
+    delete *action;
+  }
+  
+  InputTree::iterator node = m_pTestee->root();
   InputTree::const_iterator const_node = node;
+  --node;
+  --const_node;
 
   ASSERT_TRUE(isGroup(node));
   ASSERT_TRUE(isGroup(const_node));
-  ASSERT_TRUE(m_pTestee->hasInput());
-  ASSERT_EQ(1, m_pTestee->numOfInputs());
+  ASSERT_FALSE(m_pAlloc->empty());
+  ASSERT_TRUE(1 == m_pAlloc->size());
 
   --node;
 
@@ -65,23 +95,25 @@
 
   ASSERT_FALSE(isGroup(node));
   ASSERT_FALSE(isGroup(const_node2));
-  ASSERT_TRUE(m_pTestee->hasInput());
-  ASSERT_FALSE(m_pTestee->numOfInputs()==0);
+  ASSERT_FALSE(m_pAlloc->empty());
+  ASSERT_FALSE(m_pAlloc->size()==0);
 
-  ASSERT_TRUE(m_pTestee->size()==2);
+  ASSERT_TRUE(m_pTestee->size()==3);
 }
 
 TEST_F( InputTreeTest, forLoop_TEST ) {
   InputTree::iterator node = m_pTestee->root();
 
   
-  m_pTestee->insert<InputTree::Inclusive>(node, "FileSpec", "path1");
+  Input* input = m_pAlloc->produce("FileSpec", "path1");
+  m_pTestee->insert<InputTree::Inclusive>(node, *input);
   InputTree::const_iterator const_node = node;
   --node;
 
   for(int i=0 ; i<100 ; ++i) 
   {
-    m_pTestee->insert<InputTree::Inclusive>(node,"FileSpec", "path1");
+    Input* input = m_pAlloc->produce("FileSpec", "path1");
+    m_pTestee->insert<InputTree::Inclusive>(node, *input);
     ++node;
   }
 
@@ -90,8 +122,8 @@
 
   ASSERT_FALSE(node.isRoot());
   ASSERT_TRUE(isGroup(node));
-  ASSERT_TRUE(m_pTestee->hasInput());
-  ASSERT_FALSE(m_pTestee->numOfInputs()==100);
+  ASSERT_FALSE(m_pAlloc->empty());
+  ASSERT_FALSE(m_pAlloc->size()==100);
 
   ASSERT_TRUE(m_pTestee->size()==102);
 }
@@ -104,14 +136,15 @@
     m_pTestee->enterGroup(node, InputTree::Downward);
     --node;
 
-    m_pTestee->insert(node, InputTree::Afterward, "FileSpec", "path1");
+    Input* input = m_pAlloc->produce("FileSpec", "path1");
+    m_pTestee->insert(node, InputTree::Afterward, *input);
     ++node;
   }
   
   ASSERT_FALSE(node.isRoot());
   ASSERT_FALSE(isGroup(node));
-  ASSERT_TRUE(m_pTestee->hasInput());
-  ASSERT_TRUE(m_pTestee->numOfInputs()==50);
+  ASSERT_FALSE(m_pAlloc->empty());
+  ASSERT_TRUE(m_pAlloc->size()==50);
   ASSERT_TRUE(m_pTestee->size()==100);
 }
 
@@ -119,14 +152,19 @@
 {
   
   InputTree::iterator node = m_pTestee->root(); 
-  m_pTestee->insert<InputTree::Inclusive>(node, "111", "/");
+  Input* input = m_pAlloc->produce("111", "/");
+  m_pTestee->insert<InputTree::Inclusive>(node, *input);
   node.move<InputTree::Inclusive>();
 
-  m_pTestee->insert<InputTree::Positional>(node, "10", "/");
+  input = m_pAlloc->produce("10", "/");
+  m_pTestee->insert<InputTree::Positional>(node, *input);
   m_pTestee->enterGroup<InputTree::Inclusive>(node);
   node.move<InputTree::Inclusive>();
-  m_pTestee->insert<InputTree::Inclusive>(node, "7", "/");
-  m_pTestee->insert<InputTree::Positional>(node, "8", "/");
+
+  input = m_pAlloc->produce("7", "/");
+  m_pTestee->insert<InputTree::Inclusive>(node, *input);
+  input = m_pAlloc->produce("8", "/");
+  m_pTestee->insert<InputTree::Positional>(node, *input);
 
   InputTree::dfs_iterator dfs_it = m_pTestee->dfs_begin(); 
   InputTree::dfs_iterator dfs_end = m_pTestee->dfs_end(); 
diff --git a/unittests/InputTreeTest.h b/unittests/InputTreeTest.h
index 2ffef9c..c0f59a7 100644
--- a/unittests/InputTreeTest.h
+++ b/unittests/InputTreeTest.h
@@ -6,21 +6,21 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef INPUTTREE_TEST_H
-#define INPUTTREE_TEST_H
+#ifndef UNITTESTS_INPUTTREE_TEST_H
+#define UNITTESTS_INPUTTREE_TEST_H
 
 #include <gtest.h>
+#include <mcld/MC/ContextFactory.h>
+#include <mcld/Support/MemoryAreaFactory.h>
 
-namespace mcld
-{
+namespace mcld {
+
 class InputTree;
 class InputFactory;
-class AttributeFactory;
+class InputBuilder;
+class LinkerConfig;
 
-} // namespace for mcld
-
-namespace mcldtest
-{
+namespace test {
 
 /** \class InputTreeTest
  *  \brief 
@@ -30,25 +30,31 @@
 class InputTreeTest : public ::testing::Test
 {
 public:
-	// Constructor can do set-up work for all test here.
-	InputTreeTest();
+  // Constructor can do set-up work for all test here.
+  InputTreeTest();
 
-	// Destructor can do clean-up work that doesn't throw exceptions here.
-	virtual ~InputTreeTest();
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~InputTreeTest();
 
-	// SetUp() will be called immediately before each test.
-	virtual void SetUp();
+  // SetUp() will be called immediately before each test.
+  virtual void SetUp();
 
-	// TearDown() will be called immediately after each test.
-	virtual void TearDown();
+  // TearDown() will be called immediately after each test.
+  virtual void TearDown();
 
 protected:
-	mcld::AttributeFactory *m_pAttr;
-	mcld::InputFactory *m_pAlloc;
-	mcld::InputTree* m_pTestee;
+  mcld::LinkerConfig* m_pConfig;
+
+  mcld::InputFactory* m_pAlloc;
+  mcld::InputBuilder* m_pBuilder;
+  mcld::MemoryAreaFactory m_MemFactory;
+  mcld::ContextFactory m_ContextFactory;
+
+  mcld::InputTree* m_pTestee;
 };
 
-} // namespace of mcldtest
+} // namespace of test
+} // namespace of mcld
 
 #endif
 
diff --git a/unittests/LEB128Test.cpp b/unittests/LEB128Test.cpp
index bd1aec2..e8083b1 100644
--- a/unittests/LEB128Test.cpp
+++ b/unittests/LEB128Test.cpp
@@ -51,41 +51,41 @@
   size = leb128::encode<uint32_t>(result, 2);
   ASSERT_EQ(buffer[0], 2);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 127);
   ASSERT_EQ(buffer[0], 127);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 128);
   ASSERT_EQ(buffer[0], 0 + 0x80);
   ASSERT_EQ(buffer[1], 1);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 129);
   ASSERT_EQ(buffer[0], 1 + 0x80);
   ASSERT_EQ(buffer[1], 1);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 130);
   ASSERT_EQ(buffer[0], 2 + 0x80);
   ASSERT_EQ(buffer[1], 1);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 12857);
   ASSERT_EQ(buffer[0], 57 + 0x80);
   ASSERT_EQ(buffer[1], 100);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 }
 
 TEST_F( LEB128Test, EncodeULEB_Example_from_Dwarf3_Figure22_Using_64bits) {
@@ -97,41 +97,41 @@
   size = leb128::encode<uint64_t>(result, 2);
   ASSERT_EQ(buffer[0], 2);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 127);
   ASSERT_EQ(buffer[0], 127);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 128);
   ASSERT_EQ(buffer[0], 0 + 0x80);
   ASSERT_EQ(buffer[1], 1);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 129);
   ASSERT_EQ(buffer[0], 1 + 0x80);
   ASSERT_EQ(buffer[1], 1);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 130);
   ASSERT_EQ(buffer[0], 2 + 0x80);
   ASSERT_EQ(buffer[1], 1);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 12857);
   ASSERT_EQ(buffer[0], 57 + 0x80);
   ASSERT_EQ(buffer[1], 100);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 }
 
 TEST_F( LEB128Test, EncodeSLEB_Example_from_Dwarf3_Figure22) {
@@ -143,55 +143,55 @@
   size = leb128::encode<int32_t>(result, 2);
   ASSERT_EQ(buffer[0], 2);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, -2);
   ASSERT_EQ(buffer[0], 0x7e);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, 127);
   ASSERT_EQ(buffer[0], 127 + 0x80);
   ASSERT_EQ(buffer[1], 0);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, -127);
   ASSERT_EQ(buffer[0], 1 + 0x80);
   ASSERT_EQ(buffer[1], 0x7f);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, 128);
   ASSERT_EQ(buffer[0], 0 + 0x80);
   ASSERT_EQ(buffer[1], 1);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, -128);
   ASSERT_EQ(buffer[0], 0 + 0x80);
   ASSERT_EQ(buffer[1], 0x7f);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, 129);
   ASSERT_EQ(buffer[0], 1 + 0x80);
   ASSERT_EQ(buffer[1], 1);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, -129);
   ASSERT_EQ(buffer[0], 0x7f + 0x80);
   ASSERT_EQ(buffer[1], 0x7e);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 }
 
 TEST_F( LEB128Test, DecodeULEB_Example_from_Dwarf3_Figure22) {
@@ -200,33 +200,33 @@
 
   buffer[0] = 2;
   buffer[1] = 0;
-  ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 2);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 2);
+  ASSERT_TRUE(size == 1);
 
   buffer[0] = 127;
   buffer[1] = 0;
-  ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 127);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 127);
+  ASSERT_TRUE(size == 1);
 
   buffer[0] = 0 + 0x80;
   buffer[1] = 1;
-  ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 128);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 128);
+  ASSERT_TRUE(size == 2);
 
   buffer[0] = 1 + 0x80;
   buffer[1] = 1;
-  ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 129);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 129);
+  ASSERT_TRUE(size == 2);
 
   buffer[0] = 2 + 0x80;
   buffer[1] = 1;
-  ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 130);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 130);
+  ASSERT_TRUE(size == 2);
 
   buffer[0] = 57 + 0x80;
   buffer[1] = 100;
-  ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 12857);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 12857);
+  ASSERT_TRUE(size == 2);
 
 }
 
@@ -237,42 +237,42 @@
   buffer[0] = 2;
   buffer[1] = 0;
   ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 2);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   buffer[0] = 0x7e;
   buffer[1] = 0;
   ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -2);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   buffer[0] = 127 + 0x80;
   buffer[1] = 0;
   ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 127);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   buffer[0] = 1 + 0x80;
   buffer[1] = 0x7f;
   ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -127);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   buffer[0] = 0 + 0x80;
   buffer[1] = 1;
   ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 128);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   buffer[0] = 0 + 0x80;
   buffer[1] = 0x7f;
   ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -128);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   buffer[0] = 1 + 0x80;
   buffer[1] = 1;
   ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 129);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   buffer[0] = 0x7f + 0x80;
   buffer[1] = 0x7e;
   ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -129);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 }
 
 TEST_F( LEB128Test, DecodeULEB_Tests_Found_in_Android_dalvik_dx) {
@@ -281,18 +281,18 @@
 
   content[0] = 0;
   p = content;
-  ASSERT_EQ(leb128::decode<uint64_t>(p), 0);
+  ASSERT_TRUE(leb128::decode<uint64_t>(p) == 0);
   ASSERT_EQ(p, content + 1);
 
   content[0] = 1;
   p = content;
-  ASSERT_EQ(leb128::decode<uint64_t>(p), 1);
+  ASSERT_TRUE(leb128::decode<uint64_t>(p) == 1);
   ASSERT_EQ(p, content + 1);
 
   content[0] = 0x80;
   content[1] = 0x7f;
   p = content;
-  ASSERT_EQ(leb128::decode<uint64_t>(p), 16256);
+  ASSERT_TRUE(leb128::decode<uint64_t>(p) == 16256);
   ASSERT_EQ(p, content + 2);
 }
 
@@ -305,67 +305,67 @@
   size = leb128::encode<uint32_t>(result, 0);
   ASSERT_EQ(buffer[0], 0);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 0);
   ASSERT_EQ(buffer[0], 0);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 1);
   ASSERT_EQ(buffer[0], 1);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 1);
   ASSERT_EQ(buffer[0], 1);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 16256);
   ASSERT_EQ(buffer[0], 0x80);
   ASSERT_EQ(buffer[1], 0x7f);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 16256);
   ASSERT_EQ(buffer[0], 0x80);
   ASSERT_EQ(buffer[1], 0x7f);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 0x3b4);
   ASSERT_EQ(buffer[0], 0xb4);
   ASSERT_EQ(buffer[1], 0x07);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 0x3b4);
   ASSERT_EQ(buffer[0], 0xb4);
   ASSERT_EQ(buffer[1], 0x07);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 0x40c);
   ASSERT_EQ(buffer[0], 0x8c);
   ASSERT_EQ(buffer[1], 0x08);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 0x40c);
   ASSERT_EQ(buffer[0], 0x8c);
   ASSERT_EQ(buffer[1], 0x08);
   ASSERT_EQ(result, buffer + 2);
-  ASSERT_EQ(size, 2);
+  ASSERT_TRUE(size == 2);
 
   result = buffer;
   size = leb128::encode<uint32_t>(result, 0xffffffff);
@@ -375,7 +375,7 @@
   ASSERT_EQ(buffer[3], 0xff);
   ASSERT_EQ(buffer[4], 0xf);
   ASSERT_EQ(result, buffer + 5);
-  ASSERT_EQ(size, 5);
+  ASSERT_TRUE(size == 5);
 
   result = buffer;
   size = leb128::encode<uint64_t>(result, 0xffffffff);
@@ -385,7 +385,7 @@
   ASSERT_EQ(buffer[3], 0xff);
   ASSERT_EQ(buffer[4], 0xf);
   ASSERT_EQ(result, buffer + 5);
-  ASSERT_EQ(size, 5);
+  ASSERT_TRUE(size == 5);
 }
 
 TEST_F( LEB128Test, DecodeSLEB_Tests_Found_in_Android_dalvik_dx) {
@@ -422,45 +422,46 @@
   size = leb128::encode<int32_t>(result, 0);
   ASSERT_EQ(buffer[0], 0);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<int64_t>(result, 0);
   ASSERT_EQ(buffer[0], 0);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, 1);
   ASSERT_EQ(buffer[0], 1);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<int64_t>(result, 1);
   ASSERT_EQ(buffer[0], 1);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<int32_t>(result, -1);
   ASSERT_EQ(buffer[0], 0x7f);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 
   result = buffer;
   size = leb128::encode<int64_t>(result, -1);
   ASSERT_EQ(buffer[0], 0x7f);
   ASSERT_EQ(result, buffer + 1);
-  ASSERT_EQ(size, 1);
+  ASSERT_TRUE(size == 1);
 }
 
 TEST_F( LEB128Test, Random_Regression_Test) {
   leb128::ByteType buffer[9];
 
   for (int i = 0; i < 20; i++) {
-    long int value = random();
+    unsigned long int value = random();
     uint64_t value2 = value * value;
+    int64_t value3 = value * value;
     leb128::ByteType *result;
     size_t encode_size, decode_size;
 
@@ -480,16 +481,16 @@
 
     // Test encode<uint64_t> and decode<uint64_t> on (value * value)
     result = buffer;
-    encode_size = leb128::encode<int64_t>(result, value2);
+    encode_size = leb128::encode<int64_t>(result, value3);
     ASSERT_EQ(result, buffer + encode_size);
-    ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), value2);
+    ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), value3);
     ASSERT_EQ(encode_size, decode_size);
 
     // Test encode<uint64_t> and decode<uint64_t> on -(value * value)
     result = buffer;
-    encode_size = leb128::encode<int64_t>(result, -value2);
+    encode_size = leb128::encode<int64_t>(result, -value3);
     ASSERT_EQ(result, buffer + encode_size);
-    ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), -value2);
+    ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), -value3);
     ASSERT_EQ(encode_size, decode_size);
   }
 }
@@ -506,8 +507,8 @@
   ASSERT_EQ(buffer[1], 0xb6);
   ASSERT_EQ(buffer[2], 0x9);
 
-  ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 154452);
-  ASSERT_EQ(size, 3);
+  ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 154452);
+  ASSERT_TRUE(size == 3);
 }
 
 TEST_F( LEB128Test, Type_Conversion_Test) {
@@ -522,10 +523,10 @@
   ASSERT_EQ(buffer[1], '\xb6');
   ASSERT_EQ(buffer[2], '\x09');
 
-  ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 154452);
-  ASSERT_EQ(size, 3);
+  ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 154452);
+  ASSERT_TRUE(size == 3);
 
   const char *p = buffer;
-  ASSERT_EQ(leb128::decode<uint64_t>(p), 154452);
-  ASSERT_EQ(p, buffer + 3);
+  ASSERT_TRUE(leb128::decode<uint64_t>(p) == 154452);
+  ASSERT_TRUE(p == (buffer + 3));
 }
diff --git a/unittests/LinearAllocatorTest.cpp b/unittests/LinearAllocatorTest.cpp
index 9100160..fea135f 100644
--- a/unittests/LinearAllocatorTest.cpp
+++ b/unittests/LinearAllocatorTest.cpp
@@ -56,17 +56,17 @@
 TEST_F( LinearAllocatorTest, allocateOver ) {
 	Data* pointer = m_pTestee->allocate(CHUNK_SIZE+1);
 	ASSERT_TRUE(0 == pointer);
-	ASSERT_EQ(0, m_pTestee->max_size());
+	ASSERT_TRUE(0 == m_pTestee->max_size());
 	ASSERT_TRUE(m_pTestee->empty());
 }
 
 TEST_F( LinearAllocatorTest, alloc_construct ) {
 	Data* pointer = m_pTestee->allocate();
 	m_pTestee->construct(pointer);
-	ASSERT_EQ(1, pointer->one);
-	ASSERT_EQ(2, pointer->two);
-	ASSERT_EQ(3, pointer->three);
-	ASSERT_EQ(4, pointer->four);
+	ASSERT_TRUE(1 == pointer->one);
+	ASSERT_TRUE(2 == pointer->two);
+	ASSERT_TRUE(3 == pointer->three);
+	ASSERT_TRUE(4 == pointer->four);
 }
 
 TEST_F( LinearAllocatorTest, alloc_constructCopy ) {
@@ -74,19 +74,19 @@
 	Data data(7, 7, 7, 7);
 	m_pTestee->construct(pointer, data);
 	
-	ASSERT_EQ(7, pointer->one);
-	ASSERT_EQ(7, pointer->two);
-	ASSERT_EQ(7, pointer->three);
-	ASSERT_EQ(7, pointer->four);
+	ASSERT_TRUE(7 == pointer->one);
+	ASSERT_TRUE(7 == pointer->two);
+	ASSERT_TRUE(7 == pointer->three);
+	ASSERT_TRUE(7 == pointer->four);
 }
 
 TEST_F( LinearAllocatorTest, allocN_construct ) {
 	Data* pointer = m_pTestee->allocate(10);
 	m_pTestee->construct(pointer);
-	ASSERT_EQ(1, pointer->one);
-	ASSERT_EQ(2, pointer->two);
-	ASSERT_EQ(3, pointer->three);
-	ASSERT_EQ(4, pointer->four);
+	ASSERT_TRUE(1 == pointer->one);
+	ASSERT_TRUE(2 == pointer->two);
+	ASSERT_TRUE(3 == pointer->three);
+	ASSERT_TRUE(4 == pointer->four);
 }
 
 TEST_F( LinearAllocatorTest, allocN_constructCopy ) {
@@ -94,10 +94,10 @@
 	Data data(7, 7, 7, 7);
 	m_pTestee->construct(pointer, data);
 	
-	ASSERT_EQ(7, pointer->one);
-	ASSERT_EQ(7, pointer->two);
-	ASSERT_EQ(7, pointer->three);
-	ASSERT_EQ(7, pointer->four);
+	ASSERT_TRUE(7 == pointer->one);
+	ASSERT_TRUE(7 == pointer->two);
+	ASSERT_TRUE(7 == pointer->three);
+	ASSERT_TRUE(7 == pointer->four);
 }
 
 TEST_F( LinearAllocatorTest, multi_alloc_ctor_iterate ) {
diff --git a/unittests/LinearAllocatorTest.h b/unittests/LinearAllocatorTest.h
index 9e9b2ab..a6be2b7 100644
--- a/unittests/LinearAllocatorTest.h
+++ b/unittests/LinearAllocatorTest.h
@@ -63,7 +63,7 @@
 	virtual void TearDown();
 
 protected:
-	enum { CHUNK_SIZE = 32 };
+	enum TemplateArgsType { CHUNK_SIZE = 32 };
 	typedef mcld::LinearAllocator<Data, CHUNK_SIZE> Alloc;
 protected:
 	Alloc* m_pTestee;
diff --git a/unittests/Linker/TestLinker.cpp b/unittests/Linker/TestLinker.cpp
index ad6e13a..d1ead28 100644
--- a/unittests/Linker/TestLinker.cpp
+++ b/unittests/Linker/TestLinker.cpp
@@ -8,22 +8,23 @@
 //===----------------------------------------------------------------------===//
 #include "TestLinker.h"
 
-#include <iostream>
-
 #include <llvm/Support/TargetSelect.h>
 
+#include <mcld/Environment.h>
+#include <mcld/InputTree.h>
 #include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/MC/InputTree.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/InputFactory.h>
 #include <mcld/MC/MCLDDirectory.h>
 #include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Support/RegionFactory.h>
+#include <mcld/Support/Space.h>
 #include <mcld/Support/TargetSelect.h>
 #include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/raw_ostream.h>
 #include <mcld/Support/SystemUtils.h>
 #include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/MC/ContextFactory.h>
 
-using namespace std;
 using namespace mcld;
 using namespace mcld::sys::fs;
 using namespace mcld::test;
@@ -32,9 +33,8 @@
 // TestLinker
 //===----------------------------------------------------------------------===//
 TestLinker::TestLinker()
-  : m_pTarget(NULL), m_pDriver(NULL), m_pInfo(NULL), m_pDiagLineInfo(NULL),
-    m_pDiagPrinter(NULL), m_pBackend(NULL), m_pRegionFactory(NULL),
-    m_pMemAreaFactory(NULL) {
+  : m_pTarget(NULL), m_pObjLinker(NULL), m_pConfig(NULL), m_pDiagLineInfo(NULL),
+    m_pDiagPrinter(NULL), m_pBackend(NULL), m_pBuilder(NULL), m_pOutput(NULL) {
 }
 
 TestLinker::~TestLinker()
@@ -47,36 +47,28 @@
   for (mem = m_MemAreaList.begin(); mem != mEnd; ++mem)
     delete (*mem);
 
-  delete m_pDriver;
-  delete m_pInfo;
+  delete m_pObjLinker;
+  delete m_pConfig;
   delete m_pDiagLineInfo;
   delete m_pDiagPrinter;
   delete m_pBackend;
-  delete m_pRegionFactory;
-  delete m_pMemAreaFactory;
+  delete m_pBuilder;
+  delete m_pOutput;
 }
 
 bool TestLinker::initialize(const std::string &pTriple)
 {
-  bool is_initialized = false;
-
-  if (is_initialized)
-    return false;
-
   // initilaize all llvm::Target and mcld::Target
   llvm::InitializeAllTargets();
   llvm::InitializeAllAsmPrinters();
   llvm::InitializeAllAsmParsers();
   llvm::InitializeAllTargetMCs();
-  mcld::InitializeAllTargets();
-  mcld::InitializeAllDiagnostics();
+  mcld::Initialize();
 
-  // create mcld::MCLDInfo
-  m_pInfo = new MCLDInfo(pTriple, 1, 32);
-  m_Root = m_pInfo->inputs().root();
+  // create mcld::LinkerConfig
+  m_pConfig = new LinkerConfig(pTriple);
 
-  // create mcld::RegionFactory
-  m_pRegionFactory = new mcld::RegionFactory(32);
+  m_Root = m_Module.getInputTree().root();
 
   // specify mcld::Target
   std::string error;
@@ -86,64 +78,59 @@
     return false;
   }
 
-  // create mcld::DiagnosticEngine
+  // create mcld::DiagnosticLineInfo
   m_pDiagLineInfo = m_pTarget->createDiagnosticLineInfo(*m_pTarget, pTriple);
   if (NULL == m_pDiagLineInfo) {
     fatal(diag::fatal_cannot_init_lineinfo) << pTriple;
     return false;
   }
-
-  m_pDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *m_pInfo);
-
-  mcld::InitializeDiagnosticEngine(*m_pInfo, m_pDiagLineInfo, m_pDiagPrinter);
+  mcld::getDiagnosticEngine().setLineInfo(*m_pDiagLineInfo);
 
   // create mcld::TargetLDBackend
-  m_pBackend = m_pTarget->createLDBackend(pTriple);
+  m_pBackend = m_pTarget->createLDBackend(*m_pConfig);
   if (NULL == m_pBackend) {
     fatal(diag::fatal_cannot_init_backend) << pTriple;
     return false;
   }
 
-  m_pMemAreaFactory = new MemoryAreaFactory(32);
+  m_pInputFactory = new mcld::InputFactory(10, *m_pConfig);
+  m_pContextFactory = new mcld::ContextFactory(10);
+  m_pMemAreaFactory = new mcld::MemoryAreaFactory(10);
+  m_pBuilder = new mcld::InputBuilder(*m_pConfig,
+                                      *m_pInputFactory,
+                                      *m_pContextFactory,
+                                      *m_pMemAreaFactory,
+                                      true);
 
-  m_pDriver = new mcld::MCLDDriver(*m_pInfo, *m_pBackend, *m_pMemAreaFactory);
-  m_pDriver->initMCLinker();
+  m_pObjLinker = new mcld::ObjectLinker(*m_pConfig, m_Module, *m_pBuilder, *m_pBackend);
+  m_pObjLinker->initFragmentLinker();
 
-  is_initialized = true;
   return true;
 }
 
 void TestLinker::addSearchDir(const std::string &pDirPath)
 {
-  assert(NULL != m_pInfo && "initialize() must be called before addSearchDir");
-  assert(!m_pInfo->options().sysroot().empty() &&
+  assert(NULL != m_pConfig && "initialize() must be called before addSearchDir");
+  assert(!m_pConfig->options().sysroot().empty() &&
          "must setSysRoot before addSearchDir");
 
-  mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
-
-  if (sd->isInSysroot()) {
-    sd->setSysroot(m_pInfo->options().sysroot());
-  }
-
-  if (exists(sd->path()) && is_directory(sd->path())) {
-    m_pInfo->options().directories().add(*sd);
-  } else {
-    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
+  if (!m_pConfig->options().directories().insert(pDirPath)) {
+    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
   }
 }
 
 void TestLinker::setSysRoot(const mcld::sys::fs::Path &pPath)
 {
-  assert(NULL != m_pInfo && "initialize() must be called before setSysRoot");
-  m_pInfo->options().setSysroot(pPath);
+  assert(NULL != m_pConfig && "initialize() must be called before setSysRoot");
+  m_pConfig->options().setSysroot(pPath);
 }
 
 void TestLinker::addObject(const std::string &pPath)
 {
-  mcld::Input* input = m_pInfo->inputFactory().produce(pPath, pPath,
-                                                       mcld::Input::Unknown);
+  mcld::Input* input = m_pInputFactory->produce(pPath, pPath,
+                                                mcld::Input::Unknown);
 
-  m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+  m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
 
   advanceRoot();
 
@@ -155,38 +142,37 @@
                                       << mcld::sys::strerror(handler->error());
   }
 
-  mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+  mcld::MemoryArea* input_memory = new MemoryArea(*handler);
   input->setMemArea(input_memory);
   m_MemAreaList.push_back(input_memory);
 
-  mcld::LDContext* context = m_pInfo->contextFactory().produce(pPath);
-  input->setContext(context);
+  m_pBuilder->setContext(*input);
 }
 
 void TestLinker::addObject(void* pMemBuffer, size_t pSize)
 {
-  mcld::Input* input = m_pInfo->inputFactory().produce("memory object", "NAN",
-                                                       mcld::Input::Unknown);
+  mcld::Input* input = m_pInputFactory->produce("memory object", "NAN",
+                                                mcld::Input::Unknown);
 
-  m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+  m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
 
   advanceRoot();
 
-  mcld::Space* space = new mcld::Space(mcld::Space::EXTERNAL, pMemBuffer, pSize);
-  mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *space);
+  mcld::Space* space = Space::Create(pMemBuffer, pSize);
+  mcld::MemoryArea* input_memory = new MemoryArea(*space);
   input->setMemArea(input_memory);
   m_MemAreaList.push_back(input_memory);
 
-  mcld::LDContext* context = m_pInfo->contextFactory().produce();
+  mcld::LDContext* context = m_pContextFactory->produce();
   input->setContext(context);
 }
 
 void TestLinker::addObject(int pFileHandler)
 {
-  mcld::Input* input = m_pInfo->inputFactory().produce("handler object", "NAN",
-                                                       mcld::Input::Unknown);
+  mcld::Input* input = m_pInputFactory->produce("handler object", "NAN",
+                                                mcld::Input::Unknown);
 
-  m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+  m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
 
   advanceRoot();
 
@@ -194,11 +180,11 @@
   m_FileHandleList.push_back(handler);
   handler->delegate(pFileHandler);
 
-  mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+  mcld::MemoryArea* input_memory = new MemoryArea(*handler);
   input->setMemArea(input_memory);
   m_MemAreaList.push_back(input_memory);
 
-  mcld::LDContext* context = m_pInfo->contextFactory().produce();
+  mcld::LDContext* context = m_pContextFactory->produce();
   input->setContext(context);
 }
 
@@ -206,26 +192,26 @@
 {
   mcld::sys::fs::Path* path = NULL;
   // find out the real path of the namespec.
-  if (m_pInfo->attrFactory().constraint().isSharedSystem()) {
+  if (m_pConfig->attribute().constraint().isSharedSystem()) {
     // In the system with shared object support, we can find both archive
     // and shared object.
 
-    if (m_pInfo->attrFactory().last().isStatic()) {
+    if (m_pInputFactory->attr().isStatic()) {
       // with --static, we must search an archive.
-      path = m_pInfo->options().directories().find(pNameSpec,
-                                                   mcld::Input::Archive);
+      path = m_pConfig->options().directories().find(pNameSpec,
+                                                     mcld::Input::Archive);
     }
     else {
       // otherwise, with --Bdynamic, we can find either an archive or a
       // shared object.
-      path = m_pInfo->options().directories().find(pNameSpec,
+      path = m_pConfig->options().directories().find(pNameSpec,
                                                    mcld::Input::DynObj);
     }
   }
   else {
     // In the system without shared object support, we only look for an
     // archive.
-    path = m_pInfo->options().directories().find(pNameSpec,
+    path = m_pConfig->options().directories().find(pNameSpec,
                                                  mcld::Input::Archive);
   }
 
@@ -234,10 +220,10 @@
     return;
   }
 
-  mcld::Input* input = m_pInfo->inputFactory().produce(pNameSpec, *path,
-                                                       mcld::Input::Unknown);
+  mcld::Input* input = m_pInputFactory->produce(pNameSpec, *path,
+                                                mcld::Input::Unknown);
 
-  m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+  m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
 
   advanceRoot();
 
@@ -249,19 +235,15 @@
                                       << mcld::sys::strerror(handler->error());
   }
 
-  mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+  mcld::MemoryArea* input_memory = new MemoryArea(*handler);
   input->setMemArea(input_memory);
   m_MemAreaList.push_back(input_memory);
 
-  mcld::LDContext* context = m_pInfo->contextFactory().produce(*path);
-  input->setContext(context);
+  m_pBuilder->setContext(*input);
 }
 
 bool TestLinker::setOutput(const std::string &pPath)
 {
-  if (m_pInfo->output().hasContext())
-    return false;
-
   mcld::FileHandle* handler = new mcld::FileHandle();
   m_FileHandleList.push_back(handler);
   bool open_res = handler->open(pPath, mcld::FileHandle::ReadWrite |
@@ -274,15 +256,10 @@
                                       << mcld::sys::strerror(handler->error());
   }
 
-  mcld::MemoryArea* output_memory = new MemoryArea(*m_pRegionFactory, *handler);
-  m_pInfo->output().setMemArea(output_memory);
-  m_MemAreaList.push_back(output_memory);
-
-  mcld::LDContext* context = m_pInfo->contextFactory().produce(pPath);
-  m_pInfo->output().setContext(context);
+  m_pOutput = new MemoryArea(*handler);
 
   // FIXME: remove the initStdSections().
-  m_pDriver->initStdSections();
+  m_pObjLinker->initStdSections();
   return true;
 }
 
@@ -293,22 +270,14 @@
 
 bool TestLinker::setOutput(int pFileHandler)
 {
-  if (m_pInfo->output().hasContext())
-    return false;
-
   mcld::FileHandle* handler = new mcld::FileHandle();
   handler->delegate(pFileHandler);
   m_FileHandleList.push_back(handler);
 
-  mcld::MemoryArea* output_memory = new MemoryArea(*m_pRegionFactory, *handler);
-  m_pInfo->output().setMemArea(output_memory);
-  m_MemAreaList.push_back(output_memory);
-
-  mcld::LDContext* context = m_pInfo->contextFactory().produce();
-  m_pInfo->output().setContext(context);
+  m_pOutput = new MemoryArea(*handler);
 
   // FIXME: remove the initStdSections().
-  m_pDriver->initStdSections();
+  m_pObjLinker->initStdSections();
   return true;
 }
 
diff --git a/unittests/Linker/TestLinker.h b/unittests/Linker/TestLinker.h
index f44d2b0..701a405 100644
--- a/unittests/Linker/TestLinker.h
+++ b/unittests/Linker/TestLinker.h
@@ -14,8 +14,9 @@
 #include <string>
 #include <list>
 
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Module.h>
+#include <mcld/Object/ObjectLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
 #include <mcld/LD/DiagnosticPrinter.h>
 #include <mcld/LD/DiagnosticLineInfo.h>
 #include <mcld/Support/TargetRegistry.h>
@@ -23,12 +24,16 @@
 
 namespace mcld {
 
-class MCLDInfo;
+class FileHandle;
+class LinkerConfig;
 class TargetLDBackend;
 class RegionFactory;
+class InputFactory;
+class MemoryAreaFactory;
+class ContextFactory;
+class InputBuilder;
 
-namespace test
-{
+namespace test {
 
 class TestLinker
 {
@@ -39,16 +44,19 @@
 
   bool initialize(const std::string &pTriple);
 
-  MCLDInfo* config() {
-    assert(NULL != m_pInfo);
-    return m_pInfo;
+  LinkerConfig* config() {
+    assert(NULL != m_pConfig);
+    return m_pConfig;
   }
 
-  const MCLDInfo* config() const {
-    assert(NULL != m_pInfo);
-    return m_pInfo;
+  const LinkerConfig* config() const {
+    assert(NULL != m_pConfig);
+    return m_pConfig;
   }
 
+  const Module* module() const { return &m_Module; }
+  Module*       module()       { return &m_Module; }
+
   // -----  search directories  ----- //
   void addSearchDir(const std::string &pPath);
 
@@ -72,28 +80,32 @@
 
   bool setOutput(const sys::fs::Path &pPath);
 
-  /// getDriver
-  MCLDDriver* getDriver() {
-    assert(NULL != m_pDriver);
-    return m_pDriver;
+  const MemoryArea* getOutput() const { return m_pOutput; }
+
+  MemoryArea*       getOutput()       { return m_pOutput; }
+
+  /// getObjLinker
+  ObjectLinker* getObjLinker() {
+    assert(NULL != m_pObjLinker);
+    return m_pObjLinker;
   }
 
-  /// getDriver
-  const MCLDDriver* getDriver() const {
-    assert(NULL != m_pDriver);
-    return m_pDriver;
+  /// getObjLinker
+  const ObjectLinker* getObjLinker() const {
+    assert(NULL != m_pObjLinker);
+    return m_pObjLinker;
   }
 
   /// getLinker
-  MCLinker* getLinker() {
-    assert(NULL != m_pDriver);
-    return m_pDriver->getLinker();
+  FragmentLinker* getLinker() {
+    assert(NULL != m_pObjLinker);
+    return m_pObjLinker->getLinker();
   }
 
   /// getLinker
-  const MCLinker* getLinker() const {
-    assert(NULL != m_pDriver);
-    return m_pDriver->getLinker();
+  const FragmentLinker* getLinker() const {
+    assert(NULL != m_pObjLinker);
+    return m_pObjLinker->getLinker();
   }
 
 private:
@@ -101,21 +113,27 @@
 
 private:
   const mcld::Target* m_pTarget;
-  mcld::MCLDDriver *m_pDriver;
-  mcld::MCLDInfo* m_pInfo;
+  mcld::ObjectLinker *m_pObjLinker;
+  mcld::LinkerConfig* m_pConfig;
+  mcld::Module m_Module;
   mcld::DiagnosticLineInfo* m_pDiagLineInfo;
   mcld::DiagnosticPrinter* m_pDiagPrinter;
   mcld::TargetLDBackend* m_pBackend;
   mcld::InputTree::iterator m_Root;
-  mcld::RegionFactory* m_pRegionFactory;
+  mcld::InputFactory* m_pInputFactory;
   mcld::MemoryAreaFactory* m_pMemAreaFactory;
+  mcld::ContextFactory* m_pContextFactory;
+
+  mcld::InputBuilder* m_pBuilder;
 
   std::list<mcld::FileHandle*> m_FileHandleList;
   std::list<mcld::MemoryArea*> m_MemAreaList;
 
+  mcld::MemoryArea* m_pOutput;
 };
 
 } // namespace of test
 } // namespace of mcld
+
 #endif
 
diff --git a/unittests/LinkerTest.cpp b/unittests/LinkerTest.cpp
new file mode 100644
index 0000000..64da08d
--- /dev/null
+++ b/unittests/LinkerTest.cpp
@@ -0,0 +1,415 @@
+//===- LinkerTest.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "LinkerTest.h"
+
+#include <mcld/Environment.h>
+#include <mcld/Module.h>
+#include <mcld/InputTree.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/Linker.h>
+#include <mcld/LinkerConfig.h>
+
+#include <mcld/Support/Path.h>
+
+#include <llvm/Support/ELF.h>
+
+using namespace mcld;
+using namespace mcld::test;
+using namespace mcld::sys::fs;
+
+
+// Constructor can do set-up work for all test here.
+LinkerTest::LinkerTest()
+{
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+LinkerTest::~LinkerTest()
+{
+}
+
+// SetUp() will be called immediately before each test.
+void LinkerTest::SetUp()
+{
+}
+
+// TearDown() will be called immediately after each test.
+void LinkerTest::TearDown()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Testcases
+//===----------------------------------------------------------------------===//
+TEST_F( LinkerTest, set_up_n_clean_up) {
+
+  Initialize();
+  LinkerConfig config("arm-none-linux-gnueabi");
+
+  Module module("test");
+  config.setCodeGenType(LinkerConfig::DynObj);
+
+  Linker linker;
+  linker.config(config);
+
+  IRBuilder builder(module, config);
+  // create inputs here
+  //   builder.CreateInput("./test.o");
+
+  if (linker.link(module, builder))
+    linker.emit("./test.so");
+
+  Finalize();
+}
+
+// %MCLinker --shared -soname=libplasma.so -Bsymbolic
+// -mtriple="armv7-none-linux-gnueabi"
+// -L=%p/../../../libs/ARM/Android/android-14
+// %p/../../../libs/ARM/Android/android-14/crtbegin_so.o
+// %p/plasma.o
+// -lm -llog -ljnigraphics -lc
+// %p/../../../libs/ARM/Android/android-14/crtend_so.o
+// -o libplasma.so
+TEST_F( LinkerTest, plasma) {
+
+  Initialize();
+  Linker linker;
+
+  ///< --mtriple="armv7-none-linux-gnueabi"
+  LinkerConfig config("armv7-none-linux-gnueabi");
+
+  /// To configure linker before setting options. Linker::config sets up
+  /// default target-dependent configuration to LinkerConfig.
+  linker.config(config);
+
+  config.setCodeGenType(LinkerConfig::DynObj);  ///< --shared
+  config.options().setSOName("libplasma.so");   ///< --soname=libplasma.so
+  config.options().setBsymbolic();              ///< -Bsymbolic
+
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  Path search_dir(TOPDIR);
+  search_dir.append("test/libs/ARM/Android/android-14");
+  config.options().directories().insert(search_dir);
+
+  Module module("libplasma.so");
+  IRBuilder builder(module, config);
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+  Path crtbegin(search_dir);
+  crtbegin.append("crtbegin_so.o");
+  builder.ReadInput("crtbegin", crtbegin);
+
+  /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+  Path plasma(TOPDIR);
+  plasma.append("test/Android/Plasma/ARM/plasma.o");
+  builder.ReadInput("plasma", plasma);
+
+  // -lm -llog -ljnigraphics -lc
+  builder.ReadInput("m");
+  builder.ReadInput("log");
+  builder.ReadInput("jnigraphics");
+  builder.ReadInput("c");
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+  Path crtend(search_dir);
+  crtend.append("crtend_so.o");
+  builder.ReadInput("crtend", crtend);
+
+  if (linker.link(module, builder)) {
+    linker.emit("libplasma.so"); ///< -o libplasma.so
+  }
+
+  Finalize();
+}
+
+// The outputs generated without -Bsymbolic usually have more relocation
+// entries than the outputs generated with -Bsymbolic. This testcase generates
+// output with -Bsymbolic first, then generate the same output without -Bsymbolic.
+// By this way, we can make sure symbols and relocations are cleaned between
+// two linkings.
+TEST_F( LinkerTest, plasma_twice) {
+
+  Initialize();
+  Linker linker;
+
+  ///< --mtriple="armv7-none-linux-gnueabi"
+  LinkerConfig config1("armv7-none-linux-gnueabi");
+
+  /// To configure linker before setting options. Linker::config sets up
+  /// default target-dependent configuration to LinkerConfig.
+  linker.config(config1);
+
+  config1.setCodeGenType(LinkerConfig::DynObj);  ///< --shared
+  config1.options().setSOName("libplasma.once.so");   ///< --soname=libplasma.twice.so
+  config1.options().setBsymbolic(false);              ///< -Bsymbolic
+
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  Path search_dir(TOPDIR);
+  search_dir.append("test/libs/ARM/Android/android-14");
+  config1.options().directories().insert(search_dir);
+
+  Module module1("libplasma.once.so");
+  IRBuilder builder1(module1, config1);
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+  Path crtbegin(search_dir);
+  crtbegin.append("crtbegin_so.o");
+  builder1.ReadInput("crtbegin", crtbegin);
+
+  /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+  Path plasma(TOPDIR);
+  plasma.append("test/Android/Plasma/ARM/plasma.o");
+  builder1.ReadInput("plasma", plasma);
+
+  // -lm -llog -ljnigraphics -lc
+  builder1.ReadInput("m");
+  builder1.ReadInput("log");
+  builder1.ReadInput("jnigraphics");
+  builder1.ReadInput("c");
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+  Path crtend(search_dir);
+  crtend.append("crtend_so.o");
+  builder1.ReadInput("crtend", crtend);
+
+  if (linker.link(module1, builder1)) {
+    linker.emit("libplasma.once.so"); ///< -o libplasma.so
+  }
+
+  Finalize();
+
+  linker.reset();
+
+  Initialize();
+
+  ///< --mtriple="armv7-none-linux-gnueabi"
+  LinkerConfig config2("armv7-none-linux-gnueabi");
+
+  /// To configure linker before setting options. Linker::config sets up
+  /// default target-dependent configuration to LinkerConfig.
+  linker.config(config2);
+
+  config2.setCodeGenType(LinkerConfig::DynObj);  ///< --shared
+  config2.options().setSOName("libplasma.twice.so");   ///< --soname=libplasma.twice.exe
+  config2.options().setBsymbolic();              ///< -Bsymbolic
+
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  config2.options().directories().insert(search_dir);
+
+  Module module2("libplasma.so");
+  IRBuilder builder2(module2, config2);
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+  builder2.ReadInput("crtbegin", crtbegin);
+
+  /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+  builder2.ReadInput("plasma", plasma);
+
+  // -lm -llog -ljnigraphics -lc
+  builder2.ReadInput("m");
+  builder2.ReadInput("log");
+  builder2.ReadInput("jnigraphics");
+  builder2.ReadInput("c");
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+  builder2.ReadInput("crtend", crtend);
+
+  if (linker.link(module2, builder2)) {
+    linker.emit("libplasma.twice.so"); ///< -o libplasma.exe
+  }
+
+  Finalize();
+}
+
+// This testcase put IRBuilder in the heap
+TEST_F( LinkerTest, plasma_twice_irbuilder_heap) {
+
+  Initialize();
+  Linker linker;
+
+  ///< --mtriple="armv7-none-linux-gnueabi"
+  LinkerConfig config1("armv7-none-linux-gnueabi");
+
+  /// To configure linker before setting options. Linker::config sets up
+  /// default target-dependent configuration to LinkerConfig.
+  linker.config(config1);
+
+  config1.setCodeGenType(LinkerConfig::DynObj);  ///< --shared
+  config1.options().setSOName("libplasma.once.so");   ///< --soname=libplasma.twice.so
+  config1.options().setBsymbolic(false);              ///< -Bsymbolic
+
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  Path search_dir(TOPDIR);
+  search_dir.append("test/libs/ARM/Android/android-14");
+  config1.options().directories().insert(search_dir);
+
+  Module module1("libplasma.once.so");
+  IRBuilder *builder1 = new IRBuilder(module1, config1);
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+  Path crtbegin(search_dir);
+  crtbegin.append("crtbegin_so.o");
+  builder1->ReadInput("crtbegin", crtbegin);
+
+  /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+  Path plasma(TOPDIR);
+  plasma.append("test/Android/Plasma/ARM/plasma.o");
+  builder1->ReadInput("plasma", plasma);
+
+  // -lm -llog -ljnigraphics -lc
+  builder1->ReadInput("m");
+  builder1->ReadInput("log");
+  builder1->ReadInput("jnigraphics");
+  builder1->ReadInput("c");
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+  Path crtend(search_dir);
+  crtend.append("crtend_so.o");
+  builder1->ReadInput("crtend", crtend);
+
+  if (linker.link(module1, *builder1)) {
+    linker.emit("libplasma.once.so"); ///< -o libplasma.so
+  }
+
+  // Can not delete builder until emit the output. Dynamic string table
+  // needs the file name of the input files, and the inputs' life is
+  // controlled by IRBuilder
+  delete builder1;
+
+  Finalize();
+
+  linker.reset();
+
+  Initialize();
+
+  ///< --mtriple="armv7-none-linux-gnueabi"
+  LinkerConfig config2("armv7-none-linux-gnueabi");
+
+  /// To configure linker before setting options. Linker::config sets up
+  /// default target-dependent configuration to LinkerConfig.
+  linker.config(config2);
+
+  config2.setCodeGenType(LinkerConfig::DynObj);  ///< --shared
+  config2.options().setSOName("libplasma.twice.so");   ///< --soname=libplasma.twice.exe
+  config2.options().setBsymbolic();              ///< -Bsymbolic
+
+  /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+  config2.options().directories().insert(search_dir);
+
+  Module module2("libplasma.so");
+  IRBuilder* builder2 = new IRBuilder(module2, config2);
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+  builder2->ReadInput("crtbegin", crtbegin);
+
+  /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+  builder2->ReadInput("plasma", plasma);
+
+  // -lm -llog -ljnigraphics -lc
+  builder2->ReadInput("m");
+  builder2->ReadInput("log");
+  builder2->ReadInput("jnigraphics");
+  builder2->ReadInput("c");
+
+  /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+  builder2->ReadInput("crtend", crtend);
+
+  if (linker.link(module2, *builder2)) {
+    linker.emit("libplasma.twice.so"); ///< -o libplasma.exe
+  }
+
+  delete builder2;
+  Finalize();
+}
+
+// %MCLinker --shared -soname=libgotplt.so -mtriple arm-none-linux-gnueabi
+// gotplt.o -o libgotplt.so
+TEST_F( LinkerTest, plasma_object) {
+
+  Initialize();
+  Linker linker;
+
+  ///< --mtriple="armv7-none-linux-gnueabi"
+  LinkerConfig config("armv7-none-linux-gnueabi");
+
+  /// To configure linker before setting options. Linker::config sets up
+  /// default target-dependent configuration to LinkerConfig.
+  linker.config(config);
+
+  config.setCodeGenType(LinkerConfig::DynObj);  ///< --shared
+  config.options().setSOName("libgotplt.so");   ///< --soname=libgotplt.so
+
+  Module module;
+  IRBuilder builder(module, config);
+
+  Path gotplt_o(TOPDIR);
+  gotplt_o.append("test/PLT/gotplt.o");
+  Input* input = builder.CreateInput("gotplt.o", gotplt_o, Input::Object);
+
+  /// [ 0]                   NULL            00000000 000000 000000 00      0   0  0
+  builder.CreateELFHeader(*input,
+                          "",
+                          LDFileFormat::Null,
+                          llvm::ELF::SHT_NULL,
+                          0x0);
+
+  /// [ 1] .text             PROGBITS        00000000 000034 000010 00  AX  0   0  4
+  LDSection* text = builder.CreateELFHeader(*input,
+                              ".text",
+                              llvm::ELF::SHT_PROGBITS,
+                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
+                              4);
+
+  SectionData* text_data = builder.CreateSectionData(*text);
+  static uint8_t text_content[] = { 0x00, 0x48, 0x2d, 0xe9,
+                                    0xfe, 0xff, 0xff, 0xeb,
+                                    0x00, 0x48, 0xbd, 0xe8,
+                                    0x0e, 0xf0, 0xa0, 0xe1 };
+  Fragment* text_frag = builder.CreateRegion(text_content, 0x10);
+  builder.AppendFragment(*text_frag, *text_data);
+
+  // [ 3] .data             PROGBITS        00000000 000044 000000 00  WA  0   0  4
+  builder.CreateELFHeader(*input,
+                          ".data",
+                          llvm::ELF::SHT_PROGBITS,
+                          llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+                          4);
+
+  // [ 4] .bss              NOBITS          00000000 000044 000000 00  WA  0   0  4
+  builder.CreateELFHeader(*input,
+                          ".bss",
+                          llvm::ELF::SHT_PROGBITS,
+                          llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+                          4);
+  // [ 5] .ARM.attributes   ARM_ATTRIBUTES  00000000 000044 000020 00      0   0  1
+  LDSection* attr = builder.CreateELFHeader(*input,
+                              ".ARM.attributes",
+                              llvm::ELF::SHT_ARM_ATTRIBUTES,
+                              0x0,
+                              4);
+
+  SectionData* attr_data = builder.CreateSectionData(*attr);
+  static uint8_t attr_content[] = {
+                      0x41, 0x1f, 0x00, 0x00,
+                      0x00, 0x61, 0x65, 0x61,
+                      0x62, 0x69, 0x00, 0x01,
+                      0x15, 0x00, 0x00, 0x00,
+                      0x06, 0x02, 0x08, 0x01,
+                      0x09, 0x01, 0x14, 0x01,
+                      0x15, 0x01, 0x17, 0x03,
+                      0x18, 0x01, 0x19, 0x01 };
+  Fragment* attr_frag = builder.CreateRegion(attr_content, 0x20);
+  builder.AppendFragment(*attr_frag, *attr_data);
+
+  if (linker.link(module, builder)) {
+    linker.emit("libgotplt.so"); ///< -o libgotplt.so
+  }
+
+  Finalize();
+}
diff --git a/unittests/LinkerTest.h b/unittests/LinkerTest.h
new file mode 100644
index 0000000..cb60d40
--- /dev/null
+++ b/unittests/LinkerTest.h
@@ -0,0 +1,40 @@
+//===- LinkerTest.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LINKER_TEST_H
+#define MCLD_LINKER_TEST_H
+
+#include <gtest.h>
+
+namespace mcld {
+
+class Linker;
+
+namespace test {
+
+class LinkerTest : public ::testing::Test
+{
+public:
+  // Constructor can do set-up work for all test here.
+  LinkerTest();
+
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~LinkerTest();
+
+  // 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 for mcld
+
+#endif
+
diff --git a/unittests/PathTest.cpp b/unittests/PathTest.cpp
index 2a4de80..2a44368 100644
--- a/unittests/PathTest.cpp
+++ b/unittests/PathTest.cpp
@@ -155,3 +155,13 @@
   EXPECT_TRUE(m_pTestee->parent_path().empty());
 }
 
+TEST_F(PathTest, filename) {
+  m_pTestee->assign("aa/bb/cc");
+  EXPECT_STREQ("cc", m_pTestee->filename().c_str());
+
+  m_pTestee->assign("aa/bb/");
+  EXPECT_STREQ("", m_pTestee->filename().c_str());
+
+  m_pTestee->assign("aa");
+  EXPECT_STREQ("aa", m_pTestee->filename().c_str());
+}
diff --git a/unittests/RTLinearAllocatorTest.cpp b/unittests/RTLinearAllocatorTest.cpp
index 9ef31e5..7ed5dac 100644
--- a/unittests/RTLinearAllocatorTest.cpp
+++ b/unittests/RTLinearAllocatorTest.cpp
@@ -43,31 +43,31 @@
 TEST_F(RTLinearAllocatorTest, AllocateN) {
 	Data* pointer = m_pTestee->allocate(10);
 	ASSERT_FALSE(0 == pointer);
-	ASSERT_EQ(CHUNK_SIZE, m_pTestee->max_size());
+	ASSERT_TRUE(CHUNK_SIZE == m_pTestee->max_size());
 	ASSERT_FALSE(m_pTestee->empty());
 }
 
 TEST_F(RTLinearAllocatorTest, allocate ) {
 	Data* pointer = m_pTestee->allocate();
 	ASSERT_FALSE(0 == pointer);
-	ASSERT_EQ(CHUNK_SIZE, m_pTestee->max_size());
+	ASSERT_TRUE(CHUNK_SIZE == m_pTestee->max_size());
 	ASSERT_FALSE(m_pTestee->empty());
 }
 
 TEST_F(RTLinearAllocatorTest, allocateOver ) {
 	Data* pointer = m_pTestee->allocate(CHUNK_SIZE+1);
 	ASSERT_TRUE(0 == pointer);
-	ASSERT_EQ(0, m_pTestee->max_size());
+	ASSERT_TRUE(0 == m_pTestee->max_size());
 	ASSERT_TRUE(m_pTestee->empty());
 }
 
 TEST_F(RTLinearAllocatorTest, alloc_construct ) {
 	Data* pointer = m_pTestee->allocate();
 	m_pTestee->construct(pointer);
-	ASSERT_EQ(1, pointer->one);
-	ASSERT_EQ(2, pointer->two);
-	ASSERT_EQ(3, pointer->three);
-	ASSERT_EQ(4, pointer->four);
+	ASSERT_TRUE(1 == pointer->one);
+	ASSERT_TRUE(2 == pointer->two);
+	ASSERT_TRUE(3 == pointer->three);
+	ASSERT_TRUE(4 == pointer->four);
 }
 
 TEST_F(RTLinearAllocatorTest, alloc_constructCopy ) {
@@ -75,19 +75,19 @@
 	Data data(7, 7, 7, 7);
 	m_pTestee->construct(pointer, data);
 
-	ASSERT_EQ(7, pointer->one);
-	ASSERT_EQ(7, pointer->two);
-	ASSERT_EQ(7, pointer->three);
-	ASSERT_EQ(7, pointer->four);
+	ASSERT_TRUE(7 == pointer->one);
+	ASSERT_TRUE(7 == pointer->two);
+	ASSERT_TRUE(7 == pointer->three);
+	ASSERT_TRUE(7 == pointer->four);
 }
 
 TEST_F(RTLinearAllocatorTest, allocN_construct ) {
 	Data* pointer = m_pTestee->allocate(10);
 	m_pTestee->construct(pointer);
-	ASSERT_EQ(1, pointer->one);
-	ASSERT_EQ(2, pointer->two);
-	ASSERT_EQ(3, pointer->three);
-	ASSERT_EQ(4, pointer->four);
+	ASSERT_TRUE(1 == pointer->one);
+	ASSERT_TRUE(2 == pointer->two);
+	ASSERT_TRUE(3 == pointer->three);
+	ASSERT_TRUE(4 == pointer->four);
 }
 
 TEST_F(RTLinearAllocatorTest, allocN_constructCopy ) {
@@ -95,10 +95,10 @@
 	Data data(7, 7, 7, 7);
 	m_pTestee->construct(pointer, data);
 	
-	ASSERT_EQ(7, pointer->one);
-	ASSERT_EQ(7, pointer->two);
-	ASSERT_EQ(7, pointer->three);
-	ASSERT_EQ(7, pointer->four);
+	ASSERT_TRUE(7 == pointer->one);
+	ASSERT_TRUE(7 == pointer->two);
+	ASSERT_TRUE(7 == pointer->three);
+	ASSERT_TRUE(7 == pointer->four);
 }
 
 TEST_F(RTLinearAllocatorTest, multi_alloc_ctor_iterate ) {
diff --git a/unittests/ReadStageTest.cpp b/unittests/ReadStageTest.cpp
index c687c0b..b2aaf8d 100644
--- a/unittests/ReadStageTest.cpp
+++ b/unittests/ReadStageTest.cpp
@@ -7,13 +7,17 @@
 //
 //===----------------------------------------------------------------------===//
 #include "ReadStageTest.h"
+
+#include <mcld/Module.h>
 #include <mcld/LD/LDContext.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/SectionData.h>
-#include <mcld/LD/Fragment.h>
-#include <mcld/LD/FragmentRef.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/FragmentRef.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/ResolveInfo.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/Support/FileHandle.h>
 
 #include <sstream>
 #include <iostream>
@@ -41,13 +45,13 @@
   m_pLinker->initialize("arm-none-linux-gnueabi");
 
   // set up target-dependent constraints of attributes
-  m_pLinker->config()->attrFactory().constraint().enableWholeArchive();
-  m_pLinker->config()->attrFactory().constraint().disableAsNeeded();
-  m_pLinker->config()->attrFactory().constraint().setSharedSystem();
+  m_pLinker->config()->attribute().constraint().enableWholeArchive();
+  m_pLinker->config()->attribute().constraint().disableAsNeeded();
+  m_pLinker->config()->attribute().constraint().setSharedSystem();
 
   // set up the predefined attributes
-  m_pLinker->config()->attrFactory().predefined().setWholeArchive();
-  m_pLinker->config()->attrFactory().predefined().setDynamic();
+  m_pLinker->config()->attribute().predefined().setWholeArchive();
+  m_pLinker->config()->attribute().predefined().setDynamic();
 
   // set up target dependent options
   mcld::sys::fs::Path path = TOPDIR;
@@ -68,17 +72,17 @@
 void ReadStageTest::dumpInput(const mcld::Input &pInput, mcld::FileHandle &pFile, size_t pIdent)
 {
   stringstream sstream;
-  for (int i=0; i < pIdent; ++i)
+  for (size_t i=0; i < pIdent; ++i)
     sstream << " ";
   sstream << "<input name=\"" << pInput.name() << "\">\n";
 
   LDContext::const_sect_iterator sect, sectEnd = pInput.context()->sectEnd();
   for (sect = pInput.context()->sectBegin(); sect != sectEnd; ++sect) {
-    for (int i=0; i < (pIdent+1); ++i)
+    for (size_t i=0; i < (pIdent+1); ++i)
       sstream << " ";
     sstream << "<section name=\"" << (*sect)->name() << "\"/>\n";
   }
-  for (int i=0; i < pIdent; ++i)
+  for (size_t i=0; i < pIdent; ++i)
     sstream << " ";
   sstream << "</input>\n";
 
@@ -87,20 +91,20 @@
   pFile.write(sstream.str().data(), org_size, sstream.str().size());
 }
 
-void ReadStageTest::dumpOutput(const mcld::Output &pOutput, mcld::FileHandle &pFile, size_t pIdent)
+void ReadStageTest::dumpOutput(const mcld::Module& pModule, mcld::FileHandle &pFile, size_t pIdent)
 {
   stringstream sstream;
-  for (int i=0; i < pIdent; ++i)
+  for (size_t i=0; i < pIdent; ++i)
     sstream << " ";
-  sstream << "<output name=\"" << pOutput.name() << "\">\n";
+  sstream << "<output name=\"" << m_pLinker->module()->name() << "\">\n";
 
-  LDContext::const_sect_iterator sect, sectEnd = pOutput.context()->sectEnd();
-  for (sect = pOutput.context()->sectBegin(); sect != sectEnd; ++sect) {
-    for (int i=0; i < (pIdent+1); ++i)
+  Module::const_iterator sect, sectEnd = pModule.end();
+  for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+    for (size_t i=0; i < (pIdent+1); ++i)
       sstream << " ";
     sstream << "<section name=\"" << (*sect)->name() << "\"/>\n";
   }
-  for (int i=0; i < pIdent; ++i)
+  for (size_t i=0; i < pIdent; ++i)
     sstream << " ";
   sstream << "</output>\n";
 
@@ -115,7 +119,7 @@
   mcld::sys::fs::Path top_level = TOPDIR;
 
   // set up output
-  m_pLinker->config()->output().setType(mcld::Output::DynObj);
+  m_pLinker->config()->setCodeGenType(mcld::LinkerConfig::DynObj);
   m_pLinker->setOutput(top_level + "unittests/plasma.so");
 
 
@@ -129,19 +133,19 @@
   m_pLinker->addObject(top_level + "test/libs/ARM/Android/android-14/crtend_so.o");
 
   // dump status
-  m_pLinker->getDriver()->normalize();
+  m_pLinker->getObjLinker()->normalize();
 
   FileHandle file;
   file.open(top_level + "unittests/read_stage.xml",
      FileHandle::ReadWrite | FileHandle::Create | FileHandle::Truncate, 0644);
 
-  InputTree::iterator input, inEnd = m_pLinker->config()->inputs().end();
-  for (input = m_pLinker->config()->inputs().begin(); input != inEnd; ++input) {
+  Module::input_iterator input, inEnd = m_pLinker->module()->input_end();
+  for (input = m_pLinker->module()->input_begin(); input != inEnd; ++input) {
     dumpInput(**input, file, 1);
   }
 
-  dumpOutput(m_pLinker->config()->output(), file, 1);
+  dumpOutput(*m_pLinker->module(), file, 1);
   // dump status
-  ASSERT_TRUE(m_pLinker->getDriver()->mergeSections());
+  ASSERT_TRUE(m_pLinker->getObjLinker()->mergeSections());
 }
 
diff --git a/unittests/ReadStageTest.h b/unittests/ReadStageTest.h
index 5fd4595..e799664 100644
--- a/unittests/ReadStageTest.h
+++ b/unittests/ReadStageTest.h
@@ -32,7 +32,7 @@
 
   void dumpInput(const mcld::Input &pInput, mcld::FileHandle &pFile, size_t pIdent);
 
-  void dumpOutput(const mcld::Output &pOutput, mcld::FileHandle &pFile, size_t pIdent);
+  void dumpOutput(const mcld::Module &pModule, mcld::FileHandle &pFile, size_t pIdent);
 protected:
   TestLinker* m_pLinker;
 };
diff --git a/unittests/SectionDataTest.cpp b/unittests/SectionDataTest.cpp
index d100f56..5113068 100644
--- a/unittests/SectionDataTest.cpp
+++ b/unittests/SectionDataTest.cpp
@@ -41,29 +41,27 @@
 //===----------------------------------------------------------------------===//
  
 TEST_F( SectionDataTest, constructor_and_trivial_func ) {
-  LDSection test("test", LDFileFormat::Null, 0, 0);
+  LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
   
-  SectionData* s = new SectionData(test);
+  SectionData* s = SectionData::Create(*test);
   EXPECT_TRUE(s->getSection().name() == "test" && \
               s->getSection().kind() == LDFileFormat::Null);
   
-  s->setAlignment(5566);
-  EXPECT_TRUE(5566 == s->getAlignment());
 
-  delete s;
+  LDSection::Destroy(test);
 }
 
 TEST_F( SectionDataTest, Fragment_list_and_iterator ) {
-  LDSection test("test", LDFileFormat::Null, 0, 0);
-  SectionData* s = new SectionData(test);
+  LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
+  SectionData* s = SectionData::Create(*test);
   EXPECT_TRUE(s->empty());
 
-  Fragment* f1 = new Fragment(Fragment::Alignment, s);
-  Fragment* f2 = new Fragment(Fragment::Alignment, s);
-  Fragment* f3 = new Fragment(Fragment::Region, s);
-  Fragment* f4 = new Fragment(Fragment::Fillment, s);
-  Fragment* f5 = new Fragment(Fragment::Relocation, s);
-  Fragment* f6 = new Fragment(Fragment::Target, s);
+  new Fragment(Fragment::Alignment, s);
+  new Fragment(Fragment::Alignment, s);
+  new Fragment(Fragment::Region, s);
+  new Fragment(Fragment::Fillment, s);
+  new Fragment(Fragment::Relocation, s);
+  new Fragment(Fragment::Target, s);
   EXPECT_TRUE(6 == s->size());
 
   //iterator
@@ -82,5 +80,5 @@
   ++iter;
   EXPECT_TRUE(iter == s->end());
 
-  delete s;
+  LDSection::Destroy(test);
 }
diff --git a/unittests/StaticResolverTest.cpp b/unittests/StaticResolverTest.cpp
index 439f21a..cb4c668 100644
--- a/unittests/StaticResolverTest.cpp
+++ b/unittests/StaticResolverTest.cpp
@@ -6,24 +6,14 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include "StaticResolverTest.h"
 #include <mcld/Support/TargetSelect.h>
 #include <mcld/LD/StaticResolver.h>
 #include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/ResolveInfoFactory.h>
-#include <mcld/LD/DiagnosticPrinter.h>
-#include <mcld/LD/DiagnosticLineInfo.h>
-#include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/MC/MCLDInfo.h>
-#include "StaticResolverTest.h"
+#include <mcld/LinkerConfig.h>
 
-#include <iostream>
-#include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/FileSystem.h>
-#include <mcld/LD/DiagnosticLineInfo.h>
-#include <mcld/LD/TextDiagnosticPrinter.h>
 
-using namespace std;
 using namespace mcld;
 using namespace mcldtest;
 
@@ -32,25 +22,20 @@
 //===----------------------------------------------------------------------===//
 // Constructor can do set-up work for all test here.
 StaticResolverTest::StaticResolverTest()
-  : m_pResolver(NULL), m_pFactory(NULL), m_pLDInfo(NULL), m_pLineInfo(NULL) {
+  : m_pResolver(NULL), m_pConfig(NULL) {
   // create testee. modify it if need
   m_pResolver = new StaticResolver();
-  m_pFactory = new ResolveInfoFactory();
 
   mcld::InitializeAllDiagnostics();
 
-  m_pLDInfo = new MCLDInfo("arm-none-linux-gnueabi", 10, 10);
-  m_pLineInfo = new DiagnosticLineInfo();
-  mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, NULL);
+  m_pConfig = new LinkerConfig("arm-none-linux-gnueabi");
 }
 
 // Destructor can do clean-up work that doesn't throw exceptions here.
 StaticResolverTest::~StaticResolverTest()
 {
   delete m_pResolver;
-  delete m_pFactory;
-  delete m_pLDInfo;
-  delete m_pLineInfo;
+  delete m_pConfig;
 }
 
 // SetUp() will be called immediately before each test.
@@ -67,12 +52,12 @@
 // Testcases
 //
 TEST_F( StaticResolverTest, MDEF ) {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   new_sym->setDesc(ResolveInfo::Define);
   old_sym->setDesc(ResolveInfo::Define);
-  ASSERT_EQ( mcld::ResolveInfo::Define, new_sym->desc());
-  ASSERT_EQ( mcld::ResolveInfo::Define, old_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Define == new_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Define == old_sym->desc());
   ASSERT_TRUE( mcld::ResolveInfo::define_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::define_flag == old_sym->info());
   bool override = true;
@@ -82,8 +67,8 @@
 }
 
 TEST_F( StaticResolverTest, DynDefAfterDynUndef ) {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   
   new_sym->setBinding(ResolveInfo::Global);
   old_sym->setBinding(ResolveInfo::Global);
@@ -96,21 +81,21 @@
 
   old_sym->setSize(1);
 
-  ASSERT_EQ( mcld::ResolveInfo::Global,    new_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Global,    old_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Undefined, new_sym->desc());
-  ASSERT_EQ( mcld::ResolveInfo::Define,    old_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Global == old_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Undefined == new_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Define    == old_sym->desc());
 
   bool override = false;
   bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
-  ASSERT_EQ(1, old_sym->size());
+  ASSERT_TRUE(1 == old_sym->size());
 }
 
 TEST_F( StaticResolverTest, DynDefAfterDynDef ) {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   
   new_sym->setBinding(ResolveInfo::Global);
   old_sym->setBinding(ResolveInfo::Global);
@@ -123,21 +108,21 @@
 
   old_sym->setSize(1);
 
-  ASSERT_EQ( mcld::ResolveInfo::Global, new_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Global, old_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Define, new_sym->desc());
-  ASSERT_EQ( mcld::ResolveInfo::Define, old_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Global == old_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Define == new_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Define == old_sym->desc());
 
   bool override = false;
   bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
-  ASSERT_EQ(1, old_sym->size());
+  ASSERT_TRUE(1 == old_sym->size());
 }
 
 TEST_F( StaticResolverTest, DynUndefAfterDynUndef ) {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   
   new_sym->setBinding(ResolveInfo::Global);
   old_sym->setBinding(ResolveInfo::Global);
@@ -150,30 +135,30 @@
 
   old_sym->setSize(1);
 
-  ASSERT_EQ( mcld::ResolveInfo::Global,    new_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Global,    old_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Undefined, new_sym->desc());
-  ASSERT_EQ( mcld::ResolveInfo::Undefined, old_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Global    == new_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Global    == old_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Undefined == new_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Undefined ==  old_sym->desc());
 
   bool override = false;
   bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
-  ASSERT_EQ(1, old_sym->size());
+  ASSERT_TRUE(1 == old_sym->size());
 }
 
 TEST_F( StaticResolverTest, OverrideWeakByGlobal )
 {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   
   new_sym->setBinding(ResolveInfo::Global);
   old_sym->setBinding(ResolveInfo::Weak);
   new_sym->setSize(0);
   old_sym->setSize(1);
 
-  ASSERT_EQ( mcld::ResolveInfo::Global, new_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Weak, old_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Weak == old_sym->binding());
 
   ASSERT_TRUE( mcld::ResolveInfo::global_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::weak_flag == old_sym->info());
@@ -181,12 +166,12 @@
   bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
   ASSERT_TRUE(result);
   ASSERT_TRUE( override );
-  ASSERT_EQ(0, old_sym->size());
+  ASSERT_TRUE(0 == old_sym->size());
 }
 
 TEST_F( StaticResolverTest, DynWeakAfterDynDef ) {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   
   old_sym->setBinding(ResolveInfo::Weak);
   new_sym->setBinding(ResolveInfo::Global);
@@ -201,30 +186,30 @@
 
   old_sym->setSize(1);
 
-  ASSERT_EQ( mcld::ResolveInfo::Weak,   old_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Global, new_sym->binding());
-  ASSERT_EQ( mcld::ResolveInfo::Define, old_sym->desc());
-  ASSERT_EQ( mcld::ResolveInfo::Define, new_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Weak   == old_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+  ASSERT_TRUE( mcld::ResolveInfo::Define == old_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Define == new_sym->desc());
 
   bool override = false;
   bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
-  ASSERT_EQ(1, old_sym->size());
+  ASSERT_TRUE(1 == old_sym->size());
 }
 
 TEST_F( StaticResolverTest, MarkByBiggerCommon )
 {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   
   new_sym->setDesc(ResolveInfo::Common);
   old_sym->setDesc(ResolveInfo::Common);
   new_sym->setSize(999);
   old_sym->setSize(0);
 
-  ASSERT_EQ( mcld::ResolveInfo::Common, new_sym->desc());
-  ASSERT_EQ( mcld::ResolveInfo::Common, old_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Common == new_sym->desc());
+  ASSERT_TRUE( mcld::ResolveInfo::Common == old_sym->desc());
 
   ASSERT_TRUE( mcld::ResolveInfo::common_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::common_flag == old_sym->info());
@@ -232,13 +217,13 @@
   bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
   ASSERT_TRUE(result);
   ASSERT_FALSE( override );
-  ASSERT_EQ(999, old_sym->size());
+  ASSERT_TRUE(999 == old_sym->size());
 }
 
 TEST_F( StaticResolverTest, OverrideByBiggerCommon )
 {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   
   new_sym->setDesc(ResolveInfo::Common);
   old_sym->setDesc(ResolveInfo::Common);
@@ -246,9 +231,9 @@
   new_sym->setSize(999);
   old_sym->setSize(0);
 
-  ASSERT_EQ( ResolveInfo::Common, new_sym->desc());
-  ASSERT_EQ( ResolveInfo::Common, old_sym->desc());
-  ASSERT_EQ( ResolveInfo::Weak, old_sym->binding());
+  ASSERT_TRUE( ResolveInfo::Common == new_sym->desc());
+  ASSERT_TRUE( ResolveInfo::Common == old_sym->desc());
+  ASSERT_TRUE( ResolveInfo::Weak == old_sym->binding());
 
   ASSERT_TRUE( ResolveInfo::common_flag == new_sym->info());
   ASSERT_TRUE( (ResolveInfo::weak_flag | ResolveInfo::common_flag) == old_sym->info());
@@ -257,13 +242,13 @@
   bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
   ASSERT_TRUE(result);
   ASSERT_TRUE( override );
-  ASSERT_EQ(999, old_sym->size());
+  ASSERT_TRUE(999 == old_sym->size());
 }
 
 TEST_F( StaticResolverTest, OverrideCommonByDefine)
 {
-  ResolveInfo* old_sym = m_pFactory->produce("abc");
-  ResolveInfo* new_sym = m_pFactory->produce("abc");
+  ResolveInfo* old_sym = ResolveInfo::Create("abc");
+  ResolveInfo* new_sym = ResolveInfo::Create("abc");
   
   old_sym->setDesc(ResolveInfo::Common);
   old_sym->setSize(0);
@@ -271,8 +256,8 @@
   new_sym->setDesc(ResolveInfo::Define);
   new_sym->setSize(999);
 
-  ASSERT_EQ( ResolveInfo::Define, new_sym->desc());
-  ASSERT_EQ( ResolveInfo::Common, old_sym->desc());
+  ASSERT_TRUE( ResolveInfo::Define == new_sym->desc());
+  ASSERT_TRUE( ResolveInfo::Common == old_sym->desc());
 
   ASSERT_TRUE( ResolveInfo::define_flag == new_sym->info());
   ASSERT_TRUE( ResolveInfo::common_flag == old_sym->info());
@@ -281,12 +266,12 @@
   bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
   ASSERT_TRUE(result);
   ASSERT_TRUE( override );
-  ASSERT_EQ(999, old_sym->size());
+  ASSERT_TRUE(999 == old_sym->size());
 }
 
 TEST_F( StaticResolverTest, SetUpDesc)
 {
-  ResolveInfo* sym = m_pFactory->produce("abc");
+  ResolveInfo* sym = ResolveInfo::Create("abc");
   
   sym->setIsSymbol(true);
 
@@ -300,10 +285,10 @@
   ASSERT_FALSE( sym->isDyn() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( 0, sym->desc() );
-  ASSERT_EQ( 0, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( 0 == sym->desc() );
+  ASSERT_TRUE( 0 == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 
   sym->setIsSymbol(false);
   ASSERT_FALSE( sym->isSymbol() );
@@ -316,10 +301,10 @@
   ASSERT_FALSE( sym->isDyn() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( 0, sym->desc() );
-  ASSERT_EQ( 0, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( 0 == sym->desc() );
+  ASSERT_TRUE( 0 == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 
   sym->setDesc(ResolveInfo::Define);
   ASSERT_FALSE( sym->isSymbol() );
@@ -332,10 +317,10 @@
   ASSERT_FALSE( sym->isDyn() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( ResolveInfo::Define, sym->desc() );
-  ASSERT_EQ( 0, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( ResolveInfo::Define == sym->desc() );
+  ASSERT_TRUE( 0 == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 
   sym->setDesc(ResolveInfo::Common);
   ASSERT_FALSE( sym->isSymbol() );
@@ -348,10 +333,10 @@
   ASSERT_FALSE( sym->isUndef() );
   ASSERT_TRUE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( ResolveInfo::Common, sym->desc() );
-  ASSERT_EQ( 0, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( ResolveInfo::Common == sym->desc() );
+  ASSERT_TRUE( 0 == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 
   sym->setDesc(ResolveInfo::Indirect);
   ASSERT_FALSE( sym->isSymbol() );
@@ -363,10 +348,10 @@
   ASSERT_FALSE( sym->isUndef() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_TRUE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( ResolveInfo::Indirect, sym->desc() );
-  ASSERT_EQ( 0, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( ResolveInfo::Indirect == sym->desc() );
+  ASSERT_TRUE( 0 == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 
   sym->setDesc(ResolveInfo::Undefined);
   ASSERT_FALSE( sym->isSymbol() );
@@ -378,15 +363,15 @@
   ASSERT_FALSE( sym->isDefine() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( 0, sym->desc() );
-  ASSERT_EQ( 0, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( 0 == sym->desc() );
+  ASSERT_TRUE( 0 == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 }
 
 TEST_F( StaticResolverTest, SetUpBinding)
 {
-  ResolveInfo* sym = m_pFactory->produce("abc");
+  ResolveInfo* sym = ResolveInfo::Create("abc");
   
   sym->setIsSymbol(true);
 
@@ -400,10 +385,10 @@
   ASSERT_FALSE( sym->isDyn() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( 0, sym->desc() );
-  ASSERT_EQ( 0, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( 0 == sym->desc() );
+  ASSERT_TRUE( 0 == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 
   sym->setBinding(ResolveInfo::Global);
   ASSERT_TRUE( sym->isSymbol() );
@@ -415,10 +400,10 @@
   ASSERT_FALSE( sym->isDyn() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( 0, sym->desc() );
-  ASSERT_EQ( ResolveInfo::Global, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( 0 == sym->desc() );
+  ASSERT_TRUE( ResolveInfo::Global == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 
   sym->setBinding(ResolveInfo::Weak);
   ASSERT_TRUE( sym->isSymbol() );
@@ -430,10 +415,10 @@
   ASSERT_TRUE( sym->isUndef() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( 0, sym->desc() );
-  ASSERT_EQ( ResolveInfo::Weak, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( 0 == sym->desc() );
+  ASSERT_TRUE( ResolveInfo::Weak == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 
   sym->setBinding(ResolveInfo::Local);
   ASSERT_TRUE( sym->isSymbol() );
@@ -445,9 +430,9 @@
   ASSERT_TRUE( sym->isUndef() );
   ASSERT_FALSE( sym->isCommon() );
   ASSERT_FALSE( sym->isIndirect() );
-  ASSERT_EQ( ResolveInfo::NoType, sym->type());
-  ASSERT_EQ( 0, sym->desc() );
-  ASSERT_EQ( ResolveInfo::Local, sym->binding() );
-  ASSERT_EQ( 0, sym->other() );
+  ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+  ASSERT_TRUE( 0 == sym->desc() );
+  ASSERT_TRUE( ResolveInfo::Local == sym->binding() );
+  ASSERT_TRUE( 0 == sym->other() );
 }
 
diff --git a/unittests/StaticResolverTest.h b/unittests/StaticResolverTest.h
index e4ffa50..89157f0 100644
--- a/unittests/StaticResolverTest.h
+++ b/unittests/StaticResolverTest.h
@@ -10,12 +10,13 @@
 #define STATICRESOLVER_TEST_H
 
 #include <gtest.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
 
-namespace mcld
-{
+namespace mcld {
+
 class StaticResolver;
 class ResolveInfoFactory;
+class DiagnosticPrinter;
 
 } // namespace for mcld
 
@@ -44,9 +45,7 @@
 
 protected:
   mcld::StaticResolver* m_pResolver;
-  mcld::ResolveInfoFactory* m_pFactory;
-  mcld::MCLDInfo* m_pLDInfo;
-  mcld::DiagnosticLineInfo* m_pLineInfo;
+  mcld::LinkerConfig* m_pConfig;
   mcld::DiagnosticPrinter* m_pPrinter;
 };
 
diff --git a/unittests/SymbolCategoryTest.cpp b/unittests/SymbolCategoryTest.cpp
index 4233c3e..07f479b 100644
--- a/unittests/SymbolCategoryTest.cpp
+++ b/unittests/SymbolCategoryTest.cpp
@@ -20,14 +20,14 @@
 // Constructor can do set-up work for all test here.
 SymbolCategoryTest::SymbolCategoryTest()
 {
-	// create testee. modify it if need
-	m_pTestee = new SymbolCategory();
+  // create testee. modify it if need
+  m_pTestee = new SymbolCategory();
 }
 
 // Destructor can do clean-up work that doesn't throw exceptions here.
 SymbolCategoryTest::~SymbolCategoryTest()
 {
-	delete m_pTestee;
+  delete m_pTestee;
 }
 
 // SetUp() will be called immediately before each test.
@@ -45,35 +45,29 @@
 //
 
 TEST_F(SymbolCategoryTest, upward_test) {
-  ResolveInfo* a = m_InfoFactory.produce("a");
-  ResolveInfo* b = m_InfoFactory.produce("b");
-  ResolveInfo* c = m_InfoFactory.produce("c");
-  ResolveInfo* d = m_InfoFactory.produce("d");
-  ResolveInfo* e = m_InfoFactory.produce("e");
+  ResolveInfo* a = ResolveInfo::Create("a");
+  ResolveInfo* b = ResolveInfo::Create("b");
+  ResolveInfo* c = ResolveInfo::Create("c");
+  ResolveInfo* d = ResolveInfo::Create("d");
+  ResolveInfo* e = ResolveInfo::Create("e");
   e->setBinding(ResolveInfo::Global);
   d->setBinding(ResolveInfo::Weak);
   c->setDesc(ResolveInfo::Common);
   c->setBinding(ResolveInfo::Global);
   b->setBinding(ResolveInfo::Local);
   a->setType(ResolveInfo::File);
-  
-  LDSymbol aa;
-  LDSymbol bb;
-  LDSymbol cc;
-  LDSymbol dd;
-  LDSymbol ee;
 
-  aa.setResolveInfo(*a);
-  bb.setResolveInfo(*b);
-  cc.setResolveInfo(*c);
-  dd.setResolveInfo(*d);
-  ee.setResolveInfo(*e);
+  LDSymbol* aa = LDSymbol::Create(*a);
+  LDSymbol* bb = LDSymbol::Create(*b);
+  LDSymbol* cc = LDSymbol::Create(*c);
+  LDSymbol* dd = LDSymbol::Create(*d);
+  LDSymbol* ee = LDSymbol::Create(*e);
 
-  m_pTestee->add(ee);
-  m_pTestee->add(dd);
-  m_pTestee->add(cc);
-  m_pTestee->add(bb);
-  m_pTestee->add(aa);
+  m_pTestee->add(*ee);
+  m_pTestee->add(*dd);
+  m_pTestee->add(*cc);
+  m_pTestee->add(*bb);
+  m_pTestee->add(*aa);
 
   SymbolCategory::iterator sym = m_pTestee->begin();
   ASSERT_STREQ("a", (*sym)->name());
@@ -86,9 +80,65 @@
   ++sym;
   ASSERT_STREQ("e", (*sym)->name());
 
-  ASSERT_EQ(2, m_pTestee->numOfLocals());
-  ASSERT_EQ(1, m_pTestee->numOfCommons());
-  ASSERT_EQ(2, m_pTestee->numOfRegulars());
-  ASSERT_EQ(5, m_pTestee->numOfSymbols());
+  ASSERT_TRUE(2 == m_pTestee->numOfLocals());
+  ASSERT_TRUE(1 == m_pTestee->numOfCommons());
+  ASSERT_TRUE(2 == m_pTestee->numOfRegulars());
+  ASSERT_TRUE(5 == m_pTestee->numOfSymbols());
 }
 
+TEST_F(SymbolCategoryTest, change_local_to_tls) {
+  ResolveInfo* a = ResolveInfo::Create("a");
+  ResolveInfo* b = ResolveInfo::Create("b");
+  ResolveInfo* c = ResolveInfo::Create("c");
+  ResolveInfo* d = ResolveInfo::Create("d");
+  ResolveInfo* e = ResolveInfo::Create("e");
+
+  a->setBinding(ResolveInfo::Local);
+  b->setBinding(ResolveInfo::Local);
+  c->setBinding(ResolveInfo::Local);
+  d->setDesc(ResolveInfo::Common);
+  d->setBinding(ResolveInfo::Global);
+  e->setBinding(ResolveInfo::Global);
+
+  LDSymbol* aa = LDSymbol::Create(*a);
+  LDSymbol* bb = LDSymbol::Create(*b);
+  LDSymbol* cc = LDSymbol::Create(*c);
+  LDSymbol* dd = LDSymbol::Create(*d);
+  LDSymbol* ee = LDSymbol::Create(*e);
+
+  a->setSymPtr(aa);
+  b->setSymPtr(bb);
+  c->setSymPtr(cc);
+  d->setSymPtr(dd);
+  e->setSymPtr(ee);
+
+  m_pTestee->add(*ee);
+  m_pTestee->add(*dd);
+  m_pTestee->add(*cc);
+  m_pTestee->add(*bb);
+  m_pTestee->add(*aa);
+
+  SymbolCategory::iterator sym = m_pTestee->begin();
+  ASSERT_STREQ("c", (*sym)->name());
+  ++sym;
+  ASSERT_STREQ("b", (*sym)->name());
+  ++sym;
+  ASSERT_STREQ("a", (*sym)->name());
+  ++sym;
+  ASSERT_STREQ("d", (*sym)->name());
+  ++sym;
+  ASSERT_STREQ("e", (*sym)->name());
+
+  m_pTestee->changeLocalToTLS(*bb);
+
+  sym = m_pTestee->begin();
+  ASSERT_STREQ("c", (*sym)->name());
+  ++sym;
+  ASSERT_STREQ("a", (*sym)->name());
+  ++sym;
+  ASSERT_STREQ("b", (*sym)->name());
+  ++sym;
+  ASSERT_STREQ("d", (*sym)->name());
+  ++sym;
+  ASSERT_STREQ("e", (*sym)->name());
+}
diff --git a/unittests/SymbolCategoryTest.h b/unittests/SymbolCategoryTest.h
index f721368..ff5f1a6 100644
--- a/unittests/SymbolCategoryTest.h
+++ b/unittests/SymbolCategoryTest.h
@@ -8,7 +8,6 @@
 //===----------------------------------------------------------------------===//
 #ifndef MCLD_SYMBOLCATEGORY_TEST_H
 #define MCLD_SYMBOLCATEGORY_TEST_H
-#include <mcld/LD/ResolveInfoFactory.h>
 
 #include <gtest.h>
 
@@ -43,7 +42,6 @@
 
 protected:
   mcld::SymbolCategory* m_pTestee;
-  mcld::ResolveInfoFactory m_InfoFactory;
 };
 
 } // namespace of mcldtest
diff --git a/unittests/TestLinkerTest.cpp b/unittests/TestLinkerTest.cpp
index 272cd89..0b1a141 100644
--- a/unittests/TestLinkerTest.cpp
+++ b/unittests/TestLinkerTest.cpp
@@ -11,6 +11,7 @@
 
 #include <mcld/Support/Path.h>
 #include <mcld/MC/MCLDDirectory.h>
+#include <mcld/MC/InputFactory.h>
 
 using namespace mcld;
 using namespace mcld::test;
@@ -35,13 +36,13 @@
   m_pLinker->initialize("arm-none-linux-gnueabi");
 
   // set up target-dependent constraints of attributes
-  m_pLinker->config()->attrFactory().constraint().enableWholeArchive();
-  m_pLinker->config()->attrFactory().constraint().disableAsNeeded();
-  m_pLinker->config()->attrFactory().constraint().setSharedSystem();
+  m_pLinker->config()->attribute().constraint().enableWholeArchive();
+  m_pLinker->config()->attribute().constraint().disableAsNeeded();
+  m_pLinker->config()->attribute().constraint().setSharedSystem();
 
   // set up the predefined attributes
-  m_pLinker->config()->attrFactory().predefined().setWholeArchive();
-  m_pLinker->config()->attrFactory().predefined().setDynamic();
+  m_pLinker->config()->attribute().predefined().setWholeArchive();
+  m_pLinker->config()->attribute().predefined().setDynamic();
 
   // set up target dependent options
   mcld::sys::fs::Path path = TOPDIR;
diff --git a/unittests/UniqueGCFactoryBaseTest.cpp b/unittests/UniqueGCFactoryBaseTest.cpp
index 32447c2..f8e098a 100644
--- a/unittests/UniqueGCFactoryBaseTest.cpp
+++ b/unittests/UniqueGCFactoryBaseTest.cpp
@@ -8,7 +8,6 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/MC/ContextFactory.h>
 #include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetSelect.h>
 #include <mcld/Support/Path.h>
 #include "UniqueGCFactoryBaseTest.h"
@@ -22,16 +21,13 @@
 {
   InitializeAllDiagnostics();
 
-  m_pLDInfo = new MCLDInfo("arm-none-linux-gnueabi", 10, 10);
-  m_pLineInfo = new DiagnosticLineInfo();
-  mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, NULL);
+  m_pConfig = new LinkerConfig("arm-none-linux-gnueabi");
 }
 
 // Destructor can do clean-up work that doesn't throw exceptions here.
 UniqueGCFactoryBaseTest::~UniqueGCFactoryBaseTest()
 {
-  delete m_pLDInfo;
-  delete m_pLineInfo;
+  delete m_pConfig;
 }
 
 // SetUp() will be called immediately before each test.
@@ -51,7 +47,7 @@
 	ContextFactory *contextFactory = new ContextFactory(10); 
 	contextFactory->produce("/");
 	contextFactory->produce("ab/c");
-	ASSERT_EQ( 2, contextFactory->size());
+	ASSERT_TRUE( 2 == contextFactory->size());
 	delete contextFactory;
 }
 
@@ -59,7 +55,7 @@
 	ContextFactory *contextFactory = new ContextFactory(10); 
 	LDContext* context1 = contextFactory->produce("/");
 	contextFactory->produce("ab/c");
-	ASSERT_EQ( 2, contextFactory->size());
+	ASSERT_TRUE( 2 == contextFactory->size());
 	LDContext* context2 = contextFactory->produce("/");
 	ASSERT_EQ( context1, context2 );
 	delete contextFactory;
@@ -69,7 +65,7 @@
 	ContextFactory *contextFactory = new ContextFactory(10); 
 	LDContext* context1 = contextFactory->produce("abc/def");
 	contextFactory->produce("ab/c");
-	ASSERT_EQ( 2, contextFactory->size());
+	ASSERT_TRUE( 2 == contextFactory->size());
 	LDContext* context2 = contextFactory->produce("ttt/../abc/def");
 	ASSERT_EQ( context1, context2 );
 	delete contextFactory;
@@ -90,7 +86,7 @@
 	
 	ASSERT_EQ(area1, area3);
 	ASSERT_FALSE( memFactory->empty());
-	ASSERT_EQ( 2, memFactory->size());
+	ASSERT_TRUE( 2 == memFactory->size());
 	MemoryAreaFactory::iterator aIter = memFactory->begin();
 	ASSERT_EQ( area1, &(*aIter));
 	++aIter;
diff --git a/unittests/UniqueGCFactoryBaseTest.h b/unittests/UniqueGCFactoryBaseTest.h
index 525c8c4..c2f1c1b 100644
--- a/unittests/UniqueGCFactoryBaseTest.h
+++ b/unittests/UniqueGCFactoryBaseTest.h
@@ -10,9 +10,8 @@
 #define UNIQUE_GCFACTORYBASE_TEST_H
 
 #include <mcld/Support/UniqueGCFactory.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
 #include <mcld/LD/DiagnosticPrinter.h>
-#include <mcld/LD/DiagnosticLineInfo.h>
 #include <gtest.h>
 
 namespace mcldtest
@@ -26,22 +25,20 @@
 class UniqueGCFactoryBaseTest : public ::testing::Test
 {
 public:
-	// Constructor can do set-up work for all test here.
-	UniqueGCFactoryBaseTest();
+  // Constructor can do set-up work for all test here.
+  UniqueGCFactoryBaseTest();
 
-	// Destructor can do clean-up work that doesn't throw exceptions here.
-	virtual ~UniqueGCFactoryBaseTest();
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~UniqueGCFactoryBaseTest();
 
-	// SetUp() will be called immediately before each test.
-	virtual void SetUp();
+  // SetUp() will be called immediately before each test.
+  virtual void SetUp();
 
-	// TearDown() will be called immediately after each test.
-	virtual void TearDown();
+  // TearDown() will be called immediately after each test.
+  virtual void TearDown();
 
 private:
-	mcld::MCLDInfo* m_pLDInfo;
-	mcld::DiagnosticLineInfo* m_pLineInfo;
-	mcld::DiagnosticPrinter* m_pPrinter;
+  mcld::LinkerConfig* m_pConfig;
 };
 
 } // namespace of mcldtest
diff --git a/unittests/read_stage.xml b/unittests/read_stage.xml
deleted file mode 100644
index cc061d6..0000000
--- a/unittests/read_stage.xml
+++ /dev/null
@@ -1,273 +0,0 @@
- <input name="/Users/lubatang/Project/MCLinker/build/../src-tree/test/libs/ARM/Android/android-14/crtbegin_so.o">
-  <section name=""/>
-  <section name=".text"/>
-  <section name=".rel.text"/>
-  <section name=".data"/>
-  <section name=".bss"/>
-  <section name=".init_array"/>
-  <section name=".fini_array"/>
-  <section name=".rel.fini_array"/>
-  <section name=".ARM.attributes"/>
-  <section name=".shstrtab"/>
-  <section name=".symtab"/>
-  <section name=".strtab"/>
- </input>
- <input name="/Users/lubatang/Project/MCLinker/build/../src-tree/test/Android/Plasma/ARM/plasma.o">
-  <section name=""/>
-  <section name=".text"/>
-  <section name=".rel.text"/>
-  <section name=".text.now_ms"/>
-  <section name=".rel.text.now_ms"/>
-  <section name=".text.init_angles"/>
-  <section name=".rel.text.init_angles"/>
-  <section name=".text.angle_sin"/>
-  <section name=".rel.text.angle_sin"/>
-  <section name=".text.fixed_sin"/>
-  <section name=".rel.text.fixed_sin"/>
-  <section name=".text.make565"/>
-  <section name=".text.init_palette"/>
-  <section name=".rel.text.init_palette"/>
-  <section name=".text.palette_from_fixed"/>
-  <section name=".rel.text.palette_from_fixed"/>
-  <section name=".text.init_tables"/>
-  <section name=".rel.text.init_tables"/>
-  <section name=".text.fill_plasma"/>
-  <section name=".rel.text.fill_plasma"/>
-  <section name=".text.stats_init"/>
-  <section name=".rel.text.stats_init"/>
-  <section name=".text.stats_startFrame"/>
-  <section name=".rel.text.stats_startFrame"/>
-  <section name=".text.stats_endFrame"/>
-  <section name=".rel.text.stats_endFrame"/>
-  <section name=".text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
-  <section name=".rel.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
-  <section name=".rodata"/>
-  <section name=".ARM.extab.text.now_ms"/>
-  <section name=".ARM.exidx.text.now_ms"/>
-  <section name=".rel.ARM.exidx.text.now_ms"/>
-  <section name=".ARM.extab.text.init_angles"/>
-  <section name=".ARM.exidx.text.init_angles"/>
-  <section name=".rel.ARM.exidx.text.init_angles"/>
-  <section name=".ARM.extab.text.angle_sin"/>
-  <section name=".ARM.exidx.text.angle_sin"/>
-  <section name=".rel.ARM.exidx.text.angle_sin"/>
-  <section name=".ARM.extab.text.fixed_sin"/>
-  <section name=".ARM.exidx.text.fixed_sin"/>
-  <section name=".rel.ARM.exidx.text.fixed_sin"/>
-  <section name=".ARM.extab.text.make565"/>
-  <section name=".ARM.exidx.text.make565"/>
-  <section name=".rel.ARM.exidx.text.make565"/>
-  <section name=".ARM.extab.text.init_palette"/>
-  <section name=".ARM.exidx.text.init_palette"/>
-  <section name=".rel.ARM.exidx.text.init_palette"/>
-  <section name=".ARM.extab.text.palette_from_fixed"/>
-  <section name=".ARM.exidx.text.palette_from_fixed"/>
-  <section name=".rel.ARM.exidx.text.palette_from_fixed"/>
-  <section name=".ARM.extab.text.init_tables"/>
-  <section name=".ARM.exidx.text.init_tables"/>
-  <section name=".rel.ARM.exidx.text.init_tables"/>
-  <section name=".ARM.extab.text.fill_plasma"/>
-  <section name=".ARM.exidx.text.fill_plasma"/>
-  <section name=".rel.ARM.exidx.text.fill_plasma"/>
-  <section name=".ARM.extab.text.stats_init"/>
-  <section name=".ARM.exidx.text.stats_init"/>
-  <section name=".rel.ARM.exidx.text.stats_init"/>
-  <section name=".ARM.extab.text.stats_startFrame"/>
-  <section name=".ARM.exidx.text.stats_startFrame"/>
-  <section name=".rel.ARM.exidx.text.stats_startFrame"/>
-  <section name=".ARM.extab.text.stats_endFrame"/>
-  <section name=".ARM.exidx.text.stats_endFrame"/>
-  <section name=".rel.ARM.exidx.text.stats_endFrame"/>
-  <section name=".ARM.extab.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
-  <section name=".ARM.exidx.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
-  <section name=".rel.ARM.exidx.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
-  <section name=".ARM.extab"/>
-  <section name=".ARM.exidx"/>
-  <section name=".rel.ARM.exidx"/>
-  <section name=".data"/>
-  <section name=".bss"/>
-  <section name=".comment"/>
-  <section name=".debug_aranges"/>
-  <section name=".rel.debug_aranges"/>
-  <section name=".debug_pubnames"/>
-  <section name=".rel.debug_pubnames"/>
-  <section name=".debug_info"/>
-  <section name=".rel.debug_info"/>
-  <section name=".debug_abbrev"/>
-  <section name=".debug_line"/>
-  <section name=".rel.debug_line"/>
-  <section name=".debug_frame"/>
-  <section name=".rel.debug_frame"/>
-  <section name=".debug_str"/>
-  <section name=".debug_loc"/>
-  <section name=".rel.debug_loc"/>
-  <section name=".debug_ranges"/>
-  <section name=".rel.debug_ranges"/>
-  <section name=".note.GNU-stack"/>
-  <section name=".ARM.attributes"/>
-  <section name=".shstrtab"/>
-  <section name=".symtab"/>
-  <section name=".strtab"/>
- </input>
- <input name="libm.so">
-  <section name=""/>
-  <section name=".hash"/>
-  <section name=".dynsym"/>
-  <section name=".dynstr"/>
-  <section name=".text"/>
-  <section name=".dynamic"/>
-  <section name=".got"/>
-  <section name=".bss"/>
-  <section name=".ARM.attributes"/>
-  <section name=".comment"/>
-  <section name=".shstrtab"/>
-  <section name=".symtab"/>
-  <section name=".strtab"/>
- </input>
- <input name="liblog.so">
-  <section name=""/>
-  <section name=".hash"/>
-  <section name=".dynsym"/>
-  <section name=".dynstr"/>
-  <section name=".text"/>
-  <section name=".dynamic"/>
-  <section name=".got"/>
-  <section name=".ARM.attributes"/>
-  <section name=".comment"/>
-  <section name=".shstrtab"/>
-  <section name=".symtab"/>
-  <section name=".strtab"/>
- </input>
- <input name="libjnigraphics.so">
-  <section name=""/>
-  <section name=".hash"/>
-  <section name=".dynsym"/>
-  <section name=".dynstr"/>
-  <section name=".text"/>
-  <section name=".dynamic"/>
-  <section name=".got"/>
-  <section name=".ARM.attributes"/>
-  <section name=".comment"/>
-  <section name=".shstrtab"/>
-  <section name=".symtab"/>
-  <section name=".strtab"/>
- </input>
- <input name="libc.so">
-  <section name=""/>
-  <section name=".hash"/>
-  <section name=".dynsym"/>
-  <section name=".dynstr"/>
-  <section name=".text"/>
-  <section name=".dynamic"/>
-  <section name=".got"/>
-  <section name=".bss"/>
-  <section name=".ARM.attributes"/>
-  <section name=".comment"/>
-  <section name=".shstrtab"/>
-  <section name=".symtab"/>
-  <section name=".strtab"/>
- </input>
- <input name="/Users/lubatang/Project/MCLinker/build/../src-tree/test/libs/ARM/Android/android-14/crtend_so.o">
-  <section name=""/>
-  <section name=".text"/>
-  <section name=".data"/>
-  <section name=".bss"/>
-  <section name=".init_array"/>
-  <section name=".fini_array"/>
-  <section name=".ARM.attributes"/>
-  <section name=".shstrtab"/>
-  <section name=".symtab"/>
-  <section name=".strtab"/>
- </input>
- <output name="">
-  <section name=".text"/>
-  <section name=""/>
-  <section name=".rodata"/>
-  <section name=".bss"/>
-  <section name=".comment"/>
-  <section name=".data"/>
-  <section name=".debug"/>
-  <section name=".init"/>
-  <section name=".init_array"/>
-  <section name=".fini"/>
-  <section name=".fini_array"/>
-  <section name=".line"/>
-  <section name=".preinit_array"/>
-  <section name=".shstrtab"/>
-  <section name=".symtab"/>
-  <section name=".strtab"/>
-  <section name=".tbss"/>
-  <section name=".tdata"/>
-  <section name=".ctor"/>
-  <section name=".data.rel.ro"/>
-  <section name=".dtors"/>
-  <section name=".eh_frame"/>
-  <section name=".gcc_except_table"/>
-  <section name=".gnu.version"/>
-  <section name=".gnu.version_d"/>
-  <section name=".gnu.version_r"/>
-  <section name=".jcr"/>
-  <section name=".stab"/>
-  <section name=".stabstr"/>
-  <section name=".dynsym"/>
-  <section name=".dynstr"/>
-  <section name=".interp"/>
-  <section name=".hash"/>
-  <section name=".dynamic"/>
-  <section name=".rela.dyn"/>
-  <section name=".rela.plt"/>
-  <section name=".rel.dyn"/>
-  <section name=".rel.plt"/>
-  <section name=".got"/>
-  <section name=".plt"/>
-  <section name=".got.plt"/>
-  <section name=".eh_frame_hdr"/>
-  <section name=".ARM.exidx"/>
-  <section name=".ARM.extab"/>
-  <section name=".ARM.attributes"/>
-  <section name=".rel.text"/>
-  <section name=".rel.fini_array"/>
-  <section name=".rel.text.now_ms"/>
-  <section name=".rel.text.init_angles"/>
-  <section name=".rel.text.angle_sin"/>
-  <section name=".rel.text.fixed_sin"/>
-  <section name=".rel.text.init_palette"/>
-  <section name=".rel.text.palette_from_fixed"/>
-  <section name=".rel.text.init_tables"/>
-  <section name=".rel.text.fill_plasma"/>
-  <section name=".rel.text.stats_init"/>
-  <section name=".rel.text.stats_startFrame"/>
-  <section name=".rel.text.stats_endFrame"/>
-  <section name=".rel.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
-  <section name=".rel.ARM.exidx.text.now_ms"/>
-  <section name=".rel.ARM.exidx.text.init_angles"/>
-  <section name=".rel.ARM.exidx.text.angle_sin"/>
-  <section name=".rel.ARM.exidx.text.fixed_sin"/>
-  <section name=".rel.ARM.exidx.text.make565"/>
-  <section name=".rel.ARM.exidx.text.init_palette"/>
-  <section name=".rel.ARM.exidx.text.palette_from_fixed"/>
-  <section name=".rel.ARM.exidx.text.init_tables"/>
-  <section name=".rel.ARM.exidx.text.fill_plasma"/>
-  <section name=".rel.ARM.exidx.text.stats_init"/>
-  <section name=".rel.ARM.exidx.text.stats_startFrame"/>
-  <section name=".rel.ARM.exidx.text.stats_endFrame"/>
-  <section name=".rel.ARM.exidx.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
-  <section name=".rel.ARM.exidx"/>
-  <section name=".debug_aranges"/>
-  <section name=".rel.debug_aranges"/>
-  <section name=".debug_pubnames"/>
-  <section name=".rel.debug_pubnames"/>
-  <section name=".debug_info"/>
-  <section name=".rel.debug_info"/>
-  <section name=".debug_abbrev"/>
-  <section name=".debug_line"/>
-  <section name=".rel.debug_line"/>
-  <section name=".debug_frame"/>
-  <section name=".rel.debug_frame"/>
-  <section name=".debug_str"/>
-  <section name=".debug_loc"/>
-  <section name=".rel.debug_loc"/>
-  <section name=".debug_ranges"/>
-  <section name=".rel.debug_ranges"/>
-  <section name=".note.GNU-stack"/>
- </output>
diff --git a/unittests/test2.txt b/unittests/test2.txt
index f1e9c6a..1672643 100644
--- a/unittests/test2.txt
+++ b/unittests/test2.txt
Binary files differ