MCLinker upstream commit 7720f766. BUG=6886348.

Change-Id: Ifc03fbe870c8993893e92c2e55a9c3f6e3877849
diff --git a/include/mcld/ADT/BinTree.h b/include/mcld/ADT/BinTree.h
index da30a89..f015ac8 100644
--- a/include/mcld/ADT/BinTree.h
+++ b/include/mcld/ADT/BinTree.h
@@ -135,11 +135,8 @@
   reference operator->() const
   { return *static_cast<node_type*>(IteratorType::m_pNode)->data; }
 
-  bool isRoot() const
-  { return (IteratorType::m_pNode->right == IteratorType::m_pNode); }
-
   bool hasData() const
-  { return (!isRoot() && (0 != static_cast<node_type*>(IteratorType::m_pNode)->data)); }
+  { return (!IteratorType::isRoot() && (0 != static_cast<node_type*>(IteratorType::m_pNode)->data)); }
 
 };
 
diff --git a/include/mcld/ADT/TreeBase.h b/include/mcld/ADT/TreeBase.h
index 4df8d0d..10e0892 100644
--- a/include/mcld/ADT/TreeBase.h
+++ b/include/mcld/ADT/TreeBase.h
@@ -70,6 +70,9 @@
     proxy::move<DIRECT>(m_pNode);
   }
 
+  bool isRoot() const
+  { return (m_pNode->right == m_pNode); }
+
   bool hasRightChild() const
   { return ((m_pNode->right) != (m_pNode->right->right)); }
 
diff --git a/include/mcld/LD/DiagCommonKinds.inc b/include/mcld/LD/DiagCommonKinds.inc
index 25cbb8f..ac3d0e1 100644
--- a/include/mcld/LD/DiagCommonKinds.inc
+++ b/include/mcld/LD/DiagCommonKinds.inc
@@ -34,8 +34,11 @@
 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(err_out_of_range_region, DiagnosticEngine::Unreachable, "requested memory region [%0, %1] is out of range.", "requested memory region [%0, %1] 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")
+DIAG(fatal_cannot_init_target, DiagnosticEngine::Fatal, "Cannot initialize mcld::Target for given triple '%0'.\n(Detail: %1)", "Cannot initialize mcld::Target for given triple '%0'.\n(Detail: %1)")
+DIAG(fatal_cannot_init_lineinfo, DiagnosticEngine::Fatal, "Cannot initialize mcld::DiagnosticLineInfo for given triple '%0'", "Cannot initialize mcld::DiagnosticLineInfo for given triple '%0'")
+DIAG(fatal_cannot_init_backend, DiagnosticEngine::Fatal, "Cannot initialize mcld::TargetLDBackend for given triple '%0'.", "Cannot initialize mcld::TargetLDBackend for given triple '%0'.")
diff --git a/include/mcld/LD/DiagnosticEngine.h b/include/mcld/LD/DiagnosticEngine.h
index 9c106e5..77666ab 100644
--- a/include/mcld/LD/DiagnosticEngine.h
+++ b/include/mcld/LD/DiagnosticEngine.h
@@ -57,14 +57,14 @@
   };
 
 public:
-  DiagnosticEngine(const MCLDInfo& pLDInfo,
-                   DiagnosticLineInfo* pLineInfo = NULL,
-                   DiagnosticPrinter* pPrinter = NULL,
-                   bool pShouldOwnPrinter = true);
+  DiagnosticEngine();
 
   ~DiagnosticEngine();
 
-  // -----  printer functions  ----- //
+  void reset(const MCLDInfo& pLDInfo);
+
+  void setLineInfo(DiagnosticLineInfo& pLineInfo);
+
   void setPrinter(DiagnosticPrinter& pPrinter, bool pShouldOwnPrinter = true);
 
   DiagnosticPrinter* getPrinter()
@@ -128,17 +128,21 @@
   const State& state() const
   { return m_State; }
 
-  DiagnosticInfos& infoMap()
-  { return m_InfoMap; }
+  DiagnosticInfos& infoMap() {
+    assert(NULL != m_pInfoMap && "DiagnosticEngine was not initialized!");
+    return *m_pInfoMap;
+  }
 
-  const DiagnosticInfos& infoMap() const
-  { return m_InfoMap; }
+  const DiagnosticInfos& infoMap() const {
+    assert(NULL != m_pInfoMap && "DiagnosticEngine was not initialized!");
+    return *m_pInfoMap;
+  }
 
 private:
-  const MCLDInfo& m_LDInfo;
+  const MCLDInfo* m_pLDInfo;
   DiagnosticLineInfo* m_pLineInfo;
   DiagnosticPrinter* m_pPrinter;
-  DiagnosticInfos m_InfoMap;
+  DiagnosticInfos* m_pInfoMap;
   bool m_OwnPrinter;
 
   State m_State;
diff --git a/include/mcld/LD/ELFReader.h b/include/mcld/LD/ELFReader.h
index d232cab..a247804 100644
--- a/include/mcld/LD/ELFReader.h
+++ b/include/mcld/LD/ELFReader.h
@@ -86,6 +86,7 @@
                            const char* StrTab) const = 0;
 
   /// readSymbol - read a symbol from the given Input and index in symtab
+  /// This is used to get the signature of a group section.
   virtual ResolveInfo* readSymbol(Input& pInput,
                                   LDSection& pSymTab,
                                   MCLDInfo& pLDInfo,
@@ -207,6 +208,7 @@
                           const char* StrTab) const;
 
   /// readSymbol - read a symbol from the given Input and index in symtab
+  /// This is used to get the signature of a group section.
   inline ResolveInfo* readSymbol(Input& pInput,
                                  LDSection& pSymTab,
                                  MCLDInfo& pLDInfo,
diff --git a/include/mcld/LD/ELFReader.tcc b/include/mcld/LD/ELFReader.tcc
index 61e8331..4f5c036 100644
--- a/include/mcld/LD/ELFReader.tcc
+++ b/include/mcld/LD/ELFReader.tcc
@@ -112,7 +112,8 @@
   if (0x0 == shoff)
     return true;
 
-  MemoryRegion* shdr_region = pInput.memArea()->request(shoff, shnum*shentsize);
+  MemoryRegion* shdr_region = pInput.memArea()->request(
+                                 pInput.fileOffset() + shoff, shnum*shentsize);
   llvm::ELF::Elf32_Shdr* shdrTab =
                 reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
 
@@ -136,8 +137,10 @@
     sh_size   = bswap32(shdr->sh_size);
   }
 
-  MemoryRegion* sect_name_region = pInput.memArea()->request(sh_offset, sh_size);
-  const char* sect_name = reinterpret_cast<const char*>(sect_name_region->start());
+  MemoryRegion* sect_name_region = pInput.memArea()->request(
+                                      pInput.fileOffset() + sh_offset, sh_size);
+  const char* sect_name =
+                       reinterpret_cast<const char*>(sect_name_region->start());
 
   LinkInfoList link_info_list;
 
@@ -217,8 +220,8 @@
                                                          pInputSectHdr.type(),
                                                          pInputSectHdr.flag());
 
-  MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(),
-                                                   pInputSectHdr.size());
+  MemoryRegion* region = pInput.memArea()->request(
+           pInput.fileOffset() + pInputSectHdr.offset(), pInputSectHdr.size());
 
   llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
 
@@ -360,6 +363,7 @@
 }
 
 /// readSymbol - read a symbol from the given Input and index in symtab
+/// This is used to get the signature of a group section.
 ResolveInfo* ELFReader<32, true>::readSymbol(Input& pInput,
                                              LDSection& pSymTab,
                                              MCLDInfo& pLDInfo,
@@ -369,7 +373,8 @@
   LDSection* strtab = symtab->getLink();
   assert(NULL != symtab && NULL != strtab);
 
-  uint32_t offset = symtab->offset() + sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
+  uint32_t offset = pInput.fileOffset() + symtab->offset() +
+                      sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
   MemoryRegion* symbol_region =
                 pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
   llvm::ELF::Elf32_Sym* entry =
@@ -396,11 +401,12 @@
     st_shndx = bswap16(entry->st_shndx);
   }
 
-  MemoryRegion* strtab_region =
-                    pInput.memArea()->request(strtab->offset(), strtab->size());
+  MemoryRegion* strtab_region = pInput.memArea()->request(
+                       pInput.fileOffset() + strtab->offset(), strtab->size());
 
   // get ld_name
-  llvm::StringRef ld_name(reinterpret_cast<char*>(strtab_region->start() + st_name));
+  llvm::StringRef ld_name(
+                    reinterpret_cast<char*>(strtab_region->start() + st_name));
 
   // get ld_type
   ResolveInfo::Type ld_type = static_cast<ResolveInfo::Type>(st_info & 0xF);
@@ -409,7 +415,8 @@
   ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
 
   // get ld_binding
-  ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
+  ResolveInfo::Binding ld_binding =
+                             getSymBinding((st_info >> 4), st_shndx, st_other);
 
   // get ld_vis
   ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
@@ -539,11 +546,11 @@
     fatal(diag::err_cannot_read_section) << ".dynstr";
   }
 
-  MemoryRegion* dynamic_region =
-    pInput.memArea()->request(dynamic_sect->offset(), dynamic_sect->size());
+  MemoryRegion* dynamic_region = pInput.memArea()->request(
+           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
 
-  MemoryRegion* dynstr_region =
-    pInput.memArea()->request(dynstr_sect->offset(), dynstr_sect->size());
+  MemoryRegion* dynstr_region = pInput.memArea()->request(
+             pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
 
   assert(NULL != dynamic_region && NULL != dynstr_region);
 
diff --git a/include/mcld/LD/EhFrame.h b/include/mcld/LD/EhFrame.h
index 2e0d2c5..c303240 100644
--- a/include/mcld/LD/EhFrame.h
+++ b/include/mcld/LD/EhFrame.h
@@ -28,6 +28,7 @@
  */
 
 class TargetLDBackend;
+class Input;
 
 class EhFrame
 {
@@ -54,6 +55,7 @@
   uint64_t readEhFrame(Layout& pLayout,
                        const TargetLDBackend& pBackend,
                        llvm::MCSectionData& pSD,
+                       const Input& pInput,
                        LDSection& pSection,
                        MemoryArea& pArea);
 
diff --git a/include/mcld/LD/RelocationFactory.h b/include/mcld/LD/RelocationFactory.h
index eed3eae..717a709 100644
--- a/include/mcld/LD/RelocationFactory.h
+++ b/include/mcld/LD/RelocationFactory.h
@@ -37,14 +37,22 @@
   typedef Relocation::Address Address;
   typedef Relocation::DWord DWord;
 
+  enum Result {
+    OK,
+    BadReloc,
+    Overflow,
+    Unsupport,
+    Unknown
+  };
+
 public:
   explicit RelocationFactory(size_t pNum);
 
   virtual ~RelocationFactory();
 
   /// apply - general apply function
-  virtual void applyRelocation(Relocation& pRelocation,
-                               const MCLDInfo& pLDInfo) = 0;
+  virtual Result applyRelocation(Relocation& pRelocation,
+                                 const MCLDInfo& pLDInfo) = 0;
 
   // ----- production ----- //
   /// produce - produce a relocation entry
@@ -70,6 +78,8 @@
 
   virtual const TargetLDBackend& getTarget() const = 0;
 
+  virtual const char* getName(Type pType) const = 0;
+
 private:
   const Layout* m_pLayout;
 
diff --git a/include/mcld/MC/InputTree.h b/include/mcld/MC/InputTree.h
index fa6ba8f..5916916 100644
--- a/include/mcld/MC/InputTree.h
+++ b/include/mcld/MC/InputTree.h
@@ -99,19 +99,19 @@
    */
   struct Mover {
     virtual ~Mover() {}
-    virtual void connect(iterator& pFrom, const const_iterator& pTo) const = 0;
-    virtual void move(iterator& pNode) const = 0;
+    virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const = 0;
+    virtual void move(TreeIteratorBase& pNode) const = 0;
   };
 
   /** \class Succeeder
    *  \brief class Succeeder moves the iterator afterward.
    */
   struct Succeeder : public Mover {
-    virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
+    virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const {
       proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
     }
 
-    virtual void move(iterator& pNode) const {
+    virtual void move(TreeIteratorBase& pNode) const {
       pNode.move<Positional>();
     }
   };
@@ -120,11 +120,11 @@
    *  \brief class Includer moves the iterator downward.
    */
   struct Includer : public Mover {
-    virtual void connect(iterator& pFrom, const const_iterator& pTo) const {
+    virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const {
       proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
     }
 
-    virtual void move(iterator& pNode) const {
+    virtual void move(TreeIteratorBase& pNode) const {
       pNode.move<Inclusive>();
     }
   };
@@ -146,33 +146,33 @@
   //  @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 pRoot,
+  InputTree& insert(TreeIteratorBase pRoot,
                     const std::string& pNamespec,
                     const sys::fs::Path& pPath,
                     unsigned int pType = Input::Unknown);
 
   template<size_t DIRECT>
-  InputTree& enterGroup(iterator pRoot);
+  InputTree& enterGroup(TreeIteratorBase pRoot);
 
   template<size_t DIRECT>
-  InputTree& insert(iterator pRoot,
+  InputTree& insert(TreeIteratorBase pRoot,
                     const Input& pInput);
 
-  InputTree& merge(iterator pRoot, 
+  InputTree& merge(TreeIteratorBase pRoot, 
                    const Mover& pMover,
                    InputTree& pTree);
 
-  InputTree& insert(iterator pRoot,
+  InputTree& insert(TreeIteratorBase pRoot,
                     const Mover& pMover,
                     const std::string& pNamespec,
                     const sys::fs::Path& pPath,
                     unsigned int pType = Input::Unknown);
 
-  InputTree& insert(iterator pRoot,
+  InputTree& insert(TreeIteratorBase pRoot,
                     const Mover& pMover,
                     const Input& pInput);
 
-  InputTree& enterGroup(iterator pRoot,
+  InputTree& enterGroup(TreeIteratorBase pRoot,
                         const Mover& pMover);
 
   // -----  observers  ----- //
@@ -200,7 +200,7 @@
 // template member functions
 template<size_t DIRECT>
 mcld::InputTree&
-mcld::InputTree::insert(mcld::InputTree::iterator pRoot,
+mcld::InputTree::insert(mcld::TreeIteratorBase pRoot,
                         const std::string& pNamespec,
                         const mcld::sys::fs::Path& pPath,
                         unsigned int pType)
@@ -218,7 +218,7 @@
 
 template<size_t DIRECT>
 mcld::InputTree&
-mcld::InputTree::enterGroup(mcld::InputTree::iterator pRoot)
+mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot)
 {
   BinTreeTy::node_type* node = createNode(); 
   if (pRoot.isRoot())
@@ -231,7 +231,7 @@
 }
 
 template<size_t DIRECT>
-mcld::InputTree& mcld::InputTree::insert(mcld::InputTree::iterator pRoot,
+mcld::InputTree& mcld::InputTree::insert(mcld::TreeIteratorBase pRoot,
 	                                 const mcld::Input& pInput)
 {
   BinTreeTy::node_type* node = createNode();
diff --git a/include/mcld/MC/MCLDInput.h b/include/mcld/MC/MCLDInput.h
index 2f1198c..e9bb4e6 100644
--- a/include/mcld/MC/MCLDInput.h
+++ b/include/mcld/MC/MCLDInput.h
@@ -82,6 +82,6 @@
 };
 
 } // namespace of mcld
- 
+
 #endif
 
diff --git a/include/mcld/MC/MCLinker.h b/include/mcld/MC/MCLinker.h
index 29e6a46..f592d6e 100644
--- a/include/mcld/MC/MCLinker.h
+++ b/include/mcld/MC/MCLinker.h
@@ -140,9 +140,12 @@
 
   // -----  eh_frame sections  ----- //
   /// addEhFrame - add an exception handling section
+  /// @param pInput - the Input contains this section
   /// @param pSection - the input section
   /// @param pArea - the memory area which pSection is within.
-  uint64_t addEhFrame(LDSection& pSection, MemoryArea& pArea);
+  uint64_t addEhFrame(const Input& pInput,
+                      LDSection& pSection,
+                      MemoryArea& pArea);
 
   // -----  relocations  ----- //
   /// addRelocation - add a relocation entry in MCLinker (only for object file)
diff --git a/include/mcld/Support/MemoryArea.h b/include/mcld/Support/MemoryArea.h
index 5f4a29e..5337f48 100644
--- a/include/mcld/Support/MemoryArea.h
+++ b/include/mcld/Support/MemoryArea.h
@@ -53,10 +53,21 @@
  */
 class MemoryArea : private Uncopyable
 {
+  friend class MemoryAreaFactory;
 public:
-  // constructor
-  MemoryArea(RegionFactory& pRegionFactory,
-             FileHandle& pFileHandle);
+  typedef llvm::iplist<Space> SpaceList;
+
+public:
+  // constructor by file handler.
+  // If the given file handler is read-only, client can not request a region
+  // that out of the file size.
+  // @param pFileHandle - file handler
+  MemoryArea(RegionFactory& pRegionFactory, FileHandle& pFileHandle);
+
+  // constructor by set universal space.
+  // Client can not request a region that out of the universal space.
+  // @param pUniverse - file handler
+  MemoryArea(RegionFactory& pRegionFactory, Space& pUniverse);
 
   // destructor
   ~MemoryArea();
@@ -80,21 +91,6 @@
   const FileHandle* handler() const
   { return m_pFileHandle; }
 
-private:
-  friend class MemoryAreaFactory;
-
-#if defined(ENABLE_UNITTEST)
-  friend class mcldtest::MemoryAreaTest;
-#endif
-
-  typedef llvm::iplist<Space> SpaceList;
-
-private:
-  // -----  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);
 
diff --git a/include/mcld/Support/Path.h b/include/mcld/Support/Path.h
index 113ff25..54b75c5 100644
--- a/include/mcld/Support/Path.h
+++ b/include/mcld/Support/Path.h
@@ -105,6 +105,7 @@
 
 bool operator==(const Path& pLHS,const Path& pRHS);
 bool operator!=(const Path& pLHS,const Path& pRHS);
+Path operator+(const Path& pLHS, const Path& pRHS);
 
 //--------------------------------------------------------------------------//
 //                              non-member functions                        //
diff --git a/include/mcld/Support/TargetRegistry.h b/include/mcld/Support/TargetRegistry.h
index b31bed4..8d0fee8 100644
--- a/include/mcld/Support/TargetRegistry.h
+++ b/include/mcld/Support/TargetRegistry.h
@@ -49,7 +49,7 @@
   typedef TargetLDBackend  *(*TargetLDBackendCtorTy)(const llvm::Target&,
                                                      const std::string&);
 
-  typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const llvm::Target&,
+  typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&,
                                                           const std::string&);
 
 public:
@@ -97,7 +97,7 @@
   }
 
   /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
-  DiagnosticLineInfo* createDiagnosticLineInfo(const llvm::Target& pTarget,
+  DiagnosticLineInfo* createDiagnosticLineInfo(const mcld::Target& pTarget,
                                                const std::string& pTriple) const
   {
     if (!DiagnosticLineInfoCtorFn)
diff --git a/include/mcld/Target/GNULDBackend.h b/include/mcld/Target/GNULDBackend.h
index 196420a..9f3e308 100644
--- a/include/mcld/Target/GNULDBackend.h
+++ b/include/mcld/Target/GNULDBackend.h
@@ -272,6 +272,14 @@
                            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;
+
 protected:
   uint64_t getSymbolSize(const LDSymbol& pSymbol) const;
 
@@ -295,21 +303,12 @@
   /// 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,
diff --git a/lib/LD/DiagnosticEngine.cpp b/lib/LD/DiagnosticEngine.cpp
index 11dbe1b..8b209c9 100644
--- a/lib/LD/DiagnosticEngine.cpp
+++ b/lib/LD/DiagnosticEngine.cpp
@@ -13,21 +13,12 @@
 
 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()
+  : m_pLDInfo(NULL), m_pLineInfo(NULL), m_pPrinter(NULL),
+    m_pInfoMap(NULL), m_OwnPrinter(false) {
 }
 
 DiagnosticEngine::~DiagnosticEngine()
@@ -39,10 +30,22 @@
     delete m_pLineInfo;
 }
 
+void DiagnosticEngine::reset(const MCLDInfo& pLDInfo)
+{
+  m_pLDInfo = &pLDInfo;
+  m_pInfoMap = new DiagnosticInfos(*m_pLDInfo);
+  m_State.reset();
+}
+
+void DiagnosticEngine::setLineInfo(DiagnosticLineInfo& pLineInfo)
+{
+  m_pLineInfo = &pLineInfo;
+}
+
 void DiagnosticEngine::setPrinter(DiagnosticPrinter& pPrinter,
                                   bool pShouldOwnPrinter)
 {
-  if (m_OwnPrinter && m_pPrinter != NULL)
+  if (m_OwnPrinter && NULL != m_pPrinter)
     delete m_pPrinter;
   m_pPrinter = &pPrinter;
   m_OwnPrinter = pShouldOwnPrinter;
@@ -51,7 +54,7 @@
 // emit - process current diagnostic.
 bool DiagnosticEngine::emit()
 {
-  bool emitted = m_InfoMap.process(*this);
+  bool emitted = m_pInfoMap->process(*this);
   m_State.reset();
   return emitted;
 }
diff --git a/lib/LD/ELFDynObjReader.cpp b/lib/LD/ELFDynObjReader.cpp
index de36104..1251656 100644
--- a/lib/LD/ELFDynObjReader.cpp
+++ b/lib/LD/ELFDynObjReader.cpp
@@ -44,7 +44,8 @@
   // Don't warning about the frequently requests.
   // MemoryArea has a list of cache to handle this.
   size_t hdr_size = m_pELFReader->getELFHeaderSize();
-  MemoryRegion* region = pInput.memArea()->request(0, hdr_size);
+  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
+                                                   hdr_size);
 
   uint8_t* ELF_hdr = region->start();
   bool result = true;
@@ -66,7 +67,8 @@
   assert(pInput.hasMemArea());
 
   size_t hdr_size = m_pELFReader->getELFHeaderSize();
-  MemoryRegion* region = pInput.memArea()->request(0, hdr_size);
+  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
+                                                   hdr_size);
   uint8_t* ELF_hdr = region->start();
 
   bool shdr_result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
@@ -99,13 +101,14 @@
     return false;
   }
 
-  MemoryRegion* symtab_region = pInput.memArea()->request(symtab_shdr->offset(),
-                                                          symtab_shdr->size());
+  MemoryRegion* symtab_region = pInput.memArea()->request(
+              pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
 
-  MemoryRegion* strtab_region = pInput.memArea()->request(strtab_shdr->offset(),
-                                                          strtab_shdr->size());
+  MemoryRegion* strtab_region = pInput.memArea()->request(
+              pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
   char* strtab = reinterpret_cast<char*>(strtab_region->start());
-  bool result = m_pELFReader->readSymbols(pInput, m_Linker, *symtab_region, strtab);
+  bool result = m_pELFReader->readSymbols(pInput, m_Linker, *symtab_region,
+                                            strtab);
   pInput.memArea()->release(symtab_region);
   pInput.memArea()->release(strtab_region);
 
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index 1ea81e2..c69149c 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -49,7 +49,8 @@
   // Don't warning about the frequently requests.
   // MemoryArea has a list of cache to handle this.
   size_t hdr_size = m_pELFReader->getELFHeaderSize();
-  MemoryRegion* region = pInput.memArea()->request(0, hdr_size);
+  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
+                                                     hdr_size);
 
   uint8_t* ELF_hdr = region->start();
   bool result = true;
@@ -71,7 +72,8 @@
   assert(pInput.hasMemArea());
 
   size_t hdr_size = m_pELFReader->getELFHeaderSize();
-  MemoryRegion* region = pInput.memArea()->request(0, hdr_size);
+  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
+                                                     hdr_size);
   uint8_t* ELF_hdr = region->start();
   bool result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
   pInput.memArea()->release(region);
@@ -111,11 +113,10 @@
         if (exist) {
           // if this is not the first time we see this group signature, then
           // ignore all the members in this group (set NULL)
-          MemoryRegion* region =
-              pInput.memArea()->request((*section)->offset(),
-                                        (*section)->size());
+          MemoryRegion* region = pInput.memArea()->request(
+               pInput.fileOffset() + (*section)->offset(), (*section)->size());
           llvm::ELF::Elf32_Word* value =
-                      reinterpret_cast<llvm::ELF::Elf32_Word*>(region->start());
+                     reinterpret_cast<llvm::ELF::Elf32_Word*>(region->start());
 
           size_t size = region->size() / sizeof(llvm::ELF::Elf32_Word);
           if (llvm::ELF::GRP_COMDAT == *value) {
@@ -225,10 +226,10 @@
     return false;
   }
 
-  MemoryRegion* symtab_region = pInput.memArea()->request(symtab_shdr->offset(),
-                                                          symtab_shdr->size());
-  MemoryRegion* strtab_region = pInput.memArea()->request(strtab_shdr->offset(),
-                                                          strtab_shdr->size());
+  MemoryRegion* symtab_region = pInput.memArea()->request(
+             pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
+  MemoryRegion* strtab_region = pInput.memArea()->request(
+             pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
   char* strtab = reinterpret_cast<char*>(strtab_region->start());
   bool result = m_pELFReader->readSymbols(pInput,
                                           m_Linker,
@@ -252,15 +253,18 @@
 
     if ((*section)->type() == llvm::ELF::SHT_RELA &&
         (*section)->kind() == LDFileFormat::Relocation) {
-      MemoryRegion* region = mem->request((*section)->offset(), (*section)->size());
-      bool result = m_pELFReader->readRela(pInput, m_Linker, **section, *region);
+      MemoryRegion* region = mem->request(
+               pInput.fileOffset() + (*section)->offset(), (*section)->size());
+      bool result = m_pELFReader->readRela(pInput, m_Linker, **section,
+                                           *region);
       mem->release(region);
       if (!result)
         return false;
     }
     else if ((*section)->type() == llvm::ELF::SHT_REL &&
              (*section)->kind() == LDFileFormat::Relocation) {
-      MemoryRegion* region = mem->request((*section)->offset(), (*section)->size());
+      MemoryRegion* region = mem->request(
+               pInput.fileOffset() + (*section)->offset(), (*section)->size());
       bool result = m_pELFReader->readRel(pInput, m_Linker, **section, *region);
       mem->release(region);
       if (!result)
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index 6aacc08..d74d314 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -141,7 +141,7 @@
                                uint16_t pShndx,
                                uint32_t pOffset) const
 {
-  
+
   if (pShndx == llvm::ELF::SHN_UNDEF || pShndx >= llvm::ELF::SHN_LORESERVE)
     return NULL;
 
@@ -150,7 +150,7 @@
   if (NULL == sect_hdr)
     unreachable(diag::unreachable_invalid_section_idx) << pShndx
                                                        << pInput.path().native();
-  
+
   MCFragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset);
   return result;
 }
@@ -197,7 +197,7 @@
                                                          pInputSectHdr.type(),
                                                          pInputSectHdr.flag());
 
-  size_t size = pLinker.addEhFrame(pInputSectHdr, *pInput.memArea());
+  size_t size = pLinker.addEhFrame(pInput, pInputSectHdr, *pInput.memArea());
 
   out_sect.setSize(out_sect.size() + size);
   return true;
diff --git a/lib/LD/EhFrame.cpp b/lib/LD/EhFrame.cpp
index 76af403..4a84b00 100644
--- a/lib/LD/EhFrame.cpp
+++ b/lib/LD/EhFrame.cpp
@@ -28,11 +28,12 @@
 uint64_t EhFrame::readEhFrame(Layout& pLayout,
                               const TargetLDBackend& pBackend,
                               llvm::MCSectionData& pSD,
+                              const Input& pInput,
                               LDSection& pSection,
                               MemoryArea& pArea)
 {
-  MemoryRegion* region = pArea.request(pSection.offset(),
-                                       pSection.size());
+  MemoryRegion* region = pArea.request(
+                     pInput.fileOffset() + pSection.offset(), pSection.size());
   // an empty .eh_frame
   if (NULL == region) {
     note(diag::note_ehframe) << "an empty eh_frame";
@@ -100,8 +101,8 @@
     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);
+    MemoryRegion* ent_region = pArea.request(
+                pInput.fileOffset() + pSection.offset() + ent_offset, len + 4);
 
     // create and add a CIE or FDE entry
     uint32_t id = readVal(p, pBackend.isLittleEndian());
diff --git a/lib/LD/Relocation.cpp b/lib/LD/Relocation.cpp
index 0b84ad0..4a901ba 100644
--- a/lib/LD/Relocation.cpp
+++ b/lib/LD/Relocation.cpp
@@ -7,10 +7,10 @@
 //
 //===----------------------------------------------------------------------===//
 #include <llvm/MC/MCAssembler.h>
-//#include <mcld/MC/MCLDInfo.h>
 #include <mcld/LD/Relocation.h>
 #include <mcld/LD/RelocationFactory.h>
 #include <mcld/LD/Layout.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
@@ -51,7 +51,30 @@
 void Relocation::apply(RelocationFactory& pRelocFactory,
                        const MCLDInfo& pLDInfo)
 {
-  pRelocFactory.applyRelocation(*this, pLDInfo);
+  RelocationFactory::Result result =
+                                 pRelocFactory.applyRelocation(*this, pLDInfo);
+
+  switch (result) {
+    case RelocationFactory::OK: {
+      // do nothing
+      return;
+    }
+    case RelocationFactory::Overflow: {
+      error(diag::result_overflow) << pRelocFactory.getName(type())
+                                   << symInfo()->name();
+      return;
+    }
+    case RelocationFactory::BadReloc: {
+      error(diag::result_badreloc) << pRelocFactory.getName(type())
+                                   << symInfo()->name();
+      return;
+    }
+    case RelocationFactory::Unsupport: {
+      fatal(diag::unsupported_relocation) << type()
+                                          << "mclinker@googlegroups.com";
+      return;
+    }
+  } // end of switch
 }
 
 void Relocation::setType(Type pType)
diff --git a/lib/MC/InputTree.cpp b/lib/MC/InputTree.cpp
index a1d1449..1416b6a 100644
--- a/lib/MC/InputTree.cpp
+++ b/lib/MC/InputTree.cpp
@@ -24,7 +24,7 @@
 {
 }
 
-InputTree& InputTree::merge(InputTree::iterator pRoot, 
+InputTree& InputTree::merge(TreeIteratorBase pRoot, 
                             const InputTree::Mover& pMover,
                             InputTree& pTree)
 {
@@ -41,7 +41,7 @@
   return *this;
 }
 
-InputTree& InputTree::insert(InputTree::iterator pRoot,
+InputTree& InputTree::insert(TreeIteratorBase pRoot,
                              const InputTree::Mover& pMover,
                              const std::string& pNamespec,
                              const sys::fs::Path& pPath,
@@ -53,7 +53,7 @@
   return *this;
 }
 
-InputTree& InputTree::enterGroup(InputTree::iterator pRoot,
+InputTree& InputTree::enterGroup(TreeIteratorBase pRoot,
                                  const InputTree::Mover& pMover)
 {
   NodeBase* node = createNode();
@@ -61,7 +61,7 @@
   return *this;
 }
 
-InputTree& InputTree::insert(InputTree::iterator pRoot,
+InputTree& InputTree::insert(TreeIteratorBase pRoot,
                              const InputTree::Mover& pMover,
                              const mcld::Input& pInput)
 {
diff --git a/lib/MC/MCLDInput.cpp b/lib/MC/MCLDInput.cpp
index 81a8b60..0803e00 100644
--- a/lib/MC/MCLDInput.cpp
+++ b/lib/MC/MCLDInput.cpp
@@ -16,7 +16,8 @@
 Input::Input(llvm::StringRef pName, const AttributeProxy& pProxy)
  : MCLDFile(pName),
    m_pAttr(const_cast<Attribute*>(pProxy.attr())),
-   m_bNeeded(false) {
+   m_bNeeded(false),
+   m_fileOffset(0) {
 }
 
 Input::Input(llvm::StringRef pName,
diff --git a/lib/MC/MCLinker.cpp b/lib/MC/MCLinker.cpp
index 4b9c50f..7321e49 100644
--- a/lib/MC/MCLinker.cpp
+++ b/lib/MC/MCLinker.cpp
@@ -660,7 +660,9 @@
 /// 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 MCLinker::addEhFrame(const Input& pInput,
+                              LDSection& pSection,
+                              MemoryArea& pArea)
 {
   uint64_t size = 0;
 
@@ -672,8 +674,8 @@
     EhFrame* ehframe = m_Backend.getEhFrame();
     assert(NULL != ehframe);
     if (ehframe->canRecognizeAllEhFrame()) {
-      size = ehframe->readEhFrame(m_Layout, m_Backend, sect_data, pSection,
-                                       pArea);
+      size = ehframe->readEhFrame(m_Layout, m_Backend, sect_data, pInput,
+                                    pSection, pArea);
       // zero size indicate that this is an empty section or we can't recognize
       // this eh_frame, handle it as a regular section.
       if (0 != size)
@@ -682,7 +684,7 @@
   }
 
   // handle eh_frame as a regular section
-  MemoryRegion* region = pArea.request(pSection.offset(),
+  MemoryRegion* region = pArea.request(pInput.fileOffset() + pSection.offset(),
                                        pSection.size());
 
   llvm::MCFragment* frag = NULL;
diff --git a/lib/Support/MemoryArea.cpp b/lib/Support/MemoryArea.cpp
index 78a9d36..844d8f6 100644
--- a/lib/Support/MemoryArea.cpp
+++ b/lib/Support/MemoryArea.cpp
@@ -16,6 +16,7 @@
 
 //===--------------------------------------------------------------------===//
 // MemoryArea
+//===--------------------------------------------------------------------===//
 
 // MemoryArea - special constructor
 // This constructor is used for *SPECIAL* situation. I'm sorry I can not
@@ -54,12 +55,11 @@
 {
   Space* space = find(pOffset, pLength);
   if (NULL == space) {
-
     // not found
     if (NULL == m_pFileHandle) {
       // if m_pFileHandle is NULL, clients delegate us an universal Space and
       // we never remove it. In that way, space can not be NULL.
-      unreachable(diag::err_out_of_range_region);
+      unreachable(diag::err_out_of_range_region) << pOffset << pLength;
     }
 
     space = Space::createSpace(*m_pFileHandle, pOffset, pLength);
@@ -94,8 +94,8 @@
         Space::syncSpace(space, *m_pFileHandle);
       }
       Space::releaseSpace(space, *m_pFileHandle);
+      m_SpaceList.erase(space);
     }
-    m_SpaceList.erase(space);
   }
 }
 
diff --git a/lib/Support/MsgHandling.cpp b/lib/Support/MsgHandling.cpp
index 5b45289..d7611d2 100644
--- a/lib/Support/MsgHandling.cpp
+++ b/lib/Support/MsgHandling.cpp
@@ -17,58 +17,29 @@
 using namespace mcld;
 
 //===----------------------------------------------------------------------===//
-// DiagnosticInitializer
-class DiagnosticInitializer : public llvm::ManagedStaticBase
+// static variables
+//===----------------------------------------------------------------------===//
+static llvm::ManagedStatic<DiagnosticEngine> g_pEngine;
+
+void
+mcld::InitializeDiagnosticEngine(const mcld::MCLDInfo& pLDInfo,
+                                 DiagnosticLineInfo* pLineInfo,
+                                 DiagnosticPrinter* pPrinter)
 {
-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);
+  g_pEngine->reset(pLDInfo);
+  if (NULL != pLineInfo)
+    g_pEngine->setLineInfo(*pLineInfo);
 
-      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);
+  if (NULL != pPrinter)
+    g_pEngine->setPrinter(*pPrinter, false);
+  else {
+    DiagnosticPrinter* printer = new DiagnosticPrinter();
+    g_pEngine->setPrinter(*printer, true);
   }
 }
 
 DiagnosticEngine& mcld::getDiagnosticEngine()
 {
-  assert(NULL != g_pDiagnosticEngine &&
-         "mcld::InitializeDiagnostics() is not called");
-  return *g_pDiagnosticEngine;
+  return *g_pEngine;
 }
 
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index 55baa52..e35132f 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -12,7 +12,8 @@
 
 #include <locale>
 #include <string.h>
-#include <iostream>
+#include <istream>
+#include <ostream>
 
 using namespace mcld;
 using namespace mcld::sys::fs;
@@ -142,7 +143,7 @@
 Path Path::stem() const
 {
   size_t begin_pos = m_PathName.find_last_of(separator)+1;
-  size_t end_pos   = m_PathName.find_first_of(".", begin_pos);
+  size_t end_pos   = m_PathName.find_last_of(".");
   Path result_path(m_PathName.substr(begin_pos, end_pos - begin_pos));
   return result_path;
 }
@@ -156,6 +157,7 @@
 
 //===--------------------------------------------------------------------===//
 // non-member functions
+//===--------------------------------------------------------------------===//
 bool mcld::sys::fs::operator==(const Path& pLHS,const Path& pRHS)
 {
   return (pLHS.generic_string()==pRHS.generic_string());
@@ -166,6 +168,13 @@
   return !(pLHS==pRHS);
 }
 
+Path mcld::sys::fs::operator+(const Path& pLHS, const Path& pRHS)
+{
+  mcld::sys::fs::Path result = pLHS;
+  result.append(pRHS);
+  return result;
+}
+
 bool mcld::sys::fs::is_separator(char value)
 {
   return (value == separator
@@ -206,3 +215,4 @@
 {
   return pOS << pPath.native();
 }
+
diff --git a/lib/Target/ARM/ARMDiagnostic.cpp b/lib/Target/ARM/ARMDiagnostic.cpp
index 1ecf7df..d6f3988 100644
--- a/lib/Target/ARM/ARMDiagnostic.cpp
+++ b/lib/Target/ARM/ARMDiagnostic.cpp
@@ -21,7 +21,7 @@
 //===----------------------------------------------------------------------===//
 // createARMDiagnostic - the help function to create corresponding ARMDiagnostic
 //
-DiagnosticLineInfo* createARMDiagLineInfo(const llvm::Target& pTarget,
+DiagnosticLineInfo* createARMDiagLineInfo(const mcld::Target& pTarget,
                                           const std::string &pTriple)
 {
   return new DWARFLineInfo();
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
index 7430203..af37768 100644
--- a/lib/Target/ARM/ARMGOT.cpp
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -40,10 +40,9 @@
 
   // Skip GOT0 entries.
   iterator it = m_SectionData.begin();
-  iterator ie = m_SectionData.end();
 
   for (int i = 1; i < ARMGOT0Num; ++i) {
-    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
+    assert((it != m_SectionData.end()) && "Generation of GOT0 entries is incomplete!");
     ++it;
   }
 
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index e0f5dcf..81915c9 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -35,6 +35,7 @@
     m_pRelDyn(NULL),
     m_pRelPLT(NULL),
     m_pDynamic(NULL),
+    m_pGOTSymbol(NULL),
     m_pEXIDX(NULL),
     m_pEXTAB(NULL),
     m_pAttributes(NULL) {
@@ -840,8 +841,8 @@
       (0 != out_sect.size()))
     return true;
 
-  MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(),
-                                                   pInputSectHdr.size());
+  MemoryRegion* region = pInput.memArea()->request(
+          pInput.fileOffset() + pInputSectHdr.offset(), pInputSectHdr.size());
 
   llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
 
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
index 5528ef7..015d767 100644
--- a/lib/Target/ARM/ARMPLT.cpp
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -91,8 +91,7 @@
             "The number of PLT Entries and ResolveInfo doesn't match");
 
      ARMGOT::iterator got_it = m_GOT.getNextGOTPLTEntry();
-     ARMGOT::iterator got_ie = m_GOT.getGOTPLTEnd();
-     assert(got_it != got_ie && "The number of GOTPLT and PLT doesn't match");
+     assert(got_it != m_GOT.getGOTPLTEnd() && "The number of GOTPLT and PLT doesn't match");
 
      PLTEntry = llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
      GOTPLTEntry = llvm::cast<GOTEntry>(&(*got_it));
@@ -119,8 +118,8 @@
             "The number of PLT Entries and ResolveInfo doesn't match");
 
      ARMGOT::iterator got_it = m_GOT.getNextGOTPLTEntry();
-     ARMGOT::iterator got_ie = m_GOT.getGOTPLTEnd();
-     assert(got_it != got_ie && "The number of GOTPLT and PLT doesn't match");
+     assert(got_it != m_GOT.getGOTPLTEnd() &&
+            "The number of GOTPLT and PLT doesn't match");
 
      PLTEntry = llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
      GOTPLTEntry = llvm::cast<GOTEntry>(&(*got_it));
@@ -132,9 +131,9 @@
 ARMPLT0* ARMPLT::getPLT0() const {
 
   iterator first = m_SectionData.getFragmentList().begin();
-  iterator end = m_SectionData.getFragmentList().end();
 
-  assert(first!=end && "FragmentList is empty, getPLT0 failed!");
+  assert(first != m_SectionData.getFragmentList().end() &&
+         "FragmentList is empty, getPLT0 failed!");
 
   ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
 
@@ -157,9 +156,9 @@
     offset = (plt_base + 16) - got_base;
 
   iterator first = m_SectionData.getFragmentList().begin();
-  iterator end = m_SectionData.getFragmentList().end();
 
-  assert(first!=end && "FragmentList is empty, applyPLT0 failed!");
+  assert(first != m_SectionData.getFragmentList().end() &&
+         "FragmentList is empty, applyPLT0 failed!");
 
   ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
 
@@ -185,7 +184,7 @@
 
   ARMPLT::iterator it = m_SectionData.begin();
   ARMPLT::iterator ie = m_SectionData.end();
-  assert(it!=ie && "FragmentList is empty, applyPLT1 failed!");
+  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
 
   uint32_t GOTEntrySize = m_GOT.getEntrySize();
   uint32_t GOTEntryAddress =
diff --git a/lib/Target/ARM/ARMRelocationFactory.cpp b/lib/Target/ARM/ARMRelocationFactory.cpp
index 4911658..3d4b0dc 100644
--- a/lib/Target/ARM/ARMRelocationFactory.cpp
+++ b/lib/Target/ARM/ARMRelocationFactory.cpp
@@ -20,10 +20,33 @@
 
 using namespace mcld;
 
+//===--------------------------------------------------------------------===//
+// Relocation Functions and Tables
+//===--------------------------------------------------------------------===//
 DECL_ARM_APPLY_RELOC_FUNCS
 
+/// the prototype of applying function
+typedef RelocationFactory::Result (*ApplyFunctionType)(
+                                               Relocation& pReloc,
+                                               const MCLDInfo& pLDInfo,
+                                               ARMRelocationFactory& pParent);
+
+// the table entry of applying functions
+struct ApplyFunctionTriple
+{
+  ApplyFunctionType func;
+  unsigned int type;
+  const char* name;
+};
+
+// declare the table of applying functions
+static const ApplyFunctionTriple ApplyFunctions[] = {
+  DECL_ARM_APPLY_RELOC_FUNC_PTRS
+};
+
 //===--------------------------------------------------------------------===//
 // ARMRelocationFactory
+//===--------------------------------------------------------------------===//
 ARMRelocationFactory::ARMRelocationFactory(size_t pNum,
                                            ARMGNULDBackend& pParent)
   : RelocationFactory(pNum),
@@ -34,58 +57,24 @@
 {
 }
 
-void ARMRelocationFactory::applyRelocation(Relocation& pRelocation,
-                                           const MCLDInfo& pLDInfo)
+RelocationFactory::Result
+ARMRelocationFactory::applyRelocation(Relocation& pRelocation,
+                                      const MCLDInfo& pLDInfo)
 {
   Relocation::Type type = pRelocation.type();
   if (type > 130) { // 131-255 doesn't noted in ARM spec
     fatal(diag::unknown_relocation) << (int)type
                                     << pRelocation.symInfo()->name();
-    return;
+    return RelocationFactory::Unknown;
   }
 
-  /// the prototype of applying function
-  typedef Result (*ApplyFunctionType)(Relocation& pReloc,
-                                      const MCLDInfo& pLDInfo,
-                                      ARMRelocationFactory& pParent);
-
-  // the table entry of applying functions
-  struct ApplyFunctionTriple {
-    ApplyFunctionType func;
-    unsigned int type;
-    const char* name;
-  };
-
-  // declare the table of applying functions
-  static ApplyFunctionTriple apply_functions[] = {
-    DECL_ARM_APPLY_RELOC_FUNC_PTRS
-  };
-
-  // apply the relocation
-  Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
-
-  // check result
-  if (OK == result) {
-    return;
-  }
-  if (Overflow == result) {
-    error(diag::result_overflow) << apply_functions[type].name
-                                 << pRelocation.symInfo()->name();
-    return;
-  }
-  if (BadReloc == result) {
-    error(diag::result_badreloc) << apply_functions[type].name
-                                 << pRelocation.symInfo()->name();
-    return;
-  }
-  if (Unsupport == result) {
-    fatal(diag::unsupported_relocation) << type
-                                        << "mclinker@googlegroups.com";
-    return;
-  }
+  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
 }
 
-
+const char* ARMRelocationFactory::getName(RelocationFactory::Type pType) const
+{
+  return ApplyFunctions[pType].name;
+}
 
 //===--------------------------------------------------------------------===//
 // non-member functions
@@ -570,7 +559,8 @@
 
   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!");
+  if (helper_check_signed_overflow(X, 26))
+    return ARMRelocationFactory::Overflow;
   //                    Make sure the Imm is 0.          Result Mask.
   pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2);
   return ARMRelocationFactory::OK;
@@ -638,7 +628,6 @@
 
   // 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;
   }
 
@@ -664,10 +653,10 @@
   ARMRelocationFactory::DWord X;
 
   const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
-                                                  *(pReloc.targetRef().frag()));
+                                                 *(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 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) {
@@ -676,15 +665,11 @@
     }
   }
 
-  X = (S + A) | T ;
   // perform static relocation
-  pReloc.target() = (S + A) | T;
-  if (helper_check_signed_overflow(X, 16)) {
-    return ARMRelocationFactory::Overflow;
-  } else {
-    pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
-    return ARMRelocationFactory::OK;
-  }
+  X = (S + A) | T;
+  pReloc.target() = helper_insert_val_movw_movt_inst(
+                                         pReloc.target() + pReloc.addend(), X);
+  return ARMRelocationFactory::OK;
 }
 
 // R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
diff --git a/lib/Target/ARM/ARMRelocationFactory.h b/lib/Target/ARM/ARMRelocationFactory.h
index 636dbee..b0b3483 100644
--- a/lib/Target/ARM/ARMRelocationFactory.h
+++ b/lib/Target/ARM/ARMRelocationFactory.h
@@ -26,22 +26,10 @@
 class ARMRelocationFactory : public RelocationFactory
 {
 public:
-  /** \enum Reloc
-   *  \brief Reloc is the result of applying functions.
-   */
-  enum Result
-  {
-    OK,
-    Overflow,
-    BadReloc,
-    Unsupport
-  };
-
-public:
   ARMRelocationFactory(size_t pNum, ARMGNULDBackend& pParent);
   ~ARMRelocationFactory();
 
-  void applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+  Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
 
   ARMGNULDBackend& getTarget()
   { return m_Target; }
@@ -49,6 +37,8 @@
   const ARMGNULDBackend& getTarget() const
   { return m_Target; }
 
+  const char* getName(Relocation::Type pType) const;
+
 private:
   ARMGNULDBackend& m_Target;
 };
diff --git a/lib/Target/ARM/ARMSectLinker.cpp b/lib/Target/ARM/ARMSectLinker.cpp
index 06dba05..52a00e3 100644
--- a/lib/Target/ARM/ARMSectLinker.cpp
+++ b/lib/Target/ARM/ARMSectLinker.cpp
@@ -25,9 +25,11 @@
   Triple theTriple(pTriple);
   if (theTriple.isOSDarwin()) {
     assert(0 && "MachO linker has not supported yet");
+    return NULL;
   }
   if (theTriple.isOSWindows()) {
     assert(0 && "COFF linker has not supported yet");
+    return NULL;
   }
 
   // For now, use Android SectLinker directly
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
index 9fff9e3..69d0927 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -99,21 +99,21 @@
 
 bool GNULDBackend::initArchiveReader(MCLinker&, MCLDInfo &pInfo)
 {
-  if (0 == m_pArchiveReader)
+  if (NULL == m_pArchiveReader)
     m_pArchiveReader = new GNUArchiveReader(pInfo);
   return true;
 }
 
 bool GNULDBackend::initObjectReader(MCLinker& pLinker)
 {
-  if (0 == m_pObjectReader)
+  if (NULL == m_pObjectReader)
     m_pObjectReader = new ELFObjectReader(*this, pLinker);
   return true;
 }
 
 bool GNULDBackend::initDynObjReader(MCLinker& pLinker)
 {
-  if (0 == m_pDynObjReader)
+  if (NULL == m_pDynObjReader)
     m_pDynObjReader = new ELFDynObjReader(*this, pLinker);
   return true;
 }
@@ -140,7 +140,7 @@
 
 bool GNULDBackend::initExecSections(MCLinker& pMCLinker)
 {
-  if (0 == m_pExecFileFormat)
+  if (NULL == m_pExecFileFormat)
     m_pExecFileFormat = new ELFExecFileFormat(*this);
 
   // initialize standard sections
@@ -150,7 +150,7 @@
 
 bool GNULDBackend::initDynObjSections(MCLinker& pMCLinker)
 {
-  if (0 == m_pDynObjFileFormat)
+  if (NULL == m_pDynObjFileFormat)
     m_pDynObjFileFormat = new ELFDynObjFileFormat(*this);
 
   // initialize standard sections
@@ -552,37 +552,37 @@
 
 GNUArchiveReader *GNULDBackend::getArchiveReader()
 {
-  assert(0 != m_pArchiveReader);
+  assert(NULL != m_pArchiveReader);
   return m_pArchiveReader;
 }
 
 const GNUArchiveReader *GNULDBackend::getArchiveReader() const
 {
-  assert(0 != m_pArchiveReader);
+  assert(NULL != m_pArchiveReader);
   return m_pArchiveReader;
 }
 
 ELFObjectReader *GNULDBackend::getObjectReader()
 {
-  assert(0 != m_pObjectReader);
+  assert(NULL != m_pObjectReader);
   return m_pObjectReader;
 }
 
 const ELFObjectReader *GNULDBackend::getObjectReader() const
 {
-  assert(0 != m_pObjectReader);
+  assert(NULL != m_pObjectReader);
   return m_pObjectReader;
 }
 
 ELFDynObjReader *GNULDBackend::getDynObjReader()
 {
-  assert(0 != m_pDynObjReader);
+  assert(NULL != m_pDynObjReader);
   return m_pDynObjReader;
 }
 
 const ELFDynObjReader *GNULDBackend::getDynObjReader() const
 {
-  assert(0 != m_pDynObjReader);
+  assert(NULL != m_pDynObjReader);
   return m_pDynObjReader;
 }
 
@@ -600,13 +600,13 @@
 
 ELFDynObjWriter *GNULDBackend::getDynObjWriter()
 {
-  assert(0 != m_pDynObjWriter);
+  assert(NULL != m_pDynObjWriter);
   return m_pDynObjWriter;
 }
 
 const ELFDynObjWriter *GNULDBackend::getDynObjWriter() const
 {
-  assert(0 != m_pDynObjWriter);
+  assert(NULL != m_pDynObjWriter);
   return m_pDynObjWriter;
 }
 
@@ -654,25 +654,25 @@
 
 ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat()
 {
-  assert(0 != m_pDynObjFileFormat);
+  assert(NULL != m_pDynObjFileFormat);
   return m_pDynObjFileFormat;
 }
 
 const ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat() const
 {
-  assert(0 != m_pDynObjFileFormat);
+  assert(NULL != m_pDynObjFileFormat);
   return m_pDynObjFileFormat;
 }
 
 ELFExecFileFormat* GNULDBackend::getExecFileFormat()
 {
-  assert(0 != m_pExecFileFormat);
+  assert(NULL != m_pExecFileFormat);
   return m_pExecFileFormat;
 }
 
 const ELFExecFileFormat* GNULDBackend::getExecFileFormat() const
 {
-  assert(0 != m_pExecFileFormat);
+  assert(NULL != m_pExecFileFormat);
   return m_pExecFileFormat;
 }
 
diff --git a/lib/Target/Mips/MipsDiagnostic.cpp b/lib/Target/Mips/MipsDiagnostic.cpp
index c90c6ef..f6b6339 100644
--- a/lib/Target/Mips/MipsDiagnostic.cpp
+++ b/lib/Target/Mips/MipsDiagnostic.cpp
@@ -18,7 +18,7 @@
 //===----------------------------------------------------------------------===//
 // createMipsDiagnostic - the help function to create corresponding
 // MipsDiagnostic
-DiagnosticLineInfo* createMipsDiagLineInfo(const llvm::Target& pTarget,
+DiagnosticLineInfo* createMipsDiagLineInfo(const mcld::Target& pTarget,
                                            const std::string &pTriple)
 {
   return new DWARFLineInfo();
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
index 9baa033..57e5c70 100644
--- a/lib/Target/Mips/MipsGOT.cpp
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -38,10 +38,10 @@
 
   // Skip GOT0 entries.
   iterator it = m_SectionData.begin();
-  iterator ie = m_SectionData.end();
 
   for (size_t i = 1; i < MipsGOT0Num; ++i) {
-    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
+    assert((it != m_SectionData.end()) &&
+           "Generation of GOT0 entries is incomplete!");
 
     ++it;
   }
diff --git a/lib/Target/Mips/MipsRelocationFactory.cpp b/lib/Target/Mips/MipsRelocationFactory.cpp
index 948e026..e9d26f8 100644
--- a/lib/Target/Mips/MipsRelocationFactory.cpp
+++ b/lib/Target/Mips/MipsRelocationFactory.cpp
@@ -18,10 +18,32 @@
 
 using namespace mcld;
 
+//===----------------------------------------------------------------------===//
+// Relocation Functions and Tables
+//===----------------------------------------------------------------------===//
 DECL_MIPS_APPLY_RELOC_FUNCS
 
-//==========================
+/// the prototype of applying function
+typedef RelocationFactory::Result (*ApplyFunctionType)(Relocation&,
+                                                       const MCLDInfo& pLDInfo,
+                                                       MipsRelocationFactory&);
+
+// the table entry of applying functions
+struct ApplyFunctionTriple
+{
+  ApplyFunctionType func;
+  unsigned int type;
+  const char* name;
+};
+
+// declare the table of applying functions
+static const ApplyFunctionTriple ApplyFunctions[] = {
+  DECL_MIPS_APPLY_RELOC_FUNC_PTRS
+};
+
+//===----------------------------------------------------------------------===//
 // MipsRelocationFactory
+//===----------------------------------------------------------------------===//
 MipsRelocationFactory::MipsRelocationFactory(size_t pNum,
                                              MipsGNULDBackend& pParent)
   : RelocationFactory(pNum),
@@ -30,58 +52,32 @@
 {
 }
 
-void MipsRelocationFactory::applyRelocation(Relocation& pRelocation,
-                                            const MCLDInfo& pLDInfo)
+RelocationFactory::Result
+MipsRelocationFactory::applyRelocation(Relocation& pRelocation,
+                                       const MCLDInfo& pLDInfo)
 
 {
-  /// the prototype of applying function
-  typedef Result (*ApplyFunctionType)(Relocation&,
-                                      const MCLDInfo& pLDInfo,
-                                      MipsRelocationFactory&);
-
-  // the table entry of applying functions
-  struct ApplyFunctionTriple {
-    ApplyFunctionType func;
-    unsigned int type;
-    const char* name;
-  };
-
-  // declare the table of applying functions
-  static ApplyFunctionTriple apply_functions[] = {
-    DECL_MIPS_APPLY_RELOC_FUNC_PTRS
-  };
-
   Relocation::Type type = pRelocation.type();
 
-  if (type >= sizeof(apply_functions) / sizeof(apply_functions[0])) {
+  if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) {
     fatal(diag::unknown_relocation) << (int)type
                                     << pRelocation.symInfo()->name();
+    return Unknown;
   }
 
   // apply the relocation
-  Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
-
-  // check result
-  if (OK == result) {
-    return;
-  }
-  if (Overflow == result) {
-    error(diag::result_overflow) << apply_functions[type].name
-                                 << pRelocation.symInfo()->name();
-    return;
-  }
-
-  if (BadReloc == result) {
-    error(diag::result_badreloc) << apply_functions[type].name
-                                 << pRelocation.symInfo()->name();
-    return;
-  }
+  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
 }
 
-//=========================================//
-// Relocation helper function              //
-//=========================================//
+const char* MipsRelocationFactory::getName(Relocation::Type pType) const
+{
+  return ApplyFunctions[pType].name;
+}
 
+//===----------------------------------------------------------------------===//
+// Relocation helper function
+
+//===----------------------------------------------------------------------===//
 static const char * const GP_DISP_NAME = "_gp_disp";
 
 // Find next R_MIPS_LO16 relocation paired to pReloc.
diff --git a/lib/Target/Mips/MipsRelocationFactory.h b/lib/Target/Mips/MipsRelocationFactory.h
index 8f3bf93..a1c7b5d 100644
--- a/lib/Target/Mips/MipsRelocationFactory.h
+++ b/lib/Target/Mips/MipsRelocationFactory.h
@@ -25,20 +25,9 @@
 class MipsRelocationFactory : public RelocationFactory
 {
 public:
-  /** \enum Reloc
-   *  \brief Reloc is the result of applying functions.
-   */
-  enum Result
-  {
-    OK,
-    Overflow,
-    BadReloc
-  };
-
-public:
   MipsRelocationFactory(size_t pNum, MipsGNULDBackend& pParent);
 
-  void applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+  Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
 
   MipsGNULDBackend& getTarget()
   { return m_Target; }
@@ -54,6 +43,8 @@
   void setAHL(int32_t pAHL)
   { m_AHL = pAHL; }
 
+  const char* getName(Relocation::Type pType) const;
+
 private:
   MipsGNULDBackend& m_Target;
   int32_t m_AHL;
diff --git a/lib/Target/Mips/MipsSectLinker.cpp b/lib/Target/Mips/MipsSectLinker.cpp
index 7a3082c..ed04edd 100644
--- a/lib/Target/Mips/MipsSectLinker.cpp
+++ b/lib/Target/Mips/MipsSectLinker.cpp
@@ -26,9 +26,11 @@
   llvm::Triple theTriple(pTriple);
   if (theTriple.isOSDarwin()) {
     assert(0 && "MachO linker has not supported yet");
+    return NULL;
   }
   if (theTriple.isOSWindows()) {
     assert(0 && "COFF linker has not supported yet");
+    return NULL;
   }
 
   return new MipsELFSectLinker(pOption, pLDBackend);
diff --git a/lib/Target/X86/X86Diagnostic.cpp b/lib/Target/X86/X86Diagnostic.cpp
index db12dde..98f0234 100644
--- a/lib/Target/X86/X86Diagnostic.cpp
+++ b/lib/Target/X86/X86Diagnostic.cpp
@@ -21,7 +21,7 @@
 //===----------------------------------------------------------------------===//
 // createX86Diagnostic - the help function to create corresponding X86Diagnostic
 //
-DiagnosticLineInfo* createX86DiagLineInfo(const llvm::Target& pTarget,
+DiagnosticLineInfo* createX86DiagLineInfo(const mcld::Target& pTarget,
                                           const std::string &pTriple)
 {
   return new DWARFLineInfo();
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index 960c86b..2ba5669 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -37,10 +37,10 @@
 
   // Skip GOT0 entries.
   iterator it = m_SectionData.begin();
-  iterator ie = m_SectionData.end();
 
   for (size_t i = 1; i < X86GOTPLT0Num; ++i) {
-    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
+    assert((it != m_SectionData.end()) &&
+           "Generation of GOT0 entries is incomplete!");
 
     ++it;
   }
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index 79d160e..2355afc 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -33,7 +33,8 @@
     m_pGOTPLT(NULL),
     m_pRelDyn(NULL),
     m_pRelPLT(NULL),
-    m_pDynamic(NULL) {
+    m_pDynamic(NULL),
+    m_pGOTSymbol(NULL) {
 }
 
 X86GNULDBackend::~X86GNULDBackend()
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index caf6f32..2396a21 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -129,9 +129,9 @@
 X86PLT0* X86PLT::getPLT0() const {
 
   iterator first = m_SectionData.getFragmentList().begin();
-  iterator end = m_SectionData.getFragmentList().end();
 
-  assert(first!=end && "FragmentList is empty, getPLT0 failed!");
+  assert(first != m_SectionData.getFragmentList().end() &&
+         "FragmentList is empty, getPLT0 failed!");
 
   X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
 
@@ -142,9 +142,9 @@
 void X86PLT::applyPLT0() {
 
   iterator first = m_SectionData.getFragmentList().begin();
-  iterator end = m_SectionData.getFragmentList().end();
 
-  assert(first!=end && "FragmentList is empty, applyPLT0 failed!");
+  assert(first != m_SectionData.getFragmentList().end() &&
+         "FragmentList is empty, applyPLT0 failed!");
 
   X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
 
@@ -179,7 +179,7 @@
 
   X86PLT::iterator it = m_SectionData.begin();
   X86PLT::iterator ie = m_SectionData.end();
-  assert(it!=ie && "FragmentList is empty, applyPLT1 failed!");
+  assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
 
   uint64_t GOTEntrySize = m_GOTPLT.getEntrySize();
 
diff --git a/lib/Target/X86/X86RelocationFactory.cpp b/lib/Target/X86/X86RelocationFactory.cpp
index 9090d1a..71fa344 100644
--- a/lib/Target/X86/X86RelocationFactory.cpp
+++ b/lib/Target/X86/X86RelocationFactory.cpp
@@ -19,10 +19,33 @@
 
 using namespace mcld;
 
+//===--------------------------------------------------------------------===//
+// Relocation Functions and Tables
+//===--------------------------------------------------------------------===//
 DECL_X86_APPLY_RELOC_FUNCS
 
+/// the prototype of applying function
+typedef RelocationFactory::Result
+                          (*ApplyFunctionType)(Relocation& pReloc,
+                                               const MCLDInfo& pLDInfo,
+                                               X86RelocationFactory& pParent);
+
+// the table entry of applying functions
+struct ApplyFunctionTriple
+{
+  ApplyFunctionType func;
+  unsigned int type;
+  const char* name;
+};
+
+// declare the table of applying functions
+static const ApplyFunctionTriple ApplyFunctions[] = {
+  DECL_X86_APPLY_RELOC_FUNC_PTRS
+};
+
 //===--------------------------------------------------------------------===//
 // X86RelocationFactory
+//===--------------------------------------------------------------------===//
 X86RelocationFactory::X86RelocationFactory(size_t pNum,
                                            X86GNULDBackend& pParent)
   : RelocationFactory(pNum),
@@ -33,61 +56,30 @@
 {
 }
 
-void X86RelocationFactory::applyRelocation(Relocation& pRelocation,
+RelocationFactory::Result
+X86RelocationFactory::applyRelocation(Relocation& pRelocation,
                                            const MCLDInfo& pLDInfo)
 {
   Relocation::Type type = pRelocation.type();
 
-  /// the prototype of applying function
-  typedef Result (*ApplyFunctionType)(Relocation& pReloc,
-				      const MCLDInfo& pLDInfo,
-                                      X86RelocationFactory& pParent);
-
-  // the table entry of applying functions
-  struct ApplyFunctionTriple {
-    ApplyFunctionType func;
-    unsigned int type;
-    const char* name;
-  };
-
-  // declare the table of applying functions
-  static ApplyFunctionTriple apply_functions[] = {
-    DECL_X86_APPLY_RELOC_FUNC_PTRS
-  };
-
-  if (type >= sizeof (apply_functions) / sizeof (apply_functions[0]) ) {
+  if (type >= sizeof (ApplyFunctions) / sizeof (ApplyFunctions[0]) ) {
     fatal(diag::unknown_relocation) << (int)type <<
                                        pRelocation.symInfo()->name();
-    return;
+    return Unknown;
   }
 
   // apply the relocation
-  Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
-
-  // check result
-  if (OK == result) {
-    return;
-  }
-  if (Overflow == result) {
-    error(diag::result_overflow) << apply_functions[type].name
-                                 << pRelocation.symInfo()->name();
-    return;
-  }
-
-  if (BadReloc == result) {
-    error(diag::result_badreloc) << apply_functions[type].name
-                                 << pRelocation.symInfo()->name();
-    return;
-  }
+  return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
 }
 
+const char* X86RelocationFactory::getName(Relocation::Type pType) const
+{
+  return ApplyFunctions[pType].name;
+}
 
-
-// non-member functions
-
-//=========================================//
-// Relocation helper function              //
-//=========================================//
+//===--------------------------------------------------------------------===//
+// Relocation helper function
+//===--------------------------------------------------------------------===//
 
 // Check if symbol can use relocation R_386_RELATIVE
 static bool
@@ -257,6 +249,9 @@
   ResolveInfo* rsym = pReloc.symInfo();
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   RelocationFactory::DWord S = pReloc.symValue();
+  bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
+                       *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT),
+                       pLDInfo, pLDInfo.output(), true);
 
   const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
                                                   *(pReloc.targetRef().frag()));
@@ -269,7 +264,7 @@
   }
 
   // A local symbol may need REL Type dynamic relocation
-  if (rsym->isLocal() && (rsym->reserved() & X86GNULDBackend::ReserveRel)) {
+  if (rsym->isLocal() && has_dyn_rel) {
     helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
     pReloc.target() = S + A;
     return X86RelocationFactory::OK;
@@ -284,7 +279,7 @@
     // 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 (has_dyn_rel) {
       if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
         helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
       }
diff --git a/lib/Target/X86/X86RelocationFactory.h b/lib/Target/X86/X86RelocationFactory.h
index 6a6c372..4b413d7 100644
--- a/lib/Target/X86/X86RelocationFactory.h
+++ b/lib/Target/X86/X86RelocationFactory.h
@@ -26,21 +26,10 @@
 class X86RelocationFactory : public RelocationFactory
 {
 public:
-  /** \enum Reloc
-   *  \brief Reloc is the result of applying functions.
-   */
-  enum Result
-  {
-    OK,
-    Overflow,
-    BadReloc
-  };
-
-public:
   X86RelocationFactory(size_t pNum, X86GNULDBackend& pParent);
   ~X86RelocationFactory();
 
-  void applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+  Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
 
   X86GNULDBackend& getTarget()
   { return m_Target; }
@@ -48,6 +37,8 @@
   const X86GNULDBackend& getTarget() const
   { return m_Target; }
 
+  const char* getName(Relocation::Type pType) const;
+
 private:
   X86GNULDBackend& m_Target;
 };
diff --git a/lib/Target/X86/X86SectLinker.cpp b/lib/Target/X86/X86SectLinker.cpp
index 300b112..a888f47 100644
--- a/lib/Target/X86/X86SectLinker.cpp
+++ b/lib/Target/X86/X86SectLinker.cpp
@@ -11,7 +11,6 @@
 
 #include "X86.h"
 #include "X86ELFSectLinker.h"
-#include <stdlib.h>
 
 using namespace mcld;
 
@@ -26,16 +25,17 @@
   Triple theTriple(pTriple);
   if (theTriple.isOSDarwin()) {
     assert(0 && "MachO linker has not supported yet");
+    return NULL;
   }
   if (theTriple.isOSWindows()) {
     assert(0 && "COFF linker has not supported yet");
+    return NULL;
   }
 
   if (theTriple.isArch32Bit())
     return new X86ELFSectLinker(pOption, pLDBackend);
 
   assert(0 && "X86_64 has not supported yet");
-  abort();
   return NULL;
 }
 
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index 7e6b9c8..726e08e 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -896,6 +896,13 @@
 {
   LLVMContext &Context = getGlobalContext();
   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
+  cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
+
+#ifdef ENABLE_UNITTEST
+  if (UnitTest) {
+    return unit_test( argc, argv );
+  }
+#endif
 
   // Initialize targets first, so that --version shows registered targets.
   InitializeAllTargets();
@@ -906,14 +913,6 @@
   mcld::InitializeAllLinkers();
   mcld::InitializeAllDiagnostics();
 
-  cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
-
-#ifdef ENABLE_UNITTEST
-  if (UnitTest) {
-    return unit_test( argc, argv );
-  }
-#endif
-
   // Load the module to be compiled...
   std::auto_ptr<Module> M;
 
@@ -1080,7 +1079,7 @@
 
   // Set up MsgHandler
   OwningPtr<mcld::DiagnosticLineInfo>
-    diag_line_info(TheTarget->createDiagnosticLineInfo(*TheTarget->get(),
+    diag_line_info(TheTarget->createDiagnosticLineInfo(*TheTarget,
                                                        TheTriple.getTriple()));
   OwningPtr<mcld::DiagnosticPrinter>
     diag_printer(new mcld::TextDiagnosticPrinter(mcld::errs(),
diff --git a/tools/mcld/include/alone/Linker.h b/tools/mcld/include/alone/Linker.h
index 17f8baa..9321e94 100644
--- a/tools/mcld/include/alone/Linker.h
+++ b/tools/mcld/include/alone/Linker.h
@@ -6,13 +6,28 @@
 // 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>
+#include <string>
+
+namespace mcld {
+
+class TargetLDBackend;
+class MCLDDriver;
+class MemoryFactory;
+class MCLDInfo;
+class TreeIteratorBase;
+class Input;
+
+namespace sys { namespace fs {
+
+class Path;
+
+} } // end namespace sys::fs
+
+} // end namespace mcld
 
 namespace alone {
 
@@ -26,6 +41,7 @@
     kDoubleConfig,
     kCreateBackend,
     kDelegateLDInfo,
+    kFindNameSpec,
     kOpenNameSpec,
     kOpenObjectFile,
     kNotConfig,
@@ -42,9 +58,11 @@
 private:
   mcld::TargetLDBackend *mBackend;
   mcld::MCLDDriver *mDriver;
-  mcld::MCLDInfo *mLDInfo;
-  mcld::InputTree::iterator mRoot;
   MemoryFactory *mMemAreaFactory;
+  mcld::MCLDInfo *mLDInfo;
+  mcld::TreeIteratorBase *mRoot;
+  bool mShared;
+  std::string mSOName;
 
 public:
   Linker();
diff --git a/tools/mcld/lib/Core/Linker.cpp b/tools/mcld/lib/Core/Linker.cpp
index 0d112ba..9ab21cc 100644
--- a/tools/mcld/lib/Core/Linker.cpp
+++ b/tools/mcld/lib/Core/Linker.cpp
@@ -6,12 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+
 #include "alone/Linker.h"
 #include "alone/Support/LinkerConfig.h"
 #include "alone/Support/MemoryFactory.h"
+#include "alone/Support/Log.h"
 
 #include <llvm/Support/ELF.h>
 
+#include <mcld/MC/MCLDDriver.h>
+#include <mcld/MC/InputTree.h>
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/InputTree.h>
 #include <mcld/LD/LDSection.h>
@@ -20,11 +24,12 @@
 #include <mcld/Support/Path.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/TargetRegistry.h>
 
 using namespace alone;
 
-const char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode)
-{
+const char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode) {
   static const char* ErrorString[] = {
     /* kSuccess */
     "Successfully compiled.",
@@ -34,6 +39,8 @@
     "Cannot create backend.",
     /* kDelegateLDInfo */
     "Cannot get linker information",
+    /* kFindNameSpec */
+    "Cannot find -lnamespec",
     /* kOpenNameSpec */
     "Cannot open -lnamespec",
     /* kOpenObjectFile */
@@ -65,11 +72,13 @@
 // Linker
 //===----------------------------------------------------------------------===//
 Linker::Linker()
-  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL) {
+  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
+    mRoot(NULL), mShared(false) {
 }
 
 Linker::Linker(const LinkerConfig& pConfig)
-  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL) {
+  : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
+    mRoot(NULL), mShared(false) {
 
   const std::string &triple = pConfig.getTriple();
 
@@ -82,36 +91,36 @@
   return;
 }
 
-Linker::~Linker()
-{
-  if (NULL != mDriver)
-    delete mDriver;
-  if (NULL != mBackend)
-    delete mBackend;
-  if (NULL != mMemAreaFactory)
-    delete mMemAreaFactory;
+Linker::~Linker() {
+  delete mDriver;
+  delete mBackend;
+  delete mMemAreaFactory;
 }
 
-enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig)
-{
+enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
   mLDInfo = const_cast<mcld::MCLDInfo*>(pConfig.getLDInfo());
-  if (NULL == mLDInfo)
+  if (mLDInfo == NULL) {
     return kDelegateLDInfo;
+  }
 
-  mRoot = mLDInfo->inputs().root();
+  mRoot = &mLDInfo->inputs().root();
+  mShared = pConfig.isShared();
+  mSOName = pConfig.getSOName();
+
   return kSuccess;
 }
 
-enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig)
-{
-  if (NULL != mLDInfo)
+enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
+  if (mLDInfo != NULL) {
     return kDoubleConfig;
+  }
 
   extractFiles(pConfig);
 
   mBackend = pConfig.getTarget()->createLDBackend(pConfig.getTriple());
-  if (NULL == mBackend)
+  if (mBackend == NULL) {
     return kCreateBackend;
+  }
 
   mDriver = new mcld::MCLDDriver(*mLDInfo, *mBackend);
 
@@ -122,32 +131,33 @@
   return kSuccess;
 }
 
-void Linker::advanceRoot()
-{
-  if (mRoot.isRoot())
-    --mRoot;
-  else
-    ++mRoot;
+void Linker::advanceRoot() {
+  if (mRoot->isRoot()) {
+    mRoot->move<mcld::TreeIteratorBase::Leftward>();
+  } else {
+    mRoot->move<mcld::TreeIteratorBase::Rightward>();
+  }
+  return;
 }
 
-enum Linker::ErrorCode
-Linker::openFile(const mcld::sys::fs::Path& pPath, enum Linker::ErrorCode pCode, mcld::Input& pInput)
-{
+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())
+  if (input_memory->handler()->isGood()) {
     pInput.setMemArea(input_memory);
-  else
+  } 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)
-{
+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()) {
@@ -156,23 +166,29 @@
 
     if (mLDInfo->attrFactory().last().isStatic()) {
       // with --static, we must search an archive.
-      path = mLDInfo->options().directories().find(pNameSpec, mcld::Input::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);
+      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);
+    path = mLDInfo->options().directories().find(pNameSpec,
+                                                 mcld::Input::Archive);
   }
 
+  if (NULL == path)
+    return kFindNameSpec;
+
   mcld::Input* input = mLDInfo->inputFactory().produce(pNameSpec, *path,
-                                                        mcld::Input::Unknown);
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(mRoot, *input);
+                                                       mcld::Input::Unknown);
+  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
 
   advanceRoot();
 
@@ -180,13 +196,12 @@
 }
 
 /// addObject - Add a object file by the filename.
-enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath)
-{
+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);
+  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
 
   advanceRoot();
 
@@ -194,14 +209,13 @@
 }
 
 /// addObject - Add a piece of memory. The memory is of ELF format.
-enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize)
-{
+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);
+  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
 
   advanceRoot();
 
@@ -214,13 +228,12 @@
   return kSuccess;
 }
 
-enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize)
-{
+enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
   mcld::Input* input = mLDInfo->inputFactory().produce("code object",
-                                                        "NAN",
-                                                        mcld::Input::External);
+                                                       "NAN",
+                                                       mcld::Input::External);
 
-  mLDInfo->inputs().insert<mcld::InputTree::Positional>(mRoot, *input);
+  mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
 
   advanceRoot();
 
@@ -232,17 +245,20 @@
 
   // FIXME: So far, MCLinker must set up output before add input files.
   // set up LDContext
-  if (mDriver->hasInitLinker())
+  if (mDriver->hasInitLinker()) {
     return kNotConfig;
+  }
 
-  if (!mLDInfo->output().hasContext())
+  if (!mLDInfo->output().hasContext()) {
     return kNotSetUpOutput;
+  }
 
   // create NULL section
-  mcld::LDSection& null = mDriver->getLinker()->createSectHdr("",
-                             mcld::LDFileFormat::Null,
-                             llvm::ELF::SHT_NULL,
-                             0);
+  mcld::LDSection& null =
+      mDriver->getLinker()->createSectHdr("",
+                                          mcld::LDFileFormat::Null,
+                                          llvm::ELF::SHT_NULL,
+                                          0);
 
   null.setSize(0);
   null.setOffset(0);
@@ -269,43 +285,52 @@
   return kSuccess;
 }
 
-enum Linker::ErrorCode Linker::setOutput(const std::string &pPath)
-{
-  if (mLDInfo->output().hasContext())
+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);
+                      pPath,
+                      mcld::FileHandle::ReadWrite |
+                        mcld::FileHandle::Truncate |
+                        mcld::FileHandle::Create,
+                      perm);
 
-  if (!out_area->handler()->isGood())
+  if (!out_area->handler()->isGood()) {
     return kOpenOutput;
+  }
 
-  // FIXME: decide output type by command line option.
-  mLDInfo->output().setType(mcld::Output::DynObj);
+  if (mShared) {
+    mLDInfo->output().setType(mcld::Output::DynObj);
+  } else {
+    mLDInfo->output().setType(mcld::Output::Exec);
+  }
+
+  mLDInfo->output().setSOName(mSOName);
   mLDInfo->output().setMemArea(out_area);
   mLDInfo->output().setContext(mLDInfo->contextFactory().produce(pPath));
 
   // FIXME: We must initialize MCLinker before setOutput, and initialize
   // standard sections here. This is because we have to build the section
   // map before input files using it.
-  if (!mDriver->hasInitLinker())
+  if (!mDriver->hasInitLinker()) {
     return kNotConfig;
+  }
 
   mDriver->initStdSections();
 
   return kSuccess;
 }
 
-enum Linker::ErrorCode Linker::setOutput(int pFileHandler)
-{
-  if (mLDInfo->output().hasContext())
+enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
+  if (mLDInfo->output().hasContext()) {
     return kDoubleConfig;
+  }
 
   // -----  initialize output file  ----- //
   mcld::MemoryArea* out_area = mMemAreaFactory->produce(pFileHandler);
@@ -317,27 +342,29 @@
   // 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())
+  if (!mDriver->hasInitLinker()) {
     return kNotConfig;
+  }
+
   mDriver->initStdSections();
 
   return kSuccess;
 }
 
-enum Linker::ErrorCode Linker::link()
-{
+enum Linker::ErrorCode Linker::link() {
   mDriver->normalize();
 
-  if (!mDriver->readSections() ||
-      !mDriver->mergeSections())
+  if (!mDriver->readSections() || !mDriver->mergeSections()) {
     return kReadSections;
+  }
 
-  if (!mDriver->readSymbolTables())
+  if (!mDriver->readSymbolTables()) {
     return kReadSymbols;
+  }
 
-  if (!mDriver->addStandardSymbols() ||
-      !mDriver->addTargetSymbols())
+  if (!mDriver->addStandardSymbols() || !mDriver->addTargetSymbols()) {
     return kAddAdditionalSymbols;
+  }
 
   mDriver->readRelocations();
   mDriver->prelayout();
diff --git a/tools/mcld/lib/Support/LinkerConfig.cpp b/tools/mcld/lib/Support/LinkerConfig.cpp
index 8da9bbe..30506a8 100644
--- a/tools/mcld/lib/Support/LinkerConfig.cpp
+++ b/tools/mcld/lib/Support/LinkerConfig.cpp
@@ -8,10 +8,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "alone/Support/LinkerConfig.h"
+#include "alone/Support/Log.h"
 
 #include <llvm/Support/Signals.h>
 
 #include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDFile.h>
 #include <mcld/MC/MCLDDirectory.h>
 #include <mcld/LD/TextDiagnosticPrinter.h>
 #include <mcld/Support/Path.h>
@@ -21,23 +23,21 @@
 using namespace alone;
 
 LinkerConfig::LinkerConfig(const std::string &pTriple)
-  : mTriple(pTriple), mTarget(NULL), mLDInfo(NULL), mDiagLineInfo(NULL),
-    mDiagPrinter(NULL) {
+  : mTriple(pTriple), mShared(false), mSOName(), mTarget(NULL), mLDInfo(NULL),
+    mDiagLineInfo(NULL), mDiagPrinter(NULL) {
 
   initializeTarget();
   initializeLDInfo();
   initializeDiagnostic();
 }
 
-LinkerConfig::~LinkerConfig()
-{
-  if (NULL != mLDInfo)
-    delete mLDInfo;
+LinkerConfig::~LinkerConfig() {
+  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.
+  if (mDiagPrinter->getNumErrors() != 0) {
+    // If here, the program failed ungracefully. Run the interrupt handlers to
+    // ensure any other cleanups (e.g., files that registered by
+    // RemoveFileOnSignal(...)) getting done before exit.
     llvm::sys::RunInterruptHandlers();
   }
   mDiagPrinter->finish();
@@ -46,8 +46,7 @@
   delete mDiagPrinter;
 }
 
-bool LinkerConfig::initializeTarget()
-{
+bool LinkerConfig::initializeTarget() {
   std::string error;
   mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error);
   if (NULL != mTarget) {
@@ -59,8 +58,7 @@
   }
 }
 
-bool LinkerConfig::initializeLDInfo()
-{
+bool LinkerConfig::initializeLDInfo() {
   if (NULL != mLDInfo) {
     ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
           mTriple.c_str());
@@ -71,10 +69,9 @@
   return true;
 }
 
-bool LinkerConfig::initializeDiagnostic()
-{
-  // Set up MsgHandler
-  mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget->get(), mTriple);
+bool LinkerConfig::initializeDiagnostic() {
+  // Set up MsgHandler.
+  mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
 
   mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDInfo);
 
@@ -83,46 +80,99 @@
   return true;
 }
 
-void LinkerConfig::setSysRoot(const std::string &pSysRoot)
-{
-  mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
+void LinkerConfig::setShared(bool pEnable) {
+  mShared = pEnable;
+  return;
 }
 
-void LinkerConfig::addWrap(const std::string &pWrapSymbol)
-{
+void LinkerConfig::setBsymbolic(bool pEnable) {
+  mLDInfo->options().setBsymbolic(pEnable);
+  return;
+}
+
+void LinkerConfig::setSOName(const std::string &pSOName) {
+  mLDInfo->output().setSOName(pSOName);
+  return;
+}
+
+void LinkerConfig::setDyld(const std::string &pDyld) {
+  mLDInfo->options().setDyld(pDyld);
+  return;
+}
+
+void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
+  mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
+  return;
+}
+
+void LinkerConfig::addWrap(const std::string &pWrapSymbol) {
   bool exist = false;
 
-  // add wname -> __wrap_wname
+  // 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)
+  if (exist) {
     mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str;
+  }
 
-  // add __real_wname -> wname
+  // 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)
+  if (exist) {
     mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str;
+  }
+
+  return;
 }
 
-void LinkerConfig::addSearchDir(const std::string &pDirPath)
-{
+void LinkerConfig::addPortable(const std::string &pPortableSymbol) {
+  bool exist = false;
+
+  // Add pname -> pname_portable.
+  mcld::StringEntry<llvm::StringRef>* to_port =
+                mLDInfo->scripts().renameMap().insert(pPortableSymbol, exist);
+
+  std::string to_port_str = pPortableSymbol + "_portable";
+  to_port->setValue(to_port_str);
+
+  if (exist) {
+    mcld::warning(mcld::diag::rewrap) << pPortableSymbol << to_port_str;
+}
+
+  // Add __real_pname -> pname.
+  std::string from_real_str = "__real_" + pPortableSymbol;
+  mcld::StringEntry<llvm::StringRef>* from_real =
+           mLDInfo->scripts().renameMap().insert(from_real_str, exist);
+
+  from_real->setValue(pPortableSymbol);
+
+  if (exist) {
+    mcld::warning(mcld::diag::rewrap) << pPortableSymbol << from_real_str;
+  }
+
+  return;
+}
+
+void LinkerConfig::addSearchDir(const std::string &pDirPath) {
   // SearchDirs will remove the created MCLDDirectory.
   mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
 
-  if (sd->isInSysroot())
+  if (sd->isInSysroot()) {
     sd->setSysroot(mLDInfo->options().sysroot());
+  }
+
   if (exists(sd->path()) && is_directory(sd->path())) {
     mLDInfo->options().directories().add(*sd);
-  }
-  else
+  } else {
     mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
-}
+  }
 
+  return;
+}
diff --git a/unittests/Linker/TestLinker.cpp b/unittests/Linker/TestLinker.cpp
new file mode 100644
index 0000000..243be86
--- /dev/null
+++ b/unittests/Linker/TestLinker.cpp
@@ -0,0 +1,285 @@
+//===- TestLinker.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "TestLinker.h"
+
+#include <iostream>
+
+#include <llvm/Support/TargetSelect.h>
+
+#include <mcld/LD/TextDiagnosticPrinter.h>
+#include <mcld/MC/InputTree.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/Support/RegionFactory.h>
+#include <mcld/Support/TargetSelect.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/SystemUtils.h>
+
+using namespace std;
+using namespace mcld;
+using namespace mcld::test;
+
+//===----------------------------------------------------------------------===//
+// TestLinker
+//===----------------------------------------------------------------------===//
+TestLinker::TestLinker()
+  : m_pTarget(NULL), m_pDriver(NULL), m_pInfo(NULL), m_pDiagLineInfo(NULL),
+    m_pDiagPrinter(NULL), m_pBackend(NULL), m_pRegionFactory(NULL) {
+}
+
+TestLinker::~TestLinker()
+{
+  std::list<mcld::FileHandle*>::iterator file, fEnd = m_FileHandleList.end();
+  for (file = m_FileHandleList.begin(); file != fEnd; ++file)
+    delete (*file);
+
+  std::list<mcld::MemoryArea*>::iterator mem, mEnd = m_MemAreaList.end() ;
+  for (mem = m_MemAreaList.begin(); mem != mEnd; ++mem)
+    delete (*mem);
+
+  delete m_pDriver;
+  delete m_pInfo;
+  delete m_pDiagLineInfo;
+  delete m_pDiagPrinter;
+  delete m_pBackend;
+  delete m_pRegionFactory;
+}
+
+bool TestLinker::initialize(const std::string &pTriple)
+{
+  bool is_initialized = false;
+
+  if (is_initialized)
+    return false;
+
+  // initilaize all llvm::Target and mcld::Target
+  llvm::InitializeAllTargets();
+  llvm::InitializeAllAsmPrinters();
+  llvm::InitializeAllAsmParsers();
+  llvm::InitializeAllTargetMCs();
+  mcld::InitializeAllTargets();
+  mcld::InitializeAllDiagnostics();
+
+  // create mcld::MCLDInfo
+  m_pInfo = new MCLDInfo(pTriple, 1, 32);
+  m_Root = m_pInfo->inputs().root();
+
+  // create mcld::RegionFactory
+  m_pRegionFactory = new mcld::RegionFactory(32);
+
+  // specify mcld::Target
+  std::string error;
+  m_pTarget = mcld::TargetRegistry::lookupTarget(pTriple, error);
+  if (NULL == m_pTarget) {
+    fatal(diag::fatal_cannot_init_target) << pTriple << error;
+    return false;
+  }
+
+  // create mcld::DiagnosticEngine
+  m_pDiagLineInfo = m_pTarget->createDiagnosticLineInfo(*m_pTarget, pTriple);
+  if (NULL == m_pDiagLineInfo) {
+    fatal(diag::fatal_cannot_init_lineinfo) << pTriple;
+    return false;
+  }
+
+  m_pDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *m_pInfo);
+
+  mcld::InitializeDiagnosticEngine(*m_pInfo, m_pDiagLineInfo, m_pDiagPrinter);
+
+  // create mcld::TargetLDBackend
+  m_pBackend = m_pTarget->createLDBackend(pTriple);
+  if (NULL == m_pBackend) {
+    fatal(diag::fatal_cannot_init_backend) << pTriple;
+    return false;
+  }
+
+  m_pDriver = new mcld::MCLDDriver(*m_pInfo, *m_pBackend);
+
+  m_pDriver->initMCLinker();
+
+  is_initialized = true;
+  return true;
+}
+
+void TestLinker::addObject(const std::string &pPath)
+{
+  mcld::Input* input = m_pInfo->inputFactory().produce(pPath, pPath,
+                                                       mcld::Input::Unknown);
+
+  m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+
+  advanceRoot();
+
+  mcld::FileHandle* handler = new mcld::FileHandle();
+  m_FileHandleList.push_back(handler);
+  if (!handler->open(pPath, mcld::FileHandle::ReadOnly)) {
+    mcld::error(mcld::diag::err_cannot_open_file)
+                                      << pPath
+                                      << mcld::sys::strerror(handler->error());
+  }
+
+  mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+  input->setMemArea(input_memory);
+  m_MemAreaList.push_back(input_memory);
+
+  mcld::LDContext* context = m_pInfo->contextFactory().produce(pPath);
+  input->setContext(context);
+}
+
+void TestLinker::addObject(void* pMemBuffer, size_t pSize)
+{
+  mcld::Input* input = m_pInfo->inputFactory().produce("memory object", "NAN",
+                                                       mcld::Input::Unknown);
+
+  m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+
+  advanceRoot();
+
+  mcld::Space* space = new mcld::Space(mcld::Space::EXTERNAL, pMemBuffer, pSize);
+  mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *space);
+  input->setMemArea(input_memory);
+  m_MemAreaList.push_back(input_memory);
+
+  mcld::LDContext* context = m_pInfo->contextFactory().produce();
+  input->setContext(context);
+}
+
+void TestLinker::addObject(int pFileHandler)
+{
+  mcld::Input* input = m_pInfo->inputFactory().produce("handler object", "NAN",
+                                                       mcld::Input::Unknown);
+
+  m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+
+  advanceRoot();
+
+  mcld::FileHandle* handler = new mcld::FileHandle();
+  m_FileHandleList.push_back(handler);
+  handler->delegate(pFileHandler);
+
+  mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+  input->setMemArea(input_memory);
+  m_MemAreaList.push_back(input_memory);
+
+  mcld::LDContext* context = m_pInfo->contextFactory().produce();
+  input->setContext(context);
+}
+
+void TestLinker::addNameSpec(const std::string &pNameSpec)
+{
+  mcld::sys::fs::Path* path = NULL;
+  // find out the real path of the namespec.
+  if (m_pInfo->attrFactory().constraint().isSharedSystem()) {
+    // In the system with shared object support, we can find both archive
+    // and shared object.
+
+    if (m_pInfo->attrFactory().last().isStatic()) {
+      // with --static, we must search an archive.
+      path = m_pInfo->options().directories().find(pNameSpec,
+                                                   mcld::Input::Archive);
+    }
+    else {
+      // otherwise, with --Bdynamic, we can find either an archive or a
+      // shared object.
+      path = m_pInfo->options().directories().find(pNameSpec,
+                                                   mcld::Input::DynObj);
+    }
+  }
+  else {
+    // In the system without shared object support, we only look for an
+    // archive.
+    path = m_pInfo->options().directories().find(pNameSpec,
+                                                 mcld::Input::Archive);
+  }
+
+  if (NULL == path) {
+    mcld::fatal(diag::err_cannot_find_namespec) << pNameSpec;
+    return;
+  }
+
+  mcld::Input* input = m_pInfo->inputFactory().produce(pNameSpec, *path,
+                                                       mcld::Input::Unknown);
+
+  m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+
+  advanceRoot();
+
+  mcld::FileHandle* handler = new mcld::FileHandle();
+  m_FileHandleList.push_back(handler);
+  if (!handler->open(*path, mcld::FileHandle::ReadOnly)) {
+    mcld::error(mcld::diag::err_cannot_open_file)
+                                      << *path
+                                      << mcld::sys::strerror(handler->error());
+  }
+
+  mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+  input->setMemArea(input_memory);
+  m_MemAreaList.push_back(input_memory);
+
+  mcld::LDContext* context = m_pInfo->contextFactory().produce(*path);
+  input->setContext(context);
+}
+
+bool TestLinker::setOutput(const std::string &pPath)
+{
+  if (m_pInfo->output().hasContext())
+    return false;
+
+  mcld::FileHandle* handler = new mcld::FileHandle();
+  m_FileHandleList.push_back(handler);
+  bool open_res = handler->open(pPath, mcld::FileHandle::ReadWrite |
+                                       mcld::FileHandle::Truncate |
+                                       mcld::FileHandle::Create,
+                                mcld::FileHandle::Permission(0755));
+  if (!open_res) {
+    mcld::error(mcld::diag::err_cannot_open_file)
+                                      << pPath
+                                      << mcld::sys::strerror(handler->error());
+  }
+
+  mcld::MemoryArea* output_memory = new MemoryArea(*m_pRegionFactory, *handler);
+  m_pInfo->output().setMemArea(output_memory);
+  m_MemAreaList.push_back(output_memory);
+
+  mcld::LDContext* context = m_pInfo->contextFactory().produce(pPath);
+  m_pInfo->output().setContext(context);
+
+  // FIXME: remove the initStdSections().
+  m_pDriver->initStdSections();
+  return true;
+}
+
+bool TestLinker::setOutput(int pFileHandler)
+{
+  if (m_pInfo->output().hasContext())
+    return false;
+
+  mcld::FileHandle* handler = new mcld::FileHandle();
+  handler->delegate(pFileHandler);
+  m_FileHandleList.push_back(handler);
+
+  mcld::MemoryArea* output_memory = new MemoryArea(*m_pRegionFactory, *handler);
+  m_pInfo->output().setMemArea(output_memory);
+  m_MemAreaList.push_back(output_memory);
+
+  mcld::LDContext* context = m_pInfo->contextFactory().produce();
+  m_pInfo->output().setContext(context);
+
+  // FIXME: remove the initStdSections().
+  m_pDriver->initStdSections();
+  return true;
+}
+
+void TestLinker::advanceRoot()
+{
+    if (m_Root.isRoot())
+      --m_Root;
+    else
+      ++m_Root;
+}
diff --git a/unittests/Linker/TestLinker.h b/unittests/Linker/TestLinker.h
new file mode 100644
index 0000000..79b3010
--- /dev/null
+++ b/unittests/Linker/TestLinker.h
@@ -0,0 +1,112 @@
+//===- TestLinker.h -------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TEST_LINKER_H
+#define MCLD_TEST_LINKER_H
+
+#include <gtest.h>
+
+#include <string>
+#include <list>
+
+#include <mcld/MC/MCLDDriver.h>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Support/Path.h>
+
+namespace mcld {
+
+class MCLDInfo;
+class TargetLDBackend;
+class RegionFactory;
+
+namespace test
+{
+
+class TestLinker
+{
+public:
+  TestLinker();
+
+  ~TestLinker();
+
+  bool initialize(const std::string &pTriple);
+
+  MCLDInfo* config() {
+    assert(NULL != m_pInfo);
+    return m_pInfo;
+  }
+
+  const MCLDInfo* config() const {
+    assert(NULL != m_pInfo);
+    return m_pInfo;
+  }
+
+  void addObject(const std::string &pPath);
+
+  void addObject(const mcld::sys::fs::Path &pPath)
+  { addObject(pPath.native()); }
+
+  void addObject(void* pMemBuffer, size_t pSize);
+
+  void addObject(int pFileHandler);
+
+  void addNameSpec(const std::string &pNameSpec);
+
+  bool setOutput(const std::string &pPath);
+
+  bool setOutput(int pFileHandler);
+
+  /// getDriver
+  MCLDDriver* getDriver() {
+    assert(NULL != m_pDriver);
+    return m_pDriver;
+  }
+
+  /// getDriver
+  const MCLDDriver* getDriver() const {
+    assert(NULL != m_pDriver);
+    return m_pDriver;
+  }
+
+  /// getLinker
+  MCLinker* getLinker() {
+    assert(NULL != m_pDriver);
+    return m_pDriver->getLinker();
+  }
+
+  /// getLinker
+  const MCLinker* getLinker() const {
+    assert(NULL != m_pDriver);
+    return m_pDriver->getLinker();
+  }
+
+private:
+  void advanceRoot();
+
+private:
+  const mcld::Target* m_pTarget;
+  mcld::MCLDDriver *m_pDriver;
+  mcld::MCLDInfo* m_pInfo;
+  mcld::DiagnosticLineInfo* m_pDiagLineInfo;
+  mcld::DiagnosticPrinter* m_pDiagPrinter;
+  mcld::TargetLDBackend* m_pBackend;
+  mcld::InputTree::iterator m_Root;
+  mcld::RegionFactory* m_pRegionFactory;
+
+  std::list<mcld::FileHandle*> m_FileHandleList;
+  std::list<mcld::MemoryArea*> m_MemAreaList;
+
+};
+
+} // namespace of test
+} // namespace of mcld
+#endif
+
diff --git a/unittests/StaticResolverTest.cpp b/unittests/StaticResolverTest.cpp
index 0e1e5c9..5839507 100644
--- a/unittests/StaticResolverTest.cpp
+++ b/unittests/StaticResolverTest.cpp
@@ -27,19 +27,21 @@
 using namespace mcld;
 using namespace mcldtest;
 
+//===----------------------------------------------------------------------===//
+// StaticResolverTest
+//===----------------------------------------------------------------------===//
 // Constructor can do set-up work for all test here.
 StaticResolverTest::StaticResolverTest()
-{
+  : m_pResolver(NULL), m_pFactory(NULL), m_pLDInfo(NULL), m_pLineInfo(NULL) {
   // create testee. modify it if need
   m_pResolver = new StaticResolver();
   m_pFactory = new ResolveInfoFactory();
+
   mcld::InitializeAllDiagnostics();
 
   m_pLDInfo = new MCLDInfo("arm-none-linux-gnueabi", 10, 10);
   m_pLineInfo = new DiagnosticLineInfo();
-  m_pPrinter = new mcld::DiagnosticPrinter(); //llvm::errs(), *m_pLDInfo);
-  mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, m_pPrinter);
-
+  mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, NULL);
 }
 
 // Destructor can do clean-up work that doesn't throw exceptions here.
diff --git a/unittests/TestLinkerTest.cpp b/unittests/TestLinkerTest.cpp
new file mode 100644
index 0000000..b6df3cf
--- /dev/null
+++ b/unittests/TestLinkerTest.cpp
@@ -0,0 +1,75 @@
+//===- TestLinkerTest.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Linker/TestLinker.h"
+#include "TestLinkerTest.h"
+
+#include <mcld/Support/Path.h>
+#include <mcld/MC/MCLDDirectory.h>
+
+using namespace mcld;
+using namespace mcld::test;
+using namespace mcld::sys::fs;
+using namespace mcldtest;
+
+
+// Constructor can do set-up work for all test here.
+TestLinkerTest::TestLinkerTest()
+  : m_pLinker(NULL) {
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+TestLinkerTest::~TestLinkerTest()
+{
+}
+
+// SetUp() will be called immediately before each test.
+void TestLinkerTest::SetUp()
+{
+  m_pLinker = new mcld::test::TestLinker();
+  m_pLinker->initialize("arm-none-linux-gnueabi");
+
+  // set up target-dependent constraints of attributes
+  m_pLinker->config()->attrFactory().constraint().enableWholeArchive();
+  m_pLinker->config()->attrFactory().constraint().disableAsNeeded();
+  m_pLinker->config()->attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  m_pLinker->config()->attrFactory().predefined().setWholeArchive();
+  m_pLinker->config()->attrFactory().predefined().setDynamic();
+
+  // set up target dependent options
+  mcld::sys::fs::Path path = TOPDIR;
+  path.append("test/libs/ARM/Android/android-14");
+  m_pLinker->config()->options().setSysroot(path);
+  m_pLinker->config()->options().setDyld("/usr/lib/ld.so.1");
+  m_pLinker->config()->options().directories().add("=/");
+  m_pLinker->config()->options().setBsymbolic(true);
+}
+
+// TearDown() will be called immediately after each test.
+void TestLinkerTest::TearDown()
+{
+  delete m_pLinker;
+}
+
+//===----------------------------------------------------------------------===//
+// Testcases
+//===----------------------------------------------------------------------===//
+TEST_F( TestLinkerTest, test) {
+  m_pLinker->config()->options().setVerbose(3);
+  mcld::sys::fs::Path top_level = TOPDIR;
+  m_pLinker->addObject(top_level + "test/libs/ARM/Android/android-14/crtbegin_so.o");
+  m_pLinker->addObject(top_level + "test/Android/Plasma/ARM/plasma.o");
+  m_pLinker->addNameSpec("m");
+  m_pLinker->addNameSpec("log");
+  m_pLinker->addNameSpec("jnigraphics");
+  m_pLinker->addNameSpec("c");
+  m_pLinker->addObject(top_level + "test/libs/ARM/Android/android-14/crtend_so.o");
+}
+
diff --git a/unittests/TestLinkerTest.h b/unittests/TestLinkerTest.h
new file mode 100644
index 0000000..ba6efcf
--- /dev/null
+++ b/unittests/TestLinkerTest.h
@@ -0,0 +1,40 @@
+//===- TestLinkerTest.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TEST_LINKER_TEST_H
+#define MCLD_TEST_LINKER_TEST_H
+#include <gtest.h>
+
+#include "Linker/TestLinker.h"
+
+namespace mcldtest
+{
+
+class TestLinkerTest : public ::testing::Test
+{
+public:
+  // Constructor can do set-up work for all test here.
+  TestLinkerTest();
+
+  // Destructor can do clean-up work that doesn't throw exceptions here.
+  virtual ~TestLinkerTest();
+
+  // SetUp() will be called immediately before each test.
+  virtual void SetUp();
+
+  // TearDown() will be called immediately after each test.
+  virtual void TearDown();
+
+protected:
+  mcld::test::TestLinker* m_pLinker;
+};
+
+} // namespace of mcldtest
+
+#endif
+
diff --git a/unittests/UniqueGCFactoryBaseTest.cpp b/unittests/UniqueGCFactoryBaseTest.cpp
index 328e924..067467b 100644
--- a/unittests/UniqueGCFactoryBaseTest.cpp
+++ b/unittests/UniqueGCFactoryBaseTest.cpp
@@ -24,8 +24,7 @@
 
   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);
+  mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, NULL);
 }
 
 // Destructor can do clean-up work that doesn't throw exceptions here.