MCLinker upstream commit e764452.

Change-Id: I5c9ec467ec96a0143e1e67c59365f3b6303e7348
diff --git a/include/mcld/ADT/BinTree.h b/include/mcld/ADT/BinTree.h
index 5c1dc0a..da30a89 100644
--- a/include/mcld/ADT/BinTree.h
+++ b/include/mcld/ADT/BinTree.h
@@ -479,3 +479,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/Flags.h b/include/mcld/ADT/Flags.h
new file mode 100644
index 0000000..0091cea
--- /dev/null
+++ b/include/mcld/ADT/Flags.h
@@ -0,0 +1,106 @@
+//===- Flags.h ------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_FLAGS_H
+#define MCLD_FLAGS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld
+{
+
+template<typename Enum>
+class Flags
+{
+public:
+  typedef Enum enum_type;
+
+public:
+  Flags(const Flags& pOther)
+  : m_Data(pOther.m_Data) {}
+
+  Flags(Enum pFlag)
+  : m_Data(pFlag) {}
+
+  Flags(int pFlag = 0x0)
+  : m_Data(pFlag) {}
+
+  operator int () const
+  { return m_Data; }
+
+  bool operator! () const
+  { return (m_Data == 0x0); }
+
+  Flags operator& (int pMask ) const
+  { return Flags(m_Data & pMask); }
+
+  Flags operator& (unsigned int pMask ) const
+  { return Flags(m_Data & pMask); }
+
+  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;
+  }
+
+  Flags& operator=(Flags pOther) {
+    m_Data = pOther.m_Data;
+    return *this;
+  }
+
+  Flags operator^ (Flags pOther) const
+  { return Flags(m_Data^pOther.m_Data); }
+
+  Flags operator^ (Enum pOther) const
+  { return Flags(m_Data^pOther); }
+
+  Flags& operator^= (Flags pOther) {
+    m_Data ^= pOther.m_Data;
+    return *this;
+  } 
+
+  Flags& operator^= (Enum pOther) {
+    m_Data ^= pOther;
+    return *this;
+  }
+
+  Flags operator| (Flags pOther) const
+  { return Flags(m_Data | pOther.m_Data); }
+
+  Flags operator| (Enum pOther ) const
+  { return Flags(m_Data | pOther); }
+
+  Flags& operator|= (Flags pOther) {
+    m_Data |= pOther.m_Data;
+    return *this;
+  }
+
+  Flags& operator|= (Enum pOther) {
+    m_Data |= pOther;
+    return *this;
+  }
+
+  Flags operator~ () const
+  { return Flags(~m_Data); }
+
+private:
+  int m_Data;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/HashBase.h b/include/mcld/ADT/HashBase.h
index 36d825b..76410ab 100644
--- a/include/mcld/ADT/HashBase.h
+++ b/include/mcld/ADT/HashBase.h
@@ -136,3 +136,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/HashBase.tcc b/include/mcld/ADT/HashBase.tcc
index 35b40e3..62d92b1 100644
--- a/include/mcld/ADT/HashBase.tcc
+++ b/include/mcld/ADT/HashBase.tcc
@@ -247,3 +247,4 @@
   m_NumOfBuckets = pNewSize;
   m_NumOfTombstones = 0;
 }
+
diff --git a/include/mcld/ADT/HashEntry.h b/include/mcld/ADT/HashEntry.h
index bc15ecb..c034783 100644
--- a/include/mcld/ADT/HashEntry.h
+++ b/include/mcld/ADT/HashEntry.h
@@ -92,3 +92,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/HashEntry.tcc b/include/mcld/ADT/HashEntry.tcc
index f397f23..fdd886b 100644
--- a/include/mcld/ADT/HashEntry.tcc
+++ b/include/mcld/ADT/HashEntry.tcc
@@ -50,3 +50,4 @@
 {
   return new HashEntryTy(pKey);
 }
+
diff --git a/include/mcld/ADT/HashIterator.h b/include/mcld/ADT/HashIterator.h
index 055d91c..e25df77 100644
--- a/include/mcld/ADT/HashIterator.h
+++ b/include/mcld/ADT/HashIterator.h
@@ -322,3 +322,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/HashTable.h b/include/mcld/ADT/HashTable.h
index 16d87f5..dfc2f5a 100644
--- a/include/mcld/ADT/HashTable.h
+++ b/include/mcld/ADT/HashTable.h
@@ -64,7 +64,7 @@
   // -----  constructor  ----- //
   explicit HashTable(size_type pSize=3);
   ~HashTable();
-
+  
   EntryFactoryTy& getEntryFactory()
   { return m_EntryFactory; }
 
@@ -89,7 +89,7 @@
   const_iterator find(const key_type& pKey) const;
 
   size_type count(const key_type& pKey) const;
-
+  
   // -----  hash policy  ----- //
   float load_factor() const;
 
@@ -123,3 +123,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/HashTable.tcc b/include/mcld/ADT/HashTable.tcc
index 885d737..7439982 100644
--- a/include/mcld/ADT/HashTable.tcc
+++ b/include/mcld/ADT/HashTable.tcc
@@ -183,7 +183,7 @@
 HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::begin()
 {
   if (BaseTy::empty())
-    return iterator(this, 0);
+    return end();
   unsigned int index = 0;
   while (bucket_type::getTombstone() == BaseTy::m_Buckets[index].Entry ||
          bucket_type::getEmptyBucket() == BaseTy::m_Buckets[index].Entry) {
@@ -208,7 +208,7 @@
 HashTable<HashEntryTy, HashFunctionTy, EntryFactoryTy>::begin() const
 {
   if (BaseTy::empty())
-    return const_iterator(this, 0);
+    return end();
   unsigned int index = 0;
   while (bucket_type::getTombstone() == BaseTy::m_Buckets[index].Entry ||
          bucket_type::getEmptyBucket() == BaseTy::m_Buckets[index].Entry) {
@@ -265,3 +265,4 @@
 {
   return const_chain_iterator();
 }
+
diff --git a/include/mcld/ADT/SizeTraits.h b/include/mcld/ADT/SizeTraits.h
index 7e67db9..666d8c0 100644
--- a/include/mcld/ADT/SizeTraits.h
+++ b/include/mcld/ADT/SizeTraits.h
@@ -18,11 +18,12 @@
 {
 
 template<size_t SIZE>
-struct SizeTraits;
+class SizeTraits;
 
 template<>
 class SizeTraits<32>
 {
+public:
   typedef uint32_t Address;
   typedef uint32_t Offset;
   typedef uint32_t Word;
@@ -32,6 +33,7 @@
 template<>
 class SizeTraits<64>
 {
+public:
   typedef uint64_t Address;
   typedef uint64_t Offset;
   typedef uint64_t Word;
@@ -96,6 +98,18 @@
            ((pData & 0x00000000000000FFULL) << 56));
 }
 
+template <size_t SizeOfStr, typename FieldType>
+class StringSizerHelper
+{
+private:
+  char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
+public:
+  enum { Size = SizeOfStr };
+};
+
+#define STR_SIZE(str, fieldTy) StringSizerHelper<sizeof(str)-1, fieldTy>::Size
+
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/StringEntry.h b/include/mcld/ADT/StringEntry.h
new file mode 100644
index 0000000..09c8dfe
--- /dev/null
+++ b/include/mcld/ADT/StringEntry.h
@@ -0,0 +1,152 @@
+//===- StringEntry.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_STRING_ENTRY_H
+#define MCLD_STRING_ENTRY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+
+namespace mcld
+{
+template<typename DataType>
+class StringEntryFactory;
+
+/** \class StringEntry
+ *  \brief StringEntry is a pair of strings which is designed for high locality.
+ */
+template<typename DataType>
+class StringEntry
+{
+public:
+  typedef llvm::StringRef   key_type;
+  typedef DataType value_type;
+
+public:
+  key_type key()
+  { return key_type(m_Key, m_KeyLen); }
+
+  const key_type key() const
+  { return key_type(m_Key, m_KeyLen); }
+
+  value_type& value()
+  { return m_Value; }
+
+  const value_type& value() const
+  { return m_Value; }
+
+  size_t getKeyLength() const
+  { return m_KeyLen; }
+
+  size_t getValueLength() const
+  { return m_Value.size(); }
+
+  void setValue(const DataType& pVal)
+  { m_Value = pVal; }
+
+  bool compare(const llvm::StringRef& pX)
+  { return (0 == key().compare(pX)); }
+
+  bool compare(const llvm::StringRef& pX) const
+  { return (0 == key().compare(pX)); }
+
+private:
+  StringEntry();
+  StringEntry(const key_type& pKey);
+  StringEntry(const StringEntry& pCopy);
+  ~StringEntry();
+
+private:
+  DataType m_Value;
+  uint16_t m_KeyLen;
+  char m_Key[0];
+
+  friend class StringEntryFactory<DataType>;
+};
+
+
+template<>
+class StringEntry<llvm::StringRef>
+{
+public:
+  typedef llvm::StringRef key_type;
+  typedef llvm::StringRef value_type;
+
+public:
+  key_type key()
+  { return key_type(m_Key, m_KeyLen); }
+
+  const key_type key() const
+  { return key_type(m_Key, m_KeyLen); }
+
+  value_type& value()
+  { return m_Value; }
+
+  const value_type& value() const
+  { return m_Value; }
+
+  size_t getKeyLength() const
+  { return m_KeyLen; }
+
+  size_t getValueLength() const
+  { return m_Value.size(); }
+
+  void setValue(const std::string& pVal)
+  { setValue(pVal.c_str()); }
+
+  void setValue(const char* pVal);
+
+  void setValue(llvm::StringRef& pVal);
+
+  bool compare(const llvm::StringRef& pX)
+  { return (0 == key().compare(pX)); }
+
+  bool compare(const llvm::StringRef& pX) const
+  { return (0 == key().compare(pX)); }
+
+private:
+  StringEntry();
+  StringEntry(const key_type& pKey);
+  StringEntry(const StringEntry& pCopy);
+  ~StringEntry();
+
+private:
+  llvm::StringRef m_Value;
+  uint16_t m_KeyLen;
+  char m_Key[0];
+
+  friend class StringEntryFactory<llvm::StringRef>;
+};
+
+template<typename DataType>
+class StringEntryFactory
+{
+public:
+  typedef StringEntry<DataType>             entry_type;
+  typedef typename StringEntry<DataType>::key_type   key_type;
+  typedef typename StringEntry<DataType>::value_type value_type;
+
+public:
+  StringEntryFactory();
+  ~StringEntryFactory();
+
+  StringEntry<DataType>* produce(const key_type& pKey);
+  void destroy(StringEntry<DataType>* pEntry);
+};
+
+#include "StringEntry.tcc"
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/StringEntry.tcc b/include/mcld/ADT/StringEntry.tcc
new file mode 100644
index 0000000..fa86f24
--- /dev/null
+++ b/include/mcld/ADT/StringEntry.tcc
@@ -0,0 +1,71 @@
+//===- StringEntry.tcc -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// StringEntry
+template<typename DataType>
+StringEntry<DataType>::StringEntry()
+  : m_KeyLen(0) {
+}
+
+template<typename DataType>
+StringEntry<DataType>::StringEntry(const StringEntry::key_type& pKey)
+  : m_KeyLen(pKey.size()) {
+}
+
+template<typename DataType>
+StringEntry<DataType>::StringEntry(const StringEntry<DataType>& pCopy)
+  : m_KeyLen(pCopy.m_KeyLen), m_Value(pCopy.m_Value) {
+  assert("Copy constructor of StringEntry should not be called!");
+}
+
+template<typename DataType>
+StringEntry<DataType>::~StringEntry()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// StringEntryFactory
+template<typename DataType>
+StringEntryFactory<DataType>::StringEntryFactory()
+{
+}
+
+template<typename DataType>
+StringEntryFactory<DataType>::~StringEntryFactory()
+{
+}
+
+template<typename DataType>
+StringEntry<DataType>*
+StringEntryFactory<DataType>::produce(const typename StringEntryFactory<DataType>::key_type& pKey)
+{
+  StringEntry<DataType>* result = static_cast<StringEntry<DataType>*>(
+                           malloc(sizeof(StringEntry<DataType>) + pKey.size() + 1));
+
+  if (NULL == result)
+    return NULL;
+
+  size_t len = pKey.size();
+  new (result) StringEntry<DataType>();
+  std::memcpy(result->m_Key, pKey.data(), len);
+  result->m_Key[len] = '\0';
+  result->m_KeyLen = len;
+  return result;
+}
+
+template<typename DataType>
+void StringEntryFactory<DataType>::destroy(StringEntry<DataType>* pEntry)
+{
+  if (NULL != pEntry) {
+    pEntry->~StringEntry<DataType>();
+    free(pEntry);
+  }
+}
+
diff --git a/include/mcld/ADT/StringHash.h b/include/mcld/ADT/StringHash.h
index cf6276d..f100a49 100644
--- a/include/mcld/ADT/StringHash.h
+++ b/include/mcld/ADT/StringHash.h
@@ -78,7 +78,7 @@
 
     for(unsigned int i = 0; i < pKey.size(); ++i) {
        hash_val ^= ((hash_val << 5) + pKey[i] + (hash_val >> 2));
-    }
+    } 
     return hash_val;
   }
 };
@@ -123,7 +123,7 @@
     for (unsigned int i = 0; i < pKey.size(); ++i) {
       hash_val = (hash_val << 4) + pKey[i];
       if((x = hash_val & 0xF0000000L) != 0)
-        hash_val ^= (x >> 24);
+        hash_val ^= (x >> 24); 
       hash_val &= ~x;
     }
     return hash_val;
@@ -140,7 +140,7 @@
   {
     const size_t seed = 131;
     size_t hash_val = 0;
-
+      
     for(size_t i = 0; i < pKey.size(); ++i)
       hash_val = (hash_val * seed) + pKey[i];
     return hash_val;
@@ -248,13 +248,13 @@
   size_t operator()(const llvm::StringRef& pKey) const
   {
     unsigned int hash_val = 0xAAAAAAAA;
-
-    for(size_t i = 0; i < pKey.size(); ++i) {
+   
+    for(size_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))));
     }
-
+   
     return hash_val;
   }
 };
@@ -286,3 +286,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/TreeAllocator.h b/include/mcld/ADT/TreeAllocator.h
index fc95bf7..899896c 100644
--- a/include/mcld/ADT/TreeAllocator.h
+++ b/include/mcld/ADT/TreeAllocator.h
@@ -27,7 +27,7 @@
  *  NodeFactory provides delegation of memory. Sometimes, we have to merge two
  *  NodeFactories, and NodeFactory::delegate() can move the memory from one
  *  NodeFactories to another.
- *
+ *  
  *  @see LinearAllocator
  */
 template<typename DataType>
@@ -95,3 +95,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/TreeBase.h b/include/mcld/ADT/TreeBase.h
index e231148..4df8d0d 100644
--- a/include/mcld/ADT/TreeBase.h
+++ b/include/mcld/ADT/TreeBase.h
@@ -126,3 +126,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/TypeTraits.h b/include/mcld/ADT/TypeTraits.h
index c24c4ae..90b2224 100644
--- a/include/mcld/ADT/TypeTraits.h
+++ b/include/mcld/ADT/TypeTraits.h
@@ -68,3 +68,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/ADT/Uncopyable.h b/include/mcld/ADT/Uncopyable.h
index d98c939..7ddfbe3 100644
--- a/include/mcld/ADT/Uncopyable.h
+++ b/include/mcld/ADT/Uncopyable.h
@@ -33,3 +33,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/CodeGen/SectLinker.h b/include/mcld/CodeGen/SectLinker.h
index cbc7214..b31b968 100644
--- a/include/mcld/CodeGen/SectLinker.h
+++ b/include/mcld/CodeGen/SectLinker.h
@@ -11,9 +11,8 @@
 //This class primarily handles common functionality used by all linkers.
 //
 //===----------------------------------------------------------------------===//
-
-#ifndef SECTION_LINKER_H
-#define SECTION_LINKER_H
+#ifndef MCLD_SECTION_LINKER_H
+#define MCLD_SECTION_LINKER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -23,84 +22,83 @@
 
 namespace llvm
 {
-  class Module;
-  class MachineFunction;
+class Module;
+class MachineFunction;
 } // namespace of llvm
 
 namespace mcld
 {
-  class MCLDFile;
-  class MCLDDriver;
-  class TargetLDBackend;
-  class AttributeFactory;
-  class SectLinkerOption;
+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 MCSectionDatas 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);
+/** \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 MCSectionDatas 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();
+public:
+  virtual ~SectLinker();
 
-    /// addTargetOptions - target SectLinker can hook this function to add
-    /// target-specific inputs
-    virtual void addTargetOptions(llvm::Module &pM,
-                                  SectLinkerOption &pOption)
-    { }
+  /// 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);
 
-    /// 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);
 
-    /// 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);
 
-    /// runOnMachineFunction
-    /// redirect to AsmPrinter
-    virtual bool runOnMachineFunction(llvm::MachineFunction& pMFn);
+protected:
+  void initializeInputTree(const PositionDependentOptions &pOptions) const;
 
-  protected:
-    void initializeInputTree(const PositionDependentOptions &pOptions) const;
+  void initializeInputOutput(MCLDInfo& pLDInfo);
 
-    AttributeFactory* attrFactory()
-    { return m_pAttrFactory; }
+  MemoryAreaFactory* memAreaFactory()
+  { return m_pMemAreaFactory; }
 
-  private:
-    SectLinkerOption *m_pOption;
+private:
+  SectLinkerOption *m_pOption;
 
-  protected:
-    TargetLDBackend *m_pLDBackend;
-    MCLDDriver *m_pLDDriver;
-    AttributeFactory *m_pAttrFactory;
+protected:
+  TargetLDBackend *m_pLDBackend;
+  MCLDDriver *m_pLDDriver;
+  MemoryAreaFactory *m_pMemAreaFactory;
 
-  private:
-    static char m_ID;
-  };
+private:
+  static char m_ID;
+};
 
 } // namespace of MC Linker
 
 #endif
+
diff --git a/include/mcld/CodeGen/SectLinkerOption.h b/include/mcld/CodeGen/SectLinkerOption.h
index b3e3327..78c8f53 100644
--- a/include/mcld/CodeGen/SectLinkerOption.h
+++ b/include/mcld/CodeGen/SectLinkerOption.h
@@ -12,8 +12,8 @@
 #include <gtest.h>
 #endif
 
-#include "mcld/MC/MCLDInfo.h"
-#include "mcld/Support/PositionDependentOption.h"
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/Support/PositionDependentOption.h>
 
 #include <string>
 
diff --git a/include/mcld/Config/Config.h.in b/include/mcld/Config/Config.h.in
index 6d428c0..c0e7e0a 100644
--- a/include/mcld/Config/Config.h.in
+++ b/include/mcld/Config/Config.h.in
@@ -9,13 +9,8 @@
 #ifndef MCLD_CONFIG_H
 #define MCLD_CONFIG_H
 
-namespace mcld {
-namespace internal {
-
-static const char* version="@MCLD_VERSION@";
-
-} // namespace of internal
-} // namespace of mcld
+#define @MCLD_ON_PLATFORM@ 1
+#define MCLD_VERSION "@MCLD_VERSION@"
 
 #endif
 
diff --git a/include/mcld/LD/ArchiveReader.h b/include/mcld/LD/ArchiveReader.h
index 14a27e2..7d0aa58 100644
--- a/include/mcld/LD/ArchiveReader.h
+++ b/include/mcld/LD/ArchiveReader.h
@@ -23,9 +23,26 @@
  *  \brief ArchiveReader provides an common interface for all archive readers.
  *
  *  ArchiveReader also reads the target-independent parts of an archive file.
+ *  There are some property on all the archive formats.
+ *  1. All archive elements star on an even boundary, new line padded;
+ *  2. All archive headers are char *;
+ *  3. All archive headers are the same size.
  */
+
 class ArchiveReader : public LDReader
 {
+protected:
+  struct ArchiveMemberHeader
+  {
+    char name[16];
+    char date[12];
+    char uid[6];
+    char gid[6];
+    char mode[8];
+    char size[10];
+    char finalMagic[2];
+  };
+
 public:
   ArchiveReader();
   virtual ~ArchiveReader();
@@ -36,3 +53,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/BSDArchiveReader.h b/include/mcld/LD/BSDArchiveReader.h
index 26add69..a275621 100644
--- a/include/mcld/LD/BSDArchiveReader.h
+++ b/include/mcld/LD/BSDArchiveReader.h
@@ -36,3 +36,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/BranchIsland.h b/include/mcld/LD/BranchIsland.h
index 9f13692..8e5cf9c 100644
--- a/include/mcld/LD/BranchIsland.h
+++ b/include/mcld/LD/BranchIsland.h
@@ -27,3 +27,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/CIE.h b/include/mcld/LD/CIE.h
new file mode 100644
index 0000000..15e1d69
--- /dev/null
+++ b/include/mcld/LD/CIE.h
@@ -0,0 +1,44 @@
+//===- 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/MC/MCRegionFragment.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 MCRegionFragment
+{
+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/DWARFLineInfo.h b/include/mcld/LD/DWARFLineInfo.h
new file mode 100644
index 0000000..004d597
--- /dev/null
+++ b/include/mcld/LD/DWARFLineInfo.h
@@ -0,0 +1,31 @@
+//===- DWARFLineInfo.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_DWARF_LINE_INFO_H
+#define MCLD_DWARF_LINE_INFO_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/LD/DiagnosticLineInfo.h>
+
+namespace mcld
+{
+
+/** \class DWARFLineInfo
+ *  \brief DWARFLineInfo provides the conversion from address to line of code
+ *  by DWARF format.
+ */
+class DWARFLineInfo : public DiagnosticLineInfo
+{
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/DiagCommonKinds.inc b/include/mcld/LD/DiagCommonKinds.inc
new file mode 100644
index 0000000..25cbb8f
--- /dev/null
+++ b/include/mcld/LD/DiagCommonKinds.inc
@@ -0,0 +1,41 @@
+DIAG(err_cannot_open_input, DiagnosticEngine::Error, "can not open input file `%0': %1", "can not open input file `%0' : %1")
+DIAG(err_cannot_open_output_file, DiagnosticEngine::Fatal, "cannot open output file `%0': %1", "cannot open output file `%0': %1")
+DIAG(warn_cannot_open_search_dir, DiagnosticEngine::Warning, "can not open search directory `-L%0'", "can not open search directory `-L%0'")
+DIAG(err_no_inputs, DiagnosticEngine::Error, "no inputs", "no inputs")
+DIAG(err_empty_input, DiagnosticEngine::Error, "Empty input file `%0' : %1", "Empty input file `%0' : %1")
+DIAG(err_unrecognized_input_file, DiagnosticEngine::Fatal, "cannot recognize the format of file `%0'.\n  object format or given target machine (%1) is wrong.","cannot recognize the format of file `%0'.\n  object format or given target machine (%1) is wrong.") 
+DIAG(err_cannot_find_namespec, DiagnosticEngine::Fatal, "cannot recognize namespec -l%0", "cannot recognize namespec -l%0")
+DIAG(err_cannot_identify_option, DiagnosticEngine::Fatal, "unknown command line argument `%0' at %1", "unknown command line argument `%0' at %1")
+DIAG(err_mixed_shared_static_objects, DiagnosticEngine::Error, "cannot link shared objects with -static option.\nShared object `%0': %1", "cannot link shared objects with -static option.\nShared object `%0': %1")
+DIAG(unrecognized_output_file, DiagnosticEngine::Unreachable, "unsupported output file format: `%0'", "unsupported output file format: `%0'")
+DIAG(unrecognized_output_sectoin, DiagnosticEngine::Unreachable, "Unable to emit section `%0'\nPlease report to `%1'", "Unable to emit section `%0'\nPlease report to `%1'")
+DIAG(duplicated_wrap, DiagnosticEngine::Warning, "wrapped symbol `%0' had been claimed", "wrapped symbol `%0' had been claimed")
+DIAG(rewrap, DiagnosticEngine::Warning, "There are duplicated --wrap `%0' on the command line\nsymbol `%1' had been claimed", "There are duplicated --wrap `%0' on the command line]\nsymbol `%1' had been claimed.")
+DIAG(err_cannot_read_symbol, DiagnosticEngine::Fatal, "can not read symbol[%0] in file %1", "can not read symbol[%0] in file %1")
+DIAG(err_cannot_read_section, DiagnosticEngine::Fatal, "can not read section `%0'.", "can not read section `%0'.")
+DIAG(err_cannot_read_target_section, DiagnosticEngine::Fatal, "can not read target-dependent section `%0'.", "can not read target-dependent section `%0'.")
+DIAG(err_cannot_read_relocated_section, DiagnosticEngine::Fatal, "can not read the section being relocated in file %0.\ninvalid sh_info: %1\nrelocation section: %2", "can not read the section being relocated in file %0.\ninvalid sh_info: %1\nrelocation section: %2")
+DIAG(err_unsupported_section, DiagnosticEngine::Fatal, "unsupported section `%0' (type %1)", "unsupported section `%0' (type %1)")
+DIAG(unreachable_invalid_section_idx, DiagnosticEngine::Unreachable, "section[%0] is invalid in file %1", "section[%0] is invalid in file %1")
+DIAG(err_unsupported_whole_archive, DiagnosticEngine::Error, "Target does not support --whole-archive", "Target does not support --whole-archive")
+DIAG(err_unsupported_as_needed, DiagnosticEngine::Error, "Target does not support --as-needed", "Target does not support --as-needed")
+DIAG(err_unsupported_add_needed, DiagnosticEngine::Error, "Target doest not support --add-needed", "Target does not support --add-needed")
+DIAG(err_unsupported_Bdynamic, DiagnosticEngine::Error, "Target does not support --Bdynamic", "Target does not support --Bdynamic")
+DIAG(err_enable_as_needed_on_static_system, DiagnosticEngine::Warning, "can not enable --as-needed on the target which does not support shared objects", "can not enable --as-needed on the target which does not support shared objects")
+DIAG(err_mix_static_as_needed, DiagnosticEngine::Warning, "cannot mix --static with --as-needed", "cannot mix --static with --as-needed")
+DIAG(err_cannot_change_file_size, DiagnosticEngine::Error, "cannot truncate file `%0' to size %1", "cannot truncate ffile `%0' to size %1")
+DIAG(err_cannot_open_file, DiagnosticEngine::Error, "cannot open file %0.\nError Code: %1", "cannot open file %0.\nError Code: %1")
+DIAG(err_cannot_close_file, DiagnosticEngine::Error, "cannot close file %0.\nError Code: %1", "cannot close file %0.\nError Code: %1")
+DIAG(err_cannot_get_file_status, DiagnosticEngine::Error, "cannot get file status.\nError Code: %0", "cannot get file status.\nError Code: %0")
+DIAG(err_cannot_read_file, DiagnosticEngine::Error, "cannot read file %0 from offset %1 to length %2.", "cannot read file %0 from offset %1 to length %2.")
+DIAG(err_cannot_read_small_file, DiagnosticEngine::Fatal, "file %0 is too small to read.\n  file size is %1.\n  read from %2.", "file %0 is too small to read.\n  file size is %1.\n  read from %2.")
+DIAG(err_cannot_mmap_file, DiagnosticEngine::Error, "cannot open memory mapped file %0 from offset %1 to length %2.", "cannot open memoory mpped file %0 from offset %1 to length %2.")
+DIAG(err_cannot_munmap_file, DiagnosticEngine::Error, "cannot remove the mapped memory of file %0.", "cannot remove the mapped memory of file %0.")
+DIAG(err_cannot_write_file, DiagnosticEngine::Error, "cannot write file %0 from offset %1 to length %2.", "cannot write file %0 from offset %1 to length %2.")
+DIAG(warn_illegal_input_section, DiagnosticEngine::Warning, "section `%0' should not appear in input file `%1': %2", "section `%0' should not appear in input file `%1': %2")
+DIAG(err_cannot_trace_file, DiagnosticEngine::Unreachable, "cannot identify the type (%0) of input file `%1'.\n  %2", "cannot identify the type (%0) of input file `%1'.\n  %2")
+DIAG(err_out_of_range_region, DiagnosticEngine::Unreachable, "requested memory region is out of range.", "requested memory region is out of range.")
+DIAG(debug_eh_unsupport, DiagnosticEngine::Debug, "unsupported eh_frame: %0", "unsupported eh_frame: %0")
+DIAG(note_ehframe, DiagnosticEngine::Note, "eh_frame: %0", "eh_frame: %0")
+DIAG(note_eh_cie, DiagnosticEngine::Note, "CIE length: %0, aug_string: %1, fde_encodeing: %2", "CIE length: %0, aug_string: %1, fde_encodeing: %2")
+DIAG(note_eh_fde, DiagnosticEngine::Note, "FDE length: %0, offset of PC Begin: %1", "FDE length: %0, offset of PC Begin: %1")
diff --git a/include/mcld/LD/DiagGOTPLT.inc b/include/mcld/LD/DiagGOTPLT.inc
new file mode 100644
index 0000000..f0d3d2c
--- /dev/null
+++ b/include/mcld/LD/DiagGOTPLT.inc
@@ -0,0 +1,3 @@
+DIAG(mips_got_symbol, DiagnosticEngine::Unreachable, "%0 is not a dynamic symbol, do not put it in global got", "%0 is not a dynamic symbol, do not put it in global got")
+DIAG(fail_allocate_memory, DiagnosticEngine::Fatal, "fial to allocate memory for %0", "fial to allocate memory for %0")
+DIAG(reserve_entry_number_mismatch, DiagnosticEngine::Unreachable, "The number of reserved entries for %0 is inconsist", "The number of reserved entries for %0 is inconsist")
diff --git a/include/mcld/LD/DiagLayouts.inc b/include/mcld/LD/DiagLayouts.inc
new file mode 100644
index 0000000..af6bc96
--- /dev/null
+++ b/include/mcld/LD/DiagLayouts.inc
@@ -0,0 +1,3 @@
+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")
diff --git a/include/mcld/LD/DiagReaders.inc b/include/mcld/LD/DiagReaders.inc
new file mode 100644
index 0000000..8ba28c2
--- /dev/null
+++ b/include/mcld/LD/DiagReaders.inc
@@ -0,0 +1 @@
+DIAG(archive_magic_mismatch, DiagnosticEngine::Error, "magic number is mismatched in `%0'", "magic number is mismatched in `%0'")
diff --git a/include/mcld/LD/DiagRelocations.inc b/include/mcld/LD/DiagRelocations.inc
new file mode 100644
index 0000000..e115fd8
--- /dev/null
+++ b/include/mcld/LD/DiagRelocations.inc
@@ -0,0 +1,9 @@
+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(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'")
diff --git a/include/mcld/LD/DiagSymbolResolutions.inc b/include/mcld/LD/DiagSymbolResolutions.inc
new file mode 100644
index 0000000..786eb4b
--- /dev/null
+++ b/include/mcld/LD/DiagSymbolResolutions.inc
@@ -0,0 +1,10 @@
+DIAG(note_has_no_symtab, DiagnosticEngine::Note, "input file `%0' has no symbol table `%2'\n  path of input file: %1", "input file `%0' has no symbol table `%2'\n  path of input file: %1")
+DIAG(fatal_cannot_read_strtab, DiagnosticEngine::Fatal, "cannot read strtab for %2 in file `%0': %1", "cannot read strtab for %2 in file `%0': %1")
+DIAG(fail_sym_resolution, DiagnosticEngine::Unreachable, "Fails to resolve symbols [%0:%1]\nPlease reports to `%2'", "Fails to resolve symbols [%0:%1]\nPlease reports to `%2'")
+DIAG(mark_dynamic_defined, DiagnosticEngine::Ignore, "refer to dynamic symbol %0", "call a external function %0")
+DIAG(comm_refer_to_define, DiagnosticEngine::Ignore, "common symbol %0 is overridden by previous definition", "common symbol %0 is overridden by previous definition")
+DIAG(redefine_common, DiagnosticEngine::Ignore, "common symbol %0 is overridden by definition", "common symbol %0 is overriden by definition")
+DIAG(indirect_refer_to_common, DiagnosticEngine::Ignore, "indirect symbol %0 points to a common symbol", "indirect symbol %0 points to a common symbol")
+DIAG(indirect_refer_to_inexist, DiagnosticEngine::Fatal, "indirect symbol %0 points to a undefined symbol", "variable %0 is undefined")
+DIAG(multiple_definitions, DiagnosticEngine::Error, "multiple definition of symbol `%0'", "you define variable %0 twice")
+DIAG(undefined_situation, DiagnosticEngine::Unreachable, "reach undefined situation, action: %0, old(%1) -> new(%2)", "reach undefined situation, action: %0, old(%1) -> new(%2)")
diff --git a/include/mcld/LD/Diagnostic.h b/include/mcld/LD/Diagnostic.h
new file mode 100644
index 0000000..5e7d436
--- /dev/null
+++ b/include/mcld/LD/Diagnostic.h
@@ -0,0 +1,97 @@
+//===- Diagnostic.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_DIAGNOSTIC_H
+#define MCLD_DIAGNOSTIC_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+#include <cassert>
+#include <mcld/LD/DiagnosticEngine.h>
+
+namespace mcld
+{
+
+/** \class Diagnostic
+ *  \brief Diagnostic provides current status to DiagnosticPrinters.
+ */
+class Diagnostic
+{
+public:
+  Diagnostic(DiagnosticEngine& pEngine);
+
+  ~Diagnostic();
+
+  unsigned int getID() const
+  { return m_Engine.state().ID; }
+
+  unsigned int getNumArgs() const
+  { return m_Engine.state().numArgs; }
+
+  DiagnosticEngine::ArgumentKind getArgKind(unsigned int pIdx) const {
+    assert(pIdx < getNumArgs() && "Argument index is out of range!");
+    return (DiagnosticEngine::ArgumentKind)m_Engine.state().ArgumentKinds[pIdx];
+  }
+
+  const std::string &getArgStdStr(unsigned int pIdx) const {
+    assert(getArgKind(pIdx) == DiagnosticEngine::ak_std_string &&
+           "Invalid argument accessor!");
+    return m_Engine.state().ArgumentStrs[pIdx];
+  }
+
+  const char* getArgCStr(unsigned int pIdx) const {
+    assert(getArgKind(pIdx) == DiagnosticEngine::ak_c_string &&
+           "Invalid argument accessor!");
+    return reinterpret_cast<const char*>(m_Engine.state().ArgumentVals[pIdx]);
+  }
+
+  int getArgSInt(unsigned int pIdx) const {
+    assert(getArgKind(pIdx) == DiagnosticEngine::ak_sint &&
+           "Invalid argument accessor!");
+    return (int)m_Engine.state().ArgumentVals[pIdx];
+  }
+
+  unsigned int getArgUInt(unsigned int pIdx) const {
+    assert(getArgKind(pIdx) == DiagnosticEngine::ak_uint &&
+           "Invalid argument accessor!");
+    return (unsigned int)m_Engine.state().ArgumentVals[pIdx];
+  }
+
+  bool getArgBool(unsigned int pIdx) const {
+    assert(getArgKind(pIdx) == DiagnosticEngine::ak_bool &&
+           "Invalid argument accessor!");
+    return (bool)m_Engine.state().ArgumentVals[pIdx];
+  }
+
+  intptr_t getRawVals(unsigned int pIdx) const {
+    assert(getArgKind(pIdx) != DiagnosticEngine::ak_std_string &&
+           "Invalid argument accessor!");
+    return m_Engine.state().ArgumentVals[pIdx];
+  }
+
+  // format - format this diagnostic into string, subsituting the formal
+  // arguments. The result is appended at on the pOutStr.
+  void format(std::string& pOutStr) const;
+
+  // format - format the given formal string, subsituting the formal
+  // arguments. The result is appended at on the pOutStr.
+  void format(const char* pBegin, const char* pEnd, std::string& pOutStr) const;
+
+private:
+  const char* findMatch(char pVal, const char* pBegin, const char* pEnd ) const;
+
+private:
+  DiagnosticEngine& m_Engine;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/DiagnosticEngine.h b/include/mcld/LD/DiagnosticEngine.h
new file mode 100644
index 0000000..9c106e5
--- /dev/null
+++ b/include/mcld/LD/DiagnosticEngine.h
@@ -0,0 +1,150 @@
+//===- DiagnosticEngine.h -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_DIAGNOSTIC_ENGINE_H
+#define MCLD_DIAGNOSTIC_ENGINE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <string>
+#include <llvm/Support/DataTypes.h>
+#include <mcld/LD/DiagnosticInfos.h>
+
+namespace mcld {
+
+class Input;
+class MCLDInfo;
+class MsgHandler;
+class DiagnosticPrinter;
+class DiagnosticLineInfo;
+
+/** \class DiagnosticEngine
+ *  \brief DiagnosticEngine is used to report problems and issues.
+ *
+ *  DiagnosticEngine is used to report problems and issues. It creates the
+ *  Diagnostics and passes them to the DiagnosticPrinter for reporting to the
+ *  user.
+ *
+ *  DiagnosticEngine is a complex class, it is responsible for
+ *  - remember the argument string for MsgHandler
+ *  - choice the severity of a message by options
+ */
+class DiagnosticEngine
+{
+public:
+  enum Severity {
+    Unreachable,
+    Fatal,
+    Error,
+    Warning,
+    Debug,
+    Note,
+    Ignore,
+    None
+  };
+
+  enum ArgumentKind {
+    ak_std_string,  // std::string
+    ak_c_string,    // const char *
+    ak_sint,        // int
+    ak_uint,        // unsigned int
+    ak_bool         // bool
+  };
+
+public:
+  DiagnosticEngine(const MCLDInfo& pLDInfo,
+                   DiagnosticLineInfo* pLineInfo = NULL,
+                   DiagnosticPrinter* pPrinter = NULL,
+                   bool pShouldOwnPrinter = true);
+
+  ~DiagnosticEngine();
+
+  // -----  printer functions  ----- //
+  void setPrinter(DiagnosticPrinter& pPrinter, bool pShouldOwnPrinter = true);
+
+  DiagnosticPrinter* getPrinter()
+  { return m_pPrinter; }
+
+  const DiagnosticPrinter* getPrinter() const
+  { return m_pPrinter; }
+
+  DiagnosticPrinter* takePrinter() {
+    m_OwnPrinter = false;
+    return m_pPrinter;
+  }
+
+  bool ownPrinter() const
+  { return m_OwnPrinter; }
+
+  // -----  emission  ----- //
+  // emit - process the message to printer
+  bool emit();
+
+  // report - issue the message to the printer
+  MsgHandler report(uint16_t pID, Severity pSeverity);
+
+private:
+  friend class MsgHandler;
+  friend class Diagnostic;
+
+  enum {
+    /// MaxArguments - The maximum number of arguments we can hold. We currently
+    /// only support up to 10 arguments (%0-%9).
+    MaxArguments = 10,
+  };
+
+  struct State
+  {
+  public:
+    State() : numArgs(0), ID(-1), severity(None), file(NULL) { }
+    ~State() { }
+
+    void reset() {
+      numArgs = 0;
+      ID = -1;
+      severity = None;
+      file = NULL;
+    }
+
+  public:
+    std::string ArgumentStrs[MaxArguments];
+    intptr_t ArgumentVals[MaxArguments];
+    uint8_t ArgumentKinds[MaxArguments];
+    int8_t numArgs;
+    uint16_t ID;
+    Severity severity;
+    Input* file;
+  };
+
+private:
+  State& state()
+  { return m_State; }
+
+  const State& state() const
+  { return m_State; }
+
+  DiagnosticInfos& infoMap()
+  { return m_InfoMap; }
+
+  const DiagnosticInfos& infoMap() const
+  { return m_InfoMap; }
+
+private:
+  const MCLDInfo& m_LDInfo;
+  DiagnosticLineInfo* m_pLineInfo;
+  DiagnosticPrinter* m_pPrinter;
+  DiagnosticInfos m_InfoMap;
+  bool m_OwnPrinter;
+
+  State m_State;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/DiagnosticInfos.h b/include/mcld/LD/DiagnosticInfos.h
new file mode 100644
index 0000000..66f7fc0
--- /dev/null
+++ b/include/mcld/LD/DiagnosticInfos.h
@@ -0,0 +1,56 @@
+//===- DiagnosticInfo.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_DIAGNOSTIC_INFORMATION_H
+#define MCLD_DIAGNOSTIC_INFORMATION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/ADT/StringRef.h>
+
+namespace mcld {
+
+namespace diag {
+  enum ID {
+#define DIAG(ENUM, CLASS, ADDRMSG, LINEMSG) ENUM,
+#include "mcld/LD/DiagCommonKinds.inc"
+#include "mcld/LD/DiagReaders.inc"
+#include "mcld/LD/DiagSymbolResolutions.inc"
+#include "mcld/LD/DiagRelocations.inc"
+#include "mcld/LD/DiagLayouts.inc"
+#include "mcld/LD/DiagGOTPLT.inc"
+#undef DIAG
+    NUM_OF_BUILDIN_DIAGNOSTIC_INFO
+  };
+} // namespace of diag
+
+class MCLDInfo;
+class DiagnosticEngine;
+
+/** \class DiagnosticInfos
+ *  \brief DiagnosticInfos caches run-time information of DiagnosticInfo.
+ */
+class DiagnosticInfos
+{
+public:
+  DiagnosticInfos(const MCLDInfo& pLDInfo);
+
+  ~DiagnosticInfos();
+
+  llvm::StringRef getDescription(unsigned int pID, bool pLoC) const;
+
+  bool process(DiagnosticEngine& pEngine) const;
+
+private:
+  const MCLDInfo& m_LDInfo;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/DiagnosticLineInfo.h b/include/mcld/LD/DiagnosticLineInfo.h
new file mode 100644
index 0000000..30f0546
--- /dev/null
+++ b/include/mcld/LD/DiagnosticLineInfo.h
@@ -0,0 +1,29 @@
+//===- DiagnosticLineInfo.h -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_DIAGNOSTICLINEINFO_H
+#define MCLD_DIAGNOSTICLINEINFO_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld
+{
+
+/** \class DiagnosticLineInfo
+ *  \brief Map the address to the line of code.
+ */
+class DiagnosticLineInfo
+{
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/DiagnosticPrinter.h b/include/mcld/LD/DiagnosticPrinter.h
new file mode 100644
index 0000000..13911f5
--- /dev/null
+++ b/include/mcld/LD/DiagnosticPrinter.h
@@ -0,0 +1,59 @@
+//===- DiagnosticPrinter.h ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_DIAGNOSTIC_PRINTER_H
+#define MCLD_DIAGNOSTIC_PRINTER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/LD/DiagnosticEngine.h>
+#include <mcld/LD/Diagnostic.h>
+
+namespace mcld
+{
+
+/** \class DiagnosticPrinter
+ *  \brief DiagnosticPrinter provides the interface to customize diagnostic
+ *  messages and output.
+ */
+class DiagnosticPrinter
+{
+public:
+  DiagnosticPrinter();
+
+  virtual ~DiagnosticPrinter();
+
+  virtual void beginInput(const Input& pInput, const MCLDInfo& pLDInfo) {}
+
+  virtual void endInput() {}
+
+  virtual void finish() {}
+
+  virtual void clear()
+  { m_NumErrors = m_NumWarnings = 0; }
+
+  /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+  /// capturing it to a log as needed.
+  virtual void handleDiagnostic(DiagnosticEngine::Severity pSeverity,
+                                const Diagnostic& pInfo);
+
+  unsigned int getNumErrors() const
+  { return m_NumErrors; }
+
+  unsigned int getNumWarnings() const
+  { return m_NumWarnings; }
+
+protected:
+  unsigned int m_NumErrors;
+  unsigned int m_NumWarnings;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/DynObjFileFormat.h b/include/mcld/LD/DynObjFileFormat.h
index 6a25184..7b1626d 100644
--- a/include/mcld/LD/DynObjFileFormat.h
+++ b/include/mcld/LD/DynObjFileFormat.h
@@ -26,3 +26,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/DynObjReader.h b/include/mcld/LD/DynObjReader.h
index c3b4099..0900109 100644
--- a/include/mcld/LD/DynObjReader.h
+++ b/include/mcld/LD/DynObjReader.h
@@ -42,3 +42,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/DynObjWriter.h b/include/mcld/LD/DynObjWriter.h
index 08bb237..1c77bd4 100644
--- a/include/mcld/LD/DynObjWriter.h
+++ b/include/mcld/LD/DynObjWriter.h
@@ -38,3 +38,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFDynObjFileFormat.h b/include/mcld/LD/ELFDynObjFileFormat.h
index 02d7103..9b77e91 100644
--- a/include/mcld/LD/ELFDynObjFileFormat.h
+++ b/include/mcld/LD/ELFDynObjFileFormat.h
@@ -35,3 +35,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFDynObjReader.h b/include/mcld/LD/ELFDynObjReader.h
index 7fdcc23..72a3336 100644
--- a/include/mcld/LD/ELFDynObjReader.h
+++ b/include/mcld/LD/ELFDynObjReader.h
@@ -48,3 +48,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFDynObjWriter.h b/include/mcld/LD/ELFDynObjWriter.h
index 7cfac05..dc0e37b 100644
--- a/include/mcld/LD/ELFDynObjWriter.h
+++ b/include/mcld/LD/ELFDynObjWriter.h
@@ -50,3 +50,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFExecFileFormat.h b/include/mcld/LD/ELFExecFileFormat.h
index a6544fa..3c0d8bd 100644
--- a/include/mcld/LD/ELFExecFileFormat.h
+++ b/include/mcld/LD/ELFExecFileFormat.h
@@ -28,10 +28,10 @@
   ELFExecFileFormat(GNULDBackend& pBackend) : ELFFileFormat(pBackend)
   {}
 
-  void initObjectType(MCLinker& pLinker)
-  { /** TODO **/ }
+  void initObjectType(MCLinker& pLinker);
 };
 
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFExecWriter.h b/include/mcld/LD/ELFExecWriter.h
new file mode 100644
index 0000000..09709f7
--- /dev/null
+++ b/include/mcld/LD/ELFExecWriter.h
@@ -0,0 +1,53 @@
+//===- ELFDynObjWriter.h --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELF_EXECUTABLE_OBJECT_WRITER_H
+#define MCLD_ELF_EXECUTABLE_OBJECT_WRITER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <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
+{
+
+class GNULDBackend;
+class MCLinker;
+
+/** \class ELFDynObjWriter
+ *  \brief ELFDynObjWriter writes the dynamic sections.
+ */
+class ELFExecWriter : public ExecWriter, private ELFWriter
+{
+public:
+  typedef ELFWriter::FileOffset FileOffset;
+
+public:
+  ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker);
+  ~ELFExecWriter();
+
+  llvm::error_code writeExecutable(Output& pOutput);
+
+private:
+  GNULDBackend& m_Backend;
+  MCLinker& m_Linker;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ELFFileFormat.h b/include/mcld/LD/ELFFileFormat.h
index 1706a66..f7a0c68 100644
--- a/include/mcld/LD/ELFFileFormat.h
+++ b/include/mcld/LD/ELFFileFormat.h
@@ -171,6 +171,9 @@
   bool hasStabStr() const
   { return (NULL != f_pStabStr) && (0 != f_pStabStr->size()); }
 
+  bool hasStack() const
+  { return (NULL != f_pStack) && (0 != f_pStack->size()); }
+
   // -----  access functions  ----- //
   /// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
   LDSection& getNULLSection() {
@@ -595,6 +598,15 @@
     return *f_pStabStr;
   }
 
+  LDSection& getStack() {
+    assert(NULL != f_pStack);
+    return *f_pStack;
+  }
+
+  const LDSection& getStack() const {
+    assert(NULL != f_pStack);
+    return *f_pStack;
+  }
 protected:
   GNULDBackend& f_Backend;
 
@@ -646,8 +658,12 @@
   LDSection* f_pNoteABITag;        // .note.ABI-tag
   LDSection* f_pStab;              // .stab
   LDSection* f_pStabStr;           // .stabstr
+
+  /// practical
+  LDSection* f_pStack;             // .stack
 };
 
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFObjectReader.h b/include/mcld/LD/ELFObjectReader.h
index 635da85..ac11261 100644
--- a/include/mcld/LD/ELFObjectReader.h
+++ b/include/mcld/LD/ELFObjectReader.h
@@ -56,3 +56,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFObjectWriter.h b/include/mcld/LD/ELFObjectWriter.h
index e534a58..a6b9a87 100644
--- a/include/mcld/LD/ELFObjectWriter.h
+++ b/include/mcld/LD/ELFObjectWriter.h
@@ -44,3 +44,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFReader.h b/include/mcld/LD/ELFReader.h
index 3acbf25..d232cab 100644
--- a/include/mcld/LD/ELFReader.h
+++ b/include/mcld/LD/ELFReader.h
@@ -24,6 +24,7 @@
 #include <mcld/LD/LDContext.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 
 namespace mcld
 {
@@ -101,6 +102,14 @@
                        MCLinker& 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;
+
 protected:
   /// LinkInfo - some section needs sh_link and sh_info, remember them.
   struct LinkInfo {
@@ -214,6 +223,9 @@
                       MCLinker& pLinker,
                       LDSection& pSection,
                       const MemoryRegion& pRegion) const;
+
+  /// readDynamic - read ELF .dynamic in input dynobj
+  inline bool readDynamic(Input& pInput) const;
 };
 
 #include "ELFReader.tcc"
@@ -221,3 +233,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFReader.tcc b/include/mcld/LD/ELFReader.tcc
index 862b971..61e8331 100644
--- a/include/mcld/LD/ELFReader.tcc
+++ b/include/mcld/LD/ELFReader.tcc
@@ -190,7 +190,8 @@
   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::Group == info->section->kind() ||
+        LDFileFormat::Note == info->section->kind()) {
       info->section->setLink(pInput.context()->getSection(info->sh_link));
       continue;
     }
@@ -254,8 +255,8 @@
 {
   // get number of symbols
   size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf32_Sym);
-  llvm::ELF::Elf32_Sym* symtab =
-                      reinterpret_cast<llvm::ELF::Elf32_Sym*>(pRegion.start());
+  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;
@@ -292,9 +293,6 @@
         st_shndx = llvm::ELF::SHN_UNDEF;
     }
 
-    // get ld_name
-    llvm::StringRef ld_name(pStrTab + st_name);
-
     // get ld_type
     ResolveInfo::Type ld_type = static_cast<ResolveInfo::Type>(st_info & 0xF);
 
@@ -316,6 +314,19 @@
     // 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;
 
@@ -404,13 +415,13 @@
   ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
 
   ResolveInfo* result =
-         pLDInfo.getStrSymPool().createSymbol(ld_name,
-                                              pInput.type() == Input::DynObj,
-                                              ld_type,
-                                              ld_desc,
-                                              ld_binding,
-                                              st_size,
-                                              ld_vis);
+         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);
@@ -426,8 +437,8 @@
 {
   // get the number of rela
   size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rela);
-  llvm::ELF::Elf32_Rela* relaTab =
-                     reinterpret_cast<llvm::ELF::Elf32_Rela*>(pRegion.start());
+  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;
@@ -447,13 +458,8 @@
     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) {
-      llvm::report_fatal_error(llvm::Twine("invalid symbol index :") +
-                               llvm::Twine(r_sym) +
-                               llvm::Twine(" in file `") +
-                               pInput.path().native() +
-                               llvm::Twine("'.\n"));
-    }
+    if (NULL == symbol)
+      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
 
     ResolveInfo* resolve_info = symbol->resolveInfo();
 
@@ -461,16 +467,13 @@
          pLinker.getLayout().getFragmentRef(*pSection.getLink(), r_offset);
 
     if (NULL == frag_ref) {
-      llvm::report_fatal_error(llvm::Twine("invalid sh_info: ") +
-                               llvm::Twine(pSection.getLink()->index()) +
-                               llvm::Twine(" of the relocation section `") +
-                               pSection.name() +
-                               llvm::Twine("' in file `") +
-                               pInput.path().native() +
-                               llvm::Twine(".\n"));
+      fatal(diag::err_cannot_read_relocated_section)
+                                << pSection.name()
+                                << pSection.getLink()->index()
+                                << pInput.path();
     }
 
-    pLinker.addRelocation(r_type, *symbol,  *resolve_info, *frag_ref, r_addend);
+    pLinker.addRelocation(r_type, *symbol,  *resolve_info, *frag_ref, pSection, r_addend);
   }
   return true;
 }
@@ -483,8 +486,8 @@
 {
   // get the number of rel
   size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rel);
-  llvm::ELF::Elf32_Rel* relTab =
-                      reinterpret_cast<llvm::ELF::Elf32_Rel*>(pRegion.start());
+  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;
@@ -503,11 +506,7 @@
 
     LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
     if (NULL == symbol) {
-      llvm::report_fatal_error(llvm::Twine("invalid symbol index :") +
-                               llvm::Twine(r_sym) +
-                               llvm::Twine(" in file `") +
-                               pInput.path().native() +
-                               llvm::Twine("'.\n"));
+      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
     }
 
     ResolveInfo* resolve_info = symbol->resolveInfo();
@@ -516,16 +515,78 @@
          pLinker.getLayout().getFragmentRef(*pSection.getLink(), r_offset);
 
     if (NULL == frag_ref) {
-      llvm::report_fatal_error(llvm::Twine("invalid sh_info: ") +
-                               llvm::Twine(pSection.getLink()->index()) +
-                               llvm::Twine(" of the relocation section `") +
-                               pSection.name() +
-                               llvm::Twine("' in file `") +
-                               pInput.path().native() +
-                               llvm::Twine(".\n"));
+      fatal(diag::err_cannot_read_relocated_section)
+                                << pSection.name()
+                                << pSection.getLink()->index()
+                                << pInput.path();
     }
 
-    pLinker.addRelocation(r_type, *symbol, *resolve_info, *frag_ref);
+    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(dynamic_sect->offset(), dynamic_sect->size());
+
+  MemoryRegion* dynstr_region =
+    pInput.memArea()->request(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/ELFSegment.h b/include/mcld/LD/ELFSegment.h
index 312f0a7..8b9ff98 100644
--- a/include/mcld/LD/ELFSegment.h
+++ b/include/mcld/LD/ELFSegment.h
@@ -36,7 +36,8 @@
              uint64_t pPaddr = 0,
              uint64_t pFilesz = 0,
              uint64_t pMemsz = 0,
-             uint64_t pAlign = 0);
+             uint64_t pAlign = 0,
+             uint64_t pMaxSectAlign = 0);
   ~ELFSegment();
 
   ///  -----  iterators  -----  ///
@@ -52,34 +53,32 @@
   const_sect_iterator sectEnd() const
   { return m_SectionList.end(); }
 
-  const LDSection* getFirstSection()
+  LDSection* getFirstSection()
   {
-    if (0 == m_SectionList.size())
+    if (0 == numOfSections())
       return NULL;
     return m_SectionList[0];
   }
 
-  const LDSection* getLastSection()
+  LDSection* getLastSection()
   {
-    size_t size = m_SectionList.size();
-    if (0 == size)
+    if (0 == numOfSections())
       return NULL;
-    return m_SectionList[size - 1];
+    return m_SectionList[numOfSections() - 1];
   }
 
   const LDSection* getFirstSection() const
   {
-    if (0 == m_SectionList.size())
+    if (0 == numOfSections())
       return NULL;
     return m_SectionList[0];
   }
 
   const LDSection* getLastSection() const
   {
-    size_t size = m_SectionList.size();
-    if (0 == size)
+    if (0 == numOfSections())
       return NULL;
-    return m_SectionList[size - 1];
+    return m_SectionList[numOfSections() - 1];
   }
 
   ///  -----  observers  -----  ///
@@ -105,7 +104,7 @@
   { return m_Flag; }
 
   uint64_t align() const
-  { return m_Align; }
+  { return std::max(m_Align, m_MaxSectionAlign); }
 
   size_t numOfSections() const
   { return m_SectionList.size(); }
@@ -142,21 +141,25 @@
   void addSection(LDSection* pSection)
   {
     assert(NULL != pSection);
+    if (pSection->align() > m_MaxSectionAlign)
+      m_MaxSectionAlign = pSection->align();
     m_SectionList.push_back(pSection);
   }
 
 private:
-  uint32_t m_Type;    // Type of segment
-  uint32_t m_Flag;    // Segment flags
-  uint64_t m_Offset;  // File offset where segment is located, in bytes
-  uint64_t m_Vaddr;   // Virtual address of beginning of segment
-  uint64_t m_Paddr;   // Physical address of beginning of segment (OS-specific)
-  uint64_t m_Filesz;  // Num. of bytes in file image of segment (may be zero)
-  uint64_t m_Memsz;   // Num. of bytes in mem image of segment (may be zero)
-  uint64_t m_Align;   // Segment alignment constraint
+  uint32_t m_Type;            // Type of segment
+  uint32_t m_Flag;            // Segment flags
+  uint64_t m_Offset;          // File offset where segment is located, in bytes
+  uint64_t m_Vaddr;           // Virtual address of the segment
+  uint64_t m_Paddr;           // Physical address of the segment (OS-specific)
+  uint64_t m_Filesz;          // # of bytes in file image of segment (may be 0)
+  uint64_t m_Memsz;           // # of bytes in mem image of segment (may be 0)
+  uint64_t m_Align;           // alignment constraint
+  uint64_t m_MaxSectionAlign; // max alignment of the sections in this segment
   std::vector<LDSection*> m_SectionList;
 };
 
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFSegmentFactory.h b/include/mcld/LD/ELFSegmentFactory.h
index 7b5e305..5085a18 100644
--- a/include/mcld/LD/ELFSegmentFactory.h
+++ b/include/mcld/LD/ELFSegmentFactory.h
@@ -31,12 +31,16 @@
   /// produce - produce an empty ELF segment information.
   /// this function will create an ELF segment
   /// @param pType - p_type in ELF program header
-  ELFSegment* produce(uint32_t pType);
+  ELFSegment* produce(uint32_t pType, uint32_t pFlag = llvm::ELF::PF_R);
 
-  /// destroy - destruct the ELF segment
-  void destroy(ELFSegment*& pSegment);
+  ELFSegment*
+  find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear);
+
+  const ELFSegment*
+  find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear) const;
 };
 
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ELFWriter.h b/include/mcld/LD/ELFWriter.h
index 51834d1..34a6483 100644
--- a/include/mcld/LD/ELFWriter.h
+++ b/include/mcld/LD/ELFWriter.h
@@ -71,6 +71,12 @@
 
   void emitELF64SectionHeader(Output& pOutput, MCLinker& pLinker) const;
 
+  void emitELF32ProgramHeader(Output& pOutput,
+                              const GNULDBackend& pBackend) const;
+
+  void emitELF64ProgramHeader(Output& pOutput,
+                              const GNULDBackend& pBackend) const;
+
   // emitShStrTab - emit .shstrtab
   void emitELF32ShStrTab(Output& pOutput, MCLinker& pLinker) const;
 
@@ -119,3 +125,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/EhFrame.h b/include/mcld/LD/EhFrame.h
new file mode 100644
index 0000000..2e0d2c5
--- /dev/null
+++ b/include/mcld/LD/EhFrame.h
@@ -0,0 +1,140 @@
+//===- EhFrame.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_EXCEPTION_HANDLING_FRAME_H
+#define MCLD_EXCEPTION_HANDLING_FRAME_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <vector>
+
+#include <mcld/ADT/TypeTraits.h>
+#include <mcld/LD/CIE.h>
+#include <mcld/LD/FDE.h>
+#include <mcld/MC/MCRegionFragment.h>
+#include <mcld/Support/GCFactory.h>
+
+namespace mcld
+{
+/** \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 TargetLDBackend;
+
+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;
+
+public:
+  EhFrame();
+  ~EhFrame();
+
+  /// readEhFrame - read an .eh_frame section and create the corresponding
+  /// CIEs and FDEs
+  /// @param pSD - the MCSectionData 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,
+                       llvm::MCSectionData& pSD,
+                       LDSection& pSection,
+                       MemoryArea& pArea);
+
+  // ----- observers ----- //
+  cie_iterator cie_begin()
+  { return m_CIEs.begin(); }
+
+  const_cie_iterator cie_begin() const
+  { return m_CIEs.begin(); }
+
+  cie_iterator cie_end()
+  { return m_CIEs.end(); }
+
+  const_cie_iterator cie_end() const
+  { return m_CIEs.end(); }
+
+  fde_iterator fde_begin()
+  { return m_FDEs.begin(); }
+
+  const_fde_iterator fde_begin() const
+  { return m_FDEs.begin(); }
+
+  fde_iterator fde_end()
+  { return m_FDEs.end(); }
+
+  const_fde_iterator fde_end() const
+  { return m_FDEs.end(); }
+
+  /// getFDECount - the number of FDE entries
+  size_t getFDECount()
+  { return m_FDEs.size(); }
+
+  size_t getFDECount() const
+  { return m_FDEs.size(); }
+
+  /// 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; }
+
+private:
+  typedef std::vector<llvm::MCFragment*> FragListType;
+
+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 MCFragments in pList
+  void deleteFragments(FragListType& pList, MemoryArea& pArea);
+
+private:
+  CIEListType m_CIEs;
+  FDEListType m_FDEs;
+
+  bool m_fCanRecognizeAll;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/EhFrameHdr.h b/include/mcld/LD/EhFrameHdr.h
new file mode 100644
index 0000000..70f915c
--- /dev/null
+++ b/include/mcld/LD/EhFrameHdr.h
@@ -0,0 +1,99 @@
+//===- EhFrameHdr.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_EHFRAMEHDR_H
+#define MCLD_EHFRAMEHDR_H
+#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>
+
+namespace mcld
+{
+class EhFrame;
+class LDSection;
+class Output;
+class FDE;
+class MCLinker;
+
+/** \class EhFrameHdr
+ *  \brief EhFrameHdr represents .eh_frame_hdr section.
+ */
+class EhFrameHdr
+{
+public:
+  EhFrameHdr(const EhFrame& pEhFrameData,
+             const LDSection& pEhFrameSect,
+             LDSection& pEhFrameHdrSect);
+
+  ~EhFrameHdr();
+
+  /// sizeOutput - base on the fde count to size output
+  void sizeOutput();
+
+  /// emitOutput - write out eh_frame_hdr
+  template<size_t size>
+  void emitOutput(Output& pOutput, MCLinker& pLinker);
+
+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; }
+  };
+
+private:
+  /// eh_frame data
+  const EhFrame& m_EhFrameData;
+
+  /// .eh_frame section
+  const LDSection& m_EhFrameSect;
+
+  /// .eh_frame_hdr section
+  LDSection& m_EhFrameHdrSect;
+};
+
+#include "EhFrameHdr.tcc"
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/EhFrameHdr.tcc b/include/mcld/LD/EhFrameHdr.tcc
new file mode 100644
index 0000000..3b7d8ee
--- /dev/null
+++ b/include/mcld/LD/EhFrameHdr.tcc
@@ -0,0 +1,163 @@
+//===- 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/ExecWriter.h b/include/mcld/LD/ExecWriter.h
new file mode 100644
index 0000000..edce096
--- /dev/null
+++ b/include/mcld/LD/ExecWriter.h
@@ -0,0 +1,41 @@
+//===- ExecWriter.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_EXECUTABLE_OBJECT_WRITER_H
+#define MCLD_EXECUTABLE_OBJECT_WRITER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/MC/MCLDOutput.h>
+#include <mcld/LD/LDWriter.h>
+#include <llvm/Support/system_error.h>
+
+namespace mcld
+{
+
+/** \class ExecWriter
+ *  \brief ExecWriter provides an common interface for different object
+ *  formats.
+ */
+class ExecWriter : public LDWriter
+{
+protected:
+  // force to have a TargetLDBackend
+  ExecWriter(TargetLDBackend& pLDBackend)
+  { }
+
+public:
+  virtual ~ExecWriter() { }
+
+  virtual llvm::error_code writeExecutable(Output& pOutput) = 0;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/FDE.h b/include/mcld/LD/FDE.h
new file mode 100644
index 0000000..bd52e78
--- /dev/null
+++ b/include/mcld/LD/FDE.h
@@ -0,0 +1,53 @@
+//===- FDE.h --------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_FRAME_DESCRIPTION_ENTRY_H
+#define MCLD_FRAME_DESCRIPTION_ENTRY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/LD/CIE.h>
+#include <mcld/MC/MCRegionFragment.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 MCRegionFragment
+{
+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 8beac2c..92c7e7a 100644
--- a/include/mcld/LD/GNUArchiveReader.h
+++ b/include/mcld/LD/GNUArchiveReader.h
@@ -13,8 +13,6 @@
 #endif
 
 #include "mcld/LD/ArchiveReader.h"
-#include "mcld/Support/Path.h"
-#include <llvm/ADT/OwningPtr.h>
 
 #include <vector>
 #include <string>
@@ -27,6 +25,7 @@
 
 namespace mcld
 {
+class MemoryArea;
 class MCLDInfo;
 class Input;
 class InputTree;
@@ -37,13 +36,24 @@
 class GNUArchiveReader : public ArchiveReader
 {
 private:
-  struct ArchiveMemberHeader;
   struct SymbolTableEntry;
 
+  enum Constant
+  {
+    /// The length of the magic strign at the end of an archive member header.
+    HeaderFinalMagicSize = 2,
+    /// The length of the magic string at the start of an archive.
+    ArchiveMagicSize = 8
+  };
+  /// The magic string at the start of an archive.
+  static const char ArchiveMagic[ArchiveMagicSize];
+  static const char ThinArchiveMagic[ArchiveMagicSize];
+  /// The Magic string expected at the end of an archive member header.
+  static const char HeaderFinalMagic[HeaderFinalMagicSize];
+
 public:
-  explicit GNUArchiveReader(MCLDInfo &pLDInfo, LDReader::Endian endian)
-  : m_pLDInfo(pLDInfo),
-    m_endian(endian)
+  explicit GNUArchiveReader(MCLDInfo &pLDInfo)
+  : m_pLDInfo(pLDInfo)
   { }
 
   ~GNUArchiveReader()
@@ -63,23 +73,23 @@
   /// second, read extended file name which is used in thin archive
   InputTree *setupNewArchive(Input &pInput, size_t off);
 
-  /// parse the archive header, and return the member size
-  size_t parseMemberHeader(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile,
+  /// read the archive header, and return the member size
+  size_t readMemberHeader(MemoryArea &pArea,
                    off_t off,
                    std::string *p_Name,
                    off_t *nestedOff,
                    std::string &p_ExtendedName);
 
-  void readSymbolTable(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile,
+  void readSymbolTable(MemoryArea &pArea,
                       std::vector<SymbolTableEntry> &pSymbolTable,
                       off_t start,
                       size_t size);
 
 private:
   MCLDInfo &m_pLDInfo;
-  LDReader::Endian m_endian;
 };
 
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/Group.h b/include/mcld/LD/Group.h
index c5ce827..31c4a68 100644
--- a/include/mcld/LD/Group.h
+++ b/include/mcld/LD/Group.h
@@ -25,3 +25,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/InputSymbolTable.h b/include/mcld/LD/InputSymbolTable.h
deleted file mode 100644
index c1614dd..0000000
--- a/include/mcld/LD/InputSymbolTable.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- InputSymbolTable.h -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef INPUTSYMBOLTABLE_H
-#define INPUTSYMBOLTABLE_H
-#include <llvm/ADT/StringRef.h>
-#include "mcld/LD/SymbolTableIF.h"
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-namespace mcld
-{
-
-class LDSymbol;
-
-/** \class InputSymbolTable
- *  \brief Input symbol table, for MCLDInput.
- *
- *  \see
- */
-class InputSymbolTable : public SymbolTableIF
-{
-  /* draft. */
-  friend class SymbolTableFactory;
-private:
-  InputSymbolTable(StrSymPool &pStrSymPool,
-                   size_t pNumOfSymbols,
-                   StringTable &pEntireStringTable,
-                   StringTable &pDynamicStringTable);
-private:
-  virtual void doInsertSymbol(LDSymbol *);
-  virtual void doMerge(const SymbolTableIF &);
-public:
-  virtual ~InputSymbolTable();
-};
-
-} // namespace of mcld
-
-#endif
diff --git a/include/mcld/LD/LDContext.h b/include/mcld/LD/LDContext.h
index a9cc978..878ba8d 100644
--- a/include/mcld/LD/LDContext.h
+++ b/include/mcld/LD/LDContext.h
@@ -102,3 +102,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/LDFileFormat.h b/include/mcld/LD/LDFileFormat.h
index 511471a..a537fb1 100644
--- a/include/mcld/LD/LDFileFormat.h
+++ b/include/mcld/LD/LDFileFormat.h
@@ -35,7 +35,9 @@
     Relocation,
     Debug,
     Target,
-    Exception,
+    EhFrame,
+    EhFrameHdr,
+    GCCExceptTable,
     Version,
     Note,
     MetaData,
@@ -110,3 +112,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/LDReader.h b/include/mcld/LD/LDReader.h
index cb1e454..4fde9f0 100644
--- a/include/mcld/LD/LDReader.h
+++ b/include/mcld/LD/LDReader.h
@@ -44,3 +44,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/LDSection.h b/include/mcld/LD/LDSection.h
index 460c479..4c793de 100644
--- a/include/mcld/LD/LDSection.h
+++ b/include/mcld/LD/LDSection.h
@@ -202,3 +202,4 @@
 } // end namespace mcld
 
 #endif
+
diff --git a/include/mcld/LD/LDSectionFactory.h b/include/mcld/LD/LDSectionFactory.h
index 8495924..49b11c7 100644
--- a/include/mcld/LD/LDSectionFactory.h
+++ b/include/mcld/LD/LDSectionFactory.h
@@ -55,3 +55,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/LDSymbol.h b/include/mcld/LD/LDSymbol.h
index eabd05b..45c0b75 100644
--- a/include/mcld/LD/LDSymbol.h
+++ b/include/mcld/LD/LDSymbol.h
@@ -95,7 +95,7 @@
   ResolveInfo* resolveInfo()
   { return m_pResolveInfo; }
 
-  const ResolveInfo* resolveInfo() const
+  const ResolveInfo* resolveInfo() const 
   { return m_pResolveInfo; }
 
   bool hasFragRef() const
@@ -109,7 +109,7 @@
 
   void setValue(ValueType pValue)
   { m_Value = pValue; }
-
+ 
   void setFragmentRef(MCFragmentRef* pFragmentRef);
 
   void setResolveInfo(const ResolveInfo& pInfo);
@@ -125,3 +125,4 @@
 } // namespace mcld
 
 #endif
+
diff --git a/include/mcld/LD/LDWriter.h b/include/mcld/LD/LDWriter.h
index 415c5c1..78c2871 100644
--- a/include/mcld/LD/LDWriter.h
+++ b/include/mcld/LD/LDWriter.h
@@ -38,3 +38,4 @@
 } //end namespace
 
 #endif
+
diff --git a/include/mcld/LD/Layout.h b/include/mcld/LD/Layout.h
index ea0d971..2b36126 100644
--- a/include/mcld/LD/Layout.h
+++ b/include/mcld/LD/Layout.h
@@ -18,6 +18,7 @@
 #include <mcld/MC/MCFragmentRef.h>
 #include <mcld/Support/GCFactory.h>
 #include <mcld/LD/LDSection.h>
+#include <mcld/MC/MCLDInfo.h>
 #include <map>
 
 namespace mcld
@@ -112,7 +113,7 @@
   const LDSection* getOutputLDSection(const llvm::MCFragment& pFrag) const;
 
   // -----  modifiers  ----- //
-  bool layout(Output& pOutput, const TargetLDBackend& pBackend);
+  bool layout(Output& pOutput, const TargetLDBackend& pBackend, const MCLDInfo& pInfo);
 
   /// addInputRange
   void addInputRange(const llvm::MCSectionData& pSD,
@@ -252,7 +253,8 @@
   /// sortSectionOrder - perform sorting on m_SectionOrder to get final layout
   /// ordering
   void sortSectionOrder(const Output& pOutput,
-                        const TargetLDBackend& pBackend);
+                        const TargetLDBackend& pBackend,
+                        const MCLDInfo& pInfo);
 
 private:
   /// a vector to describe the order of sections
@@ -267,3 +269,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/MsgHandler.h b/include/mcld/LD/MsgHandler.h
new file mode 100644
index 0000000..d10f8a2
--- /dev/null
+++ b/include/mcld/LD/MsgHandler.h
@@ -0,0 +1,128 @@
+//===- MsgHandler.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MESSAGE_HANDLER_H
+#define MCLD_MESSAGE_HANDLER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <string>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/Twine.h>
+#include <mcld/Support/Path.h>
+#include <mcld/LD/DiagnosticEngine.h>
+
+namespace mcld
+{
+
+/** \class MsgHandler
+ *  \brief MsgHandler controls the timing to output message.
+ */
+class MsgHandler
+{
+public:
+  MsgHandler(DiagnosticEngine& pEngine);
+  ~MsgHandler();
+
+  bool emit();
+
+  void addString(llvm::StringRef pStr) const;
+
+  void addString(const std::string& pStr) const;
+
+  void addTaggedVal(intptr_t pValue, DiagnosticEngine::ArgumentKind pKind) const;
+
+private:
+  void flushCounts()
+  { m_Engine.state().numArgs = m_NumArgs; }
+
+private:
+  DiagnosticEngine& m_Engine;
+  mutable unsigned int m_NumArgs;
+};
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, llvm::StringRef pStr)
+{
+  pHandler.addString(pStr);
+  return pHandler;
+}
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, const std::string& pStr)
+{
+  pHandler.addString(pStr);
+  return pHandler;
+}
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, const sys::fs::Path& pPath)
+{
+  pHandler.addString(pPath.native());
+  return pHandler;
+}
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, const char* pStr)
+{
+  pHandler.addTaggedVal(reinterpret_cast<intptr_t>(pStr),
+                        DiagnosticEngine::ak_c_string);
+  return pHandler;
+}
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, int pValue)
+{
+  pHandler.addTaggedVal(pValue, DiagnosticEngine::ak_sint);
+  return pHandler;
+}
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, unsigned int pValue)
+{
+  pHandler.addTaggedVal(pValue, DiagnosticEngine::ak_uint);
+  return pHandler;
+}
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, long pValue)
+{
+  pHandler.addTaggedVal(pValue, DiagnosticEngine::ak_sint);
+  return pHandler;
+}
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, unsigned long pValue)
+{
+  pHandler.addTaggedVal(pValue, DiagnosticEngine::ak_uint);
+  return pHandler;
+}
+
+inline const MsgHandler &
+operator<<(const MsgHandler& pHandler, bool pValue)
+{
+  pHandler.addTaggedVal(pValue, DiagnosticEngine::ak_bool);
+  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/StrSymPool.h b/include/mcld/LD/NamePool.h
similarity index 89%
rename from include/mcld/LD/StrSymPool.h
rename to include/mcld/LD/NamePool.h
index 0550a4c..79d55b9 100644
--- a/include/mcld/LD/StrSymPool.h
+++ b/include/mcld/LD/NamePool.h
@@ -1,4 +1,4 @@
-//===- StrSymPool.h -------------------------------------------------------===//
+//===- NamePool.h ---------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MCLD_STRING_SYMBOL_POOL_H
-#define MCLD_STRING_SYMBOL_POOL_H
+#ifndef MCLD_NAME_POOL_H
+#define MCLD_NAME_POOL_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -33,20 +33,20 @@
 class StringTable;
 class SymbolTableIF;
 
-/** \class StrSymPool
+/** \class NamePool
  *  \brief Store symbol and search symbol by name. Can help symbol resolution.
  *
- *  - MCLinker is responsed for creating StrSymPool.
+ *  - MCLinker is responsed for creating NamePool.
  */
-class StrSymPool : private Uncopyable
+class NamePool : private Uncopyable
 {
 public:
   typedef HashTable<ResolveInfo, StringHash<ELF>, ResolveInfoFactory> Table;
   typedef size_t size_type;
 
 public:
-  StrSymPool(const Resolver& pResolver, size_type pSize = 3);
-  ~StrSymPool();
+  NamePool(const Resolver& pResolver, size_type pSize = 3);
+  ~NamePool();
 
   // -----  modifiers  ----- //
   /// createSymbol - create a symbol but do not insert into the pool.
@@ -57,7 +57,7 @@
                             ResolveInfo::Binding pBinding,
                             ResolveInfo::SizeType pSize,
                             ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
-
+  
   /// insertSymbol - insert a symbol and resolve the symbol immediately
   /// @param pOldInfo - if pOldInfo is not NULL, the old ResolveInfo being
   ///                   overriden is kept in pOldInfo.
@@ -100,7 +100,7 @@
   size_type capacity() const;
 
 private:
-  Resolver* m_pResolver;
+  const Resolver* m_pResolver;
   Table m_Table;
 
 };
@@ -108,3 +108,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ObjectReader.h b/include/mcld/LD/ObjectReader.h
index bd49d5e..9dbe9ac 100644
--- a/include/mcld/LD/ObjectReader.h
+++ b/include/mcld/LD/ObjectReader.h
@@ -66,3 +66,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ObjectWriter.h b/include/mcld/LD/ObjectWriter.h
index d10bfdc..0c48723 100644
--- a/include/mcld/LD/ObjectWriter.h
+++ b/include/mcld/LD/ObjectWriter.h
@@ -36,3 +36,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/OutputSymbolTable.h b/include/mcld/LD/OutputSymbolTable.h
deleted file mode 100644
index 1494ab7..0000000
--- a/include/mcld/LD/OutputSymbolTable.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- OutputSymbolTable.h ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef OUTPUTSYMBOLTABLE_H
-#define OUTPUTSYMBOLTABLE_H
-#include <llvm/ADT/StringRef.h>
-#include "mcld/LD/SymbolTableIF.h"
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-namespace mcld
-{
-
-class LDSymbol;
-
-/** \class OutputSymbolTable
- *  \brief Output symbol table, for MCLDOutput.
- *
- *  \see
- */
-class OutputSymbolTable : public SymbolTableIF
-{
-  /* draft. */
-  friend class SymbolTableFactory;
-private:
-  OutputSymbolTable(StrSymPool &pStrSymPool,
-                    size_t pNumOfSymbols,
-                    StringTable &pEntireStringTable,
-                    StringTable &pDynamicStringTable);
-private:
-  virtual void doInsertSymbol(LDSymbol *);
-  virtual void doMerge(const SymbolTableIF &);
-};
-
-} // namespace of mcld
-
-#endif
diff --git a/include/mcld/LD/Relocation.h b/include/mcld/LD/Relocation.h
index 9f7a117..09ff6e4 100644
--- a/include/mcld/LD/Relocation.h
+++ b/include/mcld/LD/Relocation.h
@@ -112,3 +112,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/RelocationFactory.h b/include/mcld/LD/RelocationFactory.h
index 357c2d3..eed3eae 100644
--- a/include/mcld/LD/RelocationFactory.h
+++ b/include/mcld/LD/RelocationFactory.h
@@ -78,3 +78,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ResolveInfo.h b/include/mcld/LD/ResolveInfo.h
index 70e4f27..7b3cb27 100644
--- a/include/mcld/LD/ResolveInfo.h
+++ b/include/mcld/LD/ResolveInfo.h
@@ -55,7 +55,8 @@
     Section       = 3,
     File          = 4,
     CommonBlock   = 5,
-    ThreadLocal    = 6,
+    ThreadLocal   = 6,
+    IndirectFunc  = 10,
     LoProc        = 13,
     HiProc        = 15
   };
@@ -276,3 +277,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/ResolveInfoFactory.h b/include/mcld/LD/ResolveInfoFactory.h
index 13a26b6..fcadf48 100644
--- a/include/mcld/LD/ResolveInfoFactory.h
+++ b/include/mcld/LD/ResolveInfoFactory.h
@@ -34,3 +34,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/Resolver.h b/include/mcld/LD/Resolver.h
index 8596eeb..d506a2d 100644
--- a/include/mcld/LD/Resolver.h
+++ b/include/mcld/LD/Resolver.h
@@ -18,7 +18,7 @@
 {
 
 class ResolveInfo;
-class StrSymPool;
+class NamePool;
 
 /** \class Resolver
  *  \brief Resolver binds a symbol reference from one file to a symbol
@@ -51,49 +51,32 @@
   };
 
 public:
-  Resolver();
-
-  Resolver(const Resolver& pCopy);
-
   virtual ~Resolver();
 
   /// shouldOverride - Can resolver override the symbol pOld by the symbol pNew?
   /// @return the action should be taken.
   /// @param pOld the symbol which may be overridden.
   /// @param pNew the symbol which is used to replace pOld
-  virtual unsigned int resolve(ResolveInfo & __restrict__ pOld,
-                               const ResolveInfo & __restrict__ pNew,
-                               bool &pOverride) = 0;
+  virtual bool resolve(ResolveInfo & __restrict__ pOld,
+                       const ResolveInfo & __restrict__ pNew,
+                       bool &pOverride) const = 0;
 
   /// resolveAgain - Can override by derived classes.
   /// @return the pointer to resolved ResolveInfo
   /// @return is the symbol existent?
-  virtual void resolveAgain(StrSymPool& pStrSymPool,
+  virtual void resolveAgain(NamePool& pNamePool,
                               unsigned int pAction,
                               ResolveInfo& __restrict__ pOld,
                               const ResolveInfo& __restrict__ pNew,
-                              Result& pResult) {
+                              Result& pResult) const {
     pResult.info = NULL;
     pResult.existent = false;
     pResult.overriden = false;
   }
 
-  const std::string& mesg() const
-  { return m_Mesg; }
-
-  void clearMesg();
-
-  Resolver* clone() const {
-    return doClone();
-  }
-
-protected:
-  std::string m_Mesg;
-
-private:
-  virtual Resolver* doClone() const = 0;
 };
 
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/SectionMap.h b/include/mcld/LD/SectionMap.h
index 77e7e21..06ae02e 100644
--- a/include/mcld/LD/SectionMap.h
+++ b/include/mcld/LD/SectionMap.h
@@ -31,7 +31,6 @@
   struct Mapping {
     std::string inputSubStr;
     std::string outputStr;
-    uint64_t offset;
   };
 
   typedef std::vector<struct Mapping> SectionMappingTy;
@@ -49,8 +48,7 @@
 
   // add a mapping from input substr to output name and offset.
   bool push_back(const std::string& pInput,
-                 const std::string& pOutput,
-                 const uint64_t pOffset = 0);
+                 const std::string& pOutput);
 
   // find - return the iterator to the mapping
   iterator find(const std::string& pInput);
@@ -102,3 +100,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/SectionMerger.h b/include/mcld/LD/SectionMerger.h
index a1c2a10..40f1453 100644
--- a/include/mcld/LD/SectionMerger.h
+++ b/include/mcld/LD/SectionMerger.h
@@ -95,3 +95,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/StaticResolver.h b/include/mcld/LD/StaticResolver.h
index 6275c59..9fc6104 100644
--- a/include/mcld/LD/StaticResolver.h
+++ b/include/mcld/LD/StaticResolver.h
@@ -18,7 +18,7 @@
 namespace mcld
 {
 
-class StrSymPool;
+class NamePool;
 
 /** \class StaticResolver
  */
@@ -75,7 +75,7 @@
     w_D  = ResolveInfo::weak_flag   | ResolveInfo::regular_flag | ResolveInfo::define_flag,
     d_D  = ResolveInfo::global_flag | ResolveInfo::dynamic_flag | ResolveInfo::define_flag,
     wd_D = ResolveInfo::weak_flag   | ResolveInfo::dynamic_flag | ResolveInfo::define_flag,
-    C    = ResolveInfo::global_flag | ResolveInfo::regular_flag | ResolveInfo::common_flag,
+    C    = ResolveInfo::global_flag | ResolveInfo::regular_flag | ResolveInfo::common_flag, 
     w_C  = ResolveInfo::weak_flag   | ResolveInfo::regular_flag | ResolveInfo::common_flag,
     d_C  = ResolveInfo::global_flag | ResolveInfo::dynamic_flag | ResolveInfo::common_flag,
     wd_C = ResolveInfo::weak_flag   | ResolveInfo::dynamic_flag | ResolveInfo::common_flag,
@@ -103,23 +103,15 @@
   };
 
 public:
-  StaticResolver();
-
-  StaticResolver(const StaticResolver& pCopy);
-
   virtual ~StaticResolver();
 
   /// shouldOverride - Can resolver override the symbol pOld by the symbol pNew?
-  /// @return the action should be taken.
+  /// @return successfully resolved, return true; otherwise, return false.
   /// @param pOld the symbol which may be overridden.
   /// @param pNew the symbol which is used to replace pOld
-  virtual unsigned int resolve(ResolveInfo & __restrict__ pOld,
-                               const ResolveInfo & __restrict__ pNew,
-                               bool &pOverride);
-
-  StaticResolver* doClone() const {
-    return new StaticResolver(*this);
-  }
+  virtual bool resolve(ResolveInfo & __restrict__ pOld,
+                       const ResolveInfo & __restrict__ pNew,
+                       bool &pOverride) const;
 
 private:
   inline unsigned int getOrdinate(const ResolveInfo& pInfo) const {
@@ -142,3 +134,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/StringUnorderedMap.h b/include/mcld/LD/StringUnorderedMap.h
index 7453c9f..05788aa 100644
--- a/include/mcld/LD/StringUnorderedMap.h
+++ b/include/mcld/LD/StringUnorderedMap.h
@@ -222,3 +222,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/LD/SymbolTableFactory.h b/include/mcld/LD/SymbolTableFactory.h
deleted file mode 100644
index 6196603..0000000
--- a/include/mcld/LD/SymbolTableFactory.h
+++ /dev/null
@@ -1,72 +0,0 @@
-//===- SymbolTableFactory.h -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SYMBOL_TABLE_FACTORY_H
-#define MCLD_SYMBOL_TABLE_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include "mcld/LD/InputSymbolTable.h"
-#include "mcld/LD/OutputSymbolTable.h"
-
-namespace mcld
-{
-
-class StringTable;
-class StrSymPool;
-
-/** \class SymbolTableFactory
- *  \brief SymbolTableFactory manages SymbolTableIFs.
- *
- *  SymbolTableFactory is responsed for construction and destruction of
- *  SymbolTableIF. Since different MCLDFiles have different type of
- *  SymbolTableIF, SymbolTableFactory separates the construction of
- *  SymbolTableIF into createInputTable() and createOutputTable().
- *
- *  @see SymbolTableIF InputSymbolTable OutputSymbolTable
- */
-class SymbolTableFactory
-{
-public:
-  /// SymbolTableFactory - constructor
-  //  @param pNumOfSymbolTables is the most appropriate number of created
-  //  symbol tables.
-  //  @param pStorage the real storage of created symbols
-  explicit SymbolTableFactory(size_t pNumOfSymbolTables,
-                              StrSymPool& pStrSymPool);
-  /// ~SymbolTableFactory - destructor
-  //  destructor destroys all created symbol tables.
-  ~SymbolTableFactory();
-
-  /// createInputTable - create a symbol table for an input file
-  //  @param pEntireStringTable the string table of created Symbols.
-  //  @param pDynamicStringTable the string table of created Dynamic Symbols.
-  //  @param pReserve Created symbol table must reserve pReserve number of
-  //  storages of symbol for creating symbols.
-  SymbolTableIF *createInputTable(StringTable &pEntireStringTable,
-                                  StringTable &pDynamicStringTable,
-                                  size_t pReserve=256);
-
-  /// createOutputTable - create a symbol table for an output file
-  //  @param pEntireStringTable the string table of created Symbols.
-  //  @param pDynamicStringTable the string table of created Dynamic Symbols.
-  //  @param pReserve Created symbol table must reserve pReserve number of
-  //  storages of symbol for creating symbols.
-  SymbolTableIF *createOutputTable(StringTable &pEntireStringTable,
-                                   StringTable &pDynamicStringTable,
-                                   size_t pReserve=256);
-private:
-  StrSymPool &m_StrSymPool;
-  GCFactory<InputSymbolTable, 0> m_InputFactory;
-  GCFactory<OutputSymbolTable, 0> m_OutputFactory;
-
-};
-
-} // namespace of mcld
-
-#endif
diff --git a/include/mcld/LD/TextDiagnosticPrinter.h b/include/mcld/LD/TextDiagnosticPrinter.h
new file mode 100644
index 0000000..278c00f
--- /dev/null
+++ b/include/mcld/LD/TextDiagnosticPrinter.h
@@ -0,0 +1,50 @@
+//===- TextDiagnosticPrinter.h --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TEXT_DIAGNOSTIC_PRINTER_H
+#define MCLD_TEXT_DIAGNOSTIC_PRINTER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/LD/DiagnosticPrinter.h>
+#include <llvm/Support/raw_ostream.h>
+
+namespace mcld
+{
+
+class MCLDInfo;
+
+/** \class TextDiagnosticPrinter
+ *  \brief The plain, text-based DiagnosticPrinter.
+ */
+class TextDiagnosticPrinter : public DiagnosticPrinter
+{
+public:
+  TextDiagnosticPrinter(llvm::raw_ostream& pOStream, const MCLDInfo& pLDInfo);
+
+  virtual ~TextDiagnosticPrinter();
+
+  /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+  /// capturing it to a log as needed.
+  virtual void handleDiagnostic(DiagnosticEngine::Severity pSeverity,
+                                const Diagnostic& pInfo);
+
+  virtual void beginInput(const Input& pInput, const MCLDInfo& pLDInfo);
+
+  virtual void endInput();
+
+private:
+  llvm::raw_ostream& m_OStream;
+  const MCLDInfo& m_LDInfo;
+  const Input* m_pInput;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/MC/AttributeFactory.h b/include/mcld/MC/AttributeFactory.h
index eb4368b..0af1328 100644
--- a/include/mcld/MC/AttributeFactory.h
+++ b/include/mcld/MC/AttributeFactory.h
@@ -11,8 +11,8 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/MC/MCLDAttribute.h"
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/MC/MCLDAttribute.h>
 
 namespace mcld
 {
diff --git a/include/mcld/MC/ContextFactory.h b/include/mcld/MC/ContextFactory.h
index 1ae0d45..dde2627 100644
--- a/include/mcld/MC/ContextFactory.h
+++ b/include/mcld/MC/ContextFactory.h
@@ -38,6 +38,7 @@
   explicit ContextFactory(size_t pNum);
   ~ContextFactory();
 
+  LDContext* produce();
   LDContext* produce(const sys::fs::Path& pPath);
 };
 
diff --git a/include/mcld/MC/MCLDInputTree.h b/include/mcld/MC/InputTree.h
similarity index 76%
rename from include/mcld/MC/MCLDInputTree.h
rename to include/mcld/MC/InputTree.h
index 7d8050c..fa6ba8f 100644
--- a/include/mcld/MC/MCLDInputTree.h
+++ b/include/mcld/MC/InputTree.h
@@ -1,4 +1,4 @@
-//===- MCLDInputTree.h ----------------------------------------------------===//
+//===- InputTree.h --------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -90,13 +90,23 @@
   typedef BinaryTree<Input>::const_iterator const_iterator;
 
 public:
-  struct Connector {
-    virtual ~Connector() {}
+  /** \class Mover
+   *  \brief Mover provides the interface for moving iterator forward.
+   *
+   *  Mover is a function object (functor). @ref Mover::move moves
+   *  iterator forward in certain direction. @ref Mover::connect
+   *  connects two nodes of the given iterators togather.
+   */
+  struct Mover {
+    virtual ~Mover() {}
     virtual void connect(iterator& pFrom, const const_iterator& pTo) const = 0;
     virtual void move(iterator& pNode) const = 0;
   };
 
-  struct Succeeder : public Connector {
+  /** \class Succeeder
+   *  \brief class Succeeder moves the iterator afterward.
+   */
+  struct Succeeder : public Mover {
     virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
       proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
     }
@@ -106,7 +116,10 @@
     }
   };
 
-  struct Includer : public Connector {
+  /** \class Includer
+   *  \brief class Includer moves the iterator downward.
+   */
+  struct Includer : public Mover {
     virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
       proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
     }
@@ -130,38 +143,37 @@
   // -----  modify  ----- //
   /// insert - create a leaf node and merge it in the tree.
   //  This version of join determines the direction at run time.
-  //  @param position the parent node
-  //  @param value the value being pushed.
-  //  @param pConnector the direction of the connecting edge of the parent node.
+  //  @param pRoot  position the parent node
+  //  @param pMover the direction of the connecting edge of the parent node.
   template<size_t DIRECT>
-  InputTree& insert(iterator pPosition,
+  InputTree& insert(iterator pRoot,
                     const std::string& pNamespec,
                     const sys::fs::Path& pPath,
                     unsigned int pType = Input::Unknown);
 
   template<size_t DIRECT>
-  InputTree& enterGroup(iterator pPosition);
+  InputTree& enterGroup(iterator pRoot);
 
   template<size_t DIRECT>
-  InputTree& insert(iterator pPosition,
+  InputTree& insert(iterator pRoot,
                     const Input& pInput);
 
-  InputTree& merge(iterator pPosition, 
-                   const Connector& pConnector,
+  InputTree& merge(iterator pRoot, 
+                   const Mover& pMover,
                    InputTree& pTree);
 
-  InputTree& insert(iterator pPosition,
-                    const Connector& pConnector,
+  InputTree& insert(iterator pRoot,
+                    const Mover& pMover,
                     const std::string& pNamespec,
                     const sys::fs::Path& pPath,
                     unsigned int pType = Input::Unknown);
 
-  InputTree& insert(iterator pPosition,
-                    const Connector& pConnector,
+  InputTree& insert(iterator pRoot,
+                    const Mover& pMover,
                     const Input& pInput);
 
-  InputTree& enterGroup(iterator pPosition,
-                        const Connector& pConnector);
+  InputTree& enterGroup(iterator pRoot,
+                        const Mover& pMover);
 
   // -----  observers  ----- //
   unsigned int numOfInputs() const
@@ -188,47 +200,47 @@
 // template member functions
 template<size_t DIRECT>
 mcld::InputTree&
-mcld::InputTree::insert(mcld::InputTree::iterator pPosition,
+mcld::InputTree::insert(mcld::InputTree::iterator 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 (pPosition.isRoot())
-    proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
+  if (pRoot.isRoot())
+    proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
         const_cast<const node_type*>(node));
   else
-    proxy::hook<DIRECT>(pPosition.m_pNode,
+    proxy::hook<DIRECT>(pRoot.m_pNode,
         const_cast<const node_type*>(node));
   return *this;
 }
 
 template<size_t DIRECT>
 mcld::InputTree&
-mcld::InputTree::enterGroup(mcld::InputTree::iterator pPosition)
+mcld::InputTree::enterGroup(mcld::InputTree::iterator pRoot)
 {
   BinTreeTy::node_type* node = createNode(); 
-  if (pPosition.isRoot())
-    proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
+  if (pRoot.isRoot())
+    proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
         const_cast<const node_type*>(node));
   else
-    proxy::hook<DIRECT>(pPosition.m_pNode,
+    proxy::hook<DIRECT>(pRoot.m_pNode,
         const_cast<const node_type*>(node));
   return *this;
 }
 
 template<size_t DIRECT>
-mcld::InputTree& mcld::InputTree::insert(mcld::InputTree::iterator pPosition,
+mcld::InputTree& mcld::InputTree::insert(mcld::InputTree::iterator pRoot,
 	                                 const mcld::Input& pInput)
 {
   BinTreeTy::node_type* node = createNode();
   node->data = const_cast<mcld::Input*>(&pInput);
-  if (pPosition.isRoot())
-    proxy::hook<TreeIteratorBase::Leftward>(pPosition.m_pNode,
+  if (pRoot.isRoot())
+    proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
                                          const_cast<const node_type*>(node));
   else
-    proxy::hook<DIRECT>(pPosition.m_pNode,
+    proxy::hook<DIRECT>(pRoot.m_pNode,
                         const_cast<const node_type*>(node));
   return *this;
 }
diff --git a/include/mcld/MC/MCDataFragment.h b/include/mcld/MC/MCDataFragment.h
index 330c9be..63ae497 100644
--- a/include/mcld/MC/MCDataFragment.h
+++ b/include/mcld/MC/MCDataFragment.h
@@ -21,9 +21,6 @@
 
 /** \class MCDataFragment
  *  \brief MCDataFragment for mcld
- *
- *  \see
- *  \author Diana Chen <diana.chen@mediatek.com>
  */
 class MCDataFragment : public  llvm::MCFragment
 {
@@ -33,7 +30,7 @@
 
   ///  m_pFragment - llvm MCDataFragment for this MCDataFragment
   llvm::MCDataFragment* m_pFragment;
- 
+
   /// m_Relocation - The list of relocations in this fragment
   RelocationsType m_Relocations;
 
@@ -49,14 +46,14 @@
     setLayoutOrder( pFragment.getLayoutOrder());
   }
   ~MCDataFragment(){}
-   
+
   // ------ observers ------//
   llvm::SmallString<32> &getContents() { return m_pFragment->getContents();  }
   const llvm::SmallString<32> &getContents() const { return m_pFragment->getContents();  }
 
   // relocation access
   void addRelocation(Relocation &pReloc){  m_Relocations.push_back(&pReloc); }
-  
+
   RelocationsType &getRelocations() { return m_Relocations; }
   const RelocationsType &getRelcoations() const { return m_Relocations; }
 
@@ -73,10 +70,10 @@
     return pF->getKind() == llvm::MCFragment::FT_Data;
   }
   static bool classof(const MCDataFragment *) { return true; }
-  
+
   // overwrite parent method
-  FragmentType getKind() const { return m_pFragment->getKind(); } 
-  
+  FragmentType getKind() const { return m_pFragment->getKind(); }
+
 };
 
 } // namespace of mcld
diff --git a/include/mcld/MC/MCInstFragment.h b/include/mcld/MC/MCInstFragment.h
index 8625c42..6dbbc85 100644
--- a/include/mcld/MC/MCInstFragment.h
+++ b/include/mcld/MC/MCInstFragment.h
@@ -23,9 +23,6 @@
 
 /** \class MCInstFragment
  *  \brief MCInstFragment for mcld
- *
- *  \see
- *  \author Diana Chen <diana.chen@mediatek.com>
  */
 class MCInstFragment : public  llvm::MCFragment
 {
@@ -35,10 +32,10 @@
 
   ///  m_pFragment - llvm MCInstFragment for this MCInstFragment
   llvm::MCInstFragment* m_pFragment;
-  
+
   /// m_Relocation - The list of relocations in this fragment
   RelocationsType m_Relocations;
-  
+
 public:
   typedef RelocationsType::const_iterator const_relocation_iterator;
   typedef RelocationsType::iterator relocation_iterator;
@@ -51,7 +48,7 @@
     setLayoutOrder( pFragment.getLayoutOrder());
   }
   ~MCInstFragment(){}
-   
+
   // ------ observers ------//
   llvm::SmallVectorImpl<char> &getCode() { return m_pFragment->getCode(); }
   const llvm::SmallVectorImpl<char> &getCode() const { return m_pFragment->getCode(); }
@@ -60,13 +57,13 @@
 
   llvm::MCInst &getInst() { return m_pFragment->getInst(); }
   const llvm::MCInst &getInst() const { return m_pFragment->getInst(); }
-  
+
   // ----- modifiers ------//
   void setInst(llvm::MCInst pValue) { m_pFragment->setInst(pValue); }
 
   // relocation access
   void addRelocation(Relocation &pReloc){  m_Relocations.push_back(&pReloc); }
-  
+
   RelocationsType &getRelocations() { return m_Relocations; }
   const RelocationsType &getRelcoations() const { return m_Relocations; }
 
@@ -83,9 +80,9 @@
     return pF->getKind() == llvm::MCFragment::FT_Inst;
   }
   static bool classof(const MCInstFragment *) { return true; }
-  
+
   // overwrite parent method
-  FragmentType getKind() const { return m_pFragment->getKind(); } 
+  FragmentType getKind() const { return m_pFragment->getKind(); }
 
 };
 
diff --git a/include/mcld/MC/MCLDAttribute.h b/include/mcld/MC/MCLDAttribute.h
index 829cf61..f7f9f97 100644
--- a/include/mcld/MC/MCLDAttribute.h
+++ b/include/mcld/MC/MCLDAttribute.h
@@ -161,7 +161,7 @@
   bool isStaticSystem() const
   { return m_Static; }
   
-  bool isLegal(const Attribute& pAttr, std::string& pErrMesg) const;
+  bool isLegal(const Attribute& pAttr) const;
 };
 
 /** \class AttributeProxy
diff --git a/include/mcld/MC/MCLDDriver.h b/include/mcld/MC/MCLDDriver.h
index b4a7288..ec8acf5 100644
--- a/include/mcld/MC/MCLDDriver.h
+++ b/include/mcld/MC/MCLDDriver.h
@@ -19,12 +19,14 @@
 #endif
 
 #include <mcld/LD/SectionMap.h>
+
 namespace mcld
 {
 
 class MCLinker;
 class MCLDInfo;
 class TargetLDBackend;
+class MemoryAreaFactory;
 
 //===----------------------------------------------------------------------===//
 /// MCLDDriver - MCLDDriver prepares parameters for MCLinker.
@@ -35,6 +37,13 @@
   MCLDDriver(MCLDInfo& pLDInfo, TargetLDBackend& pLDBackend);
   ~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();
 
@@ -44,10 +53,6 @@
   ///  - check every Input has a correct Attribute
   bool linkable() const;
 
-  /// initMCLinker - initialize MCLinker
-  ///  Connect all components in MCLinker
-  bool initMCLinker();
-
   /// readSections - read all input section headers
   bool readSections();
 
@@ -95,7 +100,7 @@
   /// Create relocation section, asking TargetLDBackend to
   /// read the relocation information into RelocationEntry
   /// and push_back into the relocation section
-  bool relocate();
+  bool relocation();
 
   /// finalizeSymbolValue - finalize the symbol value
   bool finalizeSymbolValue();
@@ -106,6 +111,18 @@
   /// 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;
diff --git a/include/mcld/MC/MCLDFile.h b/include/mcld/MC/MCLDFile.h
index 30cac7e..f77fe82 100644
--- a/include/mcld/MC/MCLDFile.h
+++ b/include/mcld/MC/MCLDFile.h
@@ -50,7 +50,8 @@
     DynObj,
     CoreFile,
     Script,
-    Archive
+    Archive,
+    External
   };
 
 public:
diff --git a/include/mcld/MC/MCLDInfo.h b/include/mcld/MC/MCLDInfo.h
index 15e70ff..d76fff4 100644
--- a/include/mcld/MC/MCLDInfo.h
+++ b/include/mcld/MC/MCLDInfo.h
@@ -15,23 +15,24 @@
 #include <llvm/ADT/Triple.h>
 
 #include <mcld/Support/FileSystem.h>
-#include <mcld/Support/MemoryAreaFactory.h>
 #include <mcld/MC/MCLDOutput.h>
 #include <mcld/MC/MCLDOptions.h>
-#include <mcld/MC/MCLDInputTree.h>
+#include <mcld/MC/InputTree.h>
 #include <mcld/MC/AttributeFactory.h>
 #include <mcld/MC/ContextFactory.h>
-#include <mcld/LD/StrSymPool.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.
+ *   options()        - the general options
+ *   scripts()        - the script options
  *   inputs()         - the tree of inputs
  *   bitcode()        - the bitcode being linked
  *   output()         - the output file
@@ -55,6 +56,12 @@
   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;
@@ -90,33 +97,25 @@
   const ContextFactory& contextFactory() const
   { return *m_pCntxtFactory; }
 
-  MemoryAreaFactory& memAreaFactory()
-  { return *m_pMemAreaFactory; }
-
-  const MemoryAreaFactory& memAreaFactory() const
-  { return *m_pMemAreaFactory; }
-
   const llvm::Triple& triple() const
   { return m_Triple; }
 
   static const char* version();
 
-  void setNamePool(StrSymPool& pPool)
-  { m_pStrSymPool = &pPool; }
-
-  StrSymPool& getStrSymPool() {
-    assert(NULL != m_pStrSymPool);
-    return *m_pStrSymPool;
+  NamePool& getNamePool() {
+    assert(NULL != m_pNamePool);
+    return *m_pNamePool;
   }
 
-  const StrSymPool& getStrSymPool() const {
-    assert(NULL != m_pStrSymPool);
-    return *m_pStrSymPool;
+  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;
@@ -126,10 +125,10 @@
   InputFactory *m_pInputFactory;
   AttributeFactory *m_pAttrFactory;
   ContextFactory *m_pCntxtFactory;
-  MemoryAreaFactory *m_pMemAreaFactory;
 
   // -----  string and symbols  ----- //
-  StrSymPool* m_pStrSymPool;
+  Resolver* m_pResolver;
+  NamePool* m_pNamePool;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/MC/MCLDInput.h b/include/mcld/MC/MCLDInput.h
index 097b8f6..2f1198c 100644
--- a/include/mcld/MC/MCLDInput.h
+++ b/include/mcld/MC/MCLDInput.h
@@ -40,7 +40,8 @@
     Object = MCLDFile::Object,
     DynObj = MCLDFile::DynObj,
     Archive = MCLDFile::Archive,
-    Script = MCLDFile::Script
+    Script = MCLDFile::Script,
+    External = MCLDFile::External
   };
 
 private:
diff --git a/include/mcld/MC/MCLDOptions.h b/include/mcld/MC/MCLDOptions.h
index 06097aa..ad857cb 100644
--- a/include/mcld/MC/MCLDOptions.h
+++ b/include/mcld/MC/MCLDOptions.h
@@ -11,9 +11,14 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include "mcld/Support/RealPath.h"
-#include "mcld/MC/SearchDirs.h"
-#include "mcld/Support/FileSystem.h"
+#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
 {
@@ -22,8 +27,25 @@
 /** \class ScriptOptions
  *
  */
-class ScriptOption
+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
@@ -35,6 +57,9 @@
 class GeneralOptions
 {
 public:
+  GeneralOptions();
+  ~GeneralOptions();
+
   /// default link script
   bool hasDefaultLDScript() const;
   const char* defaultLDScript() const;
@@ -60,18 +85,24 @@
   bool trace() const
   { return m_bTrace; }
 
-  void setVerbose(bool pVerbose = true)
-  { m_bVerbose = pVerbose; }
-
-  bool verbose() const
-  { return m_bVerbose; }
-
   void setBsymbolic(bool pBsymbolic = false)
   { m_Bsymbolic = pBsymbolic; }
 
   bool Bsymbolic() const
   { return m_Bsymbolic; }
 
+  void setPIE(bool pPIE = true)
+  { m_bPIE = pPIE; }
+
+  bool isPIE() const
+  { return m_bPIE; }
+
+  void setBgroup(bool pBgroup = false)
+  { m_Bgroup = pBgroup; }
+
+  bool Bgroup() const
+  { return m_Bgroup; }
+
   bool hasEntry() const
   { return !m_Entry.empty(); }
 
@@ -81,15 +112,155 @@
   const std::string& entry() const
   { return m_Entry; }
 
+  void setDyld(const std::string& pDyld)
+  { m_Dyld = pDyld; }
+
+  const std::string& dyld() const
+  { return m_Dyld; }
+
+  bool hasDyld() const
+  { return !m_Dyld.empty(); }
+
+  void setAllowShlibUndefined(bool pEnabled = true)
+  { m_bAllowShlibUndefined = pEnabled; }
+
+  bool isAllowShlibUndefined() const
+  { return m_bAllowShlibUndefined; }
+
+  void setVerbose(int8_t pVerbose = -1)
+  { m_Verbose = pVerbose; }
+
+  int8_t verbose() const
+  { return m_Verbose; }
+
+  void setMaxErrorNum(int16_t pNum)
+  { m_MaxErrorNum = pNum; }
+
+  int16_t maxErrorNum() const
+  { return m_MaxErrorNum; }
+
+  void setMaxWarnNum(int16_t pNum)
+  { m_MaxWarnNum = pNum; }
+
+  int16_t maxWarnNum() const
+  { return m_MaxWarnNum; }
+
+  void setColor(bool pEnabled = true)
+  { m_bColor = pEnabled; }
+
+  bool color() const
+  { return m_bColor; }
+
+  void setNoUndefined(bool pEnable = false)
+  { m_bNoUndefined = pEnable; }
+
+  void setMulDefs(bool pEnable = false)
+  { m_bMulDefs = pEnable; }
+
+  void setEhFrameHdr(bool pEnable = true)
+  { m_bCreateEhFrameHdr = pEnable; }
+
+  ///  -----  the -z options  -----  ///
+  void addZOption(const mcld::ZOption& pOption);
+
+  bool hasCombReloc() const
+  { return m_bCombReloc; }
+
+  bool isNoUndefined() const
+  { return m_bNoUndefined; }
+
+  bool hasStackSet() const
+  { return (Unknown != m_ExecStack); }
+
+  bool hasExecStack() const
+  { return (YES == m_ExecStack); }
+
+  bool hasInitFirst() const
+  { return m_bInitFirst; }
+
+  bool hasInterPose() const
+  { return m_bInterPose; }
+
+  bool hasLoadFltr() const
+  { return m_bLoadFltr; }
+
+  bool hasMulDefs() const
+  { return m_bMulDefs; }
+
+  bool hasNoCopyReloc() const
+  { return m_bNoCopyReloc; }
+
+  bool hasNoDefaultLib() const
+  { return m_bNoDefaultLib; }
+
+  bool hasNoDelete() const
+  { return m_bNoDelete; }
+
+  bool hasNoDLOpen() const
+  { return m_bNoDLOpen; }
+
+  bool hasNoDump() const
+  { return m_bNoDump; }
+
+  bool hasRelro() const
+  { return m_bRelro; }
+
+  bool hasNow() const
+  { return m_bNow; }
+
+  bool hasOrigin() const
+  { return m_bOrigin; }
+
+  uint64_t commPageSize() const
+  { return m_CommPageSize; }
+
+  uint64_t maxPageSize() const
+  { return m_MaxPageSize; }
+
+  bool hasEhFrameHdr() const
+  { return m_bCreateEhFrameHdr; }
+
+private:
+  enum status {
+    YES,
+    NO,
+    Unknown
+  };
+
 private:
   Input* m_pDefaultBitcode;
   std::string m_DefaultLDScript;
   sys::fs::RealPath m_Sysroot;
   SearchDirs m_SearchDirs;
-  bool m_bTrace;
-  bool m_bVerbose;
-  bool m_Bsymbolic;
   std::string m_Entry;
+  std::string m_Dyld;
+  int8_t m_Verbose;            // --verbose[=0,1,2]
+  uint16_t m_MaxErrorNum;      // --error-limit=N
+  uint16_t m_MaxWarnNum;       // --warning-limit=N
+  status m_ExecStack;          // execstack, noexecstack
+  uint64_t m_CommPageSize;     // common-page-size=value
+  uint64_t m_MaxPageSize;      // max-page-size=value
+  bool m_bCombReloc     : 1;   // combreloc, nocombreloc
+  bool m_bNoUndefined   : 1;   // defs, --no-undefined
+  bool m_bInitFirst     : 1;   // initfirst
+  bool m_bInterPose     : 1;   // interpose
+  bool m_bLoadFltr      : 1;   // loadfltr
+  bool m_bMulDefs       : 1;   // muldefs
+  bool m_bNoCopyReloc   : 1;   // nocopyreloc
+  bool m_bNoDefaultLib  : 1;   // nodefaultlib
+  bool m_bNoDelete      : 1;   // nodelete
+  bool m_bNoDLOpen      : 1;   // nodlopen
+  bool m_bNoDump        : 1;   // nodump
+  bool m_bRelro         : 1;   // relro, norelro
+  bool m_bNow           : 1;   // lazy, now
+  bool m_bOrigin        : 1;   // origin
+  bool m_bTrace         : 1;   // --trace
+  bool m_Bsymbolic      : 1;   // --Bsymbolic
+  bool m_Bgroup         : 1;
+  bool m_bPIE           : 1;
+  bool m_bColor         : 1;   // --color[=true,false,auto]
+  bool m_bAllowShlibUndefined : 1; // --[no-]allow-shlib-undefined and
+  bool m_bCreateEhFrameHdr : 1;    // --eh-frame-hdr
 };
 
 } // namespace of mcld
diff --git a/include/mcld/MC/MCLinker.h b/include/mcld/MC/MCLinker.h
index 8de7148..29e6a46 100644
--- a/include/mcld/MC/MCLinker.h
+++ b/include/mcld/MC/MCLinker.h
@@ -19,7 +19,6 @@
 
 #include <llvm/ADT/ilist.h>
 #include <llvm/MC/MCAssembler.h>
-#include <mcld/LD/StrSymPool.h>
 #include <mcld/LD/StaticResolver.h>
 #include <mcld/LD/LDSectionFactory.h>
 #include <mcld/LD/LDFileFormat.h>
@@ -42,6 +41,8 @@
 class LDSectionFactory;
 class SectionMap;
 class Output;
+class EhFrame;
+class EhFrameHdr;
 
 /** \class MCLinker
  *  \brief MCLinker provides a pass to link object files.
@@ -64,9 +65,8 @@
 public:
   MCLinker(TargetLDBackend& pBackend,
            MCLDInfo& pLDInfo,
-           LDContext& pContext,
-           SectionMap& pSectionMap,
-           const Resolver& pResolver = StaticResolver());
+           SectionMap& pSectionMap);
+
   ~MCLinker();
 
   // ----- about symbols  ----- //
@@ -111,12 +111,6 @@
                          MCFragmentRef* pFragmentRef,
                          ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
 
-  /// mergeSymbolTable - merge the symbol table and resolve symbols.
-  ///   Since in current design, MCLinker resolves symbols when reading symbol
-  ///   tables, this function do nothing.
-  bool mergeSymbolTable(Input& pInput)
-  { return true; }
-
   bool finalizeSymbols();
 
   // -----  sections  ----- //
@@ -144,7 +138,13 @@
   /// getOrCreateSectData - for reader to map and perform section merging immediately
   llvm::MCSectionData& getOrCreateSectData(LDSection& pSection);
 
-  // -----  relocations ----- //
+  // -----  eh_frame sections  ----- //
+  /// addEhFrame - add an exception handling section
+  /// @param pSection - the input section
+  /// @param pArea - the memory area which pSection is within.
+  uint64_t addEhFrame(LDSection& pSection, MemoryArea& pArea);
+
+  // -----  relocations  ----- //
   /// addRelocation - add a relocation entry in MCLinker (only for object file)
   /// @param pType - the type of the relocation
   /// @param pResolveInfo - the symbol should be the symbol in the input file. MCLinker
@@ -155,6 +155,7 @@
                             const LDSymbol& pSym,
                             ResolveInfo& pResolveInfo,
                             MCFragmentRef& pFragmentRef,
+                            const LDSection& pSection,
                             Relocation::Address pAddend = 0);
 
   /// applyRelocations - apply all relocation enties.
@@ -165,6 +166,8 @@
   void syncRelocationResult();
 
   // -----  layout  ----- //
+  void initSectionMap();
+
   Layout& getLayout()
   { return m_Layout; }
 
@@ -182,10 +185,10 @@
 
   // -----  capacity  ----- //
   MCLDInfo& getLDInfo()
-  { return m_Info; }
+  { return m_LDInfo; }
 
   const MCLDInfo& getLDInfo() const
-  { return m_Info; }
+  { return m_LDInfo; }
 
 private:
   LDSymbol* defineSymbolForcefully(const llvm::StringRef& pName,
@@ -257,18 +260,15 @@
 
 private:
   TargetLDBackend& m_Backend;
-  MCLDInfo& m_Info;
-  LDContext& m_Output;
+  MCLDInfo& m_LDInfo;
   SectionMap& m_SectionMap;
   LDSymbolFactory m_LDSymbolFactory;
   LDSectionFactory m_LDSectHdrFactory;
   LDSectionDataFactory m_LDSectDataFactory;
-  SectionMerger m_SectionMerger;
-  StrSymPool m_StrSymPool;
+  SectionMerger* m_pSectionMerger;
   Layout m_Layout;
   RelocationListType m_RelocationList;
   SymbolCategory m_OutputSymbols;
-
 };
 
 #include "MCLinker.tcc"
diff --git a/include/mcld/MC/MCLinker.tcc b/include/mcld/MC/MCLinker.tcc
index 19a83ec..d6c5744 100644
--- a/include/mcld/MC/MCLinker.tcc
+++ b/include/mcld/MC/MCLinker.tcc
@@ -18,10 +18,19 @@
                               MCFragmentRef* pFragmentRef,
                               ResolveInfo::Visibility pVisibility)
 {
-  // These if/else should be optimized by compiler.
-  // This function is defined for clarity.
+  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
+                                = getLDInfo().scripts().renameMap().find(pName);
+    if (renameSym != getLDInfo().scripts().renameMap().end())
+      symbol_name = renameSym.getEntry()->value();
+  }
+
   if (FROM == Input::DynObj)
-    return addSymbolFromDynObj(pName,
+    return addSymbolFromDynObj(symbol_name,
                                pType,
                                pDesc,
                                pBinding,
@@ -31,7 +40,7 @@
                                pVisibility);
 
   if (FROM == Input::Object)
-    return addSymbolFromObject(pName,
+    return addSymbolFromObject(symbol_name,
                                pType,
                                pDesc,
                                pBinding,
diff --git a/include/mcld/MC/SearchDirs.h b/include/mcld/MC/SearchDirs.h
index 1a22cf4..e0cf169 100644
--- a/include/mcld/MC/SearchDirs.h
+++ b/include/mcld/MC/SearchDirs.h
@@ -47,8 +47,9 @@
   SearchDirs();
   ~SearchDirs();
 
-  /// find - give a namespec, return a real path of the shared object.
-  sys::fs::Path* find(const std::string& pNamespec, mcld::Input::Type pType);
+  // find - give a namespec, return a real path of the shared object.
+  //
+  sys::fs::Path* find(const std::string& pNamespec, mcld::Input::Type pPreferType);
 
   // -----  iterators  ----- //
   iterator begin()
diff --git a/include/mcld/MC/ZOption.h b/include/mcld/MC/ZOption.h
new file mode 100644
index 0000000..e451734
--- /dev/null
+++ b/include/mcld/MC/ZOption.h
@@ -0,0 +1,75 @@
+//===- ZOption.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ZOPTION_H
+#define MCLD_ZOPTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/Support/DataTypes.h>
+
+namespace mcld
+{
+
+/** \class ZOption
+ *  \brief The -z options for GNU ld compatibility.
+ */
+class ZOption
+{
+public:
+  enum Kind {
+    CombReloc,
+    NoCombReloc,
+    Defs,
+    ExecStack,
+    NoExecStack,
+    InitFirst,
+    InterPose,
+    LoadFltr,
+    MulDefs,
+    NoCopyReloc,
+    NoDefaultLib,
+    NoDelete,
+    NoDLOpen,
+    NoDump,
+    Relro,
+    NoRelro,
+    Lazy,
+    Now,
+    Origin,
+    CommPageSize,
+    MaxPageSize,
+    Unknown
+  };
+
+public:
+  ZOption();
+
+  ~ZOption();
+
+  Kind kind() const
+  { return m_Kind; }
+
+  uint64_t pageSize() const
+  { return m_PageSize; }
+
+  void setKind(Kind pKind)
+  { m_Kind = pKind; }
+
+  void setPageSize(uint64_t pPageSize)
+  { m_PageSize = pPageSize; }
+
+private:
+  Kind m_Kind;
+  uint64_t m_PageSize;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/Allocators.h b/include/mcld/Support/Allocators.h
index 426cbc3..de6edec 100644
--- a/include/mcld/Support/Allocators.h
+++ b/include/mcld/Support/Allocators.h
@@ -15,7 +15,6 @@
 #include "mcld/ADT/Uncopyable.h"
 #include "mcld/ADT/TypeTraits.h"
 #include "mcld/LD/LDContext.h"
-
 #include <cstddef>
 #include <cstdlib>
 
@@ -438,3 +437,4 @@
 } // namespace mcld
 
 #endif
+
diff --git a/include/mcld/Support/CommandLine.h b/include/mcld/Support/CommandLine.h
index e52c4a3..6a90309 100644
--- a/include/mcld/Support/CommandLine.h
+++ b/include/mcld/Support/CommandLine.h
@@ -13,8 +13,9 @@
 #endif
 #include <llvm/ADT/StringRef.h>
 #include <llvm/Support/CommandLine.h>
-#include "mcld/Support/FileSystem.h"
-#include "mcld/MC/MCLDDirectory.h"
+#include <mcld/Support/FileSystem.h>
+#include <mcld/MC/MCLDDirectory.h>
+#include <mcld/MC/ZOption.h>
 
 //--------------------------------------------------
 // parser<mcld::sys::fs::Path>
@@ -56,6 +57,23 @@
   virtual void anchor();
 };
 
+//--------------------------------------------------
+// parser<mcld::ZOption>
+//
+template<>
+class parser<mcld::ZOption> : public llvm::cl::basic_parser<mcld::ZOption>
+{
+public:
+  bool parse(Option &O, StringRef ArgName, StringRef Arg, mcld::ZOption &Val);
+
+  virtual const char *getValueName() const { return "z-option"; }
+  void printOptionDiff(const Option &O,
+                       const mcld::ZOption &V,
+                       OptVal Default,
+                       size_t GlobalWidth) const;
+  virtual void anchor();
+};
+
 } // namespace of cl
 } // namespace of llvm
 
diff --git a/include/mcld/Support/Directory.h b/include/mcld/Support/Directory.h
index 117d51d..c52dce1 100644
--- a/include/mcld/Support/Directory.h
+++ b/include/mcld/Support/Directory.h
@@ -12,13 +12,12 @@
 #include <gtest.h>
 #endif
 
-#include <cstddef>
-
 #include "mcld/ADT/TypeTraits.h"
 #include "mcld/Support/FileSystem.h"
 #include "mcld/Support/Path.h"
 #include "mcld/Support/PathCache.h"
 #include <llvm/Support/Allocator.h>
+#include <cstddef>
 
 
 namespace mcld {
diff --git a/include/mcld/Support/FileHandle.h b/include/mcld/Support/FileHandle.h
new file mode 100644
index 0000000..f6881c3
--- /dev/null
+++ b/include/mcld/Support/FileHandle.h
@@ -0,0 +1,141 @@
+//===- FileHandle.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_FILE_HANDLE_H
+#define MCLD_FILE_HANDLE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Support/Path.h>
+#include <mcld/ADT/Flags.h>
+#include <errno.h>
+
+namespace mcld
+{
+
+/** \class FileHandle
+ *  \brief FileHandle class provides an interface for reading from and writing
+ *  to files.
+ *
+ *  Operators of FileHandle should neither throw exceptions nor call expressive
+ *  diagnostic output.
+ */
+class FileHandle
+{
+public:
+  enum IOState
+  {
+    GoodBit    = 0,       // no error
+    BadBit     = 1L << 0, // error due to the inappropriate operation
+    EOFBit     = 1L << 1, // reached End-Of-File
+    FailBit    = 1L << 2, // internal logic fail
+    IOStateEnd = 1L << 16
+  };
+
+  enum OpenModeEnum
+  {
+    NotOpen   = 0x00,
+    ReadOnly  = 0x01,
+    WriteOnly = 0x02,
+    ReadWrite = ReadOnly | WriteOnly,
+    Append    = 0x04,
+    Create    = 0x08,
+    Truncate  = 0x10,
+    Unknown   = 0xFF
+  };
+
+  typedef Flags<OpenModeEnum> OpenMode;
+
+  enum PermissionEnum
+  {
+    ReadOwner   = 0x0400,
+    WriteOwner  = 0x0200,
+    ExeOwner    = 0x0100,
+    ReadGroup   = 0x0040,
+    WriteGroup  = 0x0020,
+    ExeGroup    = 0x0010,
+    ReadOther   = 0x0004,
+    WriteOther  = 0x0002,
+    ExeOther    = 0x0001
+  };
+
+  typedef Flags<PermissionEnum> Permission;
+
+public:
+  FileHandle();
+
+  ~FileHandle();
+
+  bool open(const sys::fs::Path& pPath,
+            OpenMode pMode);
+
+  bool open(const sys::fs::Path& pPath,
+            OpenMode pMode,
+            Permission pPerm);
+
+  bool delegate(int pFD, OpenMode pMode = Unknown);
+
+  bool close();
+
+  void setState(IOState pState);
+
+  void cleanState(IOState pState = GoodBit);
+
+  // truncate - truncate the file up to the pSize.
+  bool truncate(size_t pSize);
+
+  bool read(void* pMemBuffer, size_t pStartOffset, size_t pLength);
+
+  bool write(const void* pMemBuffer, size_t pStartOffset, size_t pLength);
+
+  bool mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength);
+
+  bool munmap(void* pMemBuffer, size_t pLength);
+
+  // -----  observers  ----- //
+  const sys::fs::Path& path() const
+  { return m_Path; }
+
+  size_t size() const
+  { return m_Size; }
+
+  int handler() const
+  { return m_Handler; }
+
+  uint16_t rdstate() const
+  { return m_State; }
+
+  bool isOpened() const;
+
+  bool isGood() const;
+
+  bool isBad() const;
+
+  bool isFailed() const;
+
+  bool isReadable() const;
+
+  bool isWritable() const;
+
+  bool isReadWrite() const;
+
+  int error() const
+  { return errno; }
+
+private:
+  sys::fs::Path m_Path;
+  int m_Handler;
+  unsigned int m_Size;
+  uint16_t m_State;
+  OpenMode m_OpenMode;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/FileSystem.h b/include/mcld/Support/FileSystem.h
index 28dc563..230fa9b 100644
--- a/include/mcld/Support/FileSystem.h
+++ b/include/mcld/Support/FileSystem.h
@@ -18,12 +18,14 @@
 #endif
 
 #include "mcld/Support/PathCache.h"
+#include <mcld/Config/Config.h>
 #include <string>
 #include <iosfwd>
 #include <locale>
 
 namespace mcld {
 namespace sys {
+
 namespace fs {
 
 enum FileType
@@ -89,8 +91,6 @@
 namespace detail
 {
 
-typedef unsigned char* Address;
-typedef off_t Offset;
 extern std::string static_library_extension;
 extern std::string shared_library_extension;
 extern std::string executable_extension;
@@ -106,9 +106,12 @@
 void open_dir(Directory& pDir);
 void close_dir(Directory& pDir);
 void get_pwd(std::string& pPWD);
-size_t pread(int pFD, Address pBuf, size_t pCount, off_t pOffset);
-size_t pwrite(int pFD, const Address pBuf, size_t pCount, off_t pOffset);
-char *strerror(int pErrnum);
+
+int open(const Path& pPath, int pOFlag);
+int open(const Path& pPath, int pOFlag, int pPermission);
+ssize_t pread(int pFD, void* pBuf, size_t pCount, size_t pOffset);
+ssize_t pwrite(int pFD, const void* pBuf, size_t pCount, size_t pOffset);
+int ftruncate(int pFD, size_t pLength);
 
 } // namespace of detail
 } // namespace of fs
diff --git a/include/mcld/Support/GCFactory.h b/include/mcld/Support/GCFactory.h
index eb3f9db..6679f41 100644
--- a/include/mcld/Support/GCFactory.h
+++ b/include/mcld/Support/GCFactory.h
@@ -228,3 +228,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/include/mcld/Support/HandleToArea.h b/include/mcld/Support/HandleToArea.h
new file mode 100644
index 0000000..3cced3d
--- /dev/null
+++ b/include/mcld/Support/HandleToArea.h
@@ -0,0 +1,119 @@
+//===- HandleToArea.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_FILE_HANDLE_TO_MEMORY_AREA_H
+#define MCLD_FILE_HANDLE_TO_MEMORY_AREA_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/ADT/TypeTraits.h>
+#include <mcld/ADT/StringHash.h>
+#include <mcld/Support/Path.h>
+#include <mcld/Support/FileHandle.h>
+#include <vector>
+
+namespace mcld
+{
+
+class MemoryArea;
+
+/** \class HandleToArea
+ *
+ *  Special double-key associative container. Keys are Path and file handler,
+ *  associative value is MemoryArea.
+ *
+ *  For high performance, HandleToArea is not designed to contain unique
+ *  <key, value> pair. The key and value may be duplicated.
+ *
+ *  Like FileHandle, HandleToArea should neither throw exception nor call
+ *  expressive diagnostic.
+ */
+class HandleToArea : private Uncopyable
+{
+private:
+  struct Bucket {
+    unsigned int hash_value;
+    FileHandle* handle;
+    MemoryArea* area;
+  };
+
+  // the best data structure is a binary search tree.
+  // However, by the shrinking time-to-market constraint, I used
+  // vector and sequential search here.
+  typedef std::vector<Bucket> HandleToAreaMap;
+
+  typedef StringHash<BKDR> HashFunction;
+
+public:
+  typedef HandleToAreaMap::iterator iterator;
+  typedef HandleToAreaMap::const_iterator const_iterator;
+
+public:
+  struct Result {
+  public:
+    Result(FileHandle* pHandle, MemoryArea* pArea)
+      : handle(pHandle), area(pArea) { }
+
+  public:
+    FileHandle* handle;
+    MemoryArea* area;
+  };
+
+  struct ConstResult {
+  public:
+    ConstResult(const FileHandle* pHandle, const MemoryArea* pArea)
+      : handle(pHandle), area(pArea) { }
+
+  public:
+    const FileHandle* handle;
+    const MemoryArea* area;
+  };
+
+public:
+  bool push_back(FileHandle* pHandle, MemoryArea* pArea);
+
+  bool erase(MemoryArea* pArea);
+
+  bool erase(const sys::fs::Path& pPath);
+
+  Result findFirst(const sys::fs::Path& pPath);
+
+  ConstResult findFirst(const sys::fs::Path& pPath) const;
+
+  iterator begin()
+  { return m_AreaMap.begin(); }
+
+  iterator end()
+  { return m_AreaMap.end(); }
+
+  const_iterator begin() const
+  { return m_AreaMap.begin(); }
+
+  const_iterator end() const
+  { return m_AreaMap.end(); }
+
+  // -----  capacity  ----- //
+  bool empty() const
+  { return m_AreaMap.empty(); }
+
+  size_t size() const
+  { return m_AreaMap.size(); }
+
+  HandleToArea() : m_AreaMap() { }
+
+  ~HandleToArea() { }
+
+private:
+  HandleToAreaMap m_AreaMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/MemoryArea.h b/include/mcld/Support/MemoryArea.h
index 2c04aff..5f4a29e 100644
--- a/include/mcld/Support/MemoryArea.h
+++ b/include/mcld/Support/MemoryArea.h
@@ -12,22 +12,23 @@
 #include <gtest.h>
 #endif
 
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/Support/FileSystem.h"
-#include "mcld/Support/Path.h"
-#include <llvm/ADT/ilist.h>
-#include <llvm/ADT/ilist_node.h>
+#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>
 
+
 #if defined(ENABLE_UNITTEST)
 namespace mcldtest
 {
   class MemoryAreaTest;
 } // namespace of mcldtest
-
 #endif
+
 namespace mcld
 {
 
@@ -52,85 +53,10 @@
  */
 class MemoryArea : private Uncopyable
 {
-#if defined(ENABLE_UNITTEST)
-friend class mcldtest::MemoryAreaTest;
-#endif
-public:
-  enum IOState
-  {
-    GoodBit    = 0,
-    BadBit     = 1L << 0,
-    EOFBit     = 1L << 1,
-    FailBit    = 1L << 2,
-    IOStateEnd = 1L << 16
-  };
-
-  enum AccessMode
-  {
-    ReadOnly = O_RDONLY,
-    WriteOnly = O_WRONLY,
-    ReadWrite = O_RDWR,
-    AccessMask = O_ACCMODE
-  };
-
-private:
-  typedef sys::fs::detail::Address Address;
-
-  friend class MemoryRegion;
-  friend class RegionFactory;
-  struct Space : public llvm::ilist_node<Space>
-  {
-  public:
-    enum Type
-    {
-      ALLOCATED_ARRAY,
-      MMAPED,
-      UNALLOCATED
-    };
-
-  public:
-    Space()
-    : m_pParent(NULL),
-      type(UNALLOCATED),
-      file_offset(0),
-      size(0),
-      data(0),
-      region_num(0)
-    { }
-
-    Space(MemoryArea* pParent, size_t pOffset, size_t pLength)
-    : m_pParent(pParent),
-      type(UNALLOCATED),
-      file_offset(pOffset),
-      size(pLength),
-      data(0),
-      region_num(0)
-    { }
-
-    ~Space()
-    { }
-
-    void sync()
-    { m_pParent->write(*this); }
-
-  private:
-    MemoryArea* m_pParent;
-
-  public:
-    Type type;
-    size_t file_offset;
-    size_t size;
-    sys::fs::detail::Address data;
-    size_t region_num;
-  };
-
-  friend class Space;
-  typedef llvm::iplist<Space> SpaceList;
-
 public:
   // constructor
-  // @param pRegionFactory the factory to manage MemoryRegions
-  MemoryArea(RegionFactory& pRegionFactory);
+  MemoryArea(RegionFactory& pRegionFactory,
+             FileHandle& pFileHandle);
 
   // destructor
   ~MemoryArea();
@@ -145,113 +71,39 @@
   // release a MemoryRegion does not cause
   void release(MemoryRegion* pRegion);
 
-  // clean - release all MemoryRegion and unmap all spaces.
-  void clean();
+  // clear - release all memory regions.
+  void clear();
 
-  // sync - sync all MemoryRegion
-  void sync();
+  FileHandle* handler()
+  { return m_pFileHandle; }
 
-  // map - open the file pPath and mapped it onto MemoryArea
-  // @param flags see man 2 open
-  void map(const sys::fs::Path& pPath, int flags);
-
-  // map - open the file pPath and mapped it onto MemoryArea
-  // @param flags see man 2 open
-  // @param mode see man 2 open
-  void map(const sys::fs::Path& pPath, int flags, int mode);
-
-  // unmap - close the opened file and unmap the MemoryArea
-  void unmap();
-
-  // path - the path of the mapped file.
-  const sys::fs::Path& path() const
-  { return m_FilePath; }
-
-  // size - the real size of the mapped file.
-  size_t size() const
-  { return m_FileSize; }
-
-  // isMapped - check if MemoryArea is mapped to a file
-  bool isMapped() const;
-
-  // isGood - check if the state of the opened area is good for read/write
-  // operations
-  bool isGood() const;
-
-  // isBad - check if an error causes the loss of integrity of the memory space
-  bool isBad() const;
-
-  // isFailed - check if an error related to the internal logic of the operation
-  // itself occurs
-  bool isFailed() const;
-
-  // isEOF - check if we reach the end of the file
-  bool isEOF() const;
-
-  // isReadable - check if the memory area is readable
-  bool isReadable() const;
-
-  // isWriteable - check if the memory area is writable
-  bool isWritable() const;
-
-  // rdstate - get error state flags
-  // Returns the current internal error state flags of the stream
-  int rdstate() const;
-
-  // setState - set error state flag
-  void setState(IOState pState);
-
-  // clear - set error state flag
-  void clear(IOState pState = GoodBit);
+  const FileHandle* handler() const
+  { return m_pFileHandle; }
 
 private:
-  // readToBuffer - read data from the file behind this MemorySpace and store
-  // those bytes in pBuf. Return the number of byte read or -1 on error.
-  ssize_t readToBuffer(sys::fs::detail::Address pBuf,
-                       size_t pSize, size_t pOffset);
+  friend class MemoryAreaFactory;
+
+#if defined(ENABLE_UNITTEST)
+  friend class mcldtest::MemoryAreaTest;
+#endif
+
+  typedef llvm::iplist<Space> SpaceList;
 
 private:
-  // find - first fit search
+  // -----  special methods ----- //
+  // @param pRegionFactory  The factory of regions.
+  // @param pUniverse       A initial univeral space.
+  MemoryArea(RegionFactory& pRegionFactory, Space& pUniverse);
+
+  // -----  space list methods  ----- //
   Space* find(size_t pOffset, size_t pLength);
 
-  // release a Space, but does not remove it from space list
-  void release(Space* pSpace);
-
-  // read - read data from mapped file into virtual memroy of pSpace. Return
-  // false on error.
-  bool read(Space& pSpace);
-
-  // write - write back the virtual memory of pSpace into mapped file.
-  void write(const Space& pSpace);
-
-  // truncate - truncate the file size to length.
-  void truncate(size_t pLength);
-
-  // policy - decide whehter to use dynamic memory or memory mapped I/O
-  Space::Type policy(off_t pOffset, size_t pLength);
-
-  // the size of one page
-  static const off_t PageSize = 4096;
-
-  // page_boundary - Given a file size, return the size to read integral pages.
-  // return the first page boundary after pFileOffset
-  static off_t page_boundary(off_t pFileOffset)
-  { return (pFileOffset + (PageSize - 1)) & ~ (PageSize - 1); }
-
-  // Given a file offset, return the page offset.
-  // return the first page boundary before pFileOffset
-  static off_t page_offset(off_t pFileOffset)
-  { return pFileOffset & ~ (PageSize - 1); }
+  const Space* find(size_t pOffset, size_t pLength) const;
 
 private:
   RegionFactory& m_RegionFactory;
-  sys::fs::Path m_FilePath;
-  int m_FileDescriptor;
-  size_t m_FileSize;
-  int m_AccessFlags;
-  int m_State;
-
   SpaceList m_SpaceList;
+  FileHandle* m_pFileHandle;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Support/MemoryAreaFactory.h b/include/mcld/Support/MemoryAreaFactory.h
index f9ffa6e..be86b8c 100644
--- a/include/mcld/Support/MemoryAreaFactory.h
+++ b/include/mcld/Support/MemoryAreaFactory.h
@@ -11,13 +11,11 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-
-#include "mcld/Support/UniqueGCFactory.h"
-#include "mcld/Support/MemoryArea.h"
-#include "mcld/Support/Path.h"
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fcntl.h>
+#include <mcld/Support/GCFactory.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/Path.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/HandleToArea.h>
 
 namespace mcld
 {
@@ -40,21 +38,35 @@
  *  MemoryRegion is requested.
  *
  *  @see MemoryRegion
- *  @see UniqueGCFactoryBase
  */
-class MemoryAreaFactory : public UniqueGCFactoryBase<sys::fs::Path, MemoryArea, 0>
+class MemoryAreaFactory : public GCFactory<MemoryArea, 0>
 {
 public:
   explicit MemoryAreaFactory(size_t pNum);
-  ~MemoryAreaFactory();
 
-  // produce - create a MemoryArea and open its file
-  // If the file fails to be opened, the returned MemoryArea::isMapped() 
-  // should be false
-  MemoryArea* produce(const sys::fs::Path& pPath, int pFlags);
-  MemoryArea* produce(const sys::fs::Path& pPath, int pFlags, mode_t pMode);
+  virtual ~MemoryAreaFactory();
+
+  // produce - create a MemoryArea and open its file.
+  MemoryArea* produce(const sys::fs::Path& pPath,
+                      FileHandle::OpenMode pMode);
+
+  // produce - create a MemoryArea and open its file.
+  MemoryArea* produce(const sys::fs::Path& pPath,
+                      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);
+
+  // Create a MemoryArea by the given file handler
+  MemoryArea* create(int pFD, FileHandle::OpenMode pMode);
 
 private:
+  HandleToArea m_HandleToArea;
   RegionFactory* m_pRegionFactory;
 };
 
diff --git a/include/mcld/Support/MemoryRegion.h b/include/mcld/Support/MemoryRegion.h
index 49f5fda..caa929f 100644
--- a/include/mcld/Support/MemoryRegion.h
+++ b/include/mcld/Support/MemoryRegion.h
@@ -13,12 +13,9 @@
 #endif
 
 #include <mcld/ADT/Uncopyable.h>
-#include <mcld/ADT/SizeTraits.h>
-#include <mcld/ADT/TypeTraits.h>
 #include <mcld/Support/FileSystem.h>
 #include <mcld/Support/MemoryArea.h>
-#include <llvm/ADT/ilist.h>
-#include <llvm/ADT/StringRef.h>
+#include <mcld/Support/Space.h>
 
 namespace mcld
 {
@@ -42,24 +39,17 @@
 friend class MemoryArea;
 
 public:
-typedef NonConstTraits<mcld::sys::fs::detail::Address>::value_type Address;
-typedef ConstTraits<mcld::sys::fs::detail::Address>::value_type    ConstAddress;
-typedef NonConstTraits<mcld::sys::fs::detail::Offset>::value_type  Offset;
-typedef ConstTraits<mcld::sys::fs::detail::Offset>::value_type     ConstOffset;
+  typedef Space::Address Address;
+  typedef Space::ConstAddress ConstAddress;
 
 private:
-  MemoryRegion(MemoryArea::Space* pParentSpace,
-               const Address pVMAStart,
-               size_t pSize);
+  MemoryRegion(Space& pParent, const Address pVMAStart, size_t pSize);
 
-  // drift - leave parent space
-  void drift();
+  Space* parent()
+  { return &m_Parent; }
 
-  MemoryArea::Space* parent()
-  { return m_pParentSpace; }
-
-  const MemoryArea::Space* parent() const
-  { return m_pParentSpace; }
+  const Space* parent() const
+  { return &m_Parent; }
 
 public:
   ~MemoryRegion();
@@ -79,14 +69,14 @@
   size_t size() const
   { return m_Length; }
 
-  Address getBuffer(Offset pOffset = 0)
+  Address getBuffer(size_t pOffset = 0)
   { return m_VMAStart+pOffset; }
 
-  ConstAddress getBuffer(Offset pOffset = 0) const
+  ConstAddress getBuffer(size_t pOffset = 0) const
   { return m_VMAStart+pOffset; }
  
 private:
-  MemoryArea::Space* m_pParentSpace;
+  Space& m_Parent;
   Address m_VMAStart;
   size_t m_Length;
 };
diff --git a/include/mcld/Support/MsgHandling.h b/include/mcld/Support/MsgHandling.h
new file mode 100644
index 0000000..a42bb54
--- /dev/null
+++ b/include/mcld/Support/MsgHandling.h
@@ -0,0 +1,77 @@
+//===- MsgHandling.h ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MESSAGE_HANDLING_H
+#define MCLD_MESSAGE_HANDLING_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/LD/MsgHandler.h>
+
+namespace mcld
+{
+
+class MCLDInfo;
+class DiagnosticPrinter;
+class DiagnosticLineInfo;
+
+void InitializeDiagnosticEngine(const MCLDInfo& pLDInfo,
+                                DiagnosticLineInfo* pLineInfo,
+                                DiagnosticPrinter* pPrinter);
+
+DiagnosticEngine& getDiagnosticEngine();
+
+MsgHandler unreachable(unsigned int pID);
+MsgHandler fatal(unsigned int pID);
+MsgHandler error(unsigned int pID);
+MsgHandler warning(unsigned int pID);
+MsgHandler debug(unsigned int pID);
+MsgHandler note(unsigned int pID);
+MsgHandler ignore(unsigned int pID);
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+//  Inline functions
+inline mcld::MsgHandler mcld::unreachable(unsigned int pID)
+{
+  return getDiagnosticEngine().report(pID, DiagnosticEngine::Unreachable);
+}
+
+inline mcld::MsgHandler mcld::fatal(unsigned int pID)
+{
+  return getDiagnosticEngine().report(pID, DiagnosticEngine::Fatal);
+}
+
+inline mcld::MsgHandler mcld::error(unsigned int pID)
+{
+  return getDiagnosticEngine().report(pID, DiagnosticEngine::Error);
+}
+
+inline mcld::MsgHandler mcld::warning(unsigned int pID)
+{
+  return getDiagnosticEngine().report(pID, DiagnosticEngine::Warning);
+}
+
+inline mcld::MsgHandler mcld::debug(unsigned int pID)
+{
+  return getDiagnosticEngine().report(pID, DiagnosticEngine::Debug);
+}
+
+inline mcld::MsgHandler mcld::note(unsigned int pID)
+{
+  return getDiagnosticEngine().report(pID, DiagnosticEngine::Note);
+}
+
+inline mcld::MsgHandler mcld::ignore(unsigned int pID)
+{
+  return getDiagnosticEngine().report(pID, DiagnosticEngine::Ignore);
+}
+
+#endif
+
diff --git a/include/mcld/Support/Path.h b/include/mcld/Support/Path.h
index f5ee56c..113ff25 100644
--- a/include/mcld/Support/Path.h
+++ b/include/mcld/Support/Path.h
@@ -10,7 +10,6 @@
 // filesystem (v3), but modified to remove exception handling and the
 // path class.
 //===----------------------------------------------------------------------===//
-
 #ifndef MCLD_PATH_H
 #define MCLD_PATH_H
 #ifdef ENABLE_UNITTEST
@@ -18,15 +17,17 @@
 #endif
 
 #include <llvm/Support/raw_ostream.h>
+#include <mcld/Config/Config.h>
+
+#include <iosfwd>
 #include <functional>
 #include <string>
 
-//#include "mcld/Support/Directory.h"
 namespace mcld {
 namespace sys  {
 namespace fs   {
 
-#ifdef LLVM_ON_WIN32
+#if defined(MCLD_ON_WIN32)
 const wchar_t       separator = L'\\';
 const wchar_t       preferred_separator = L'\\';
 #else
@@ -44,7 +45,7 @@
 class Path
 {
 public:
-#ifdef LLVM_ON_WIN32
+#if defined(MCLD_ON_WIN32)
   typedef wchar_t                            ValueType;
 #else
   typedef char                               ValueType;
diff --git a/include/mcld/Support/PositionDependentOption.h b/include/mcld/Support/PositionDependentOption.h
index b5d60e8..8dd969d 100644
--- a/include/mcld/Support/PositionDependentOption.h
+++ b/include/mcld/Support/PositionDependentOption.h
@@ -40,20 +40,26 @@
     };
 
   protected:
-    PositionDependentOption(unsigned pPosition, Type pType)
+    PositionDependentOption(unsigned int pPosition, Type pType)
       : m_Type(pType),
         m_Position(pPosition) {}
 
   public:
-    inline const Type& type() const
+    Type type()
     { return m_Type; }
 
-    inline unsigned position() const
+    Type type() const
+    { return m_Type; }
+
+    unsigned int position()
+    { return m_Position; }
+
+    unsigned int position() const
     { return m_Position; }
 
   private:
     Type m_Type;
-    unsigned m_Position;
+    unsigned int m_Position;
   };
 
   typedef std::vector<PositionDependentOption*> PositionDependentOptions;
diff --git a/include/mcld/Support/RegionFactory.h b/include/mcld/Support/RegionFactory.h
index ba9a88d..8893500 100644
--- a/include/mcld/Support/RegionFactory.h
+++ b/include/mcld/Support/RegionFactory.h
@@ -11,10 +11,10 @@
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
-#include "mcld/Support/GCFactory.h"
-#include "mcld/Support/MemoryRegion.h"
-#include "mcld/Support/MemoryArea.h"
-#include "mcld/Support/FileSystem.h"
+#include <mcld/Support/GCFactory.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/FileSystem.h>
 
 namespace mcld
 {
@@ -35,9 +35,7 @@
   ~RegionFactory();
 
   // ----- production ----- //
-  MemoryRegion* produce(MemoryArea::Space* pSpace,
-                        const sys::fs::detail::Address pVMAStart,
-                        size_t pSize);
+  MemoryRegion* produce(Space& pSpace, void* pVMAStart, size_t pSize);
 
   void destruct(MemoryRegion* pRegion);
 };
diff --git a/include/mcld/Support/Space.h b/include/mcld/Support/Space.h
new file mode 100644
index 0000000..7ebedce
--- /dev/null
+++ b/include/mcld/Support/Space.h
@@ -0,0 +1,104 @@
+//===- Space.h ------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MEMORY_SPACE_H
+#define MCLD_MEMORY_SPACE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/Support/DataTypes.h>
+#include <llvm/ADT/ilist.h>
+#include <llvm/ADT/ilist_node.h>
+#include <mcld/ADT/TypeTraits.h>
+
+namespace mcld
+{
+
+class FileHandle;
+class MemoryRegion;
+
+/** \class Space
+ *  \brief Space contains a chunk of memory space that does not overlap with
+ *  the other Space.
+ *
+ */
+class Space : public llvm::ilist_node<Space>
+{
+public:
+  enum Type
+  {
+    ALLOCATED_ARRAY,
+    MMAPED,
+    EXTERNAL,
+    UNALLOCATED
+  };
+
+  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.
+  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; }
+
+  Address memory()
+  { return m_Data; }
+
+  ConstAddress memory() const
+  { return m_Data; }
+
+  size_t start() const
+  { return m_StartOffset; }
+
+  size_t size() const
+  { return m_Size; }
+
+  Type type() const
+  { return m_Type; }
+
+  void addRegion(MemoryRegion& pRegion)
+  { ++m_RegionCount; }
+
+  void removeRegion(MemoryRegion& pRegion)
+  { --m_RegionCount; }
+
+  size_t numOfRegions() const
+  { return m_RegionCount; }
+
+  static Space* createSpace(FileHandle& pHandler,
+                            size_t pOffset, size_t pSize);
+  
+  static void releaseSpace(Space* pSpace, FileHandle& pHandler);
+
+  static void syncSpace(Space* pSpace, FileHandle& pHandler);
+
+private:
+  Address m_Data;
+  uint32_t m_StartOffset;
+  uint32_t m_Size;
+  uint16_t m_RegionCount;
+  Type m_Type : 2;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/SystemUtils.h b/include/mcld/Support/SystemUtils.h
new file mode 100644
index 0000000..bfc522b
--- /dev/null
+++ b/include/mcld/Support/SystemUtils.h
@@ -0,0 +1,33 @@
+//===- SystemUtils.h ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SYSTEM_UTILS_H
+#define MCLD_SYSTEM_UTILS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Config/Config.h>
+
+namespace mcld {
+namespace sys {
+
+typedef uint8_t* Address;
+typedef off_t Offset;
+
+/** \fn strerror
+ *  \brief system error message
+ */
+char *strerror(int pErrnum);
+
+} // namespace of sys
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/TargetRegistry.h b/include/mcld/Support/TargetRegistry.h
index a9ad875..b31bed4 100644
--- a/include/mcld/Support/TargetRegistry.h
+++ b/include/mcld/Support/TargetRegistry.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef TARGET_REGISTRY_H
-#define TARGET_REGISTRY_H
+#ifndef MCLD_TARGET_REGISTRY_H
+#define MCLD_TARGET_REGISTRY_H
 #include <llvm/Support/TargetRegistry.h>
 #include <string>
 #include <list>
@@ -28,6 +28,7 @@
 class AttributeFactory;
 class InputFactory;
 class ContextFactory;
+class DiagnosticLineInfo;
 
 //===----------------------------------------------------------------------===//
 /// Target - mcld::Target is an object adapter of llvm::Target
@@ -48,30 +49,28 @@
   typedef TargetLDBackend  *(*TargetLDBackendCtorTy)(const llvm::Target&,
                                                      const std::string&);
 
-private:
-  TargetMachineCtorTy TargetMachineCtorFn;
-  SectLinkerCtorTy SectLinkerCtorFn;
-  TargetLDBackendCtorTy TargetLDBackendCtorFn;
+  typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const llvm::Target&,
+                                                          const std::string&);
 
 public:
   Target();
 
-  void setTarget(const llvm::Target& pTarget) {
-    m_pT = &pTarget;
-  }
+  void setTarget(const llvm::Target& pTarget)
+  { m_pT = &pTarget; }
 
   mcld::LLVMTargetMachine *createTargetMachine(const std::string &pTriple,
                           const std::string &pCPU, const std::string &pFeatures,
                           const llvm::TargetOptions &Options,
                           llvm::Reloc::Model RM = llvm::Reloc::Default,
                           llvm::CodeModel::Model CM = llvm::CodeModel::Default,
-                          llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default) const {
+                          llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default) const
+  {
     if (TargetMachineCtorFn && m_pT) {
       llvm::TargetMachine *tm = m_pT->createTargetMachine(pTriple, pCPU, pFeatures, Options, RM, CM, OL);
       if (tm)
         return TargetMachineCtorFn(*this, *tm, pTriple);
     }
-    return 0;
+    return NULL;
   }
 
   /// createSectLinker - create target-specific SectLinker
@@ -81,7 +80,7 @@
                                SectLinkerOption &pOption,
                                TargetLDBackend &pLDBackend) const {
     if (!SectLinkerCtorFn)
-      return 0;
+      return NULL;
     return SectLinkerCtorFn(pTriple,
                             pOption,
                             pLDBackend);
@@ -90,17 +89,33 @@
   /// createLDBackend - create target-specific LDBackend
   ///
   /// @return created TargetLDBackend
-  TargetLDBackend *createLDBackend(const llvm::Target& T, const std::string& Triple) const {
+  TargetLDBackend* createLDBackend(const std::string& Triple) const
+  {
     if (!TargetLDBackendCtorFn)
-      return 0;
-    return TargetLDBackendCtorFn(T, Triple);
+      return NULL;
+    return TargetLDBackendCtorFn(*get(), Triple);
   }
 
-  const llvm::Target* get() const {
-    return m_pT;
+  /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
+  DiagnosticLineInfo* createDiagnosticLineInfo(const llvm::Target& pTarget,
+                                               const std::string& pTriple) const
+  {
+    if (!DiagnosticLineInfoCtorFn)
+      return NULL;
+    return DiagnosticLineInfoCtorFn(pTarget, pTriple);
   }
 
+  const llvm::Target* get() const
+  { return m_pT; }
+
 private:
+  // -----  function pointers  ----- //
+  TargetMachineCtorTy TargetMachineCtorFn;
+  SectLinkerCtorTy SectLinkerCtorFn;
+  TargetLDBackendCtorTy TargetLDBackendCtorFn;
+  DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn;
+
+  // -----  adapted llvm::Target  ----- //
   const llvm::Target* m_pT;
 };
 
@@ -139,7 +154,8 @@
   ///
   /// @param T - The target being registered.
   /// @param Fn - A function to construct a TargetMachine for the target.
-  static void RegisterTargetMachine(mcld::Target &T, mcld::Target::TargetMachineCtorTy Fn) {
+  static void RegisterTargetMachine(mcld::Target &T, mcld::Target::TargetMachineCtorTy Fn)
+  {
     // Ignore duplicate registration.
     if (!T.TargetMachineCtorFn)
       T.TargetMachineCtorFn = Fn;
@@ -150,7 +166,8 @@
   ///
   /// @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) {
+  static void RegisterSectLinker(mcld::Target &T, mcld::Target::SectLinkerCtorTy Fn)
+  {
     if (!T.SectLinkerCtorFn)
       T.SectLinkerCtorFn = Fn;
   }
@@ -160,11 +177,25 @@
   ///
   /// @param T - The target being registered
   /// @param Fn - A function to create TargetLDBackend for the target
-  static void RegisterTargetLDBackend(mcld::Target &T, mcld::Target::TargetLDBackendCtorTy Fn) {
+  static void RegisterTargetLDBackend(mcld::Target &T, mcld::Target::TargetLDBackendCtorTy Fn)
+  {
     if (!T.TargetLDBackendCtorFn)
       T.TargetLDBackendCtorFn = Fn;
   }
 
+  /// RegisterTargetDiagnosticLineInfo - Register a DiagnosticLineInfo
+  /// implementation for the given target.
+  ///
+  /// @param T - The target being registered
+  /// @param Fn - A function to create DiagnosticLineInfo for the target
+  static void
+  RegisterDiagnosticLineInfo(mcld::Target &T,
+                             mcld::Target::DiagnosticLineInfoCtorTy Fn)
+  {
+    if (!T.DiagnosticLineInfoCtorFn)
+      T.DiagnosticLineInfoCtorFn = Fn;
+  }
+
   /// lookupTarget - Lookup a target based on a llvm::Target.
   ///
   /// @param T - The llvm::Target to find
diff --git a/include/mcld/Support/TargetSelect.h b/include/mcld/Support/TargetSelect.h
index e040ae2..0788d1d 100644
--- a/include/mcld/Support/TargetSelect.h
+++ b/include/mcld/Support/TargetSelect.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef TARGETSELECT_H
-#define TARGETSELECT_H
+#ifndef MCLD_TARGET_SELECT_H
+#define MCLD_TARGET_SELECT_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -32,6 +32,11 @@
   // Declare all of the available target-specific linker
 #define LLVM_LINKER(TargetName) void LLVMInitialize##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();
+#include "mcld/Config/Linkers.def"
+
 } // extern "C"
 
 namespace mcld
@@ -56,6 +61,9 @@
 
 #define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##LDTarget();
 #include "mcld/Config/Targets.def"
+
+#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##LDBackend();
+#include "mcld/Config/Targets.def"
   }
 
   /// InitializeAllLinkers - The main program should call this function if it
@@ -66,8 +74,13 @@
   inline void InitializeAllLinkers() {
 #define LLVM_LINKER(TargetName) LLVMInitialize##TargetName##SectLinker();
 #include "mcld/Config/Linkers.def"
+  }
 
-#define LLVM_LINKER(TargetName) LLVMInitialize##TargetName##LDBackend();
+  /// InitializeMsgHandler - The main program should call this function if it
+  /// wants to print linker-specific messages. To make them available via the
+  /// TargetRegistry.
+  inline void InitializeAllDiagnostics() {
+#define LLVM_LINKER(TargetName)  LLVMInitialize##TargetName##DiagnosticLineInfo();
 #include "mcld/Config/Linkers.def"
   }
 
diff --git a/include/mcld/Support/raw_ostream.h b/include/mcld/Support/raw_ostream.h
new file mode 100644
index 0000000..61706de
--- /dev/null
+++ b/include/mcld/Support/raw_ostream.h
@@ -0,0 +1,81 @@
+//===- raw_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_OSTREAM_H
+#define MCLD_RAW_OSTREAM_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <string>
+#include <llvm/Support/raw_ostream.h>
+#include <mcld/MC/MCLDInfo.h>
+
+namespace mcld
+{
+
+class raw_fd_ostream : public llvm::raw_fd_ostream
+{
+public:
+  /// raw_fd_ostream - Open the specified file for writing. If an error occurs,
+  /// information about the error is put into ErrorInfo, and the stream should
+  /// be immediately destroyed; the string will be empty if no error occurred.
+  /// This allows optional flags to control how the file will be opened.
+  ///
+  /// As a special case, if Filename is "-", then the stream will use
+  /// STDOUT_FILENO instead of opening a file. Note that it will still consider
+  /// itself to own the file descriptor. In particular, it will close the
+  /// file descriptor when it is done (this is necessary to detect
+  /// output errors).
+  raw_fd_ostream(const char *pFilename,
+                 std::string &pErrorInfo,
+                 unsigned int pFlags = 0,
+                 const MCLDInfo* pLDInfo = NULL);
+
+  /// 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);
+
+  virtual ~raw_fd_ostream();
+
+  void setLDInfo(const MCLDInfo& pLDInfo);
+
+
+  llvm::raw_ostream &changeColor(enum llvm::raw_ostream::Colors pColors,
+                                 bool pBold=false,
+                                 bool pBackground=false);
+
+  llvm::raw_ostream &resetColor();
+
+  // FIXME: migrate to newer LLVM
+  // llvm::raw_ostream &reverseColor();
+
+  bool is_displayed() const;
+
+private:
+  const MCLDInfo* m_pLDInfo;
+
+};
+
+/// 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();
+
+/// errs() - This returns a reference to a raw_ostream for standard error.
+/// Use it like: errs() << "foo" << "bar";
+mcld::raw_fd_ostream &errs();
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Target/AndroidSectLinker.h b/include/mcld/Target/AndroidSectLinker.h
deleted file mode 100644
index dd68ff2..0000000
--- a/include/mcld/Target/AndroidSectLinker.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- AndroidSectLinker.h ------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// AndroidSectLinker is a customized linker pass for Android platform.
-// This pass set up default parameters for Android.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ANDROID_SECTLINKER_H
-#define ANDROID_SECTLINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/CodeGen/SectLinker.h>
-
-namespace mcld
-{
-
-class AndroidSectLinker : public SectLinker
-{
-public:
-  AndroidSectLinker(SectLinkerOption &pOption,
-                    mcld::TargetLDBackend &pLDBackend);
-
-  virtual ~AndroidSectLinker();
-
-  // addTargetInputs - add Android-specific linker options
-  virtual void addTargetOptions(llvm::Module &pM,
-                                SectLinkerOption &pOption);
-
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Target/ELFSectLinker.h b/include/mcld/Target/ELFSectLinker.h
new file mode 100644
index 0000000..04234a8
--- /dev/null
+++ b/include/mcld/Target/ELFSectLinker.h
@@ -0,0 +1,36 @@
+//===- ELFSectLinker.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// ELFSectLinker is a customized linker pass for ELF platform.
+// This pass set up default parameters for ELF.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELF_SECTION_LINKER_H
+#define MCLD_ELF_SECTION_LINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/CodeGen/SectLinker.h>
+
+namespace mcld
+{
+
+class ELFSectLinker : public SectLinker
+{
+public:
+  ELFSectLinker(SectLinkerOption &pOption,
+                mcld::TargetLDBackend &pLDBackend);
+
+  virtual ~ELFSectLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Target/GNULDBackend.h b/include/mcld/Target/GNULDBackend.h
index 7f51448..196420a 100644
--- a/include/mcld/Target/GNULDBackend.h
+++ b/include/mcld/Target/GNULDBackend.h
@@ -15,18 +15,20 @@
 #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/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/ELFDynObjFileFormat.h>
-#include <mcld/LD/ELFExecFileFormat.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>
-#include <mcld/LD/ELFSegmentFactory.h>
 
 namespace mcld
 {
@@ -56,85 +58,81 @@
  */
 class GNULDBackend : public TargetLDBackend
 {
-  // These dynamic section tags are GNU extension.
-  enum {
-    DT_RELACOUNT  = 0x6ffffff9,
-    DT_RELCOUNT   = 0x6ffffffa,
-    DT_FLAGS_1    = 0x6ffffffb,
-    DT_VERDEF     = 0x6ffffffc,
-    DT_VERDEFNUM  = 0x6ffffffd,
-    DT_VERNEED    = 0x6ffffffe,
-    DT_VERNEEDNUM = 0x6fffffff
-  };
-
-protected:
-  // Based on Kind in LDFileFormat to define basic section orders for ELF, and
-  // refer gold linker to add more enumerations to handle Regular and BSS kind
-  enum SectionOrder {
-    SHO_INTERP = 1,          // .interp
-    SHO_RO_NOTE,             // .note.ABI-tag, .note.gnu.build-id
-    SHO_NAMEPOOL,            // *.hash, .dynsym, .dynstr
-    SHO_RELOCATION,          // .rel.*, .rela.*
-    SHO_REL_PLT,             // .rel.plt should come after other .rel.*
-    SHO_INIT,                // .init
-    SHO_PLT,                 // .plt
-    SHO_TEXT,                // .text
-    SHO_FINI,                // .fini
-    SHO_RO,                  // .rodata
-    SHO_EHFRAME,             // .eh_frame_hdr, .eh_frame
-    SHO_TLS_DATA,            // .tdata
-    SHO_TLS_BSS,             // .tbss
-    SHO_RELRO_LOCAL,         // .data.rel.ro.local
-    SHO_RELRO,               // .data.rel.ro,
-    SHO_RELRO_LAST,          // for x86 to adjust .got if needed
-    SHO_NON_RELRO_FIRST,     // for x86 to adjust .got.plt if needed
-    SHO_DATA,                // .data
-    SHO_LARGE_DATA,          // .ldata
-    SHO_RW_NOTE,             //
-    SHO_SMALL_DATA,          // .sdata
-    SHO_SMALL_BSS,           // .sbss
-    SHO_BSS,                 // .bss
-    SHO_LARGE_BSS,           // .lbss
-    SHO_UNDEFINED = ~(0U)    // default order
-  };
-
 protected:
   GNULDBackend();
 
 public:
   virtual ~GNULDBackend();
 
+  // -----  readers/writers  ----- //
   bool initArchiveReader(MCLinker& pLinker, MCLDInfo& pInfo);
   bool initObjectReader(MCLinker& pLinker);
   bool initDynObjReader(MCLinker& pLinker);
   bool initObjectWriter(MCLinker& pLinker);
   bool initDynObjWriter(MCLinker& pLinker);
-
-  bool initExecSections(MCLinker& pMCLinker);
-  bool initDynObjSections(MCLinker& pMCLinker);
-
-  bool initStandardSymbols(MCLinker& pLinker);
+  bool initExecWriter(MCLinker& pLinker);
 
   GNUArchiveReader *getArchiveReader();
-  GNUArchiveReader *getArchiveReader() const;
+  const GNUArchiveReader *getArchiveReader() const;
 
   ELFObjectReader *getObjectReader();
-  ELFObjectReader *getObjectReader() const;
+  const ELFObjectReader *getObjectReader() const;
 
   ELFDynObjReader *getDynObjReader();
-  ELFDynObjReader *getDynObjReader() const;
+  const ELFDynObjReader *getDynObjReader() const;
 
   ELFObjectWriter *getObjectWriter();
-  ELFObjectWriter *getObjectWriter() const;
+  const ELFObjectWriter *getObjectWriter() const;
 
   ELFDynObjWriter *getDynObjWriter();
-  ELFDynObjWriter *getDynObjWriter() const;
+  const ELFDynObjWriter *getDynObjWriter() const;
+
+  ELFExecWriter *getExecWriter();
+  const ELFExecWriter *getExecWriter() const;
+
+  // -----  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);
+
+  /// getOutputFormat - get the sections of the output file.
+  ELFFileFormat* getOutputFormat(const Output& pOutput);
+  const ELFFileFormat* getOutputFormat(const Output& pOutput) const;
 
   ELFDynObjFileFormat* getDynObjFileFormat();
-  ELFDynObjFileFormat* getDynObjFileFormat() const;
+  const ELFDynObjFileFormat* getDynObjFileFormat() const;
 
   ELFExecFileFormat* getExecFileFormat();
-  ELFExecFileFormat* getExecFileFormat() const;
+  const ELFExecFileFormat* getExecFileFormat() const;
+
+  // -----  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
+  /// 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);
+
+  /// 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));
+  }
+
+  /// finalizeStandardSymbols - set the value of standard symbols
+  virtual bool finalizeStandardSymbols(MCLinker& pLinker,
+                                       const Output& pOutput);
+
+  /// finalizeTargetSymbols - set the value of target symbols
+  virtual bool finalizeTargetSymbols(MCLinker& pLinker,
+                                     const Output& pOutput) = 0;
 
   size_t sectionStartOffset() const;
 
@@ -158,6 +156,21 @@
   virtual const char* entry() const
   { return "_start"; }
 
+  /// dyld - the name of the default dynamic linker
+  /// target may override this function if needed.
+  /// @ref gnu ld, bfd/elf32-i386.c:521
+  virtual const char* dyld() const
+  { return "/usr/lib/libc.so.1"; }
+
+  /// defaultTextSegmentAddr - target should specify its own default start address
+  /// of the text segment. esp. for exec.
+  virtual uint64_t defaultTextSegmentAddr() const
+  { return 0x0; }
+
+  /// segmentStartAddr - this function returns the start address of the segment
+  uint64_t segmentStartAddr(const Output& pOutput,
+                            const MCLDInfo& pInfo) const;
+
   /// sizeNamePools - compute the size of regular name pools
   /// In ELF executable files, regular name pools are .symtab, .strtab.,
   /// .dynsym, .dynstr, and .hash
@@ -169,6 +182,7 @@
   virtual uint64_t emitSectionData(const Output& pOutput,
                                    const LDSection& pSection,
                                    const MCLDInfo& pInfo,
+                                   const Layout& pLayout,
                                    MemoryRegion& pRegion) const = 0;
 
   /// emitRegNamePools - emit regular name pools - .symtab, .strtab
@@ -183,6 +197,13 @@
                                 const Layout& pLayout,
                                 const MCLDInfo& pLDInfo);
 
+  /// 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);
+
+  /// emitInterp - emit the .interp
+  virtual void emitInterp(Output& pOutput, const MCLDInfo& pLDInfo);
+
   /// getSectionOrder - compute the layout order of the section
   /// Layout calls this function to get the default order of the pSectHdr.
   /// If the pSectHdr.type() is LDFileFormat::Target, then getSectionOrder()
@@ -193,7 +214,8 @@
   ///
   /// @see getTargetSectionOrder
   virtual unsigned int getSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr) const;
+                                       const LDSection& pSectHdr,
+                                       const MCLDInfo& pInfo) const;
 
   /// getTargetSectionOrder - compute the layout order of target section
   /// If the target favors certain order for the given gSectHdr, please
@@ -202,37 +224,107 @@
   /// 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
+  getTargetSectionOrder(const Output& pOutput,
+                        const LDSection& pSectHdr,
+                        const MCLDInfo& pInfo) const
   { return (unsigned int)-1; }
 
-  /// emitProgramHdrs - emit ELF program headers
-  /// if the target favors other ways to emit program header, please override
-  /// this function
-  virtual void emitProgramHdrs(Output& pOutput);
-
   /// numOfSegments - return the number of segments
   /// if the target favors other ways to emit program header, please override
   /// this function
   virtual unsigned int numOfSegments() const
   { return m_ELFSegmentTable.size(); }
 
-  /// pagesize - the page size of the target machine, we set it to 4K here.
-  /// If target favors tht different size of page, please override this function
-  virtual unsigned int pagesize() const
-  { return 0x1000; }
+  /// elfSegmentTable - return the reference of the elf segment table
+  ELFSegmentFactory& elfSegmentTable()
+  { return m_ELFSegmentTable; }
+
+  /// elfSegmentTable - return the reference of the elf segment table
+  const ELFSegmentFactory& elfSegmentTable() const
+  { return m_ELFSegmentTable; }
+
+  /// 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;
+
+  /// 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;
 
   /// getSymbolIdx - get the symbol index of ouput symbol table
   size_t getSymbolIdx(LDSymbol* pSymbol) const;
 
+  /// isDefaultExecStack - target should specify whether the stack is default
+  /// executable. If target favors another choice, please override this function
+  virtual bool isDefaultExecStack() const
+  { return true; }
+
+  /// 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;
+
+  /// 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;
+
+protected:
+  uint64_t getSymbolSize(const LDSymbol& pSymbol) const;
+
+  uint64_t getSymbolInfo(const LDSymbol& pSymbol) const;
+
+  uint64_t getSymbolValue(const LDSymbol& pSymbol) const;
+
+  uint64_t getSymbolShndx(const LDSymbol& pSymbol, const Layout& pLayout) const;
+
+  /// getHashBucketCount - calculate hash bucket count.
+  /// @ref Google gold linker, dynobj.cc:791
+  static unsigned getHashBucketCount(unsigned pNumOfSymbols, bool pIsGNUStyle);
+
+  /// isDynamicSymbol
+  /// @ref Google gold linker: symtab.cc:311
+  static bool isDynamicSymbol(const LDSymbol& pSymbol, const Output& pOutput);
+
+  /// 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;
+
+public:
+  /// 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;
+
+  /// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
+  /// @ref Google gold linker, symtab.h:645
+  bool symbolNeedsDynRel(const ResolveInfo& pSym,
+                         bool pSymHasPLT,
+                         const MCLDInfo& pLDInfo,
+                         const Output& pOutput,
+                         bool isAbsReloc) const;
+
+  /// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
+  bool symbolNeedsCopyReloc(const Layout& pLayout,
+                            const Relocation& pReloc,
+                            const ResolveInfo& pSym,
+                            const MCLDInfo& pLDInfo,
+                            const Output& pOutput) const;
+
 private:
   /// createProgramHdrs - base on output sections to create the program headers
-  void createProgramHdrs(LDContext& pContext);
+  void createProgramHdrs(Output& pOutput,
+                         const MCLDInfo& pInfo);
 
-  /// writeELF32ProgramHdrs - write out the ELF32 program headers
-  void writeELF32ProgramHdrs(Output& pOutput);
-
-  /// writeELF64ProgramHdrs - write out the ELF64 program headers
-  void writeELF64ProgramHdrs(Output& pOutput);
+  /// 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);
 
   /// getSegmentFlag - give a section flag and return the corresponding segment
   /// flag
@@ -246,6 +338,11 @@
     return flag;
   }
 
+  /// createGNUStackInfo - create an output GNU stack section or segment if needed
+  void createGNUStackInfo(const Output& pOutput,
+                          const MCLDInfo& pInfo,
+                          MCLinker& pLinker);
+
   /// preLayout - Backend can do any needed modification before layout
   void preLayout(const Output& pOutput,
                  const MCLDInfo& pInfo,
@@ -256,16 +353,6 @@
                  const MCLDInfo& pInfo,
                  MCLinker& pLinker);
 
-protected:
-  uint64_t getSymbolSize(const LDSymbol& pSymbol) const;
-
-  uint64_t getSymbolInfo(const LDSymbol& pSymbol) const;
-
-  uint64_t getSymbolValue(const LDSymbol& pSymbol) const;
-
-  uint64_t getSymbolShndx(const LDSymbol& pSymbol, const Layout& pLayout) const;
-
-private:
   /// preLayout - Backend can do any needed modification before layout
   virtual void doPreLayout(const Output& pOutput,
                          const MCLDInfo& pInfo,
@@ -276,6 +363,11 @@
                           const MCLDInfo& pInfo,
                           MCLinker& pLinker) = 0;
 
+  /// postProcessing - Backend can do any needed modification in the final stage
+  void postProcessing(const Output& pOutput,
+                      const MCLDInfo& pInfo,
+                      MCLinker& pLinker);
+
   /// dynamic - the dynamic section of the target machine.
   virtual ELFDynamic& dynamic() = 0;
 
@@ -283,37 +375,81 @@
   virtual const ELFDynamic& dynamic() const = 0;
 
 protected:
+  // Based on Kind in LDFileFormat to define basic section orders for ELF, and
+  // refer gold linker to add more enumerations to handle Regular and BSS kind
+  enum SectionOrder {
+    SHO_INTERP = 1,          // .interp
+    SHO_RO_NOTE,             // .note.ABI-tag, .note.gnu.build-id
+    SHO_NAMEPOOL,            // *.hash, .dynsym, .dynstr
+    SHO_RELOCATION,          // .rel.*, .rela.*
+    SHO_REL_PLT,             // .rel.plt should come after other .rel.*
+    SHO_INIT,                // .init
+    SHO_PLT,                 // .plt
+    SHO_TEXT,                // .text
+    SHO_FINI,                // .fini
+    SHO_RO,                  // .rodata
+    SHO_EXCEPTION,           // .eh_frame_hdr, .eh_frame, .gcc_except_table
+    SHO_TLS_DATA,            // .tdata
+    SHO_TLS_BSS,             // .tbss
+    SHO_RELRO_LOCAL,         // .data.rel.ro.local
+    SHO_RELRO,               // .data.rel.ro,
+    SHO_RELRO_LAST,          // for x86 to adjust .got if needed
+    SHO_NON_RELRO_FIRST,     // for x86 to adjust .got.plt if needed
+    SHO_DATA,                // .data
+    SHO_LARGE_DATA,          // .ldata
+    SHO_RW_NOTE,             //
+    SHO_SMALL_DATA,          // .sdata
+    SHO_SMALL_BSS,           // .sbss
+    SHO_BSS,                 // .bss
+    SHO_LARGE_BSS,           // .lbss
+    SHO_UNDEFINED = ~(0U)    // default order
+  };
+
+  typedef HashEntry<LDSymbol*, size_t, SymCompare> HashEntryType;
+  typedef HashTable<HashEntryType, PtrHash, EntryFactory<HashEntryType> > 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;
 
-  // -----  ELF segment factory  ----- //
+  // ELF segment factory
   ELFSegmentFactory m_ELFSegmentTable;
 
-  // -----  ELF special sections  ----- //
-
-protected:
-  /// getHashBucketCount - calculate hash bucket count.
-  /// @ref Google gold linker, dynobj.cc:791
-  static unsigned getHashBucketCount(unsigned pNumOfSymbols, bool pIsGNUStyle);
-
-  /// isDynamicSymbol
-  /// @ref Google gold linker: symtab.cc:311
-  static bool isDynamicSymbol(const LDSymbol& pSymbol, const Output& pOutput);
-
-protected:
-  typedef HashEntry<LDSymbol*, size_t, SymCompare> HashEntryType;
-  typedef HashTable<HashEntryType, PtrHash, EntryFactory<HashEntryType> > HashTableType;
-
-  /// m_pSymIndexMap - Map the LDSymbol to its index in the output symbol table
+  // map the LDSymbol to its index in the output symbol table
   HashTableType* m_pSymIndexMap;
+
+  // section .eh_frame_hdr
+  EhFrameHdr* m_pEhFrameHdr;
+
+  // -----  standard symbols  ----- //
+  // section symbols
+  LDSymbol* f_pPreInitArrayStart;
+  LDSymbol* f_pPreInitArrayEnd;
+  LDSymbol* f_pInitArrayStart;
+  LDSymbol* f_pInitArrayEnd;
+  LDSymbol* f_pFiniArrayStart;
+  LDSymbol* f_pFiniArrayEnd;
+  LDSymbol* f_pStack;
+
+  // segment symbols
+  LDSymbol* f_pExecutableStart;
+  LDSymbol* f_pEText;
+  LDSymbol* f_p_EText;
+  LDSymbol* f_p__EText;
+  LDSymbol* f_pEData;
+  LDSymbol* f_p_EData;
+  LDSymbol* f_pBSSStart;
+  LDSymbol* f_pEnd;
+  LDSymbol* f_p_End;
 };
 
 } // namespace of mcld
diff --git a/include/mcld/Target/OutputRelocSection.h b/include/mcld/Target/OutputRelocSection.h
index c0cb5ca..fe83f2a 100644
--- a/include/mcld/Target/OutputRelocSection.h
+++ b/include/mcld/Target/OutputRelocSection.h
@@ -1,4 +1,4 @@
-//===- OutputRelocSection.h --------------------------------------------------===//
+//===- OutputRelocSection.h -----------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef OUTPUTRELOCSECTION_H
-#define OUTPUTRELOCSECTION_H
+#ifndef MCLD_OUTPUT_RELOCATION_SECTION_H
+#define MCLD_OUTPUT_RELOCATION_SECTION_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -28,15 +28,10 @@
 class OutputRelocSection
 {
 public:
-  typedef llvm::DenseMap<const ResolveInfo*, Relocation*> SymRelMapType;
-  typedef SymRelMapType::iterator SymRelMapIterator;
-
-  typedef llvm::MCSectionData::iterator MCFragmentIterator;
-
-public:
   OutputRelocSection(LDSection& pSection,
                    llvm::MCSectionData& pSectionData,
                    unsigned int pEntrySize);
+
   ~OutputRelocSection();
 
   void reserveEntry(RelocationFactory& pRelFactory, size_t pNum=1);
@@ -46,6 +41,13 @@
                        bool& pExist);
 
 private:
+  typedef llvm::DenseMap<const ResolveInfo*, Relocation*> SymRelMapType;
+
+  typedef SymRelMapType::iterator SymRelMapIterator;
+
+  typedef llvm::MCSectionData::iterator MCFragmentIterator;
+
+private:
   /// m_pSection - LDSection of this Section
   LDSection* m_pSection;
 
@@ -56,7 +58,7 @@
   unsigned int m_EntryBytes;
 
   /// m_isVisit - First time visit the function getEntry() or not
-  bool m_isVisit ;
+  bool m_isVisit;
 
   /// m_ValidEntryIterator - point to the first valid entry
   MCFragmentIterator m_ValidEntryIterator;
diff --git a/include/mcld/Target/TargetLDBackend.h b/include/mcld/Target/TargetLDBackend.h
index 781b86f..205e1f2 100644
--- a/include/mcld/Target/TargetLDBackend.h
+++ b/include/mcld/Target/TargetLDBackend.h
@@ -11,6 +11,7 @@
 
 #include <llvm/Support/DataTypes.h>
 #include <mcld/MC/MCLDOutput.h>
+#include <mcld/LD/EhFrame.h>
 
 namespace mcld {
 
@@ -23,6 +24,7 @@
 class DynObjReader;
 class ObjectWriter;
 class DynObjWriter;
+class ExecWriter;
 class LDContext;
 class SectionMap;
 class Output;
@@ -50,9 +52,9 @@
   virtual bool initTargetSectionMap(SectionMap& pSectionMap) { return true;}
   virtual void initTargetSegments(MCLinker& pLinker) { }
   virtual void initTargetSections(MCLinker& pLinker) { }
-  virtual void initTargetSymbols(MCLinker& pLinker) { }
+  virtual void initTargetSymbols(MCLinker& pLinker, const Output& pOutput) { }
   virtual void initTargetRelocation(MCLinker& pLinker) { }
-  virtual bool initStandardSymbols(MCLinker& pLinker) = 0;
+  virtual bool initStandardSymbols(MCLinker& pLinker, const Output& pOutput) = 0;
   virtual bool initRelocFactory(const MCLinker& pLinker) = 0;
 
   virtual RelocationFactory* getRelocFactory() = 0;
@@ -68,7 +70,8 @@
                               const LDSymbol& pInputSym,
                               MCLinker& pLinker,
                               const MCLDInfo& pLDInfo,
-                              const Output& pOutput) = 0;
+                              const Output& pOutput,
+                              const LDSection& pSection) = 0;
 
   // -----  format dependent  ----- //
   virtual bool initArchiveReader(MCLinker&, MCLDInfo&) = 0;
@@ -76,6 +79,7 @@
   virtual bool initDynObjReader(MCLinker&) = 0;
   virtual bool initObjectWriter(MCLinker&) = 0;
   virtual bool initDynObjWriter(MCLinker&) = 0;
+  virtual bool initExecWriter(MCLinker&) = 0;
 
   virtual bool initExecSections(MCLinker&) = 0;
   virtual bool initDynObjSections(MCLinker&) = 0;
@@ -85,6 +89,7 @@
   virtual DynObjReader *getDynObjReader() = 0;
   virtual ObjectWriter *getObjectWriter() = 0;
   virtual DynObjWriter *getDynObjWriter() = 0;
+  virtual ExecWriter *getExecWriter() = 0;
 
   virtual LDFileFormat* getDynObjFileFormat() = 0;
   virtual LDFileFormat* getExecFileFormat() = 0;
@@ -99,21 +104,30 @@
                           const MCLDInfo& pInfo,
                           MCLinker& 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;
+
   /// Is the target machine little endian? **/
   virtual bool isLittleEndian() const = 0;
 
   /// bit class. the bit length of the target machine, 32 or 64 **/
   virtual unsigned int bitclass() const = 0;
 
-  /// the page size of the target machine
-  virtual unsigned int pagesize() const = 0;
+  /// the common page size of the target machine
+  virtual uint64_t commonPageSize(const MCLDInfo& pInfo) const = 0;
+
+  /// the abi page size of the target machine
+  virtual uint64_t abiPageSize(const MCLDInfo& pInfo) 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 = 0;
+                                       const LDSection& pSectHdr,
+                                       const MCLDInfo& pInfo) const = 0;
 
   /// sizeNamePools - compute the size of regular name pools
   /// In ELF executable files, regular name pools are .symtab, .strtab.,
@@ -127,7 +141,7 @@
   /// 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 finalizeSymbol(LDSymbol& pSymbol) const = 0;
+  virtual bool finalizeSymbols(MCLinker& pLinker, const Output& pOutput) = 0;
 
   /// allocateCommonSymbols - allocate common symbols in the corresponding
   /// sections.
@@ -139,6 +153,22 @@
                            LDSection& pInputSectHdr)
   { return true; }
 
+  /// dyld - the name of the default dynamic linker
+  virtual const char* dyld() const = 0;
+
+  /// sizeInterp - compute the size of program interpreter's name
+  /// In ELF executables, this is the length of dynamic linker's path name
+  virtual void sizeInterp(const Output& pOutput, const MCLDInfo& pLDInfo) = 0;
+
+public:
+  EhFrame* getEhFrame();
+
+  const EhFrame* getEhFrame() const;
+
+private:
+  /// m_pEhFrame - section .eh_frame
+  EhFrame* m_pEhFrame;
+
 };
 
 } // End mcld namespace
diff --git a/include/mcld/Target/TargetMachine.h b/include/mcld/Target/TargetMachine.h
index 438edfd..02df7fd 100644
--- a/include/mcld/Target/TargetMachine.h
+++ b/include/mcld/Target/TargetMachine.h
@@ -36,7 +36,6 @@
 enum CodeGenFileType {
   CGFT_ASMFile,
   CGFT_OBJFile,
-  CGFT_ARCFile,
   CGFT_DSOFile,
   CGFT_EXEFile,
   CGFT_NULLFile
diff --git a/lib/ADT/StringEntry.cpp b/lib/ADT/StringEntry.cpp
new file mode 100644
index 0000000..c853f83
--- /dev/null
+++ b/lib/ADT/StringEntry.cpp
@@ -0,0 +1,48 @@
+//===- StringEntry.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/ADT/StringEntry.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// StringEntry<llvm::StringRef>
+StringEntry<llvm::StringRef>::StringEntry()
+{
+}
+
+StringEntry<llvm::StringRef>::StringEntry(const StringEntry::key_type& pKey)
+{
+}
+
+StringEntry<llvm::StringRef>::StringEntry(const StringEntry<llvm::StringRef>& pCopy)
+{
+  assert("Copy constructor of StringEntry should not be called!");
+}
+
+StringEntry<llvm::StringRef>::~StringEntry()
+{
+  if (!m_Value.empty())
+    free(const_cast<char*>(m_Value.data()));
+}
+
+void StringEntry<llvm::StringRef>::setValue(llvm::StringRef& pVal)
+{
+  char* data = (char*)malloc(pVal.size()+1);
+  strcpy(data, pVal.data());
+  m_Value = llvm::StringRef(data, pVal.size());
+}
+
+void StringEntry<llvm::StringRef>::setValue(const char* pVal)
+{
+  size_t length = strlen(pVal);
+  char* data = (char*)malloc(length+1);
+  strcpy(data, pVal);
+  m_Value = llvm::StringRef(data, length);
+}
+
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index 13efa96..e24596c 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -231,10 +231,6 @@
     pPM.add(createGCInfoDeleter()); // not in addPassesToMC
     break;
   }
-  case CGFT_ARCFile: {
-    assert(0 && "Output to archive file has not been supported yet!");
-    break;
-  }
   case CGFT_EXEFile: {
     if (pLinkerOpt == NULL)
       return true;
@@ -378,7 +374,7 @@
     return true;
   pPM.add(printer);
 #endif
-  TargetLDBackend* ldBackend = getTarget().createLDBackend(*getTarget().get(), m_Triple);
+  TargetLDBackend* ldBackend = getTarget().createLDBackend(m_Triple);
   if (0 == ldBackend)
     return true;
 
@@ -410,3 +406,4 @@
   pPM.add(funcPass);
   return false;
 }
+
diff --git a/lib/CodeGen/SectLinker.cpp b/lib/CodeGen/SectLinker.cpp
index 95e9e4f..4f32c4f 100644
--- a/lib/CodeGen/SectLinker.cpp
+++ b/lib/CodeGen/SectLinker.cpp
@@ -10,19 +10,20 @@
 // This file implements the SectLinker class.
 //
 //===----------------------------------------------------------------------===//
-
-#include <mcld/ADT/BinTree.h>
+#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 <mcld/MC/MCLDInputTree.h>
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/Support/DerivedPositionDependentOptions.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Target/TargetLDBackend.h>
 
 #include <llvm/Module.h>
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/Support/raw_ostream.h>
 
 #include <algorithm>
 #include <stack>
@@ -44,11 +45,16 @@
   : MachineFunctionPass(m_ID),
     m_pOption(&pOption),
     m_pLDBackend(&pLDBackend),
-    m_pLDDriver(NULL) { }
+    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
@@ -57,36 +63,19 @@
   // 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();
 
-  // setup the output
-  info.output().setContext(info.contextFactory().produce(info.output().path()));
-
-  int mode = (Output::Object == info.output().type())? 0544 : 0755;
-  info.output().setMemArea(
-      info.memAreaFactory().produce(info.output().path(),
-                                    O_RDWR | O_CREAT | O_TRUNC,
-                                    mode));
-
-  //   make sure output is openend successfully.
-  if (!info.output().hasMemArea())
-    report_fatal_error("output is not given on the command line\n");
-
-  if (!info.output().memArea()->isGood())
-    report_fatal_error("can not open output file :"+info.output().path().native());
-
-  // let the target override the target-specific parameters
-  addTargetOptions(pM, *m_pOption);
-
   // ----- 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);
 
@@ -97,42 +86,45 @@
 {
   const MCLDInfo &info = m_pOption->info();
 
-  // 3. - initialize output's standard segments and sections
+  // 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().verbose()) {
-    outs() << "MCLinker (LLVM Sub-project) - ";
-    outs() << MCLDInfo::version();
-    outs() << "\n";
-  }
-
   if (info.options().trace()) {
     static int counter = 0;
-    outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
+    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) {
-      outs() << counter++ << " *  " << (*input)->name();
+      mcld::outs() << counter++ << " *  " << (*input)->name();
       switch((*input)->type()) {
       case Input::Archive:
-        outs() << "\tarchive\t(";
+        mcld::outs() << "\tarchive\t(";
         break;
       case Input::Object:
-        outs() << "\tobject\t(";
+        mcld::outs() << "\tobject\t(";
         break;
       case Input::DynObj:
-        outs() << "\tshared\t(";
+        mcld::outs() << "\tshared\t(";
         break;
       case Input::Script:
-        outs() << "\tscript\t(";
+        mcld::outs() << "\tscript\t(";
+        break;
+      case Input::External:
+        mcld::outs() << "\textern\t(";
         break;
       default:
-        report_fatal_error("** Trace a unsupported file. It must be an internal bug!");
+        unreachable(diag::err_cannot_trace_file) << (*input)->type()
+                                                 << (*input)->name()
+                                                 << (*input)->path();
       }
-      outs() << (*input)->path().c_str() << ")\n";
+      mcld::outs() << (*input)->path() << ")\n";
     }
   }
 
@@ -147,8 +139,7 @@
     return true;
 
   // 7. - read all symbol tables of input files and resolve them
-  if (!m_pLDDriver->readSymbolTables() ||
-      !m_pLDDriver->mergeSymbolTables())
+  if (!m_pLDDriver->readSymbolTables())
     return true;
 
   // 7.a - add standard symbols and target-dependent symbols
@@ -173,7 +164,7 @@
   m_pLDDriver->finalizeSymbolValue();
 
   // 12. - apply relocations
-  m_pLDDriver->relocate();
+  m_pLDDriver->relocation();
 
   // 13. - write out output
   m_pLDDriver->emitOutput();
@@ -189,86 +180,188 @@
   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())
-    return;
+    fatal(diag::err_no_inputs);
 
   MCLDInfo &info = m_pOption->info();
-  PositionDependentOptions::const_iterator cur_char = pPosDepOptions.begin();
+  PositionDependentOptions::const_iterator option = pPosDepOptions.begin();
   if (1 == pPosDepOptions.size() &&
-      ((*cur_char)->type() != PositionDependentOption::INPUT_FILE &&
-       (*cur_char)->type() != PositionDependentOption::NAMESPEC))
-    return;
+      ((*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);
+  }
 
-  InputTree::Connector *prev_ward = &InputTree::Downward;
+  // -----  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;
-  InputTree::iterator cur_node = info.inputs().root();
 
-  PositionDependentOptions::const_iterator charEnd = pPosDepOptions.end();
-  while (cur_char != charEnd ) {
-    switch ((*cur_char)->type()) {
-    case PositionDependentOption::BITCODE: {
-      // threat bitcode as a script in this version.
-      const BitcodeOption *bitcode_option =
-          static_cast<const BitcodeOption*>(*cur_char);
-      info.inputs().insert(cur_node,
-                           *prev_ward,
-                           bitcode_option->path()->native(),
-                           *(bitcode_option->path()),
-                           Input::Script);
-      info.setBitcode(**cur_node);
-      prev_ward->move(cur_node);
-      prev_ward = &InputTree::Afterward;
-      break;
-    }
-    case PositionDependentOption::INPUT_FILE: {
-      const InputFileOption *input_file_option =
-          static_cast<const InputFileOption*>(*cur_char);
-      info.inputs().insert(cur_node,
-                           *prev_ward,
-                           input_file_option->path()->native(),
-                           *(input_file_option->path()));
-      prev_ward->move(cur_node);
-      prev_ward = &InputTree::Afterward;
-      break;
-    }
+  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 = 0;
+      sys::fs::Path* path = NULL;
       const NamespecOption *namespec_option =
-          static_cast<const NamespecOption*>(*cur_char);
-      if (info.attrFactory().last().isStatic()) {
+          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);
       }
-      else {
-        path = info.options().directories().find(namespec_option->namespec(),
-                                                 Input::DynObj);
-      }
 
-      if (0 == path) {
-        llvm::report_fatal_error(std::string("Can't find namespec: ")+
-                                 namespec_option->namespec());
-      }
-      info.inputs().insert(cur_node,
-                           *prev_ward,
+      if (NULL == path)
+        fatal(diag::err_cannot_find_namespec) << namespec_option->namespec();
+
+      info.inputs().insert(root, *move,
                            namespec_option->namespec(),
                            *path);
-      prev_ward->move(cur_node);
-      prev_ward = &InputTree::Afterward;
+
+      // 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(cur_node, *prev_ward);
-      prev_ward->move(cur_node);
-      returnStack.push(cur_node);
-      prev_ward = &InputTree::Downward;
+      info.inputs().enterGroup(root, *move);
+      move->move(root);
+      returnStack.push(root);
+      move = &InputTree::Downward;
       break;
+    /** end group **/
     case PositionDependentOption::END_GROUP:
-      cur_node = returnStack.top();
+      root = returnStack.top();
       returnStack.pop();
-      prev_ward = &InputTree::Afterward;
+      move = &InputTree::Afterward;
       break;
     case PositionDependentOption::WHOLE_ARCHIVE:
       info.attrFactory().last().setWholeArchive();
@@ -295,10 +388,11 @@
       info.attrFactory().last().setDynamic();
       break;
     default:
-      report_fatal_error("can not find the type of input file");
-    }
-    ++cur_char;
-  }
+      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");
diff --git a/lib/LD/BSDArchiveReader.cpp b/lib/LD/BSDArchiveReader.cpp
index 1264824..079153b 100644
--- a/lib/LD/BSDArchiveReader.cpp
+++ b/lib/LD/BSDArchiveReader.cpp
@@ -6,9 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInput.h"
-#include "mcld/MC/MCLDInputTree.h"
-#include "mcld/LD/BSDArchiveReader.h"
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/InputTree.h>
+#include <mcld/LD/BSDArchiveReader.h>
 
 using namespace mcld;
 
diff --git a/lib/LD/CIE.cpp b/lib/LD/CIE.cpp
new file mode 100644
index 0000000..c2f4317
--- /dev/null
+++ b/lib/LD/CIE.cpp
@@ -0,0 +1,23 @@
+//===- CIE.cpp ------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/CIE.h>
+
+using namespace mcld;
+
+//==========================
+// CIE
+
+CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
+  : MCRegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+}
+
+CIE::~CIE()
+{
+}
diff --git a/lib/LD/DWARFLineInfo.cpp b/lib/LD/DWARFLineInfo.cpp
new file mode 100644
index 0000000..63c588d
--- /dev/null
+++ b/lib/LD/DWARFLineInfo.cpp
@@ -0,0 +1,15 @@
+//===- DWARFLineInfo.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DWARFLineInfo.h>
+
+using namespace mcld;
+
+//==========================
+// DWARFLineInfo
+
diff --git a/lib/LD/Diagnostic.cpp b/lib/LD/Diagnostic.cpp
new file mode 100644
index 0000000..5175ebd
--- /dev/null
+++ b/lib/LD/Diagnostic.cpp
@@ -0,0 +1,173 @@
+//===- Diagnostic.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/Diagnostic.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/ADT/Twine.h>
+#include <ctype.h>
+#include <algorithm>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+//  Diagnostic
+Diagnostic::Diagnostic(DiagnosticEngine& pEngine)
+  : m_Engine(pEngine) {
+}
+
+Diagnostic::~Diagnostic()
+{
+}
+
+// format - format this diagnostic into string, subsituting the formal
+// arguments. The result is appended at on the pOutStr.
+void Diagnostic::format(std::string& pOutStr) const
+{
+  // we've not implemented DWARF LOC messages yet. So, keep pIsLoC false 
+  llvm::StringRef desc = m_Engine.infoMap().getDescription(getID(), false);
+
+  format(desc.begin(), desc.end(), pOutStr);
+}
+
+const char* Diagnostic::findMatch(char pVal,
+                                  const char* pBegin, const char* pEnd ) const
+{
+  unsigned int depth = 0;
+  for (; pBegin != pEnd; ++pBegin) {
+    if (0 == depth && *pBegin == pVal)
+      return pBegin;
+    if (0 != depth && *pBegin == '}')
+      --depth;
+
+    if ('%' == *pBegin) {
+      ++pBegin;
+      if (pBegin == pEnd)
+        break;
+
+      if (!isdigit(*pBegin) && !ispunct(*pBegin)) {
+        ++pBegin;
+        while (pBegin != pEnd && !isdigit(*pBegin) && *pBegin != '{')
+          ++pBegin;
+
+        if (pBegin == pEnd)
+          break;
+        if ('{' == *pBegin)
+          ++depth;
+      }
+    }
+  } // end of for
+  return pEnd;
+}
+
+// format - format the given formal string, subsituting the formal
+// arguments. The result is appended at on the pOutStr.
+void Diagnostic::format(const char* pBegin, const char* pEnd,
+                        std::string& pOutStr) const
+{
+  const char* cur_char = pBegin;
+  while (cur_char != pEnd) {
+    if ('%' != *cur_char) {
+      const char* new_end = std::find(cur_char, pEnd, '%');
+      pOutStr.append(cur_char, new_end);
+      cur_char = new_end;
+      continue;
+    }
+    else if (ispunct(cur_char[1])) {
+      pOutStr.push_back(cur_char[1]);  // %% -> %.
+      cur_char += 2;
+      continue;
+    }
+
+    // skip the %.
+    ++cur_char;
+
+    const char* modifier = NULL, *argument = NULL;
+    size_t modifier_len = 0, argument_len = 0;
+
+    // we get a modifier
+    if (!isdigit(*cur_char)) {
+      modifier = cur_char;
+      while (*cur_char == '-' || (*cur_char >= 'a' && *cur_char <= 'z'))
+        ++cur_char;
+      modifier_len = cur_char - modifier;
+
+      // we get an argument
+      if ('{' == *cur_char) {
+        ++cur_char; // skip '{'
+        argument = cur_char;
+        cur_char = findMatch('}', cur_char, pEnd);
+
+        if (cur_char == pEnd) {
+          // DIAG's format error
+          llvm::report_fatal_error(llvm::Twine("Mismatched {} in the diagnostic: ") +
+                                   llvm::Twine(getID()));
+        }
+
+        argument_len = cur_char - argument;
+        ++cur_char; // skip '}'
+      }
+    }
+    if (!isdigit(*cur_char)) {
+      llvm::report_fatal_error(llvm::Twine("In diagnostic: ") +
+                               llvm::Twine(getID()) + llvm::Twine(": ") +
+                               llvm::Twine(pBegin) +
+                               llvm::Twine("\nNo given arugment number:\n"));
+    }
+
+    unsigned int arg_no = *cur_char - '0';
+    ++cur_char; // skip argument number
+
+    DiagnosticEngine::ArgumentKind kind = getArgKind(arg_no);
+    switch (kind) {
+      case DiagnosticEngine::ak_std_string: {
+        if (0 != modifier_len) {
+          llvm::report_fatal_error(llvm::Twine("In diagnostic: ") +
+                                   llvm::Twine(getID()) +
+                                   llvm::Twine(": ") + llvm::Twine(pBegin) +
+                                   llvm::Twine("\nNo modifiers for strings yet\n"));
+        }
+        const std::string& str = getArgStdStr(arg_no);
+        pOutStr.append(str.begin(), str.end());
+        break;
+      }
+      case DiagnosticEngine::ak_c_string: {
+        if (0 != modifier_len) {
+          llvm::report_fatal_error(llvm::Twine("In diagnostic: ") +
+                                   llvm::Twine(getID()) +
+                                   llvm::Twine(": ") + llvm::Twine(pBegin) +
+                                   llvm::Twine("\nNo modifiers for strings yet\n"));
+        }
+        const char* str = getArgCStr(arg_no);
+        if (NULL == str)
+          str = "(null)";
+        pOutStr.append(str);
+        break;
+      }
+      case DiagnosticEngine::ak_sint: {
+        int val = getArgSInt(arg_no);
+        llvm::raw_string_ostream(pOutStr) << val;
+        break;
+      }
+      case DiagnosticEngine::ak_uint: {
+        unsigned int val = getArgUInt(arg_no);
+        llvm::raw_string_ostream(pOutStr) << val;
+        break;
+      }
+      case DiagnosticEngine::ak_bool: {
+        bool val = getArgBool(arg_no);
+        if (val)
+          pOutStr.append("true");
+        else
+          pOutStr.append("false");
+        break;
+      }
+    } // end of switch
+  } // end of while
+}
+
diff --git a/lib/LD/DiagnosticEngine.cpp b/lib/LD/DiagnosticEngine.cpp
new file mode 100644
index 0000000..11dbe1b
--- /dev/null
+++ b/lib/LD/DiagnosticEngine.cpp
@@ -0,0 +1,58 @@
+//===- DiagnosticEngine.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticEngine.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/MC/MCLDInfo.h>
+
+using namespace mcld;
+
+//==========================
+// DiagnosticEngine
+DiagnosticEngine::DiagnosticEngine(const MCLDInfo& pLDInfo,
+                                   DiagnosticLineInfo* pLineInfo,
+                                   DiagnosticPrinter* pPrinter,
+                                   bool pShouldOwnPrinter)
+  : m_LDInfo(pLDInfo),
+    m_pLineInfo(pLineInfo),
+    m_pPrinter(pPrinter),
+    m_InfoMap(pLDInfo),
+    m_OwnPrinter(pShouldOwnPrinter) {
+  if (NULL == m_pPrinter) {
+    m_pPrinter = new DiagnosticPrinter(); // Dumb printer
+    m_OwnPrinter = true;
+  }
+}
+
+DiagnosticEngine::~DiagnosticEngine()
+{
+  if (m_OwnPrinter && m_pPrinter != NULL)
+    delete m_pPrinter;
+
+  if (NULL != m_pLineInfo)
+    delete m_pLineInfo;
+}
+
+void DiagnosticEngine::setPrinter(DiagnosticPrinter& pPrinter,
+                                  bool pShouldOwnPrinter)
+{
+  if (m_OwnPrinter && m_pPrinter != NULL)
+    delete m_pPrinter;
+  m_pPrinter = &pPrinter;
+  m_OwnPrinter = pShouldOwnPrinter;
+}
+
+// emit - process current diagnostic.
+bool DiagnosticEngine::emit()
+{
+  bool emitted = m_InfoMap.process(*this);
+  m_State.reset();
+  return emitted;
+}
+
diff --git a/lib/LD/DiagnosticInfos.cpp b/lib/LD/DiagnosticInfos.cpp
new file mode 100644
index 0000000..b9a6fa9
--- /dev/null
+++ b/lib/LD/DiagnosticInfos.cpp
@@ -0,0 +1,149 @@
+//===- DiagnosticInfo.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
+
+#include <mcld/ADT/SizeTraits.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LD/Diagnostic.h>
+#include <mcld/LD/DiagnosticInfos.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+
+using namespace mcld;
+
+namespace {
+
+struct DiagStaticInfo
+{
+public:
+  uint16_t ID;
+  DiagnosticEngine::Severity Severity;
+  uint16_t DescriptionLen;
+  const char* DescriptionStr;
+
+public:
+  llvm::StringRef getDescription() const
+  { return llvm::StringRef(DescriptionStr, DescriptionLen); }
+
+  bool operator<(const DiagStaticInfo& pRHS) const
+  { return (ID < pRHS.ID); }
+};
+
+} // namespace anonymous
+
+static const DiagStaticInfo DiagCommonInfo[] = {
+#define DIAG(ENUM, CLASS, ADDRDESC, LOCDESC) \
+  { diag::ENUM, CLASS, STR_SIZE(ADDRDESC, uint16_t), ADDRDESC },
+#include "mcld/LD/DiagCommonKinds.inc"
+#include "mcld/LD/DiagReaders.inc"
+#include "mcld/LD/DiagSymbolResolutions.inc"
+#include "mcld/LD/DiagRelocations.inc"
+#include "mcld/LD/DiagLayouts.inc"
+#include "mcld/LD/DiagGOTPLT.inc"
+#undef DIAG
+  { 0, DiagnosticEngine::None, 0, 0}
+};
+
+static const unsigned int DiagCommonInfoSize =
+  sizeof(DiagCommonInfo)/sizeof(DiagCommonInfo[0])-1;
+
+static const DiagStaticInfo DiagLoCInfo[] = {
+#define DIAG(ENUM, CLASS, ADDRDESC, LOCDESC) \
+  { diag::ENUM, CLASS, STR_SIZE(LOCDESC, uint16_t), LOCDESC },
+#include "mcld/LD/DiagReaders.inc"
+#include "mcld/LD/DiagSymbolResolutions.inc"
+#include "mcld/LD/DiagRelocations.inc"
+#include "mcld/LD/DiagLayouts.inc"
+#include "mcld/LD/DiagGOTPLT.inc"
+#undef DIAG
+  { 0, DiagnosticEngine::None, 0, 0}
+};
+
+static const unsigned int DiagLoCInfoSize =
+  sizeof(DiagLoCInfo)/sizeof(DiagLoCInfo[0])-1;
+
+
+static const DiagStaticInfo* getDiagInfo(unsigned int pID, bool pInLoC = false)
+{
+  const DiagStaticInfo* static_info = (pInLoC)?DiagLoCInfo:DiagCommonInfo;
+  unsigned int info_size = (pInLoC)?DiagLoCInfoSize:DiagCommonInfoSize;
+
+  DiagStaticInfo key = { static_cast<uint16_t>(pID), DiagnosticEngine::None, 0, 0 };
+  const DiagStaticInfo *result = std::lower_bound(static_info, static_info + info_size, key);
+
+  if (result == (static_info + info_size) || result->ID != pID)
+    return NULL;
+
+  return result;
+}
+
+//===----------------------------------------------------------------------===//
+//  DiagnosticInfos
+DiagnosticInfos::DiagnosticInfos(const MCLDInfo& pLDInfo)
+  : m_LDInfo(pLDInfo) {
+}
+
+DiagnosticInfos::~DiagnosticInfos()
+{
+}
+
+llvm::StringRef DiagnosticInfos::getDescription(unsigned int pID, bool pInLoC) const
+{
+  return getDiagInfo(pID, pInLoC)->getDescription();
+}
+
+bool DiagnosticInfos::process(DiagnosticEngine& pEngine) const
+{
+  Diagnostic info(pEngine);
+
+  unsigned int ID = info.getID();
+
+  // we are not implement LineInfo, so keep pIsLoC false.
+  const DiagStaticInfo* static_info = getDiagInfo(ID);
+
+  DiagnosticEngine::Severity severity = static_info->Severity;
+
+  switch (ID) {
+    case diag::multiple_definitions: {
+      if (m_LDInfo.options().hasMulDefs()) {
+        severity = DiagnosticEngine::Ignore;
+      }
+      break;
+    }
+    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())
+            severity = DiagnosticEngine::Error;
+          else
+            severity = DiagnosticEngine::Ignore;
+        break;
+        case Output::DynObj:
+          if (m_LDInfo.options().isNoUndefined() || !m_LDInfo.options().isAllowShlibUndefined())
+            severity = DiagnosticEngine::Error;
+          else
+            severity = DiagnosticEngine::Ignore;
+        break;
+        case Output::Exec:
+          severity = DiagnosticEngine::Error;
+        break;
+      }
+      break;
+    }
+    default:
+      break;
+  } // end of switch
+
+  // finally, report it.
+  pEngine.getPrinter()->handleDiagnostic(severity, info);
+  return true;
+}
+
diff --git a/lib/LD/DiagnosticLineInfo.cpp b/lib/LD/DiagnosticLineInfo.cpp
new file mode 100644
index 0000000..d3c9190
--- /dev/null
+++ b/lib/LD/DiagnosticLineInfo.cpp
@@ -0,0 +1,15 @@
+//===- DiagnosticLineInfo.cpp ---------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticLineInfo.h>
+
+using namespace mcld;
+
+//==========================
+// DiagnosticLineInfo
+
diff --git a/lib/LD/DiagnosticPrinter.cpp b/lib/LD/DiagnosticPrinter.cpp
new file mode 100644
index 0000000..7bbf473
--- /dev/null
+++ b/lib/LD/DiagnosticPrinter.cpp
@@ -0,0 +1,34 @@
+//===- DiagnosticPrinter.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticPrinter.h>
+
+using namespace mcld;
+
+//==========================
+// DiagnosticPrinter
+DiagnosticPrinter::DiagnosticPrinter()
+  : m_NumErrors(0), m_NumWarnings(0) {
+}
+
+DiagnosticPrinter::~DiagnosticPrinter()
+{
+  clear();
+}
+
+/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+/// capturing it to a log as needed.
+void DiagnosticPrinter::handleDiagnostic(DiagnosticEngine::Severity pSeverity,
+                                         const Diagnostic& pInfo)
+{
+  if (pSeverity == DiagnosticEngine::Warning)
+    ++m_NumWarnings;
+  else if (pSeverity <= DiagnosticEngine::Error)
+    ++m_NumErrors;
+}
+
diff --git a/lib/LD/ELFDynObjFileFormat.cpp b/lib/LD/ELFDynObjFileFormat.cpp
index 77034eb..30183cc 100644
--- a/lib/LD/ELFDynObjFileFormat.cpp
+++ b/lib/LD/ELFDynObjFileFormat.cpp
@@ -6,11 +6,11 @@
 // 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 <llvm/Support/ELF.h>
 #include <mcld/Target/GNULDBackend.h>
 
 using namespace mcld;
@@ -77,5 +77,10 @@
                                            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);
 }
 
diff --git a/lib/LD/ELFDynObjReader.cpp b/lib/LD/ELFDynObjReader.cpp
index 12e6d7c..de36104 100644
--- a/lib/LD/ELFDynObjReader.cpp
+++ b/lib/LD/ELFDynObjReader.cpp
@@ -69,9 +69,13 @@
   MemoryRegion* region = pInput.memArea()->request(0, hdr_size);
   uint8_t* ELF_hdr = region->start();
 
-  bool result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
+  bool shdr_result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
   pInput.memArea()->release(region);
-  return result;
+
+  // read .dynamic to get the correct SONAME
+  bool dyn_result = m_pELFReader->readDynamic(pInput);
+
+  return (shdr_result && dyn_result);
 }
 
 /// readSymbols
@@ -80,9 +84,20 @@
   assert(pInput.hasMemArea());
 
   LDSection* symtab_shdr = pInput.context()->getSection(".dynsym");
+  if (NULL == symtab_shdr) {
+    note(diag::note_has_no_symtab) << pInput.name()
+                                   << pInput.path()
+                                   << ".dynsym";
+    return true;
+  }
+
   LDSection* strtab_shdr = symtab_shdr->getLink();
-  if (NULL == symtab_shdr || NULL == strtab_shdr)
+  if (NULL == strtab_shdr) {
+    fatal(diag::fatal_cannot_read_strtab) << pInput.name()
+                                          << pInput.path()
+                                          << ".dynsym";
     return false;
+  }
 
   MemoryRegion* symtab_region = pInput.memArea()->request(symtab_shdr->offset(),
                                                           symtab_shdr->size());
diff --git a/lib/LD/ELFDynObjWriter.cpp b/lib/LD/ELFDynObjWriter.cpp
index 21cd8e4..cabc9e9 100644
--- a/lib/LD/ELFDynObjWriter.cpp
+++ b/lib/LD/ELFDynObjWriter.cpp
@@ -58,7 +58,10 @@
     switch(sect->kind()) {
       case LDFileFormat::Regular:
       case LDFileFormat::Relocation:
-      case LDFileFormat::Target: {
+      case LDFileFormat::Target:
+      case LDFileFormat::Debug:
+      case LDFileFormat::GCCExceptTable:
+      case LDFileFormat::EhFrame: {
         region = pOutput.memArea()->request(sect->offset(), sect->size());
         if (NULL == region) {
           llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") +
@@ -72,11 +75,10 @@
       case LDFileFormat::Null:
       case LDFileFormat::NamePool:
       case LDFileFormat::BSS:
-      case LDFileFormat::Debug:
       case LDFileFormat::Note:
       case LDFileFormat::MetaData:
-      case LDFileFormat::Exception:
       case LDFileFormat::Version:
+      case LDFileFormat::EhFrameHdr:
         // ignore these sections
         continue;
       default: {
@@ -91,7 +93,12 @@
 
     // write out sections with data
     switch(sect->kind()) {
-      case LDFileFormat::Regular: {
+      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);
         break;
       }
@@ -99,11 +106,16 @@
         emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
         break;
       case LDFileFormat::Target:
-        target().emitSectionData(pOutput, *sect, m_Linker.getLDInfo(), *region);
+        target().emitSectionData(pOutput,
+                                 *sect,
+                                 m_Linker.getLDInfo(),
+                                 m_Linker.getLayout(),
+                                 *region);
         break;
       default:
         continue;
     }
+
   } // end of for loop
 
   if (32 == target().bitclass()) {
@@ -116,6 +128,8 @@
                      target(),
                      pOutput);
 
+    emitELF32ProgramHeader(pOutput, target());
+
     emitELF32SectionHeader(pOutput, m_Linker);
   }
   else if (64 == target().bitclass()) {
@@ -128,11 +142,13 @@
                      target(),
                      pOutput);
 
+    emitELF64ProgramHeader(pOutput, target());
+
     emitELF64SectionHeader(pOutput, m_Linker);
   }
   else
     return make_error_code(errc::not_supported);
-
+  pOutput.memArea()->clear();
   return llvm::make_error_code(llvm::errc::success);
 }
 
diff --git a/lib/LD/ELFExecFileFormat.cpp b/lib/LD/ELFExecFileFormat.cpp
index f10d764..8ae0de0 100644
--- a/lib/LD/ELFExecFileFormat.cpp
+++ b/lib/LD/ELFExecFileFormat.cpp
@@ -6,8 +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>
 
 using namespace mcld;
 
+void ELFExecFileFormat::initObjectType(MCLinker& pLinker)
+{
+  // FIXME: make sure ELF executable files has these sections.
+  f_pDynSymTab    = &pLinker.getOrCreateOutputSectHdr(".dynsym",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_DYNSYM,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pDynStrTab    = &pLinker.getOrCreateOutputSectHdr(".dynstr",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_STRTAB,
+                                           llvm::ELF::SHF_ALLOC,
+                                           0x1);
+  f_pInterp       = &pLinker.getOrCreateOutputSectHdr(".interp",
+                                           LDFileFormat::Note,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC,
+                                           0x1);
+  f_pHashTab      = &pLinker.getOrCreateOutputSectHdr(".hash",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_HASH,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pDynamic      = &pLinker.getOrCreateOutputSectHdr(".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",
+                                           LDFileFormat::Relocation,
+                                           llvm::ELF::SHT_RELA,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pRelaPlt      = &pLinker.getOrCreateOutputSectHdr(".rela.plt",
+                                           LDFileFormat::Relocation,
+                                           llvm::ELF::SHT_RELA,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pRelDyn      = &pLinker.getOrCreateOutputSectHdr(".rel.dyn",
+                                           LDFileFormat::Relocation,
+                                           llvm::ELF::SHT_REL,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pRelPlt      = &pLinker.getOrCreateOutputSectHdr(".rel.plt",
+                                           LDFileFormat::Relocation,
+                                           llvm::ELF::SHT_REL,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pGOT          = &pLinker.getOrCreateOutputSectHdr(".got",
+                                           LDFileFormat::Target,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+                                           f_Backend.bitclass() / 8);
+  f_pPLT          = &pLinker.getOrCreateOutputSectHdr(".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",
+                                           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);
+}
diff --git a/lib/LD/ELFExecWriter.cpp b/lib/LD/ELFExecWriter.cpp
new file mode 100644
index 0000000..7438180
--- /dev/null
+++ b/lib/LD/ELFExecWriter.cpp
@@ -0,0 +1,157 @@
+//===- ELFExecWriter.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFExecWriter.h>
+#include <mcld/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 <llvm/Support/ELF.h>
+#include <vector>
+
+using namespace llvm;
+using namespace mcld;
+
+
+//==========================
+// ELFExecWriter
+ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker)
+  : ExecWriter(pBackend),
+    ELFWriter(pBackend),
+    m_Backend(pBackend),
+    m_Linker(pLinker) {
+
+}
+
+ELFExecWriter::~ELFExecWriter()
+{
+}
+
+llvm::error_code ELFExecWriter::writeExecutable(Output& pOutput)
+{
+  // write out the interpreter section: .interp
+  target().emitInterp(pOutput, m_Linker.getLDInfo());
+
+  // Write out name pool sections: .dynsym, .dynstr, .hash
+  target().emitDynNamePools(pOutput,
+                            m_Linker.getOutputSymbols(),
+                            m_Linker.getLayout(),
+                            m_Linker.getLDInfo());
+
+  // Write out name pool sections: .symtab, .strtab
+  target().emitRegNamePools(pOutput,
+                            m_Linker.getOutputSymbols(),
+                            m_Linker.getLayout(),
+                            m_Linker.getLDInfo());
+
+  // 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);
+    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.memArea()->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"));
+        }
+        break;
+      }
+      case LDFileFormat::Null:
+      case LDFileFormat::NamePool:
+      case LDFileFormat::BSS:
+      case LDFileFormat::Note:
+      case LDFileFormat::MetaData:
+      case LDFileFormat::Version:
+      case LDFileFormat::EhFrameHdr:
+        // 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(m_Linker.getLayout(), *sect, *region);
+        break;
+      }
+      case LDFileFormat::Relocation:
+        emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
+        break;
+      case LDFileFormat::Target:
+        target().emitSectionData(pOutput,
+                                 *sect,
+                                 m_Linker.getLDInfo(),
+                                 m_Linker.getLayout(),
+                                 *region);
+        break;
+      default:
+        continue;
+    }
+  } // end of for loop
+
+  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(),
+                     pOutput);
+
+    emitELF32ProgramHeader(pOutput, target());
+
+    emitELF32SectionHeader(pOutput, m_Linker);
+  }
+  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(),
+                     pOutput);
+
+    emitELF64ProgramHeader(pOutput, target());
+
+    emitELF64SectionHeader(pOutput, m_Linker);
+  }
+  else
+    return make_error_code(errc::not_supported);
+
+  pOutput.memArea()->clear();
+  return llvm::make_error_code(llvm::errc::success);
+}
+
diff --git a/lib/LD/ELFFileFormat.cpp b/lib/LD/ELFFileFormat.cpp
index 9394e44..f1c39cb 100644
--- a/lib/LD/ELFFileFormat.cpp
+++ b/lib/LD/ELFFileFormat.cpp
@@ -57,7 +57,8 @@
     f_pJCR(NULL),
     f_pNoteABITag(NULL),
     f_pStab(NULL),
-    f_pStabStr(NULL) {
+    f_pStabStr(NULL),
+    f_pStack(NULL) {
 
 }
 
@@ -186,7 +187,7 @@
   f_pDataRelRo      = &pLinker.getOrCreateOutputSectHdr(".data.rel.ro",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
-                                              llvm::ELF::SHF_ALLOC,
+                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
   f_pDtors          = &pLinker.getOrCreateOutputSectHdr(".dtors",
                                               LDFileFormat::Regular,
@@ -194,20 +195,15 @@
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
   f_pEhFrame        = &pLinker.getOrCreateOutputSectHdr(".eh_frame",
-                                              LDFileFormat::Exception,
+                                              LDFileFormat::EhFrame,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
-                                              0x1);
-  f_pEhFrameHdr     = &pLinker.getOrCreateOutputSectHdr(".eh_frame_hdr",
-                                              LDFileFormat::Exception,
-                                              llvm::ELF::SHT_PROGBITS,
-                                              llvm::ELF::SHF_ALLOC,
-                                              0x1);
+                                              0x4);
   f_pGCCExceptTable = &pLinker.getOrCreateOutputSectHdr(".gcc_except_table",
-                                              LDFileFormat::Exception,
+                                              LDFileFormat::GCCExceptTable,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
-                                              0x1);
+                                              0x4);
   f_pGNUVersion     = &pLinker.getOrCreateOutputSectHdr(".gnu.version",
                                               LDFileFormat::Version,
                                               llvm::ELF::SHT_GNU_versym,
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index abc3d30..1ea81e2 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -8,13 +8,13 @@
 //===----------------------------------------------------------------------===//
 #include <llvm/Support/ELF.h>
 #include <llvm/ADT/Twine.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/LD/ELFObjectReader.h>
 #include <mcld/LD/ELFReader.h>
 #include <mcld/MC/MCLDInput.h>
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/MCRegionFragment.h>
 #include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MsgHandling.h>
 
 #include <string>
 #include <cassert>
@@ -99,7 +99,14 @@
                                        (*section)->getInfo());
 
         bool exist = false;
-        signatures().insert(signature->name(), exist);
+        if (0 == std::strlen(signature->name()) &&
+            ResolveInfo::Section == signature->type()) {
+          // if the signature is a section symbol in input object, we use the
+          // section name as group signature.
+          signatures().insert((*section)->name(), exist);
+        } else {
+          signatures().insert(signature->name(), exist);
+        }
 
         if (exist) {
           // if this is not the first time we see this group signature, then
@@ -132,28 +139,32 @@
         break;
       }
       /** normal sections **/
-      // FIXME: support Debug, Exception and Version Kinds
-      case LDFileFormat::Debug:
-      case LDFileFormat::Exception:
+      // FIXME: support Version Kinds
       case LDFileFormat::Version:
       /** Fall through **/
       case LDFileFormat::Regular:
       case LDFileFormat::Note:
+      case LDFileFormat::Debug:
       case LDFileFormat::MetaData: {
         if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
-          llvm::report_fatal_error(
-                                llvm::Twine("can not read regular section `") +
-                                (*section)->name() +
-                                llvm::Twine("'.\n"));
+          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();
         break;
       }
       /** target dependent sections **/
       case LDFileFormat::Target: {
         if (!m_pELFReader->readTargetSection(pInput, m_Linker, **section))
-          llvm::report_fatal_error(
-                        llvm::Twine("can not read target dependentsection `") +
-                        (*section)->name() +
-                        llvm::Twine("'.\n"));
+          fatal(diag::err_cannot_read_target_section) << (*section)->name();
         break;
       }
       /** BSS sections **/
@@ -179,7 +190,14 @@
       case LDFileFormat::Null:
       case LDFileFormat::NamePool:
         continue;
-
+      // warning
+      case LDFileFormat::EhFrameHdr:
+      default: {
+        warning(diag::warn_illegal_input_section) << (*section)->name()
+                                                  << pInput.name()
+                                                  << pInput.path();
+        break;
+      }
     }
   } // end of for all sections
 
@@ -192,9 +210,20 @@
   assert(pInput.hasMemArea());
 
   LDSection* symtab_shdr = pInput.context()->getSection(".symtab");
+  if (NULL == symtab_shdr) {
+    note(diag::note_has_no_symtab) << pInput.name()
+                                   << pInput.path()
+                                   << ".symtab";
+    return true;
+  }
+
   LDSection* strtab_shdr = symtab_shdr->getLink();
-  if (NULL == symtab_shdr || NULL == strtab_shdr)
+  if (NULL == strtab_shdr) {
+    fatal(diag::fatal_cannot_read_strtab) << pInput.name()
+                                          << pInput.path()
+                                          << ".symtab";
     return false;
+  }
 
   MemoryRegion* symtab_region = pInput.memArea()->request(symtab_shdr->offset(),
                                                           symtab_shdr->size());
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index 1fd2a13..6aacc08 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -7,15 +7,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <llvm/Support/ELF.h>
 #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/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.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;
@@ -28,16 +29,22 @@
 {
   // name rules
   llvm::StringRef name(pName);
-  if (llvm::StringRef::npos != name.find(".debug"))
+  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") ||
-      name.startswith(".eh_frame_hdr") ||
-      name.startswith(".gcc_except_table"))
-    return LDFileFormat::Exception;
+  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) {
@@ -74,8 +81,7 @@
         (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) ||
         (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER))
       return LDFileFormat::Target;
-    llvm::report_fatal_error(llvm::Twine("unsupported ELF section type: ") +
-                             llvm::Twine(pType) + llvm::Twine(".\n"));
+    fatal(diag::err_unsupported_section) << pName << pType;
   }
   return LDFileFormat::MetaData;
 }
@@ -141,13 +147,9 @@
 
   LDSection* sect_hdr = pInput.context()->getSection(pShndx);
 
-  if (NULL == sect_hdr) {
-    llvm::report_fatal_error(llvm::Twine("section[") +
-                             llvm::Twine(pShndx) +
-                             llvm::Twine("] is invalid in file `") +
-                             pInput.path().native() +
-                             llvm::Twine("'.\n"));
-  }
+  if (NULL == sect_hdr)
+    unreachable(diag::unreachable_invalid_section_idx) << pShndx
+                                                       << pInput.path().native();
   
   MCFragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset);
   return result;
@@ -186,3 +188,17 @@
   return 0x0;
 }
 
+bool ELFReaderIF::readEhFrame(Input& pInput,
+                              MCLinker& pLinker,
+                              LDSection& pInputSectHdr) const
+{
+  LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
+                                                         pInputSectHdr.kind(),
+                                                         pInputSectHdr.type(),
+                                                         pInputSectHdr.flag());
+
+  size_t size = pLinker.addEhFrame(pInputSectHdr, *pInput.memArea());
+
+  out_sect.setSize(out_sect.size() + size);
+  return true;
+}
diff --git a/lib/LD/ELFSegment.cpp b/lib/LD/ELFSegment.cpp
index a08641b..dbefbc5 100644
--- a/lib/LD/ELFSegment.cpp
+++ b/lib/LD/ELFSegment.cpp
@@ -19,7 +19,8 @@
                        uint64_t pPaddr,
                        uint64_t pFilesz,
                        uint64_t pMemsz,
-                       uint64_t pAlign)
+                       uint64_t pAlign,
+                       uint64_t pMaxSectAlign)
   : m_Type(pType),
     m_Flag(pFlag),
     m_Offset(pOffset),
@@ -27,7 +28,8 @@
     m_Paddr(pPaddr),
     m_Filesz(pFilesz),
     m_Memsz(pMemsz),
-    m_Align(pAlign) {
+    m_Align(pAlign),
+    m_MaxSectionAlign(pMaxSectAlign) {
 }
 
 ELFSegment::~ELFSegment()
diff --git a/lib/LD/ELFSegmentFactory.cpp b/lib/LD/ELFSegmentFactory.cpp
index d8ad3cc..af0f588 100644
--- a/lib/LD/ELFSegmentFactory.cpp
+++ b/lib/LD/ELFSegmentFactory.cpp
@@ -25,16 +25,40 @@
 /// produce - produce an empty ELF segment information.
 /// this function will create an ELF segment
 /// @param pType - p_type in ELF program header
-ELFSegment* ELFSegmentFactory::produce(uint32_t pType)
+ELFSegment* ELFSegmentFactory::produce(uint32_t pType, uint32_t pFlag)
 {
   ELFSegment* segment = allocate();
-  new (segment) ELFSegment(pType);
+  new (segment) ELFSegment(pType, pFlag);
   return segment;
 }
 
-/// destroy - destruct the ELF segment
-void ELFSegmentFactory::destroy(ELFSegment*& pSegment)
+ELFSegment*
+ELFSegmentFactory::find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear)
 {
-  deallocate(pSegment);
+  iterator segment, segEnd = end();
+  for (segment = begin(); segment != segEnd; ++segment) {
+    if ((*segment).type() == pType &&
+        ((*segment).flag() & pFlagSet) == pFlagSet &&
+        ((*segment).flag() & pFlagClear) == 0x0) {
+      return &(*segment);
+    }
+  }
+  return NULL;
+}
+
+const ELFSegment*
+ELFSegmentFactory::find(uint32_t pType,
+                        uint32_t pFlagSet,
+                        uint32_t pFlagClear) const
+{
+  const_iterator segment, segEnd = end();
+  for (segment = begin(); segment != segEnd; ++segment) {
+    if ((*segment).type() == pType &&
+        ((*segment).flag() & pFlagSet) == pFlagSet &&
+        ((*segment).flag() & pFlagClear) == 0x0) {
+      return &(*segment);
+    }
+  }
+  return NULL;
 }
 
diff --git a/lib/LD/ELFWriter.cpp b/lib/LD/ELFWriter.cpp
index a94fd5c..2f2d898 100644
--- a/lib/LD/ELFWriter.cpp
+++ b/lib/LD/ELFWriter.cpp
@@ -18,6 +18,8 @@
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/Layout.h>
+#include <mcld/LD/ELFSegment.h>
+#include <mcld/LD/ELFSegmentFactory.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <cstdlib>
 #include <cstring>
@@ -146,7 +148,7 @@
                        && (pOutput.type() != Output::Object)
                        && (pOutput.type() != Output::DynObj));
 
-  const LDSymbol* entry_symbol = pLDInfo.getStrSymPool().findSymbol(entry_name);
+  const LDSymbol* entry_symbol = pLDInfo.getNamePool().findSymbol(entry_name);
 
   // found the symbol
   if (NULL != entry_symbol) {
@@ -244,6 +246,70 @@
   }
 }
 
+
+/// emitELF32ProgramHeader - emit Elf32_Phdr
+void ELFWriter::emitELF32ProgramHeader(Output& pOutput,
+                                       const GNULDBackend& pBackend) 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);
+
+  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();
+  for (; seg != segEnd; ++seg, ++index) {
+    phdr[index].p_type   = (*seg).type();
+    phdr[index].p_flags  = (*seg).flag();
+    phdr[index].p_offset = (*seg).offset();
+    phdr[index].p_vaddr  = (*seg).vaddr();
+    phdr[index].p_paddr  = (*seg).paddr();
+    phdr[index].p_filesz = (*seg).filesz();
+    phdr[index].p_memsz  = (*seg).memsz();
+    phdr[index].p_align  = (*seg).align();
+  }
+}
+
+/// emitELF64ProgramHeader - emit ElfR64Phdr
+void ELFWriter::emitELF64ProgramHeader(Output& pOutput,
+                                       const GNULDBackend& pBackend) 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);
+  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();
+  for (; seg != segEnd; ++seg, ++index) {
+    phdr[index].p_type   = (*seg).type();
+    phdr[index].p_flags  = (*seg).flag();
+    phdr[index].p_offset = (*seg).offset();
+    phdr[index].p_vaddr  = (*seg).vaddr();
+    phdr[index].p_paddr  = (*seg).paddr();
+    phdr[index].p_filesz = (*seg).filesz();
+    phdr[index].p_memsz  = (*seg).memsz();
+    phdr[index].p_align  = (*seg).align();
+  }
+}
+
 /// emitELF32ShStrTab - emit section string table
 void ELFWriter::emitELF32ShStrTab(Output& pOutput, MCLinker& pLinker) const
 {
diff --git a/lib/LD/EhFrame.cpp b/lib/LD/EhFrame.cpp
new file mode 100644
index 0000000..76af403
--- /dev/null
+++ b/lib/LD/EhFrame.cpp
@@ -0,0 +1,373 @@
+//===- EhFrame.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrame.h>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <llvm/Support/Dwarf.h>
+#include <llvm/Support/Host.h>
+
+using namespace mcld;
+
+//==========================
+// EhFrame
+EhFrame::EhFrame()
+ : m_fCanRecognizeAll(true) {
+}
+
+EhFrame::~EhFrame()
+{
+}
+
+uint64_t EhFrame::readEhFrame(Layout& pLayout,
+                              const TargetLDBackend& pBackend,
+                              llvm::MCSectionData& pSD,
+                              LDSection& pSection,
+                              MemoryArea& pArea)
+{
+  MemoryRegion* region = pArea.request(pSection.offset(),
+                                       pSection.size());
+  // an empty .eh_frame
+  if (NULL == region) {
+    note(diag::note_ehframe) << "an empty eh_frame";
+    return 0;
+  }
+
+  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) {
+    note(diag::note_ehframe) << "a terminator";
+    pArea.release(region);
+    return 0;
+  }
+
+  if (0xffffffff == len) {
+    debug(diag::debug_eh_unsupport) << "64-bit eh_frame";
+    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) << "CIE or FDE size smaller than 4";
+      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) << "Non-end entry with zero length";
+        m_fCanRecognizeAll = false;
+      }
+      break;
+    }
+    if (0xffffffff == len) {
+      debug(diag::debug_eh_unsupport) << "64-bit eh_frame";
+      m_fCanRecognizeAll = false;
+      break;
+    }
+
+    if (eh_end - p < 4) {
+      debug(diag::debug_eh_unsupport) <<
+        "CIE:ID field / FDE: CIE Pointer field";
+      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(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) {
+    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;
+}
+
+bool EhFrame::addCIE(MemoryRegion& pRegion,
+                     const TargetLDBackend& pBackend,
+                     FragListType& pFragList)
+{
+  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) {
+    debug(diag::debug_eh_unsupport) << "CIE version";
+    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)) {
+    debug(diag::debug_eh_unsupport) << "unrecognized Code Alignment Factor";
+    return false;
+  }
+  // skip the Data Alignment Factor
+  if (!skipLEB128(&p, cie_end)) {
+    debug(diag::debug_eh_unsupport) << "unrecognized Data Alignment Factor";
+    return false;
+  }
+  // skip the Return Address Register
+  if (cie_end - p < 1) {
+    debug(diag::debug_eh_unsupport) << "unrecognized Return Address Register";
+    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') {
+    debug(diag::debug_eh_unsupport) << "augmentation string `eh`";
+    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)) {
+      debug(diag::debug_eh_unsupport) <<
+        "unrecognized Augmentation Data Length";
+      return false;
+    }
+
+    while (aug_str != aug_str_end) {
+      switch (*aug_str) {
+        default:
+          debug(diag::debug_eh_unsupport) << "augmentation string";
+          return false;
+
+        // LDSA encoding (1 byte)
+        case 'L':
+          if (cie_end - p < 1) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `L`";
+            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) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+            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)) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+            return false;
+          }
+          switch (per_encode & 7) {
+            default:
+              debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+              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) {
+              debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+              return false;
+            }
+            p += per_align;
+          }
+          // skip the second argument
+          if (static_cast<uint32_t>(cie_end - p) < per_length) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+            return false;
+          }
+          p += per_length;
+        }
+        break;
+
+        // FDE encoding (1 byte)
+        case 'R':
+          if (cie_end - p < 1) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `R`";
+            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:
+              debug(diag::debug_eh_unsupport) << "FDE encoding";
+              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<llvm::MCFragment*>(entry));
+  return true;
+}
+
+bool EhFrame::addFDE(MemoryRegion& pRegion,
+                     const TargetLDBackend& pBackend,
+                     FragListType& pFragList)
+{
+  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) {
+    debug(diag::debug_eh_unsupport) << "FDE PC Begin";
+    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<llvm::MCFragment*>(entry));
+  return true;
+}
+
+uint32_t EhFrame::readVal(ConstAddress pAddr, bool pIsTargetLittleEndian)
+{
+  const uint32_t* p = reinterpret_cast<const uint32_t*>(pAddr);
+  uint32_t val = *p;
+
+  // byte swapping if the host and target have different endian
+  if (llvm::sys::isLittleEndianHost() != pIsTargetLittleEndian)
+    val = bswap32(val);
+  return val;
+}
+
+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;
+}
+
+void EhFrame::deleteFragments(FragListType& pList, MemoryArea& pArea)
+{
+  MCRegionFragment* frag = NULL;
+  for (FragListType::iterator it = pList.begin(); it != pList.end(); ++it) {
+    frag = static_cast<MCRegionFragment*>(*it);
+    pArea.release(&(frag->getRegion()));
+    delete *it;
+  }
+  pList.clear();
+}
+
diff --git a/lib/LD/EhFrameHdr.cpp b/lib/LD/EhFrameHdr.cpp
new file mode 100644
index 0000000..8806af4
--- /dev/null
+++ b/lib/LD/EhFrameHdr.cpp
@@ -0,0 +1,49 @@
+//===- EhFrameHdr.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrameHdr.h>
+
+using namespace mcld;
+
+//==========================
+// EhFrameHdr
+EhFrameHdr::EhFrameHdr(const EhFrame& pEhFrameData,
+                       const LDSection& pEhFrameSect,
+                       LDSection& pEhFrameHdrSect)
+  : m_EhFrameData(pEhFrameData),
+    m_EhFrameSect(pEhFrameSect),
+    m_EhFrameHdrSect(pEhFrameHdrSect)
+{
+}
+
+EhFrameHdr::~EhFrameHdr()
+{
+}
+
+/// @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
+
+/// 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);
+}
+
diff --git a/lib/LD/ExecWriter.cpp b/lib/LD/ExecWriter.cpp
new file mode 100644
index 0000000..d66cd17
--- /dev/null
+++ b/lib/LD/ExecWriter.cpp
@@ -0,0 +1,16 @@
+//===- ExecWriter.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "mcld/LD/ExecWriter.h"
+#include "mcld/Target/TargetLDBackend.h"
+#include "mcld/MC/MCLDInput.h"
+
+using namespace mcld;
+
+//==========================
+// ExecWriter
diff --git a/lib/LD/FDE.cpp b/lib/LD/FDE.cpp
new file mode 100644
index 0000000..b70f7e1
--- /dev/null
+++ b/lib/LD/FDE.cpp
@@ -0,0 +1,24 @@
+//===- 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/EhFrame.h>
+#include <mcld/LD/FDE.h>
+
+using namespace mcld;
+
+//==========================
+// FDE
+
+FDE::FDE(MemoryRegion& pRegion, const CIE& pCIE, Offset pPCBeginOffset)
+  : MCRegionFragment(pRegion), m_CIE(pCIE), m_PCBeginOffset(pPCBeginOffset) {
+}
+
+FDE::~FDE()
+{
+}
+
diff --git a/lib/LD/GNUArchiveReader.cpp b/lib/LD/GNUArchiveReader.cpp
index 3fa00b8..0a64752 100644
--- a/lib/LD/GNUArchiveReader.cpp
+++ b/lib/LD/GNUArchiveReader.cpp
@@ -6,42 +6,35 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInfo.h"
-#include "mcld/MC/MCLDInput.h"
-#include "mcld/MC/MCLDInputTree.h"
-#include "mcld/LD/GNUArchiveReader.h"
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/InputTree.h>
+#include <mcld/LD/GNUArchiveReader.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/ADT/SizeTraits.h>
 
-#include <llvm/Support/MemoryBuffer.h>
 #include <llvm/Support/system_error.h>
+#include <llvm/Support/Host.h>
 
 #include <sstream>
 #include <string>
 #include <vector>
 #include <cstdlib>
 
-using namespace std;
 using namespace mcld;
 
-typedef size_t sectionSizeTy;
 typedef uint32_t elfWord;
 
-/// Archive Header, Magic number, etc..
 
-const unsigned archiveMagicSize = 8;
-const char archiveMagic[archiveMagicSize] = { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' };
-const char thinArchiveMagic[archiveMagicSize] = { '!', '<', 't', 'h', 'i', 'n', '>', '\n' };
-const char archiveFinalMagic[2] = { '`', '\n' };
+/// Archive Header, Magic number
+const char GNUArchiveReader::ArchiveMagic[ArchiveMagicSize] = { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' };
+const char GNUArchiveReader::ThinArchiveMagic[ArchiveMagicSize] = { '!', '<', 't', 'h', 'i', 'n', '>', '\n' };
+const char GNUArchiveReader::HeaderFinalMagic[HeaderFinalMagicSize] = { '`', '\n' };
 
-struct GNUArchiveReader::ArchiveMemberHeader
-{
-  char name[16];
-  char date[12];
-  char uid[6];
-  char gid[6];
-  char mode[8];
-  char size[10];
-  char finalMagic[2];
-};
 
 struct GNUArchiveReader::SymbolTableEntry
 {
@@ -49,13 +42,6 @@
   std::string name;
 };
 
-inline void endian_swap(unsigned int& x)
-{
-  x = (x>>24) |
-      ((x<<8) & 0x00FF0000) |
-      ((x>>8) & 0x0000FF00) |
-      (x<<24);
-}
 
 
 /// convert string to size_t
@@ -73,22 +59,25 @@
 /// Public API
 bool GNUArchiveReader::isMyFormat(Input &pInput) const
 {
-  llvm::OwningPtr<llvm::MemoryBuffer> mapFile;
-  llvm::MemoryBuffer::getFile(pInput.path().c_str(), mapFile);
-  const char* pFile = mapFile->getBufferStart();
+  assert(pInput.hasMemArea());
+
+  MemoryRegion *region = pInput.memArea()->request(0, ArchiveMagicSize);
+  if (!region)
+    llvm::report_fatal_error("can't request MemoryRegion for archive magic");
+
+  const char *p_buffer = reinterpret_cast<char *> (region->getBuffer());
 
   /// check archive format.
-  if(mapFile->getBufferSize() <= archiveMagicSize)
+  if (memcmp(p_buffer, ArchiveMagic, ArchiveMagicSize) != 0
+      && memcmp(p_buffer, ThinArchiveMagic, ArchiveMagicSize) != 0) {
     return false;
-  bool isThinArchive = memcmp(pFile, thinArchiveMagic, archiveMagicSize) == 0;
-  if(!isThinArchive && memcmp(pFile, archiveMagic, archiveMagicSize) != 0)
-    return false;
+  }
   return true;
 }
 
 LDReader::Endian GNUArchiveReader::endian(Input& pFile) const
 {
-  return m_endian;
+  return LDReader::BigEndian;
 }
 
 InputTree *GNUArchiveReader::readArchive(Input &pInput)
@@ -103,62 +92,59 @@
 InputTree *GNUArchiveReader::setupNewArchive(Input &pInput,
                                             size_t off)
 {
-  llvm::OwningPtr<llvm::MemoryBuffer> mapFile;
-  if(llvm::MemoryBuffer::getFile(pInput.path().c_str(), mapFile))
-  {
-    assert(0 && "GNUArchiveReader:can't map a file to MemoryBuffer\n");
-    return NULL;
-  }
+  assert(pInput.hasMemArea());
+  MemoryRegion *region = pInput.memArea()->request(off, ArchiveMagicSize);
+
+  if (!region)
+    llvm::report_fatal_error("can't request MemoryRegion for archive magic");
+
+  const char *pFile = reinterpret_cast<char *> (region->getBuffer());
+
+  /// check archive format.
+  bool isThinArchive;
+  isThinArchive = memcmp(pFile, ThinArchiveMagic, ArchiveMagicSize) == 0;
+  if(!isThinArchive && memcmp(pFile, ArchiveMagic, ArchiveMagicSize) != 0)
+    llvm::report_fatal_error("Fail : archive magic number is not matched");
 
   InputTree *resultTree = new InputTree(m_pLDInfo.inputFactory());
   std::vector<SymbolTableEntry> symbolTable;
   std::string archiveMemberName;
   std::string extendedName;
-  bool isThinArchive;
-  const char *pFile = mapFile->getBufferStart();
 
-  /// check archive format.
-  if(mapFile->getBufferSize() <= archiveMagicSize)
-    return NULL;
-  else
-  {
-    isThinArchive = memcmp(pFile, thinArchiveMagic, archiveMagicSize) == 0;
-    if(!isThinArchive && memcmp(pFile, archiveMagic, archiveMagicSize) != 0)
-      return NULL;
-  }
-
-  off += archiveMagicSize ;
-  size_t symbolTableSize = parseMemberHeader(mapFile, off, &archiveMemberName,
+  off += ArchiveMagicSize ;
+  size_t symbolTableSize = readMemberHeader(*pInput.memArea(), off, &archiveMemberName,
                                             NULL, extendedName);
   /// read archive symbol table
   if(archiveMemberName.empty())
   {
-    readSymbolTable(mapFile, symbolTable,
-                    off+sizeof(GNUArchiveReader::ArchiveMemberHeader), symbolTableSize);
-    off = off + sizeof(GNUArchiveReader::ArchiveMemberHeader) + symbolTableSize;
+    readSymbolTable(*pInput.memArea(), symbolTable,
+                    off+sizeof(ArchiveMemberHeader), symbolTableSize);
+    off = off + sizeof(ArchiveMemberHeader) + symbolTableSize;
   }
   else
   {
-    assert(0 && "fatal error : need symbol table\n");
+    llvm::report_fatal_error("fatal error : need symbol table\n");
     return NULL;
   }
 
   if((off&1) != 0)
     ++off;
 
-  size_t extendedSize = parseMemberHeader(mapFile, off, &archiveMemberName,
+  size_t extendedSize = readMemberHeader(*pInput.memArea(), off, &archiveMemberName,
                                           NULL, extendedName);
   /// read long Name table if exist
   if(archiveMemberName == "/")
   {
-    off += sizeof(GNUArchiveReader::ArchiveMemberHeader);
-    pFile += off;
-    extendedName.assign(pFile,extendedSize);
+    off += sizeof(ArchiveMemberHeader);
+    MemoryRegion *extended_name_region = pInput.memArea()->request(off, extendedSize);
+    pFile = reinterpret_cast<char *>(extended_name_region->getBuffer());
+    extendedName.assign(pFile, extendedSize);
+
   }
 
   /// traverse all the archive members
   InputTree::iterator node = resultTree->root();
-  set<string> haveSeen;
+  std::set<std::string> haveSeen;
   for(unsigned i=0 ; i<symbolTable.size() ; ++i)
   {
     /// We shall get each member at this archive.
@@ -166,7 +152,7 @@
     /// the original InputTree, resultTree.
     off_t nestedOff = 0;
 
-    parseMemberHeader(mapFile, symbolTable[i].fileOffset, &archiveMemberName,
+    readMemberHeader(*pInput.memArea(), symbolTable[i].fileOffset, &archiveMemberName,
                       &nestedOff, extendedName);
 
     if(haveSeen.find(archiveMemberName)==haveSeen.end())
@@ -191,8 +177,13 @@
 
       continue;
     }
-
-    /// create the real path
+    
+    /// TODO:(Duo)
+    /// adjust the relative pathname
+    /// For example
+    /// thin archive pathname : "/usr/lib/thin.a"
+    ///           Member name : "member.a"
+    /// pathname after adjust : "/usr/lib/member.a"
     sys::fs::RealPath realPath(archiveMemberName);
     if(nestedOff > 0)
     {
@@ -237,20 +228,20 @@
 /// "filename.o/        " - regular file with short name
 /// "/5566              " - name at offset 5566 at long name table
 
-size_t GNUArchiveReader::parseMemberHeader(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile,
+size_t GNUArchiveReader::readMemberHeader(MemoryArea &pArea,
                                            off_t off,
                                            std::string *p_Name,
                                            off_t *p_NestedOff,
                                            std::string &p_ExtendedName)
 {
-  const char *pFile = mapFile->getBufferStart();
-  pFile += off;
+  MemoryRegion *region = pArea.request(off, sizeof(ArchiveMemberHeader));
+  const char *pFile = reinterpret_cast<char *>(region->getBuffer());
   const ArchiveMemberHeader *header = reinterpret_cast<const ArchiveMemberHeader *>(pFile);
 
   /// check magic number of member header
-  if(memcmp(header->finalMagic, archiveFinalMagic, sizeof archiveFinalMagic))
+  if(memcmp(header->finalMagic, HeaderFinalMagic, sizeof HeaderFinalMagic))
   {
-    assert(0 && "archive member header magic number false");
+    llvm::report_fatal_error("archive member header magic number false");
     return 0;
   }
 
@@ -259,7 +250,7 @@
   size_t memberSize = stringToType<size_t>(sizeString);
   if(memberSize == 0)
   {
-    assert(0 && "member Size Error");
+    llvm::report_fatal_error("member Size Error");
     return 0;
   }
 
@@ -270,7 +261,7 @@
     size_t nameLen = ((nameEnd == NULL) ? 0 : (nameEnd - header->name));
     if((nameLen <= 0) || (nameLen >= sizeof(header->name)))
     {
-      assert(0 && "header name format error\n");
+      llvm::report_fatal_error("header name format error\n");
       return 0;
     }
     p_Name->assign(header->name, nameLen);
@@ -302,7 +293,7 @@
        || extendedNameOff < 0
        || static_cast<size_t>(extendedNameOff) >= p_ExtendedName.size())
     {
-      assert(0 && "extended name");
+      llvm::report_fatal_error("extended name");
       return 0;
     }
 
@@ -311,7 +302,7 @@
     if(nameEnd[-1] != '/'
        || static_cast<size_t>(nameEnd-name) > p_ExtendedName.size())
     {
-      assert(0 && "p_ExtendedName substring is not end with / \n");
+      llvm::report_fatal_error("p_ExtendedName substring is not end with / \n");
       return 0;
     }
     p_Name->assign(name, nameEnd-name-1);
@@ -322,35 +313,40 @@
   return memberSize;
 }
 
-void GNUArchiveReader::readSymbolTable(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile,
+void GNUArchiveReader::readSymbolTable(MemoryArea &pArea,
                                        std::vector<SymbolTableEntry> &pSymbolTable,
                                        off_t start,
                                        size_t size)
 {
-  const char *startPtr = mapFile->getBufferStart() + start;
-  const elfWord *p_Word = reinterpret_cast<const elfWord *>(startPtr);
+  MemoryRegion *region = pArea.request(start, size);
+  const char *pFile = reinterpret_cast<char *>(region->getBuffer());
+  const elfWord *p_Word = reinterpret_cast<const elfWord *>(pFile);
   unsigned int symbolNum = *p_Word;
 
   /// Portable Issue on Sparc platform
   /// Intel, ARM and Mips are littel-endian , Sparc is little-endian after verion 9
   /// symbolNum in symbol table is always big-endian
-  if(m_endian == LDReader::LittleEndian)
-    endian_swap(symbolNum);
+  if(llvm::sys::isLittleEndianHost())
+    symbolNum = bswap32(symbolNum);
   ++p_Word;
 
   const char *p_Name = reinterpret_cast<const char *>(p_Word + symbolNum);
 
-  pSymbolTable.resize(symbolNum);
   for(unsigned int i=0 ; i<symbolNum ; ++i)
   {
-    /// assign member offset
+    SymbolTableEntry entry;
+    /// member offset
     unsigned int memberOffset = *p_Word;
-    endian_swap(memberOffset);
-    pSymbolTable[i].fileOffset = static_cast<off_t>(memberOffset);
+    if(llvm::sys::isLittleEndianHost())
+      memberOffset = bswap32(memberOffset);
+    entry.fileOffset = static_cast<off_t>(memberOffset);
     ++p_Word;
-    /// assign member name
+    /// member name
     off_t nameEnd = strlen(p_Name) + 1;
-    pSymbolTable[i].name.assign(p_Name, nameEnd);
+    entry.name.assign(p_Name, nameEnd);
     p_Name += nameEnd;
+    /// the symbol is found in symbol pool
+    if (m_pLDInfo.getNamePool().findSymbol(entry.name))
+      pSymbolTable.push_back(entry);
   }
 }
diff --git a/lib/LD/InputSymbolTable.cpp b/lib/LD/InputSymbolTable.cpp
deleted file mode 100644
index e34679c..0000000
--- a/lib/LD/InputSymbolTable.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- InputSymbolTable.cpp -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/InputSymbolTable.h"
-#include <vector>
-
-using namespace mcld;
-
-//==========================
-// InputSymbolTable
-
-InputSymbolTable::InputSymbolTable(StrSymPool &pStrSymPool,
-                                   size_t pNumOfSymbols,
-                                   StringTable &pEntireStringTable,
-                                   StringTable &pDynamicStringTable)
-  : SymbolTableIF(pStrSymPool)
-{
-  f_StrSymPool.addIndirectClient(*this);
-
-  f_pCategorySet->at(CategorySet::Entire).reserve(pNumOfSymbols);
-
-  f_pCategorySet->at(CategorySet::Entire).interpose(&pEntireStringTable);
-  f_pCategorySet->at(CategorySet::Dynamic).interpose(&pDynamicStringTable);
-}
-
-void InputSymbolTable::doInsertSymbol(LDSymbol *pSym)
-{
-  f_pCategorySet->insertSymbolPointer(pSym);
-}
-
-void InputSymbolTable::doMerge(const SymbolTableIF &pSymTab)
-{
-  if (this == &pSymTab)
-     return;
-  for (size_t i = 0; i < CategorySet::NumOfCategories; ++i)
-    f_pCategorySet->at(i).insert(f_pCategorySet->at(i).end(),
-                                 pSymTab.begin(i),
-                                 pSymTab.end(i));
-}
-
-InputSymbolTable::~InputSymbolTable()
-{
-}
diff --git a/lib/LD/Layout.cpp b/lib/LD/Layout.cpp
index 9328d74..bc91cee 100644
--- a/lib/LD/Layout.cpp
+++ b/lib/LD/Layout.cpp
@@ -8,14 +8,14 @@
 //===----------------------------------------------------------------------===//
 
 #include <llvm/ADT/Twine.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/ADT/SizeTraits.h>
 #include <mcld/LD/Layout.h>
+#include <mcld/LD/LDContext.h>
 #include <mcld/LD/LDFileFormat.h>
+#include <mcld/LD/LDSection.h>
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/LDContext.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Target/TargetLDBackend.h>
 #include <cassert>
 
@@ -132,16 +132,6 @@
   }
   else {
     range_list = m_SDRangeMap[&pSD];
-#ifdef MCLD_DEBUG
-    RangeList::iterator rangeIter, rangeEnd = range_list->end();
-    for (rangeIter = range_list->begin(); rangeIter != rangeEnd; ++rangeIter) {
-      if (&pInputHdr == rangeIter->header) {
-        llvm::report_fatal_error(llvm::Twine("Trying to map the same LDSection: ") +
-                                 pInputHdr.name() +
-                                 llvm::Twine(" into the different ranges.\n"));
-      }
-    }
-#endif
   }
 
   // make a range and push it into the range list
@@ -425,9 +415,7 @@
 
   // range not found
   if (range == rangeEnd) {
-    llvm::report_fatal_error(llvm::Twine("section ") +
-                             pInputSection.name() +
-                             llvm::Twine(" never be in the range list.\n"));
+    fatal(diag::err_section_not_laid_out) << pInputSection.name();
   }
 
   return getFragmentRef(*range, pOffset);
@@ -481,7 +469,7 @@
                              llvm::Twine(" never be in the range list.\n"));
   }
 
-  return getFragmentRef(*range, target_offset);
+  return getFragmentRef(*range, pBigOffset);
 }
 
 uint64_t Layout::getOutputOffset(const llvm::MCFragment& pFrag)
@@ -516,7 +504,8 @@
 }
 
 void Layout::sortSectionOrder(const Output& pOutput,
-                              const TargetLDBackend& pBackend)
+                              const TargetLDBackend& pBackend,
+                              const MCLDInfo& pInfo)
 {
   typedef std::pair<LDSection*, unsigned int> SectOrder;
   typedef std::vector<SectOrder > SectListTy;
@@ -525,7 +514,7 @@
   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])));
+                    pBackend.getSectionOrder(pOutput, *m_SectionOrder[index], pInfo)));
 
   // simple insertion sort should be fine for general cases such as so and exec
   for (unsigned int i = 1; i < sect_list.size(); ++i) {
@@ -545,7 +534,9 @@
   }
 }
 
-bool Layout::layout(Output& pOutput, const TargetLDBackend& pBackend)
+bool Layout::layout(Output& pOutput,
+                    const TargetLDBackend& pBackend,
+                    const MCLDInfo& pInfo)
 {
   // determine what sections in output context will go into final output, and
   // push the needed sections into m_SectionOrder for later processing
@@ -558,10 +549,12 @@
     switch (sect->kind()) {
       // ignore if there is no SectionData for certain section kinds
       case LDFileFormat::Regular:
-      case LDFileFormat::Note:
       case LDFileFormat::Target:
       case LDFileFormat::MetaData:
       case LDFileFormat::BSS:
+      case LDFileFormat::Debug:
+      case LDFileFormat::EhFrame:
+      case LDFileFormat::GCCExceptTable:
         if (0 != sect->size()) {
           if (NULL != sect->getSectionData() &&
               !sect->getSectionData()->getFragmentList().empty()) {
@@ -581,6 +574,8 @@
       // ignore if section size is 0
       case LDFileFormat::NamePool:
       case LDFileFormat::Relocation:
+      case LDFileFormat::Note:
+      case LDFileFormat::EhFrameHdr:
         if (0 != sect->size())
           m_SectionOrder.push_back(sect);
         break;
@@ -590,47 +585,22 @@
           ;
         }
         break;
-      case LDFileFormat::Debug:
-        if (0 != sect->size()) {
-          m_SectionOrder.push_back(sect);
-          llvm::errs() << "WARNING: DWRAF debugging has not been fully supported yet.\n"
-                       << "section `" << sect->name() << "'.\n";
-        }
-        break;
-      case LDFileFormat::Exception:
-        if (0 != sect->size()) {
-          llvm::errs() << "WARNING: Exception handling has not been fully supported yet.\n"
-                       << "section `" << sect->name() << "'.\n";
-          if (NULL != sect->getSectionData() &&
-              !sect->getSectionData()->getFragmentList().empty()) {
-            // make sure that all fragments are valid
-            llvm::MCFragment& frag =
-              sect->getSectionData()->getFragmentList().back();
-            setFragmentLayoutOrder(&frag);
-            setFragmentLayoutOffset(&frag);
-          }
-          m_SectionOrder.push_back(sect);
-        }
-        break;
       case LDFileFormat::Version:
         if (0 != sect->size()) {
           m_SectionOrder.push_back(sect);
-          llvm::errs() << "WARNING: Symbolic versioning has not been fully supported yet.\n"
-                       << "section `" << sect->name() << "'.\n";
+          warning(diag::warn_unsupported_symbolic_versioning) << sect->name();
         }
         break;
       default:
-        llvm::report_fatal_error(llvm::Twine("Unsupported section kind of `") +
-                                 sect->name() +
-                                 llvm::Twine("': ") +
-                                 llvm::Twine(sect->kind()) +
-                                 llvm::Twine(".\n"));
+        if (0 != sect->size()) {
+          error(diag::err_unsupported_section) << sect->name() << sect->kind();
+        }
         break;
     }
   }
 
   // perform sorting on m_SectionOrder to get a ordering for final layout
-  sortSectionOrder(pOutput, pBackend);
+  sortSectionOrder(pOutput, pBackend, pInfo);
 
   // Backend defines the section start offset for section 1.
   uint64_t offset = pBackend.sectionStartOffset();
diff --git a/lib/LD/MsgHandler.cpp b/lib/LD/MsgHandler.cpp
new file mode 100644
index 0000000..96310a2
--- /dev/null
+++ b/lib/LD/MsgHandler.cpp
@@ -0,0 +1,52 @@
+//===- MsgHandler.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/MsgHandler.h>
+#include <mcld/LD/DiagnosticEngine.h>
+
+using namespace mcld;
+
+MsgHandler::MsgHandler(DiagnosticEngine& pEngine)
+ : m_Engine(pEngine), m_NumArgs(0) {
+}
+
+MsgHandler::~MsgHandler()
+{
+  emit();
+}
+
+bool MsgHandler::emit()
+{
+  flushCounts();
+  return m_Engine.emit();
+}
+
+void MsgHandler::addString(llvm::StringRef pStr) const
+{
+  assert(m_NumArgs < DiagnosticEngine::MaxArguments &&
+         "Too many arguments to diagnostic!");
+  m_Engine.state().ArgumentKinds[m_NumArgs] = DiagnosticEngine::ak_std_string;
+  m_Engine.state().ArgumentStrs[m_NumArgs++] = pStr.data();
+}
+
+void MsgHandler::addString(const std::string& pStr) const
+{
+  assert(m_NumArgs < DiagnosticEngine::MaxArguments &&
+         "Too many arguments to diagnostic!");
+  m_Engine.state().ArgumentKinds[m_NumArgs] = DiagnosticEngine::ak_std_string;
+  m_Engine.state().ArgumentStrs[m_NumArgs++] = pStr;
+}
+
+void MsgHandler::addTaggedVal(intptr_t pValue, DiagnosticEngine::ArgumentKind pKind) const
+{
+  assert(m_NumArgs < DiagnosticEngine::MaxArguments &&
+         "Too many arguments to diagnostic!");
+  m_Engine.state().ArgumentKinds[m_NumArgs] = pKind;
+  m_Engine.state().ArgumentVals[m_NumArgs++] = pValue;
+}
+
diff --git a/lib/LD/StrSymPool.cpp b/lib/LD/NamePool.cpp
similarity index 69%
rename from lib/LD/StrSymPool.cpp
rename to lib/LD/NamePool.cpp
index abe3fb7..1247057 100644
--- a/lib/LD/StrSymPool.cpp
+++ b/lib/LD/NamePool.cpp
@@ -1,4 +1,4 @@
-//===- StrSymPool.cpp -----------------------------------------------------===//
+//===- NamePool.cpp -------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,27 +6,24 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#include "mcld/LD/StrSymPool.h"
-#include "mcld/LD/Resolver.h"
 #include <llvm/Support/raw_ostream.h>
+#include <mcld/LD/NamePool.h>
+#include <mcld/LD/Resolver.h>
 
 using namespace mcld;
 
 //==========================
-// StrSymPool
-StrSymPool::StrSymPool(const Resolver& pResolver, StrSymPool::size_type pSize)
-  : m_pResolver(pResolver.clone()), m_Table(pSize) {
+// NamePool
+NamePool::NamePool(const Resolver& pResolver, NamePool::size_type pSize)
+  : m_pResolver(&pResolver), m_Table(pSize) {
 }
 
-StrSymPool::~StrSymPool()
+NamePool::~NamePool()
 {
-  if (0 != m_pResolver)
-    delete m_pResolver;
 }
 
 /// createSymbol - create a symbol
-ResolveInfo* StrSymPool::createSymbol(const llvm::StringRef& pName,
+ResolveInfo* NamePool::createSymbol(const llvm::StringRef& pName,
                                       bool pIsDyn,
                                       ResolveInfo::Type pType,
                                       ResolveInfo::Desc pDesc,
@@ -48,7 +45,7 @@
 /// insertSymbol - insert a symbol and resolve it immediately
 /// @return the pointer of resolved ResolveInfo
 /// @return is the symbol existent?
-void StrSymPool::insertSymbol(const llvm::StringRef& pName,
+void NamePool::insertSymbol(const llvm::StringRef& pName,
                               bool pIsDyn,
                               ResolveInfo::Type pType,
                               ResolveInfo::Desc pDesc,
@@ -98,69 +95,49 @@
   // symbol resolution
   bool override = false;
   unsigned int action = Resolver::LastAction;
-  switch(m_pResolver->resolve(*old_symbol, *new_symbol, override)) {
-    case Resolver::Success: {
-      pResult.info      = old_symbol;
-      pResult.existent  = true;
-      pResult.overriden = override;
-      break;
-    }
-    case Resolver::Warning: {
-      llvm::errs() << "WARNING: " << m_pResolver->mesg() << "\n";
-      m_pResolver->clearMesg();
-      pResult.info      = old_symbol;
-      pResult.existent  = true;
-      pResult.overriden = override;
-      break;
-    }
-    case Resolver::Abort: {
-      llvm::report_fatal_error(m_pResolver->mesg());
-      pResult.info      = old_symbol;
-      pResult.existent  = true;
-      pResult.overriden = override;
-      break;
-    }
-    default: {
-      m_pResolver->resolveAgain(*this, action, *old_symbol, *new_symbol, pResult);
-      break;
-    }
+  if (m_pResolver->resolve(*old_symbol, *new_symbol, override)) {
+    pResult.info      = old_symbol;
+    pResult.existent  = true;
+    pResult.overriden = override;
   }
+  else
+      m_pResolver->resolveAgain(*this, action, *old_symbol, *new_symbol, pResult);
   return;
 }
 
-llvm::StringRef StrSymPool::insertString(const llvm::StringRef& pString)
+llvm::StringRef NamePool::insertString(const llvm::StringRef& pString)
 {
   bool exist = false;
   ResolveInfo* resolve_info = m_Table.insert(pString, exist);
   return llvm::StringRef(resolve_info->name(), resolve_info->nameSize());
 }
 
-void StrSymPool::reserve(StrSymPool::size_type pSize)
+void NamePool::reserve(NamePool::size_type pSize)
 {
   m_Table.rehash(pSize);
 }
 
-StrSymPool::size_type StrSymPool::capacity() const
+NamePool::size_type NamePool::capacity() const
 {
   return (m_Table.numOfBuckets() - m_Table.numOfEntries());
 }
 
 /// findInfo - find the resolved ResolveInfo
-ResolveInfo* StrSymPool::findInfo(const llvm::StringRef& pName)
+ResolveInfo* NamePool::findInfo(const llvm::StringRef& pName)
 {
   Table::iterator iter = m_Table.find(pName);
   return iter.getEntry();
 }
 
 /// findInfo - find the resolved ResolveInfo
-const ResolveInfo* StrSymPool::findInfo(const llvm::StringRef& pName) const
+const ResolveInfo* NamePool::findInfo(const llvm::StringRef& pName) const
 {
   Table::const_iterator iter = m_Table.find(pName);
   return iter.getEntry();
 }
 
 /// findSymbol - find the resolved output LDSymbol
-LDSymbol* StrSymPool::findSymbol(const llvm::StringRef& pName)
+LDSymbol* NamePool::findSymbol(const llvm::StringRef& pName)
 {
   ResolveInfo* info = findInfo(pName);
   if (NULL == info)
@@ -169,7 +146,7 @@
 }
 
 /// findSymbol - find the resolved output LDSymbol
-const LDSymbol* StrSymPool::findSymbol(const llvm::StringRef& pName) const
+const LDSymbol* NamePool::findSymbol(const llvm::StringRef& pName) const
 {
   const ResolveInfo* info = findInfo(pName);
   if (NULL == info)
diff --git a/lib/LD/OutputSymbolTable.cpp b/lib/LD/OutputSymbolTable.cpp
deleted file mode 100644
index a17a211..0000000
--- a/lib/LD/OutputSymbolTable.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- OutputSymbolTable.cpp ----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/OutputSymbolTable.h"
-
-using namespace mcld;
-
-//==========================
-// OutputSymbolTable
-
-
-OutputSymbolTable::OutputSymbolTable(StrSymPool &pStrSymPool,
-                                     size_t pNumOfSymbols,
-                                     StringTable &pEntireStringTable,
-                                     StringTable &pDynamicStringTable)
-  : SymbolTableIF(pStrSymPool)
-{
-  f_StrSymPool.addDirectClient(*this);
-
-  f_pCategorySet->at(CategorySet::Entire).reserve(pNumOfSymbols);
-
-  f_pCategorySet->at(CategorySet::Entire).interpose(&pEntireStringTable);
-  f_pCategorySet->at(CategorySet::Dynamic).interpose(&pDynamicStringTable);
-}
-
-void OutputSymbolTable::doInsertSymbol(LDSymbol *sym)
-{
-  // OutputSymbolTable didn't have any real containers,
-  // so no need to do anything.
-}
-
-void OutputSymbolTable::doMerge(const SymbolTableIF &pSymTab)
-{
-  // OutputSymbolTable didn't have any real containers,
-  // so no need to do anything.
-}
diff --git a/lib/LD/Relocation.cpp b/lib/LD/Relocation.cpp
index 73db39b..0b84ad0 100644
--- a/lib/LD/Relocation.cpp
+++ b/lib/LD/Relocation.cpp
@@ -40,7 +40,7 @@
 
 Relocation::Address Relocation::symValue() const
 {
-  if(m_pSymInfo->type() == ResolveInfo::Section &&
+  if (m_pSymInfo->type() == ResolveInfo::Section &&
      m_pSymInfo->outSymbol()->hasFragRef()) {
     return llvm::cast<LDSection>(
       m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection()).addr();
diff --git a/lib/LD/Resolver.cpp b/lib/LD/Resolver.cpp
index 0f7f06e..aa39b13 100644
--- a/lib/LD/Resolver.cpp
+++ b/lib/LD/Resolver.cpp
@@ -6,28 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/LD/Resolver.h"
-#include <cassert>
+#include <mcld/LD/Resolver.h>
 
 using namespace mcld;
 
 //==========================
 // Resolver
-Resolver::Resolver()
-  : m_Mesg() {
-}
-
-Resolver::Resolver(const Resolver& pCopy)
-  : m_Mesg(pCopy.m_Mesg) {
-}
-
 Resolver::~Resolver()
 {
-  m_Mesg.clear();
-}
-
-void Resolver::clearMesg()
-{
-  m_Mesg.clear();
 }
 
diff --git a/lib/LD/SectionMap.cpp b/lib/LD/SectionMap.cpp
index d81dfdd..9d32391 100644
--- a/lib/LD/SectionMap.cpp
+++ b/lib/LD/SectionMap.cpp
@@ -12,9 +12,8 @@
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // SectionMap
-
 SectionMap::SectionMap()
 {
 }
@@ -38,13 +37,11 @@
   // 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,
-                           const uint64_t pOffset)
+                           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
@@ -57,7 +54,6 @@
   struct Mapping mapping = {
     pInput,
     pOutput,
-    pOffset,
   };
   m_SectMap.push_back(mapping);
   return true;
diff --git a/lib/LD/SectionMerger.cpp b/lib/LD/SectionMerger.cpp
index f6aef9e..f3a5b65 100644
--- a/lib/LD/SectionMerger.cpp
+++ b/lib/LD/SectionMerger.cpp
@@ -18,7 +18,7 @@
 SectionMerger::SectionMerger(SectionMap& pSectionMap, LDContext& pContext)
 : m_SectionNameMap(pSectionMap),
   m_Output(pContext),
-  m_LDSectionMap(pSectionMap.size())
+  m_LDSectionMap()
 {
 }
 
diff --git a/lib/LD/StaticResolver.cpp b/lib/LD/StaticResolver.cpp
index 3ba49e2..09cbc11 100644
--- a/lib/LD/StaticResolver.cpp
+++ b/lib/LD/StaticResolver.cpp
@@ -8,28 +8,19 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/StaticResolver.h>
 #include <mcld/LD/LDSymbol.h>
-#include <cassert>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
-
 //==========================
 // StaticResolver
-StaticResolver::StaticResolver()
-{
-}
-
 StaticResolver::~StaticResolver()
 {
 }
 
-StaticResolver::StaticResolver(const StaticResolver& pCopy)
-  : Resolver(pCopy) {
-}
-
-unsigned int StaticResolver::resolve(ResolveInfo& __restrict__ pOld,
-                                     const ResolveInfo& __restrict__ pNew,
-                                     bool &pOverride)
+bool StaticResolver::resolve(ResolveInfo& __restrict__ pOld,
+                             const ResolveInfo& __restrict__ pNew,
+                             bool &pOverride) const
 {
 
   /* The state table itself.
@@ -41,13 +32,13 @@
   static const enum LinkAction link_action[LAST_ORD][LAST_ORD] =
   {
     /* new\old  U       w_U     d_U    wd_U   D      w_D    d_D    wd_D   C      w_C,   Cs,    Is   */
-    /* U    */ {NOACT,  UND,    UND,   UND,   NOACT, NOACT, DUND,  DUNDW, NOACT, NOACT, NOACT, REFC },
-    /* w_U  */ {NOACT,  NOACT,  NOACT, WEAK,  NOACT, NOACT, DUND,  DUNDW, NOACT, NOACT, NOACT, REFC },
+    /* U    */ {NOACT,  UND,    UND,   UND,   NOACT, NOACT, DUND,  DUND,  NOACT, NOACT, NOACT, REFC },
+    /* w_U  */ {NOACT,  NOACT,  NOACT, WEAK,  NOACT, NOACT, DUNDW, DUNDW, NOACT, NOACT, NOACT, REFC },
     /* d_U  */ {NOACT,  NOACT,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
     /* wd_U */ {NOACT,  NOACT,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
     /* D    */ {DEF,    DEF,    DEF,   DEF,   MDEF,  DEF,   DEF,   DEF,   CDEF,  CDEF,  CDEF,  MDEF },
     /* w_D  */ {DEFW,   DEFW,   DEFW,  DEFW,  NOACT, NOACT, DEFW,  DEFW,  NOACT, NOACT, NOACT, NOACT},
-    /* d_D  */ {DEFD,   MDEFD,  DEFD,  DEFD,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF },
+    /* d_D  */ {MDEFD,  MDEFD,  DEFD,  DEFD,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF },
     /* wd_D */ {MDEFWD, MDEFWD, DEFWD, DEFWD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT},
     /* C    */ {COM,    COM,    COM,   COM,   CREF,  COM,   COM,   COM,   MBIG,  COM,   BIG,   REFC },
     /* w_C  */ {COM,    COM,    COM,   COM,   NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
@@ -71,26 +62,23 @@
   unsigned int col = getOrdinate(pOld);
 
   bool cycle = false;
-  unsigned int result = Resolver::Success;
   pOverride = false;
   ResolveInfo* old = &pOld;
   LinkAction action;
   do {
-    result = Resolver::Success;
     cycle = false;
     action = link_action[row][col];
 
     switch(action) {
       case FAIL: {       /* abort.  */
-        m_Mesg = std::string("internal error [StaticResolver.cpp:loc 86].\n") +
-                 std::string("Please report to `mclinker@googlegroups.com'.\n");
-        result = Resolver::Abort;
-        break;
+        fatal(diag::fail_sym_resolution)
+                << __FILE__ << __LINE__
+                << "mclinker@googlegroups.com";
+        return false;
       }
       case NOACT: {      /* no action.  */
         pOverride = false;
         old->overrideVisibility(pNew);
-        result = Resolver::Success;
         break;
       }
       case UND:          /* override by symbol undefined symbol.  */
@@ -102,7 +90,6 @@
       case COM: {        /* override by symbol common defined.  */
         pOverride = true;
         old->override(pNew);
-        result = Resolver::Success;
         break;
       }
       case MDEFD:        /* mark symbol dynamic defined.  */
@@ -110,31 +97,22 @@
         uint32_t binding = old->binding();
         old->override(pNew);
         old->setBinding(binding);
-        m_Mesg = std::string("symbol `") +
-                 old->name() +
-                 std::string("' uses the type, dynamic, size and type in the dynamic symbol.");
+        ignore(diag::mark_dynamic_defined) << old->name();
         pOverride = true;
-        result = Resolver::Warning;
         break;
       }
       case DUND:
       case DUNDW: {
-        if (old->binding() == ResolveInfo::Weak &&
-            pNew.binding() != ResolveInfo::Weak) {
-          old->setBinding(pNew.binding());
-        }
+        old->override(pNew);
         old->overrideVisibility(pNew);
+        old->setDynamic();
         pOverride = false;
-        result = Resolver::Success;
         break;
       }
       case CREF: {       /* Possibly warn about common reference to defined symbol.  */
         // A common symbol does not override a definition.
-        m_Mesg = std::string("common '") +
-                 pNew.name() +
-                 std::string("' overriden by previous definition.");
+        ignore(diag::comm_refer_to_define) << old->name();
         pOverride = false;
-        result = Resolver::Warning;
         break;
       }
       case CDEF: {       /* redefine existing common symbol.  */
@@ -142,12 +120,9 @@
         // definition overrides.
         //
 	// NOTE: m_Mesg uses 'name' instead of `name' for being compatible to GNU ld.
-        m_Mesg = std::string("definition of '") +
-                 old->name() +
-                 std::string("' is overriding common.");
+        ignore(diag::redefine_common) << old->name();
         old->override(pNew);
         pOverride = true;
-        result = Resolver::Warning;
         break;
       }
       case BIG: {        /* override by symbol common using largest size.  */
@@ -156,7 +131,6 @@
         old->overrideAttributes(pNew);
         old->overrideVisibility(pNew);
         pOverride = true;
-        result = Resolver::Success;
         break;
       }
       case MBIG: {       /* mark common symbol by larger size. */
@@ -164,22 +138,15 @@
           old->setSize(pNew.size());
         old->overrideVisibility(pNew);
         pOverride = false;
-        result = Resolver::Success;
         break;
       }
       case CIND: {       /* mark indirect symbol from existing common symbol.  */
-         m_Mesg = std::string("indirect symbol `") +
-                  pNew.name()+
-                  std::string("' point to a common symbol.\n");
-         result = Resolver::Warning;
+         ignore(diag::indirect_refer_to_common) << old->name();
       }
       /* Fall through */
       case IND: {        /* override by indirect symbol.  */
-        if (0 == pNew.link()) {
-          m_Mesg = std::string("indirect symbol `") +
-                   pNew.name() +
-                   std::string("' point to a inexistent symbol.");
-          result = Resolver::Abort;
+        if (NULL == pNew.link()) {
+          fatal(diag::indirect_refer_to_inexist) << pNew.name();
           break;
         }
 
@@ -203,18 +170,12 @@
       }
       /* Fall through */
       case MDEF: {       /* multiple definition error.  */
-        m_Mesg = std::string("multiple definitions of `") +
-                 pNew.name() +
-                 std::string("'.");
-        result = Resolver::Abort;
+        error(diag::multiple_definitions) << pNew.name();
         break;
       }
       case REFC: {       /* Mark indirect symbol referenced and then CYCLE.  */
-        if (0 == old->link()) {
-          m_Mesg = std::string("indirect symbol `") +
-                   old->name() +
-                   std::string("' point to a inexistent symbol.");
-          result = Resolver::Abort;
+        if (NULL == old->link()) {
+          fatal(diag::indirect_refer_to_inexist) << old->name();
           break;
         }
 
@@ -223,8 +184,12 @@
         cycle = true;
         break;
       }
+      default: {
+        error(diag::undefined_situation) << action << old->name() << pNew.name();
+        return false;
+      }
     } // end of the big switch (action)
   } while(cycle);
-  return result;
+  return true;
 }
 
diff --git a/lib/LD/SymbolTableFactory.cpp b/lib/LD/SymbolTableFactory.cpp
deleted file mode 100644
index 180a4a9..0000000
--- a/lib/LD/SymbolTableFactory.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- SymbolTableFactory.cpp ---------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/SymbolTableFactory.h"
-
-using namespace mcld;
-
-//==========================
-// SymbolTableFactory
-
-SymbolTableFactory::SymbolTableFactory(size_t pNumOfSymbolTables,
-                                       StrSymPool& pStrSymPool)
-  : m_StrSymPool(pStrSymPool),
-    m_InputFactory(pNumOfSymbolTables),
-    m_OutputFactory(pNumOfSymbolTables)
-{
-}
-
-SymbolTableFactory::~SymbolTableFactory()
-{
-}
-
-SymbolTableIF *SymbolTableFactory::
-createInputTable(StringTable &pEntireStringTable,
-                 StringTable &pDynamicStringTable,
-                 size_t pReserve)
-{
-  InputSymbolTable *inputSymTab = m_InputFactory.allocate();
-  new (inputSymTab) InputSymbolTable(m_StrSymPool,
-                                     pReserve,
-                                     pEntireStringTable,
-                                     pDynamicStringTable);
-  return inputSymTab;
-}
-
-SymbolTableIF *SymbolTableFactory::
-createOutputTable(StringTable &pEntireStringTable,
-                  StringTable &pDynamicStringTable,
-                  size_t pReserve)
-{
-  OutputSymbolTable *outputSymTab = m_OutputFactory.allocate();
-  new (outputSymTab) OutputSymbolTable(m_StrSymPool,
-                                       pReserve,
-                                       pEntireStringTable,
-                                       pDynamicStringTable);
-  return outputSymTab;
-}
diff --git a/lib/LD/TextDiagnosticPrinter.cpp b/lib/LD/TextDiagnosticPrinter.cpp
new file mode 100644
index 0000000..466d16d
--- /dev/null
+++ b/lib/LD/TextDiagnosticPrinter.cpp
@@ -0,0 +1,167 @@
+//===- TextDiagnosticPrinter.cpp ------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/TextDiagnosticPrinter.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <llvm/Support/Signals.h>
+#include <string>
+
+using namespace mcld;
+
+static const enum llvm::raw_ostream::Colors UnreachableColor = llvm::raw_ostream::RED;
+static const enum llvm::raw_ostream::Colors FatalColor       = llvm::raw_ostream::YELLOW;
+static const enum llvm::raw_ostream::Colors ErrorColor       = llvm::raw_ostream::RED;
+static const enum llvm::raw_ostream::Colors WarningColor     = llvm::raw_ostream::MAGENTA;
+static const enum llvm::raw_ostream::Colors DebugColor       = llvm::raw_ostream::CYAN;
+static const enum llvm::raw_ostream::Colors NoteColor        = llvm::raw_ostream::GREEN;
+static const enum llvm::raw_ostream::Colors IgnoreColor      = llvm::raw_ostream::BLUE;
+
+// Used for changing only the bold attribute.
+static const enum llvm::raw_ostream::Colors SavedColor = llvm::raw_ostream::SAVEDCOLOR;
+
+//===----------------------------------------------------------------------===//
+// TextDiagnosticPrinter
+TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream& pOStream,
+                                             const MCLDInfo& pLDInfo)
+  : m_OStream(pOStream), m_LDInfo(pLDInfo), m_pInput(NULL) {
+}
+
+TextDiagnosticPrinter::~TextDiagnosticPrinter()
+{
+}
+
+/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+/// capturing it to a log as needed.
+void
+TextDiagnosticPrinter::handleDiagnostic(DiagnosticEngine::Severity pSeverity,
+                                        const Diagnostic& pInfo)
+{
+  DiagnosticPrinter::handleDiagnostic(pSeverity, pInfo);
+
+  std::string out_string;
+  pInfo.format(out_string);
+
+  switch (pSeverity) {
+    case DiagnosticEngine::Unreachable: {
+      m_OStream.changeColor(UnreachableColor, true);
+      m_OStream << "Unreachable: ";
+      m_OStream.resetColor();
+      m_OStream << out_string << "\n";
+      break;
+    }
+    case DiagnosticEngine::Fatal: {
+      m_OStream.changeColor(FatalColor, true);
+      m_OStream << "Fatal: ";
+      m_OStream.resetColor();
+      m_OStream << out_string << "\n";
+      break;
+    }
+    case DiagnosticEngine::Error: {
+      m_OStream.changeColor(ErrorColor, true);
+      m_OStream << "Error: ";
+      m_OStream.resetColor();
+      m_OStream << out_string << "\n";
+      break;
+    }
+    case DiagnosticEngine::Warning: {
+      m_OStream.changeColor(WarningColor, true);
+      m_OStream << "Warning: ";
+      m_OStream.resetColor();
+      m_OStream << out_string << "\n";
+      break;
+    }
+    case DiagnosticEngine::Debug: {
+      // show debug message only if verbose >= 0
+      if (0 <= m_LDInfo.options().verbose()) {
+        m_OStream.changeColor(DebugColor, true);
+        m_OStream << "Debug: ";
+        m_OStream.resetColor();
+        m_OStream << out_string << "\n";
+      }
+      break;
+    }
+    case DiagnosticEngine::Note: {
+      // show ignored message only if verbose >= 1
+      if (1 <= m_LDInfo.options().verbose()) {
+        m_OStream.changeColor(NoteColor, true);
+        m_OStream << "Note: ";
+        m_OStream.resetColor();
+        m_OStream << out_string << "\n";
+      }
+      break;
+    }
+    case DiagnosticEngine::Ignore: {
+      // show ignored message only if verbose >= 2
+      if (2 <= m_LDInfo.options().verbose()) {
+        m_OStream.changeColor(IgnoreColor, true);
+        m_OStream << "Ignore: ";
+        m_OStream.resetColor();
+        m_OStream << out_string << "\n";
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  switch (pSeverity) {
+    case DiagnosticEngine::Unreachable: {
+      m_OStream << "\n\n";
+      m_OStream.changeColor(llvm::raw_ostream::YELLOW);
+      m_OStream << "You encounter a bug of MCLinker, please report to:\n"
+                << "  mclinker@googlegroups.com\n";
+      m_OStream.resetColor();
+    }
+    /** fall through **/
+    case DiagnosticEngine::Fatal: {
+      // 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();
+      exit(1);
+      break;
+    }
+    case DiagnosticEngine::Error: {
+      int16_t error_limit = m_LDInfo.options().maxErrorNum();
+      if ((error_limit != -1) &&
+          (getNumErrors() > static_cast<unsigned>(error_limit))) {
+        m_OStream << "\n\n";
+        m_OStream.changeColor(llvm::raw_ostream::YELLOW);
+        m_OStream << "too many error messages (>" << error_limit << ")...\n";
+        m_OStream.resetColor();
+        llvm::sys::RunInterruptHandlers();
+        exit(1);
+      }
+      break;
+    }
+    case DiagnosticEngine::Warning: {
+      int16_t warning_limit = m_LDInfo.options().maxWarnNum();
+      if ((warning_limit != -1) &&
+          (getNumWarnings() > static_cast<unsigned>(warning_limit))) {
+        m_OStream << "\n\n";
+        m_OStream.changeColor(llvm::raw_ostream::YELLOW);
+        m_OStream << "too many warning messages (>" << warning_limit << ")...\n";
+        m_OStream.resetColor();
+        llvm::sys::RunInterruptHandlers();
+        exit(1);
+      }
+    }
+    default:
+      break;
+  }
+}
+
+void TextDiagnosticPrinter::beginInput(const Input& pInput, const MCLDInfo& pLDInfo)
+{
+  m_pInput = &pInput;
+}
+
+void TextDiagnosticPrinter::endInput()
+{
+  m_pInput = NULL;
+}
diff --git a/lib/MC/ContextFactory.cpp b/lib/MC/ContextFactory.cpp
index d32ea8b..5b698c7 100644
--- a/lib/MC/ContextFactory.cpp
+++ b/lib/MC/ContextFactory.cpp
@@ -33,3 +33,10 @@
   return result;
 }
 
+LDContext* ContextFactory::produce()
+{
+  LDContext* result = allocate();
+  new (result) LDContext();
+  return result;
+}
+
diff --git a/lib/MC/MCLDInputTree.cpp b/lib/MC/InputTree.cpp
similarity index 70%
rename from lib/MC/MCLDInputTree.cpp
rename to lib/MC/InputTree.cpp
index b423988..a1d1449 100644
--- a/lib/MC/MCLDInputTree.cpp
+++ b/lib/MC/InputTree.cpp
@@ -1,4 +1,4 @@
-//===- MCLDInputTree.cpp --------------------------------------------------===//
+//===- InputTree.cpp ------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInputTree.h"
-#include "mcld/MC/InputFactory.h"
+#include <mcld/MC/InputTree.h>
+#include <mcld/MC/InputFactory.h>
 
 using namespace mcld;
 
@@ -24,15 +24,15 @@
 {
 }
 
-InputTree& InputTree::merge(InputTree::iterator pPosition, 
-                            const InputTree::Connector& pConnector,
+InputTree& InputTree::merge(InputTree::iterator pRoot, 
+                            const InputTree::Mover& pMover,
                             InputTree& pTree)
 {
   if (this == &pTree)
     return *this;
 
   if (!pTree.empty()) {
-    pConnector.connect(pPosition, iterator(pTree.m_Root.node.right));
+    pMover.connect(pRoot, iterator(pTree.m_Root.node.right));
     BinaryTreeBase<Input>::m_Root.summon(
         pTree.BinaryTreeBase<Input>::m_Root);
     BinaryTreeBase<Input>::m_Root.delegate(pTree.m_Root);
@@ -41,33 +41,33 @@
   return *this;
 }
 
-InputTree& InputTree::insert(InputTree::iterator pPosition,
-                             const InputTree::Connector& pConnector,
+InputTree& InputTree::insert(InputTree::iterator 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);
-  pConnector.connect(pPosition, iterator(node));
+  pMover.connect(pRoot, iterator(node));
   return *this;
 }
 
-InputTree& InputTree::enterGroup(InputTree::iterator pPosition,
-                                 const InputTree::Connector& pConnector)
+InputTree& InputTree::enterGroup(InputTree::iterator pRoot,
+                                 const InputTree::Mover& pMover)
 {
   NodeBase* node = createNode();
-  pConnector.connect(pPosition, iterator(node));
+  pMover.connect(pRoot, iterator(node));
   return *this;
 }
 
-InputTree& InputTree::insert(InputTree::iterator pPosition,
-                             const InputTree::Connector& pConnector,
+InputTree& InputTree::insert(InputTree::iterator pRoot,
+                             const InputTree::Mover& pMover,
                              const mcld::Input& pInput)
 {
   BinaryTree<Input>::node_type* node = createNode();
   node->data = const_cast<mcld::Input*>(&pInput);
-  pConnector.connect(pPosition, iterator(node));
+  pMover.connect(pRoot, iterator(node));
   return *this;
 }
 
diff --git a/lib/MC/MCLDAttribute.cpp b/lib/MC/MCLDAttribute.cpp
index a361691..f7b7e47 100644
--- a/lib/MC/MCLDAttribute.cpp
+++ b/lib/MC/MCLDAttribute.cpp
@@ -6,40 +6,40 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDAttribute.h"
-#include "mcld/MC/AttributeFactory.h"
+#include <mcld/MC/MCLDAttribute.h>
+#include <mcld/MC/AttributeFactory.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
 //==========================
 // AttrConstraint
-bool AttrConstraint::isLegal(const Attribute& pAttr, std::string &pErrMesg) const
+bool AttrConstraint::isLegal(const Attribute& pAttr) const
 {
   if (!isWholeArchive() && pAttr.isWholeArchive()) {
-    pErrMesg = std::string("Target does not support --whole-archive");
+    error(diag::err_unsupported_whole_archive);
     return false;
   }
   if (!isAsNeeded() && pAttr.isAsNeeded()) {
-    pErrMesg = std::string("Target does not support --as-needed");
+    error(diag::err_unsupported_as_needed);
     return false;
   }
   if (!isAddNeeded() && pAttr.isAddNeeded()) {
-    pErrMesg = std::string("Target does not support --add-needed");
+    error(diag::err_unsupported_add_needed);
     return false;
   }
   if (isStaticSystem() && pAttr.isDynamic()) {
-    pErrMesg = std::string("Target does not support --Bdynamic");
+    error(diag::err_unsupported_Bdynamic);
     return false;
   }
-  // FIXME: may be it's legal, but ignored by GNU ld.
   if (isStaticSystem() && pAttr.isAsNeeded()) {
-    pErrMesg = std::string("Can't enable --as-needed on a target which does not support dynamic linking");
-    return false;
+    warning(diag::err_enable_as_needed_on_static_system);
+    return true;
   }
   // FIXME: may be it's legal, but ignored by GNU ld.
   if (pAttr.isAsNeeded() && pAttr.isStatic()) {
-    pErrMesg = std::string("Can't mix --static with --as-needed");
-    return false;
+    warning(diag::err_mix_static_as_needed);
+    return true;
   }
   return true;
 }
diff --git a/lib/MC/MCLDDriver.cpp b/lib/MC/MCLDDriver.cpp
index 5e89097..a86983d 100644
--- a/lib/MC/MCLDDriver.cpp
+++ b/lib/MC/MCLDDriver.cpp
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/MC/InputTree.h>
 #include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCLDInputTree.h>
 #include <mcld/MC/MCLDDriver.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/LD/ArchiveReader.h>
@@ -15,10 +15,12 @@
 #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 <llvm/Support/ErrorHandling.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace llvm;
 using namespace mcld;
@@ -26,91 +28,83 @@
 MCLDDriver::MCLDDriver(MCLDInfo& pLDInfo, TargetLDBackend& pLDBackend)
   : m_LDInfo(pLDInfo),
     m_LDBackend(pLDBackend),
-    m_pLinker(0) {
+    m_pLinker(NULL) {
+
 }
 
 MCLDDriver::~MCLDDriver()
 {
-  if (0 != m_pLinker)
+  if (NULL != m_pLinker)
     delete m_pLinker;
+
 }
 
-void MCLDDriver::normalize() {
-
+void MCLDDriver::normalize()
+{
+  // -----  set up inputs  ----- //
   InputTree::dfs_iterator input, inEnd = m_LDInfo.inputs().dfs_end();
   for (input = m_LDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
-    // already got type - for example, bitcode
+    // 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::Archive ||
+        (*input)->type() == Input::External)
       continue;
 
-
-    MemoryArea *input_memory =
-        m_LDInfo.memAreaFactory().produce((*input)->path(), O_RDONLY);
-    if ((input_memory != NULL) && input_memory->isGood()) {
-      (*input)->setMemArea(input_memory);
-    }
-    else {
-      llvm::report_fatal_error("can not open file: " + (*input)->path().native());
-      return;
-    }
-
     // is a relocatable object file
     if (m_LDBackend.getObjectReader()->isMyFormat(**input)) {
       (*input)->setType(Input::Object);
-      (*input)->setContext(m_LDInfo.contextFactory().produce((*input)->path()));
       m_LDBackend.getObjectReader()->readObject(**input);
     }
     // is a shared object file
     else if (m_LDBackend.getDynObjReader()->isMyFormat(**input)) {
       (*input)->setType(Input::DynObj);
-      (*input)->setContext(m_LDInfo.contextFactory().produce((*input)->path()));
-      (*input)->setSOName((*input)->path().native());
       m_LDBackend.getDynObjReader()->readDSO(**input);
     }
     // is an archive
     else if (m_LDBackend.getArchiveReader()->isMyFormat(*(*input))) {
       (*input)->setType(Input::Archive);
-      mcld::InputTree* archive_member = m_LDBackend.getArchiveReader()->readArchive(**input);
-      if(!archive_member)  {
-        llvm::report_fatal_error("wrong format archive" + (*input)->path().string());
+      mcld::InputTree* archive_member =
+                          m_LDBackend.getArchiveReader()->readArchive(**input);
+      if(NULL == archive_member)  {
+        error(diag::err_empty_input) << (*input)->name() << (*input)->path();
         return;
       }
 
       m_LDInfo.inputs().merge<InputTree::Inclusive>(input, *archive_member);
     }
     else {
-      llvm::report_fatal_error(llvm::Twine("can not recognize file format: ") +
-                               (*input)->path().native() +
-                               llvm::Twine("\nobject format or target machine is wrong\n"));
+      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) {
-    std::string error_code;
-    if (!m_LDInfo.attrFactory().constraint().isLegal((**attr), error_code)) {
-      report_fatal_error(error_code);
+    if (!m_LDInfo.attrFactory().constraint().isLegal((**attr))) {
       return false;
     }
   }
 
-
-  bool hasDynObj = 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 ) {
-      hasDynObj = true;
+    if ((*input)->type() == mcld::Input::DynObj) {
       if((*input)->attribute()->isStatic()) {
-        report_fatal_error("Can't link shared object with -static option");
+        error(diag::err_mixed_shared_static_objects)
+                                        << (*input)->name() << (*input)->path();
         return false;
       }
     }
@@ -127,7 +121,6 @@
   if (0 == m_pLinker)
     m_pLinker = new MCLinker(m_LDBackend,
                              m_LDInfo,
-                             *m_LDInfo.output().context(),
                              m_SectionMap);
 
   // initialize the readers and writers
@@ -137,16 +130,32 @@
       !m_LDBackend.initObjectReader(*m_pLinker) ||
       !m_LDBackend.initDynObjReader(*m_pLinker) ||
       !m_LDBackend.initObjectWriter(*m_pLinker) ||
-      !m_LDBackend.initDynObjWriter(*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;
 
-  // initialize standard segments and sections
+  /// 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
@@ -174,12 +183,9 @@
     }
   } // end of switch
 
-  // initialize target-dependent segments and sections
+  // initialize target-dependent sections
   m_LDBackend.initTargetSections(*m_pLinker);
 
-  // initialize RelocationFactory
-  m_LDBackend.initRelocFactory(*m_pLinker);
-
   return true;
 }
 
@@ -226,25 +232,13 @@
   return true;
 }
 
-/// mergeSymbolTables - merge the symbol tables of input files into the
-/// output's symbol table.
-bool MCLDDriver::mergeSymbolTables()
-{
-  mcld::InputTree::dfs_iterator input, inEnd = m_LDInfo.inputs().dfs_end();
-  for (input=m_LDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
-    if (!m_pLinker->mergeSymbolTable(**input))
-      return false;
-  }
-  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);
+  return m_LDBackend.initStandardSymbols(*m_pLinker, m_LDInfo.output());
 }
 
 /// addTargetSymbols - some targets, such as MIPS and ARM, need some
@@ -253,7 +247,7 @@
 ///   target symbols, return false
 bool MCLDDriver::addTargetSymbols()
 {
-  m_LDBackend.initTargetSymbols(*m_pLinker);
+  m_LDBackend.initTargetSymbols(*m_pLinker, m_LDInfo.output());
   return true;
 }
 
@@ -284,6 +278,11 @@
 
   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.
@@ -314,16 +313,6 @@
   return true;
 }
 
-/// 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::relocate()
-{
-  return m_pLinker->applyRelocations();
-}
-
 /// finalizeSymbolValue - finalize the resolved symbol value.
 ///   Before relocate(), after layout(), MCLinker should correct value of all
 ///   symbol.
@@ -332,6 +321,16 @@
   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()
 {
@@ -342,10 +341,9 @@
     case Output::DynObj:
       m_LDBackend.getDynObjWriter()->writeDynObj(m_LDInfo.output());
       return true;
-    /** TODO: open the executable file writer **/
-    // case Output::Exec:
-      // m_LDBackend.getExecWriter()->writeObject(m_LDInfo.output());
-      // return true;
+    case Output::Exec:
+      m_LDBackend.getExecWriter()->writeExecutable(m_LDInfo.output());
+      return true;
   }
   return false;
 }
@@ -354,5 +352,9 @@
 bool MCLDDriver::postProcessing()
 {
   m_pLinker->syncRelocationResult();
+
+  m_LDBackend.postProcessing(m_LDInfo.output(),
+                             m_LDInfo,
+                             *m_pLinker);
   return true;
 }
diff --git a/lib/MC/MCLDInfo.cpp b/lib/MC/MCLDInfo.cpp
index 3cd0838..7ac154c 100644
--- a/lib/MC/MCLDInfo.cpp
+++ b/lib/MC/MCLDInfo.cpp
@@ -6,12 +6,14 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/Config/Config.h>
 #include <mcld/MC/MCLDInfo.h>
-#include <mcld/Support/FileSystem.h>
 #include <mcld/MC/InputFactory.h>
 #include <mcld/MC/AttributeFactory.h>
 #include <mcld/MC/ContextFactory.h>
-#include <mcld/Config/Config.h>
+#include <mcld/LD/NamePool.h>
+#include <mcld/LD/StaticResolver.h>
+#include <mcld/Support/FileSystem.h>
 #include <string>
 
 using namespace mcld;
@@ -22,16 +24,17 @@
                    size_t pAttrNum,
                    size_t pInputNum)
   : m_Options(),
-    m_pBitcode(0),
-    m_Triple(pTripleString),
-    m_pStrSymPool(0)
+    m_Scripts(),
+    m_pBitcode(NULL),
+    m_Triple(pTripleString)
 {
   m_pAttrFactory = new AttributeFactory(pAttrNum);
   m_pCntxtFactory = new ContextFactory(pInputNum);
-  m_pMemAreaFactory = new MemoryAreaFactory(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()
@@ -39,9 +42,10 @@
   delete m_pOutput;
   delete m_pAttrFactory;
   delete m_pCntxtFactory;
-  delete m_pMemAreaFactory;
   delete m_pInputFactory;
   delete m_pInputTree;
+  delete m_pResolver;
+  delete m_pNamePool;
 }
 
 void MCLDInfo::setBitcode(const Input& pInput)
@@ -63,5 +67,5 @@
 
 const char* MCLDInfo::version()
 {
-  return mcld::internal::version;
+  return MCLD_VERSION;
 }
diff --git a/lib/MC/MCLDOptions.cpp b/lib/MC/MCLDOptions.cpp
index ae07f26..47dbc35 100644
--- a/lib/MC/MCLDOptions.cpp
+++ b/lib/MC/MCLDOptions.cpp
@@ -6,13 +6,59 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDOptions.h"
-#include "mcld/MC/MCLDInput.h"
+#include <mcld/MC/MCLDOptions.h>
+#include <mcld/MC/MCLDInput.h>
 
 using namespace mcld;
 
-//==========================
-// MCLDOptions
+//===----------------------------------------------------------------------===//
+// ScriptOptions
+ScriptOptions::ScriptOptions()
+{
+}
+
+ScriptOptions::~ScriptOptions()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// GeneralOptions
+GeneralOptions::GeneralOptions()
+  : m_pDefaultBitcode(NULL),
+    m_Verbose(-1),
+    m_MaxErrorNum(-1),
+    m_MaxWarnNum(-1),
+    m_ExecStack(Unknown),
+    m_CommPageSize(0x0),
+    m_MaxPageSize(0x0),
+    m_bCombReloc(true),
+    m_bNoUndefined(false),
+    m_bInitFirst(false),
+    m_bInterPose(false),
+    m_bLoadFltr(false),
+    m_bMulDefs(false),
+    m_bNoCopyReloc(false),
+    m_bNoDefaultLib(false),
+    m_bNoDelete(false),
+    m_bNoDLOpen(false),
+    m_bNoDump(false),
+    m_bRelro(false),
+    m_bNow(false),
+    m_bOrigin(false),
+    m_bTrace(false),
+    m_Bsymbolic(false),
+    m_Bgroup(false),
+    m_bPIE(false),
+    m_bColor(true),
+    m_bAllowShlibUndefined(true),
+    m_bCreateEhFrameHdr(false)
+{
+}
+
+GeneralOptions::~GeneralOptions()
+{
+}
+
 bool GeneralOptions::hasDefaultLDScript() const
 {
   return true;
@@ -32,3 +78,75 @@
   m_Sysroot.assign(pSysroot);
 }
 
+void GeneralOptions::addZOption(const ZOption& pOption)
+{
+  switch (pOption.kind()) {
+    case ZOption::CombReloc:
+      m_bCombReloc = true;
+      break;
+    case ZOption::NoCombReloc:
+      m_bCombReloc = false;
+      break;
+    case ZOption::Defs:
+      m_bNoUndefined = true;
+      break;
+    case ZOption::ExecStack:
+      m_ExecStack = YES;
+      break;
+    case ZOption::NoExecStack:
+      m_ExecStack = NO;
+      break;
+    case ZOption::InitFirst:
+      m_bInitFirst = true;
+      break;
+    case ZOption::InterPose:
+      m_bInterPose = true;
+      break;
+    case ZOption::LoadFltr:
+      m_bLoadFltr = true;
+      break;
+    case ZOption::MulDefs:
+      m_bMulDefs = true;
+      break;
+    case ZOption::NoCopyReloc:
+      m_bNoCopyReloc = true;
+      break;
+    case ZOption::NoDefaultLib:
+      m_bNoDefaultLib = true;
+      break;
+    case ZOption::NoDelete:
+      m_bNoDelete = true;
+      break;
+    case ZOption::NoDLOpen:
+      m_bNoDLOpen = true;
+      break;
+    case ZOption::NoDump:
+      m_bNoDump = true;
+      break;
+    case ZOption::NoRelro:
+      m_bRelro = false;
+      break;
+    case ZOption::Relro:
+      m_bRelro = true;
+      break;
+    case ZOption::Lazy:
+      m_bNow = false;
+      break;
+    case ZOption::Now:
+      m_bNow = true;
+      break;
+    case ZOption::Origin:
+      m_bOrigin = true;
+      break;
+    case ZOption::CommPageSize:
+      m_CommPageSize = pOption.pageSize();
+      break;
+    case ZOption::MaxPageSize:
+      m_MaxPageSize = pOption.pageSize();
+      break;
+    case ZOption::Unknown:
+    default:
+      assert(false && "Not a recognized -z option.");
+      break;
+  }
+}
diff --git a/lib/MC/MCLinker.cpp b/lib/MC/MCLinker.cpp
index e5327e8..4b9c50f 100644
--- a/lib/MC/MCLinker.cpp
+++ b/lib/MC/MCLinker.cpp
@@ -10,7 +10,6 @@
 // This file implements the MCLinker class
 //
 //===----------------------------------------------------------------------===//
-
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/MCLDInput.h>
 #include <mcld/MC/MCLDInfo.h>
@@ -20,7 +19,10 @@
 #include <mcld/LD/LDSectionFactory.h>
 #include <mcld/LD/SectionMap.h>
 #include <mcld/LD/RelocationFactory.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>
 #include <llvm/Support/Host.h>
 #include <llvm/Support/raw_ostream.h>
@@ -30,25 +32,22 @@
 /// Constructor
 MCLinker::MCLinker(TargetLDBackend& pBackend,
                    MCLDInfo& pInfo,
-                   LDContext& pContext,
-                   SectionMap& pSectionMap,
-                   const Resolver& pResolver)
+                   SectionMap& pSectionMap)
 : m_Backend(pBackend),
-  m_Info(pInfo),
-  m_Output(pContext),
+  m_LDInfo(pInfo),
   m_SectionMap(pSectionMap),
   m_LDSymbolFactory(128),
   m_LDSectHdrFactory(10), // the average number of sections. (assuming 10.)
   m_LDSectDataFactory(10),
-  m_SectionMerger(pSectionMap, pContext),
-  m_StrSymPool(pResolver, 128)
+  m_pSectionMerger(NULL)
 {
-  m_Info.setNamePool(m_StrSymPool);
 }
 
 /// Destructor
 MCLinker::~MCLinker()
 {
+  if (NULL != m_pSectionMerger)
+    delete m_pSectionMerger;
 }
 
 /// addSymbolFromObject - add a symbol from object file and resolve it
@@ -70,7 +69,7 @@
   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_StrSymPool.createSymbol(pName,
+    resolved_result.info     = m_LDInfo.getNamePool().createSymbol(pName,
                                                          false,
                                                          pType,
                                                          pDesc,
@@ -85,8 +84,9 @@
   }
   else {
     // if the symbol is not local, insert and resolve it immediately
-    m_StrSymPool.insertSymbol(pName, false, pType, pDesc, pBinding, pSize,
-                              pVisibility, &old_info, resolved_result);
+    m_LDInfo.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
+                                        pSize, pVisibility,
+                                        &old_info, resolved_result);
   }
 
   // the return ResolveInfo should not NULL
@@ -188,7 +188,8 @@
   // insert symbol and resolve it immediately
   // resolved_result is a triple <resolved_info, existent, override>
   Resolver::Result resolved_result;
-  m_StrSymPool.insertSymbol(pName, true, pType, pDesc, pBinding, pSize, pVisibility,
+  m_LDInfo.getNamePool().insertSymbol(pName, true, pType, pDesc,
+                            pBinding, pSize, pVisibility,
                             NULL, resolved_result);
 
   // the return ResolveInfo should not NULL
@@ -238,14 +239,15 @@
                                            MCFragmentRef* pFragmentRef,
                                            ResolveInfo::Visibility pVisibility)
 {
-  ResolveInfo* info = m_StrSymPool.findInfo(pName);
+  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_StrSymPool.insertSymbol(pName, pIsDyn, pType, pDesc, pBinding, pSize, pVisibility,
-                              NULL, result);
+    m_LDInfo.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc,
+                                        pBinding, pSize, pVisibility,
+                                        NULL, result);
     assert(!result.existent);
 
     // create a output LDSymbol
@@ -307,7 +309,7 @@
                                            MCFragmentRef* pFragmentRef,
                                            ResolveInfo::Visibility pVisibility)
 {
-  ResolveInfo* info = m_StrSymPool.findInfo(pName);
+  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
 
   if (NULL == info || !info->isUndef()) {
     // only undefined symbol can make a reference.
@@ -361,8 +363,9 @@
   // Result is <info, existent, override>
   Resolver::Result result;
   ResolveInfo old_info;
-  m_StrSymPool.insertSymbol(pName, pIsDyn, pType, pDesc, pBinding, pSize, pVisibility,
-                            &old_info, result);
+  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);
@@ -403,7 +406,7 @@
                                                     MCFragmentRef* pFragmentRef,
                                                     ResolveInfo::Visibility pVisibility)
 {
-  ResolveInfo* info = m_StrSymPool.findInfo(pName);
+  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
 
   if (NULL == info || !info->isUndef()) {
     // only undefined symbol can make a reference
@@ -427,20 +430,22 @@
                                    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_Output.getSection(sect_name);
+  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_Output.getSectionTable().push_back(output_sect);
-    m_SectionMerger.addMapping(pName, output_sect);
+    m_LDInfo.output().context()->getSectionTable().push_back(output_sect);
+    m_pSectionMerger->addMapping(pName, output_sect);
   }
   return *result;
 }
@@ -453,17 +458,19 @@
                                               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_Output.getSection(sect_name);
+  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_Output.getSectionTable().push_back(output_sect);
-    m_SectionMerger.addMapping(pName, output_sect);
+    m_LDInfo.output().context()->getSectionTable().push_back(output_sect);
+    m_pSectionMerger->addMapping(pName, output_sect);
   }
   return *output_sect;
 }
@@ -481,7 +488,7 @@
 
   // try to get one from output LDSection
   LDSection* output_sect =
-    m_SectionMerger.getOutputSectHdr(pSection.name());
+    m_pSectionMerger->getOutputSectHdr(pSection.name());
 
   assert(NULL != output_sect);
 
@@ -509,8 +516,17 @@
                                     const LDSymbol& pSym,
                                     ResolveInfo& pResolveInfo,
                                     MCFragmentRef& 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);
@@ -519,9 +535,11 @@
 
   m_RelocationList.push_back(relocation);
 
-  m_Backend.scanRelocation(*relocation, pSym, *this, m_Info,
-                           m_Info.output());
+  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;
 }
 
@@ -531,7 +549,7 @@
 
   for (relocIter = m_RelocationList.begin(); relocIter != relocEnd; ++relocIter) {
     llvm::MCFragment* frag = (llvm::MCFragment*)relocIter;
-    static_cast<Relocation*>(frag)->apply(*m_Backend.getRelocFactory(), m_Info);
+    static_cast<Relocation*>(frag)->apply(*m_Backend.getRelocFactory(), m_LDInfo);
   }
   return true;
 }
@@ -539,9 +557,8 @@
 void MCLinker::syncRelocationResult()
 {
 
-  m_Info.output().memArea()->clean();
-  MemoryRegion* region = m_Info.output().memArea()->request(0,
-                              m_Info.output().memArea()->size());
+  MemoryRegion* region = m_LDInfo.output().memArea()->request(0,
+                              m_LDInfo.output().memArea()->handler()->size());
 
   uint8_t* data = region->getBuffer();
 
@@ -580,13 +597,19 @@
     }
   } // end of for
 
-  m_Info.output().memArea()->sync();
+  m_LDInfo.output().memArea()->clear();
 }
 
+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_Info.output(), m_Backend);
+  return m_Layout.layout(m_LDInfo.output(), m_Backend, m_LDInfo);
 }
 
 bool MCLinker::finalizeSymbols()
@@ -594,18 +617,9 @@
   SymbolCategory::iterator symbol, symEnd = m_OutputSymbols.end();
   for (symbol = m_OutputSymbols.begin(); symbol != symEnd; ++symbol) {
 
-    if (0x0 != (*symbol)->resolveInfo()->reserved()) {
-      // if the symbol is target reserved, target backend is responsible
-      // for finalizing the value.
-      // if target backend does not know this symbol, it will return false
-      // and we have to take over the symbol.
-      if (m_Backend.finalizeSymbol(**symbol))
-        continue;
-    }
-
     if ((*symbol)->resolveInfo()->isAbsolute() ||
         (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
-      // absolute symbols and symbols with function type should have
+      // absolute symbols or symbols with function type should have
       // zero value
       (*symbol)->setValue(0x0);
       continue;
@@ -623,7 +637,8 @@
     }
   }
 
-  return true;
+  // finialize target-dependent symbols
+  return m_Backend.finalizeSymbols(*this, m_LDInfo.output());
 }
 
 bool MCLinker::shouldForceLocal(const ResolveInfo& pInfo) const
@@ -633,7 +648,7 @@
   // 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_Info.output().type() != Output::Object &&
+  if (m_LDInfo.output().type() != Output::Object &&
       (pInfo.visibility() == ResolveInfo::Hidden ||
          pInfo.visibility() == ResolveInfo::Internal) &&
       (pInfo.isGlobal() || pInfo.isWeak()) &&
@@ -642,3 +657,44 @@
   return false;
 }
 
+/// addEhFrame - add an exception handling section
+/// @param pSection - the input section
+/// @param pArea - the memory area which pSection is within.
+uint64_t MCLinker::addEhFrame(LDSection& pSection, MemoryArea& pArea)
+{
+  uint64_t size = 0;
+
+  // get the SectionData of this eh_frame
+  llvm::MCSectionData& 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, 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(pSection.offset(),
+                                       pSection.size());
+
+  llvm::MCFragment* 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 llvm::MCFillFragment(0x0, 0, 0);
+  }
+  else
+    frag = new MCRegionFragment(*region);
+
+  size = m_Layout.appendFragment(*frag, sect_data, pSection.align());
+  return size;
+}
+
diff --git a/lib/MC/README b/lib/MC/README
deleted file mode 100644
index f020b50..0000000
--- a/lib/MC/README
+++ /dev/null
@@ -1,8 +0,0 @@
-MCLDStreamer is similar to MCObjectStreamer
-MCLinker is similar to MCAssembler
-MCLDWriter is similar to MCObjectWriter
-
-MCELFObjectReader parses ELF object files
-to MCInst classes
-
-
diff --git a/lib/MC/SearchDirs.cpp b/lib/MC/SearchDirs.cpp
index 0d21e46..40d625b 100644
--- a/lib/MC/SearchDirs.cpp
+++ b/lib/MC/SearchDirs.cpp
@@ -6,16 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/ADT/Twine.h>
-
-#include "mcld/MC/SearchDirs.h"
-#include "mcld/Support/FileSystem.h"
-#include "mcld/MC/MCLDDirectory.h"
+#include <mcld/MC/SearchDirs.h>
+#include <mcld/MC/MCLDDirectory.h>
+#include <mcld/Support/FileSystem.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // Non-member functions
 static void SpecToFilename(const std::string& pSpec, std::string& pFile)
 {
@@ -23,7 +20,7 @@
   pFile += pSpec;
 }
 
-//==========================
+//===----------------------------------------------------------------------===//
 // SearchDirs
 SearchDirs::SearchDirs()
 {
@@ -47,6 +44,8 @@
 
 mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec, mcld::Input::Type pType)
 {
+  assert(Input::DynObj == pType || Input::Archive == pType);
+
   std::string file;
   SpecToFilename(pNamespec, file);
   // for all MCLDDirectorys
@@ -64,11 +63,10 @@
               return entry.path();
             }
           }
-
           ++entry;
         }
       }
-
+      /** Fall through **/
       case Input::Archive : {
         entry = (*mcld_dir)->begin();
         enEnd = (*mcld_dir)->end();
@@ -78,15 +76,12 @@
             return entry.path();
           }
           ++entry;
-       }
-     }
-     default: {
-       llvm::report_fatal_error(llvm::Twine("SearchDir can not recoginize namespec: `") +
-                                pNamespec +
-                                llvm::Twine("'."));
-     }
-    }
-  }
-  return 0;
+        }
+      }
+      default:
+        break;
+    } // end of switch
+  } // end of while
+  return NULL;
 }
 
diff --git a/lib/MC/ZOption.cpp b/lib/MC/ZOption.cpp
new file mode 100644
index 0000000..a58562d
--- /dev/null
+++ b/lib/MC/ZOption.cpp
@@ -0,0 +1,25 @@
+//===- ZOption.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/ZOption.h>
+
+using namespace mcld;
+
+//==========================
+// ZOption
+
+ZOption::ZOption()
+  : m_Kind(Unknown),
+    m_PageSize(0x0)
+{
+}
+
+ZOption::~ZOption()
+{
+}
+
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 57b82df..cc15e37 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -6,12 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/CommandLine.h"
+#include <mcld/Support/CommandLine.h>
 #include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/ErrorHandling.h>
 
 using namespace llvm;
 using namespace llvm::cl;
 
+using namespace mcld;
+
 //--------------------------------------------------
 // parser<mcld::sys::fs::Path>
 //
@@ -82,3 +86,81 @@
   // do nothing
 }
 
+//--------------------------------------------------
+// parser<mcld::ZOption>
+//
+bool parser<mcld::ZOption>::parse(llvm::cl::Option &O,
+                                  llvm::StringRef ArgName,
+                                  llvm::StringRef Arg,
+                                  mcld::ZOption &Val)
+{
+  if (0 == Arg.compare("combreloc"))
+    Val.setKind(ZOption::CombReloc);
+  else if (0 == Arg.compare("nocombreloc"))
+    Val.setKind(ZOption::NoCombReloc);
+  else if (0 == Arg.compare("defs"))
+    Val.setKind(ZOption::Defs);
+  else if (0 == Arg.compare("execstack"))
+    Val.setKind(ZOption::ExecStack);
+  else if (0 == Arg.compare("noexecstack"))
+    Val.setKind(ZOption::NoExecStack);
+  else if (0 == Arg.compare("initfirst"))
+    Val.setKind(ZOption::InitFirst);
+  else if (0 == Arg.compare("interpose"))
+    Val.setKind(ZOption::InterPose);
+  else if (0 == Arg.compare("loadfltr"))
+    Val.setKind(ZOption::LoadFltr);
+  else if (0 == Arg.compare("muldefs"))
+    Val.setKind(ZOption::MulDefs);
+  else if (0 == Arg.compare("nocopyreloc"))
+    Val.setKind(ZOption::NoCopyReloc);
+  else if (0 == Arg.compare("nodefaultlib"))
+    Val.setKind(ZOption::NoDefaultLib);
+  else if (0 == Arg.compare("nodelete"))
+    Val.setKind(ZOption::NoDelete);
+  else if (0 == Arg.compare("nodlopen"))
+    Val.setKind(ZOption::NoDLOpen);
+  else if (0 == Arg.compare("nodump"))
+    Val.setKind(ZOption::NoDump);
+  else if (0 == Arg.compare("relro"))
+    Val.setKind(ZOption::Relro);
+  else if (0 == Arg.compare("norelro"))
+    Val.setKind(ZOption::NoRelro);
+  else if (0 == Arg.compare("lazy"))
+    Val.setKind(ZOption::Lazy);
+  else if (0 == Arg.compare("now"))
+    Val.setKind(ZOption::Now);
+  else if (0 == Arg.compare("origin"))
+    Val.setKind(ZOption::Origin);
+  else if (Arg.startswith("common-page-size=")) {
+    Val.setKind(ZOption::CommPageSize);
+    long long unsigned size = 0;
+    Arg.drop_front(17).getAsInteger(0, size);
+    Val.setPageSize(static_cast<uint64_t>(size));
+  } else if (Arg.startswith("max-page-size=")) {
+    Val.setKind(ZOption::MaxPageSize);
+    long long unsigned size = 0;
+    Arg.drop_front(14).getAsInteger(0, size);
+    Val.setPageSize(static_cast<uint64_t>(size));
+  }
+
+  if (ZOption::Unknown == Val.kind())
+    llvm::report_fatal_error(llvm::Twine("unknown -z option: `") +
+                             Arg +
+                             llvm::Twine("'\n"));
+  return false;
+}
+
+void parser<mcld::ZOption>::printOptionDiff(const llvm::cl::Option &O,
+                                            const mcld::ZOption &V,
+                                            parser<mcld::ZOption>::OptVal Default,
+                                            size_t GlobalWidth) const
+{
+  // TODO
+}
+
+void parser<mcld::ZOption>::anchor()
+{
+  // do nothing
+}
+
diff --git a/lib/Support/Directory.cpp b/lib/Support/Directory.cpp
index 211b42a..78bb761 100644
--- a/lib/Support/Directory.cpp
+++ b/lib/Support/Directory.cpp
@@ -32,7 +32,7 @@
   : m_Path(),
     m_FileStatus(),
     m_SymLinkStatus(),
-    m_Handler(NULL),
+    m_Handler(0),
     m_Cache(),
     m_CacheFull(false) {
 }
@@ -43,7 +43,7 @@
   : m_Path(pPath),
     m_FileStatus(st),
     m_SymLinkStatus(symlink_st),
-    m_Handler(NULL),
+    m_Handler(0),
     m_Cache(),
     m_CacheFull(false) {
   if (m_Path.native() == ".")
@@ -56,7 +56,7 @@
   : m_Path(pCopy.m_Path),
     m_FileStatus(pCopy.m_FileStatus),
     m_SymLinkStatus(pCopy.m_SymLinkStatus),
-    m_Handler(NULL),
+    m_Handler(0),
     m_Cache(),
     m_CacheFull(false) {
   mcld::sys::fs::detail::open_dir(*this);
diff --git a/lib/Support/FileHandle.cpp b/lib/Support/FileHandle.cpp
new file mode 100644
index 0000000..f6b898c
--- /dev/null
+++ b/lib/Support/FileHandle.cpp
@@ -0,0 +1,332 @@
+//===- FileHandle.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/FileSystem.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// FileHandle
+FileHandle::FileHandle()
+  : m_Path(),
+    m_Handler(-1),
+    m_Size(0),
+    m_State(GoodBit),
+    m_OpenMode(NotOpen) {
+}
+
+FileHandle::~FileHandle()
+{
+  if (isOpened())
+    close();
+}
+
+inline static int oflag(FileHandle::OpenMode pMode)
+{
+  int result = 0x0;
+  if (FileHandle::Unknown == pMode)
+    return result;
+
+  if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
+    result |= O_RDWR;
+  else if (pMode & FileHandle::ReadOnly)
+    result |= O_RDONLY;
+  else if (pMode & FileHandle::WriteOnly)
+    result |= O_WRONLY;
+
+  if (pMode & FileHandle::Append)
+    result |= O_APPEND;
+
+  if (pMode & FileHandle::Create)
+    result |= O_CREAT;
+
+  if (pMode & FileHandle::Truncate)
+    result |= O_TRUNC;
+
+  return result;
+}
+
+inline static bool get_size(int pHandler, unsigned int &pSize)
+{
+  struct ::stat file_stat;
+  if (-1 == ::fstat(pHandler, &file_stat)) {
+    pSize = 0;
+    return false;
+  }
+  pSize = file_stat.st_size;
+  return true;
+}
+
+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)
+{
+  if (isOpened() || Unknown == pMode) {
+    setState(BadBit);
+    return false;
+  }
+
+  m_OpenMode = pMode;
+  m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
+  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::delegate(int pFD, FileHandle::OpenMode pMode)
+{
+  if (isOpened()) {
+    setState(BadBit);
+    return false;
+  }
+
+  m_Handler = pFD;
+  m_OpenMode = pMode;
+  m_State = GoodBit;
+
+  if (!get_size(m_Handler, m_Size)) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+bool FileHandle::close()
+{
+  if (!isOpened()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (-1 == ::close(m_Handler)) {
+    setState(FailBit);
+    return false;
+  }
+
+  m_Path.native().clear();
+  m_Size = 0;
+  m_OpenMode = NotOpen;
+  cleanState();
+  return true;
+}
+
+bool FileHandle::truncate(size_t pSize)
+{
+  if (!isOpened() || !isWritable()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (-1 == sys::fs::detail::ftruncate(m_Handler, pSize)) {
+    setState(FailBit);
+    return false;
+  }
+
+  m_Size = pSize;
+  return true;
+}
+
+bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+  if (!isOpened() || !isReadable()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (0 == pLength)
+    return true;
+
+  ssize_t read_bytes = sys::fs::detail::pread(m_Handler,
+                                              pMemBuffer,
+                                              pLength,
+                                              pStartOffset);
+
+  if (-1 == read_bytes) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+bool FileHandle::write(const void* pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+  if (!isOpened() || !isWritable()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (0 == pLength)
+    return true;
+
+
+  ssize_t write_bytes = sys::fs::detail::pwrite(m_Handler,
+                                                pMemBuffer,
+                                                pLength,
+                                                pStartOffset);
+
+  if (-1 == write_bytes) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+#include <iostream>
+using namespace std;
+
+bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+  if (!isOpened()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (0 == pLength)
+    return true;
+
+  int prot, flag;
+  if (isReadable() && !isWritable()) {
+    // read-only
+    prot = PROT_READ;
+    flag = MAP_FILE | MAP_PRIVATE;
+  }
+  else if (!isReadable() && isWritable()) {
+    // write-only
+    prot = PROT_WRITE;
+    flag = MAP_FILE | MAP_SHARED;
+  }
+  else if (isReadWrite()) {
+    // read and write
+    prot = PROT_READ | PROT_WRITE;
+    flag = MAP_FILE | MAP_SHARED;
+  }
+  else {
+    // can not read/write
+    setState(BadBit);
+    return false;
+  }
+
+  pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset);
+
+  if (MAP_FAILED == pMemBuffer) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+bool FileHandle::munmap(void* pMemBuffer, size_t pLength)
+{
+  if (!isOpened()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (-1 == ::munmap(pMemBuffer, pLength)) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+void FileHandle::setState(FileHandle::IOState pState)
+{
+  m_State |= pState;
+}
+
+void FileHandle::cleanState(FileHandle::IOState pState)
+{
+  m_State = pState;
+}
+
+bool FileHandle::isOpened() const
+{
+  if (-1 != m_Handler && m_OpenMode != NotOpen && isGood())
+    return true;
+
+  return false;
+}
+
+// Assume Unknown OpenMode is readable
+bool FileHandle::isReadable() const
+{
+  return (m_OpenMode & ReadOnly);
+}
+
+// Assume Unknown OpenMode is writable
+bool FileHandle::isWritable() const
+{
+  return (m_OpenMode & WriteOnly);
+}
+
+// Assume Unknown OpenMode is both readable and writable
+bool FileHandle::isReadWrite() const
+{
+  return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite));
+}
+
+bool FileHandle::isGood() const
+{
+  return !(m_State & (BadBit | FailBit));
+}
+
+bool FileHandle::isBad() const
+{
+  return (m_State & BadBit);
+}
+
+bool FileHandle::isFailed() const
+{
+  return (m_State & (BadBit | FailBit));
+}
+
diff --git a/lib/Support/FileSystem.cpp b/lib/Support/FileSystem.cpp
index d3366c0..fb2633d 100644
--- a/lib/Support/FileSystem.cpp
+++ b/lib/Support/FileSystem.cpp
@@ -9,10 +9,6 @@
 #include "mcld/Support/FileSystem.h"
 #include "mcld/Support/Path.h"
 
-#if defined(ANDROID)
-#include <llvm/Config/config.h>
-#endif
-
 using namespace mcld::sys::fs;
 
 
@@ -22,12 +18,12 @@
 //===--------------------------------------------------------------------===//
 // non-member functions
 
-// Include the truly platform-specific parts.
-#if defined(LLVM_ON_UNIX)
+// Include the truly platform-specific parts. 
+#if defined(MCLD_ON_UNIX)
 #include "Unix/FileSystem.inc"
-#include "Unix/PathV3.inc"
-#endif
-#if defined(LLVM_ON_WIN32)
+#include "Unix/PathV3.inc" 
+#endif 
+#if defined(MCLD_ON_WIN32)
 #include "Windows/FileSystem.inc"
-#include "Windows/PathV3.inc"
-#endif
+#include "Windows/PathV3.inc" 
+#endif 
diff --git a/lib/Support/HandleToArea.cpp b/lib/Support/HandleToArea.cpp
new file mode 100644
index 0000000..f580e64
--- /dev/null
+++ b/lib/Support/HandleToArea.cpp
@@ -0,0 +1,94 @@
+//===- HandleToArea.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/HandleToArea.h>
+#include <mcld/Support/MemoryArea.h>
+#include <llvm/ADT/StringRef.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// HandleToArea
+bool HandleToArea::push_back(FileHandle* pHandle, MemoryArea* pArea)
+{
+  if (NULL == pHandle || NULL == pArea)
+    return false;
+
+  Bucket bucket;
+  bucket.hash_value = HashFunction()(
+                              llvm::StringRef(pHandle->path().native().c_str(),
+                                              pHandle->path().native().size()));
+
+  bucket.handle = pHandle;
+  bucket.area = pArea;
+  m_AreaMap.push_back(bucket);
+  return true;
+}
+
+bool HandleToArea::erase(MemoryArea* pArea)
+{
+  if (NULL == pArea || NULL == pArea->handler())
+    return false;
+
+  return erase(pArea->handler()->path());
+}
+
+bool HandleToArea::erase(const sys::fs::Path& pPath)
+{
+  unsigned int hash_value = HashFunction()(
+                                  llvm::StringRef(pPath.native().c_str(),
+                                                  pPath.native().size()));
+
+  HandleToAreaMap::iterator bucket, bEnd = m_AreaMap.end();
+  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+    if (bucket->hash_value == hash_value && bucket->handle->path() == pPath) {
+      // found
+      m_AreaMap.erase(bucket);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+HandleToArea::Result HandleToArea::findFirst(const sys::fs::Path& pPath)
+{
+  unsigned int hash_value = HashFunction()(llvm::StringRef(pPath.native().c_str(),
+                                                         pPath.native().size()));
+
+  HandleToAreaMap::iterator bucket, bEnd = m_AreaMap.end();
+
+  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+    if (bucket->hash_value == hash_value) {
+      if (bucket->handle->path() == pPath) {
+        return Result(bucket->handle, bucket->area);
+      }
+    }
+  }
+
+  return Result(NULL, NULL);
+}
+
+HandleToArea::ConstResult HandleToArea::findFirst(const sys::fs::Path& pPath) const
+{
+  unsigned int hash_value = HashFunction()(llvm::StringRef(pPath.native().c_str(),
+                                                         pPath.native().size()));
+
+  HandleToAreaMap::const_iterator bucket, bEnd = m_AreaMap.end();
+
+  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+    if (bucket->hash_value == hash_value) {
+      if (bucket->handle->path() == pPath) {
+        return ConstResult(bucket->handle, bucket->area);
+      }
+    }
+  }
+
+  return ConstResult(NULL, NULL);
+}
+
diff --git a/lib/Support/MemoryArea.cpp b/lib/Support/MemoryArea.cpp
index f388e94..78a9d36 100644
--- a/lib/Support/MemoryArea.cpp
+++ b/lib/Support/MemoryArea.cpp
@@ -6,164 +6,31 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/ADT/Twine.h>
-
 #include <mcld/Support/RegionFactory.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/FileSystem.h>
-
-#include <cerrno>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
 //===--------------------------------------------------------------------===//
 // MemoryArea
-MemoryArea::MemoryArea(RegionFactory& pRegionFactory)
-  : m_RegionFactory(pRegionFactory),
-    m_FileDescriptor(-1),
-    m_FileSize(0),
-    m_AccessFlags(ReadOnly),
-    m_State(BadBit) {
+
+// 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(RegionFactory& pRegionFactory, FileHandle& pFileHandle)
+  : m_RegionFactory(pRegionFactory), m_pFileHandle(&pFileHandle) {
 }
 
 MemoryArea::~MemoryArea()
 {
-  // truncate the file to real size
-  if (isWritable())
-    truncate(m_FileSize);
-
-  unmap();
-}
-
-void MemoryArea::truncate(size_t pLength)
-{
-  if (!isWritable())
-    return;
-
-  if (-1 == ::ftruncate(m_FileDescriptor, static_cast<off_t>(pLength))) {
-    llvm::report_fatal_error(llvm::Twine("Cannot truncate `") +
-                             m_FilePath.native() +
-                             llvm::Twine("' to size: ") +
-                             llvm::Twine(pLength) +
-                             llvm::Twine(".\n"));
-  }
-}
-
-void MemoryArea::map(const sys::fs::Path& pPath, int pFlags)
-{
-  m_AccessFlags = pFlags;
-  m_FilePath = pPath;
-  m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags);
-
-  if (-1 == m_FileDescriptor) {
-    m_State |= FailBit;
-  }
-  else {
-    struct stat st;
-    int stat_result = ::stat(m_FilePath.native().c_str(), &st);
-    if (0x0 == stat_result) {
-      m_FileSize = static_cast<size_t>(st.st_size);
-      m_State = GoodBit;
-    }
-    else {
-      m_FileSize = 0x0;
-      m_State |= FailBit;
-      m_State |= BadBit;
-    }
-  }
-}
-
-void MemoryArea::map(const sys::fs::Path& pPath, int pFlags, int pMode)
-{
-  m_AccessFlags = pFlags;
-  m_FilePath = pPath;
-  m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags, pMode);
-
-  if (-1 == m_FileDescriptor) {
-    m_State |= FailBit;
-  }
-  else {
-    struct stat st;
-    int stat_result = ::stat(m_FilePath.native().c_str(), &st);
-    if (0x0 == stat_result) {
-      m_FileSize = static_cast<size_t>(st.st_size);
-      m_State = GoodBit;
-    }
-    else {
-      m_FileSize = 0x0;
-      m_State |= FailBit;
-      m_State |= BadBit;
-    }
-  }
-}
-
-void MemoryArea::unmap()
-{
-  if (isMapped()) {
-    if (-1 == ::close(m_FileDescriptor))
-      m_State |= FailBit;
-    else {
-      m_FileDescriptor = -1;
-      m_AccessFlags = ReadOnly;
-    }
-  }
-}
-
-bool MemoryArea::isMapped() const
-{
-  return (-1 != m_FileDescriptor);
-}
-
-bool MemoryArea::isGood() const
-{
-  return 0x0 == (m_State & (BadBit | FailBit));
-}
-
-bool MemoryArea::isBad() const
-{
-  return 0x0 != (m_State & BadBit);
-}
-
-bool MemoryArea::isFailed() const
-{
-  return 0x0 != (m_State & FailBit);
-}
-
-bool MemoryArea::isEOF() const
-{
-  return 0x0 != (m_State & EOFBit);
-}
-
-bool MemoryArea::isReadable() const
-{
-  return (((m_AccessFlags & AccessMask) == ReadOnly) ||
-         ((m_AccessFlags & AccessMask) == ReadWrite));
-}
-
-bool MemoryArea::isWritable() const
-{
-  return (((m_AccessFlags & AccessMask) == WriteOnly) ||
-         ((m_AccessFlags & AccessMask) == ReadWrite));
-}
-
-int MemoryArea::rdstate() const
-{
-  return m_State;
-}
-
-void MemoryArea::setState(MemoryArea::IOState pState)
-{
-  m_State |= pState;
-}
-
-void MemoryArea::clear(MemoryArea::IOState pState)
-{
-  m_State = pState;
 }
 
 // The layout of MemorySpace in the virtual memory space
@@ -185,242 +52,100 @@
 //
 MemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength)
 {
-  if (!isMapped() || !isGood())
-    return NULL;
-
-  if (0x0 == pLength)
-    return NULL;
-
-  if (!isWritable() && (pOffset + pLength) > m_FileSize)
-    return NULL;
-
-  if (isWritable() && (pOffset + pLength) > m_FileSize) {
-    // If the memory area is writable, user can expand the size of file by
-    // request a region larger than the file.
-    // MemoryArea should enlarge the file if the requested region is larger
-    // than the file.
-    m_FileSize = page_boundary(pOffset + pLength + 1);
-    truncate(m_FileSize);
-  }
-
   Space* space = find(pOffset, pLength);
-  MemoryArea::Address r_start = 0;
   if (NULL == space) {
-    // the space does not exist, create a new space.
-    space = new Space(this, pOffset, pLength);
+
+    // not found
+    if (NULL == m_pFileHandle) {
+      // if m_pFileHandle is NULL, clients delegate us an universal Space and
+      // we never remove it. In that way, space can not be NULL.
+      unreachable(diag::err_out_of_range_region);
+    }
+
+    space = Space::createSpace(*m_pFileHandle, pOffset, pLength);
     m_SpaceList.push_back(space);
-    switch(space->type = policy(pOffset, pLength)) {
-      case Space::MMAPED: {
-        int mm_prot, mm_flag;
-        if (isWritable()) {
-          mm_prot = PROT_READ | PROT_WRITE;
-          mm_flag = MAP_FILE | MAP_SHARED;
-        }
-        else {
-          mm_prot = PROT_READ;
-          mm_flag = MAP_FILE | MAP_PRIVATE;
-        }
-
-        space->file_offset = page_offset(pOffset);
-
-        // The space's size may be larger than filesize.
-        space->size = page_boundary(pLength + pOffset + 1 - space->file_offset);
-        space->data = (Address) ::mmap(NULL,
-                                       space->size,
-                                       mm_prot, mm_flag,
-                                       m_FileDescriptor,
-                                       space->file_offset);
-
-        if (space->data == MAP_FAILED) {
-          llvm::report_fatal_error(llvm::Twine("cannot open memory map file :") +
-                                   m_FilePath.native() +
-                                   llvm::Twine(" (") +
-                                   sys::fs::detail::strerror(errno) +
-                                   llvm::Twine(").\n"));
-        }
-
-        r_start = space->data + (pOffset - space->file_offset);
-        break;
-      }
-      case Space::ALLOCATED_ARRAY: {
-        // space->offset and space->size are set in constructor. We only need
-        // to set up data.
-        space->data = new unsigned char[pLength];
-        r_start = space->data;
-        if ((m_AccessFlags & AccessMask) != WriteOnly) {
-          // Read data from the backend file.
-          if (!read(*space)) {
-            llvm::report_fatal_error(llvm::Twine("Failed to read data from ") +
-                                     m_FilePath.native() +
-                                     llvm::Twine(" (") +
-                                     sys::fs::detail::strerror(errno) +
-                                     llvm::Twine(") at offset ") +
-                                     llvm::Twine(pOffset) +
-                                     llvm::Twine(" lenght ") +
-                                     llvm::Twine(pLength) + llvm::Twine(".\n"));
-          }
-        }
-        break;
-      } // case
-      default: {
-        llvm::report_fatal_error("unhandled space type\n");
-      }
-    } // switch
   }
-  else { // found
-    off_t distance = pOffset - space->file_offset;
-    r_start = space->data + distance;
-  }
+
+  // adjust r_start
+  off_t distance = pOffset - space->start();
+  void* r_start = space->memory() + distance;
 
   // now, we have a legal space to hold the new MemoryRegion
-  return m_RegionFactory.produce(space, r_start, pLength);
+  return m_RegionFactory.produce(*space, r_start, pLength);
 }
 
 // release - release a MemoryRegion
 void MemoryArea::release(MemoryRegion* pRegion)
 {
-  if (!isMapped() || !isGood())
+  if (NULL == pRegion)
     return;
 
   Space *space = pRegion->parent();
   m_RegionFactory.destruct(pRegion);
 
-  if (0 == space->region_num) {
-    write(*space);
-    m_SpaceList.remove(*space);
-    release(space);
+  if (0 == space->numOfRegions()) {
+
+    if (NULL != m_pFileHandle) {
+      // if m_pFileHandle is NULL, clients delegate us an universal Space and
+      // we never remove it. Otherwise, we have to synchronize and release
+      // Space.
+      if (m_pFileHandle->isWritable()) {
+        // synchronize writable space before we release it.
+        Space::syncSpace(space, *m_pFileHandle);
+      }
+      Space::releaseSpace(space, *m_pFileHandle);
+    }
+    m_SpaceList.erase(space);
   }
 }
 
-void MemoryArea::clean()
+// clear - release all MemoryRegions
+void MemoryArea::clear()
 {
-  m_RegionFactory.clear();
+  if (NULL == m_pFileHandle)
+    return;
 
-  SpaceList::iterator sIter, sEnd = m_SpaceList.end();
-  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
-    write(*sIter);
-    release(sIter);
+  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);
+    }
   }
+  else {
+    SpaceList::iterator space, sEnd = m_SpaceList.end();
+    for (space = m_SpaceList.begin(); space != sEnd; ++space)
+      Space::releaseSpace(space, *m_pFileHandle);
+  }
+
   m_SpaceList.clear();
 }
 
-void MemoryArea::sync()
+//===--------------------------------------------------------------------===//
+// 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) {
-    write(*sIter);
-  }
-}
-
-MemoryArea::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->file_offset <= pOffset &&
-       (pOffset+pLength) <= (sIter->file_offset+sIter->size) ) { // within
+    if (sIter->start() <= pOffset &&
+       (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
+      // within
       return sIter;
     }
   }
   return NULL;
 }
 
-void MemoryArea::release(MemoryArea::Space* pSpace)
+const Space* MemoryArea::find(size_t pOffset, size_t pLength) const
 {
-  switch (pSpace->type) {
-    case Space::ALLOCATED_ARRAY: {
-      delete [] pSpace->data;
-      break;
-    }
-    case Space::MMAPED: {
-      ::munmap(pSpace->data, pSpace->size);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-MemoryArea::Space::Type MemoryArea::policy(off_t pOffset, size_t pLength)
-{
-  const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux
-  if (pLength < threshold)
-    return Space::ALLOCATED_ARRAY;
-  else
-    return Space::MMAPED;
-}
-
-ssize_t MemoryArea::readToBuffer(sys::fs::detail::Address pBuf,
-                                 size_t pSize, size_t pOffset) {
-  assert(((m_AccessFlags & AccessMask) != WriteOnly) &&
-         "Write-only file cannot be read!");
-
-  ssize_t read_bytes = sys::fs::detail::pread(m_FileDescriptor, pBuf,
-                                              pSize, pOffset);
-  if (static_cast<size_t>(read_bytes) != pSize) {
-    // Some error occurred during pread().
-    if (read_bytes < 0) {
-      m_State |= FailBit;
-    }
-    else if (static_cast<size_t>(read_bytes) < pSize) {
-      m_State |= EOFBit;
-      if ((m_AccessFlags & AccessMask) != ReadWrite) {
-        // Files which is not read-write are not allowed read beyonds the EOF
-        // marker.
-        m_State |= BadBit;
-      }
-    }
-    else {
-      m_State |= BadBit;
+  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;
     }
   }
-  return read_bytes;
-}
-
-bool MemoryArea::read(Space& pSpace) {
-  if (!isGood() || !isReadable())
-    return false;
-
-  if (pSpace.type == Space::ALLOCATED_ARRAY) {
-    readToBuffer(pSpace.data, pSpace.size, pSpace.file_offset);
-    return isGood();
-  }
-  else {
-    // Data associated with mmap()'ed space is already at the position the
-    // pSpace points to.
-    assert((pSpace.type == Space::MMAPED) && "Unknown type of Space!");
-    return true;
-  }
-}
-
-
-void MemoryArea::write(const Space& pSpace)
-{
-  if (!isMapped() || !isGood() || !isWritable())
-    return;
-
-  switch(pSpace.type) {
-    case Space::MMAPED: {
-      if(-1 == ::msync(pSpace.data, pSpace.size, MS_SYNC))
-        m_State |= FailBit;
-      return;
-    }
-    case Space::ALLOCATED_ARRAY: {
-      ssize_t write_bytes = sys::fs::detail::pwrite(m_FileDescriptor,
-                                                    pSpace.data,
-                                                    pSpace.size,
-                                                    pSpace.file_offset);
-      if (0 > write_bytes) {
-        m_State |= FailBit;
-        return;
-      }
-      if (0 == write_bytes && 0 != pSpace.size)
-        m_State |= BadBit;
-      if ( pSpace.size > static_cast<size_t>(write_bytes) )
-        m_State |= EOFBit;
-      return;
-    }
-    default:
-      return;
-  }
+  return NULL;
 }
 
diff --git a/lib/Support/MemoryAreaFactory.cpp b/lib/Support/MemoryAreaFactory.cpp
index 1f7e523..3da07d5 100644
--- a/lib/Support/MemoryAreaFactory.cpp
+++ b/lib/Support/MemoryAreaFactory.cpp
@@ -6,15 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/MemoryAreaFactory.h"
-#include "mcld/Support/RegionFactory.h"
+#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>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // MemoryAreaFactory
 MemoryAreaFactory::MemoryAreaFactory(size_t pNum)
-  : UniqueGCFactoryBase<sys::fs::Path, MemoryArea, 0>(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.
@@ -23,30 +26,91 @@
 
 MemoryAreaFactory::~MemoryAreaFactory()
 {
+  HandleToArea::iterator rec, rEnd = m_HandleToArea.end();
+  for (rec = m_HandleToArea.begin(); rec != rEnd; ++rec) {
+    if (rec->handle->isOpened()) {
+      rec->handle->close();
+    }
+    delete rec->handle;
+  }
+
   delete m_pRegionFactory;
 }
 
-MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath, int pFlags)
+MemoryArea*
+MemoryAreaFactory::produce(const sys::fs::Path& pPath,
+                           FileHandle::OpenMode pMode)
 {
-  MemoryArea* result = find(pPath);
-  if (0 == result) {
-    result = allocate();
-    new (result) MemoryArea(*m_pRegionFactory);
-    result->map(pPath, pFlags);
-    f_KeyMap.insert(std::make_pair(pPath, result));
+  HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
+  if (NULL == map_result.area) {
+    // can not found
+    FileHandle* handler = new FileHandle();
+    if (!handler->open(pPath, pMode)) {
+      error(diag::err_cannot_open_file) << pPath
+                                        << sys::strerror(handler->error());
+    }
+
+    MemoryArea* result = allocate();
+    new (result) MemoryArea(*m_pRegionFactory, *handler);
+
+    m_HandleToArea.push_back(handler, result);
+    return result;
   }
+
+  return map_result.area;
+}
+
+MemoryArea*
+MemoryAreaFactory::produce(const sys::fs::Path& pPath,
+                           FileHandle::OpenMode pMode,
+                           FileHandle::Permission pPerm)
+{
+  HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
+  if (NULL == map_result.area) {
+    // can not found
+    FileHandle* handler = new FileHandle();
+    if (!handler->open(pPath, pMode, pPerm)) {
+      error(diag::err_cannot_open_file) << pPath
+                                        << sys::strerror(handler->error());
+    }
+
+    MemoryArea* result = allocate();
+    new (result) MemoryArea(*m_pRegionFactory, *handler);
+
+    m_HandleToArea.push_back(handler, result);
+    return result;
+  }
+
+  return map_result.area;
+}
+
+void MemoryAreaFactory::destruct(MemoryArea* pArea)
+{
+  m_HandleToArea.erase(pArea);
+  pArea->clear();
+  pArea->handler()->close();
+  destroy(pArea);
+  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::produce(const sys::fs::Path& pPath, int pFlags, mode_t pMode)
+MemoryArea*
+MemoryAreaFactory::create(int pFD, FileHandle::OpenMode pMode)
 {
-  MemoryArea* result = find(pPath);
-  if (0 == result) {
-    result = allocate();
-    new (result) MemoryArea(*m_pRegionFactory);
-    result->map(pPath, pFlags, pMode);
-    f_KeyMap.insert(std::make_pair(pPath, result));
-  }
+  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 3a35f4e..32e790b 100644
--- a/lib/Support/MemoryRegion.cpp
+++ b/lib/Support/MemoryRegion.cpp
@@ -12,23 +12,13 @@
 
 //==========================
 // MemoryRegion
-MemoryRegion::MemoryRegion(MemoryArea::Space *pParentSpace,
-                           const MemoryRegion::Address pVMAStart,
+MemoryRegion::MemoryRegion(Space& pParent,
+                           MemoryRegion::Address pVMAStart,
                            size_t pSize)
-  : m_pParentSpace(pParentSpace), m_VMAStart(pVMAStart), m_Length(pSize) {
-  m_pParentSpace->region_num++;
+  : m_Parent(pParent), m_VMAStart(pVMAStart), m_Length(pSize) {
 }
 
 MemoryRegion::~MemoryRegion()
 {
-  drift();
-}
-
-void MemoryRegion::drift()
-{
-  if (NULL == m_pParentSpace)
-    return;
-  m_pParentSpace->region_num--;
-  m_pParentSpace = NULL;
 }
 
diff --git a/lib/Support/MsgHandling.cpp b/lib/Support/MsgHandling.cpp
new file mode 100644
index 0000000..5b45289
--- /dev/null
+++ b/lib/Support/MsgHandling.cpp
@@ -0,0 +1,74 @@
+//===- MsgHandling.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticEngine.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/MsgHandler.h>
+#include <mcld/Support/MsgHandling.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/raw_ostream.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// DiagnosticInitializer
+class DiagnosticInitializer : public llvm::ManagedStaticBase
+{
+public:
+  DiagnosticEngine* initialize(const MCLDInfo& pLDInfo,
+                               DiagnosticLineInfo* pLineInfo,
+                               DiagnosticPrinter* pPrinter)
+  {
+    RegisterManagedStatic(NULL, llvm::object_deleter<DiagnosticEngine>::call);
+    if (llvm::llvm_is_multithreaded()) {
+      llvm::llvm_acquire_global_lock();
+      void* tmp = NULL;
+      if (NULL != pPrinter)
+        tmp = new DiagnosticEngine(pLDInfo, pLineInfo, pPrinter, false);
+      else
+        tmp = new DiagnosticEngine(pLDInfo, pLineInfo, NULL, false);
+
+      TsanHappensBefore(this);
+      llvm::sys::MemoryFence();
+      TsanIgnoreWritesBegin();
+      Ptr = tmp;
+      TsanIgnoreWritesEnd();
+      llvm::llvm_release_global_lock();
+    }
+    else {
+      if (NULL != pPrinter)
+        Ptr = new DiagnosticEngine(pLDInfo, pLineInfo, pPrinter, false);
+      else
+        Ptr = new DiagnosticEngine(pLDInfo, pLineInfo, NULL, false);
+    }
+    return static_cast<DiagnosticEngine*>(Ptr);
+  }
+};
+
+static DiagnosticInitializer g_DiagInitializer;
+static DiagnosticEngine* g_pDiagnosticEngine = NULL;
+
+void mcld::InitializeDiagnosticEngine(const mcld::MCLDInfo& pLDInfo,
+                                DiagnosticLineInfo* pLineInfo,
+                                DiagnosticPrinter* pPrinter)
+{
+  if (NULL == g_pDiagnosticEngine) {
+    g_pDiagnosticEngine = g_DiagInitializer.initialize(pLDInfo,
+                                                       pLineInfo,
+                                                       pPrinter);
+  }
+}
+
+DiagnosticEngine& mcld::getDiagnosticEngine()
+{
+  assert(NULL != g_pDiagnosticEngine &&
+         "mcld::InitializeDiagnostics() is not called");
+  return *g_pDiagnosticEngine;
+}
+
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index ffb449f..8cc384d 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -11,11 +11,8 @@
 #include <llvm/ADT/StringRef.h>
 
 #include <locale>
-#include <stdio.h>
 #include <string.h>
 
-#include <iostream>
-
 using namespace mcld;
 using namespace mcld::sys::fs;
 
@@ -119,7 +116,7 @@
 Path::StringType::size_type Path::m_append_separator_if_needed()
 {
   if (!m_PathName.empty() &&
-#ifdef LLVM_ON_WIN32
+#if defined(MCLD_ON_WIN32)
       *(m_PathName.end()-1) != colon &&
 #endif
       !is_separator(*(m_PathName.end()-1))) {
@@ -171,7 +168,7 @@
 bool mcld::sys::fs::is_separator(char value)
 {
   return (value == separator
-#ifdef LLVM_ON_WIN32
+#if defined(MCLD_ON_WIN32)
           || value == preferred_separator
 #endif
           );
diff --git a/lib/Support/RegionFactory.cpp b/lib/Support/RegionFactory.cpp
index e87d389..ddce433 100644
--- a/lib/Support/RegionFactory.cpp
+++ b/lib/Support/RegionFactory.cpp
@@ -6,8 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/RegionFactory.h"
-#include "mcld/Support/MemoryArea.h"
+#include <mcld/Support/RegionFactory.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/Space.h>
 
 using namespace mcld;
 
@@ -21,18 +22,19 @@
 {
 }
 
-MemoryRegion* RegionFactory::produce(MemoryArea::Space* pSpace,
-                                     const sys::fs::detail::Address pVMAStart,
-                                     size_t pSize)
+MemoryRegion* RegionFactory::produce(Space& pSpace, void* pVMAStart, size_t pSize)
 {
   MemoryRegion* result = Alloc::allocate();
-  new (result) MemoryRegion(pSpace, pVMAStart, pSize);
+  new (result) MemoryRegion(pSpace,
+                            static_cast<const MemoryRegion::Address>(pVMAStart),
+                            pSize);
+  pSpace.addRegion(*result);
   return result;
 }
 
 void RegionFactory::destruct(MemoryRegion* pRegion)
 {
-  pRegion->drift();
+  pRegion->parent()->removeRegion(*pRegion);
   destroy(pRegion);
   deallocate(pRegion);
 }
diff --git a/lib/Support/Space.cpp b/lib/Support/Space.cpp
new file mode 100644
index 0000000..4024da1
--- /dev/null
+++ b/lib/Support/Space.cpp
@@ -0,0 +1,179 @@
+//===- Space.cpp ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/Space.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MsgHandling.h>
+#include <cstdlib>
+#include <unistd.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// constant data
+static const off_t PageSize = getpagesize();
+
+//===----------------------------------------------------------------------===//
+// Non-member functions
+//
+// low address      A page             high address
+// |--------------------|------------------|
+// ^ page_offset        ^ pFileOffset      ^ page_boundary
+
+// Given a file offset, return the page offset.
+// return the first page boundary \b before pFileOffset
+inline static off_t page_offset(off_t pFileOffset)
+{ return pFileOffset & ~ (PageSize - 1); }
+
+// page_boundary - Given a file size, return the size to read integral pages.
+// return the first page boundary \b after pFileOffset
+inline static off_t page_boundary(off_t pFileOffset)
+{ return (pFileOffset + (PageSize - 1)) & ~ (PageSize - 1); }
+
+inline static Space::Type policy(off_t pOffset, size_t pLength)
+{
+  const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux
+  if (pLength < threshold)
+    return Space::ALLOCATED_ARRAY;
+  else
+    return Space::MMAPED;
+}
+
+//===----------------------------------------------------------------------===//
+// Space
+Space::Space()
+  : m_Data(NULL), m_StartOffset(0), m_Size(0),
+    m_RegionCount(0), m_Type(UNALLOCATED) {
+}
+
+Space::Space(Space::Type pType, void* pMemBuffer, size_t pSize)
+  : m_Data(static_cast<Address>(pMemBuffer)), m_StartOffset(0), m_Size(pSize),
+    m_RegionCount(0), m_Type(pType)
+{
+}
+
+Space::~Space()
+{
+  // do nothing. m_Data is deleted by @ref releaseSpace
+}
+
+Space* Space::createSpace(FileHandle& pHandler,
+                          size_t pStart, size_t pSize)
+{
+  Type type;
+  void* memory;
+  Space* result = NULL;
+  size_t start, size = 0, total_offset;
+  switch(type = policy(pStart, pSize)) {
+    case ALLOCATED_ARRAY: {
+      // adjust total_offset, start and size
+      total_offset = pStart + pSize;
+      start = pStart;
+      if (total_offset > pHandler.size()) {
+        if (pHandler.isWritable()) {
+          size = pSize;
+          pHandler.truncate(total_offset);
+        }
+        else if (pHandler.size() > start)
+          size = pHandler.size() - start;
+        else {
+          // create a space out of a read-only file.
+          fatal(diag::err_cannot_read_small_file) << pHandler.path()
+                                                  << pHandler.size()
+                                                  << start << size;
+        }
+      }
+      else
+        size = pSize;
+
+      // malloc
+      memory = (void*)malloc(size);
+      if (!pHandler.read(memory, start, size))
+        error(diag::err_cannot_read_file) << pHandler.path() << start << size;
+
+      break;
+    }
+    case MMAPED: {
+      // adjust total_offset, start and size
+      total_offset = page_boundary(pStart + pSize);
+      start = page_offset(pStart);
+      if (total_offset > pHandler.size()) {
+        if (pHandler.isWritable()) {
+          size = page_boundary((pStart - start) + pSize);
+          pHandler.truncate(total_offset);
+        }
+        else if (pHandler.size() > start)
+          size = pHandler.size() - start;
+        else {
+          // create a space out of a read-only file.
+          fatal(diag::err_cannot_read_small_file) << pHandler.path()
+                                                  << pHandler.size()
+                                                  << start << size;
+        }
+      }
+      else
+        size = page_boundary((pStart - start) + pSize);
+
+      // mmap
+      if (!pHandler.mmap(memory, start, size))
+        error(diag::err_cannot_mmap_file) << pHandler.path() << start << size;
+
+      break;
+    }
+    default:
+      break;
+  } // end of switch
+
+  result = new Space(type, memory, size);
+  result->setStart(start);
+  return result;
+}
+
+void Space::releaseSpace(Space* pSpace, FileHandle& pHandler)
+{
+  if (NULL == pSpace)
+    return;
+
+  switch(pSpace->type()) {
+    case ALLOCATED_ARRAY:
+      free(pSpace->memory());
+      break;
+    case MMAPED:
+      if (!pHandler.munmap(pSpace->memory(), pSpace->size()))
+        error(diag::err_cannot_munmap_file) << pHandler.path();
+      break;
+    default: // external and unallocated memory buffers
+      break;
+  } // end of switch
+}
+
+void Space::syncSpace(Space* pSpace, FileHandle& pHandler)
+{
+  if (NULL == pSpace || !pHandler.isWritable())
+    return;
+
+  switch(pSpace->type()) {
+    case Space::ALLOCATED_ARRAY: {
+      if (!pHandler.write(pSpace->memory(),
+                          pSpace->start(),
+                          pSpace->size())) {
+        error(diag::err_cannot_write_file) << pHandler.path()
+                                           << pSpace->start()
+                                           << pSpace->size();
+      }
+      return;
+    }
+    case Space::MMAPED:
+    default: {
+      // system will eventually write bakc the memory after
+      // calling ::munmap
+      return;
+    }
+  } // end of switch
+}
+
diff --git a/lib/Support/SystemUtils.cpp b/lib/Support/SystemUtils.cpp
new file mode 100644
index 0000000..5dfea36
--- /dev/null
+++ b/lib/Support/SystemUtils.cpp
@@ -0,0 +1,20 @@
+//===- SystemUtils.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/SystemUtils.h>
+
+using namespace mcld::sys;
+
+//===----------------------------------------------------------------------===//
+// Non-member functions
+#if defined(MCLD_ON_UNIX)
+#include "Unix/System.inc"
+#endif
+#if defined(MCLD_ON_WIN32)
+#include "Windows/System.inc"
+#endif 
diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index 246cbe8..8bfa235 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/lib/Support/TargetRegistry.cpp
@@ -6,13 +6,11 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/TargetRegistry.h"
+#include <mcld/Support/TargetRegistry.h>
 
 
 mcld::TargetRegistry::TargetListTy mcld::TargetRegistry::s_TargetList;
 
-/* ** */
-
 void mcld::TargetRegistry::RegisterTarget(mcld::Target &T)
 {
   s_TargetList.push_back(&T);
@@ -34,7 +32,7 @@
 const mcld::Target *mcld::TargetRegistry::lookupTarget(const std::string &pTriple,
                                                        std::string &pError) 
 {
-  const llvm::Target* target = llvm::TargetRegistry::lookupTarget( pTriple, pError );
+  const llvm::Target* target = llvm::TargetRegistry::lookupTarget(pTriple, pError);
   if (!target)
     return 0;
   return lookupTarget( *target );
diff --git a/lib/Support/Unix/FileSystem.inc b/lib/Support/Unix/FileSystem.inc
index 6499d66..ce6d0df 100644
--- a/lib/Support/Unix/FileSystem.inc
+++ b/lib/Support/Unix/FileSystem.inc
@@ -9,6 +9,7 @@
 #include <string>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include <fcntl.h>
 
 namespace mcld{
@@ -23,19 +24,29 @@
 std::string assembly_extension = ".s";
 std::string bitcode_extension = ".bc";
 
-size_t pread(int pFD, Address pBuf, size_t pCount, off_t pOffset)
+int open(const Path& pPath, int pOFlag)
 {
-  return ::pread(pFD, (void*) pBuf, pCount, pOffset);
+  return ::open(pPath.native().c_str(), pOFlag);
 }
 
-size_t pwrite(int pFD, const Address pBuf, size_t pCount, off_t pOffset)
+int open(const Path& pPath, int pOFlag, int pPerm)
 {
-  return ::pwrite(pFD, (const void*) pBuf, pCount, pOffset);
+  return ::open(pPath.native().c_str(), pOFlag, pPerm);
 }
 
-char *strerror(int errnum)
+ssize_t pread(int pFD, void* pBuf, size_t pCount, size_t pOffset)
 {
-  return ::strerror(errnum);
+  return ::pread(pFD, pBuf, pCount, pOffset);
+}
+
+ssize_t pwrite(int pFD, const void* pBuf, size_t pCount, size_t pOffset)
+{
+  return ::pwrite(pFD, pBuf, pCount, pOffset);
+}
+
+int ftruncate(int pFD, size_t pLength)
+{
+  return ::ftruncate(pFD, pLength);
 }
 
 } // namespace of detail
diff --git a/lib/Support/Unix/PathV3.inc b/lib/Support/Unix/PathV3.inc
index 2e8e6d0..68b0c36 100644
--- a/lib/Support/Unix/PathV3.inc
+++ b/lib/Support/Unix/PathV3.inc
@@ -282,7 +282,7 @@
 {
   if (pDir.m_Handler)
     closedir(reinterpret_cast<DIR *>(pDir.m_Handler));
-  pDir.m_Handler = NULL;
+  pDir.m_Handler = 0;
 }
 
 void get_pwd(std::string& pPWD)
diff --git a/lib/Support/Unix/System.inc b/lib/Support/Unix/System.inc
new file mode 100644
index 0000000..716aaa2
--- /dev/null
+++ b/lib/Support/Unix/System.inc
@@ -0,0 +1,24 @@
+//===- System.inc ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace mcld{
+namespace sys{
+
+char *strerror(int errnum)
+{
+  return ::strerror(errnum);
+}
+
+} // namespace of sys
+} // namespace of mcld
+
diff --git a/lib/Support/Windows/System.inc b/lib/Support/Windows/System.inc
new file mode 100644
index 0000000..bfd75ee
--- /dev/null
+++ b/lib/Support/Windows/System.inc
@@ -0,0 +1,19 @@
+//===- System.inc ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace mcld{
+namespace sys{
+
+} // namespace of sys
+} // namespace of mcld
+
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
new file mode 100644
index 0000000..2453c2c
--- /dev/null
+++ b/lib/Support/raw_ostream.cpp
@@ -0,0 +1,95 @@
+//===- raw_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_ostream.h>
+
+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) {
+}
+
+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) {
+}
+
+mcld::raw_fd_ostream::~raw_fd_ostream()
+{
+}
+
+void mcld::raw_fd_ostream::setLDInfo(const MCLDInfo& pLDInfo)
+{
+  m_pLDInfo = &pLDInfo;
+}
+
+llvm::raw_ostream &
+mcld::raw_fd_ostream::changeColor(enum llvm::raw_ostream::Colors pColor,
+                                  bool pBold,
+                                  bool pBackground)
+{
+  if (!is_displayed())
+    return *this;
+  return llvm::raw_fd_ostream::changeColor(pColor, pBold, pBackground);
+}
+
+llvm::raw_ostream& mcld::raw_fd_ostream::resetColor()
+{
+  if (!is_displayed())
+    return *this;
+  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();
+
+  return m_pLDInfo->options().color();
+}
+
+//===----------------------------------------------------------------------===//
+//  outs(), errs(), nulls()
+//===----------------------------------------------------------------------===//
+mcld::raw_fd_ostream& mcld::outs() {
+  // 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);
+  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);
+  return S;
+}
+
+void mcld::InitializeOStreams(const MCLDInfo& pLDInfo)
+{
+  outs().setLDInfo(pLDInfo);
+  errs().setLDInfo(pLDInfo);
+}
+
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h
index b833151..53e4795 100644
--- a/lib/Target/ARM/ARM.h
+++ b/lib/Target/ARM/ARM.h
@@ -9,15 +9,17 @@
 #ifndef MCLD_ARM_H
 #define MCLD_ARM_H
 #include <string>
-#include "mcld/Target/TargetMachine.h"
+#include <mcld/Target/TargetMachine.h>
 
 namespace mcld {
 class TargetLDBackend;
 
 extern mcld::Target TheARMTarget;
+extern mcld::Target TheThumbTarget;
 
 TargetLDBackend *createARMLDBackend(const llvm::Target&, const std::string&);
 
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMAndroidSectLinker.cpp b/lib/Target/ARM/ARMAndroidSectLinker.cpp
deleted file mode 100644
index a704cfa..0000000
--- a/lib/Target/ARM/ARMAndroidSectLinker.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- ARMAndroidSectLinker.cpp -------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ARMAndroidSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-ARMAndroidSectLinker::ARMAndroidSectLinker(SectLinkerOption &pOption,
-                                           TargetLDBackend &pLDBackend)
-  : AndroidSectLinker(pOption,
-                      pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attributes
-  info.attrFactory().constraint().disableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().unsetWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-
-}
-
-ARMAndroidSectLinker::~ARMAndroidSectLinker()
-{
-}
-
diff --git a/lib/Target/ARM/ARMAndroidSectLinker.h b/lib/Target/ARM/ARMAndroidSectLinker.h
deleted file mode 100644
index 8a47a94..0000000
--- a/lib/Target/ARM/ARMAndroidSectLinker.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- ARMAndroidSectLinker.h ---------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ARM_ANDROIDSECTLINKER_H
-#define ARM_ANDROIDSECTLINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/Target/AndroidSectLinker.h>
-
-namespace mcld
-{
-
-class MCLDInfo;
-
-/** \class ARMAndroidSectLinker
- *  \brief ARMAndroidSectLinker sets up the environment for linking.
- *
- *  \see
- *  \author Anders Cheng <Anders.Cheng@mediatek.com>
- */
-class ARMAndroidSectLinker : public AndroidSectLinker
-{
-public:
-  ARMAndroidSectLinker(SectLinkerOption &pOption,
-                       mcld::TargetLDBackend &pLDBackend);
-
-  ~ARMAndroidSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/ARM/ARMDiagnostic.cpp b/lib/Target/ARM/ARMDiagnostic.cpp
new file mode 100644
index 0000000..1ecf7df
--- /dev/null
+++ b/lib/Target/ARM/ARMDiagnostic.cpp
@@ -0,0 +1,39 @@
+//===- ARMDiagnostic.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/DWARFLineInfo.h>
+#include "ARM.h"
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ARMDiagnostic
+
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createARMDiagnostic - the help function to create corresponding ARMDiagnostic
+//
+DiagnosticLineInfo* createARMDiagLineInfo(const llvm::Target& pTarget,
+                                          const std::string &pTriple)
+{
+  return new DWARFLineInfo();
+}
+
+} // namespace of mcld
+
+//==========================
+// InitializeARMDiagnostic
+extern "C" void LLVMInitializeARMDiagnosticLineInfo() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheARMTarget, createARMDiagLineInfo);
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheThumbTarget, createARMDiagLineInfo);
+}
+
diff --git a/lib/Target/ARM/ARMELFArchiveReader.h b/lib/Target/ARM/ARMELFArchiveReader.h
index b60a12d..2fa9ce2 100644
--- a/lib/Target/ARM/ARMELFArchiveReader.h
+++ b/lib/Target/ARM/ARMELFArchiveReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef ARMELFARCHIVEREADER_H
-#define ARMELFARCHIVEREADER_H
+#ifndef MCLD_ARM_ELF_ARCHIVE_READER_H
+#define MCLD_ARM_ELF_ARCHIVE_READER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/lib/Target/ARM/ARMELFSectLinker.h b/lib/Target/ARM/ARMELFSectLinker.h
index 7493d59..ab626b9 100644
--- a/lib/Target/ARM/ARMELFSectLinker.h
+++ b/lib/Target/ARM/ARMELFSectLinker.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef ARM_ELFSECTLINKER_H
-#define ARM_ELFSECTLINKER_H
+#ifndef ARM_ELF_SECTION_LINKER_H
+#define ARM_ELF_SECTION_LINKER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h
index 1bf82f5..f42b940 100644
--- a/lib/Target/ARM/ARMFixupKinds.h
+++ b/lib/Target/ARM/ARMFixupKinds.h
@@ -41,9 +41,9 @@
   // instruction.
   fixup_t2_adr_pcrel_12,
   // fixup_arm_condbranch - 24-bit PC relative relocation for conditional branch
-  // instructions.
+  // instructions. 
   fixup_arm_condbranch,
-  // fixup_arm_uncondbranch - 24-bit PC relative relocation for
+  // fixup_arm_uncondbranch - 24-bit PC relative relocation for 
   // branch instructions. (unconditional)
   fixup_arm_uncondbranch,
   // fixup_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
index 37d8e6b..7430203 100644
--- a/lib/Target/ARM/ARMGOT.cpp
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -9,7 +9,7 @@
 #include "ARMGOT.h"
 #include <mcld/LD/LDFileFormat.h>
 #include <mcld/Support/MemoryRegion.h>
-#include <llvm/Support/ErrorHandling.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
@@ -33,7 +33,7 @@
                                         &m_SectionData);
 
     if (!Entry)
-      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+      fatal(diag::fail_allocate_memory) << "GOT0";
 
     m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
   }
@@ -43,9 +43,7 @@
   iterator ie = m_SectionData.end();
 
   for (int i = 1; i < ARMGOT0Num; ++i) {
-    if (it == ie)
-      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
-
+    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
     ++it;
   }
 
@@ -69,7 +67,7 @@
                                         &m_SectionData);
 
     if (!Entry)
-      llvm::report_fatal_error("Allocating new memory for GOTEntry failed");
+      fatal(diag::fail_allocate_memory) << "GOTEntry";
 
     m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
   }
@@ -82,7 +80,7 @@
     got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
 
     if (!got_entry)
-      llvm::report_fatal_error("Allocating new memory for GOT failed!");
+      fatal(diag::fail_allocate_memory) << "GOTEntry";
 
     m_Section.setSize(m_Section.size() + getEntrySize());
 
@@ -182,3 +180,4 @@
   }
   return result;
 }
+
diff --git a/lib/Target/ARM/ARMGOT.h b/lib/Target/ARM/ARMGOT.h
index 4667421..90f0f53 100644
--- a/lib/Target/ARM/ARMGOT.h
+++ b/lib/Target/ARM/ARMGOT.h
@@ -89,3 +89,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index fe57fd6..e0f5dcf 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -9,7 +9,6 @@
 #include <llvm/ADT/Triple.h>
 #include <llvm/ADT/Twine.h>
 #include <llvm/Support/ELF.h>
-#include <llvm/Support/ErrorHandling.h>
 
 #include <mcld/LD/SectionMap.h>
 #include <mcld/MC/MCLDInfo.h>
@@ -17,6 +16,7 @@
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/MCRegionFragment.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
 
 #include <cstring>
@@ -42,17 +42,17 @@
 
 ARMGNULDBackend::~ARMGNULDBackend()
 {
-  if (m_pRelocFactory)
+  if (NULL != m_pRelocFactory)
     delete m_pRelocFactory;
-  if(m_pGOT)
+  if (NULL != m_pGOT)
     delete m_pGOT;
-  if(m_pPLT)
+  if (NULL != m_pPLT)
     delete m_pPLT;
-  if(m_pRelDyn)
+  if (NULL != m_pRelDyn)
     delete m_pRelDyn;
-  if(m_pRelPLT)
+  if (NULL != m_pRelPLT)
     delete m_pRelPLT;
-  if(m_pDynamic)
+  if (NULL != m_pDynamic)
     delete m_pDynamic;
 }
 
@@ -85,12 +85,12 @@
  // FIXME: Currently we set exidx and extab to "Exception" and directly emit
  // them from input
   m_pEXIDX        = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx",
-                                                      LDFileFormat::Exception,
+                                                      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::Exception,
+                                                      LDFileFormat::Target,
                                                       llvm::ELF::SHT_PROGBITS,
                                                       llvm::ELF::SHF_ALLOC,
                                                       0x1);
@@ -101,7 +101,7 @@
                                                       0x1);
 }
 
-void ARMGNULDBackend::initTargetSymbols(MCLinker& pLinker)
+void ARMGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
@@ -122,7 +122,7 @@
                                   MCLinker& pLinker)
 {
   // when building shared object, the .got section is must.
-  if(pOutput.type() == Output::DynObj && (NULL == m_pGOT)) {
+  if (pOutput.type() == Output::DynObj && (NULL == m_pGOT)) {
       createARMGOT(pLinker, pOutput);
   }
 }
@@ -131,11 +131,7 @@
                                    const MCLDInfo& pInfo,
                                    MCLinker& pLinker)
 {
-  // emit program headers
-  if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
-    emitProgramHdrs(pLinker.getLDInfo().output());
-
-  ELFFileFormat *file_format = getOutputFormat(pOutput);
+  const ELFFileFormat *file_format = getOutputFormat(pOutput);
 
   // apply PLT
   if (file_format->hasPLT()) {
@@ -177,11 +173,6 @@
   return *m_pDynamic;
 }
 
-bool ARMGNULDBackend::isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const
-{
-  return (pOutput.type() == Output::DynObj);
-}
-
 void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput)
 {
   // get .got LDSection and create MCSectionData
@@ -191,7 +182,7 @@
   m_pGOT = new ARMGOT(got, pLinker.getOrCreateSectData(got));
 
   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
-  if( m_pGOTSymbol != NULL ) {
+  if (m_pGOTSymbol != NULL) {
     pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
@@ -249,62 +240,73 @@
                                      8);
 }
 
-ELFFileFormat* ARMGNULDBackend::getOutputFormat(const Output& pOutput) const
+void ARMGNULDBackend::addCopyReloc(ResolveInfo& pSym)
 {
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      return getDynObjFileFormat();
-    case Output::Exec:
-      return getExecFileFormat();
-    // FIXME: We do not support building .o now
-    case Output::Object:
-    default:
-      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
-                               llvm::Twine(pOutput.type()));
-      return NULL;
+  bool exist;
+  Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
+  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)
+{
+  // 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);
+  }
 
-bool ARMGNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym,
-                                       const MCLDInfo& pLDInfo,
-                                       const Output& pOutput) const
-{
-  return (Output::DynObj == pOutput.type() &&
-          ResolveInfo::Function == pSym.type() &&
-          (pSym.isDyn() || pSym.isUndef() ||
-            isSymbolPreemptible(pSym, pLDInfo, pOutput)));
-}
+  // get or create corresponding BSS MCSectionData
+  assert(NULL != bss_sect_hdr);
+  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(
+                                     *bss_sect_hdr);
 
-bool ARMGNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym,
-                                          const Output& pOutput,
-                                          bool isAbsReloc) const
-{
-  if(pSym.isUndef() && (Output::Exec == pOutput.type()))
-    return false;
-  if(pSym.isAbsolute())
-    return false;
-  if(Output::DynObj == pOutput.type() && isAbsReloc)
-    return true;
-  if(pSym.isDyn() || pSym.isUndef())
-    return true;
+  // Determine the alignment by the symbol value
+  // FIXME: here we use the largest alignment
+  uint32_t addralign = bitclass() / 8;
 
-  return false;
-}
+  // allocate space in BSS for the copy symbol
+  llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, pSym.size());
+  uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                     bss_section,
+                                                     addralign);
+  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
 
-bool ARMGNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
-                                          const MCLDInfo& pLDInfo,
-                                          const Output& pOutput) const
-{
-  if(pSym.other() != ResolveInfo::Default)
-    return false;
+  // change symbol binding to Global if it's a weak symbol
+  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
+  if (binding == ResolveInfo::Weak)
+    binding = ResolveInfo::Global;
 
-  if(Output::DynObj != pOutput.type())
-    return false;
+  // Define the copy symbol in the bss section and resolve it
+  LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+                      pSym.name(),
+                      false,
+                      (ResolveInfo::Type)pSym.type(),
+                      ResolveInfo::Define,
+                      binding,
+                      pSym.size(),  // size
+                      0x0,          // value
+                      pLinker.getLayout().getFragmentRef(*frag, 0x0),
+                      (ResolveInfo::Visibility)pSym.other());
 
-  if(pLDInfo.options().Bsymbolic())
-    return false;
-
-  return true;
+  return *cpy_sym;
 }
 
 /// checkValidReloc - When we attempt to generate a dynamic relocation for
@@ -314,7 +316,7 @@
                                       const Output& pOutput) const
 {
   // If not building a PIC object, no relocation type is invalid
-  if (!isPIC(pLDInfo, pOutput))
+  if (!isOutputPIC(pOutput, pLDInfo))
     return;
 
   switch(pReloc.type()) {
@@ -331,13 +333,8 @@
       break;
 
     default:
-      llvm::report_fatal_error(llvm::Twine("Attempt to generate unsupported") +
-                               llvm::Twine(" relocation type ") +
-                               llvm::Twine((int)pReloc.type()) +
-                               llvm::Twine(" for symbol '") +
-                               llvm::Twine(pReloc.symInfo()->name()) +
-                               llvm::Twine("', recompile with -fPIC")
-                              );
+      error(diag::non_pic_relocation) << (int)pReloc.type()
+                                      << pReloc.symInfo()->name();
       break;
   }
 }
@@ -347,7 +344,7 @@
                                    const Layout& pLayout) const
 {
   // Update value keep in addend if we meet a section symbol
-  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
     pReloc.setAddend(pLayout.getOutputOffset(
                      *pInputSym.fragRef()) + pReloc.addend());
   }
@@ -368,6 +365,8 @@
 
     // Set R_ARM_TARGET1 to R_ARM_ABS32
     // Ref: GNU gold 1.11 arm.cc, line 9892
+    // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
+    // or --target1-rel
     case llvm::ELF::R_ARM_TARGET1:
        pReloc.setType(llvm::ELF::R_ARM_ABS32);
     case llvm::ELF::R_ARM_ABS32:
@@ -375,13 +374,13 @@
       // 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(isPIC(pLDInfo, pOutput)) {
-        // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+      if (isOutputPIC(pOutput, pLDInfo)) {
+        //create .rel.dyn section if not exist
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set Rel bit
-        rsym->setReserved(rsym->reserved() | 0x1u);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
         }
       return;
     }
@@ -395,53 +394,41 @@
     case llvm::ELF::R_ARM_MOVT_ABS:
     case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
     case llvm::ELF::R_ARM_THM_MOVT_ABS: {
-      // Update value keep in relocation place if we meet a section symbol
-      if(rsym->type() == ResolveInfo::Section) {
-        pReloc.target() = pLinker.getLayout().getOutputOffset(
-                            *pInputSym.fragRef()) + pReloc.target();
-      }
-
-      // If building PIC object (shared library or PIC executable),
-      // a dynamic relocation for this location is needed.
-      // Reserve an entry in .rel.dyn
-      if(isPIC(pLDInfo, pOutput)) {
-        checkValidReloc(pReloc, pLDInfo, pOutput);
-        // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
-          createARMRelDyn(pLinker, pOutput);
-        m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | 0x1u);
+      // PIC code should not contain these kinds of relocation
+      if (isOutputPIC(pOutput, pLDInfo)) {
+        error(diag::non_pic_relocation) << (int)pReloc.type()
+                                        << pReloc.symInfo()->name();
       }
       return;
     }
     case llvm::ELF::R_ARM_GOTOFF32:
     case llvm::ELF::R_ARM_GOTOFF12: {
       // A GOT section is needed
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
       return;
     }
 
     // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
     // Ref: GNU gold 1.11 arm.cc, line 9892
+    // FIXME: R_ARM_TARGET2 should be set by option --target2
     case llvm::ELF::R_ARM_TARGET2:
       pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
     case llvm::ELF::R_ARM_GOT_BREL:
     case llvm::ELF::R_ARM_GOT_PREL: {
       // A GOT entry is needed for these relocation type.
       // return if we already create GOT for this symbol
-      if(rsym->reserved() & 0x6u)
+      if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
       m_pGOT->reserveEntry();
       // If building PIC object, a dynamic relocation with
       // type RELATIVE is needed to relocate this GOT entry.
       // Reserve an entry in .rel.dyn
-      if(isPIC(pLDInfo, pOutput)) {
+      if (isOutputPIC(pOutput, pLDInfo)) {
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
@@ -456,12 +443,9 @@
     case llvm::ELF::R_ARM_BASE_PREL: {
       // FIXME: Currently we only support R_ARM_BASE_PREL against
       // symbol _GLOBAL_OFFSET_TABLE_
-      if(rsym != m_pGOTSymbol->resolveInfo()) {
-        llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
-                                 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
-                                 llvm::Twine(rsym->name()) +
-                                 llvm::Twine(".'"));
-      }
+      if (rsym != m_pGOTSymbol->resolveInfo())
+        fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
+                                     << "mclinker@googlegroups.com";
       return;
     }
     case llvm::ELF::R_ARM_COPY:
@@ -470,9 +454,7 @@
     case llvm::ELF::R_ARM_RELATIVE: {
       // These are relocation type for dynamic linker, shold not
       // appear in object file.
-      llvm::report_fatal_error(llvm::Twine("unexpected reloc ") +
-                               llvm::Twine((int)pReloc.type()) +
-                               llvm::Twine(" in object file"));
+      fatal(diag::dynamic_relocation) << (int)pReloc.type();
       break;
     }
     default: {
@@ -494,6 +476,8 @@
 
     // Set R_ARM_TARGET1 to R_ARM_ABS32
     // Ref: GNU gold 1.11 arm.cc, line 9892
+    // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
+    // or --target1-rel
     case llvm::ELF::R_ARM_TARGET1:
       pReloc.setType(llvm::ELF::R_ARM_ABS32);
     case llvm::ELF::R_ARM_ABS32:
@@ -509,14 +493,14 @@
     case llvm::ELF::R_ARM_ABS32_NOI: {
       // Absolute relocation type, symbol may needs PLT entry or
       // dynamic relocation entry
-      if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
         // create plt for this symbol if it does not have one
-        if(!(rsym->reserved() & 0x8u)){
+        if (!(rsym->reserved() & ReservePLT)){
           // Create .got section if it doesn't exist
-          if(NULL == m_pGOT)
+          if (NULL == m_pGOT)
             createARMGOT(pLinker, pOutput);
           // create .plt and .rel.plt if not exist
-          if(NULL == m_pPLT)
+          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
@@ -525,19 +509,27 @@
           m_pPLT->reserveEntry();
           m_pRelPLT->reserveEntry(*m_pRelocFactory);
           // set PLT bit
-          rsym->setReserved(rsym->reserved() | 0x8u);
+          rsym->setReserved(rsym->reserved() | ReservePLT);
         }
       }
 
-      if(isSymbolNeedsDynRel(*rsym, pOutput, true)) {
-        checkValidReloc(pReloc, pLDInfo, pOutput);
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                            pLDInfo, pOutput, true)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | 0x1u);
+        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
+                          pOutput)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          checkValidReloc(pReloc, pLDInfo, pOutput);
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+        }
       }
       return;
     }
@@ -545,19 +537,20 @@
     case llvm::ELF::R_ARM_GOTOFF32:
     case llvm::ELF::R_ARM_GOTOFF12: {
       // A GOT section is needed
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
       return;
     }
 
     case llvm::ELF::R_ARM_BASE_PREL:
-      // FIXME: Currently we only support R_ARM_BASE_PREL against
+    case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
+    case llvm::ELF::R_ARM_THM_MOVW_BREL:
+    case llvm::ELF::R_ARM_THM_MOVT_BREL:
+      // FIXME: Currently we only support these relocations against
       // symbol _GLOBAL_OFFSET_TABLE_
-      if(rsym != m_pGOTSymbol->resolveInfo()) {
-        llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
-                                 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
-                                 llvm::Twine(rsym->name()) +
-                                 llvm::Twine(".'"));
+      if (rsym != m_pGOTSymbol->resolveInfo()) {
+        fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
+                                     << "mclinker@googlegroups.com";
       }
     case llvm::ELF::R_ARM_REL32:
     case llvm::ELF::R_ARM_LDR_PC_G0:
@@ -599,19 +592,25 @@
     case llvm::ELF::R_ARM_LDC_SB_G2:
     case llvm::ELF::R_ARM_MOVW_BREL_NC:
     case llvm::ELF::R_ARM_MOVT_BREL:
-    case llvm::ELF::R_ARM_MOVW_BREL:
-    case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
-    case llvm::ELF::R_ARM_THM_MOVT_BREL:
-    case llvm::ELF::R_ARM_THM_MOVW_BREL: {
+    case llvm::ELF::R_ARM_MOVW_BREL: {
       // Relative addressing relocation, may needs dynamic relocation
-      if(isSymbolNeedsDynRel(*rsym, pOutput, false)) {
-        checkValidReloc(pReloc, pLDInfo, pOutput);
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                            pLDInfo, pOutput, false)) {
+        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | 0x1u);
+        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
+                          pOutput)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          checkValidReloc(pReloc, pLDInfo, pOutput);
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+        }
       }
       return;
     }
@@ -631,22 +630,22 @@
       // A PLT entry is needed when building shared library
 
       // return if we already create plt for this symbol
-      if(rsym->reserved() & 0x8u)
+      if (rsym->reserved() & ReservePLT)
         return;
 
       // if symbol is defined in the ouput file and it's not
       // preemptible, no need plt
-      if(rsym->isDefine() && !rsym->isDyn() &&
+      if (rsym->isDefine() && !rsym->isDyn() &&
          !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
         return;
       }
 
       // Create .got section if it doesn't exist
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
 
       // create .plt and .rel.plt if not exist
-      if(NULL == m_pPLT)
+      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
@@ -655,12 +654,13 @@
       m_pPLT->reserveEntry();
       m_pRelPLT->reserveEntry(*m_pRelocFactory);
       // set PLT bit
-      rsym->setReserved(rsym->reserved() | 0x8u);
+      rsym->setReserved(rsym->reserved() | ReservePLT);
       return;
     }
 
     // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
     // Ref: GNU gold 1.11 arm.cc, line 9892
+    // FIXME: R_ARM_TARGET2 should be set by option --target2
     case llvm::ELF::R_ARM_TARGET2:
       pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
     case llvm::ELF::R_ARM_GOT_BREL:
@@ -668,25 +668,25 @@
     case llvm::ELF::R_ARM_GOT_PREL: {
       // Symbol needs GOT entry, reserve entry in .got
       // return if we already create GOT for this symbol
-      if(rsym->reserved() & 0x6u)
+      if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if(NULL == m_pGOT)
+      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()) {
+      if (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | 0x4u);
+        rsym->setReserved(rsym->reserved() | GOTRel);
         return;
       }
       // set GOT bit
-      rsym->setReserved(rsym->reserved() | 0x2u);
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
     }
 
@@ -696,9 +696,7 @@
     case llvm::ELF::R_ARM_RELATIVE: {
       // These are relocation type for dynamic linker, shold not
       // appear in object file.
-      llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") +
-                               llvm::Twine((int)pReloc.type()) +
-                               llvm::Twine(" in object file"));
+      fatal(diag::dynamic_relocation) << (int)pReloc.type();
       break;
     }
     default: {
@@ -711,12 +709,21 @@
                                      const LDSymbol& pInputSym,
                                      MCLinker& pLinker,
                                      const MCLDInfo& pLDInfo,
-                                     const Output& pOutput)
+                                     const Output& pOutput,
+                                     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;
+  }
+
   // 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
@@ -724,14 +731,14 @@
 
   // 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()) {
+  if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
+    if (rsym == m_pGOTSymbol->resolveInfo()) {
       createARMGOT(pLinker, pOutput);
     }
   }
 
   // rsym is local
-  if(rsym->isLocal())
+  if (rsym->isLocal())
     scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
 
   // rsym is external
@@ -743,25 +750,54 @@
 uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput,
                                           const LDSection& pSection,
                                           const MCLDInfo& pInfo,
+                                          const Layout& pLayout,
                                           MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
-  if (&pSection == m_pAttributes) {
-    // FIXME: Currently Emitting .ARM.attributes directly from the input file.
+  if (&pSection == m_pAttributes ||
+      &pSection == m_pEXIDX ||
+      &pSection == m_pEXTAB) {
+    // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
+    // directly from the input file.
     const llvm::MCSectionData* sect_data = pSection.getSectionData();
-    assert(sect_data &&
-           "Emit .ARM.attribute failed, MCSectionData doesn't exist!");
-
-    uint8_t* start =
-              llvm::cast<MCRegionFragment>(
-                     sect_data->getFragmentList().front()).getRegion().start();
-
-    memcpy(pRegion.start(), start, pRegion.size());
+    llvm::MCSectionData::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);
+      switch(frag_iter->getKind()) {
+        case llvm::MCFragment::FT_Region: {
+          const MCRegionFragment& region_frag =
+            llvm::cast<MCRegionFragment>(*frag_iter);
+          const uint8_t* start = region_frag.getRegion().start();
+          memcpy(out_offset, start, size);
+          break;
+        }
+        case llvm::MCFragment::FT_Align: {
+          llvm::MCAlignFragment& align_frag =
+            llvm::cast<llvm::MCAlignFragment>(*frag_iter);
+          uint64_t count = size / align_frag.getValueSize();
+          switch (align_frag.getValueSize()) {
+            case 1u:
+              std::memset(out_offset, align_frag.getValue(), count);
+              break;
+            default:
+              llvm::report_fatal_error(
+                "unsupported value size for align fragment emission yet.\n");
+              break;
+          } // end switch
+          break;
+        }
+        default:
+          llvm::report_fatal_error("unsupported fragment type.\n");
+          break;
+      } // end switch
+      out_offset += size;
+    } // end for
     return pRegion.size();
-  }
+  } // end if
 
   if (&pSection == &(file_format->getPLT())) {
     assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
@@ -774,116 +810,15 @@
     uint64_t result = m_pGOT->emit(pRegion);
     return result;
   }
-
-  llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
-                           pSection.name() +
-                           llvm::Twine("'.\n"));
+  fatal(diag::unrecognized_output_sectoin)
+          << pSection.name()
+          << "mclinker@googlegroups.com";
   return 0x0;
 }
 
 /// finalizeSymbol - finalize the symbol value
-/// If the symbol's reserved field is not zero, MCLinker will call back this
-/// function to ask the final value of the symbol
-bool ARMGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+bool ARMGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
-  return false;
-}
-
-/// allocateCommonSymbols - allocate common symbols in the corresponding
-/// sections.
-/// @refer Google gold linker: common.cc: 214
-bool
-ARMGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
-{
-  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
-
-  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
-    return true;
-
-  // addralign := max value of all common symbols
-  uint64_t addralign = 0x0;
-
-  // Due to the visibility, some common symbols may be forcefully local.
-  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      if ((*com_sym)->value() > addralign)
-        addralign = (*com_sym)->value();
-    }
-  }
-
-  // global common symbols.
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    if ((*com_sym)->value() > addralign)
-      addralign = (*com_sym)->value();
-  }
-
-  // FIXME: If the order of common symbols is defined, then sort common symbols
-  // com_sym = symbol_list.commonBegin();
-  // std::sort(com_sym, com_end, some kind of order);
-
-  // get or create corresponding BSS LDSection
-  LDSection* bss_sect_hdr = NULL;
-  if (ResolveInfo::ThreadLocal == (*com_sym)->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);
-  }
-
-  // get or create corresponding BSS MCSectionData
-  assert(NULL != bss_sect_hdr);
-  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
-
-  // allocate all common symbols
-  uint64_t offset = bss_sect_hdr->size();
-
-  // allocate all local common symbols
-  com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      // We have to reset the description of the symbol here. When doing
-      // incremental linking, the output relocatable object may have common
-      // symbols. Therefore, we can not treat common symbols as normal symbols
-      // when emitting the regular name pools. We must change the symbols'
-      // description here.
-      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-      uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                         bss_section,
-                                                         (*com_sym)->value());
-      offset += size;
-    }
-  }
-
-  // allocate all global common symbols
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    // We have to reset the description of the symbol here. When doing
-    // incremental linking, the output relocatable object may have common
-    // symbols. Therefore, we can not treat common symbols as normal symbols
-    // when emitting the regular name pools. We must change the symbols'
-    // description here.
-    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-    uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                       bss_section,
-                                                       (*com_sym)->value());
-    offset += size;
-  }
-
-  bss_sect_hdr->setSize(offset);
-  symbol_list.changeCommonsToGlobal();
   return true;
 }
 
@@ -910,9 +845,20 @@
 
   llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
 
-  new MCRegionFragment(*region, &sect_data);
+  llvm::MCFragment* 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 llvm::MCFillFragment(0x0, 0, 0);
+  }
+  else
+    frag = new MCRegionFragment(*region);
 
-  out_sect.setSize(out_sect.size() + pInputSectHdr.size());
+  uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                     sect_data,
+                                                     pInputSectHdr.align());
+
+  out_sect.setSize(out_sect.size() + size);
   return true;
 }
 
@@ -966,16 +912,25 @@
 
 unsigned int
 ARMGNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr) const
+                                       const LDSection& pSectHdr,
+                                       const MCLDInfo& pInfo) const
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
-  if (&pSectHdr == &file_format->getGOT())
+  if (&pSectHdr == &file_format->getGOT()) {
+    if (pInfo.options().hasNow())
+      return SHO_RELRO_LAST;
     return SHO_DATA;
+  }
 
   if (&pSectHdr == &file_format->getPLT())
     return SHO_PLT;
 
+  if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) {
+    // put ARM.exidx and ARM.extab in the same order of .eh_frame
+    return SHO_EXCEPTION;
+  }
+
   return SHO_UNDEFINED;
 }
 
@@ -1014,4 +969,6 @@
 extern "C" void LLVMInitializeARMLDBackend() {
   // 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 27acdf1..3e46cd7 100644
--- a/lib/Target/ARM/ARMLDBackend.h
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -86,7 +86,7 @@
   void initTargetSections(MCLinker& pLinker);
 
   /// initTargetSymbols - initialize target dependent symbols in output.
-  void initTargetSymbols(MCLinker& pLinker);
+  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// initRelocFactory - create and initialize RelocationFactory
   bool initRelocFactory(const MCLinker& pLinker);
@@ -104,7 +104,8 @@
                       const LDSymbol& pInputSym,
                       MCLinker& pLinker,
                       const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+                      const Output& pOutput,
+                      const LDSection& pSection);
 
   uint32_t machine() const
   { return llvm::ELF::EM_ARM; }
@@ -127,6 +128,9 @@
   unsigned int bitclass() const
   { return 32; }
 
+  uint64_t defaultTextSegmentAddr() const
+  { return 0x8000; }
+
   /// doPreLayout - Backend can do any needed modification before layout
   void doPreLayout(const Output& pOutput,
                    const MCLDInfo& pInfo,
@@ -160,11 +164,13 @@
   /// @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,
                            MemoryRegion& pRegion) const;
 
   ARMGOT& getGOT();
@@ -185,29 +191,17 @@
 
   /// getTargetSectionOrder - compute the layout order of ARM target sections
   unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr) const;
+                                     const LDSection& pSectHdr,
+                                     const MCLDInfo& pInfo) const;
 
-  /// finalizeSymbol - finalize the symbol value
-  /// If the symbol's reserved field is not zero, MCLinker will call back this
-  /// function to ask the final value of the symbol
-  bool finalizeSymbol(LDSymbol& pSymbol) const;
-
-  /// allocateCommonSymbols - allocate common symbols in the corresponding
-  /// sections.
-  bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
+  /// finalizeTargetSymbols - finalize the symbol value
+  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// readSection - read target dependent sections
   bool readSection(Input& pInput,
                    MCLinker& pLinker,
                    LDSection& pInputSectHdr);
 
-public:
-  bool isSymbolPreemptible(const ResolveInfo& pSym,
-                           const MCLDInfo& pLDInfo,
-                           const Output& pOutput) const;
-
-  bool isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const;
-
 private:
   void scanLocalReloc(Relocation& pReloc,
                       const LDSymbol& pInputSym,
@@ -221,19 +215,20 @@
                        const MCLDInfo& pLDInfo,
                        const Output& pOutput);
 
-  bool isSymbolNeedsPLT(const ResolveInfo& pSym,
-                        const MCLDInfo& pLDInfo,
-                        const Output& pOutput) const;
-
-  bool isSymbolNeedsDynRel(const ResolveInfo& pSym,
-                           const Output& pOutput,
-                           bool isAbsReloc) const;
-
-
   void checkValidReloc(Relocation& pReloc,
                        const MCLDInfo& pLDInfo,
                        const Output& pOutput) const;
 
+  /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
+  /// @param pSym - A resolved copy symbol that defined in BSS section
+  void addCopyReloc(ResolveInfo& pSym);
+
+  /// defineSymbolforCopyReloc - allocate a space in BSS section and
+  /// and force define the copy of pSym to BSS section
+  /// @return the output LDSymbol of the copy symbol
+  LDSymbol& defineSymbolforCopyReloc(MCLinker& 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
@@ -251,8 +246,6 @@
 
   void createARMRelDyn(MCLinker& pLinker, const Output& pOutput);
 
-  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
-
 private:
   RelocationFactory* m_pRelocFactory;
   ARMGOT* m_pGOT;
@@ -294,3 +287,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
index b3461d0..5528ef7 100644
--- a/lib/Target/ARM/ARMPLT.cpp
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -9,8 +9,8 @@
 #include "ARMGOT.h"
 #include "ARMPLT.h"
 #include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
@@ -65,7 +65,7 @@
     plt1_entry = new (std::nothrow) ARMPLT1(&m_SectionData);
 
     if (!plt1_entry)
-      llvm::report_fatal_error("Allocating new memory for ARMPLT1 failed!");
+      fatal(diag::fail_allocate_memory) << "ARMPLT1";
 
     m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
 
@@ -167,7 +167,7 @@
   data = static_cast<uint32_t*>(malloc(plt0->getEntrySize()));
 
   if (!data)
-    llvm::report_fatal_error("Allocating new memory for plt0 failed!");
+    fatal(diag::fail_allocate_memory) << "plt0";
 
   memcpy(data, arm_plt0, plt0->getEntrySize());
   data[4] = offset;
@@ -204,7 +204,7 @@
     Out = static_cast<uint32_t*>(malloc(plt1->getEntrySize()));
 
     if (!Out)
-      llvm::report_fatal_error("Allocating new memory for plt1 failed!");
+      fatal(diag::fail_allocate_memory) << "plt1";
 
     // Offset is the distance between the last PLT entry and the associated
     // GOT entry.
@@ -247,3 +247,4 @@
   }
   return result;
 }
+
diff --git a/lib/Target/ARM/ARMPLT.h b/lib/Target/ARM/ARMPLT.h
index 11d0bd0..f55aaa3 100644
--- a/lib/Target/ARM/ARMPLT.h
+++ b/lib/Target/ARM/ARMPLT.h
@@ -84,3 +84,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMRelocationFactory.cpp b/lib/Target/ARM/ARMRelocationFactory.cpp
index 2763b3b..4911658 100644
--- a/lib/Target/ARM/ARMRelocationFactory.cpp
+++ b/lib/Target/ARM/ARMRelocationFactory.cpp
@@ -8,11 +8,12 @@
 //===--------------------------------------------------------------------===//
 
 #include <llvm/ADT/Twine.h>
-#include <llvm/Support/ErrorHandling.h>
 #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/Support/MsgHandling.h>
 
 #include "ARMRelocationFactory.h"
 #include "ARMRelocationFunctions.h"
@@ -38,10 +39,8 @@
 {
   Relocation::Type type = pRelocation.type();
   if (type > 130) { // 131-255 doesn't noted in ARM spec
-    llvm::report_fatal_error(llvm::Twine("Unknown relocation type. "
-                                         "To symbol `") +
-                             pRelocation.symInfo()->name() +
-                             llvm::Twine("'."));
+    fatal(diag::unknown_relocation) << (int)type
+                                    << pRelocation.symInfo()->name();
     return;
   }
 
@@ -70,29 +69,18 @@
     return;
   }
   if (Overflow == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' causes overflow. on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_overflow) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
-
   if (BadReloc == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' encounters unexpected opcode. "
-                                         "on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_badreloc) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
   if (Unsupport == result) {
-    llvm::report_fatal_error(llvm::Twine("Encounter unsupported relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    fatal(diag::unsupported_relocation) << type
+                                        << "mclinker@googlegroups.com";
     return;
   }
 }
@@ -106,7 +94,7 @@
   // Set thumb bit if
   // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
   RelocationFactory::DWord thumbBit =
-       ((pReloc.symInfo()->desc() != ResolveInfo::Undefined) &&
+       ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
         (pReloc.symInfo()->type() == ResolveInfo::Function) &&
         ((pReloc.symValue() & 0x1) != 0))?
         1:0;
@@ -144,11 +132,11 @@
                           const ARMRelocationFactory& pFactory)
 {
   // if symbol is dynamic or undefine or preemptible
-  if(pSym.isDyn() ||
-     pSym.isUndef() ||
-     pFactory.getTarget().isSymbolPreemptible(pSym,
-                                              pLDInfo,
-                                              pLDInfo.output()))
+  if (pSym.isDyn() ||
+      pSym.isUndef() ||
+      pFactory.getTarget().isSymbolPreemptible(pSym,
+                                               pLDInfo,
+                                               pLDInfo.output()))
     return false;
   return true;
 }
@@ -176,7 +164,7 @@
       Relocation& rel_entry =
         *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
       assert(!exist && "GOT entry not exist, but DynRel entry exist!");
-      if( rsym->isLocal() ||
+      if ( rsym->isLocal() ||
           helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
         // Initialize got entry to target symbol address
         got_entry.setContent(pReloc.symValue());
@@ -192,7 +180,7 @@
       rel_entry.targetRef().assign(got_entry);
     }
     else {
-      llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+      fatal(diag::reserve_entry_number_mismatch) << "GOT";
     }
   }
   return got_entry;
@@ -239,7 +227,7 @@
       rel_entry.setSymInfo(rsym);
     }
     else {
-      llvm::report_fatal_error("No PLT entry reserved for PLT type relocation!");
+      fatal(diag::reserve_entry_number_mismatch) << "PLT";
     }
   }
   return plt_entry;
@@ -279,7 +267,7 @@
   rel_entry.setType(pType);
   rel_entry.targetRef() = pReloc.targetRef();
 
-  if(pType == llvm::ELF::R_ARM_RELATIVE)
+  if (pType == llvm::ELF::R_ARM_RELATIVE)
     rel_entry.setSymInfo(0);
   else
     rel_entry.setSymInfo(rsym);
@@ -307,13 +295,17 @@
 static ARMRelocationFactory::DWord
 helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
 {
-  // TODO: By the rsloader experience: If we use 32bit, we need to consider
-  // endianness problem. We'd better have a thumb instruction type.
+  // 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((((pTarget >> 4) & 0xf000U) |
-                             ((pTarget >> 15) & 0x0800U) |
-                             ((pTarget >> 4) & 0x0700U) |
-                             (pTarget & 0x00ffU)),
+  return helper_sign_extend((((val >> 4) & 0xf000U) |
+                             ((val >> 15) & 0x0800U) |
+                             ((val >> 4) & 0x0700U) |
+                             (val & 0x00ffU)),
                             16);
 }
 
@@ -321,15 +313,19 @@
 helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
                                        ARMRelocationFactory::DWord pImm)
 {
-  // TODO: By the rsloader experience: If we use 32bit, we need to consider
-  // endianness problem. We'd better have a thumb instruction type.
+  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);
-  return pTarget;
+
+  // 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;
 }
 
 static ARMRelocationFactory::DWord
@@ -408,13 +404,27 @@
   ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   ARMRelocationFactory::DWord S = pReloc.symValue();
 
-  if(rsym->isLocal() && (rsym->reserved() & 0x1u)) {
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    pReloc.target() = (S + A) | T;
+    return ARMRelocationFactory::OK;
+  }
+
+  // A local symbol may need REL Type dynamic relocation
+  if (rsym->isLocal() && (rsym->reserved() & ARMGNULDBackend::ReserveRel)) {
     helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
     pReloc.target() = (S + A) | T ;
     return ARMRelocationFactory::OK;
   }
-  else if(!rsym->isLocal()) {
-    if(rsym->reserved() & 0x8u) {
+
+  // An external symbol may need PLT and dynamic relocation
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
       T = 0 ; // PLT is not thumb
       pReloc.target() = (S + A) | T;
@@ -422,8 +432,8 @@
     // 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() & 0x1u) {
-      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+    if (rsym->reserved() & ARMGNULDBackend::ReserveRel) {
+      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
         helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
       }
       else {
@@ -433,6 +443,7 @@
     }
   }
 
+
   // perform static relocation
   pReloc.target() = (S + A) | T;
   return ARMRelocationFactory::OK;
@@ -481,7 +492,8 @@
                                       const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
-  if(!(pReloc.symInfo()->reserved() & 0x6u)) {
+  if (!(pReloc.symInfo()->reserved() &
+      (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
     return ARMRelocationFactory::BadReloc;
   }
   ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
@@ -497,7 +509,8 @@
                                       const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
-  if(!(pReloc.symInfo()->reserved() & 0x6u)) {
+  if (!(pReloc.symInfo()->reserved() &
+      (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
     return ARMRelocationFactory::BadReloc;
   }
   ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
@@ -515,18 +528,23 @@
                                   const MCLDInfo& pLDInfo,
                                   ARMRelocationFactory& pParent)
 {
-  // TODO: Some issue have not been considered, e.g. thumb, overflow?
+  // 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.
-  if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() &&
+  // next instruction unless it has PLT entry. Rewrite instruction
+  // to NOP.
+  if (pReloc.symInfo()->isWeak() &&
+      pReloc.symInfo()->isUndef() &&
+      !pReloc.symInfo()->isDyn() &&
       !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
     // change target to NOP : mov r0, r0
     pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000;
     return ARMRelocationFactory::OK;
   }
 
-  ARMRelocationFactory::Address S; // S dependent on exist PLT or not.
+  ARMRelocationFactory::Address S; // S depends on PLT exists or not.
   ARMRelocationFactory::DWord   T = getThumbBit(pReloc);
   ARMRelocationFactory::DWord   A =
     helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26)
@@ -534,16 +552,23 @@
   ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
 
   S = pReloc.symValue();
-  if( pReloc.symInfo()->reserved() & 0x8u) {
+  if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
     S = helper_PLT(pReloc, pParent);
     T = 0;  // PLT is not thumb.
   }
 
-  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
-
-  if (X & 0x03u) {  // Lowest two bit is not zero.
-    llvm::report_fatal_error("Target is thumb, need stub!");
+  // If the jump target is thumb instruction, switch mode is needed, rewrite
+  // the instruction to BLX
+  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.");
+    pReloc.target() = (pReloc.target() & 0xffffff) |
+                      0xfa000000 |
+                      (((S + A - P) & 2) << 23);
   }
+
+  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
   // Check X is 24bit sign int. If not, we should use stub or PLT before apply.
   assert(!helper_check_signed_overflow(X, 26) && "Jump or Call target too far!");
   //                    Make sure the Imm is 0.          Result Mask.
@@ -552,29 +577,25 @@
 }
 
 // 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
-  // next instruction unless it has PLT entry.
-  if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() &&
+  // next instruction unless it has PLT entry. Rewrite instruction
+  // to NOP.
+  if (pReloc.symInfo()->isWeak() &&
+      pReloc.symInfo()->isUndef() &&
+      !pReloc.symInfo()->isDyn() &&
       !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
     pReloc.target() = (0xe000U << 16) | 0xbf00U;
     return ARMRelocationFactory::OK;
   }
 
-  // TODO: By the rsloader experience: If we use 32bit, we need to consider
-  // endianness problem. Here is an ugly solution. We'd better have a thumb
-  // instruction type.
-  //uint16_t upper16 = *(
-  //    reinterpret_cast<uint16_t*>(&pReloc.target())
-  //  ),
-  //         lower16 = *(
-  //    reinterpret_cast<uint16_t*>(&pReloc.target()) + 1
-  //  );
-  ARMRelocationFactory::DWord upper16 = ((pReloc.target() & 0xffff0000U) >> 16),
-                              lower16 = (pReloc.target() & 0xffffU);
+  // 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);
 
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
   ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper16,
@@ -582,44 +603,52 @@
   ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
   ARMRelocationFactory::Address S;
 
-  S = pReloc.symValue();
   // if symbol has plt
-  if( pReloc.symInfo()->reserved() & 0x8u) {
+  if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
     S = helper_PLT(pReloc, pParent);
     T = 0;  // PLT is not thumb.
   }
-
-  // TODO: If the target is not thumb, we should rewrite instruction to BLX.
-
-  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
-  X >>= 1;
-
-  // FIXME: Check bit size is 24(thumb2) or 22?
-  if (helper_check_signed_overflow(X, 24)) {
-    assert(!"Offset is too far. We need stub or PLT for it.");
-    return ARMRelocationFactory::Overflow;
+  else {
+    S = pReloc.symValue();
   }
 
-  // For a BLX instruction, make sure that the relocation is rounded up
-  // to a word boundary. This follows the semantics of the instruction
-  // which specifies that bit 1 of the target address will come from bit
-  // 1 of the base address.
-  if ((X & 0x5000U) == 0x4000U) {
-    X = (X + 2) & ~0x3U;
+  S = S + A;
+
+  // 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) {
+    // 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;
+  }
+  else {
+    // otherwise, the instruction should be BL
+    lower16 |= 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)) {
+    assert(!"Offset is too far. We need stub or PLT for it.");
+    return ARMRelocationFactory::Overflow;
   }
 
   upper16 = helper_thumb32_branch_upper(upper16, X);
   lower16 = helper_thumb32_branch_lower(lower16, X);
 
-  // TODO: By the rsloader experience: If we use 32bit, we need to consider
-  // endianness problem. Here is an ugly solution. We'd better have a thumb
-  // instruction type.
-  //*(reinterpret_cast<uint16_t*>(&preloc.target())) = upper16;
-  //*(reinterpret_cast<uint16_t*>(&preloc.target()) + 1) = lower16;
-  pReloc.target() = (upper16 << 16);
-  pReloc.target() |= lower16;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper16;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower16;
 
-  return ARMRelocationFactory::OK;
+ return ARMRelocationFactory::OK;
 }
 
 // R_ARM_MOVW_ABS_NC: (S + A) | T
@@ -634,11 +663,19 @@
       helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  // use plt
-  if(rsym->reserved() & 0x8u) {
-    S = helper_PLT(pReloc, pParent);
-    T = 0 ; // PLT is not thumb
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // 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())) {
+    // use plt
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+      T = 0 ; // PLT is not thumb
+    }
   }
+
   X = (S + A) | T ;
   // perform static relocation
   pReloc.target() = (S + A) | T;
@@ -683,9 +720,16 @@
     helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  // use plt
-  if(rsym->reserved() & 0x8u) {
-    S = helper_PLT(pReloc, pParent);
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // 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())) {
+    // use plt
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+    }
   }
 
   X = S + A;
@@ -725,20 +769,22 @@
       helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  // use plt
-  if(rsym->reserved() & 0x8u) {
-    S = helper_PLT(pReloc, pParent);
-    T = 0; // PLT is not thumb
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // 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())) {
+    // use plt
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+      T = 0; // PLT is not thumb
+    }
   }
   X = (S + A) | T;
-  // check 16-bit overflow
-  if (helper_check_signed_overflow(X, 16)) {
-    return ARMRelocationFactory::Overflow;
-  } else {
-    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                             X);
-    return ARMRelocationFactory::OK;
-  }
+  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                           X);
+  return ARMRelocationFactory::OK;
 }
 
 // R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
@@ -756,13 +802,30 @@
   X = ((S + A) | T) - P;
 
   // check 16-bit overflow
-  if (helper_check_signed_overflow(X, 16)) {
-    return ARMRelocationFactory::Overflow;
-  } else {
-    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                             X);
-    return ARMRelocationFactory::OK;
-  }
+  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                           X);
+  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 A =
+      helper_extract_thumb_movw_movt_addend(pReloc.target()) + 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);
+  return ARMRelocationFactory::OK;
 }
 
 // R_ARM_THM_MOVT_ABS: S + A
@@ -776,10 +839,18 @@
       helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  // use plt
-  if(rsym->reserved() & 0x8u) {
-    S = helper_PLT(pReloc, pParent);
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // 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())) {
+    // use plt
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+    }
   }
+
   X = S + A;
   X >>= 16;
 
@@ -794,6 +865,7 @@
 }
 
 // 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)
@@ -806,15 +878,9 @@
 
   X = S + A - P;
   X >>= 16;
-
-  // check 16-bit overflow
-  if (helper_check_signed_overflow(X, 16)) {
-    return ARMRelocationFactory::Overflow;
-  } else {
-    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
                                                              X);
-    return ARMRelocationFactory::OK;
-  }
+  return ARMRelocationFactory::OK;
 }
 
 // R_ARM_PREL31: (S + A) | T
@@ -830,14 +896,14 @@
 
   S = pReloc.symValue();
   // if symbol has plt
-  if( pReloc.symInfo()->reserved() & 0x8u) {
+  if ( pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
     S = helper_PLT(pReloc, pParent);
     T = 0;  // PLT is not thumb.
   }
 
   ARMRelocationFactory::DWord X = (S + A) | T ;
   pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
-  if(helper_check_signed_overflow(X, 31))
+  if (helper_check_signed_overflow(X, 31))
     return ARMRelocationFactory::Overflow;
   return ARMRelocationFactory::OK;
 }
@@ -849,7 +915,6 @@
                                  const MCLDInfo& pLDInfo,
                                  ARMRelocationFactory& pParent)
 {
-  llvm::report_fatal_error("We don't support TLS relocation yet.");
   return ARMRelocationFactory::Unsupport;
 }
 
diff --git a/lib/Target/ARM/ARMRelocationFactory.h b/lib/Target/ARM/ARMRelocationFactory.h
index 0426100..636dbee 100644
--- a/lib/Target/ARM/ARMRelocationFactory.h
+++ b/lib/Target/ARM/ARMRelocationFactory.h
@@ -56,3 +56,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMRelocationFunctions.h b/lib/Target/ARM/ARMRelocationFunctions.h
index 10d27a4..bb6e727 100644
--- a/lib/Target/ARM/ARMRelocationFunctions.h
+++ b/lib/Target/ARM/ARMRelocationFunctions.h
@@ -27,6 +27,7 @@
 DECL_ARM_APPLY_RELOC_FUNC(movt_prel)        \
 DECL_ARM_APPLY_RELOC_FUNC(thm_movw_abs_nc)  \
 DECL_ARM_APPLY_RELOC_FUNC(thm_movw_prel_nc) \
+DECL_ARM_APPLY_RELOC_FUNC(thm_movw_brel)    \
 DECL_ARM_APPLY_RELOC_FUNC(thm_movt_abs)     \
 DECL_ARM_APPLY_RELOC_FUNC(thm_movt_prel)    \
 DECL_ARM_APPLY_RELOC_FUNC(prel31)           \
@@ -66,7 +67,7 @@
   { &call,              27, "R_ARM_PLT32"             },  \
   { &call,              28, "R_ARM_CALL"              },  \
   { &call,              29, "R_ARM_JUMP24"            },  \
-  { &unsupport,         30, "R_ARM_THM_JUMP24"        },  \
+  { &thm_call,          30, "R_ARM_THM_JUMP24"        },  \
   { &unsupport,         31, "R_ARM_BASE_ABS"          },  \
   { &unsupport,         32, "R_ARM_ALU_PCREL_7_0"     },  \
   { &unsupport,         33, "R_ARM_ALU_PCREL_15_8"    },  \
@@ -123,9 +124,9 @@
   { &unsupport,         84, "R_ARM_MOVW_BREL_NC"      },  \
   { &unsupport,         85, "R_ARM_MOVT_BREL"         },  \
   { &unsupport,         86, "R_ARM_MOVW_BREL"         },  \
-  { &unsupport,         87, "R_ARM_THM_MOVW_BREL_NC"  },  \
-  { &unsupport,         88, "R_ARM_THM_MOVT_BREL"     },  \
-  { &unsupport,         89, "R_ARM_THM_MOVW_BREL"     },  \
+  { &thm_movw_brel,     87, "R_ARM_THM_MOVW_BREL_NC"  },  \
+  { &thm_movt_prel,     88, "R_ARM_THM_MOVT_BREL"     },  \
+  { &thm_movw_brel,     89, "R_ARM_THM_MOVW_BREL"     },  \
   { &unsupport,         90, "R_ARM_TLS_GOTDESC"       },  \
   { &unsupport,         91, "R_ARM_TLS_CALL"          },  \
   { &unsupport,         92, "R_ARM_TLS_DESCSEQ"       },  \
diff --git a/lib/Target/ARM/ARMSectLinker.cpp b/lib/Target/ARM/ARMSectLinker.cpp
index 16d2126..06dba05 100644
--- a/lib/Target/ARM/ARMSectLinker.cpp
+++ b/lib/Target/ARM/ARMSectLinker.cpp
@@ -9,7 +9,6 @@
 #include <llvm/ADT/Triple.h>
 #include <mcld/Support/TargetRegistry.h>
 #include "ARM.h"
-#include "ARMAndroidSectLinker.h"
 #include "ARMELFSectLinker.h"
 
 
@@ -32,8 +31,7 @@
   }
 
   // For now, use Android SectLinker directly
-  return new ARMAndroidSectLinker(pOption,
-                                  pLDBackend);
+  return new ARMELFSectLinker(pOption, pLDBackend);
 }
 
 } // namespace of mcld
@@ -43,4 +41,6 @@
 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 3cb7793..54e1b3d 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -15,6 +15,7 @@
 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);
 }
 
 mcld::ARMBaseTargetMachine::ARMBaseTargetMachine(llvm::TargetMachine& pPM,
@@ -30,3 +31,4 @@
 {
   delete m_pLDInfo;
 }
+
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index 419826c..19f8aa2 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -37,3 +37,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/README b/lib/Target/ARM/README
index 2110344..ea88bfe 100644
--- a/lib/Target/ARM/README
+++ b/lib/Target/ARM/README
@@ -1,2 +1,2 @@
-ARMLDBackend stands like ARMAsmBackend. It's a backend of linker,
+ARMLDBackend stands like ARMAsmBackend. It's a backend of linker, 
 and all target-dependent behavior and data are here.
diff --git a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
index 7e6a41a..4f2f815 100644
--- a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
+++ b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
@@ -12,10 +12,12 @@
 namespace mcld {
 
 mcld::Target TheARMTarget;
+mcld::Target TheThumbTarget;
 
 extern "C" void LLVMInitializeARMLDTargetInfo() {
   // register into mcld::TargetRegistry
   mcld::RegisterTarget X(TheARMTarget, "arm" );
+  mcld::RegisterTarget Y(TheThumbTarget, "thumb" );
 }
 
 } // namespace of mcld
diff --git a/lib/Target/AndroidSectLinker.cpp b/lib/Target/AndroidSectLinker.cpp
deleted file mode 100644
index 8f3acbf..0000000
--- a/lib/Target/AndroidSectLinker.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- AndroidSectLinker.cpp ----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <mcld/Target/AndroidSectLinker.h>
-
-#include <llvm/Support/ErrorHandling.h>
-#include <mcld/MC/MCLDDirectory.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-//==========================
-// AndroidSectLinker
-
-AndroidSectLinker::AndroidSectLinker(SectLinkerOption &pOption,
-                                     TargetLDBackend &pLDBackend)
-  : SectLinker(pOption, pLDBackend) {
-}
-
-AndroidSectLinker::~AndroidSectLinker()
-{
-  // SectLinker will delete m_pLDBackend and m_pLDDriver;
-}
-
-void AndroidSectLinker::addTargetOptions(llvm::Module &pM,
-                                         SectLinkerOption &pOption)
-{
-  // -----  Set up General Options  ----- //
-  MCLDInfo &info = pOption.info();
-  MCLDDirectory search_path("=/system/lib");
-  search_path.setSysroot(info.options().sysroot());
-  if (exists(search_path.path()) && is_directory(search_path.path()))
-    info.options().directories().add(search_path);
-  else {
-    // FIXME: need a warning function
-    llvm::errs() << "WARNING: can not open search directory: `-L" << search_path.name() << "'.\n";
-  }
-}
-
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
index b863ab1..cb7c435 100644
--- a/lib/Target/ELFDynamic.cpp
+++ b/lib/Target/ELFDynamic.cpp
@@ -84,7 +84,6 @@
   ++m_Idx;
 }
 
-
 /// reserveEntries - reserve entries
 void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo,
                                 const ELFFileFormat& pFormat)
@@ -146,6 +145,28 @@
     reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
     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
+    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()))) {
+    reserveOne(llvm::ELF::DT_FLAGS_1); // DT_FLAGS_1
+  }
+
   reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
 }
 
@@ -217,6 +238,44 @@
     applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
   }
 
+  uint64_t dt_flags = 0x0;
+  if (pInfo.options().hasOrigin())
+    dt_flags |= llvm::ELF::DF_ORIGIN;
+  if (pInfo.options().Bsymbolic())
+    dt_flags |= llvm::ELF::DF_SYMBOLIC;
+  if (pInfo.options().hasNow())
+    dt_flags |= llvm::ELF::DF_BIND_NOW;
+  // TODO: add checks for DF_TEXTREL and 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())
+    dt_flags_1 |= llvm::ELF::DF_1_NOW;
+  if (pInfo.options().hasLoadFltr())
+    dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
+  if (pInfo.options().hasOrigin())
+    dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
+  if (pInfo.options().hasInterPose())
+    dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
+  if (pInfo.options().hasNoDefaultLib())
+    dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
+  if (pInfo.options().hasNoDump())
+    dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
+  if (pInfo.options().Bgroup())
+    dt_flags_1 |= llvm::ELF::DF_1_GROUP;
+  if (pInfo.output().type() == Output::DynObj) {
+    if (pInfo.options().hasNoDelete())
+      dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
+    if (pInfo.options().hasInitFirst())
+      dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
+    if (pInfo.options().hasNoDLOpen())
+      dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
+  }
+  if (0x0 != dt_flags_1)
+    applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1); // DT_FLAGS_1
+
   applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
 }
 
diff --git a/lib/Target/ELFSectLinker.cpp b/lib/Target/ELFSectLinker.cpp
new file mode 100644
index 0000000..b95ed0b
--- /dev/null
+++ b/lib/Target/ELFSectLinker.cpp
@@ -0,0 +1,25 @@
+//===- 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 b82af73..9fff9e3 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -11,12 +11,14 @@
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLDInputTree.h>
+#include <mcld/MC/InputTree.h>
 #include <mcld/MC/SymbolCategory.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/Layout.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/MC/MCLinker.h>
 #include <string>
 #include <cstring>
 #include <cassert>
@@ -26,36 +28,57 @@
 //===----------------------------------------------------------------------===//
 // GNULDBackend
 GNULDBackend::GNULDBackend()
-  : m_pArchiveReader(0),
-    m_pObjectReader(0),
-    m_pDynObjReader(0),
-    m_pObjectWriter(0),
-    m_pDynObjWriter(0),
-    m_pDynObjFileFormat(0),
-    m_pExecFileFormat(0),
-    m_ELFSegmentTable(9)// magic number
-{
+  : m_pArchiveReader(NULL),
+    m_pObjectReader(NULL),
+    m_pDynObjReader(NULL),
+    m_pObjectWriter(NULL),
+    m_pDynObjWriter(NULL),
+    m_pExecWriter(NULL),
+    m_pDynObjFileFormat(NULL),
+    m_pExecFileFormat(NULL),
+    m_ELFSegmentTable(9), // magic number
+    m_pEhFrameHdr(NULL),
+    f_pPreInitArrayStart(NULL),
+    f_pPreInitArrayEnd(NULL),
+    f_pInitArrayStart(NULL),
+    f_pInitArrayEnd(NULL),
+    f_pFiniArrayStart(NULL),
+    f_pFiniArrayEnd(NULL),
+    f_pStack(NULL),
+    f_pExecutableStart(NULL),
+    f_pEText(NULL),
+    f_p_EText(NULL),
+    f_p__EText(NULL),
+    f_pEData(NULL),
+    f_p_EData(NULL),
+    f_pBSSStart(NULL),
+    f_pEnd(NULL),
+    f_p_End(NULL) {
   m_pSymIndexMap = new HashTableType(1024);
 }
 
 GNULDBackend::~GNULDBackend()
 {
-  if (m_pArchiveReader)
+  if (NULL != m_pArchiveReader)
     delete m_pArchiveReader;
-  if (m_pObjectReader)
+  if (NULL != m_pObjectReader)
     delete m_pObjectReader;
-  if (m_pDynObjReader)
+  if (NULL != m_pDynObjReader)
     delete m_pDynObjReader;
-  if (m_pObjectWriter)
+  if (NULL != m_pObjectWriter)
     delete m_pObjectWriter;
-  if (m_pDynObjWriter)
+  if (NULL != m_pDynObjWriter)
     delete m_pDynObjWriter;
-  if (m_pDynObjFileFormat)
+  if (NULL != m_pExecWriter)
+    delete m_pExecWriter;
+  if (NULL != m_pDynObjFileFormat)
     delete m_pDynObjFileFormat;
-  if (m_pExecFileFormat)
+  if (NULL != m_pExecFileFormat)
     delete m_pExecFileFormat;
-  if(m_pSymIndexMap)
+  if (NULL != m_pSymIndexMap)
     delete m_pSymIndexMap;
+  if (NULL != m_pEhFrameHdr)
+    delete m_pEhFrameHdr;
 }
 
 size_t GNULDBackend::sectionStartOffset() const
@@ -64,13 +87,20 @@
   return sizeof(llvm::ELF::Elf64_Ehdr)+10*sizeof(llvm::ELF::Elf64_Phdr);
 }
 
+uint64_t GNULDBackend::segmentStartAddr(const Output& pOutput,
+                                        const MCLDInfo& pInfo) const
+{
+  // TODO: handle the user option: -TText=
+  if (isOutputPIC(pOutput, pInfo))
+    return 0x0;
+  else
+    return defaultTextSegmentAddr();
+}
+
 bool GNULDBackend::initArchiveReader(MCLinker&, MCLDInfo &pInfo)
 {
   if (0 == m_pArchiveReader)
-  {
-    LDReader::Endian isLittleEndian = LDReader::LittleEndian;
-    m_pArchiveReader = new GNUArchiveReader(pInfo, isLittleEndian);
-  }
+    m_pArchiveReader = new GNUArchiveReader(pInfo);
   return true;
 }
 
@@ -96,11 +126,18 @@
 
 bool GNULDBackend::initDynObjWriter(MCLinker& pLinker)
 {
-  if (0 == m_pDynObjWriter)
+  if (NULL == m_pDynObjWriter)
     m_pDynObjWriter = new ELFDynObjWriter(*this, pLinker);
   return true;
 }
 
+bool GNULDBackend::initExecWriter(MCLinker& pLinker)
+{
+  if (NULL == m_pExecWriter)
+    m_pExecWriter = new ELFExecWriter(*this, pLinker);
+  return true;
+}
+
 bool GNULDBackend::initExecSections(MCLinker& pMCLinker)
 {
   if (0 == m_pExecFileFormat)
@@ -121,8 +158,395 @@
   return true;
 }
 
-bool GNULDBackend::initStandardSymbols(MCLinker& pLinker)
+bool GNULDBackend::initStandardSymbols(MCLinker& pLinker, const Output& pOutput)
 {
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  // -----  section symbols  ----- //
+  // .preinit_array
+  MCFragmentRef* preinit_array = NULL;
+  if (file_format->hasPreInitArray()) {
+    preinit_array = pLinker.getLayout().getFragmentRef(
+                   *(file_format->getPreInitArray().getSectionData()->begin()),
+                   0x0);
+  }
+  f_pPreInitArrayStart =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__preinit_array_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             preinit_array, // FragRef
+                                             ResolveInfo::Hidden);
+  f_pPreInitArrayEnd =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__preinit_array_end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Hidden);
+
+  // .init_array
+  MCFragmentRef* init_array = NULL;
+  if (file_format->hasInitArray()) {
+    init_array = pLinker.getLayout().getFragmentRef(
+                      *(file_format->getInitArray().getSectionData()->begin()),
+                      0x0);
+  }
+
+  f_pInitArrayStart =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__init_array_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             init_array, // FragRef
+                                             ResolveInfo::Hidden);
+  f_pInitArrayEnd =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__init_array_end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             init_array, // FragRef
+                                             ResolveInfo::Hidden);
+
+  // .fini_array
+  MCFragmentRef* fini_array = NULL;
+  if (file_format->hasFiniArray()) {
+    fini_array = pLinker.getLayout().getFragmentRef(
+                     *(file_format->getFiniArray().getSectionData()->begin()),
+                     0x0);
+  }
+
+  f_pFiniArrayStart =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__fini_array_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             fini_array, // FragRef
+                                             ResolveInfo::Hidden);
+  f_pFiniArrayEnd =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__fini_array_end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             fini_array, // FragRef
+                                             ResolveInfo::Hidden);
+
+  // .stack
+  MCFragmentRef* stack = NULL;
+  if (file_format->hasStack()) {
+    stack = pLinker.getLayout().getFragmentRef(
+                          *(file_format->getStack().getSectionData()->begin()),
+                          0x0);
+  }
+  f_pStack =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__stack",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             stack, // FragRef
+                                             ResolveInfo::Hidden);
+
+  // -----  segment symbols  ----- //
+  f_pExecutableStart =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__executable_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+  f_pEText =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("etext",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+  f_p_EText =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("_etext",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+  f_p__EText =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__etext",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+  f_pEData =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("edata",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+
+  f_pEnd =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             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",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             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",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             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",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+
+  return true;
+}
+
+bool
+GNULDBackend::finalizeStandardSymbols(MCLinker& pLinker, const Output& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  // -----  section symbols  ----- //
+  if (NULL != f_pPreInitArrayStart) {
+    if (!f_pPreInitArrayStart->hasFragRef()) {
+      f_pPreInitArrayStart->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pPreInitArrayStart->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pPreInitArrayEnd) {
+    if (f_pPreInitArrayEnd->hasFragRef()) {
+      f_pPreInitArrayEnd->setValue(f_pPreInitArrayEnd->value() +
+                                   file_format->getPreInitArray().size());
+    }
+    else {
+      f_pPreInitArrayEnd->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pPreInitArrayEnd->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pInitArrayStart) {
+    if (!f_pInitArrayStart->hasFragRef()) {
+      f_pInitArrayStart->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pInitArrayStart->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pInitArrayEnd) {
+    if (f_pInitArrayEnd->hasFragRef()) {
+      f_pInitArrayEnd->setValue(f_pInitArrayEnd->value() +
+                                file_format->getInitArray().size());
+    }
+    else {
+      f_pInitArrayEnd->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pInitArrayEnd->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pFiniArrayStart) {
+    if (!f_pFiniArrayStart->hasFragRef()) {
+      f_pFiniArrayStart->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pFiniArrayStart->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pFiniArrayEnd) {
+    if (f_pFiniArrayEnd->hasFragRef()) {
+      f_pFiniArrayEnd->setValue(f_pFiniArrayEnd->value() +
+                                file_format->getFiniArray().size());
+    }
+    else {
+      f_pFiniArrayEnd->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pFiniArrayEnd->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pStack) {
+    if (!f_pStack->hasFragRef()) {
+      f_pStack->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pStack->setValue(0x0);
+    }
+  }
+
+  // -----  segment symbols  ----- //
+  if (NULL != f_pExecutableStart) {
+    ELFSegment* exec_start = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD, 0x0, 0x0);
+    if (NULL != exec_start) {
+      if (ResolveInfo::ThreadLocal != f_pExecutableStart->type()) {
+        f_pExecutableStart->setValue(f_pExecutableStart->value() +
+                                     exec_start->vaddr());
+      }
+    }
+    else
+      f_pExecutableStart->setValue(0x0);
+  }
+
+  if (NULL != f_pEText || NULL != f_p_EText || NULL !=f_p__EText) {
+    ELFSegment* etext = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD,
+                                               llvm::ELF::PF_X,
+                                               llvm::ELF::PF_W);
+    if (NULL != etext) {
+      if (NULL != f_pEText && ResolveInfo::ThreadLocal != f_pEText->type()) {
+        f_pEText->setValue(f_pEText->value() +
+                           etext->vaddr() +
+                           etext->memsz());
+      }
+      if (NULL != f_p_EText && ResolveInfo::ThreadLocal != f_p_EText->type()) {
+        f_p_EText->setValue(f_p_EText->value() +
+                            etext->vaddr() +
+                            etext->memsz());
+      }
+      if (NULL != f_p__EText && ResolveInfo::ThreadLocal != f_p__EText->type()) {
+        f_p__EText->setValue(f_p__EText->value() +
+                            etext->vaddr() +
+                            etext->memsz());
+      }
+    }
+    else {
+      if (NULL != f_pEText)
+        f_pEText->setValue(0x0);
+      if (NULL != f_p_EText)
+        f_p_EText->setValue(0x0);
+      if (NULL != f_p__EText)
+        f_p__EText->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pEData || NULL != f_p_EData || NULL != f_pBSSStart ||
+      NULL != f_pEnd || NULL != f_p_End) {
+    ELFSegment* edata = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD,
+                                               llvm::ELF::PF_W,
+                                               0x0);
+    if (NULL != edata) {
+      if (NULL != f_pEData && ResolveInfo::ThreadLocal != f_pEData->type()) {
+        f_pEData->setValue(f_pEData->value() +
+                            edata->vaddr() +
+                            edata->filesz());
+      }
+      if (NULL != f_p_EData && ResolveInfo::ThreadLocal != f_p_EData->type()) {
+        f_p_EData->setValue(f_p_EData->value() +
+                            edata->vaddr() +
+                            edata->filesz());
+      }
+      if (NULL != f_pBSSStart && ResolveInfo::ThreadLocal != f_pBSSStart->type()) {
+        f_pBSSStart->setValue(f_pBSSStart->value() +
+                              edata->vaddr() +
+                              edata->filesz());
+      }
+
+      if (NULL != f_pEnd && ResolveInfo::ThreadLocal != f_pEnd->type()) {
+        f_pEnd->setValue(f_pEnd->value() +
+                         edata->vaddr() +
+                         edata->memsz());
+      }
+      if (NULL != f_p_End && ResolveInfo::ThreadLocal != f_p_End->type()) {
+        f_p_End->setValue(f_p_End->value() +
+                          edata->vaddr() +
+                          edata->memsz());
+      }
+    }
+    else {
+      if (NULL != f_pEData)
+        f_pEData->setValue(0x0);
+      if (NULL != f_p_EData)
+        f_p_EData->setValue(0x0);
+      if (NULL != f_pBSSStart)
+        f_pBSSStart->setValue(0x0);
+
+      if (NULL != f_pEnd)
+        f_pEnd->setValue(0x0);
+      if (NULL != f_p_End)
+        f_p_End->setValue(0x0);
+    }
+  }
+
   return true;
 }
 
@@ -132,7 +556,7 @@
   return m_pArchiveReader;
 }
 
-GNUArchiveReader *GNULDBackend::getArchiveReader() const
+const GNUArchiveReader *GNULDBackend::getArchiveReader() const
 {
   assert(0 != m_pArchiveReader);
   return m_pArchiveReader;
@@ -144,7 +568,7 @@
   return m_pObjectReader;
 }
 
-ELFObjectReader *GNULDBackend::getObjectReader() const
+const ELFObjectReader *GNULDBackend::getObjectReader() const
 {
   assert(0 != m_pObjectReader);
   return m_pObjectReader;
@@ -156,7 +580,7 @@
   return m_pDynObjReader;
 }
 
-ELFDynObjReader *GNULDBackend::getDynObjReader() const
+const ELFDynObjReader *GNULDBackend::getDynObjReader() const
 {
   assert(0 != m_pDynObjReader);
   return m_pDynObjReader;
@@ -168,7 +592,7 @@
   return NULL;
 }
 
-ELFObjectWriter *GNULDBackend::getObjectWriter() const
+const ELFObjectWriter *GNULDBackend::getObjectWriter() const
 {
   // TODO
   return NULL;
@@ -180,19 +604,61 @@
   return m_pDynObjWriter;
 }
 
-ELFDynObjWriter *GNULDBackend::getDynObjWriter() const
+const ELFDynObjWriter *GNULDBackend::getDynObjWriter() const
 {
   assert(0 != 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:
+    default:
+      fatal(diag::unrecognized_output_file) << pOutput.type();
+      return NULL;
+  }
+}
+
+const ELFFileFormat* GNULDBackend::getOutputFormat(const Output& pOutput) 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:
+    default:
+      fatal(diag::unrecognized_output_file) << pOutput.type();
+      return NULL;
+  }
+}
+
 ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat()
 {
   assert(0 != m_pDynObjFileFormat);
   return m_pDynObjFileFormat;
 }
 
-ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat() const
+const ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat() const
 {
   assert(0 != m_pDynObjFileFormat);
   return m_pDynObjFileFormat;
@@ -204,7 +670,7 @@
   return m_pExecFileFormat;
 }
 
-ELFExecFileFormat* GNULDBackend::getExecFileFormat() const
+const ELFExecFileFormat* GNULDBackend::getExecFileFormat() const
 {
   assert(0 != m_pExecFileFormat);
   return m_pExecFileFormat;
@@ -241,20 +707,7 @@
     strtab += str_size;
   }
 
-  ELFFileFormat* file_format = NULL;
-  switch(pOutput.type()) {
-    // compute size of .dynstr and .hash
-    case Output::DynObj:
-      file_format = getDynObjFileFormat();
-      break;
-    case Output::Exec:
-      file_format = getExecFileFormat();
-      break;
-    case Output::Object:
-    default:
-      // TODO: not support yet
-      return;
-  }
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   switch(pOutput.type()) {
     // compute size of .dynstr and .hash
@@ -335,23 +788,14 @@
   bool sym_exist = false;
   HashTableType::entry_type* entry = 0;
 
-  ELFFileFormat* file_format = NULL;
-  switch(pOutput.type()) {
-    // compute size of .dynstr and .hash
-    case Output::DynObj:
-      file_format = getDynObjFileFormat();
-      break;
-    case Output::Exec:
-      file_format = getExecFileFormat();
-      break;
-    case Output::Object:
-    default:
-      // add first symbol into m_pSymIndexMap
-      entry = m_pSymIndexMap->insert(NULL, sym_exist);
-      entry->setValue(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;
+    // TODO: not support yet
+    return;
   }
 
   LDSection& symtab_sect = file_format->getSymTab();
@@ -446,25 +890,11 @@
                                     const MCLDInfo& pLDInfo)
 {
   assert(pOutput.hasMemArea());
-  ELFFileFormat* file_format = NULL;
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   bool sym_exist = false;
   HashTableType::entry_type* entry = 0;
 
-  switch(pOutput.type()) {
-    // compute size of .dynstr and .hash
-    case Output::DynObj:
-      file_format = getDynObjFileFormat();
-      break;
-    case Output::Exec:
-      file_format = getExecFileFormat();
-      break;
-    case Output::Object:
-    default:
-      // TODO: not support yet
-      return;
-  }
-
   LDSection& symtab_sect = file_format->getDynSymTab();
   LDSection& strtab_sect = file_format->getDynStrTab();
   LDSection& hash_sect   = file_format->getHashTab();
@@ -587,7 +1017,8 @@
 
   // emit soname
   // initialize value of ELF .dynamic section
-  dynamic().applySoname(strtabsize);
+  if (Output::DynObj == pOutput.type())
+    dynamic().applySoname(strtabsize);
   dynamic().applyEntries(pLDInfo, *file_format);
   dynamic().emit(dyn_sect, *dyn_region);
 
@@ -633,9 +1064,44 @@
   }
 }
 
+/// sizeInterp - compute the size of the .interp section
+void GNULDBackend::sizeInterp(const Output& pOutput, const MCLDInfo& pLDInfo)
+{
+  assert(pOutput.type() == Output::Exec);
+
+  const char* dyld_name;
+  if (pLDInfo.options().hasDyld())
+    dyld_name = pLDInfo.options().dyld().c_str();
+  else
+    dyld_name = dyld();
+
+  LDSection& interp = getExecFileFormat()->getInterp();
+  interp.setSize(std::strlen(dyld_name) + 1);
+}
+
+/// emitInterp - emit the .interp
+void GNULDBackend::emitInterp(Output& pOutput, const MCLDInfo& pLDInfo)
+{
+  assert(pOutput.type() == Output::Exec &&
+         getExecFileFormat()->hasInterp() &&
+         pOutput.hasMemArea());
+
+  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());
+}
+
 /// getSectionOrder
 unsigned int GNULDBackend::getSectionOrder(const Output& pOutput,
-                                           const LDSection& pSectHdr) const
+                                           const LDSection& pSectHdr,
+                                           const MCLDInfo& pInfo) const
 {
   // NULL section should be the "1st" section
   if (LDFileFormat::Null == pSectHdr.kind())
@@ -647,19 +1113,7 @@
 
   bool is_write = (pSectHdr.flag() & llvm::ELF::SHF_WRITE) != 0;
   bool is_exec = (pSectHdr.flag() & llvm::ELF::SHF_EXECINSTR) != 0;
-  ELFFileFormat* file_format = NULL;
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      file_format = getDynObjFileFormat();
-      break;
-    case Output::Exec:
-      file_format = getExecFileFormat();
-      break;
-    case Output::Object:
-    default:
-      assert(0 && "Not support yet.\n");
-      break;
-  }
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   // TODO: need to take care other possible output sections
   switch (pSectHdr.kind()) {
@@ -673,13 +1127,18 @@
       } else if (!is_write) {
         return SHO_RO;
       } else {
-        if (pSectHdr.type() == llvm::ELF::SHT_PREINIT_ARRAY ||
-            pSectHdr.type() == llvm::ELF::SHT_INIT_ARRAY ||
-            pSectHdr.type() == llvm::ELF::SHT_FINI_ARRAY ||
-            &pSectHdr == &file_format->getCtors() ||
-            &pSectHdr == &file_format->getDtors())
-          return SHO_RELRO;
-
+        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 ||
+              &pSectHdr == &file_format->getCtors() ||
+              &pSectHdr == &file_format->getDtors() ||
+              &pSectHdr == &file_format->getJCR() ||
+              0 == pSectHdr.name().compare(".data.rel.ro"))
+            return SHO_RELRO;
+          if (0 == pSectHdr.name().compare(".data.rel.ro.local"))
+            return SHO_RELRO_LOCAL;
+        }
         return SHO_DATA;
       }
 
@@ -699,14 +1158,16 @@
 
     // get the order from target for target specific sections
     case LDFileFormat::Target:
-      return getTargetSectionOrder(pOutput, pSectHdr);
+      return getTargetSectionOrder(pOutput, pSectHdr, pInfo);
 
     // handle .interp
     case LDFileFormat::Note:
       return SHO_INTERP;
 
-    case LDFileFormat::Exception:
-      return SHO_EHFRAME;
+    case LDFileFormat::EhFrame:
+    case LDFileFormat::EhFrameHdr:
+    case LDFileFormat::GCCExceptTable:
+      return SHO_EXCEPTION;
 
     case LDFileFormat::MetaData:
     case LDFileFormat::Debug:
@@ -745,7 +1206,12 @@
       pSymbol.visibility() == llvm::ELF::STV_HIDDEN)
     bind = llvm::ELF::STB_LOCAL;
 
-  return (pSymbol.resolveInfo()->type() | (bind << 4));
+  uint32_t type = pSymbol.resolveInfo()->type();
+  // if the IndirectFunc symbol (i.e., STT_GNU_IFUNC) is from dynobj, change
+  // its type to Function
+  if (type == ResolveInfo::IndirectFunc && pSymbol.isDyn())
+    type = ResolveInfo::Function;
+  return (type | (bind << 4));
 }
 
 /// getSymbolValue - this function is called after layout()
@@ -776,7 +1242,7 @@
     }
   }
 
-  assert(pSymbol.hasFragRef());
+  assert(pSymbol.hasFragRef() && "symbols must have fragment reference to get its index");
   return pLayout.getOutputLDSection(*pSymbol.fragRef()->frag())->index();
 }
 
@@ -787,38 +1253,154 @@
    return entry.getEntry()->value();
 }
 
-/// emitProgramHdrs - emit ELF program headers
-void GNULDBackend::emitProgramHdrs(Output& pOutput)
+/// allocateCommonSymbols - allocate common symbols in the corresponding
+/// sections.
+/// @refer Google gold linker: common.cc: 214
+bool
+GNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
 {
-  assert(NULL != pOutput.context());
-  createProgramHdrs(*pOutput.context());
+  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
 
-  if (32 == bitclass())
-    writeELF32ProgramHdrs(pOutput);
-  else
-    writeELF64ProgramHdrs(pOutput);
+  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
+    return true;
+
+  SymbolCategory::iterator com_sym, com_end;
+
+  // 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 or create corresponding BSS MCSectionData
+  llvm::MCSectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
+  llvm::MCSectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
+
+  // remember original BSS 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();
+
+  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
+    if (ResolveInfo::Common == (*com_sym)->desc()) {
+      // We have to reset the description of the symbol here. When doing
+      // incremental linking, the output relocatable object may have common
+      // symbols. Therefore, we can not treat common symbols as normal symbols
+      // when emitting the regular name pools. We must change the symbols'
+      // description here.
+      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
+      (*com_sym)->setFragmentRef(new MCFragmentRef(*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());
+      }
+      else {
+        bss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                         bss_sect_data,
+                                                         (*com_sym)->value());
+      }
+    }
+  }
+
+  // allocate all global common symbols
+  com_end = symbol_list.commonEnd();
+  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
+    // We have to reset the description of the symbol here. When doing
+    // incremental linking, the output relocatable object may have common
+    // symbols. Therefore, we can not treat common symbols as normal symbols
+    // when emitting the regular name pools. We must change the symbols'
+    // description here.
+    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
+    (*com_sym)->setFragmentRef(new MCFragmentRef(*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());
+    }
+    else {
+      bss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                       bss_sect_data,
+                                                       (*com_sym)->value());
+    }
+  }
+
+  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(LDContext& pContext)
+void GNULDBackend::createProgramHdrs(Output& pOutput, const MCLDInfo& pInfo)
 {
+  assert(pOutput.hasContext());
+  ELFFileFormat *file_format = getOutputFormat(pOutput);
+
   // make PT_PHDR
   m_ELFSegmentTable.produce(llvm::ELF::PT_PHDR);
 
   // make PT_INTERP
-  LDSection* interp = pContext.getSection(".interp");
-  if (NULL != interp) {
+  if (file_format->hasInterp()) {
     ELFSegment* interp_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_INTERP);
-    interp_seg->addSection(interp);
-    interp_seg->setAlign(bitclass() / 8);
+    interp_seg->addSection(&file_format->getInterp());
+  }
+
+  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 = 0;
+    while (idx < pOutput.context()->numOfSections()) {
+      // find the first non-relro section, and align its offset to a page
+      // boundary
+      if (getSectionOrder(pOutput, *sect_table[idx], pInfo) > SHO_RELRO_LAST) {
+        uint64_t offset = sect_table[idx]->offset();
+        alignAddress(offset, commonPageSize(pInfo));
+        sect_table[idx]->setOffset(offset);
+        ++idx;
+        break;
+      }
+      ++idx;
+    }
+    while (idx < pOutput.context()->numOfSections()) {
+      // adjust the remaining sections' offset
+      uint64_t offset = sect_table[idx - 1]->offset();
+      if (LDFileFormat::BSS != sect_table[idx - 1]->kind())
+        offset += sect_table[idx - 1]->size();
+      alignAddress(offset, sect_table[idx]->align());
+      sect_table[idx]->setOffset(offset);
+      ++idx;
+    }
   }
 
   uint32_t cur_seg_flag, prev_seg_flag = getSegmentFlag(0);
   uint64_t padding = 0;
   ELFSegment* load_seg = NULL;
   // make possible PT_LOAD segments
-  LDContext::sect_iterator sect, sect_end = pContext.sectEnd();
-  for (sect = pContext.sectBegin(); sect != sect_end; ++sect) {
+  LDContext::sect_iterator sect, sect_end = pOutput.context()->sectEnd();
+  for (sect = pOutput.context()->sectBegin(); sect != sect_end; ++sect) {
+
     if (0 == ((*sect)->flag() & llvm::ELF::SHF_ALLOC) &&
         LDFileFormat::Null != (*sect)->kind())
       continue;
@@ -829,36 +1411,60 @@
          LDFileFormat::Null == (*sect)->kind()) {
       // create new PT_LOAD segment
       load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD);
-      load_seg->setAlign(pagesize());
+      load_seg->setAlign(commonPageSize(pInfo));
 
       // check if this segment needs padding
       padding = 0;
-      if (((*sect)->offset() & (load_seg->align() - 1)) != 0)
-        padding = load_seg->align();
+      if (((*sect)->offset() & (abiPageSize(pInfo) - 1)) != 0)
+        padding = abiPageSize(pInfo);
     }
 
     assert(NULL != load_seg);
-    load_seg->addSection(*sect);
-    load_seg->updateFlag(cur_seg_flag);
+    load_seg->addSection((*sect));
+    if (cur_seg_flag != prev_seg_flag)
+      load_seg->updateFlag(cur_seg_flag);
 
-    // FIXME: set section's vma
-    // need to handle start vma for user-defined one or for executable.
-    (*sect)->setAddr((*sect)->offset() + padding);
+    if (LDFileFormat::Null != (*sect)->kind())
+      (*sect)->setAddr(segmentStartAddr(pOutput, pInfo) +
+                       (*sect)->offset() +
+                       padding);
 
     prev_seg_flag = cur_seg_flag;
   }
 
   // make PT_DYNAMIC
-  LDSection* dynamic = pContext.getSection(".dynamic");
-  if (NULL != dynamic) {
-    ELFSegment* dyn_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_DYNAMIC);
-    dyn_seg->setFlag(llvm::ELF::PF_R | llvm::ELF::PF_W);
-    dyn_seg->addSection(dynamic);
-    dyn_seg->setAlign(bitclass() / 8);
+  if (file_format->hasDynamic()) {
+    ELFSegment* dyn_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_DYNAMIC,
+                                                    llvm::ELF::PF_R |
+                                                    llvm::ELF::PF_W);
+    dyn_seg->addSection(&file_format->getDynamic());
   }
 
+  if (pInfo.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);
+      }
+    }
+  }
+
+  // make PT_GNU_EH_FRAME
+  if (file_format->hasEhFrameHdr()) {
+    ELFSegment* eh_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_EH_FRAME);
+    eh_seg->addSection(&file_format->getEhFrameHdr());
+  }
+}
+
+/// setupProgramHdrs - set up the attributes of segments
+void GNULDBackend:: setupProgramHdrs(const Output& pOutput, const MCLDInfo& pInfo)
+{
   // update segment info
-  uint64_t file_size = 0;
   ELFSegmentFactory::iterator seg, seg_end = m_ELFSegmentTable.end();
   for (seg = m_ELFSegmentTable.begin(); seg != seg_end; ++seg) {
     ELFSegment& segment = *seg;
@@ -875,7 +1481,7 @@
         phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
       }
       segment.setOffset(offset);
-      segment.setVaddr(offset);
+      segment.setVaddr(segmentStartAddr(pOutput, pInfo) + offset);
       segment.setPaddr(segment.vaddr());
       segment.setFilesz(numOfSegments() * phdr_size);
       segment.setMemsz(numOfSegments() * phdr_size);
@@ -883,14 +1489,21 @@
       continue;
     }
 
-    assert(NULL != segment.getFirstSection());
+    // bypass if there is no section in this segment (e.g., PT_GNU_STACK)
+    if (segment.numOfSections() == 0)
+      continue;
+
     segment.setOffset(segment.getFirstSection()->offset());
-    segment.setVaddr(segment.getFirstSection()->addr());
+    if (llvm::ELF::PT_LOAD == segment.type() &&
+        LDFileFormat::Null == segment.getFirstSection()->kind())
+      segment.setVaddr(segmentStartAddr(pOutput, pInfo));
+    else
+      segment.setVaddr(segment.getFirstSection()->addr());
     segment.setPaddr(segment.vaddr());
 
     const LDSection* last_sect = segment.getLastSection();
     assert(NULL != last_sect);
-    file_size = last_sect->offset() - segment.offset();
+    uint64_t file_size = last_sect->offset() - segment.offset();
     if (LDFileFormat::BSS != last_sect->kind())
       file_size += last_sect->size();
     segment.setFilesz(file_size);
@@ -899,61 +1512,58 @@
   }
 }
 
-/// writeELF32ProgramHdrs - write out the ELF32 program headers
-void GNULDBackend::writeELF32ProgramHdrs(Output& pOutput)
+/// createGNUStackInfo - create an output GNU stack section or segment if needed
+/// @ref gold linker: layout.cc:2608
+void GNULDBackend::createGNUStackInfo(const Output& pOutput,
+                                      const MCLDInfo& pInfo,
+                                      MCLinker& pLinker)
 {
-  assert(pOutput.hasMemArea());
+  uint32_t flag = 0x0;
+  if (pInfo.options().hasStackSet()) {
+    // 1. check the command line option (-z execstack or -z noexecstack)
+    if (pInfo.options().hasExecStack())
+      flag = llvm::ELF::SHF_EXECINSTR;
+  } else {
+    // 2. check the stack info from the input objects
+    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;
+          }
+        }
+      }
+    }
 
-  uint64_t start_offset, phdr_size;
+    // 2.2 there are no stack note sections in all input objects
+    if (0 == stack_note_count)
+      return;
 
-  start_offset = sizeof(llvm::ELF::Elf32_Ehdr);
-  phdr_size = sizeof(llvm::ELF::Elf32_Phdr);
-  // Program header must start directly after ELF header
-  MemoryRegion *region = pOutput.memArea()->request(start_offset,
-                                                    numOfSegments()*phdr_size);
-
-  llvm::ELF::Elf32_Phdr* phdr = (llvm::ELF::Elf32_Phdr*)region->start();
-
-  size_t index = 0;
-  ELFSegmentFactory::iterator seg, segEnd = m_ELFSegmentTable.end();
-  for (seg = m_ELFSegmentTable.begin(); seg != segEnd; ++seg, ++index) {
-    phdr[index].p_type   = (*seg).type();
-    phdr[index].p_flags  = (*seg).flag();
-    phdr[index].p_offset = (*seg).offset();
-    phdr[index].p_vaddr  = (*seg).vaddr();
-    phdr[index].p_paddr  = (*seg).paddr();
-    phdr[index].p_filesz = (*seg).filesz();
-    phdr[index].p_memsz  = (*seg).memsz();
-    phdr[index].p_align  = (*seg).align();
+    // 2.3 a special case. Use the target default to decide if the stack should
+    //     be executable
+    if (llvm::ELF::SHF_EXECINSTR != flag && object_count != stack_note_count)
+      if (isDefaultExecStack())
+        flag = llvm::ELF::SHF_EXECINSTR;
   }
-}
 
-/// writeELF64ProgramHdrs - write out the ELF64 program headers
-void GNULDBackend::writeELF64ProgramHdrs(Output& pOutput)
-{
-  assert(pOutput.hasMemArea());
-
-  uint64_t start_offset, phdr_size;
-
-  start_offset = sizeof(llvm::ELF::Elf64_Ehdr);
-  phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
-  // Program header must start directly after ELF header
-  MemoryRegion *region = pOutput.memArea()->request(start_offset,
-                                                    numOfSegments() *phdr_size);
-  llvm::ELF::Elf64_Phdr* phdr = (llvm::ELF::Elf64_Phdr*)region->start();
-
-  size_t index = 0;
-  ELFSegmentFactory::iterator seg, segEnd = m_ELFSegmentTable.end();
-  for (seg = m_ELFSegmentTable.begin(); seg != segEnd; ++seg, ++index) {
-    phdr[index].p_type   = (*seg).type();
-    phdr[index].p_flags  = (*seg).flag();
-    phdr[index].p_offset = (*seg).offset();
-    phdr[index].p_vaddr  = (*seg).vaddr();
-    phdr[index].p_paddr  = (*seg).paddr();
-    phdr[index].p_filesz = (*seg).filesz();
-    phdr[index].p_memsz  = (*seg).memsz();
-    phdr[index].p_align  = (*seg).align();
-  }
+  if (pOutput.type() != Output::Object)
+    m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_STACK,
+                              llvm::ELF::PF_R |
+                              llvm::ELF::PF_W |
+                              getSegmentFlag(flag));
+  else
+    pLinker.getOrCreateOutputSectHdr(".note.GNU-stack",
+                                     LDFileFormat::Note,
+                                     llvm::ELF::SHT_PROGBITS,
+                                     flag);
 }
 
 /// preLayout - Backend can do any needed modification before layout
@@ -963,6 +1573,16 @@
 {
   // prelayout target first
   doPreLayout(pOutput, pLDInfo, pLinker);
+
+  if (pLDInfo.options().hasEhFrameHdr()) {
+    // init EhFrameHdr and size the output section
+    ELFFileFormat* format = getOutputFormat(pOutput);
+    assert(NULL != getEhFrame());
+    m_pEhFrameHdr = new EhFrameHdr(*getEhFrame(),
+                                   format->getEhFrame(),
+                                   format->getEhFrameHdr());
+    m_pEhFrameHdr->sizeOutput();
+  }
 }
 
 /// postLayout -Backend can do any needed modification after layout
@@ -970,10 +1590,36 @@
                               const MCLDInfo& pInfo,
                               MCLinker& pLinker)
 {
-  // post layout target first
+  // 1. emit program headers
+  if (pOutput.type() != Output::Object) {
+    // 1.1 create program headers
+    createProgramHdrs(pLinker.getLDInfo().output(), pInfo);
+  }
+
+  // 1.2 create special GNU Stack note section or segment
+  createGNUStackInfo(pOutput, pInfo, pLinker);
+
+  if (pOutput.type() != Output::Object) {
+    // 1.3 set up the attributes of program headers
+    setupProgramHdrs(pOutput, pInfo);
+  }
+
+  // 2. target specific post layout
   doPostLayout(pOutput, pInfo, pLinker);
 }
 
+void GNULDBackend::postProcessing(const Output& pOutput,
+                                  const MCLDInfo& pInfo,
+                                  MCLinker& pLinker)
+{
+  if (pInfo.options().hasEhFrameHdr()) {
+    // emit eh_frame_hdr
+    if (bitclass() == 32)
+      m_pEhFrameHdr->emitOutput<32>(pLinker.getLDInfo().output(),
+                                    pLinker);
+  }
+}
+
 /// getHashBucketCount - calculate hash bucket count.
 /// @ref Google gold linker, dynobj.cc:791
 unsigned GNULDBackend::getHashBucketCount(unsigned pNumOfSymbols,
@@ -1012,10 +1658,147 @@
 
   // If we are building shared object, and the visibility is external, we
   // need to add it.
-  if (Output::DynObj == pOutput.type())
+  if (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type())
     if (pSymbol.resolveInfo()->visibility() == ResolveInfo::Default ||
         pSymbol.resolveInfo()->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
+{
+  if (pInfo.options().commPageSize() > 0)
+    return std::min(pInfo.options().commPageSize(), abiPageSize(pInfo));
+  else
+    return std::min(static_cast<uint64_t>(0x1000), abiPageSize(pInfo));
+}
+
+/// abiPageSize - the abi page size of the target machine.
+/// @ref gold linker: target.h:125
+uint64_t GNULDBackend::abiPageSize(const MCLDInfo& pInfo) const
+{
+  if (pInfo.options().maxPageSize() > 0)
+    return pInfo.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
+{
+  if (pSym.other() != ResolveInfo::Default)
+    return false;
+
+  if (Output::DynObj != pOutput.type())
+    return false;
+
+  if (pLDInfo.options().Bsymbolic())
+    return false;
+
+  return true;
+}
+
+/// 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
+{
+  if (pSym.isUndef() && !pSym.isDyn() && pOutput.type() != Output::DynObj)
+    return false;
+
+  // An IndirectFunc symbol (i.e., STT_GNU_IFUNC) always needs a plt entry
+  if (pSym.type() == ResolveInfo::IndirectFunc)
+    return true;
+
+  if (pSym.type() != ResolveInfo::Function)
+    return false;
+
+  if (isStaticLink(pOutput, pLDInfo) || pLDInfo.options().isPIE())
+    return false;
+
+  return (pSym.isDyn() ||
+          pSym.isUndef() ||
+          isSymbolPreemptible(pSym, pLDInfo, pOutput));
+}
+
+/// 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
+{
+  // 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()))
+    return false;
+  if (pSym.isAbsolute())
+    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))
+    return true;
 
   return false;
 }
+
+/// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
+bool GNULDBackend::symbolNeedsCopyReloc(const Layout& pLayout,
+                                        const Relocation& pReloc,
+                                        const ResolveInfo& pSym,
+                                        const MCLDInfo& pLDInfo,
+                                        const Output& pOutput) const
+{
+  // only the reference from dynamic executable to non-function symbol in
+  // the dynamic objects may need copy relocation
+  if (isOutputPIC(pOutput, pLDInfo) ||
+      !pSym.isDyn() ||
+      pSym.type() == ResolveInfo::Function ||
+      pSym.size() == 0)
+    return false;
+
+  // check if the option -z nocopyreloc is given
+  if (pLDInfo.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)
+    return true;
+
+  return false;
+}
+
diff --git a/lib/Target/Mips/MipsAndroidSectLinker.cpp b/lib/Target/Mips/MipsAndroidSectLinker.cpp
deleted file mode 100644
index e697fbc..0000000
--- a/lib/Target/Mips/MipsAndroidSectLinker.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- MipsAndroidSectLinker.cpp ------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsAndroidSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-MipsAndroidSectLinker::MipsAndroidSectLinker(SectLinkerOption &pOption,
-                                             TargetLDBackend &pLDBackend)
-  : AndroidSectLinker(pOption,
-                      pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attibutes
-  info.attrFactory().constraint().disableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().unsetWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-}
-
-MipsAndroidSectLinker::~MipsAndroidSectLinker()
-{
-}
diff --git a/lib/Target/Mips/MipsAndroidSectLinker.h b/lib/Target/Mips/MipsAndroidSectLinker.h
deleted file mode 100644
index ba216e4..0000000
--- a/lib/Target/Mips/MipsAndroidSectLinker.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- MipsAndroidSectLinker.h --------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MIPS_ANDROIDSECTLINKER_H
-#define MIPS_ANDROIDSECTLINKER_H
-
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include "mcld/Target/AndroidSectLinker.h"
-
-namespace mcld
-{
-
-/** \class MipsAndroidSectLinker
- *  \brief MipsAndroidSectLinker sets up the environment for linking.
- *
- */
-class MipsAndroidSectLinker : public AndroidSectLinker
-{
-public:
-  MipsAndroidSectLinker(SectLinkerOption &pOption,
-                        mcld::TargetLDBackend &pLDBackend);
-
-  ~MipsAndroidSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
diff --git a/lib/Target/Mips/MipsDiagnostic.cpp b/lib/Target/Mips/MipsDiagnostic.cpp
new file mode 100644
index 0000000..c90c6ef
--- /dev/null
+++ b/lib/Target/Mips/MipsDiagnostic.cpp
@@ -0,0 +1,35 @@
+//===- MipsDiagnostic.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/DWARFLineInfo.h>
+#include "Mips.h"
+
+using namespace mcld;
+
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createMipsDiagnostic - the help function to create corresponding
+// MipsDiagnostic
+DiagnosticLineInfo* createMipsDiagLineInfo(const llvm::Target& pTarget,
+                                           const std::string &pTriple)
+{
+  return new DWARFLineInfo();
+}
+
+} // namespace of mcld
+
+//==========================
+// InitializeMipsDiagnostic
+extern "C" void LLVMInitializeMipsDiagnosticLineInfo() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheMipselTarget, createMipsDiagLineInfo);
+}
+
diff --git a/lib/Target/Mips/MipsELFSectLinker.cpp b/lib/Target/Mips/MipsELFSectLinker.cpp
index aa41f36..dedf505 100644
--- a/lib/Target/Mips/MipsELFSectLinker.cpp
+++ b/lib/Target/Mips/MipsELFSectLinker.cpp
@@ -6,7 +6,6 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include "MipsELFSectLinker.h"
 
 #include <mcld/CodeGen/SectLinkerOption.h>
@@ -31,3 +30,4 @@
 MipsELFSectLinker::~MipsELFSectLinker()
 {
 }
+
diff --git a/lib/Target/Mips/MipsELFSectLinker.h b/lib/Target/Mips/MipsELFSectLinker.h
index 949508d..1aacfef 100644
--- a/lib/Target/Mips/MipsELFSectLinker.h
+++ b/lib/Target/Mips/MipsELFSectLinker.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MIPS_ELFSECTLINKER_H
-#define MIPS_ELFSECTLINKER_H
+#ifndef MIPS_ELF_SECTION_LINKER_H
+#define MIPS_ELF_SECTION_LINKER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -31,3 +31,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
index e1185ca..9baa033 100644
--- a/lib/Target/Mips/MipsGOT.cpp
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -7,9 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include "MipsGOT.h"
 
 namespace {
@@ -31,7 +31,7 @@
       new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
 
     if (NULL == entry)
-      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+      fatal(diag::fail_allocate_memory) << "GOT0";
 
     m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
   }
@@ -41,8 +41,7 @@
   iterator ie = m_SectionData.end();
 
   for (size_t i = 1; i < MipsGOT0Num; ++i) {
-    if (it == ie)
-      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
+    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
 
     ++it;
   }
@@ -95,7 +94,7 @@
       new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
 
     if (NULL == entry)
-      llvm::report_fatal_error("Allocating new GOTEntry failed");
+      fatal(diag::fail_allocate_memory) << "GOTEntry";
 
     m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
   }
@@ -118,12 +117,22 @@
 
 GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
 {
+  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;
+  }
+
   GOTEntry*& entry = m_GeneralGOTMap[&pInfo];
 
   pExist = NULL != entry;
 
   if (!pExist) {
-    iterator& it = pInfo.isLocal() ? m_LocalGOTIterator : m_GlobalGOTIterator;
+    iterator& it = isLocal(&pInfo)  ? m_LocalGOTIterator : m_GlobalGOTIterator;
 
     ++it;
 
@@ -145,3 +154,4 @@
 {
   return m_pLocalNum;
 }
+
diff --git a/lib/Target/Mips/MipsGOT.h b/lib/Target/Mips/MipsGOT.h
index dc8a23e..2f04ef4 100644
--- a/lib/Target/Mips/MipsGOT.h
+++ b/lib/Target/Mips/MipsGOT.h
@@ -26,6 +26,7 @@
 {
 private:
   typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
+  typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolTypeMapType;
 
 public:
   typedef llvm::MCSectionData::iterator iterator;
@@ -50,8 +51,26 @@
   size_t getTotalNum() const;
   size_t getLocalNum() const;
 
+  void setLocal(const ResolveInfo* pInfo) {
+    m_GOTTypeMap[pInfo] = false;
+  }
+
+  void setGlobal(const ResolveInfo* pInfo) {
+    m_GOTTypeMap[pInfo] = true;
+  }
+
+  bool isLocal(const ResolveInfo* pInfo) {
+    return m_GOTTypeMap[pInfo] == false;
+  }
+
+  bool isGlobal(const ResolveInfo* pInfo) {
+    return m_GOTTypeMap[pInfo] == true;
+  }
+
 private:
-  SymbolIndexMapType m_GeneralGOTMap;
+  SymbolIndexMapType m_GeneralGOTMap; // Map ResolveInfo* to GOTEntry *.
+  SymbolTypeMapType m_GOTTypeMap;
+
   iterator m_LocalGOTIterator;  // last local GOT entries
   iterator m_GlobalGOTIterator; // last global GOT entries
   size_t m_pLocalNum;
@@ -64,3 +83,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
index c7a6b23..87e43b8 100644
--- a/lib/Target/Mips/MipsLDBackend.cpp
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -14,6 +14,7 @@
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/MC/MCLinker.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/Target/OutputRelocSection.h>
 
@@ -66,11 +67,24 @@
 
 void MipsGNULDBackend::initTargetSections(MCLinker& pLinker)
 {
-  // Nothing to do because we do not support
-  // any MIPS specific sections now.
+  // Set up .dynamic
+  ELFFileFormat* file_format = NULL;
+  switch(pLinker.getLDInfo().output().type()) {
+    case Output::DynObj:
+      file_format = getDynObjFileFormat();
+      break;
+    case Output::Exec:
+      file_format = getExecFileFormat();
+      break;
+    case Output::Object:
+    default:
+      // TODO: not support yet
+      return;
+  }
+  file_format->getDynamic().setFlag(llvm::ELF::SHF_ALLOC);
 }
 
-void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker)
+void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
@@ -120,12 +134,21 @@
                                       const LDSymbol& pInputSym,
                                       MCLinker& pLinker,
                                       const MCLDInfo& pLDInfo,
-                                      const Output& pOutput)
+                                      const Output& pOutput,
+                                      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) {
@@ -134,7 +157,15 @@
     }
   }
 
-  if (rsym->isLocal())
+  // Skip relocation against _gp_disp
+  if (strcmp("_gp_disp", pInputSym.name()) == 0)
+    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) ||
+      !rsym->isDyn()) && !rsym->isUndef())
     scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
   else
     scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
@@ -177,6 +208,11 @@
   return 32;
 }
 
+uint64_t MipsGNULDBackend::defaultTextSegmentAddr() const
+{
+  return 0x80000;
+}
+
 void MipsGNULDBackend::doPreLayout(const Output& pOutput,
                                    const MCLDInfo& pInfo,
                                    MCLinker& pLinker)
@@ -191,9 +227,6 @@
                                     const MCLDInfo& pInfo,
                                     MCLinker& pLinker)
 {
-  // emit program headers
-  if (pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
-    emitProgramHdrs(pLinker.getLDInfo().output());
 }
 
 /// dynamic - the dynamic section of the target machine.
@@ -217,11 +250,12 @@
 uint64_t MipsGNULDBackend::emitSectionData(const Output& pOutput,
                                            const LDSection& pSection,
                                            const MCLDInfo& pInfo,
+                                           const Layout& pLayout,
                                            MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   if (&pSection == &(file_format->getGOT())) {
     assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
@@ -229,17 +263,15 @@
     return result;
   }
 
-  llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
-                           pSection.name() +
-                           llvm::Twine("'.\n"));
+  fatal(diag::unrecognized_output_sectoin)
+          << pSection.name()
+          << "mclinker@googlegroups.com";
   return 0;
 }
-/// isGOTSymbol - return true if the symbol is the GOT entry.
-bool MipsGNULDBackend::isGOTSymbol(const LDSymbol& pSymbol) const
+/// isGlobalGOTSymbol - return true if the symbol is the global GOT entry.
+bool MipsGNULDBackend::isGlobalGOTSymbol(const LDSymbol& pSymbol) const
 {
-  return std::find(m_LocalGOTSyms.begin(),
-                   m_LocalGOTSyms.end(), &pSymbol) != m_LocalGOTSyms.end() ||
-         std::find(m_GlobalGOTSyms.begin(),
+  return std::find(m_GlobalGOTSyms.begin(),
                    m_GlobalGOTSyms.end(), &pSymbol) != m_GlobalGOTSyms.end();
 }
 
@@ -326,7 +358,7 @@
     if (!isDynamicSymbol(**symbol, pOutput))
       continue;
 
-    if (isGOTSymbol(**symbol))
+    if (isGlobalGOTSymbol(**symbol))
       continue;
 
     emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
@@ -342,6 +374,12 @@
        symbol_end = m_GlobalGOTSyms.end();
        symbol != symbol_end; ++symbol) {
 
+    // Make sure this golbal GOT entry is a dynamic symbol.
+    // If not, something is wrong earlier when putting this symbol into
+    //  global GOT.
+    if (!isDynamicSymbol(**symbol, pOutput))
+      fatal(diag::mips_got_symbol) << (*symbol)->name();
+
     emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
                       strtabsize, symtabIdx);
 
@@ -382,7 +420,8 @@
 
   // emit soname
   // initialize value of ELF .dynamic section
-  dynamic().applySoname(strtabsize);
+  if (Output::DynObj == pOutput.type())
+    dynamic().applySoname(strtabsize);
   dynamic().applyEntries(pLDInfo, *file_format);
   dynamic().emit(dyn_sect, *dyn_region);
 
@@ -445,9 +484,10 @@
 
 unsigned int
 MipsGNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                        const LDSection& pSectHdr) const
+                                        const LDSection& pSectHdr,
+                                        const MCLDInfo& pInfo) const
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   if (&pSectHdr == &file_format->getGOT())
     return SHO_DATA;
@@ -456,15 +496,10 @@
 }
 
 /// finalizeSymbol - finalize the symbol value
-/// If the symbol's reserved field is not zero, MCLinker will call back this
-/// function to ask the final value of the symbol
-bool MipsGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+bool MipsGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
-  if (&pSymbol == m_pGpDispSymbol) {
-    m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
-    return true;
-  }
-  return false;
+  m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
+  return true;
 }
 
 /// allocateCommonSymbols - allocate common symbols in the corresponding
@@ -474,96 +509,112 @@
 bool
 MipsGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
 {
-  // SymbolCategory contains all symbols that must emit to the output files.
-  // We are not like Google gold linker, we don't remember symbols before symbol
-  // resolution. All symbols in SymbolCategory are already resolved. Therefore, we
-  // don't need to care about some symbols may be changed its category due to symbol
-  // resolution.
   SymbolCategory& symbol_list = pLinker.getOutputSymbols();
 
   if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
     return true;
 
-  // addralign := max value of all common symbols
-  uint64_t addralign = 0x0;
-
-  // Due to the visibility, some common symbols may be forcefully local.
-  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      if ((*com_sym)->value() > addralign)
-        addralign = (*com_sym)->value();
-    }
-  }
-
-  // global common symbols.
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    if ((*com_sym)->value() > addralign)
-      addralign = (*com_sym)->value();
-  }
+  SymbolCategory::iterator com_sym, com_end;
 
   // FIXME: If the order of common symbols is defined, then sort common symbols
-  // com_sym = symbol_list.commonBegin();
   // std::sort(com_sym, com_end, some kind of order);
 
   // get or create corresponding BSS LDSection
-  LDSection* bss_sect_hdr = NULL;
-  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
+  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);
-  }
-  else {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
+
+  // 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_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 or create corresponding BSS MCSectionData
-  assert(NULL != bss_sect_hdr);
-  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
+  llvm::MCSectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
+  llvm::MCSectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
 
-  // allocate all common symbols
-  uint64_t offset = bss_sect_hdr->size();
+  // remember original BSS 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();
+
   for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
     if (ResolveInfo::Common == (*com_sym)->desc()) {
-      alignAddress(offset, (*com_sym)->value());
       // We have to reset the description of the symbol here. When doing
       // incremental linking, the output relocatable object may have common
       // symbols. Therefore, we can not treat common symbols as normal symbols
       // when emitting the regular name pools. We must change the symbols'
       // description here.
       (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section);
+      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
       (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-      offset += (*com_sym)->size();
+
+      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());
+      }
+      // FIXME: how to identify small and large common symbols?
+      else {
+        bss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                         bss_sect_data,
+                                                         (*com_sym)->value());
+      }
     }
   }
 
   // allocate all global common symbols
   com_end = symbol_list.commonEnd();
   for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    alignAddress(offset, (*com_sym)->value());
-
     // We have to reset the description of the symbol here. When doing
     // incremental linking, the output relocatable object may have common
     // symbols. Therefore, we can not treat common symbols as normal symbols
     // when emitting the regular name pools. We must change the symbols'
     // description here.
     (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section);
+    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
     (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-    offset += (*com_sym)->size();
+
+    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());
+    }
+    // FIXME: how to identify small and large common symbols?
+    else {
+      bss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                       bss_sect_data,
+                                                       (*com_sym)->value());
+    }
   }
 
-  bss_sect_hdr->setSize(offset);
+  bss_sect->setSize(bss_offset);
+  tbss_sect->setSize(tbss_offset);
   symbol_list.changeCommonsToGlobal();
   return true;
 }
@@ -573,7 +624,7 @@
                                    const Layout& pLayout) const
 {
   // Update value keep in addend if we meet a section symbol
-  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
     pReloc.setAddend(pLayout.getOutputOffset(
                      *pInputSym.fragRef()) + pReloc.addend());
   }
@@ -604,6 +655,12 @@
 
         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;
     case llvm::ELF::R_MIPS_REL32:
@@ -637,10 +694,19 @@
       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();
+        // Remeber this rsym is a local GOT entry
+        m_pGOT->setLocal(rsym);
+        return;
+      }
+
       if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
         m_pGOT->reserveLocalEntry();
         rsym->setReserved(rsym->reserved() | ReserveGot);
-        m_LocalGOTSyms.push_back(rsym->outSymbol());
+        // Remeber this rsym is a local GOT entry
+        m_pGOT->setLocal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_GPREL32:
@@ -668,11 +734,8 @@
     case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
       break;
     default:
-      llvm::report_fatal_error(llvm::Twine("Unknown relocation ") +
-                               llvm::Twine(pReloc.type()) +
-                               llvm::Twine("for the local symbol `") +
-                               pReloc.symInfo()->name() +
-                               llvm::Twine("'."));
+      fatal(diag::unknown_relocation) << (int)pReloc.type()
+                                      << pReloc.symInfo()->name();
   }
 }
 
@@ -701,12 +764,18 @@
     case llvm::ELF::R_MIPS_64:
     case llvm::ELF::R_MIPS_HI16:
     case llvm::ELF::R_MIPS_LO16:
-      if (isSymbolNeedsDynRel(*rsym, pOutput)) {
+      if (symbolNeedsDynRel(*rsym, false, pLDInfo, pOutput, true)) {
         if (NULL == m_pRelDyn)
           createRelDyn(pLinker, pOutput);
 
         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;
     case llvm::ELF::R_MIPS_GOT16:
@@ -725,16 +794,14 @@
         m_pGOT->reserveGlobalEntry();
         rsym->setReserved(rsym->reserved() | ReserveGot);
         m_GlobalGOTSyms.push_back(rsym->outSymbol());
+        // Remeber this rsym is a global GOT entry
+        m_pGOT->setGlobal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_LITERAL:
     case llvm::ELF::R_MIPS_GPREL32:
-      llvm::report_fatal_error(llvm::Twine("Relocation ") +
-                               llvm::Twine(pReloc.type()) +
-                               llvm::Twine(" is not defined for the "
-                                           "global symbol `") +
-                               pReloc.symInfo()->name() +
-                               llvm::Twine("'."));
+      fatal(diag::invalid_global_relocation) << (int)pReloc.type()
+                                             << pReloc.symInfo()->name();
       break;
     case llvm::ELF::R_MIPS_GPREL16:
       break;
@@ -766,45 +833,14 @@
     case llvm::ELF::R_MIPS_COPY:
     case llvm::ELF::R_MIPS_GLOB_DAT:
     case llvm::ELF::R_MIPS_JUMP_SLOT:
-      llvm::report_fatal_error(llvm::Twine("Relocation ") +
-                               llvm::Twine(pReloc.type()) +
-                               llvm::Twine("for the global symbol `") +
-                               pReloc.symInfo()->name() +
-                               llvm::Twine("' should only be seen "
-                                           "by the dynamic linker"));
+      fatal(diag::dynamic_relocation) << (int)pReloc.type();
       break;
     default:
-      llvm::report_fatal_error(llvm::Twine("Unknown relocation ") +
-                               llvm::Twine(pReloc.type()) +
-                               llvm::Twine("for the global symbol `") +
-                               pReloc.symInfo()->name() +
-                               llvm::Twine("'."));
+      fatal(diag::unknown_relocation) << (int)pReloc.type()
+                                      << pReloc.symInfo()->name();
   }
 }
 
-bool MipsGNULDBackend::isSymbolNeedsPLT(ResolveInfo& pSym,
-                                        const Output& pOutput) const
-{
-  return (Output::DynObj == pOutput.type() &&
-         ResolveInfo::Function == pSym.type() &&
-         (pSym.isDyn() || pSym.isUndef()));
-}
-
-bool MipsGNULDBackend::isSymbolNeedsDynRel(ResolveInfo& pSym,
-                                           const Output& pOutput) const
-{
-  if(pSym.isUndef() && Output::Exec == pOutput.type())
-    return false;
-  if(pSym.isAbsolute())
-    return false;
-  if(Output::DynObj == pOutput.type())
-    return true;
-  if(pSym.isDyn() || pSym.isUndef())
-    return true;
-
-  return false;
-}
-
 void MipsGNULDBackend::createGOT(MCLinker& pLinker, const Output& pOutput)
 {
   ELFFileFormat* file_format = getOutputFormat(pOutput);
@@ -813,7 +849,7 @@
   m_pGOT = new MipsGOT(got, pLinker.getOrCreateSectData(got));
 
   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
-  if( m_pGOTSymbol != NULL ) {
+  if ( m_pGOTSymbol != NULL ) {
     pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
@@ -851,22 +887,6 @@
                                      8);
 }
 
-ELFFileFormat* MipsGNULDBackend::getOutputFormat(const Output& pOutput) const
-{
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      return getDynObjFileFormat();
-    case Output::Exec:
-      return getExecFileFormat();
-    case Output::Object:
-      return NULL;
-    default:
-      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
-                               llvm::Twine(pOutput.type()));
-      return NULL;
-  }
-}
-
 //===----------------------------------------------------------------------===//
 /// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
 ///
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
index c4f1d46..f9742ed 100644
--- a/lib/Target/Mips/MipsLDBackend.h
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -43,7 +43,7 @@
   void initTargetSections(MCLinker& pLinker);
 
   /// initTargetSymbols - initialize target dependent symbols in output.
-  void initTargetSymbols(MCLinker& pLinker);
+  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// initRelocFactory - create and initialize RelocationFactory.
   bool initRelocFactory(const MCLinker& pLinker);
@@ -58,7 +58,8 @@
                       const LDSymbol& pInputSym,
                       MCLinker& pLinker,
                       const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+                      const Output& pOutput,
+                      const LDSection& pSection);
 
   uint32_t machine() const;
 
@@ -75,6 +76,8 @@
 
   unsigned int bitclass() const;
 
+  uint64_t defaultTextSegmentAddr() const;
+
   /// preLayout - Backend can do any needed modification before layout
   void doPreLayout(const Output& pOutput,
                    const MCLDInfo& pInfo,
@@ -107,11 +110,13 @@
   /// @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,
                            MemoryRegion& pRegion) const;
 
   /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
@@ -128,12 +133,11 @@
 
   /// getTargetSectionOrder - compute the layout order of ARM target sections
   unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr) const;
+                                     const LDSection& pSectHdr,
+                                     const MCLDInfo& pInfo) const;
 
   /// finalizeSymbol - finalize the symbol value
-  /// If the symbol's reserved field is not zero, MCLinker will call back this
-  /// function to ask the final value of the symbol
-  bool finalizeSymbol(LDSymbol& pSymbol) const;
+  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// allocateCommonSymbols - allocate common symbols in the corresponding
   /// sections.
@@ -152,14 +156,9 @@
                       const MCLDInfo& pLDInfo,
                       const Output& pOutput);
 
-  bool isSymbolNeedsPLT(ResolveInfo& pSym, const Output& pOutput) const;
-  bool isSymbolNeedsDynRel(ResolveInfo& pSym, const Output& pOutput) const;
-
   void createGOT(MCLinker& pLinker, const Output& pOutput);
   void createRelDyn(MCLinker& pLinker, const Output& pOutput);
 
-  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
-
   /// 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
@@ -178,12 +177,11 @@
   LDSymbol* m_pGOTSymbol;
   LDSymbol* m_pGpDispSymbol;
 
-  std::vector<LDSymbol*> m_LocalGOTSyms;
   std::vector<LDSymbol*> m_GlobalGOTSyms;
 
 private:
-  /// isGOTSymbol - return true if the symbol is the GOT entry.
-  bool isGOTSymbol(const LDSymbol& pSymbol) const;
+  /// 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,
@@ -197,3 +195,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/Mips/MipsRelocationFactory.cpp b/lib/Target/Mips/MipsRelocationFactory.cpp
index e3a7793..948e026 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 <llvm/Support/ErrorHandling.h>
 #include <mcld/LD/Layout.h>
 #include <mcld/Target/OutputRelocSection.h>
+#include <mcld/Support/MsgHandling.h>
 
 #include "MipsRelocationFactory.h"
 #include "MipsRelocationFunctions.h"
@@ -54,32 +54,26 @@
   Relocation::Type type = pRelocation.type();
 
   if (type >= sizeof(apply_functions) / sizeof(apply_functions[0])) {
-    llvm::report_fatal_error(llvm::Twine("Unknown relocation type. "
-                                         "To symbol `") +
-                             pRelocation.symInfo()->name() +
-                             llvm::Twine("'."));
+    fatal(diag::unknown_relocation) << (int)type
+                                    << pRelocation.symInfo()->name();
   }
 
   // apply the relocation
   Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
 
   // check result
+  if (OK == result) {
+    return;
+  }
   if (Overflow == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' causes overflow. on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_overflow) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
 
   if (BadReloc == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' encounters unexpected opcode. "
-                                         "on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_badreloc) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
 }
@@ -90,26 +84,6 @@
 
 static const char * const GP_DISP_NAME = "_gp_disp";
 
-// Get an relocation entry in .rel.dyn and set its type to R_MIPS_REL32,
-// its FragmentRef to pReloc->targetFrag() and its ResolveInfo
-// to pReloc->symInfo()
-static
-void helper_SetRelDynEntry(Relocation& pReloc,
-                   MipsRelocationFactory& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  MipsGNULDBackend& ld_backend = pParent.getTarget();
-
-  bool exist;
-  Relocation& rel_entry =
-    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
-
-  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
-  rel_entry.targetRef() = pReloc.targetRef();
-  rel_entry.setSymInfo(0);
-}
-
 // Find next R_MIPS_LO16 relocation paired to pReloc.
 static
 Relocation* helper_FindLo16Reloc(Relocation& pReloc)
@@ -142,24 +116,27 @@
 
 static
 GOTEntry& helper_GetGOTEntry(Relocation& pReloc,
-                             MipsRelocationFactory& pParent)
+                             MipsRelocationFactory& pParent,
+                             bool& pExist, int32_t value)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   MipsGNULDBackend& ld_backend = pParent.getTarget();
+  MipsGOT& got = ld_backend.getGOT();
 
-  bool exist;
-  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
+  GOTEntry& got_entry = *got.getEntry(*rsym, pExist);
 
-  if (exist)
+  if (pExist)
     return got_entry;
 
   // If we first get this GOT entry, we should initialize it.
-  if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
-    got_entry.setContent(pReloc.symValue());
-  }
-  else {
-    llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+  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";
+    }
   }
 
   return got_entry;
@@ -169,7 +146,8 @@
 RelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc,
                                                MipsRelocationFactory& pParent)
 {
-  GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
+  bool exist;
+  GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
   return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
 }
 
@@ -196,6 +174,7 @@
 {
   ResolveInfo* rsym = pReloc.symInfo();
   MipsGNULDBackend& ld_backend = pParent.getTarget();
+  MipsGOT& got = ld_backend.getGOT();
 
   bool exist;
   Relocation& rel_entry =
@@ -203,7 +182,19 @@
 
   rel_entry.setType(llvm::ELF::R_MIPS_REL32);
   rel_entry.targetRef() = pReloc.targetRef();
-  rel_entry.setSymInfo(rsym->isLocal() ? NULL : rsym);
+
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  RelocationFactory::DWord S = pReloc.symValue();
+
+  if (got.isLocal(rsym)) {
+    rel_entry.setSymInfo(NULL);
+    pReloc.target() = A + S;
+  }
+  else {
+    rel_entry.setSymInfo(rsym);
+    // Don't add symbol value that will be resolved by the dynamic linker
+    pReloc.target() = A;
+  }
 }
 
 //=========================================//
@@ -227,14 +218,26 @@
 {
   ResolveInfo* rsym = pReloc.symInfo();
 
-  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
-    helper_DynRel(pReloc, pParent);
-  }
-
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   RelocationFactory::DWord S = pReloc.symValue();
 
-  pReloc.target() |= (S + A);
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    pReloc.target() = S + A;
+    return MipsRelocationFactory::OK;
+  }
+
+  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
+    helper_DynRel(pReloc, pParent);
+
+    return MipsRelocationFactory::OK;
+  }
+
+  pReloc.target() = (S + A);
 
   return MipsRelocationFactory::OK;
 }
@@ -279,17 +282,21 @@
                                    const MCLDInfo& pLDInfo,
                                    MipsRelocationFactory& pParent)
 {
-  int32_t AHL = pParent.getAHL();
   int32_t res = 0;
 
   if (helper_isGpDisp(pReloc)) {
     int32_t P = pReloc.place(pParent.getLayout());
     int32_t GP = helper_GetGP(pParent);
+    int32_t AHL = pParent.getAHL();
     res = AHL + GP - P + 4;
   }
   else {
     int32_t S = pReloc.symValue();
-    res = AHL + S;
+    // The previous AHL may be for other hi/lo pairs.
+    // We need to calcuate the lo part now.  It is easy.
+    // Remember to add the section offset to ALO.
+    int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend();
+    res = ALO + S;
   }
 
   pReloc.target() &= 0xFFFF0000;
@@ -307,6 +314,7 @@
                                     MipsRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
+  RelocationFactory::Address G = 0;
 
   if (rsym->isLocal()) {
     Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
@@ -317,13 +325,16 @@
 
     pParent.setAHL(AHL);
 
-    GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
-
     int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
-    got_entry.setContent(res);
-  }
+    bool exist;
+    GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
 
-  RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
+    got_entry.setContent(res);
+    G = pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
+  }
+  else {
+    G = helper_GetGOTOffset(pReloc, pParent);
+  }
 
   pReloc.target() &= 0xFFFF0000;
   pReloc.target() |= (G & 0xFFFF);
@@ -351,7 +362,8 @@
                                       const MCLDInfo& pLDInfo,
                                       MipsRelocationFactory& pParent)
 {
-  int32_t A = pReloc.target();
+  // Remember to add the section offset to A.
+  int32_t A = pReloc.target() + pReloc.addend();
   int32_t S = pReloc.symValue();
   int32_t GP = helper_GetGP(pParent);
 
diff --git a/lib/Target/Mips/MipsSectLinker.cpp b/lib/Target/Mips/MipsSectLinker.cpp
index af543c9..7a3082c 100644
--- a/lib/Target/Mips/MipsSectLinker.cpp
+++ b/lib/Target/Mips/MipsSectLinker.cpp
@@ -10,7 +10,7 @@
 #include <llvm/ADT/Triple.h>
 #include <mcld/Support/TargetRegistry.h>
 #include "Mips.h"
-#include "MipsAndroidSectLinker.h"
+#include "MipsELFSectLinker.h"
 
 using namespace mcld;
 
@@ -31,9 +31,7 @@
     assert(0 && "COFF linker has not supported yet");
   }
 
-  // For now, use Android SectLinker directly
-  return new MipsAndroidSectLinker(pOption,
-                                   pLDBackend);
+  return new MipsELFSectLinker(pOption, pLDBackend);
 }
 
 } // namespace of mcld
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
index 89b4f52..dbb8194 100644
--- a/lib/Target/OutputRelocSection.cpp
+++ b/lib/Target/OutputRelocSection.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/LDSection.h>
 #include <mcld/Target/OutputRelocSection.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
@@ -64,18 +65,18 @@
 
   if(isForGOT) {
     // get or create entry in m_SymRelMap
-    Relocation *&Entry = m_SymRelMap[&pSymbol];
-    pExist = 1;
+    Relocation *&entry = m_SymRelMap[&pSymbol];
+    pExist = true;
 
-    if(!Entry) {
-      pExist = 0;
-      Entry = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
+    if(NULL == entry) {
+      pExist = false;
+      entry = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
       ++m_ValidEntryIterator;
     }
-    result = Entry;
+    result = entry;
   }
   else {
-    pExist = 0;
+    pExist = false;
     result = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
     ++m_ValidEntryIterator;
   }
diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp
index 58178ec..ec8dc87 100644
--- a/lib/Target/Target.cpp
+++ b/lib/Target/Target.cpp
@@ -6,20 +6,19 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/Target/TargetMachine.h"
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Target/TargetMachine.h>
 #include <llvm/Support/TargetRegistry.h>
 #include <llvm/Target/TargetMachine.h>
 
 using namespace llvm;
-using namespace mcld;
 
-/* ** */
 mcld::Target::Target()
-  : TargetMachineCtorFn(0),
-    SectLinkerCtorFn(0),
-    TargetLDBackendCtorFn(0),
-    m_pT(0)
+  : TargetMachineCtorFn(NULL),
+    SectLinkerCtorFn(NULL),
+    TargetLDBackendCtorFn(NULL),
+    DiagnosticLineInfoCtorFn(NULL),
+    m_pT(NULL)
 {
 }
 
diff --git a/lib/Target/TargetLDBackend.cpp b/lib/Target/TargetLDBackend.cpp
index 1a8ab6b..4eda0a6 100644
--- a/lib/Target/TargetLDBackend.cpp
+++ b/lib/Target/TargetLDBackend.cpp
@@ -14,10 +14,24 @@
 
 /* ** */
 TargetLDBackend::TargetLDBackend()
-{
+  : m_pEhFrame(NULL) {
 }
 
 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/X86.h b/lib/Target/X86/X86.h
index c575d80..2d07314 100644
--- a/lib/Target/X86/X86.h
+++ b/lib/Target/X86/X86.h
@@ -21,3 +21,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86AndroidSectLinker.cpp b/lib/Target/X86/X86AndroidSectLinker.cpp
deleted file mode 100644
index fe7a2cc..0000000
--- a/lib/Target/X86/X86AndroidSectLinker.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- X86AndroidSectLinker.cpp -------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86AndroidSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-X86AndroidSectLinker::X86AndroidSectLinker(SectLinkerOption &pOption,
-                                           TargetLDBackend &pLDBackend)
-  : AndroidSectLinker(pOption,
-                      pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attibutes
-  info.attrFactory().constraint().disableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().unsetWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-
-}
-
-X86AndroidSectLinker::~X86AndroidSectLinker() {
-}
diff --git a/lib/Target/X86/X86AndroidSectLinker.h b/lib/Target/X86/X86AndroidSectLinker.h
deleted file mode 100644
index b275aca..0000000
--- a/lib/Target/X86/X86AndroidSectLinker.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- X86AndroidSectLinker.h ---------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef X86_ANDROIDSECTLINKER_H
-#define X86_ANDROIDSECTLINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/Target/AndroidSectLinker.h>
-
-namespace mcld
-{
-
-/** \class X86AndroidSectLinker
- *  \brief X86AndroidSectLinker sets up the environment for linking.
- *
- *  \see
- *  \author Anders Cheng <Anders.Cheng@mediatek.com>
- */
-class X86AndroidSectLinker : public AndroidSectLinker
-{
-public:
-  X86AndroidSectLinker(SectLinkerOption &pOption,
-                       mcld::TargetLDBackend &pLDBackend);
-
-  ~X86AndroidSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/X86/X86Diagnostic.cpp b/lib/Target/X86/X86Diagnostic.cpp
new file mode 100644
index 0000000..db12dde
--- /dev/null
+++ b/lib/Target/X86/X86Diagnostic.cpp
@@ -0,0 +1,38 @@
+//===- X86Diagnostic.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/DWARFLineInfo.h>
+#include "X86.h"
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// X86Diagnostic
+
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createX86Diagnostic - the help function to create corresponding X86Diagnostic
+//
+DiagnosticLineInfo* createX86DiagLineInfo(const llvm::Target& pTarget,
+                                          const std::string &pTriple)
+{
+  return new DWARFLineInfo();
+}
+
+} // namespace of mcld
+
+//==========================
+// InitializeX86Diagnostic
+extern "C" void LLVMInitializeX86DiagnosticLineInfo() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheX86Target, createX86DiagLineInfo);
+}
+
diff --git a/lib/Target/X86/X86ELFDynamic.cpp b/lib/Target/X86/X86ELFDynamic.cpp
index ee6b1f6..af86b2c 100644
--- a/lib/Target/X86/X86ELFDynamic.cpp
+++ b/lib/Target/X86/X86ELFDynamic.cpp
@@ -13,24 +13,25 @@
 using namespace mcld;
 
 X86ELFDynamic::X86ELFDynamic(const GNULDBackend& pParent)
-  : ELFDynamic(pParent), m_HasGOTPLT(false) {
+  : ELFDynamic(pParent)
+{
 }
 
-X86ELFDynamic::~X86ELFDynamic() {
+X86ELFDynamic::~X86ELFDynamic()
+{
 }
 
-void X86ELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat) {
+void X86ELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat)
+{
   // reservePLTGOT
-  if (m_HasGOTPLT ? pFormat.hasGOTPLT() : pFormat.hasGOT())
+  if (pFormat.hasGOTPLT())
     reserveOne(llvm::ELF::DT_PLTGOT);
 }
 
-void X86ELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat) {
+void X86ELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat)
+{
   // applyPLTGOT
-  if (m_HasGOTPLT) {
-      if (pFormat.hasGOTPLT())
-	applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOTPLT().addr());
-  }
-  else if (pFormat.hasGOT())
-    applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOT().addr());
+  if (pFormat.hasGOTPLT())
+	  applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOTPLT().addr());
 }
+
diff --git a/lib/Target/X86/X86ELFDynamic.h b/lib/Target/X86/X86ELFDynamic.h
index b9e70ce..7053a0b 100644
--- a/lib/Target/X86/X86ELFDynamic.h
+++ b/lib/Target/X86/X86ELFDynamic.h
@@ -25,12 +25,6 @@
 private:
   void reserveTargetEntries(const ELFFileFormat& pFormat);
   void applyTargetEntries(const ELFFileFormat& pFormat);
-
-private:
-  // True if we have .got.plt section, which will avoid GOT0 entries
-  // when PLT isn't used.  To support .got.plt section, we must combine
-  // .got section and .got.plt section into a single GOT.
-  bool m_HasGOTPLT;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
index 544b5e9..91c7d65 100644
--- a/lib/Target/X86/X86GOT.cpp
+++ b/lib/Target/X86/X86GOT.cpp
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include "X86GOT.h"
 #include <mcld/LD/LDFileFormat.h>
-#include <llvm/Support/ErrorHandling.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
@@ -21,36 +21,8 @@
 // X86GOT
 X86GOT::X86GOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
              : GOT(pSection, pSectionData, X86GOTEntrySize),
-               m_GeneralGOTNum(0), m_GOTPLTNum(0), m_GeneralGOTIterator(),
-               m_GOTPLTIterator(), m_LastGOT0()
+               m_GOTIterator(), m_fIsVisit(false)
 {
-  GOTEntry* Entry = 0;
-
-  // Create GOT0 entries.
-  for (unsigned int i = 0; i < X86GOT0Num; i++) {
-    Entry = new (std::nothrow) GOTEntry(0, X86GOTEntrySize,
-                                        &m_SectionData);
-
-    if (!Entry)
-      llvm::report_fatal_error("Allocating GOT0 entries failed!");
-
-    m_Section.setSize(m_Section.size() + X86GOTEntrySize);
-  }
-
-  // Skip GOT0 entries.
-  iterator it = m_SectionData.begin();
-  iterator ie = m_SectionData.end();
-
-  for (unsigned int i = 1; i < X86GOT0Num; ++i) {
-    if (it == ie)
-      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
-
-    ++it;
-  }
-
-  m_LastGOT0 = it;
-  m_GeneralGOTIterator = it;
-  m_GOTPLTIterator = it;
 }
 
 X86GOT::~X86GOT()
@@ -66,38 +38,37 @@
                                         &m_SectionData);
 
     if (!Entry)
-      llvm::report_fatal_error("Allocating new memory for GOTEntry failed");
+      fatal(diag::fail_allocate_memory) << "GOTEntry";
 
     m_Section.setSize(m_Section.size() + X86GOTEntrySize);
-    ++m_GeneralGOTNum;
   }
 }
 
 
 GOTEntry* X86GOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
 {
-  GOTEntry *&Entry = m_GeneralGOTMap[&pInfo];
+  // 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;
-
-    ++m_GeneralGOTIterator;
-    assert(m_GeneralGOTIterator != m_SectionData.getFragmentList().end()
-           && "The number of GOT Entries and ResolveInfo doesn't match!");
-
-    Entry = llvm::cast<GOTEntry>(&(*m_GeneralGOTIterator));
+    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;
 }
 
-void X86GOT::applyGOT0(uint64_t pAddress)
-{
-  llvm::cast<GOTEntry>
-    (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
-}
-
 X86GOT::iterator X86GOT::begin()
 {
   return m_SectionData.getFragmentList().begin();
@@ -118,11 +89,3 @@
   return m_SectionData.getFragmentList().end();
 }
 
-unsigned int X86GOT::getGOTPLTNum() const
-{ return m_GOTPLTNum; }
-
-X86GOT::iterator X86GOT::getLastGOT0()
-{ return m_LastGOT0; }
-
-const X86GOT::iterator X86GOT::getLastGOT0() const
-{ return m_LastGOT0; }
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
index 37b48a3..d758de0 100644
--- a/lib/Target/X86/X86GOT.h
+++ b/lib/Target/X86/X86GOT.h
@@ -23,18 +23,8 @@
  *  \brief X86 Global Offset Table.
  */
 
-const unsigned int X86GOT0Num = 3;
-
 class X86GOT : public GOT
 {
-  friend void mcld::X86PLT::reserveEntry(size_t pNum);
-
-  friend mcld::PLTEntry* mcld::X86PLT::getPLTEntry(
-         const mcld::ResolveInfo& pSymbol,bool& pExist);
-
-  friend mcld::GOTEntry* mcld::X86PLT::getGOTPLTEntry(
-         const mcld::ResolveInfo& pSymbol,bool& pExist);
-
   typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
 
 public:
@@ -51,8 +41,6 @@
 
   GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
 
-  void applyGOT0(uint64_t pAddress);
-
   iterator begin();
 
   const_iterator begin() const;
@@ -61,30 +49,17 @@
 
   const_iterator end() const;
 
-  unsigned int getGOTPLTNum() const;
-
-  iterator getLastGOT0();
-
-  const iterator getLastGOT0() const;
-
 private:
+  /// m_GOTIterator - point to the first valid entry in GOT list
+  iterator m_GOTIterator;
 
-  unsigned int m_GeneralGOTNum;
-  unsigned int m_GOTPLTNum;
+  /// m_fIsVisit - first time visit the function getEntry() or not
+  bool m_fIsVisit;
 
-  // Used by getGeneralGOTEntry()
-  iterator m_GeneralGOTIterator;
-
-  // Used by getGOTPLTEntry()
-  iterator m_GOTPLTIterator;
-
-  // The last GOT0 entry
-  iterator m_LastGOT0;
-
-  SymbolIndexMapType m_GOTPLTMap;
-  SymbolIndexMapType m_GeneralGOTMap;
+  SymbolIndexMapType m_GOTMap;
 };
 
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index 55596e3..960c86b 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 #include "X86GOTPLT.h"
-#include "mcld/LD/LDFileFormat.h"
-#include <llvm/Support/ErrorHandling.h>
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
@@ -25,12 +25,12 @@
   GOTEntry* Entry = 0;
 
   // Create GOT0 entries.
-  for (int i = 0; i < 3; i++) {
+  for (size_t i = 0; i < X86GOTPLT0Num; i++) {
     Entry = new (std::nothrow) GOTEntry(0, X86GOTPLTEntrySize,
                                         &m_SectionData);
 
     if (!Entry)
-      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+      fatal(diag::fail_allocate_memory) << "GOT0";
 
     m_Section.setSize(m_Section.size() + X86GOTPLTEntrySize);
   }
@@ -39,9 +39,8 @@
   iterator it = m_SectionData.begin();
   iterator ie = m_SectionData.end();
 
-  for (size_t i = 1; i < X86GOT0Num; ++i) {
-    if (it == ie)
-      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
+  for (size_t i = 1; i < X86GOTPLT0Num; ++i) {
+    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
 
     ++it;
   }
@@ -73,31 +72,38 @@
   return m_SectionData.end();
 }
 
-void X86GOTPLT::applyGOT0(const uint64_t pAddress)
+void X86GOTPLT::applyGOT0(uint64_t pAddress)
 {
   llvm::cast<GOTEntry>
     (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
 }
 
-void X86GOTPLT::reserveGOTPLTEntry()
+void X86GOTPLT::reserveEntry(size_t pNum)
 {
-    GOTEntry* got_entry = 0;
-
-    got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
-
+  GOTEntry* got_entry = NULL;
+  for (size_t i = 0; i < pNum; ++i) {
+    got_entry = new GOTEntry(0, getEntrySize(),&(getSectionData()));
     if (!got_entry)
-      llvm::report_fatal_error("Allocating new memory for GOT failed!");
+      fatal(diag::fail_allocate_memory) << "GOT";
 
     m_Section.setSize(m_Section.size() + getEntrySize());
+  }
 }
 
-void X86GOTPLT::applyAllGOTPLT(const uint64_t pPLTBase)
+void X86GOTPLT::applyAllGOTPLT(uint64_t pPLTBase,
+                               unsigned int pPLT0Size,
+                               unsigned int pPLT1Size)
 {
-  iterator gotplt_it = begin();
-  iterator gotplt_ie = end();
-
-  for (; gotplt_it != gotplt_ie; ++gotplt_it)
-    llvm::cast<GOTEntry>(*gotplt_it).setContent(pPLTBase);
+  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;
+  for (; it != end() ; ++it) {
+    llvm::cast<GOTEntry>(*it).setContent(plt_addr + 6);
+    plt_addr += pPLT1Size;
+  }
 }
 
 GOTEntry*& X86GOTPLT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
@@ -105,9 +111,22 @@
   return m_GOTPLTMap[&pSymbol];
 }
 
-X86GOTPLT::iterator X86GOTPLT::getNextGOTPLTEntry()
+GOTEntry* X86GOTPLT::getEntry(const ResolveInfo& pInfo, bool& pExist)
 {
-  return ++m_GOTPLTIterator;
+  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 04bfad0..ae9f0f7 100644
--- a/lib/Target/X86/X86GOTPLT.h
+++ b/lib/Target/X86/X86GOTPLT.h
@@ -12,7 +12,7 @@
 #include <gtest.h>
 #endif
 
-#include "mcld/Target/GOT.h"
+#include <mcld/Target/GOT.h>
 
 namespace mcld
 {
@@ -22,7 +22,7 @@
  *  \brief X86 .got.plt section.
  */
 
-const unsigned int X86GOT0Num = 3;
+const unsigned int X86GOTPLT0Num = 3;
 
 class X86GOTPLT : public GOT
 {
@@ -47,18 +47,20 @@
 
 // For GOT0
 public:
-  void applyGOT0(const uint64_t pAddress);
+  void applyGOT0(uint64_t pAddress);
 
 // For GOTPLT
 public:
-  void reserveGOTPLTEntry();
+  void reserveEntry(size_t pNum = 1);
 
-  void applyAllGOTPLT(const uint64_t pPLTBase);
+  GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
+
+  void applyAllGOTPLT(uint64_t pPLTBase,
+                      unsigned int pPLT0Size,
+                      unsigned int pPLT1Size);
 
   GOTEntry*& lookupGOTPLTMap(const ResolveInfo& pSymbol);
 
-  iterator getNextGOTPLTEntry();
-
 private:
   iterator m_GOTPLTIterator;
   SymbolIndexMapType m_GOTPLTMap;
@@ -67,3 +69,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index 354cd51..79d160e 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -13,13 +13,14 @@
 #include "X86RelocationFactory.h"
 
 #include <llvm/ADT/Triple.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/SectionMap.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/MC/MCLDOutput.h>
 #include <mcld/MC/MCLinker.h>
-#include <mcld/LD/SectionMap.h>
 #include <mcld/MC/MCRegionFragment.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/TargetRegistry.h>
 
 #include <cstring>
 
@@ -29,6 +30,7 @@
   : m_pRelocFactory(NULL),
     m_pGOT(NULL),
     m_pPLT(NULL),
+    m_pGOTPLT(NULL),
     m_pRelDyn(NULL),
     m_pRelPLT(NULL),
     m_pDynamic(NULL) {
@@ -42,6 +44,8 @@
     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)
@@ -70,17 +74,15 @@
                                   MCLinker& pLinker)
 {
   // when building shared object, the .got section is needed
-  if(pOutput.type() == Output::DynObj && (NULL == m_pGOT))
-      createX86GOT(pLinker, pOutput);
+  if (Output::DynObj == pOutput.type() && (NULL == m_pGOTPLT)) {
+    createX86GOTPLT(pLinker, pOutput);
+  }
 }
 
 void X86GNULDBackend::doPostLayout(const Output& pOutput,
                                    const MCLDInfo& pInfo,
                                    MCLinker& pLinker)
 {
-  // emit program headers
-  if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
-    emitProgramHdrs(pLinker.getLDInfo().output());
 }
 
 /// dynamic - the dynamic section of the target machine.
@@ -108,9 +110,18 @@
 
   LDSection& got = file_format->getGOT();
   m_pGOT = new X86GOT(got, pLinker.getOrCreateSectData(got));
+}
 
-  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
-  if( m_pGOTSymbol != NULL ) {
+void X86GNULDBackend::createX86GOTPLT(MCLinker& pLinker, const Output& pOutput)
+{
+  // get .got.plt LDSection and create MCSectionData
+  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
+  if (m_pGOTSymbol != NULL) {
     pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
@@ -119,7 +130,8 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
+                                                         0x0),
                      ResolveInfo::Hidden);
   }
   else {
@@ -131,7 +143,8 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
+                                                          0x0),
                      ResolveInfo::Hidden);
   }
 }
@@ -143,8 +156,9 @@
 
   LDSection& plt = file_format->getPLT();
   LDSection& relplt = file_format->getRelPlt();
+  assert(m_pGOTPLT != NULL);
   // create MCSectionData and X86PLT
-  m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT, pOutput);
+  m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOTPLT, pOutput);
 
   // set info of .rel.plt to .plt
   relplt.setLink(&plt);
@@ -167,63 +181,73 @@
                                      8);
 }
 
-ELFFileFormat* X86GNULDBackend::getOutputFormat(const Output& pOutput) const
+void X86GNULDBackend::addCopyReloc(ResolveInfo& pSym)
 {
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      return getDynObjFileFormat();
-    case Output::Exec:
-      return getExecFileFormat();
-    // FIXME: We do not support building .o now
-    case Output::Object:
-    default:
-      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
-                               llvm::Twine(pOutput.type()));
-      return NULL;
+  bool exist;
+  Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
+  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,
+                                                    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);
+  }
 
-bool X86GNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym,
-                                       const MCLDInfo& pLDInfo,
-                                       const Output& pOutput) const
-{
-  return((Output::DynObj == pOutput.type())
-         &&(ResolveInfo::Function == pSym.type())
-         &&(pSym.isDyn() || pSym.isUndef() ||
-            isSymbolPreemptible(pSym, pLDInfo, pOutput))
-        );
-}
+  // get or create corresponding BSS MCSectionData
+  assert(NULL != bss_sect_hdr);
+  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(
+                                     *bss_sect_hdr);
 
-bool X86GNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym,
-                                          const Output& pOutput,
-                                          bool isAbsReloc) const
-{
-  if(pSym.isUndef() && (pOutput.type()==Output::Exec))
-    return false;
-  if(pSym.isAbsolute())
-    return false;
-  if(pOutput.type()==Output::DynObj && isAbsReloc)
-    return true;
-  if(pSym.isDyn() || pSym.isUndef())
-    return true;
+  // Determine the alignment by the symbol value
+  // FIXME: here we use the largest alignment
+  uint32_t addralign = bitclass() / 8;
 
-  return false;
-}
+  // allocate space in BSS for the copy symbol
+  llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, pSym.size());
+  uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                     bss_section,
+                                                     addralign);
+  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
 
-bool X86GNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
-                                         const MCLDInfo& pLDInfo,
-                                         const Output& pOutput) const
-{
-  if(pSym.other() != ResolveInfo::Default)
-    return false;
+  // change symbol binding to Global if it's a weak symbol
+  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
+  if (binding == ResolveInfo::Weak)
+    binding = ResolveInfo::Global;
 
-  if(pOutput.type() != Output::DynObj)
-    return false;
+  // Define the copy symbol in the bss section and resolve it
+  LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+                      pSym.name(),
+                      false,
+                      (ResolveInfo::Type)pSym.type(),
+                      ResolveInfo::Define,
+                      binding,
+                      pSym.size(),  // size
+                      0x0,          // value
+                      pLinker.getLayout().getFragmentRef(*frag, 0x0),
+                      (ResolveInfo::Visibility)pSym.other());
 
-  if(pLDInfo.options().Bsymbolic())
-    return false;
-
-  return true;
+  return *cpy_sym;
 }
 
 void X86GNULDBackend::updateAddend(Relocation& pReloc,
@@ -231,7 +255,7 @@
                                    const Layout& pLayout) const
 {
   // Update value keep in addend if we meet a section symbol
-  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
     pReloc.setAddend(pLayout.getOutputOffset(
                      *pInputSym.fragRef()) + pReloc.addend());
   }
@@ -254,9 +278,9 @@
       // 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(Output::DynObj == pOutput.type()) {
+      if (isOutputPIC(pOutput, pLDInfo)) {
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createX86RelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set Rel bit
@@ -267,7 +291,7 @@
     case llvm::ELF::R_386_GOTOFF:
     case llvm::ELF::R_386_GOTPC:
       // A GOT section is needed
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createX86GOT(pLinker, pOutput);
       return;
 
@@ -275,9 +299,8 @@
       return;
 
     default:
-      llvm::report_fatal_error(llvm::Twine("unexpected reloc ") +
-                               llvm::Twine((int) pReloc.type()) +
-                               llvm::Twine(" in object file"));
+      fatal(diag::unsupported_relocation) << (int)pReloc.type()
+                                          << "mclinker@googlegroups.com";
       break;
   } // end switch
 }
@@ -295,14 +318,14 @@
     case llvm::ELF::R_386_32:
       // Absolute relocation type, symbol may needs PLT entry or
       // dynamic relocation entry
-      if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
         // create plt for this symbol if it does not have one
-        if(!(rsym->reserved() & ReservePLT)){
+        if (!(rsym->reserved() & ReservePLT)){
           // Create .got section if it dosen't exist
-          if(NULL == m_pGOT)
-             createX86GOT(pLinker, pOutput);
+          if (NULL == m_pGOTPLT)
+            createX86GOTPLT(pLinker, pOutput);
           // create .plt and .rel.plt if not exist
-          if(NULL == m_pPLT)
+          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
@@ -315,21 +338,29 @@
         }
       }
 
-      if(isSymbolNeedsDynRel(*rsym, pOutput, true)) {
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                            pLDInfo, pOutput, true)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createX86RelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | ReserveRel);
+        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
+                          pOutput)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+        }
       }
       return;
 
     case llvm::ELF::R_386_GOTOFF:
     case llvm::ELF::R_386_GOTPC: {
       // A GOT section is needed
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createX86GOT(pLinker, pOutput);
       return;
     }
@@ -338,21 +369,21 @@
       // A PLT entry is needed when building shared library
 
       // return if we already create plt for this symbol
-      if(rsym->reserved() & ReservePLT)
+      if (rsym->reserved() & ReservePLT)
         return;
 
       // if symbol is defined in the ouput file and it's not
       // preemptible, no need plt
-      if(rsym->isDefine() && !rsym->isDyn() &&
+      if (rsym->isDefine() && !rsym->isDyn() &&
          !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
         return;
       }
 
       // Create .got section if it dosen't exist
-      if(NULL == m_pGOT)
-         createX86GOT(pLinker, pOutput);
+      if (NULL == m_pGOTPLT)
+         createX86GOTPLT(pLinker, pOutput);
       // create .plt and .rel.plt if not exist
-      if(NULL == m_pPLT)
+      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
@@ -367,17 +398,17 @@
     case llvm::ELF::R_386_GOT32:
       // Symbol needs GOT entry, reserve entry in .got
       // return if we already create GOT for this symbol
-      if(rsym->reserved() & (ReserveGOT | GOTRel))
+      if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createX86GOT(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()) {
+      if (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createX86RelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
@@ -389,15 +420,49 @@
       return;
 
     case llvm::ELF::R_386_PC32:
-      // We allow R_386_PC32 only if it isn't preemptible.  Otherwise
-      // we will generate writable text section in output.
-      if (!isSymbolPreemptible(*rsym, pLDInfo, pOutput))
-	return;
 
+      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput) &&
+          pOutput.type() != Output::DynObj) {
+        // 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_pRelPLT->reserveEntry(*m_pRelocFactory);
+          // set PLT bit
+          rsym->setReserved(rsym->reserved() | ReservePLT);
+        }
+      }
+
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                            pLDInfo, pOutput, 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)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+        }
+      }
+      return;
     default: {
-      llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") +
-                               llvm::Twine((int) pReloc.type()) +
-                               llvm::Twine(" in object file"));
+      fatal(diag::unsupported_relocation) << (int)pReloc.type()
+                                          << "mclinker@googlegroups.com";
       break;
     }
   } // end switch
@@ -407,27 +472,36 @@
                                      const LDSymbol& pInputSym,
                                      MCLinker& pLinker,
                                      const MCLDInfo& pLDInfo,
-                                     const Output& pOutput)
+                                     const Output& pOutput,
+                                     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;
+  }
+
   // 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 concren 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()) {
-      createX86GOT(pLinker, pOutput);
+  // 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);
     }
   }
 
   // rsym is local
-  if(rsym->isLocal())
+  if (rsym->isLocal())
     scanLocalReloc(pReloc, pInputSym,  pLinker, pLDInfo, pOutput);
 
   // rsym is external
@@ -439,11 +513,12 @@
 uint64_t X86GNULDBackend::emitSectionData(const Output& pOutput,
                                           const LDSection& pSection,
                                           const MCLDInfo& pInfo,
+                                          const Layout& pLayout,
                                           MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  ELFFileFormat* FileFormat = getOutputFormat(pOutput);
+  const ELFFileFormat* FileFormat = getOutputFormat(pOutput);
   assert(FileFormat &&
          "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
 
@@ -479,8 +554,6 @@
   else if (&pSection == &(FileFormat->getGOT())) {
     assert(m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
 
-    m_pGOT->applyGOT0(FileFormat->getDynamic().addr());
-
     uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
 
     GOTEntry* got = 0;
@@ -494,10 +567,28 @@
     }
   }
 
-  else
-    llvm::report_fatal_error("unsupported section name "
-                             + pSection.name() + " !");
+  else if (&pSection == &(FileFormat->getGOTPLT())) {
+    assert(m_pGOTPLT && "emitSectionData failed, m_pGOTPLT is NULL!");
+    m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
 
+    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+
+    GOTEntry* 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)));
+      *buffer = static_cast<uint32_t>(got->getContent());
+      RegionSize += EntrySize;
+    }
+  }
+
+  else {
+    fatal(diag::unrecognized_output_sectoin)
+            << pSection.name()
+            << "mclinker@googlegroups.com";
+  }
   return RegionSize;
 }
 uint32_t X86GNULDBackend::machine() const
@@ -517,6 +608,18 @@
   return *m_pGOT;
 }
 
+X86GOTPLT& X86GNULDBackend::getGOTPLT()
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
+const X86GOTPLT& X86GNULDBackend::getGOTPLT() const
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
 X86PLT& X86GNULDBackend::getPLT()
 {
   assert(NULL != m_pPLT && "PLT section not exist");
@@ -555,17 +658,22 @@
 
 unsigned int
 X86GNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr) const
+                                       const LDSection& pSectHdr,
+                                       const MCLDInfo& pInfo) const
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
-  // FIXME: if command line option, "-z now", is given, we can let the order of
-  // .got and .got.plt be the same as RELRO sections
-  if (&pSectHdr == &file_format->getGOT())
+  if (&pSectHdr == &file_format->getGOT()) {
+    if (pInfo.options().hasNow())
+      return SHO_RELRO;
     return SHO_RELRO_LAST;
+  }
 
-  if (&pSectHdr == &file_format->getGOTPLT())
+  if (&pSectHdr == &file_format->getGOTPLT()) {
+    if (pInfo.options().hasNow())
+      return SHO_RELRO;
     return SHO_NON_RELRO_FIRST;
+  }
 
   if (&pSectHdr == &file_format->getPLT())
     return SHO_PLT;
@@ -587,7 +695,7 @@
 {
 }
 
-void X86GNULDBackend::initTargetSymbols(MCLinker& 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
@@ -604,113 +712,8 @@
 }
 
 /// finalizeSymbol - finalize the symbol value
-/// If the symbol's reserved field is not zero, MCLinker will call back this
-/// function to ask the final value of the symbol
-bool X86GNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+bool X86GNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
-  return false;
-}
-
-/// allocateCommonSymbols - allocate common symbols in the corresponding
-/// sections.
-/// @refer Google gold linker: common.cc: 214
-bool
-X86GNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
-{
-  // SymbolCategory contains all symbols that must emit to the output files.
-  // We are not like Google gold linker, we don't remember symbols before symbol
-  // resolution. All symbols in SymbolCategory are already resolved. Therefore, we
-  // don't need to care about some symbols may be changed its category due to symbol
-  // resolution.
-  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
-
-  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
-    return true;
-
-  // addralign := max value of all common symbols
-  uint64_t addralign = 0x0;
-
-  // Due to the visibility, some common symbols may be forcefully local.
-  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      if ((*com_sym)->value() > addralign)
-        addralign = (*com_sym)->value();
-    }
-  }
-
-  // global common symbols.
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    if ((*com_sym)->value() > addralign)
-      addralign = (*com_sym)->value();
-  }
-
-  // FIXME: If the order of common symbols is defined, then sort common symbols
-  // com_sym = symbol_list.commonBegin();
-  // std::sort(com_sym, com_end, some kind of order);
-
-  // get or create corresponding BSS LDSection
-  LDSection* bss_sect_hdr = NULL;
-  if (ResolveInfo::ThreadLocal == (*com_sym)->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);
-  }
-
-  // get or create corresponding BSS MCSectionData
-  assert(NULL != bss_sect_hdr);
-  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
-
-  // allocate all common symbols
-  uint64_t offset = bss_sect_hdr->size();
-
-  // allocate all local common symbols
-  com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      // We have to reset the description of the symbol here. When doing
-      // incremental linking, the output relocatable object may have common
-      // symbols. Therefore, we can not treat common symbols as normal symbols
-      // when emitting the regular name pools. We must change the symbols'
-      // description here.
-      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-      uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                         bss_section,
-                                                         (*com_sym)->value());
-      offset += size;
-    }
-  }
-
-  // allocate all global common symbols
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    // We have to reset the description of the symbol here. When doing
-    // incremental linking, the output relocatable object may have common
-    // symbols. Therefore, we can not treat common symbols as normal symbols
-    // when emitting the regular name pools. We must change the symbols'
-    // description here.
-    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-    uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                       bss_section,
-                                                       (*com_sym)->value());
-    offset += size;
-  }
-
-  bss_sect_hdr->setSize(offset);
-  symbol_list.changeCommonsToGlobal();
   return true;
 }
 
diff --git a/lib/Target/X86/X86LDBackend.h b/lib/Target/X86/X86LDBackend.h
index a745999..7264c40 100644
--- a/lib/Target/X86/X86LDBackend.h
+++ b/lib/Target/X86/X86LDBackend.h
@@ -11,6 +11,7 @@
 
 #include "X86ELFDynamic.h"
 #include "X86GOT.h"
+#include "X86GOTPLT.h"
 #include "X86PLT.h"
 #include <mcld/LD/LDSection.h>
 #include <mcld/Target/GNULDBackend.h>
@@ -82,6 +83,10 @@
 
   const X86GOT& getGOT() const;
 
+  X86GOTPLT& getGOTPLT();
+
+  const X86GOTPLT& getGOTPLT() const;
+
   X86PLT& getPLT();
 
   const X86PLT& getPLT() const;
@@ -120,11 +125,13 @@
   /// @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,
                            MemoryRegion& pRegion) const;
 
   /// OSABI - the value of e_ident[EI_OSABI]
@@ -142,6 +149,9 @@
   uint64_t flags() const
   { return 0x0; }
 
+  uint64_t defaultTextSegmentAddr() const
+  { return 0x08048000; }
+
   /// initTargetSectionMap - initialize target dependent section mapping
   bool initTargetSectionMap(SectionMap& pSectionMap);
 
@@ -150,7 +160,7 @@
 
   void initTargetSections(MCLinker& pLinker);
 
-  void initTargetSymbols(MCLinker& pLinker);
+  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// scanRelocation - determine the empty entries are needed or not and create
   /// the empty entries if needed.
@@ -162,7 +172,8 @@
                       const LDSymbol& pInputSym,
                       MCLinker& pLinker,
                       const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+                      const Output& pOutput,
+                      const LDSection& pSection);
 
   OutputRelocSection& getRelDyn();
 
@@ -174,21 +185,11 @@
 
   /// getTargetSectionOrder - compute the layout order of X86 target sections
   unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr) const;
+                                     const LDSection& pSectHdr,
+                                     const MCLDInfo& pInfo) const;
 
-  /// finalizeSymbol - finalize the symbol value
-  /// If the symbol's reserved field is not zero, MCLinker will call back this
-  /// function to ask the final value of the symbol
-  bool finalizeSymbol(LDSymbol& pSymbol) const;
-
-  /// allocateCommonSymbols - allocate common symbols in the corresponding
-  /// sections.
-  bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
-
-public:
-  bool isSymbolPreemptible(const ResolveInfo& pSym,
-                           const MCLDInfo& pLDInfo,
-                           const Output& pOutput) const;
+  /// finalizeTargetSymbols - finalize the symbol value
+  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
 private:
   void scanLocalReloc(Relocation& pReloc,
@@ -203,28 +204,30 @@
                        const MCLDInfo& pLDInfo,
                        const Output& pOutput);
 
-  bool isSymbolNeedsPLT(const ResolveInfo& pSym,
-                        const MCLDInfo& pLDInfo,
-                        const Output& pOutput) const;
+  /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
+  /// @param pSym - A resolved copy symbol that defined in BSS section
+  void addCopyReloc(ResolveInfo& pSym);
 
-  bool isSymbolNeedsDynRel(const ResolveInfo& pSym,
-                           const Output& pOutput,
-                           bool isAbsReloc) const;
+  /// 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,
+                                     const ResolveInfo& pSym);
 
   void updateAddend(Relocation& pReloc,
                     const LDSymbol& pInputSym,
                     const Layout& pLayout) const;
 
   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);
 
-  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
-
 private:
   RelocationFactory* m_pRelocFactory;
   X86GOT* m_pGOT;
   X86PLT* m_pPLT;
+  X86GOTPLT* m_pGOTPLT;
   /// m_RelDyn - dynamic relocation table of .rel.dyn
   OutputRelocSection* m_pRelDyn;
   /// m_RelPLT - dynamic relocation table of .rel.plt
@@ -254,3 +257,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index e9f9db1..caf6f32 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -6,38 +6,38 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "X86GOT.h"
+#include "X86GOTPLT.h"
 #include "X86PLT.h"
 #include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <llvm/Support/ELF.h>
 #include <mcld/MC/MCLDOutput.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
 
 const uint8_t x86_dyn_plt0[] = {
-  0xff, 0xb3, 0x04, 0, 0, 0,		// pushl  0x4(%ebx)
-  0xff, 0xa3, 0x08, 0, 0, 0,		// jmp    *0x8(%ebx)
-  0xf, 0x1f, 0x4, 0			// nopl   0(%eax)
+  0xff, 0xb3, 0x04, 0, 0, 0, // pushl  0x4(%ebx)
+  0xff, 0xa3, 0x08, 0, 0, 0, // jmp    *0x8(%ebx)
+  0x0f, 0x1f, 0x4,  0        // nopl   0(%eax)
 };
 
 const uint8_t x86_dyn_plt1[] = {
-  0xff, 0xa3, 0, 0, 0, 0,		// jmp    *sym@GOT(%ebx)
-  0x68, 0, 0, 0, 0,			// pushl  $offset
-  0xe9, 0, 0, 0, 0			// jmp    plt0
+  0xff, 0xa3, 0, 0, 0, 0,    // jmp    *sym@GOT(%ebx)
+  0x68, 0, 0, 0, 0,          // pushl  $offset
+  0xe9, 0, 0, 0, 0           // jmp    plt0
 };
 
 const uint8_t x86_exec_plt0[] = {
-  0xff, 0x35, 0, 0, 0, 0,		// pushl  .got + 4
-  0xff, 0x25, 0, 0, 0, 0,		// jmp    *(.got + 8)
-  0xf, 0x1f, 0x4, 0			// nopl   0(%eax)
+  0xff, 0x35, 0, 0, 0, 0,    // pushl  .got + 4
+  0xff, 0x25, 0, 0, 0, 0,    // jmp    *(.got + 8)
+  0x0f, 0x1f, 0x4, 0         // nopl   0(%eax)
 };
 
 const uint8_t x86_exec_plt1[] = {
-  0xff, 0x25, 0, 0, 0, 0,		// jmp    *(sym in .got)
-  0x68, 0, 0, 0, 0,			// pushl  $offset
-  0xe9, 0, 0, 0, 0			// jmp    plt0
+  0xff, 0x25, 0, 0, 0, 0,    // jmp    *(sym in .got)
+  0x68, 0, 0, 0, 0,          // pushl  $offset
+  0xe9, 0, 0, 0, 0           // jmp    plt0
 };
 
 }
@@ -55,9 +55,12 @@
 
 X86PLT::X86PLT(LDSection& pSection,
                llvm::MCSectionData& pSectionData,
-               X86GOT &pGOTPLT,
-	       const Output& pOutput)
-  : PLT(pSection, pSectionData), m_GOT(pGOTPLT), m_PLTEntryIterator()
+               X86GOTPLT &pGOTPLT,
+               const Output& pOutput)
+  : PLT(pSection, pSectionData),
+    m_GOTPLT(pGOTPLT),
+    m_PLTEntryIterator(),
+    m_Output(pOutput)
 {
   assert (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type());
   if (Output::DynObj == pOutput.type()) {
@@ -86,26 +89,17 @@
 void X86PLT::reserveEntry(size_t pNum)
 {
   X86PLT1* plt1_entry = 0;
-  GOTEntry* got_entry = 0;
 
   for (size_t i = 0; i < pNum; ++i) {
     plt1_entry = new (std::nothrow) X86PLT1(&m_SectionData, m_PLT1Size);
 
     if (!plt1_entry)
-      llvm::report_fatal_error("Allocating new memory for X86PLT1 failed!");
+      fatal(diag::fail_allocate_memory) << "X86PLT1";
 
     m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
 
-    got_entry= new (std::nothrow) GOTEntry(0, m_GOT.getEntrySize(),
-                                           &(m_GOT.m_SectionData));
-
-    if (!got_entry)
-      llvm::report_fatal_error("Allocating new memory for GOT failed!");
-
-    m_GOT.m_Section.setSize(m_GOT.m_Section.size() + m_GOT.f_EntrySize);
-
-    ++(m_GOT.m_GOTPLTNum);
-    ++(m_GOT.m_GeneralGOTIterator);
+    // reserve corresponding entry in .got.plt
+    m_GOTPLT.reserveEntry(pNum);
   }
 }
 
@@ -116,47 +110,20 @@
    pExist = 1;
 
    if (!PLTEntry) {
-     GOTEntry *&GOTPLTEntry = m_GOT.m_GOTPLTMap[&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");
-     ++(m_GOT.m_GOTPLTIterator);
-
      PLTEntry = llvm::cast<X86PLT1>(&(*m_PLTEntryIterator));
-     GOTPLTEntry = llvm::cast<GOTEntry>(&(*(m_GOT.m_GOTPLTIterator)));
    }
-
    return PLTEntry;
 }
 
 GOTEntry* X86PLT::getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
 {
-   GOTEntry *&GOTPLTEntry = m_GOT.m_GOTPLTMap[&pSymbol];
-
-   pExist = 1;
-
-   if (!GOTPLTEntry) {
-     X86PLT1 *&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");
-     ++(m_GOT.m_GOTPLTIterator);
-
-     PLTEntry = llvm::cast<X86PLT1>(&(*m_PLTEntryIterator));
-     GOTPLTEntry = llvm::cast<GOTEntry>(&(*(m_GOT.m_GOTPLTIterator)));
-   }
-
-   return GOTPLTEntry;
+   return m_GOTPLT.getEntry(pSymbol, pExist);
 }
 
 X86PLT0* X86PLT::getPLT0() const {
@@ -185,12 +152,12 @@
   data = static_cast<unsigned char*>(malloc(plt0->getEntrySize()));
 
   if (!data)
-    llvm::report_fatal_error("Allocating new memory for plt0 failed!");
+    fatal(diag::fail_allocate_memory) << "plt0";
 
   memcpy(data, m_PLT0, plt0->getEntrySize());
 
   if (m_PLT0 == x86_exec_plt0) {
-    uint64_t got_base = m_GOT.getSection().addr();
+    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;
@@ -207,17 +174,17 @@
   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_GOTPLT.getSection().addr();
   assert(got_base && ".got base address is NULL!");
 
   X86PLT::iterator it = m_SectionData.begin();
   X86PLT::iterator ie = m_SectionData.end();
   assert(it!=ie && "FragmentList is empty, applyPLT1 failed!");
 
-  uint64_t GOTEntrySize = m_GOT.getEntrySize();
+  uint64_t GOTEntrySize = m_GOTPLT.getEntrySize();
 
   // Skip GOT0
-  uint64_t GOTEntryOffset = GOTEntrySize * X86GOT0Num;
+  uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
 
   //skip PLT0
   uint64_t PLTEntryOffset = m_PLT0Size;
@@ -233,14 +200,19 @@
     data = static_cast<unsigned char*>(malloc(plt1->getEntrySize()));
 
     if (!data)
-      llvm::report_fatal_error("Allocating new memory for plt1 failed!");
+      fatal(diag::fail_allocate_memory) << "plt1";
 
     memcpy(data, m_PLT1, plt1->getEntrySize());
 
     uint32_t* offset;
 
     offset = reinterpret_cast<uint32_t*>(data + 2);
-    *offset = GOTEntryOffset;
+    if (m_Output.type() == Output::DynObj) {
+      *offset = GOTEntryOffset;
+    } else {
+      // Exec
+      *offset = got_base + GOTEntryOffset;
+    }
     GOTEntryOffset += GOTEntrySize;
 
     offset = reinterpret_cast<uint32_t*>(data + 7);
@@ -255,24 +227,9 @@
     ++it;
   }
 
-  unsigned int GOTPLTNum = m_GOT.getGOTPLTNum();
-
-  if (GOTPLTNum != 0) {
-    X86GOT::iterator gotplt_it = m_GOT.getLastGOT0();
-    X86GOT::iterator list_ie = m_GOT.getSectionData().getFragmentList().end();
-
-    ++gotplt_it;
-    uint64_t PLTEntryAddress = plt_base + m_PLT0Size;
-    for (unsigned int i = 0; i < GOTPLTNum; ++i) {
-      if (gotplt_it == list_ie)
-        llvm::report_fatal_error(
-          "The number of got.plt entries is inconsistent!");
-
-      llvm::cast<GOTEntry>(*gotplt_it).setContent(PLTEntryAddress + 6);
-      PLTEntryAddress += m_PLT1Size;
-      ++gotplt_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 dd72f52..6c7002a 100644
--- a/lib/Target/X86/X86PLT.h
+++ b/lib/Target/X86/X86PLT.h
@@ -13,7 +13,7 @@
 
 namespace mcld {
 
-class X86GOT;
+class X86GOTPLT;
 class GOTEntry;
 class Output;
 
@@ -41,8 +41,8 @@
 public:
   X86PLT(LDSection& pSection,
          llvm::MCSectionData& pSectionData,
-         X86GOT& pGOTPLT,
-	 const Output& pOutput);
+         X86GOTPLT& pGOTPLT,
+         const Output& pOutput);
   ~X86PLT();
 
 // Override virtual function.
@@ -72,7 +72,7 @@
   void applyPLT1();
 
 private:
-  X86GOT& m_GOT;
+  X86GOTPLT& m_GOTPLT;
 
   // Used by getEntry() for mapping a ResolveInfo
   // instance to a PLT1 Entry.
@@ -84,6 +84,8 @@
   const uint8_t *m_PLT1;
   unsigned int m_PLT0Size;
   unsigned int m_PLT1Size;
+
+  const Output& m_Output;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86RelocationFactory.cpp b/lib/Target/X86/X86RelocationFactory.cpp
index 15b9a6b..9090d1a 100644
--- a/lib/Target/X86/X86RelocationFactory.cpp
+++ b/lib/Target/X86/X86RelocationFactory.cpp
@@ -8,11 +8,11 @@
 //===----------------------------------------------------------------------===//
 
 #include <llvm/ADT/Twine.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <llvm/Support/DataTypes.h>
 #include <llvm/Support/ELF.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/LD/Layout.h>
+#include <mcld/Support/MsgHandling.h>
 
 #include "X86RelocationFactory.h"
 #include "X86RelocationFunctions.h"
@@ -56,11 +56,8 @@
   };
 
   if (type >= sizeof (apply_functions) / sizeof (apply_functions[0]) ) {
-    llvm::report_fatal_error(llvm::Twine("Unknown relocation type ") +
-			     llvm::Twine((int) type) +
-			     llvm::Twine(" to symbol `") +
-                             pRelocation.symInfo()->name() +
-                             llvm::Twine("'."));
+    fatal(diag::unknown_relocation) << (int)type <<
+                                       pRelocation.symInfo()->name();
     return;
   }
 
@@ -68,22 +65,18 @@
   Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
 
   // check result
+  if (OK == result) {
+    return;
+  }
   if (Overflow == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' causes overflow. on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_overflow) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
 
   if (BadReloc == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' encounters unexpected opcode. "
-                                         "on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_badreloc) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
 }
@@ -104,7 +97,7 @@
 
 {
   // if symbol is dynamic or undefine or preemptible
-  if(pSym.isDyn() ||
+  if (pSym.isDyn() ||
      pSym.isUndef() ||
      pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output()))
     return false;
@@ -133,7 +126,7 @@
       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)) {
+      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);
@@ -147,7 +140,7 @@
       rel_entry.targetRef().assign(got_entry);
     }
     else {
-      llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+      fatal(diag::reserve_entry_number_mismatch) << "GOT";
     }
   }
   return got_entry;
@@ -157,7 +150,7 @@
 static
 X86RelocationFactory::Address helper_GOT_ORG(X86RelocationFactory& pParent)
 {
-  return pParent.getTarget().getGOT().getSection().addr();
+  return pParent.getTarget().getGOTPLT().getSection().addr();
 }
 
 
@@ -167,7 +160,9 @@
                                          X86RelocationFactory& pParent)
 {
   GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo,  pParent);
-  return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry);
+  X86RelocationFactory::Address got_addr =
+    pParent.getTarget().getGOT().getSection().addr();
+  return got_addr + pParent.getLayout().getOutputOffset(got_entry);
 }
 
 
@@ -195,7 +190,7 @@
       rel_entry.setSymInfo(rsym);
     }
     else {
-      llvm::report_fatal_error("No PLT entry reserved for PLT type relocation!");
+      fatal(diag::reserve_entry_number_mismatch) << "PLT";
     }
   }
   return plt_entry;
@@ -235,7 +230,7 @@
   rel_entry.setType(pType);
   rel_entry.targetRef() = pReloc.targetRef();
 
-  if(pType == llvm::ELF::R_386_RELATIVE)
+  if (pType == llvm::ELF::R_386_RELATIVE)
     rel_entry.setSymInfo(0);
   else
     rel_entry.setSymInfo(rsym);
@@ -263,18 +258,34 @@
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   RelocationFactory::DWord S = pReloc.symValue();
 
-  if(rsym->isLocal() && (rsym->reserved() & X86GNULDBackend::ReserveRel)) {
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    pReloc.target() = S + A;
+    return X86RelocationFactory::OK;
+  }
+
+  // A local symbol may need REL Type dynamic relocation
+  if (rsym->isLocal() && (rsym->reserved() & X86GNULDBackend::ReserveRel)) {
     helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
     pReloc.target() = S + A;
     return X86RelocationFactory::OK;
   }
-  else if(!rsym->isLocal()) {
-    if(rsym->reserved() & X86GNULDBackend::ReservePLT) {
+
+  // An external symbol may need PLT and dynamic relocation
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
       pReloc.target() = S + A;
     }
-    if(rsym->reserved() & X86GNULDBackend::ReserveRel) {
-      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
+    // If we generate a dynamic relocation (except R_386_RELATIVE)
+    // for a place, we should not perform static relocation on it
+    // in order to keep the addend store in the place correct.
+    if (rsym->reserved() & X86GNULDBackend::ReserveRel) {
+      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
         helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
       }
       else {
@@ -294,10 +305,42 @@
                                    const MCLDInfo& pLDInfo,
                                    X86RelocationFactory& pParent)
 {
-  // perform static relocation
+  ResolveInfo* rsym = pReloc.symInfo();
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
-  pReloc.target() = pReloc.symValue() + A
-      - pReloc.place(pParent.getLayout());
+  RelocationFactory::DWord S = pReloc.symValue();
+  RelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    pReloc.target() = S + A - P;
+    return X86RelocationFactory::OK;
+  }
+
+  // An external symbol may need PLT and dynamic relocation
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
+       S = helper_PLT(pReloc, pParent);
+       pReloc.target() = S + A - P;
+    }
+    if (pParent.getTarget().symbolNeedsDynRel(
+          *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo,
+                  pLDInfo.output(), false)) {
+      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
+        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+      }
+      else {
+        helper_DynRel(pReloc, pReloc.type(), pParent);
+          return X86RelocationFactory::OK;
+      }
+    }
+  }
+
+   // perform static relocation
+  pReloc.target() = S + A - P;
   return X86RelocationFactory::OK;
 }
 
@@ -331,7 +374,7 @@
                                    const MCLDInfo& pLDInfo,
                                    X86RelocationFactory& pParent)
 {
-  if(!(pReloc.symInfo()->reserved()
+  if (!(pReloc.symInfo()->reserved()
        & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
     return X86RelocationFactory::BadReloc;
   }
@@ -350,7 +393,7 @@
 {
   // PLT_S depends on if there is a PLT entry.
   X86RelocationFactory::Address PLT_S;
-  if((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
+  if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
     PLT_S = helper_PLT(pReloc, pParent);
   else
     PLT_S = pReloc.symValue();
diff --git a/lib/Target/X86/X86RelocationFactory.h b/lib/Target/X86/X86RelocationFactory.h
index 779a21d..6a6c372 100644
--- a/lib/Target/X86/X86RelocationFactory.h
+++ b/lib/Target/X86/X86RelocationFactory.h
@@ -55,3 +55,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86SectLinker.cpp b/lib/Target/X86/X86SectLinker.cpp
index 14621f3..a25a4c3 100644
--- a/lib/Target/X86/X86SectLinker.cpp
+++ b/lib/Target/X86/X86SectLinker.cpp
@@ -10,7 +10,6 @@
 #include <mcld/Support/TargetRegistry.h>
 
 #include "X86.h"
-#include "X86AndroidSectLinker.h"
 #include "X86ELFSectLinker.h"
 
 using namespace mcld;
@@ -31,9 +30,10 @@
     assert(0 && "COFF linker has not supported yet");
   }
 
-  // For now, use Android SectLinker directly
-  return new X86AndroidSectLinker(pOption,
-                                  pLDBackend);
+  if (theTriple.isArch32Bit())
+    return new X86ELFSectLinker(pOption, pLDBackend);
+
+  assert(0 && "X86_64 has not supported yet");
 }
 
 } // namespace of mcld
@@ -44,3 +44,4 @@
   // Register the linker frontend
   mcld::TargetRegistry::RegisterSectLinker(TheX86Target, createX86SectLinker);
 }
+
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index b3d7779..b036137 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -31,3 +31,4 @@
 {
   delete m_pLDInfo;
 }
+
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index 835bb59..7e6b9c8 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -11,7 +11,14 @@
 #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/FileSystem.h>
+#include <mcld/Support/raw_ostream.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>
@@ -26,9 +33,11 @@
 #include <llvm/Support/Host.h>
 #include <llvm/Support/IRReader.h>
 #include <llvm/Support/ManagedStatic.h>
+#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>
 
@@ -48,21 +57,10 @@
 
 #endif
 
-
 // General options for llc.  Other pass-specific options are specified
 // within the corresponding llc passes, and target-specific options
 // and back-end code generation options are specified with the target machine.
 //
-static cl::opt<std::string>
-InputFilename("dB",
-              cl::desc("set default bitcode"),
-              cl::value_desc("bitcode"));
-
-static cl::opt<std::string>
-OutputFilename("o",
-               cl::desc("Output filename"),
-               cl::value_desc("filename"));
-
 // Determine optimization level.
 static cl::opt<char>
 OptLevel("O",
@@ -90,21 +88,6 @@
   cl::desc("Target specific attributes (-mattr=help for details)"),
   cl::value_desc("a1,+a2,-a3,..."));
 
-static cl::opt<Reloc::Model>
-RelocModel("relocation-model",
-             cl::desc("Choose relocation model"),
-             cl::init(Reloc::Default),
-             cl::values(
-            clEnumValN(Reloc::Default, "default",
-                       "Target default relocation model"),
-            clEnumValN(Reloc::Static, "static",
-                       "Non-relocatable code"),
-            clEnumValN(Reloc::PIC_, "pic",
-                       "Fully relocatable, position independent code"),
-            clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
-                       "Relocatable external references, non-relocatable code"),
-            clEnumValEnd));
-
 static cl::opt<llvm::CodeModel::Model>
 CMModel("code-model",
         cl::desc("Choose code model"),
@@ -121,24 +104,6 @@
                               "Large code model"),
                    clEnumValEnd));
 
-cl::opt<mcld::CodeGenFileType>
-FileType("filetype", cl::init(mcld::CGFT_EXEFile),
-  cl::desc("Choose a file type (not all types are supported by all targets):"),
-  cl::values(
-       clEnumValN(mcld::CGFT_ASMFile, "asm",
-                  "Emit an assembly ('.s') file"),
-       clEnumValN(mcld::CGFT_OBJFile, "obj",
-                  "Emit a relocatable object ('.o') file"),
-       clEnumValN(mcld::CGFT_ARCFile, "arc",
-                  "Emit an archive ('.a') file"),
-       clEnumValN(mcld::CGFT_DSOFile, "dso",
-                  "Emit an dynamic shared object ('.so') file"),
-       clEnumValN(mcld::CGFT_EXEFile, "exe",
-                  "Emit a executable ('.exe') file"),
-       clEnumValN(mcld::CGFT_NULLFile, "null",
-                  "Emit nothing, for performance testing"),
-       clEnumValEnd));
-
 cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
                        cl::desc("Do not verify input module"));
 
@@ -276,6 +241,21 @@
 //===----------------------------------------------------------------------===//
 // General 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"));
+
+static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
+ArgOutputFilename("o",
+               cl::desc("Output filename"),
+               cl::value_desc("filename"));
+
+static cl::alias
+AliasOutputFilename("output",
+                    cl::desc("alias for -o"),
+                    cl::aliasopt(ArgOutputFilename));
+
+static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
 ArgSysRoot("sysroot",
            cl::desc("Use directory as the location of the sysroot, overriding the configure-time default."),
            cl::value_desc("directory"),
@@ -302,14 +282,25 @@
               cl::desc("alias for -t"),
               cl::aliasopt(ArgTrace));
 
-static cl::opt<bool>
-ArgVerbose("V",
-          cl::desc("Display the version number for ld and list the linker emulations supported."));
+static cl::opt<int>
+ArgVerbose("verbose",
+           cl::init(-1),
+           cl::desc("Display the version number for ld and list the linker emulations supported."));
 
-static cl::alias
-ArgVerboseAlias("verbose",
-                cl::desc("alias for -V"),
-                cl::aliasopt(ArgVerbose));
+static cl::opt<bool>
+ArgVersion("V",
+           cl::init(false),
+           cl::desc("Display the version number for MCLinker."));
+
+static cl::opt<int>
+ArgMaxErrorNum("error-limit",
+               cl::init(-1),
+               cl::desc("limits the maximum number of erros."));
+
+static cl::opt<int>
+ArgMaxWarnNum("warning-limit",
+               cl::init(-1),
+               cl::desc("limits the maximum number of warnings."));
 
 static cl::opt<std::string>
 ArgEntry("e",
@@ -327,11 +318,116 @@
              cl::desc("Bind references within the shared library."),
              cl::init(false));
 
+static cl::opt<bool>
+ArgBgroup("Bgroup",
+          cl::desc("Info the dynamic linker to perform lookups only inside the group."),
+          cl::init(false));
+
 static cl::opt<std::string>
 ArgSOName("soname",
           cl::desc("Set internal name of shared library"),
           cl::value_desc("name"));
 
+static cl::opt<bool>
+ArgNoUndefined("no-undefined",
+               cl::desc("Do not allow unresolved references"),
+               cl::init(false));
+
+static cl::opt<bool>
+ArgAllowMulDefs("allow-multiple-definition",
+                cl::desc("Allow multiple definition"),
+                cl::init(false));
+
+static cl::opt<bool>
+ArgEhFrameHdr("eh-frame-hdr",
+              cl::desc("Request creation of \".eh_frame_hdr\" section and ELF \"PT_GNU_EH_FRAME\" segment header."),
+              cl::init(false));
+
+static cl::list<mcld::ZOption, bool, llvm::cl::parser<mcld::ZOption> >
+ArgZOptionList("z",
+               cl::ZeroOrMore,
+               cl::desc("The -z options for GNU ld compatibility."),
+               cl::value_desc("keyword"),
+               cl::Prefix);
+
+cl::opt<mcld::CodeGenFileType>
+ArgFileType("filetype", cl::init(mcld::CGFT_EXEFile),
+  cl::desc("Choose a file type (not all types are supported by all targets):"),
+  cl::values(
+       clEnumValN(mcld::CGFT_ASMFile, "asm",
+                  "Emit an assembly ('.s') file"),
+       clEnumValN(mcld::CGFT_OBJFile, "obj",
+                  "Emit a relocatable object ('.o') file"),
+       clEnumValN(mcld::CGFT_DSOFile, "dso",
+                  "Emit an dynamic shared object ('.so') file"),
+       clEnumValN(mcld::CGFT_EXEFile, "exe",
+                  "Emit a executable ('.exe') file"),
+       clEnumValN(mcld::CGFT_NULLFile, "null",
+                  "Emit nothing, for performance testing"),
+       clEnumValEnd));
+
+static cl::opt<bool>
+ArgShared("shared",
+          cl::desc("Create a shared library."),
+          cl::init(false));
+
+static cl::alias
+ArgSharedAlias("Bshareable",
+               cl::desc("alias for -shared"),
+               cl::aliasopt(ArgShared));
+
+static cl::opt<bool>
+ArgPIE("pie",
+       cl::desc("Emit a position-independent executable file"),
+       cl::init(false));
+
+static cl::opt<Reloc::Model>
+ArgRelocModel("relocation-model",
+             cl::desc("Choose relocation model"),
+             cl::init(Reloc::Default),
+             cl::values(
+               clEnumValN(Reloc::Default, "default",
+                       "Target default relocation model"),
+               clEnumValN(Reloc::Static, "static",
+                       "Non-relocatable code"),
+               clEnumValN(Reloc::PIC_, "pic",
+                       "Fully relocatable, position independent code"),
+               clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+                       "Relocatable external references, non-relocatable code"),
+               clEnumValEnd));
+
+static cl::opt<bool>
+ArgFPIC("fPIC",
+        cl::desc("Set relocation model to pic. The same as -relocation-model=pic."),
+        cl::init(false));
+
+static cl::opt<std::string>
+ArgDyld("dynamic-linker",
+        cl::desc("Set the name of the dynamic linker."),
+        cl::value_desc("Program"));
+
+namespace color {
+enum Color {
+  Never,
+  Always,
+  Auto
+};
+} // namespace of color
+
+static cl::opt<color::Color>
+ArgColor("color",
+  cl::value_desc("WHEN"),
+  cl::desc("Surround the result strings with the marker"),
+  cl::init(color::Auto),
+  cl::values(
+    clEnumValN(color::Never, "never",
+      "do not surround result strings"),
+    clEnumValN(color::Always, "always",
+      "always surround result strings, even the output is a plain file"),
+    clEnumValN(color::Auto, "auto",
+      "surround result strings only if the output is a tty"),
+    clEnumValEnd));
+
 //===----------------------------------------------------------------------===//
 // Inputs
 static cl::list<mcld::sys::fs::Path>
@@ -440,118 +536,139 @@
 
 //===----------------------------------------------------------------------===//
 // Scripting Options
+static cl::list<std::string>
+ArgWrapList("wrap",
+            cl::ZeroOrMore,
+            cl::desc("Use a wrap function fo symbol."),
+            cl::value_desc("symbol"));
 
+static cl::list<std::string>
+ArgPortList("portable",
+            cl::ZeroOrMore,
+            cl::desc("Use a portable function fo symbol."),
+            cl::value_desc("symbol"));
 
 //===----------------------------------------------------------------------===//
 /// non-member functions
 
-// GetFileNameRoot - Helper function to get the basename of a filename.
-static inline void
-GetFileNameRoot(const std::string &pInputFilename, std::string& pFileNameRoot)
-{
-  std::string outputFilename;
-  /* *** */
-  const std::string& IFN = pInputFilename;
-  int Len = IFN.length();
-  if ((Len > 2) &&
-      IFN[Len-3] == '.' &&
-      ((IFN[Len-2] == 'b' && IFN[Len-1] == 'c') ||
-       (IFN[Len-2] == 'l' && IFN[Len-1] == 'l')))
-    pFileNameRoot = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
-  else
-    pFileNameRoot = std::string(IFN);
-}
-
+/// GetOutputStream - get the output stream.
 static tool_output_file *GetOutputStream(const char* pTargetName,
-                          Triple::OSType pOSType,
-                          mcld::CodeGenFileType pFileType,
-                          const std::string& pInputFilename,
-                          std::string& pOutputFilename)
+                                         Triple::OSType pOSType,
+                                         mcld::CodeGenFileType pFileType,
+                                         const mcld::sys::fs::Path& pInputFilename,
+                                         mcld::sys::fs::Path& pOutputFilename)
 {
-  // If we don't yet have an output filename, make one.
   if (pOutputFilename.empty()) {
-    if (pInputFilename == "-")
-      pOutputFilename = "-";
+    if (0 == pInputFilename.native().compare("-"))
+      pOutputFilename.assign("-");
     else {
-      GetFileNameRoot(pInputFilename, pOutputFilename);
+      switch(pFileType) {
+      case mcld::CGFT_ASMFile: {
+        if (0 == pInputFilename.native().compare("-"))
+          pOutputFilename.assign("_out");
+        else
+          pOutputFilename.assign(pInputFilename.stem().native());
 
-      switch (pFileType) {
-      case mcld::CGFT_ASMFile:
-        if (pTargetName[0] == 'c') {
-          if (pTargetName[1] == 0)
-            pOutputFilename += ".cbe.c";
-          else if (pTargetName[1] == 'p' && pTargetName[2] == 'p')
-            pOutputFilename += ".cpp";
+        if (0 == strcmp(pTargetName, "c"))
+          pOutputFilename.native() += ".cbe.c";
+        else if (0 == strcmp(pTargetName, "cpp"))
+          pOutputFilename.native() += ".cpp";
+        else
+          pOutputFilename.native() += ".s";
+      }
+      break;
+
+      case mcld::CGFT_OBJFile: {
+        if (0 == pInputFilename.native().compare("-"))
+          pOutputFilename.assign("_out");
+        else
+          pOutputFilename.assign(pInputFilename.stem().native());
+
+        if (pOSType == Triple::Win32)
+          pOutputFilename.native() += ".obj";
+        else
+          pOutputFilename.native() += ".o";
+      }
+      break;
+
+      case mcld::CGFT_DSOFile: {
+        if (Triple::Win32 == pOSType) {
+          if (0 == pInputFilename.native().compare("-"))
+            pOutputFilename.assign("_out");
           else
-            pOutputFilename += ".s";
+            pOutputFilename.assign(pInputFilename.stem().native());
+          pOutputFilename.native() += ".dll";
         }
         else
-          pOutputFilename += ".s";
-        break;
-      case mcld::CGFT_OBJFile:
-        if (pOSType == Triple::Win32)
-          pOutputFilename += ".obj";
+          pOutputFilename.assign("a.out");
+      }
+      break;
+
+      case mcld::CGFT_EXEFile: {
+        if (Triple::Win32 == pOSType) {
+          if (0 == pInputFilename.native().compare("-"))
+            pOutputFilename.assign("_out");
+          else
+            pOutputFilename.assign(pInputFilename.stem().native());
+          pOutputFilename.native() += ".exe";
+        }
         else
-          pOutputFilename += ".o";
-        break;
-      case mcld::CGFT_DSOFile:
-        if (pOSType == Triple::Win32)
-         pOutputFilename += ".dll";
-        else
-         pOutputFilename += ".so";
-        break;
-      case mcld::CGFT_ARCFile:
-         pOutputFilename += ".a";
-        break;
-      case mcld::CGFT_EXEFile:
+          pOutputFilename.assign("a.out");
+      }
+      break;
+
       case mcld::CGFT_NULLFile:
-        // do nothing
         break;
       default:
-        assert(0 && "Unknown file type");
-      }
-    }
-  }
+        llvm::report_fatal_error("Unknown output file type.\n");
+      } // end of switch
+    } // end of ! pInputFilename == "-"
+  } // end of if empty pOutputFilename
 
   // Decide if we need "binary" output.
-  bool Binary = false;
+  unsigned int fd_flags = 0x0;
   switch (pFileType) {
   default: assert(0 && "Unknown file type");
   case mcld::CGFT_ASMFile:
     break;
-  case mcld::CGFT_ARCFile:
   case mcld::CGFT_OBJFile:
   case mcld::CGFT_DSOFile:
   case mcld::CGFT_EXEFile:
   case mcld::CGFT_NULLFile:
-    Binary = true;
+    fd_flags |= raw_fd_ostream::F_Binary;
     break;
   }
 
   // Open the file.
-  std::string error;
-  unsigned OpenFlags = 0;
-  if (Binary) OpenFlags |= raw_fd_ostream::F_Binary;
-  tool_output_file *FDOut = new tool_output_file(pOutputFilename.c_str(), error,
-                                                 OpenFlags);
-  if (!error.empty()) {
-    errs() << error << '\n';
-    delete FDOut;
-    return 0;
+  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;
   }
 
-  return FDOut;
+  return result_output;
 }
 
-static bool ProcessLinkerInputsFromCommand(mcld::SectLinkerOption &pOption) {
+static bool ShouldColorize()
+{
+   const char* term = getenv("TERM");
+   return term && (0 != strcmp(term, "dumb"));
+}
+
+static bool ProcessLinkerOptionsFromCommand(mcld::MCLDInfo& pLDInfo) {
   // -----  Set up General Options  ----- //
   // set up soname
-  pOption.info().output().setSOName(ArgSOName);
+  pLDInfo.output().setSOName(ArgSOName);
 
   // set up sysroot
   if (!ArgSysRoot.empty()) {
     if (exists(ArgSysRoot) && is_directory(ArgSysRoot))
-      pOption.info().options().setSysroot(ArgSysRoot);
+      pLDInfo.options().setSysroot(ArgSysRoot);
   }
 
   // add all search directories
@@ -559,9 +676,9 @@
   cl::list<mcld::MCLDDirectory>::iterator sdEnd = ArgSearchDirList.end();
   for (sd=ArgSearchDirList.begin(); sd!=sdEnd; ++sd) {
     if (sd->isInSysroot())
-      sd->setSysroot(pOption.info().options().sysroot());
+      sd->setSysroot(pLDInfo.options().sysroot());
     if (exists(sd->path()) && is_directory(sd->path())) {
-      pOption.info().options().directories().add(*sd);
+      pLDInfo.options().directories().add(*sd);
     }
     else {
       // FIXME: need a warning function
@@ -571,11 +688,98 @@
     }
   }
 
-  pOption.info().options().setTrace(ArgTrace);
-  pOption.info().options().setVerbose(ArgVerbose);
-  pOption.info().options().setEntry(ArgEntry);
-  pOption.info().options().setBsymbolic(ArgBsymbolic);
+  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);
 
+  // set up rename map, for --wrap
+  cl::list<std::string>::iterator wname;
+  cl::list<std::string>::iterator wnameEnd = ArgWrapList.end();
+  for (wname = ArgWrapList.begin(); wname != wnameEnd; ++wname) {
+    bool exist = false;
+
+    // add wname -> __wrap_wname
+    mcld::StringEntry<llvm::StringRef>* to_wrap =
+                    pLDInfo.scripts().renameMap().insert(*wname, exist);
+
+    std::string to_wrap_str = "__wrap_" + *wname;
+    to_wrap->setValue(to_wrap_str);
+
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *wname << to_wrap_str;
+
+    // add __real_wname -> wname
+    std::string from_real_str = "__real_" + *wname;
+    mcld::StringEntry<llvm::StringRef>* from_real =
+             pLDInfo.scripts().renameMap().insert(from_real_str, exist);
+    from_real->setValue(*wname);
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
+  } // end of for
+
+  // set up rename map, for --portable
+  cl::list<std::string>::iterator pname;
+  cl::list<std::string>::iterator pnameEnd = ArgPortList.end();
+  for (pname = ArgPortList.begin(); pname != pnameEnd; ++pname) {
+    bool exist = false;
+
+    // add pname -> pname_portable
+    mcld::StringEntry<llvm::StringRef>* to_port =
+                  pLDInfo.scripts().renameMap().insert(*pname, exist);
+
+    std::string to_port_str = *pname + "_portable";
+    to_port->setValue(to_port_str);
+
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *pname << to_port_str;
+
+    // add __real_pname -> pname
+    std::string from_real_str = "__real_" + *pname;
+    mcld::StringEntry<llvm::StringRef>* from_real =
+             pLDInfo.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);
+  }
+
+  // -----  Set up Script Options  ----- //
+
+  return true;
+}
+
+static bool ProcessLinkerInputsFromCommand(mcld::SectLinkerOption &pOption) {
   // -----  Set up Inputs  ----- //
   // add all start-group
   cl::list<bool>::iterator sg;
@@ -685,16 +889,14 @@
     ++attr;
   }
 
-  // -----  Set up Scripting Options  ----- //
-
-  return false;
+  return true;
 }
 
 int main( int argc, char* argv[] )
 {
-
   LLVMContext &Context = getGlobalContext();
   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
+
   // Initialize targets first, so that --version shows registered targets.
   InitializeAllTargets();
   InitializeAllAsmPrinters();
@@ -702,7 +904,9 @@
   InitializeAllTargetMCs();
   mcld::InitializeAllTargets();
   mcld::InitializeAllLinkers();
-  cl::ParseCommandLineOptions(argc, argv, "llvm MCLinker\n");
+  mcld::InitializeAllDiagnostics();
+
+  cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
 
 #ifdef ENABLE_UNITTEST
   if (UnitTest) {
@@ -713,25 +917,45 @@
   // Load the module to be compiled...
   std::auto_ptr<Module> M;
 
-  if (InputFilename.empty() && (FileType != mcld::CGFT_DSOFile)) {
-    // Read from stdin
-    InputFilename = "-";
+  // -shared
+  if (true == ArgShared) {
+    ArgFileType = mcld::CGFT_DSOFile;
   }
 
-  if (!InputFilename.empty()) {
+  // -V
+  if (ArgVersion) {
+    outs() << "MCLinker - ";
+    outs() << mcld::MCLDInfo::version();
+    outs() << "\n";
+  }
+
+  if (ArgBitcodeFilename.empty() &&
+      (mcld::CGFT_DSOFile != ArgFileType &&
+       mcld::CGFT_EXEFile != ArgFileType)) {
+    // If the file is not given, forcefully read from stdin
+    if (ArgVerbose >= 0) {
+      errs() << "** The bitcode/llvm asm file is not given. Read from stdin.\n"
+             << "** Specify input bitcode/llvm asm file by\n\n"
+             << "          llvm-mcld -dB [the bitcode/llvm asm]\n\n";
+    }
+
+    ArgBitcodeFilename.assign("-");
+  }
+
+  if (!ArgBitcodeFilename.empty()) {
     SMDiagnostic Err;
-    M.reset(ParseIRFile(InputFilename, Err, Context));
+    M.reset(ParseIRFile(ArgBitcodeFilename.native(), Err, Context));
 
     if (M.get() == 0) {
       Err.print(argv[0], errs());
       errs() << "** Failed to to the given bitcode/llvm asm file '"
-             << InputFilename << "'. **\n";
+             << ArgBitcodeFilename.native() << "'. **\n";
       return 1;
     }
-  } else {
-    // If here, output must be dynamic shared object (mcld::CGFT_DSOFile).
-
-    // Create an empty Module
+  }
+  else {
+    // If here, output must be dynamic shared object (mcld::CGFT_DSOFile) and
+    // executable file (mcld::CGFT_EXEFile).
     M.reset(new Module("Empty Module", Context));
   }
   Module &mod = *M.get();
@@ -782,9 +1006,11 @@
     std::string Err;
     TheTarget = mcld::TargetRegistry::lookupTarget(TheTriple.getTriple(), Err);
     if (TheTarget == 0) {
-      errs() << argv[0] << ": error auto-selecting target for module '"
-             << Err << "'.  Please use the -march option to explicitly "
-             << "pick a target.\n";
+      errs() << "error: auto-selecting target `" << TheTriple.getTriple()
+             << "'\n"
+             << "Please use the -march option to explicitly select a target.\n"
+             << "Example:\n"
+             << "  $ " << argv[0] << " -march=arm\n";
       return 1;
     }
   }
@@ -810,6 +1036,10 @@
   case '3': OLvl = CodeGenOpt::Aggressive; break;
   }
 
+  // set -fPIC
+  if (ArgFPIC)
+    ArgRelocModel = Reloc::PIC_;
+
   TargetOptions Options;
   Options.LessPreciseFPMADOption = EnableFPMAD;
   Options.PrintMachineCode = PrintCode;
@@ -838,21 +1068,40 @@
   std::auto_ptr<mcld::LLVMTargetMachine> target_machine(
           TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr, Options,
-                                         RelocModel, CMModel, OLvl));
+                                         ArgRelocModel, CMModel, OLvl));
   assert(target_machine.get() && "Could not allocate target machine!");
   mcld::LLVMTargetMachine &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
+  OwningPtr<mcld::DiagnosticLineInfo>
+    diag_line_info(TheTarget->createDiagnosticLineInfo(*TheTarget->get(),
+                                                       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());
+
+
   // Figure out where we are going to send the output...
   OwningPtr<tool_output_file>
   Out(GetOutputStream(TheTarget->get()->getName(),
                       TheTriple.getOS(),
-                      FileType,
-                      InputFilename,
-                      OutputFilename));
-  if (!Out) return 1;
+                      ArgFileType,
+                      ArgBitcodeFilename,
+                      ArgOutputFilename));
+  if (!Out) {
+    // FIXME: show some error message pls.
+    return 1;
+  }
 
   // Build up all of the passes that we want to do to the module.
   PassManager PM;
@@ -870,7 +1119,12 @@
   mcld::SectLinkerOption *LinkerOpt =
       new mcld::SectLinkerOption(TheTargetMachine.getLDInfo());
 
-  if (ProcessLinkerInputsFromCommand(*LinkerOpt)) {
+  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;
   }
@@ -881,8 +1135,8 @@
     // Ask the target to add backend passes as necessary.
     if( TheTargetMachine.addPassesToEmitFile(PM,
                                              FOS,
-                                             OutputFilename,
-                                             FileType,
+                                             ArgOutputFilename.native(),
+                                             ArgFileType,
                                              OLvl,
                                              LinkerOpt,
                                              NoVerify)) {
@@ -903,6 +1157,16 @@
   // 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/Config/Config.h.in b/tools/mcld/include/alone/Config/Config.h.in
new file mode 100644
index 0000000..edb8721
--- /dev/null
+++ b/tools/mcld/include/alone/Config/Config.h.in
@@ -0,0 +1,14 @@
+#ifndef ALONE_CONFIG_CONFIG_H
+#define ALONE_CONFIG_CONFIG_H
+
+#define PROVIDE_@PROVIDE_ALONE_TARGET@_CODEGEN
+#define DEFAULT_@DEFAULT_ALONE_TARGET@_CODEGEN
+
+#define DEFAULT_ARM_TRIPLE_STRING "armv7-none-linux-gnueabi"
+#define DEFAULT_X86_TRIPLE_STRING "i686-unknown-linux"
+#define DEFAULT_MIPS_TRIPLE_STRING "mipsel-none-linux-gnueabi"
+#define DEFAULT_X86_64_TRIPLE_STRING "x86_64-unknown-linux"
+
+#define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_@DEFAULT_ALONE_TARGET@_TRIPLE_STRING
+
+#endif // ALONE_CONFIG_CONFIG_H
diff --git a/tools/mcld/include/alone/Linker.h b/tools/mcld/include/alone/Linker.h
new file mode 100644
index 0000000..17f8baa
--- /dev/null
+++ b/tools/mcld/include/alone/Linker.h
@@ -0,0 +1,84 @@
+//===- Linker.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ALONE_LINKER_H
+#define ALONE_LINKER_H
+
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/MC/MCLDDriver.h>
+#include <mcld/MC/InputTree.h>
+
+namespace alone {
+
+class MemoryFactory;
+class LinkerConfig;
+
+class Linker {
+public:
+  enum ErrorCode {
+    kSuccess,
+    kDoubleConfig,
+    kCreateBackend,
+    kDelegateLDInfo,
+    kOpenNameSpec,
+    kOpenObjectFile,
+    kNotConfig,
+    kNotSetUpOutput,
+    kOpenOutput,
+    kReadSections,
+    kReadSymbols,
+    kAddAdditionalSymbols,
+    kMaxErrorCode,
+  };
+
+  static const char *GetErrorString(enum ErrorCode pErrCode);
+
+private:
+  mcld::TargetLDBackend *mBackend;
+  mcld::MCLDDriver *mDriver;
+  mcld::MCLDInfo *mLDInfo;
+  mcld::InputTree::iterator mRoot;
+  MemoryFactory *mMemAreaFactory;
+
+public:
+  Linker();
+
+  Linker(const LinkerConfig& pConfig);
+
+  ~Linker();
+
+  enum ErrorCode config(const LinkerConfig& pConfig);
+
+  enum ErrorCode addNameSpec(const std::string &pNameSpec);
+
+  enum ErrorCode addObject(const std::string &pObjectPath);
+
+  enum ErrorCode addObject(void* pMemory, size_t pSize);
+
+  enum ErrorCode addCode(void* pMemory, size_t pSize);
+
+  enum ErrorCode setOutput(const std::string &pPath);
+
+  enum ErrorCode setOutput(int pFileHandler);
+
+  enum ErrorCode link();
+
+private:
+  enum ErrorCode extractFiles(const LinkerConfig& pConfig);
+
+  enum ErrorCode openFile(const mcld::sys::fs::Path& pPath,
+                          enum ErrorCode pCode,
+                          mcld::Input& pInput);
+
+  void advanceRoot();
+};
+
+} // end namespace alone
+
+#endif // ALONE_LINKER_H
diff --git a/tools/mcld/include/alone/Support/Initialization.h b/tools/mcld/include/alone/Support/Initialization.h
new file mode 100644
index 0000000..9af994e
--- /dev/null
+++ b/tools/mcld/include/alone/Support/Initialization.h
@@ -0,0 +1,23 @@
+//===- Initialization.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ALONE_SUPPORT_INITIALIZATION_H
+#define ALONE_SUPPORT_INITIALIZATION_H
+
+namespace alone {
+
+namespace init {
+
+void Initialize();
+
+} // end namespace init
+
+} // end namespace alone
+
+#endif // ALONE_SUPPORT_INITIALIZATION_H
diff --git a/tools/mcld/include/alone/Support/LinkerConfig.h b/tools/mcld/include/alone/Support/LinkerConfig.h
new file mode 100644
index 0000000..37689d2
--- /dev/null
+++ b/tools/mcld/include/alone/Support/LinkerConfig.h
@@ -0,0 +1,78 @@
+//===- Linker.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ALONE_SUPPORT_LINKER_CONFIG_H
+#define ALONE_SUPPORT_LINKER_CONFIG_H
+
+#include <string>
+
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDFile.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+
+namespace alone {
+
+class LinkerConfig {
+private:
+  //===----------------------------------------------------------------------===//
+  // Available Configurations
+  //===----------------------------------------------------------------------===//
+  std::string mTriple;
+
+private:
+  //===----------------------------------------------------------------------===//
+  // These are generated by LinkerConfig during initialize().
+  //===----------------------------------------------------------------------===//
+  const mcld::Target *mTarget;
+  bool initializeTarget();
+
+  mcld::MCLDInfo *mLDInfo;
+  bool initializeLDInfo();
+
+  mcld::DiagnosticLineInfo *mDiagLineInfo;
+  mcld::DiagnosticPrinter *mDiagPrinter;
+  bool initializeDiagnostic();
+public:
+  //===----------------------------------------------------------------------===//
+  // Getters
+  //===----------------------------------------------------------------------===//
+  inline const std::string &getTriple() const
+  { return mTriple; }
+
+  inline const mcld::Target *getTarget() const
+  { return mTarget; }
+
+  inline mcld::MCLDInfo* getLDInfo()
+  { return mLDInfo; }
+
+  inline const mcld::MCLDInfo* getLDInfo() const
+  { return mLDInfo; }
+
+  inline void setSOName(const std::string &pSOName)
+  { mLDInfo->output().setSOName(pSOName); }
+
+  inline void setDyld(const std::string &pDyld)
+  { mLDInfo->options().setDyld(pDyld); }
+
+  void setSysRoot(const std::string &pSysRoot);
+
+  void addWrap(const std::string &pWrapSymbol);
+
+  void addSearchDir(const std::string &pDir);
+
+public:
+  LinkerConfig(const std::string& pTriple);
+
+  virtual ~LinkerConfig();
+};
+
+} // end namespace alone
+
+#endif // ALONE_SUPPORT_LINKER_CONFIG_H
diff --git a/tools/mcld/include/alone/Support/MemoryFactory.h b/tools/mcld/include/alone/Support/MemoryFactory.h
new file mode 100644
index 0000000..2247d2c
--- /dev/null
+++ b/tools/mcld/include/alone/Support/MemoryFactory.h
@@ -0,0 +1,40 @@
+//===- 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();
+
+  ~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
new file mode 100644
index 0000000..229a9bd
--- /dev/null
+++ b/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
@@ -0,0 +1,78 @@
+//===- TargetLinkerConfig.h -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ALONE_SUPPORT_TARGET_LINKER_CONFIGS_H
+#define ALONE_SUPPORT_TARGET_LINKER_CONFIGS_H
+
+#include <string>
+
+#include "alone/Config/Config.h"
+#include "alone/Support/LinkerConfig.h"
+
+namespace alone {
+
+//===----------------------------------------------------------------------===//
+// ARM
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_ARM_CODEGEN)
+class ARMLinkerConfig : public LinkerConfig {
+public:
+  ARMLinkerConfig();
+};
+#endif // defined(PROVIDE_ARM_CODEGEN)
+
+//===----------------------------------------------------------------------===//
+// MIPS
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_MIPS_CODEGEN)
+class MipsLinkerConfig : public LinkerConfig {
+public:
+  MipsLinkerConfig();
+};
+#endif // defined(PROVIDE_MIPS_CODEGEN)
+
+//===----------------------------------------------------------------------===//
+// X86 and X86_64
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_X86_CODEGEN)
+class X86FamilyLinkerConfigBase : public LinkerConfig {
+public:
+  X86FamilyLinkerConfigBase(const std::string& pTriple);
+};
+
+class X86_32LinkerConfig : public X86FamilyLinkerConfigBase {
+public:
+  X86_32LinkerConfig();
+};
+
+class X86_64LinkerConfig : public X86FamilyLinkerConfigBase {
+public:
+  X86_64LinkerConfig();
+};
+#endif // defined(PROVIDE_X86_CODEGEN)
+
+//===----------------------------------------------------------------------===//
+// Default target
+//===----------------------------------------------------------------------===//
+class DefaultLinkerConfig : public
+#if defined (DEFAULT_ARM_CODEGEN)
+  ARMLinkerConfig
+#elif defined (DEFAULT_MIPS_CODEGEN)
+  MipsLinkerConfig
+#elif defined (DEFAULT_X86_CODEGEN)
+  X86_32LinkerConfig
+#elif defined (DEFAULT_X86_64_CODEGEN)
+  X86_64LinkerConfig
+#else
+#  error "Unsupported Default Target!"
+#endif
+{ };
+
+} // 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
new file mode 100644
index 0000000..0d112ba
--- /dev/null
+++ b/tools/mcld/lib/Core/Linker.cpp
@@ -0,0 +1,353 @@
+//===- Linker.cpp ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "alone/Linker.h"
+#include "alone/Support/LinkerConfig.h"
+#include "alone/Support/MemoryFactory.h"
+
+#include <llvm/Support/ELF.h>
+
+#include <mcld/MC/MCLinker.h>
+#include <mcld/MC/InputTree.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/Support/Path.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/FileHandle.h>
+
+using namespace alone;
+
+const char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode)
+{
+  static const char* ErrorString[] = {
+    /* kSuccess */
+    "Successfully compiled.",
+    /* kDoubleConfig */
+    "Configure Linker twice.",
+    /* kCreateBackend */
+    "Cannot create backend.",
+    /* kDelegateLDInfo */
+    "Cannot get linker information",
+    /* kOpenNameSpec */
+    "Cannot open -lnamespec",
+    /* kOpenObjectFile */
+    "Cannot open object file",
+    /* kNotConfig */
+    "Linker::config() is not called",
+    /* kNotSetUpOutput */
+    "Linker::setOutput() is not called before add input files",
+    /* kOpenOutput */
+    "Cannot open output file",
+    /* kReadSections */
+    "Cannot read sections",
+    /* kReadSymbols */
+    "Cannot read symbols",
+    /* kAddAdditionalSymbols */
+    "Cannot add standard and target symbols",
+    /* kMaxErrorCode */
+    "(Unknown error code)"
+  };
+
+  if (pErrCode > kMaxErrorCode) {
+    pErrCode = kMaxErrorCode;
+  }
+
+  return ErrorString[ static_cast<size_t>(pErrCode) ];
+}
+
+//===----------------------------------------------------------------------===//
+// Linker
+//===----------------------------------------------------------------------===//
+Linker::Linker()
+  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL) {
+}
+
+Linker::Linker(const LinkerConfig& pConfig)
+  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL) {
+
+  const std::string &triple = pConfig.getTriple();
+
+  enum ErrorCode err = config(pConfig);
+  if (kSuccess != err) {
+    ALOGE("%s (%s)", GetErrorString(err), triple.c_str());
+    return;
+  }
+
+  return;
+}
+
+Linker::~Linker()
+{
+  if (NULL != mDriver)
+    delete mDriver;
+  if (NULL != mBackend)
+    delete mBackend;
+  if (NULL != mMemAreaFactory)
+    delete mMemAreaFactory;
+}
+
+enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig)
+{
+  mLDInfo = const_cast<mcld::MCLDInfo*>(pConfig.getLDInfo());
+  if (NULL == mLDInfo)
+    return kDelegateLDInfo;
+
+  mRoot = mLDInfo->inputs().root();
+  return kSuccess;
+}
+
+enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig)
+{
+  if (NULL != mLDInfo)
+    return kDoubleConfig;
+
+  extractFiles(pConfig);
+
+  mBackend = pConfig.getTarget()->createLDBackend(pConfig.getTriple());
+  if (NULL == mBackend)
+    return kCreateBackend;
+
+  mDriver = new mcld::MCLDDriver(*mLDInfo, *mBackend);
+
+  mMemAreaFactory = new MemoryFactory();
+
+  mDriver->initMCLinker();
+
+  return kSuccess;
+}
+
+void Linker::advanceRoot()
+{
+  if (mRoot.isRoot())
+    --mRoot;
+  else
+    ++mRoot;
+}
+
+enum Linker::ErrorCode
+Linker::openFile(const mcld::sys::fs::Path& pPath, enum Linker::ErrorCode pCode, mcld::Input& pInput)
+{
+  mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pPath,
+                                                    mcld::FileHandle::ReadOnly);
+
+  if (input_memory->handler()->isGood())
+    pInput.setMemArea(input_memory);
+  else
+    return pCode;
+
+  mcld::LDContext *input_context = mLDInfo->contextFactory().produce(pPath);
+  pInput.setContext(input_context);
+  return kSuccess;
+}
+
+enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec)
+{
+  mcld::sys::fs::Path* path = NULL;
+  // find out the real path of the namespec.
+  if (mLDInfo->attrFactory().constraint().isSharedSystem()) {
+    // In the system with shared object support, we can find both archive
+    // and shared object.
+
+    if (mLDInfo->attrFactory().last().isStatic()) {
+      // with --static, we must search an archive.
+      path = mLDInfo->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);
+    }
+  }
+  else {
+    // In the system without shared object support, we only look for an
+    // archive.
+    path = mLDInfo->options().directories().find(pNameSpec, mcld::Input::Archive);
+  }
+
+  mcld::Input* input = mLDInfo->inputFactory().produce(pNameSpec, *path,
+                                                        mcld::Input::Unknown);
+  mLDInfo->inputs().insert<mcld::InputTree::Positional>(mRoot, *input);
+
+  advanceRoot();
+
+  return openFile(*path, kOpenNameSpec, *input);
+}
+
+/// 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);
+
+  mLDInfo->inputs().insert<mcld::InputTree::Positional>(mRoot, *input);
+
+  advanceRoot();
+
+  return openFile(pObjectPath, kOpenObjectFile, *input);
+}
+
+/// 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);
+
+  mLDInfo->inputs().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();
+  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);
+
+  mLDInfo->inputs().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();
+  input->setContext(input_context);
+
+  // FIXME: So far, MCLinker must set up output before add input files.
+  // set up LDContext
+  if (mDriver->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);
+
+  // create .text section
+  mcld::LDSection& text = mDriver->getLinker()->createSectHdr(".text",
+                              mcld::LDFileFormat::Regular,
+                              llvm::ELF::SHT_PROGBITS,
+                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR);
+
+  text.setSize(pSize);
+  text.setOffset(0x0);
+  text.setIndex(1);
+  text.setInfo(0);
+  text.setAlign(1);
+
+  input_context->getSectionTable().push_back(&text);
+
+  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(
+                        pPath,
+                        mcld::FileHandle::ReadWrite | mcld::FileHandle::Truncate,
+                        perm);
+
+  if (!out_area->handler()->isGood())
+    return kOpenOutput;
+
+  // FIXME: decide output type by command line option.
+  mLDInfo->output().setType(mcld::Output::DynObj);
+  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;
+
+  // -----  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 (!mDriver->readSections() ||
+      !mDriver->mergeSections())
+    return kReadSections;
+
+  if (!mDriver->readSymbolTables())
+    return kReadSymbols;
+
+  if (!mDriver->addStandardSymbols() ||
+      !mDriver->addTargetSymbols())
+    return kAddAdditionalSymbols;
+
+  mDriver->readRelocations();
+  mDriver->prelayout();
+  mDriver->layout();
+  mDriver->postlayout();
+  mDriver->finalizeSymbolValue();
+  mDriver->relocation();
+  mDriver->emitOutput();
+  mDriver->postProcessing();
+
+  return kSuccess;
+}
+
diff --git a/tools/mcld/lib/Support/Initialization.cpp b/tools/mcld/lib/Support/Initialization.cpp
new file mode 100644
index 0000000..83803f7
--- /dev/null
+++ b/tools/mcld/lib/Support/Initialization.cpp
@@ -0,0 +1,79 @@
+//===- Initialization.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+#include "alone/Config/Config.h"
+#include "alone/Support/Initialization.h"
+
+#include <mcld/Support/TargetSelect.h>
+#include <mcld/Support/TargetRegistry.h>
+
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/Support/ErrorHandling.h>
+
+namespace {
+
+void llvm_error_handler(void *pUserData, const std::string& pMessage) {
+  ALOGE("%s", pMessage.c_str());
+  ::exit(1);
+}
+
+} // end anonymous namespace
+
+void alone::init::Initialize() {
+  static bool is_initialized = false;
+  if (is_initialized) {
+    return;
+  }
+
+  // Setup error handler for LLVM.
+  llvm::remove_fatal_error_handler();
+  llvm::install_fatal_error_handler(llvm_error_handler, NULL);
+
+#if defined(PROVIDE_ARM_CODEGEN)
+  LLVMInitializeARMAsmPrinter();
+  LLVMInitializeARMTargetMC();
+  LLVMInitializeARMTargetInfo();
+  LLVMInitializeARMTarget();
+  LLVMInitializeARMLDTargetInfo();
+  LLVMInitializeARMLDTarget();
+  LLVMInitializeARMLDBackend();
+  LLVMInitializeARMDiagnosticLineInfo();
+#endif
+
+#if defined(PROVIDE_MIPS_CODEGEN)
+  LLVMInitializeMipsAsmPrinter();
+  LLVMInitializeMipsTargetMC();
+  LLVMInitializeMipsTargetInfo();
+  LLVMInitializeMipsTarget();
+  LLVMInitializeMipsLDTargetInfo();
+  LLVMInitializeMipsLDTarget();
+  LLVMInitializeMipsLDBackend();
+  LLVMInitializeMipsDiagnosticLineInfo();
+#endif
+
+#if defined(PROVIDE_X86_CODEGEN)
+  LLVMInitializeX86AsmPrinter();
+  LLVMInitializeX86TargetMC();
+  LLVMInitializeX86TargetInfo();
+  LLVMInitializeX86Target();
+  LLVMInitializeX86LDTargetInfo();
+  LLVMInitializeX86LDTarget();
+  LLVMInitializeX86LDBackend();
+  LLVMInitializeX86DiagnosticLineInfo();
+#endif
+
+  is_initialized = true;
+
+  return;
+}
+
diff --git a/tools/mcld/lib/Support/LinkerConfig.cpp b/tools/mcld/lib/Support/LinkerConfig.cpp
new file mode 100644
index 0000000..8da9bbe
--- /dev/null
+++ b/tools/mcld/lib/Support/LinkerConfig.cpp
@@ -0,0 +1,128 @@
+//===- LinkerConfig.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "alone/Support/LinkerConfig.h"
+
+#include <llvm/Support/Signals.h>
+
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDDirectory.h>
+#include <mcld/LD/TextDiagnosticPrinter.h>
+#include <mcld/Support/Path.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/raw_ostream.h>
+
+using namespace alone;
+
+LinkerConfig::LinkerConfig(const std::string &pTriple)
+  : mTriple(pTriple), mTarget(NULL), mLDInfo(NULL), mDiagLineInfo(NULL),
+    mDiagPrinter(NULL) {
+
+  initializeTarget();
+  initializeLDInfo();
+  initializeDiagnostic();
+}
+
+LinkerConfig::~LinkerConfig()
+{
+  if (NULL != mLDInfo)
+    delete mLDInfo;
+
+  if (0 != mDiagPrinter->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();
+  }
+  mDiagPrinter->finish();
+
+  delete mDiagLineInfo;
+  delete mDiagPrinter;
+}
+
+bool LinkerConfig::initializeTarget()
+{
+  std::string error;
+  mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error);
+  if (NULL != mTarget) {
+    return true;
+  } else {
+    ALOGE("Cannot initialize mcld::Target for given triple '%s'! (%s)\n",
+          mTriple.c_str(), error.c_str());
+    return false;
+  }
+}
+
+bool LinkerConfig::initializeLDInfo()
+{
+  if (NULL != mLDInfo) {
+    ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
+          mTriple.c_str());
+    return false;
+  }
+
+  mLDInfo = new mcld::MCLDInfo(getTriple(), 1, 32);
+  return true;
+}
+
+bool LinkerConfig::initializeDiagnostic()
+{
+  // Set up MsgHandler
+  mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget->get(), mTriple);
+
+  mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDInfo);
+
+  mcld::InitializeDiagnosticEngine(*mLDInfo, mDiagLineInfo, mDiagPrinter);
+
+  return true;
+}
+
+void LinkerConfig::setSysRoot(const std::string &pSysRoot)
+{
+  mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
+}
+
+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);
+
+  std::string to_wrap_str = "__wrap_" + pWrapSymbol;
+  to_wrap->setValue(to_wrap_str);
+
+  if (exist)
+    mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str;
+
+  // add __real_wname -> wname
+  std::string from_real_str = "__real_" + pWrapSymbol;
+  mcld::StringEntry<llvm::StringRef>* from_real =
+             mLDInfo->scripts().renameMap().insert(from_real_str, exist);
+  from_real->setValue(pWrapSymbol);
+
+  if (exist)
+    mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str;
+}
+
+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 (exists(sd->path()) && is_directory(sd->path())) {
+    mLDInfo->options().directories().add(*sd);
+  }
+  else
+    mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
+}
+
diff --git a/tools/mcld/lib/Support/MemoryFactory.cpp b/tools/mcld/lib/Support/MemoryFactory.cpp
new file mode 100644
index 0000000..0d368dc
--- /dev/null
+++ b/tools/mcld/lib/Support/MemoryFactory.cpp
@@ -0,0 +1,17 @@
+//===- MemoryFactory.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "alone/Support/MemoryFactory.h"
+
+using namespace alone;
+
+MemoryFactory::MemoryFactory()
+  : mcld::MemoryAreaFactory(32) {
+}
+
diff --git a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
new file mode 100644
index 0000000..8854f79
--- /dev/null
+++ b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
@@ -0,0 +1,121 @@
+//===- TargetLinkerConfigs.cpp --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "alone/Config/Config.h"
+#include "alone/Support/TargetLinkerConfigs.h"
+
+using namespace alone;
+
+#ifdef TARGET_BUILD
+static const char* gDefaultDyld = "/system/bin/linker";
+static const char* gDefaultSysroot = "/system";
+#else
+static const char* gDefaultDyld = "/usr/lib/ld.so.1";
+static const char* gDefaultSysroot = "/";
+#endif
+
+//===----------------------------------------------------------------------===//
+// ARM
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_ARM_CODEGEN)
+ARMLinkerConfig::ARMLinkerConfig()
+  : LinkerConfig(DEFAULT_ARM_TRIPLE_STRING) {
+
+  // set up target-dependent constraints of attributes
+  getLDInfo()->attrFactory().constraint().enableWholeArchive();
+  getLDInfo()->attrFactory().constraint().disableAsNeeded();
+  getLDInfo()->attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  getLDInfo()->attrFactory().predefined().setWholeArchive();
+  getLDInfo()->attrFactory().predefined().setDynamic();
+
+  // set up target dependent options
+  if (getLDInfo()->options().sysroot().empty())
+    getLDInfo()->options().setSysroot(gDefaultSysroot);
+
+  if (!getLDInfo()->options().hasDyld())
+    getLDInfo()->options().setDyld(gDefaultDyld);
+
+  // set up default search path
+  addSearchDir("=/lib");
+  addSearchDir("=/usr/lib");
+
+  return;
+}
+#endif // defined(PROVIDE_ARM_CODEGEN)
+
+//===----------------------------------------------------------------------===//
+// Mips
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_MIPS_CODEGEN)
+MipsLinkerConfig::MipsLinkerConfig()
+  : LinkerConfig(DEFAULT_MIPS_TRIPLE_STRING) {
+
+  // set up target-dependent constraints of attibutes
+  getLDInfo()->attrFactory().constraint().enableWholeArchive();
+  getLDInfo()->attrFactory().constraint().disableAsNeeded();
+  getLDInfo()->attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  getLDInfo()->attrFactory().predefined().setWholeArchive();
+  getLDInfo()->attrFactory().predefined().setDynamic();
+
+  // set up target dependent options
+  if (getLDInfo()->options().sysroot().empty())
+    getLDInfo()->options().setSysroot(gDefaultSysroot);
+
+  if (!getLDInfo()->options().hasDyld())
+    getLDInfo()->options().setDyld(gDefaultDyld);
+
+  // set up default search path
+  addSearchDir("=/lib");
+  addSearchDir("=/usr/lib");
+
+  return;
+}
+#endif // defined(PROVIDE_MIPS_CODEGEN)
+
+//===----------------------------------------------------------------------===//
+// X86 and X86_64
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_X86_CODEGEN)
+X86FamilyLinkerConfigBase::X86FamilyLinkerConfigBase(const std::string& pTriple)
+  : LinkerConfig(pTriple) {
+  // set up target-dependent constraints of attibutes
+  getLDInfo()->attrFactory().constraint().enableWholeArchive();
+  getLDInfo()->attrFactory().constraint().disableAsNeeded();
+  getLDInfo()->attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  getLDInfo()->attrFactory().predefined().setWholeArchive();
+  getLDInfo()->attrFactory().predefined().setDynamic();
+
+  // set up target dependent options
+  if (getLDInfo()->options().sysroot().empty())
+    getLDInfo()->options().setSysroot(gDefaultSysroot);
+
+  if (!getLDInfo()->options().hasDyld())
+    getLDInfo()->options().setDyld(gDefaultDyld);
+
+  // set up default search path
+  addSearchDir("=/lib");
+  addSearchDir("=/usr/lib");
+
+  return;
+}
+
+X86_32LinkerConfig::X86_32LinkerConfig()
+  : X86FamilyLinkerConfigBase(DEFAULT_X86_TRIPLE_STRING) {
+}
+
+X86_64LinkerConfig::X86_64LinkerConfig()
+  : X86FamilyLinkerConfigBase(DEFAULT_X86_64_TRIPLE_STRING) {
+}
+#endif // defined(PROVIDE_X86_CODEGEN)
diff --git a/tools/mcld/main.cpp b/tools/mcld/main.cpp
new file mode 100644
index 0000000..37610b8
--- /dev/null
+++ b/tools/mcld/main.cpp
@@ -0,0 +1,313 @@
+//===- mcld.cpp -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <stdlib.h>
+#include <string>
+
+#include <llvm/ADT/SmallString.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/FileSystem.h>
+#include <llvm/Support/Path.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/system_error.h>
+
+#include <alone/Config/Config.h>
+#include <alone/Support/LinkerConfig.h>
+#include <alone/Support/Initialization.h>
+#include <alone/Support/TargetLinkerConfigs.h>
+#include <alone/Linker.h>
+
+using namespace alone;
+
+//===----------------------------------------------------------------------===//
+// Compiler Options
+//===----------------------------------------------------------------------===//
+#ifdef TARGET_BUILD
+const std::string OptTargetTripe(DEFAULT_TARGET_TRIPLE_STRING);
+#else
+llvm::cl::opt<std::string>
+OptTargetTriple("mtriple",
+               llvm::cl::desc("Specify the target triple (default: "
+                              DEFAULT_TARGET_TRIPLE_STRING ")"),
+               llvm::cl::init(DEFAULT_TARGET_TRIPLE_STRING),
+               llvm::cl::value_desc("triple"));
+
+llvm::cl::alias OptTargetTripleC("C", llvm::cl::NotHidden,
+                                llvm::cl::desc("Alias for -mtriple"),
+                                llvm::cl::aliasopt(OptTargetTriple));
+#endif
+
+//===----------------------------------------------------------------------===//
+// Command Line Options
+// There are four kinds of command line options:
+//   1. input, (may be a file, such as -m and /tmp/XXXX.o.)
+//   2. scripting options, (represent a subset of link scripting language, such
+//      as --defsym.)
+//   3. and general options. (the rest of options)
+//===----------------------------------------------------------------------===//
+// General Options
+//===----------------------------------------------------------------------===//
+static llvm::cl::opt<std::string>
+OptOutputFilename("o",
+                  llvm::cl::desc("Output filename"),
+                  llvm::cl::value_desc("filename"));
+
+static llvm::cl::opt<std::string>
+OptSysRoot("sysroot",
+           llvm::cl::desc("Use directory as the location of the sysroot, overriding "
+                    "the configure-time default."),
+           llvm::cl::value_desc("directory"),
+           llvm::cl::ValueRequired);
+
+static llvm::cl::list<std::string>
+OptSearchDirList("L",
+                 llvm::cl::ZeroOrMore,
+                 llvm::cl::desc("Add path searchdir to the list of paths that ld will "
+                          "search for archive libraries and ld control scripts."),
+                 llvm::cl::value_desc("searchdir"),
+                 llvm::cl::Prefix);
+
+static llvm::cl::opt<std::string>
+OptSOName("soname",
+          llvm::cl::desc("Set internal name of shared library"),
+          llvm::cl::value_desc("name"));
+
+
+static llvm::cl::opt<bool>
+OptShared("shared",
+          llvm::cl::desc("Create a shared library."),
+          llvm::cl::init(false));
+
+static llvm::cl::opt<std::string>
+OptDyld("dynamic-linker",
+        llvm::cl::desc("Set the name of the dynamic linker."),
+        llvm::cl::value_desc("Program"));
+
+//===----------------------------------------------------------------------===//
+// Inputs
+//===----------------------------------------------------------------------===//
+static llvm::cl::list<std::string>
+OptInputObjectFiles(llvm::cl::Positional,
+                    llvm::cl::desc("[input object files]"),
+                    llvm::cl::ZeroOrMore);
+
+static llvm::cl::list<std::string>
+OptNameSpecList("l",
+                llvm::cl::ZeroOrMore,
+                llvm::cl::desc("Add the archive or object file specified by "
+                               "namespec to the list of files to link."),
+                llvm::cl::value_desc("namespec"),
+                llvm::cl::Prefix);
+
+//===----------------------------------------------------------------------===//
+// Scripting Options
+//===----------------------------------------------------------------------===//
+static llvm::cl::list<std::string>
+OptWrapList("wrap",
+            llvm::cl::ZeroOrMore,
+            llvm::cl::desc("Use a wrap function fo symbol."),
+            llvm::cl::value_desc("symbol"));
+
+//===----------------------------------------------------------------------===//
+// Helper Functions
+//===----------------------------------------------------------------------===//
+// Override "mcld -version"
+void MCLDVersionPrinter() {
+  llvm::raw_ostream &os = llvm::outs();
+  os << "mcld (The MCLinker Project, http://mclinker.googlecode.com/):\n"
+     << "  Default target: " << DEFAULT_TARGET_TRIPLE_STRING << "\n";
+
+  os << "\n";
+
+  os << "LLVM (http://llvm.org/):\n";
+  return;
+}
+
+#define DEFAULT_OUTPUT_PATH "a.out"
+static inline
+std::string DetermineOutputFilename(const std::string pOutputPath)
+{
+  if (!pOutputPath.empty()) {
+    return pOutputPath;
+  }
+
+  // User does't specify the value to -o
+  if (OptInputObjectFiles.size() > 1) {
+    llvm::errs() << "Use " DEFAULT_OUTPUT_PATH " for output file!\n";
+    return DEFAULT_OUTPUT_PATH;
+  }
+
+  // There's only one input file
+  const std::string &input_path = OptInputObjectFiles[0];
+  llvm::SmallString<200> output_path(input_path);
+
+  llvm::error_code err = llvm::sys::fs::make_absolute(output_path);
+  if (llvm::errc::success != err) {
+    llvm::errs() << "Failed to determine the absolute path of `" << input_path
+                 << "'! (detail: " << err.message() << ")\n";
+    return "";
+  }
+
+  llvm::sys::path::remove_filename(output_path);
+  llvm::sys::path::append(output_path, "a.out");
+
+  return output_path.c_str();
+}
+
+static inline
+bool ConfigLinker(Linker &pLinker, const std::string &pOutputFilename)
+{
+  LinkerConfig* config = NULL;
+
+#ifdef TARGET_BUILD
+  config = new (std::nothrow) DefaultLinkerConfig();
+#else
+  config = new (std::nothrow) LinkerConfig(OptTargetTriple);
+#endif
+  if (config == NULL) {
+    llvm::errs() << "Out of memory when create the linker configuration!\n";
+    return false;
+  }
+
+  // Setup the configuration accroding to the value of command line options.
+  // 1. set up soname
+  if (!OptSOName.empty())
+    config->setSOName(OptSOName);
+  else
+    config->setSOName(pOutputFilename);
+
+  // 2. if given, set up sysroot
+  if (!OptSysRoot.empty())
+    config->setSysRoot(OptSysRoot);
+
+  // 3. if given, set up dynamic linker path.
+  if (!OptDyld.empty())
+    config->setDyld(OptDyld);
+
+  // 4. if given, set up wrapped symbols
+  llvm::cl::list<std::string>::iterator wrap, wEnd = OptWrapList.end();
+  for (wrap = OptWrapList.begin(); wrap != wEnd; ++wrap)
+    config->addWrap(*wrap);
+
+  // 5. if given, set up search directories
+  llvm::cl::list<std::string>::iterator sdir, sdirEnd = OptSearchDirList.end();
+  for (sdir = OptSearchDirList.begin(); sdir != sdirEnd; ++sdir)
+    config->addSearchDir(*sdir);
+
+  Linker::ErrorCode result = pLinker.config(*config);
+
+  if (Linker::kSuccess != result) {
+    llvm::errs() << "Failed to configure the linker! (detail: "
+                << Linker::GetErrorString(result) << ")\n";
+    return false;
+  }
+
+  return true;
+}
+
+static inline
+bool PrepareInputOutput(Linker& pLinker, const std::string &pOutputPath)
+{
+  // -----  set output  ----- //
+  // FIXME: In MCLinker, we have to set up output before setting up inputs.
+  // This constraint is wired, and we should break this constraint.
+  Linker::ErrorCode result = pLinker.setOutput(pOutputPath);
+
+  if (Linker::kSuccess != result) {
+    llvm::errs() << "Failed to open the output file! (detail: "
+                 << pOutputPath << ": "
+                 << Linker::GetErrorString(result) << ")\n";
+    return false;
+  }
+
+  // -----  set inputs  ----- //
+  llvm::cl::list<std::string>::iterator fileIt = OptInputObjectFiles.begin();
+  llvm::cl::list<std::string>::iterator libIt  = OptNameSpecList.begin();
+
+  llvm::cl::list<std::string>::iterator fileBegin = OptInputObjectFiles.begin();
+  llvm::cl::list<std::string>::iterator libBegin = OptNameSpecList.begin();
+  llvm::cl::list<std::string>::iterator fileEnd = OptInputObjectFiles.end();
+  llvm::cl::list<std::string>::iterator libEnd = OptNameSpecList.end();
+
+  unsigned libPos = 0, filePos = 0;
+  while (true) {
+    if (libIt != libEnd)
+      libPos = OptNameSpecList.getPosition(libIt - libBegin);
+    else
+      libPos = 0;
+
+    if (fileIt != fileEnd)
+      filePos = OptInputObjectFiles.getPosition(fileIt - fileBegin);
+    else
+      filePos = 0;
+
+    if ( filePos != 0 && (libPos == 0 || filePos < libPos) ) {
+      result = pLinker.addObject(*fileIt);
+      if (Linker::kSuccess != result) {
+        llvm::errs() << "Failed to open the input file! (detail: "
+                     << *fileIt << ": "
+                     << Linker::GetErrorString(result) << ")\n";
+        return false;
+      }
+      ++fileIt;
+    }
+    else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) {
+      result = pLinker.addNameSpec(*libIt);
+      if (Linker::kSuccess != result) {
+        llvm::errs() << "Failed to open the namespec! (detail: "
+                     << *libIt << ": "
+                     << Linker::GetErrorString(result) << ")\n";
+        return false;
+      }
+      ++libIt;
+    }
+
+    else
+      break; // we're done with the list
+  }
+
+  return true;
+}
+
+static inline
+bool LinkFiles(Linker& pLinker) {
+  Linker::ErrorCode result = pLinker.link();
+  if (Linker::kSuccess != result) {
+    llvm::errs() << "Failed to linking! (detail: "
+                 << Linker::GetErrorString(result) << "\n";
+    return false;
+  }
+  return true;
+}
+
+int main(int argc, char* argv[])
+{
+  llvm::cl::SetVersionPrinter(MCLDVersionPrinter);
+  llvm::cl::ParseCommandLineOptions(argc, argv);
+  init::Initialize();
+
+  std::string OutputFilename = DetermineOutputFilename(OptOutputFilename);
+  if (OutputFilename.empty()) {
+    return EXIT_FAILURE;
+  }
+
+  Linker linker;
+  if (!ConfigLinker(linker, OutputFilename)) {
+    return EXIT_FAILURE;
+  }
+
+  if (!PrepareInputOutput(linker, OutputFilename)) {
+    return EXIT_FAILURE;
+  }
+
+  if (!LinkFiles(linker)) {
+    return EXIT_FAILURE;
+  }
+  return EXIT_SUCCESS;
+}
+
diff --git a/unittests/BinTreeTest.cpp b/unittests/BinTreeTest.cpp
index bce4b24..fdf2bd1 100644
--- a/unittests/BinTreeTest.cpp
+++ b/unittests/BinTreeTest.cpp
@@ -9,7 +9,7 @@
 #include "BinTreeTest.h"
 
 #include "mcld/ADT/TypeTraits.h"
-#include "mcld/MC/MCLDInputTree.h"
+#include "mcld/MC/InputTree.h"
 #include <string>
 
 using namespace mcld;
diff --git a/unittests/FileHandleTest.cpp b/unittests/FileHandleTest.cpp
new file mode 100644
index 0000000..993b07c
--- /dev/null
+++ b/unittests/FileHandleTest.cpp
@@ -0,0 +1,102 @@
+//===- implTest.cpp -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/Path.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "FileHandleTest.h"
+
+using namespace mcld;
+using namespace mcldtest;
+
+
+// Constructor can do set-up work for all test here.
+FileHandleTest::FileHandleTest()
+{
+  // create testee. modify it if need
+  m_pTestee = new FileHandle();
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+FileHandleTest::~FileHandleTest()
+{
+  delete m_pTestee;
+}
+
+// SetUp() will be called immediately before each test.
+void FileHandleTest::SetUp()
+{
+}
+
+// TearDown() will be called immediately after each test.
+void FileHandleTest::TearDown()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Testcases
+#include <iostream>
+using namespace std;
+
+TEST_F(FileHandleTest, open_close) {
+  mcld::sys::fs::Path path(TOPDIR);
+  path.append("unittests/test.txt");
+  ASSERT_TRUE(m_pTestee->open(path, FileHandle::ReadOnly));
+  ASSERT_TRUE(m_pTestee->isOpened());
+  ASSERT_TRUE(m_pTestee->isGood());
+
+  ASSERT_EQ(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());
+}
+
+TEST_F(FileHandleTest, delegate_close) {
+  mcld::sys::fs::Path path(TOPDIR);
+  path.append("unittests/test.txt");
+
+  int fd = ::open(path.native().c_str(), O_RDONLY);
+
+  ASSERT_TRUE(m_pTestee->delegate(fd, FileHandle::ReadOnly));
+  ASSERT_TRUE(m_pTestee->isOpened());
+  ASSERT_TRUE(m_pTestee->isGood());
+
+  ASSERT_EQ(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());
+
+  int close_result = ::close(fd);
+  int close_err = errno;
+  ASSERT_EQ(-1, close_result);
+  ASSERT_EQ(EBADF, close_err);
+}
+
+TEST_F(FileHandleTest, fail_close) {
+  mcld::sys::fs::Path path(TOPDIR);
+  path.append("unittests/test.txt");
+  ASSERT_TRUE(m_pTestee->open(path, FileHandle::ReadOnly));
+  ASSERT_TRUE(m_pTestee->isOpened());
+  ASSERT_TRUE(m_pTestee->isGood());
+
+  ASSERT_EQ(27, m_pTestee->size());
+
+  int close_result = ::close(m_pTestee->handler());
+  ASSERT_EQ(0, close_result);
+
+  ASSERT_FALSE(m_pTestee->close());
+  ASSERT_FALSE(m_pTestee->isOpened());
+  ASSERT_FALSE(m_pTestee->isGood());
+}
diff --git a/unittests/FileHandleTest.h b/unittests/FileHandleTest.h
new file mode 100644
index 0000000..88e2653
--- /dev/null
+++ b/unittests/FileHandleTest.h
@@ -0,0 +1,50 @@
+//===- headerTest.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_FILEHANDLE_TEST_H
+#define MCLD_FILEHANDLE_TEST_H
+
+#include <gtest.h>
+
+namespace mcld
+{
+class FileHandle;
+
+} // namespace for mcld
+
+namespace mcldtest
+{
+
+/** \class FileHandleTest
+ *  \brief 
+ *
+ *  \see FileHandle 
+ */
+class FileHandleTest : public ::testing::Test
+{
+public:
+  // Constructor can do set-up work for all test here.
+  FileHandleTest();
+
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~FileHandleTest();
+
+  // SetUp() will be called immediately before each test.
+  virtual void SetUp();
+
+  // TearDown() will be called immediately after each test.
+  virtual void TearDown();
+
+protected:
+  mcld::FileHandle* m_pTestee;
+};
+
+} // namespace of mcldtest
+
+#endif
+
diff --git a/unittests/InputTreeTest.cpp b/unittests/InputTreeTest.cpp
index 060eaad..0013601 100644
--- a/unittests/InputTreeTest.cpp
+++ b/unittests/InputTreeTest.cpp
@@ -6,7 +6,7 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInputTree.h"
+#include "mcld/MC/InputTree.h"
 #include "mcld/MC/MCLDInfo.h"
 #include <InputTreeTest.h>
 
diff --git a/unittests/LEB128Test.cpp b/unittests/LEB128Test.cpp
index 1f1467f..bd1aec2 100644
--- a/unittests/LEB128Test.cpp
+++ b/unittests/LEB128Test.cpp
@@ -456,7 +456,7 @@
 }
 
 TEST_F( LEB128Test, Random_Regression_Test) {
-  leb128::ByteType buffer[5];
+  leb128::ByteType buffer[9];
 
   for (int i = 0; i < 20; i++) {
     long int value = random();
diff --git a/unittests/MCFragmentRefTest.cpp b/unittests/MCFragmentRefTest.cpp
index 556fbdd..3da3463 100644
--- a/unittests/MCFragmentRefTest.cpp
+++ b/unittests/MCFragmentRefTest.cpp
@@ -6,10 +6,10 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include "mcld/MC/MCFragmentRef.h"
 #include "mcld/MC/MCRegionFragment.h"
 #include "mcld/Support/MemoryAreaFactory.h"
+#include "mcld/Support/FileHandle.h"
 #include "mcld/Support/Path.h"
 #include "MCFragmentRefTest.h"
 
@@ -45,7 +45,7 @@
   Path path(TOPDIR);
   path.append("unittests/test3.txt");
   MemoryAreaFactory* areaFactory = new MemoryAreaFactory(1);
-  MemoryArea* area = areaFactory->produce(path, MemoryArea::ReadWrite);
+  MemoryArea* area = areaFactory->produce(path, FileHandle::ReadWrite);
 
   MemoryRegion* region = area->request(0, 4096);
   MCRegionFragment *frag = new MCRegionFragment(*region);
diff --git a/unittests/MemoryAreaTest.cpp b/unittests/MemoryAreaTest.cpp
index a2e631a..0499a0d 100644
--- a/unittests/MemoryAreaTest.cpp
+++ b/unittests/MemoryAreaTest.cpp
@@ -6,13 +6,12 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-
-#include "mcld/Support/FileSystem.h"
-#include "mcld/Support/MemoryArea.h"
-#include "mcld/Support/MemoryRegion.h"
-#include "mcld/Support/MemoryAreaFactory.h"
-#include "mcld/Support/Path.h"
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/Path.h>
 
 #include "MemoryAreaTest.h"
 #include <fcntl.h>
@@ -50,12 +49,15 @@
 {
 	Path path(TOPDIR);
 	path.append("unittests/test3.txt");
+
 	MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1);
-	MemoryArea* area = AreaFactory->produce(path, O_RDONLY);
+	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadOnly);
 	MemoryRegion* region = area->request(3, 2);
 	ASSERT_EQ('L', region->getBuffer()[0]);
 	ASSERT_EQ('O', region->getBuffer()[1]);
-	delete AreaFactory;
+	area->release(region);
+	AreaFactory->destruct(area);
+	//delete AreaFactory;;
 }
 
 TEST_F( MemoryAreaTest, write_by_malloc )
@@ -63,23 +65,27 @@
 	Path path(TOPDIR);
 	path.append("unittests/test2.txt");
 	MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1);
-	MemoryArea* area = AreaFactory->produce(path, O_RDWR);
-        ASSERT_TRUE(area->isMapped());
-        ASSERT_TRUE(area->isGood());
+	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadOnly);
+        ASSERT_TRUE(area->handler()->isOpened());
+        ASSERT_TRUE(area->handler()->isGood());
 	MemoryRegion* region = area->request(3, 4);
 	region->getBuffer()[0] = 'L';
 	region->getBuffer()[1] = 'i';
 	region->getBuffer()[2] = 'n';
 	region->getBuffer()[3] = 'k';
-        area->sync();
-	area->unmap();
-        area->map(path, O_RDONLY);
-        ASSERT_TRUE(area->isMapped());
-        ASSERT_TRUE(area->isGood());
+	area->release(region);
+	area->clear();
+	area->handler()->close();
+
+        area->handler()->open(path, FileHandle::ReadOnly);
+        ASSERT_TRUE(area->handler()->isOpened());
+        ASSERT_TRUE(area->handler()->isGood());
         region = area->request(5, 2);
         ASSERT_EQ('n', region->getBuffer()[0]);
         ASSERT_EQ('k', region->getBuffer()[1]);
-	delete AreaFactory;
+	area->release(region);
+	AreaFactory->destruct(area);
+	//delete AreaFactory;;
 }
 
 TEST_F( MemoryAreaTest, read_one_page )
@@ -87,13 +93,15 @@
         Path path(TOPDIR) ;
 	path.append("unittests/test3.txt") ;
 	MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1) ;
-	MemoryArea* area = AreaFactory->produce(path, O_RDWR) ;
-	ASSERT_TRUE(area->isMapped()) ;
-	ASSERT_TRUE(area->isGood()) ;
-	MemoryRegion* region = area->request(0, 4096) ;
+	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadOnly) ;
+	ASSERT_TRUE(area->handler()->isOpened()) ;
+	ASSERT_TRUE(area->handler()->isGood()) ;
+	MemoryRegion* region = area->request(0, 4096);
 	ASSERT_EQ('H', region->getBuffer()[0]);
 	ASSERT_EQ('E', region->getBuffer()[1]);
-	delete AreaFactory ;
+	area->release(region);
+	AreaFactory->destruct(area);
+	//delete AreaFactory; ;
 }
 
 TEST_F( MemoryAreaTest, write_one_page )
@@ -101,22 +109,27 @@
         Path path(TOPDIR) ;
 	path.append("unittests/test2.txt") ;
         MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1) ;
-	MemoryArea* area = AreaFactory->produce(path, O_RDWR) ;
-	ASSERT_TRUE(area->isMapped()) ;
-	ASSERT_TRUE(area->isGood()) ;
+	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadWrite);
+	ASSERT_TRUE(area->handler()->isOpened()) ;
+	ASSERT_TRUE(area->handler()->isGood()) ;
 	MemoryRegion* region = area->request(0, 4096) ;
 	region->getBuffer()[4000] = 'K' ;
 	region->getBuffer()[4001] = 'R' ;
-	area->sync() ;
-	area->unmap() ;
-	area->map(path, O_RDONLY) ;
-	region = area->request(4000, 4) ;
+	ASSERT_EQ('K', region->getBuffer()[4000]);
+	ASSERT_EQ('R', region->getBuffer()[4001]);
+	area->release(region);
+	area->clear() ;
+	area->handler()->close();
+
+	area->handler()->open(path, FileHandle::ReadOnly);
+	region = area->request(4000, 4);
 	ASSERT_EQ('K', region->getBuffer()[0]);
 	ASSERT_EQ('R', region->getBuffer()[1]);
 	region->getBuffer()[0] = 'O' ;
 	region->getBuffer()[1] = 'H' ;
-        area->sync() ;
-	delete AreaFactory ;
+        area->clear() ;
+	AreaFactory->destruct(area);
+	//delete AreaFactory; ;
 }
 
 TEST_F( MemoryAreaTest, write_sync )
@@ -124,25 +137,29 @@
         Path path(TOPDIR) ;
 	path.append("unittests/test2.txt") ;
 	MemoryAreaFactory *AreaFactory = new MemoryAreaFactory(1) ;
-	MemoryArea* area = AreaFactory->produce(path, O_RDWR) ;
-	ASSERT_TRUE(area->isMapped()) ;
-	ASSERT_TRUE(area->isGood()) ;
+	MemoryArea* area = AreaFactory->produce(path, FileHandle::ReadWrite) ;
+	ASSERT_TRUE(area->handler()->isOpened()) ;
+	ASSERT_TRUE(area->handler()->isGood()) ;
 	MemoryRegion* region1 = area->request(0, 4096) ;
 	MemoryRegion* region2 = area->request(512, 1024) ;
 	region1->getBuffer()[1000] = 'L' ;
 	region1->getBuffer()[1001] = 'L' ;
 	region2->getBuffer()[488] = 'V' ;
 	region2->getBuffer()[489] = 'M' ;
-	area->sync() ;
-	area->unmap();
-	area->map(path, O_RDWR) ;
+	area->release(region1);
+	area->release(region2);
+	area->clear();
+	area->handler()->close();
+	area->handler()->open(path, FileHandle::ReadWrite);
 	region1 = area->request(0, 1024) ;
 	EXPECT_EQ('V', region1->getBuffer()[1000]) ;
 	EXPECT_EQ('M', region1->getBuffer()[1001]) ;
 	region1->getBuffer()[1000] = '@' ;
 	region1->getBuffer()[1001] = '@' ;
-	area->sync();
-	delete AreaFactory ;
+	area->release(region1);
+	area->clear();
+	AreaFactory->destruct(area);
+	//delete AreaFactory; ;
 }
 
 
diff --git a/unittests/NamePoolTest.cpp b/unittests/NamePoolTest.cpp
new file mode 100644
index 0000000..614ee6a
--- /dev/null
+++ b/unittests/NamePoolTest.cpp
@@ -0,0 +1,268 @@
+//===- NamePoolTest.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "NamePoolTest.h"
+#include <mcld/LD/NamePool.h>
+#include <mcld/LD/Resolver.h>
+#include <mcld/LD/StaticResolver.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <llvm/ADT/StringRef.h>
+#include <string>
+#include <cstdio>
+
+using namespace mcld;
+using namespace mcldtest;
+
+
+// Constructor can do set-up work for all test here.
+NamePoolTest::NamePoolTest()
+{
+  // create testee. modify it if need
+  StaticResolver resolver;
+  m_pTestee = new NamePool(resolver, 10);
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+NamePoolTest::~NamePoolTest()
+{
+  delete m_pTestee;
+}
+
+// SetUp() will be called immediately before each test.
+void NamePoolTest::SetUp()
+{
+}
+
+// TearDown() will be called immediately after each test.
+void NamePoolTest::TearDown()
+{
+}
+
+//==========================================================================//
+// Testcases
+//
+
+
+TEST_F( NamePoolTest, insertString ) {
+  const char *s1 = "Hello MCLinker";
+  llvm::StringRef result1 = m_pTestee->insertString(s1);
+  EXPECT_NE(s1, result1.data());
+  EXPECT_STREQ(s1, result1.data());
+}
+
+TEST_F( NamePoolTest, insertSameString ) {
+  const char *s1 = "Hello MCLinker";
+  std::string s2(s1);
+  llvm::StringRef result1 = m_pTestee->insertString(s1);
+  llvm::StringRef result2 = m_pTestee->insertString(s2.c_str());
+  EXPECT_STREQ(s1, result1.data());
+  EXPECT_STREQ(s2.c_str(), result2.data());
+  EXPECT_EQ(result1.data(), result2.data());
+}
+
+TEST_F( NamePoolTest, insert_local_defined_Symbol ) {
+  const char *name = "Hello MCLinker";
+  bool isDyn = false;
+  ResolveInfo::Type type = ResolveInfo::Function;
+  ResolveInfo::Desc desc = ResolveInfo::Define;
+  ResolveInfo::Binding binding = ResolveInfo::Local;
+  uint64_t value = 0;
+  uint64_t size = 0;
+  ResolveInfo::Visibility other = ResolveInfo::Default;
+  Resolver::Result result1;
+  m_pTestee->insertSymbol(name,
+                          isDyn,
+                          type,
+                          desc,
+                          binding,
+                          size,
+                          other,
+                          NULL,
+                          result1);
+
+  EXPECT_NE(name, result1.info->name());
+  EXPECT_STREQ(name, result1.info->name());
+  EXPECT_EQ(isDyn, result1.info->isDyn());
+  EXPECT_EQ(type, result1.info->type());
+  EXPECT_EQ(desc, result1.info->desc());
+  EXPECT_EQ(binding, result1.info->binding());
+  EXPECT_EQ(size, result1.info->size());
+  EXPECT_EQ(other, result1.info->visibility());
+
+  Resolver::Result result2;
+  m_pTestee->insertSymbol(name,
+                          isDyn,
+                          type,
+                          desc,
+                          binding,
+                          size,
+                          other,
+                          NULL,
+                          result2);
+
+  EXPECT_NE(name, result1.info->name());
+  EXPECT_STREQ(name, result1.info->name());
+  EXPECT_EQ(isDyn, result1.info->isDyn());
+  EXPECT_EQ(type, result1.info->type());
+  EXPECT_EQ(desc, result1.info->desc());
+  EXPECT_EQ(binding, result1.info->binding());
+  EXPECT_EQ(size, result1.info->size());
+  EXPECT_EQ(other, result1.info->visibility());
+
+  EXPECT_NE(result1.existent, result2.existent);
+}
+
+TEST_F( NamePoolTest, insert_global_reference_Symbol ) {
+  const char *name = "Hello MCLinker";
+  bool isDyn = false;
+  ResolveInfo::Type type = ResolveInfo::NoType;
+  ResolveInfo::Desc desc = ResolveInfo::Undefined;
+  ResolveInfo::Binding binding = ResolveInfo::Global;
+  uint64_t size = 0;
+  ResolveInfo::Visibility other = ResolveInfo::Default;
+  Resolver::Result result1;
+  m_pTestee->insertSymbol(name,
+                          isDyn,
+                          type,
+                          desc,
+                          binding,
+                          size,
+                          other,
+                          NULL,
+                          result1);
+
+  EXPECT_NE(name, result1.info->name());
+  EXPECT_STREQ(name, result1.info->name());
+  EXPECT_EQ(isDyn, result1.info->isDyn());
+  EXPECT_EQ(type, result1.info->type());
+  EXPECT_EQ(desc, result1.info->desc());
+  EXPECT_EQ(binding, result1.info->binding());
+  EXPECT_EQ(size, result1.info->size());
+  EXPECT_EQ(other, result1.info->visibility());
+
+  Resolver::Result result2;
+  m_pTestee->insertSymbol(name,
+                          isDyn,
+                          type,
+                          desc,
+                          binding,
+                          size,
+                          other,
+                          NULL,
+                          result2);
+
+  EXPECT_EQ(result1.info, result2.info);
+
+  Resolver::Result result3;
+  m_pTestee->insertSymbol("Different Symbol",
+                          isDyn,
+                          type,
+                          desc,
+                          binding,
+                          size,
+                          other,
+                          NULL,
+                          result3);
+
+
+  EXPECT_NE(result1.info, result3.info);
+}
+
+
+TEST_F( NamePoolTest, insertSymbol_after_insert_same_string ) {
+  const char *name = "Hello MCLinker";
+  bool isDyn = false;
+  LDSymbol::Type type = LDSymbol::Defined;
+  LDSymbol::Binding binding = LDSymbol::Global;
+  const llvm::MCSectionData *section = 0;
+  uint64_t value = 0;
+  uint64_t size = 0;
+  uint8_t other = 0;
+
+  const char *result1 =  m_pTestee->insertString(name);
+  LDSymbol *sym =  m_pTestee->insertSymbol(name,
+                                           isDyn,
+                                           type,
+                                           binding,
+                                           section,
+                                           value,
+                                           size,
+                                           other);
+
+  EXPECT_STREQ(name, sym->name());
+  EXPECT_EQ(result1, sym->name());
+
+  char s[16];
+  strcpy(s, result1);
+  const char *result2 = m_pTestee->insertString(result1);
+  const char *result3 = m_pTestee->insertString(s);
+
+  EXPECT_EQ(result1, result2);
+  EXPECT_EQ(result1, result3);
+}
+
+
+TEST_F( NamePoolTest, insert_16384_weak_reference_symbols ) {
+  char name[16];
+  bool isDyn = false;
+  LDSymbol::Type type = LDSymbol::Reference;
+  LDSymbol::Binding binding = LDSymbol::Weak;
+  const llvm::MCSectionData *section = 0;
+  uint64_t value = 0;
+  uint64_t size = 0;
+  uint8_t other = 0;
+  strcpy(name, "Hello MCLinker");
+  LDSymbol *syms[128][128];
+  for(int i=0; i<128 ;++i) {
+    name[0] = i;
+    for(int j=0; j<128 ;++j) {
+      name[1] = j;
+      syms[i][j] =  m_pTestee->insertSymbol(name,
+                                            isDyn,
+                                            type,
+                                            binding,
+                                            section,
+                                            value,
+                                            size,
+                                            other);
+
+      ASSERT_STREQ(name, syms[i][j]->name());
+    }
+  }
+  for(int i=127; i>=0 ;--i) {
+    name[0] = i;
+    for(int j=0; j<128 ;++j) {
+      name[1] = j;
+      LDSymbol *sym =  m_pTestee->insertSymbol(name,
+                                               isDyn,
+                                               type,
+                                               binding,
+                                               section,
+                                               value,
+                                               size,
+                                               other);
+      ASSERT_EQ(sym, syms[i][j]);
+    }
+  }
+  for(int i=0; i<128 ;++i) {
+    name[0] = i;
+    for(int j=0; j<128 ;++j) {
+      name[1] = j;
+      LDSymbol *sym =  m_pTestee->insertSymbol(name,
+                                               isDyn,
+                                               type,
+                                               binding,
+                                               section,
+                                               value,
+                                               size,
+                                               other);
+      ASSERT_EQ(sym, syms[i][j]);
+    }
+  }
+}
diff --git a/unittests/StrSymPoolTest.h b/unittests/NamePoolTest.h
similarity index 73%
rename from unittests/StrSymPoolTest.h
rename to unittests/NamePoolTest.h
index 041fafa..12103e0 100644
--- a/unittests/StrSymPoolTest.h
+++ b/unittests/NamePoolTest.h
@@ -1,4 +1,4 @@
-//===- StrSymPoolTest.h ---------------------------------------------------===//
+//===- NamePoolTest.h ---------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -13,26 +13,26 @@
 
 namespace mcld
 {
-class StrSymPool;
+class NamePool;
 
 } // namespace for mcld
 
 namespace mcldtest
 {
 
-/** \class StrSymPoolTest
+/** \class NamePoolTest
  *  \brief 
  *
- *  \see StrSymPool 
+ *  \see NamePool 
  */
-class StrSymPoolTest : public ::testing::Test
+class NamePoolTest : public ::testing::Test
 {
 public:
 	// Constructor can do set-up work for all test here.
-	StrSymPoolTest();
+	NamePoolTest();
 
 	// Destructor can do clean-up work that doesn't throw exceptions here.
-	virtual ~StrSymPoolTest();
+	virtual ~NamePoolTest();
 
 	// SetUp() will be called immediately before each test.
 	virtual void SetUp();
@@ -41,7 +41,7 @@
 	virtual void TearDown();
 
 protected:
-	mcld::StrSymPool* m_pTestee;
+	mcld::NamePool* m_pTestee;
 };
 
 } // namespace of mcldtest
diff --git a/unittests/StaticResolverTest.cpp b/unittests/StaticResolverTest.cpp
index f9dfdf4..0e1e5c9 100644
--- a/unittests/StaticResolverTest.cpp
+++ b/unittests/StaticResolverTest.cpp
@@ -6,12 +6,22 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#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 <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;
@@ -23,6 +33,13 @@
   // 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();
+  m_pPrinter = new mcld::DiagnosticPrinter(); //llvm::errs(), *m_pLDInfo);
+  mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, m_pPrinter);
+
 }
 
 // Destructor can do clean-up work that doesn't throw exceptions here.
@@ -30,6 +47,7 @@
 {
   delete m_pResolver;
   delete m_pFactory;
+  delete m_pLDInfo;
 }
 
 // SetUp() will be called immediately before each test.
@@ -55,10 +73,9 @@
   ASSERT_TRUE( mcld::ResolveInfo::define_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::define_flag == old_sym->info());
   bool override = true;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ( Resolver::Abort, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_FALSE( override );
-  ASSERT_STREQ( "multiple definitions of `abc'.", m_pResolver->mesg().c_str() );
 }
 
 TEST_F( StaticResolverTest, DynDefAfterDynUndef ) {
@@ -82,8 +99,8 @@
   ASSERT_EQ( mcld::ResolveInfo::Define,    old_sym->desc());
 
   bool override = false;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ( Resolver::Success, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_EQ(1, old_sym->size());
 }
@@ -109,8 +126,8 @@
   ASSERT_EQ( mcld::ResolveInfo::Define, old_sym->desc());
 
   bool override = false;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ( Resolver::Success, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_EQ(1, old_sym->size());
 }
@@ -136,8 +153,8 @@
   ASSERT_EQ( mcld::ResolveInfo::Undefined, old_sym->desc());
 
   bool override = false;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ( Resolver::Success, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_EQ(1, old_sym->size());
 }
@@ -158,8 +175,8 @@
   ASSERT_TRUE( mcld::ResolveInfo::global_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::weak_flag == old_sym->info());
   bool override = false;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ( Resolver::Success, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_TRUE( override );
   ASSERT_EQ(0, old_sym->size());
 }
@@ -187,8 +204,8 @@
   ASSERT_EQ( mcld::ResolveInfo::Define, new_sym->desc());
 
   bool override = false;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ( Resolver::Success, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_EQ(1, old_sym->size());
 }
@@ -209,8 +226,8 @@
   ASSERT_TRUE( mcld::ResolveInfo::common_flag == new_sym->info());
   ASSERT_TRUE( mcld::ResolveInfo::common_flag == old_sym->info());
   bool override = true;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ( Resolver::Success, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_FALSE( override );
   ASSERT_EQ(999, old_sym->size());
 }
@@ -234,8 +251,8 @@
   ASSERT_TRUE( (ResolveInfo::weak_flag | ResolveInfo::common_flag) == old_sym->info());
 
   bool override = false;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ( Resolver::Success, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_TRUE( override );
   ASSERT_EQ(999, old_sym->size());
 }
@@ -258,13 +275,10 @@
   ASSERT_TRUE( ResolveInfo::common_flag == old_sym->info());
 
   bool override = false;
-  unsigned int result = m_pResolver->resolve(*old_sym, *new_sym, override);
-  ASSERT_EQ(Resolver::Warning, result);
+  bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
+  ASSERT_TRUE(result);
   ASSERT_TRUE( override );
   ASSERT_EQ(999, old_sym->size());
-  
-  ASSERT_STREQ("definition of 'abc' is overriding common.", m_pResolver->mesg().c_str() );
-
 }
 
 TEST_F( StaticResolverTest, SetUpDesc)
diff --git a/unittests/StaticResolverTest.h b/unittests/StaticResolverTest.h
index 8b8ba31..e4ffa50 100644
--- a/unittests/StaticResolverTest.h
+++ b/unittests/StaticResolverTest.h
@@ -10,6 +10,7 @@
 #define STATICRESOLVER_TEST_H
 
 #include <gtest.h>
+#include <mcld/MC/MCLDInfo.h>
 
 namespace mcld
 {
@@ -29,21 +30,24 @@
 class StaticResolverTest : public ::testing::Test
 {
 public:
-	// Constructor can do set-up work for all test here.
-	StaticResolverTest();
+  // Constructor can do set-up work for all test here.
+  StaticResolverTest();
 
-	// Destructor can do clean-up work that doesn't throw exceptions here.
-	virtual ~StaticResolverTest();
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~StaticResolverTest();
 
-	// 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::StaticResolver* m_pResolver;
-	mcld::ResolveInfoFactory* m_pFactory;
+  mcld::StaticResolver* m_pResolver;
+  mcld::ResolveInfoFactory* m_pFactory;
+  mcld::MCLDInfo* m_pLDInfo;
+  mcld::DiagnosticLineInfo* m_pLineInfo;
+  mcld::DiagnosticPrinter* m_pPrinter;
 };
 
 } // namespace of mcldtest
diff --git a/unittests/StrSymPoolTest.cpp b/unittests/StrSymPoolTest.cpp
deleted file mode 100644
index a4ef558..0000000
--- a/unittests/StrSymPoolTest.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-//===- StrSymPoolTest.cpp -------------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/StrSymPool.h"
-#include "StrSymPoolTest.h"
-#include <string>
-#include <cstdio>
-
-using namespace mcld;
-using namespace mcldtest;
-
-
-// Constructor can do set-up work for all test here.
-StrSymPoolTest::StrSymPoolTest()
-{
-	// create testee. modify it if need
-  Resolver resolver;
-	m_pTestee = new StrSymPool(1, 1, resolver);
-}
-
-// Destructor can do clean-up work that doesn't throw exceptions here.
-StrSymPoolTest::~StrSymPoolTest()
-{
-	delete m_pTestee;
-}
-
-// SetUp() will be called immediately before each test.
-void StrSymPoolTest::SetUp()
-{
-}
-
-// TearDown() will be called immediately after each test.
-void StrSymPoolTest::TearDown()
-{
-}
-
-//==========================================================================//
-// Testcases
-//
-
-
-TEST_F( StrSymPoolTest, insertString ) {
-  const char *s1 = "Hello MCLinker";
-  const char *result1 = m_pTestee->insertString(s1);
-  EXPECT_NE(s1, result1);
-  EXPECT_STREQ(s1, result1);
-}
-
-TEST_F( StrSymPoolTest, insertSameString ) {
-  const char *s1 = "Hello MCLinker";
-  std::string s2(s1);
-  const char *result1 = m_pTestee->insertString(s1);
-  const char *result2 = m_pTestee->insertString(s2.c_str());
-  EXPECT_STREQ(s1, result1);
-  EXPECT_STREQ(s2.c_str(), result2);
-  EXPECT_EQ(result1, result2);
-}
-
-TEST_F( StrSymPoolTest, insert_local_defined_Symbol ) {
-  const char *name = "Hello MCLinker";
-  bool isDyn = false;
-  LDSymbol::Type type = LDSymbol::Defined;
-  LDSymbol::Binding binding = LDSymbol::Local;
-  const llvm::MCSectionData *section = 0;
-  uint64_t value = 0;
-  uint64_t size = 0;
-  uint8_t other = 0;
-
-  LDSymbol *sym =  m_pTestee->insertSymbol(name,
-                                           isDyn,
-                                           type,
-                                           binding,
-                                           section,
-                                           value,
-                                           size,
-                                           other);
-  EXPECT_NE(name, sym->name());
-  EXPECT_STREQ(name, sym->name());
-  EXPECT_EQ(isDyn, sym->isDyn());
-  EXPECT_EQ(type, sym->type());
-  EXPECT_EQ(binding, sym->binding());
-  EXPECT_EQ(section, sym->section());
-  EXPECT_EQ(value, sym->value());
-  EXPECT_EQ(size, sym->size());
-  EXPECT_EQ(other, sym->other());
-
-  LDSymbol *sym2 =  m_pTestee->insertSymbol(name,
-                                            isDyn,
-                                            type,
-                                            binding,
-                                            section,
-                                            value,
-                                            size,
-                                            other);
-  EXPECT_NE(name, sym2->name());
-  EXPECT_STREQ(name, sym2->name());
-  EXPECT_EQ(isDyn, sym2->isDyn());
-  EXPECT_EQ(type, sym2->type());
-  EXPECT_EQ(binding, sym2->binding());
-  EXPECT_EQ(section, sym2->section());
-  EXPECT_EQ(value, sym2->value());
-  EXPECT_EQ(size, sym2->size());
-  EXPECT_EQ(other, sym2->other());
-
-
-  EXPECT_NE(sym, sym2);
-}
-
-TEST_F( StrSymPoolTest, insert_global_reference_Symbol ) {
-  const char *name = "Hello MCLinker";
-  bool isDyn = false;
-  LDSymbol::Type type = LDSymbol::Reference;
-  LDSymbol::Binding binding = LDSymbol::Global;
-  const llvm::MCSectionData *section = 0;
-  uint64_t value = 0;
-  uint64_t size = 0;
-  uint8_t other = 0;
-
-  LDSymbol *sym =  m_pTestee->insertSymbol(name,
-                                           isDyn,
-                                           type,
-                                           binding,
-                                           section,
-                                           value,
-                                           size,
-                                           other);
-  EXPECT_NE(name, sym->name());
-  EXPECT_STREQ(name, sym->name());
-  EXPECT_EQ(isDyn, sym->isDyn());
-  EXPECT_EQ(type, sym->type());
-  EXPECT_EQ(binding, sym->binding());
-  EXPECT_EQ(section, sym->section());
-  EXPECT_EQ(value, sym->value());
-  EXPECT_EQ(size, sym->size());
-  EXPECT_EQ(other, sym->other());
-
-
-  LDSymbol *sym2 =  m_pTestee->insertSymbol(name,
-                                            isDyn,
-                                            type,
-                                            binding,
-                                            section,
-                                            value,
-                                            size,
-                                            other);
-
-
-  EXPECT_EQ(sym, sym2);
-
-
-  LDSymbol *sym3 =  m_pTestee->insertSymbol("Different symbol",
-                                            isDyn,
-                                            type,
-                                            binding,
-                                            section,
-                                            value,
-                                            size,
-                                            other);
-
-  EXPECT_NE(sym, sym3);
-}
-
-
-TEST_F( StrSymPoolTest, insertSymbol_after_insert_same_string ) {
-  const char *name = "Hello MCLinker";
-  bool isDyn = false;
-  LDSymbol::Type type = LDSymbol::Defined;
-  LDSymbol::Binding binding = LDSymbol::Global;
-  const llvm::MCSectionData *section = 0;
-  uint64_t value = 0;
-  uint64_t size = 0;
-  uint8_t other = 0;
-
-  const char *result1 =  m_pTestee->insertString(name);
-  LDSymbol *sym =  m_pTestee->insertSymbol(name,
-                                           isDyn,
-                                           type,
-                                           binding,
-                                           section,
-                                           value,
-                                           size,
-                                           other);
-
-  EXPECT_STREQ(name, sym->name());
-  EXPECT_EQ(result1, sym->name());
-
-  char s[16];
-  strcpy(s, result1);
-  const char *result2 = m_pTestee->insertString(result1);
-  const char *result3 = m_pTestee->insertString(s);
-
-  EXPECT_EQ(result1, result2);
-  EXPECT_EQ(result1, result3);
-}
-
-
-TEST_F( StrSymPoolTest, insert_16384_weak_reference_symbols ) {
-  char name[16];
-  bool isDyn = false;
-  LDSymbol::Type type = LDSymbol::Reference;
-  LDSymbol::Binding binding = LDSymbol::Weak;
-  const llvm::MCSectionData *section = 0;
-  uint64_t value = 0;
-  uint64_t size = 0;
-  uint8_t other = 0;
-  strcpy(name, "Hello MCLinker");
-  LDSymbol *syms[128][128];
-  for(int i=0; i<128 ;++i) {
-    name[0] = i;
-    for(int j=0; j<128 ;++j) {
-      name[1] = j;
-      syms[i][j] =  m_pTestee->insertSymbol(name,
-                                            isDyn,
-                                            type,
-                                            binding,
-                                            section,
-                                            value,
-                                            size,
-                                            other);
-
-      ASSERT_STREQ(name, syms[i][j]->name());
-    }
-  }
-  for(int i=127; i>=0 ;--i) {
-    name[0] = i;
-    for(int j=0; j<128 ;++j) {
-      name[1] = j;
-      LDSymbol *sym =  m_pTestee->insertSymbol(name,
-                                               isDyn,
-                                               type,
-                                               binding,
-                                               section,
-                                               value,
-                                               size,
-                                               other);
-      ASSERT_EQ(sym, syms[i][j]);
-    }
-  }
-  for(int i=0; i<128 ;++i) {
-    name[0] = i;
-    for(int j=0; j<128 ;++j) {
-      name[1] = j;
-      LDSymbol *sym =  m_pTestee->insertSymbol(name,
-                                               isDyn,
-                                               type,
-                                               binding,
-                                               section,
-                                               value,
-                                               size,
-                                               other);
-      ASSERT_EQ(sym, syms[i][j]);
-    }
-  }
-}
diff --git a/unittests/UniqueGCFactoryBaseTest.cpp b/unittests/UniqueGCFactoryBaseTest.cpp
index 08f82ba..328e924 100644
--- a/unittests/UniqueGCFactoryBaseTest.cpp
+++ b/unittests/UniqueGCFactoryBaseTest.cpp
@@ -6,8 +6,11 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/ContextFactory.h"
-#include "mcld/Support/MemoryAreaFactory.h"
+#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"
 
 using namespace mcld;
@@ -17,6 +20,12 @@
 // Constructor can do set-up work for all test here.
 UniqueGCFactoryBaseTest::UniqueGCFactoryBaseTest()
 {
+  InitializeAllDiagnostics();
+
+  m_pLDInfo = new MCLDInfo("arm-none-linux-gnueabi", 10, 10);
+  m_pLineInfo = new DiagnosticLineInfo();
+  m_pPrinter = new mcld::DiagnosticPrinter(); //llvm::errs(), *m_pLDInfo);
+  mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, m_pPrinter);
 }
 
 // Destructor can do clean-up work that doesn't throw exceptions here.
@@ -67,12 +76,18 @@
 
 TEST_F( UniqueGCFactoryBaseTest, iterator )
 {
+        sys::fs::Path path1(TOPDIR), path2(TOPDIR);
+	path1.append("unittests/test1.txt");
+	path2.append("unittests/test2.txt");
+
 	MemoryAreaFactory* memFactory = new MemoryAreaFactory(10);
-	MemoryArea* area1 = memFactory->produce("/home/luba", O_RDONLY);
-	MemoryArea* area2 = memFactory->produce("/home/jush", O_RDONLY);
+	MemoryArea* area1 = memFactory->produce(path1, FileHandle::ReadOnly);
+	MemoryArea* area2 = memFactory->produce(path2, FileHandle::ReadOnly);
 	ASSERT_NE( area1, area2);
-	MemoryArea* area3 = memFactory->produce("/home/jush/../luba", O_RDONLY);
-	ASSERT_EQ( area1, area3);
+
+	MemoryArea* area3 = memFactory->produce(path1, FileHandle::ReadOnly);
+	
+	ASSERT_EQ(area1, area3);
 	ASSERT_FALSE( memFactory->empty());
 	ASSERT_EQ( 2, memFactory->size());
 	MemoryAreaFactory::iterator aIter = memFactory->begin();
diff --git a/unittests/UniqueGCFactoryBaseTest.h b/unittests/UniqueGCFactoryBaseTest.h
index a1558e7..525c8c4 100644
--- a/unittests/UniqueGCFactoryBaseTest.h
+++ b/unittests/UniqueGCFactoryBaseTest.h
@@ -9,7 +9,10 @@
 #ifndef UNIQUE_GCFACTORYBASE_TEST_H
 #define UNIQUE_GCFACTORYBASE_TEST_H
 
-#include "mcld/Support/UniqueGCFactory.h"
+#include <mcld/Support/UniqueGCFactory.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
 #include <gtest.h>
 
 namespace mcldtest
@@ -34,6 +37,11 @@
 
 	// TearDown() will be called immediately after each test.
 	virtual void TearDown();
+
+private:
+	mcld::MCLDInfo* m_pLDInfo;
+	mcld::DiagnosticLineInfo* m_pLineInfo;
+	mcld::DiagnosticPrinter* m_pPrinter;
 };
 
 } // namespace of mcldtest