Linkloader improvement: mclinker.

Change-Id: I8805e39ccbc2ee204234fb3e71c70c906f3990bb
diff --git a/lib/Target/Mips/Android.mk b/lib/Target/Mips/Android.mk
new file mode 100644
index 0000000..cc5a211
--- /dev/null
+++ b/lib/Target/Mips/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_mips_target_SRC_FILES := \
+  MipsAndroidSectLinker.cpp \
+  MipsELFDynamic.cpp  \
+  MipsELFSectLinker.cpp \
+  MipsGOT.cpp \
+  MipsLDBackend.cpp \
+  MipsRelocationFactory.cpp \
+  MipsSectLinker.cpp  \
+  MipsTargetMachine.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_mips_target_SRC_FILES)
+LOCAL_MODULE:= libmcldMipsTarget
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifeq ($(TARGET_ARCH),mips)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_mips_target_SRC_FILES)
+LOCAL_MODULE:= libmcldMipsTarget
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h
new file mode 100644
index 0000000..a63be45
--- /dev/null
+++ b/lib/Target/Mips/Mips.h
@@ -0,0 +1,20 @@
+//===- Mips.h -------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MIPS_H
+#define MCLD_MIPS_H
+
+#include "mcld/Support/TargetRegistry.h"
+
+namespace mcld {
+
+extern mcld::Target TheMipselTarget;
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Mips/MipsAndroidSectLinker.cpp b/lib/Target/Mips/MipsAndroidSectLinker.cpp
new file mode 100644
index 0000000..e697fbc
--- /dev/null
+++ b/lib/Target/Mips/MipsAndroidSectLinker.cpp
@@ -0,0 +1,33 @@
+//===- MipsAndroidSectLinker.cpp ------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsAndroidSectLinker.h"
+
+#include <mcld/CodeGen/SectLinkerOption.h>
+
+using namespace mcld;
+
+MipsAndroidSectLinker::MipsAndroidSectLinker(SectLinkerOption &pOption,
+                                             TargetLDBackend &pLDBackend)
+  : AndroidSectLinker(pOption,
+                      pLDBackend) {
+  MCLDInfo &info = pOption.info();
+  // set up target-dependent constraints of attibutes
+  info.attrFactory().constraint().disableWholeArchive();
+  info.attrFactory().constraint().disableAsNeeded();
+  info.attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  info.attrFactory().predefined().unsetWholeArchive();
+  info.attrFactory().predefined().setDynamic();
+}
+
+MipsAndroidSectLinker::~MipsAndroidSectLinker()
+{
+}
diff --git a/lib/Target/Mips/MipsAndroidSectLinker.h b/lib/Target/Mips/MipsAndroidSectLinker.h
new file mode 100644
index 0000000..ba216e4
--- /dev/null
+++ b/lib/Target/Mips/MipsAndroidSectLinker.h
@@ -0,0 +1,36 @@
+//===- MipsAndroidSectLinker.h --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MIPS_ANDROIDSECTLINKER_H
+#define MIPS_ANDROIDSECTLINKER_H
+
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include "mcld/Target/AndroidSectLinker.h"
+
+namespace mcld
+{
+
+/** \class MipsAndroidSectLinker
+ *  \brief MipsAndroidSectLinker sets up the environment for linking.
+ *
+ */
+class MipsAndroidSectLinker : public AndroidSectLinker
+{
+public:
+  MipsAndroidSectLinker(SectLinkerOption &pOption,
+                        mcld::TargetLDBackend &pLDBackend);
+
+  ~MipsAndroidSectLinker();
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Mips/MipsELFDynamic.cpp b/lib/Target/Mips/MipsELFDynamic.cpp
new file mode 100644
index 0000000..cd692ac
--- /dev/null
+++ b/lib/Target/Mips/MipsELFDynamic.cpp
@@ -0,0 +1,90 @@
+//===- MipsELFDynamic.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/LD/ELFFileFormat.h>
+#include <mcld/Target/GNULDBackend.h>
+#include "MipsELFDynamic.h"
+#include "MipsLDBackend.h"
+
+using namespace mcld;
+
+// MIPS mandatory dynamic section entries
+enum {
+  MIPS_RLD_VERSION  = 0x70000001,
+  MIPS_FLAGS        = 0x70000005,
+  MIPS_BASE_ADDRESS = 0x70000006,
+  MIPS_LOCAL_GOTNO  = 0x7000000a,
+  MIPS_SYMTABNO     = 0x70000011,
+  MIPS_GOTSYM       = 0x70000013,
+};
+
+MipsELFDynamic::MipsELFDynamic(const MipsGNULDBackend& pParent)
+  : ELFDynamic(pParent),
+    m_pParent(pParent)
+{
+}
+
+MipsELFDynamic::~MipsELFDynamic()
+{
+}
+
+void MipsELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat)
+{
+  // reservePLTGOT
+  if (pFormat.hasGOT())
+    reserveOne(llvm::ELF::DT_PLTGOT);
+
+  reserveOne(MIPS_RLD_VERSION);
+  reserveOne(MIPS_FLAGS);
+  reserveOne(MIPS_BASE_ADDRESS);
+  reserveOne(MIPS_LOCAL_GOTNO);
+  reserveOne(MIPS_SYMTABNO);
+  reserveOne(MIPS_GOTSYM);
+}
+
+void MipsELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat)
+{
+  // applyPLTGOT
+  if (pFormat.hasGOT())
+    applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOT().addr());
+
+  applyOne(MIPS_RLD_VERSION, 1);
+  applyOne(MIPS_FLAGS, 0);
+  applyOne(MIPS_BASE_ADDRESS, 0);
+  applyOne(MIPS_LOCAL_GOTNO, getLocalGotNum(pFormat));
+  applyOne(MIPS_SYMTABNO, getSymTabNum(pFormat));
+  applyOne(MIPS_GOTSYM, getGotSym(pFormat));
+}
+
+size_t MipsELFDynamic::getSymTabNum(const ELFFileFormat& pFormat) const
+{
+  if (!pFormat.hasDynSymTab())
+    return 0;
+
+  const LDSection& dynsym = pFormat.getDynSymTab();
+  return dynsym.size() / symbolSize();
+}
+
+size_t MipsELFDynamic::getGotSym(const ELFFileFormat& pFormat) const
+{
+  if (!pFormat.hasGOT())
+    return 0;
+
+  return getSymTabNum(pFormat) -
+         m_pParent.getGOT().getTotalNum() +
+         m_pParent.getGOT().getLocalNum();
+}
+
+size_t MipsELFDynamic::getLocalGotNum(const ELFFileFormat& pFormat) const
+{
+  if (!pFormat.hasGOT())
+    return 0;
+
+  return m_pParent.getGOT().getLocalNum();
+}
diff --git a/lib/Target/Mips/MipsELFDynamic.h b/lib/Target/Mips/MipsELFDynamic.h
new file mode 100644
index 0000000..118e4f9
--- /dev/null
+++ b/lib/Target/Mips/MipsELFDynamic.h
@@ -0,0 +1,41 @@
+//===- MipsELFDynamic.h ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_Mips_ELFDYNAMIC_SECTION_H
+#define MCLD_Mips_ELFDYNAMIC_SECTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/ELFDynamic.h>
+
+namespace mcld {
+
+class MipsGNULDBackend;
+
+class MipsELFDynamic : public ELFDynamic
+{
+public:
+  MipsELFDynamic(const MipsGNULDBackend& pParent);
+  ~MipsELFDynamic();
+
+private:
+  const MipsGNULDBackend& m_pParent;
+
+private:
+  void reserveTargetEntries(const ELFFileFormat& pFormat);
+  void applyTargetEntries(const ELFFileFormat& pFormat);
+
+  size_t getSymTabNum(const ELFFileFormat& pFormat) const;
+  size_t getGotSym(const ELFFileFormat& pFormat) const;
+  size_t getLocalGotNum(const ELFFileFormat& pFormat) const;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Mips/MipsELFSectLinker.cpp b/lib/Target/Mips/MipsELFSectLinker.cpp
new file mode 100644
index 0000000..aa41f36
--- /dev/null
+++ b/lib/Target/Mips/MipsELFSectLinker.cpp
@@ -0,0 +1,33 @@
+//===- MipsELFSectLinker.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsELFSectLinker.h"
+
+#include <mcld/CodeGen/SectLinkerOption.h>
+
+using namespace mcld;
+
+MipsELFSectLinker::MipsELFSectLinker(SectLinkerOption &pOption,
+                                     TargetLDBackend &pLDBackend)
+  : SectLinker(pOption,
+               pLDBackend) {
+  MCLDInfo &info = pOption.info();
+  // set up target-dependent constraints of attibutes
+  info.attrFactory().constraint().enableWholeArchive();
+  info.attrFactory().constraint().disableAsNeeded();
+  info.attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  info.attrFactory().predefined().setWholeArchive();
+  info.attrFactory().predefined().setDynamic();
+}
+
+MipsELFSectLinker::~MipsELFSectLinker()
+{
+}
diff --git a/lib/Target/Mips/MipsELFSectLinker.h b/lib/Target/Mips/MipsELFSectLinker.h
new file mode 100644
index 0000000..82bec4c
--- /dev/null
+++ b/lib/Target/Mips/MipsELFSectLinker.h
@@ -0,0 +1,34 @@
+//===- MipsELFSectLinker.h ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MIPS_ELFSECTLINKER_H
+#define MIPS_ELFSECTLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/CodeGen/SectLinker.h>
+
+namespace mcld
+{
+
+/** \class MipsELFSectLinker
+ *  \brief MipsELFSectLinker sets up the environment for linking.
+ */
+class MipsELFSectLinker : public SectLinker
+{
+public:
+  MipsELFSectLinker(SectLinkerOption &pOption,
+                    mcld::TargetLDBackend &pLDBackend);
+
+  ~MipsELFSectLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
new file mode 100644
index 0000000..f9d5bb4
--- /dev/null
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -0,0 +1,148 @@
+//===- MipsGOT.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/Support/ErrorHandling.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/Support/MemoryRegion.h>
+#include "MipsGOT.h"
+
+namespace {
+  const size_t MipsGOTEntrySize = 4;
+  const size_t MipsGOT0Num = 1;
+}
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// MipsGOT
+MipsGOT::MipsGOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+  : GOT(pSection, pSectionData, MipsGOTEntrySize),
+    m_pLocalNum(0)
+{
+  // Create GOT0 entries.
+  for (size_t i = 0; i < MipsGOT0Num; ++i) {
+    GOTEntry* entry =
+      new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
+
+    if (NULL == entry)
+      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+
+    m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
+  }
+
+  // Skip GOT0 entries.
+  iterator it = m_SectionData.begin();
+  iterator ie = m_SectionData.end();
+
+  for (size_t i = 1; i < MipsGOT0Num; ++i) {
+    if (it == ie)
+      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
+
+    ++it;
+  }
+
+  m_LocalGOTIterator = it;
+  m_GlobalGOTIterator = it;
+  m_pLocalNum = MipsGOT0Num;
+}
+
+MipsGOT::iterator MipsGOT::begin()
+{
+  return m_SectionData.getFragmentList().begin();
+}
+
+MipsGOT::iterator MipsGOT::end()
+{
+  return m_SectionData.getFragmentList().end();
+}
+
+MipsGOT::const_iterator MipsGOT::begin() const
+{
+  return m_SectionData.getFragmentList().begin();
+}
+
+MipsGOT::const_iterator MipsGOT::end() const
+{
+  return m_SectionData.getFragmentList().end();
+}
+
+uint64_t MipsGOT::emit(MemoryRegion& pRegion)
+{
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+
+  size_t entry_size = getEntrySize();
+
+  uint64_t result = 0;
+  for (iterator it = begin(), ie = end();
+       it != ie; ++it, ++buffer) {
+    GOTEntry* got = &(llvm::cast<GOTEntry>((*it)));
+    *buffer = static_cast<uint32_t>(got->getContent());
+    result += entry_size;
+  }
+  return result;
+}
+
+void MipsGOT::reserveEntry(size_t pNum)
+{
+  for (size_t i = 0; i < pNum; ++i) {
+    GOTEntry* entry =
+      new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
+
+    if (NULL == entry)
+      llvm::report_fatal_error("Allocating new GOTEntry failed");
+
+    m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
+  }
+}
+
+void MipsGOT::reserveLocalEntry()
+{
+  reserveEntry(1);
+  ++m_pLocalNum;
+
+  // Move global entries iterator forward.
+  // We need to put global GOT entries after all local ones.
+  ++m_GlobalGOTIterator;
+}
+
+void MipsGOT::reserveGlobalEntry()
+{
+  reserveEntry(1);
+}
+
+GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
+{
+  GOTEntry*& entry = m_GeneralGOTMap[&pInfo];
+
+  pExist = NULL != entry;
+
+  if (!pExist) {
+    iterator& it = pInfo.isLocal() ? m_LocalGOTIterator : m_GlobalGOTIterator;
+
+    ++it;
+
+    assert(it != m_SectionData.getFragmentList().end() &&
+           "The number of GOT Entries and ResolveInfo doesn't match");
+
+    entry = llvm::cast<GOTEntry>(&(*it));
+  }
+
+  return entry;
+}
+
+size_t MipsGOT::getTotalNum() const
+{
+  return m_SectionData.getFragmentList().size();
+}
+
+size_t MipsGOT::getLocalNum() const
+{
+  return m_pLocalNum;
+}
+
diff --git a/lib/Target/Mips/MipsGOT.h b/lib/Target/Mips/MipsGOT.h
new file mode 100644
index 0000000..dccc7ac
--- /dev/null
+++ b/lib/Target/Mips/MipsGOT.h
@@ -0,0 +1,67 @@
+//===- MipsGOT.h ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MIPS_GOT_H
+#define MCLD_MIPS_GOT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/GOT.h>
+
+namespace mcld
+{
+class LDSection;
+class MemoryRegion;
+
+/** \class MipsGOT
+ *  \brief Mips Global Offset Table.
+ */
+class MipsGOT : public GOT
+{
+private:
+  typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
+
+public:
+  typedef llvm::MCSectionData::iterator iterator;
+  typedef llvm::MCSectionData::const_iterator const_iterator;
+
+public:
+  MipsGOT(LDSection& pSection, llvm::MCSectionData& pSectionData);
+
+  iterator begin();
+  iterator end();
+
+  const_iterator begin() const;
+  const_iterator end() const;
+
+  uint64_t emit(MemoryRegion& pRegion);
+
+  void reserveLocalEntry();
+  void reserveGlobalEntry();
+
+  GOTEntry* getEntry(const ResolveInfo& pInfo, bool& pExist);
+
+  size_t getTotalNum() const;
+  size_t getLocalNum() const;
+
+private:
+  SymbolIndexMapType m_GeneralGOTMap;
+  iterator m_LocalGOTIterator;  // last local GOT entries
+  iterator m_GlobalGOTIterator; // last global GOT entries
+  size_t m_pLocalNum;
+
+private:
+  // Use reserveLocalEntry()/reserveGlobalEntry() instead of this routine.
+  void reserveEntry(size_t pNum = 1);
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
new file mode 100644
index 0000000..c7a6b23
--- /dev/null
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -0,0 +1,894 @@
+//===- MipsLDBackend.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/ADT/Triple.h>
+#include <llvm/Support/ELF.h>
+
+#include <mcld/LD/SectionMap.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Target/OutputRelocSection.h>
+
+#include "Mips.h"
+#include "MipsELFDynamic.h"
+#include "MipsLDBackend.h"
+#include "MipsRelocationFactory.h"
+
+enum {
+  // The original o32 abi.
+  E_MIPS_ABI_O32    = 0x00001000,
+  // O32 extended to work on 64 bit architectures.
+  E_MIPS_ABI_O64    = 0x00002000,
+  // EABI in 32 bit mode.
+  E_MIPS_ABI_EABI32 = 0x00003000,
+  // EABI in 64 bit mode.
+  E_MIPS_ABI_EABI64 = 0x00004000
+};
+
+namespace mcld {
+
+MipsGNULDBackend::MipsGNULDBackend()
+  : m_pRelocFactory(NULL),
+    m_pGOT(NULL),
+    m_pRelDyn(NULL),
+    m_pDynamic(NULL),
+    m_pGOTSymbol(NULL),
+    m_pGpDispSymbol(NULL)
+{
+}
+
+MipsGNULDBackend::~MipsGNULDBackend()
+{
+  if (NULL != m_pRelocFactory)
+    delete m_pRelocFactory;
+  if (NULL != m_pGOT)
+    delete m_pGOT;
+  if (NULL != m_pRelDyn)
+    delete m_pRelDyn;
+  if (NULL != m_pDynamic)
+    delete m_pDynamic;
+}
+
+bool MipsGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
+{
+  // Nothing to do because we do not support
+  // any MIPS specific sections now.
+  return true;
+}
+
+void MipsGNULDBackend::initTargetSections(MCLinker& pLinker)
+{
+  // Nothing to do because we do not support
+  // any MIPS specific sections now.
+}
+
+void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker)
+{
+  // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
+  // same name in input
+  m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
+                   "_GLOBAL_OFFSET_TABLE_",
+                   false,
+                   ResolveInfo::Object,
+                   ResolveInfo::Define,
+                   ResolveInfo::Local,
+                   0x0,  // size
+                   0x0,  // value
+                   NULL, // FragRef
+                   ResolveInfo::Hidden);
+
+  m_pGpDispSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
+                   "_gp_disp",
+                   false,
+                   ResolveInfo::Section,
+                   ResolveInfo::Define,
+                   ResolveInfo::Absolute,
+                   0x0,  // size
+                   0x0,  // value
+                   NULL, // FragRef
+                   ResolveInfo::Default);
+
+  if (NULL != m_pGpDispSymbol) {
+    m_pGpDispSymbol->resolveInfo()->setReserved(ReserveGpDisp);
+  }
+}
+
+bool MipsGNULDBackend::initRelocFactory(const MCLinker& pLinker)
+{
+  if (NULL == m_pRelocFactory) {
+    m_pRelocFactory = new MipsRelocationFactory(1024, *this);
+    m_pRelocFactory->setLayout(pLinker.getLayout());
+  }
+  return true;
+}
+
+RelocationFactory* MipsGNULDBackend::getRelocFactory()
+{
+  assert(NULL != m_pRelocFactory);
+  return m_pRelocFactory;
+}
+
+void MipsGNULDBackend::scanRelocation(Relocation& pReloc,
+                                      const LDSymbol& pInputSym,
+                                      MCLinker& pLinker,
+                                      const MCLDInfo& pLDInfo,
+                                      const Output& pOutput)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
+
+  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies
+  // that a .got section is needed.
+  if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
+    if (rsym == m_pGOTSymbol->resolveInfo()) {
+      createGOT(pLinker, pOutput);
+    }
+  }
+
+  if (rsym->isLocal())
+    scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+  else
+    scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+}
+
+uint32_t MipsGNULDBackend::machine() const
+{
+  return llvm::ELF::EM_MIPS;
+}
+
+uint8_t MipsGNULDBackend::OSABI() const
+{
+  return llvm::ELF::ELFOSABI_NONE;
+}
+
+uint8_t MipsGNULDBackend::ABIVersion() const
+{
+  return 0;
+}
+
+uint64_t MipsGNULDBackend::flags() const
+{
+  // TODO: (simon) The correct flag's set depend on command line
+  // arguments and flags from input .o files.
+  return llvm::ELF::EF_MIPS_ARCH_32R2 |
+         llvm::ELF::EF_MIPS_NOREORDER |
+         llvm::ELF::EF_MIPS_PIC |
+         llvm::ELF::EF_MIPS_CPIC |
+         E_MIPS_ABI_O32;
+}
+
+bool MipsGNULDBackend::isLittleEndian() const
+{
+  // Now we support little endian (mipsel) target only.
+  return true;
+}
+
+unsigned int MipsGNULDBackend::bitclass() const
+{
+  return 32;
+}
+
+void MipsGNULDBackend::doPreLayout(const Output& pOutput,
+                                   const MCLDInfo& pInfo,
+                                   MCLinker& pLinker)
+{
+  // when building shared object, the .got section is must.
+  if (pOutput.type() == Output::DynObj && NULL == m_pGOT) {
+      createGOT(pLinker, pOutput);
+  }
+}
+
+void MipsGNULDBackend::doPostLayout(const Output& pOutput,
+                                    const MCLDInfo& pInfo,
+                                    MCLinker& pLinker)
+{
+  // emit program headers
+  if (pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
+    emitProgramHdrs(pLinker.getLDInfo().output());
+}
+
+/// dynamic - the dynamic section of the target machine.
+/// Use co-variant return type to return its own dynamic section.
+MipsELFDynamic& MipsGNULDBackend::dynamic()
+{
+  if (NULL == m_pDynamic)
+    m_pDynamic = new MipsELFDynamic(*this);
+
+  return *m_pDynamic;
+}
+
+/// dynamic - the dynamic section of the target machine.
+/// Use co-variant return type to return its own dynamic section.
+const MipsELFDynamic& MipsGNULDBackend::dynamic() const
+{
+  assert( NULL != m_pDynamic);
+  return *m_pDynamic;
+}
+
+uint64_t MipsGNULDBackend::emitSectionData(const Output& pOutput,
+                                           const LDSection& pSection,
+                                           const MCLDInfo& pInfo,
+                                           MemoryRegion& pRegion) const
+{
+  assert(pRegion.size() && "Size of MemoryRegion is zero!");
+
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  if (&pSection == &(file_format->getGOT())) {
+    assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
+    uint64_t result = m_pGOT->emit(pRegion);
+    return result;
+  }
+
+  llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
+                           pSection.name() +
+                           llvm::Twine("'.\n"));
+  return 0;
+}
+/// isGOTSymbol - return true if the symbol is the GOT entry.
+bool MipsGNULDBackend::isGOTSymbol(const LDSymbol& pSymbol) const
+{
+  return std::find(m_LocalGOTSyms.begin(),
+                   m_LocalGOTSyms.end(), &pSymbol) != m_LocalGOTSyms.end() ||
+         std::find(m_GlobalGOTSyms.begin(),
+                   m_GlobalGOTSyms.end(), &pSymbol) != m_GlobalGOTSyms.end();
+}
+
+/// emitDynamicSymbol - emit dynamic symbol.
+void MipsGNULDBackend::emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
+                                         Output& pOutput,
+                                         LDSymbol& pSymbol,
+                                         const Layout& pLayout,
+                                         char* strtab,
+                                         size_t strtabsize,
+                                         size_t symtabIdx)
+{
+  // maintain output's symbol and index map
+  bool sym_exist = false;
+  HashTableType::entry_type* entry = 0;
+  entry = m_pSymIndexMap->insert(&pSymbol, sym_exist);
+  entry->setValue(symtabIdx);
+
+  // FIXME: check the endian between host and target
+  // write out symbol
+  sym32.st_name  = strtabsize;
+  sym32.st_value = pSymbol.value();
+  sym32.st_size  = getSymbolSize(pSymbol);
+  sym32.st_info  = getSymbolInfo(pSymbol);
+  sym32.st_other = pSymbol.visibility();
+  sym32.st_shndx = getSymbolShndx(pSymbol, pLayout);
+  // write out string
+  strcpy((strtab + strtabsize), pSymbol.name());
+}
+
+/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
+///
+/// the size of these tables should be computed before layout
+/// layout should computes the start offset of these tables
+void MipsGNULDBackend::emitDynNamePools(Output& pOutput,
+                                        SymbolCategory& pSymbols,
+                                        const Layout& pLayout,
+                                        const MCLDInfo& pLDInfo)
+{
+  assert(pOutput.hasMemArea());
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  LDSection& symtab_sect = file_format->getDynSymTab();
+  LDSection& strtab_sect = file_format->getDynStrTab();
+  LDSection& hash_sect   = file_format->getHashTab();
+  LDSection& dyn_sect    = file_format->getDynamic();
+
+  MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
+                                                           symtab_sect.size());
+  MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
+                                                           strtab_sect.size());
+  MemoryRegion* hash_region = pOutput.memArea()->request(hash_sect.offset(),
+                                                         hash_sect.size());
+  MemoryRegion* dyn_region = pOutput.memArea()->request(dyn_sect.offset(),
+                                                        dyn_sect.size());
+  // set up symtab_region
+  llvm::ELF::Elf32_Sym* symtab32 = NULL;
+  symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
+
+  symtab32[0].st_name  = 0;
+  symtab32[0].st_value = 0;
+  symtab32[0].st_size  = 0;
+  symtab32[0].st_info  = 0;
+  symtab32[0].st_other = 0;
+  symtab32[0].st_shndx = 0;
+
+  // set up strtab_region
+  char* strtab = (char*)strtab_region->start();
+  strtab[0] = '\0';
+
+  bool sym_exist = false;
+  HashTableType::entry_type* entry = 0;
+
+  // add index 0 symbol into SymIndexMap
+  entry = m_pSymIndexMap->insert(NULL, sym_exist);
+  entry->setValue(0);
+
+  size_t symtabIdx = 1;
+  size_t strtabsize = 1;
+
+  // emit of .dynsym, and .dynstr except GOT entries
+  for (SymbolCategory::iterator symbol = pSymbols.begin(),
+       sym_end = pSymbols.end(); symbol != sym_end; ++symbol) {
+    if (!isDynamicSymbol(**symbol, pOutput))
+      continue;
+
+    if (isGOTSymbol(**symbol))
+      continue;
+
+    emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
+                      strtabsize, symtabIdx);
+
+    // sum up counters
+    ++symtabIdx;
+    strtabsize += (*symbol)->nameSize() + 1;
+  }
+
+  // emit global GOT
+  for (std::vector<LDSymbol*>::const_iterator symbol = m_GlobalGOTSyms.begin(),
+       symbol_end = m_GlobalGOTSyms.end();
+       symbol != symbol_end; ++symbol) {
+
+    emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
+                      strtabsize, symtabIdx);
+
+    // sum up counters
+    ++symtabIdx;
+    strtabsize += (*symbol)->nameSize() + 1;
+  }
+
+  // emit DT_NEED
+  // add DT_NEED strings into .dynstr
+  // Rules:
+  //   1. ignore --no-add-needed
+  //   2. force count in --no-as-needed
+  //   3. judge --as-needed
+  ELFDynamic::iterator dt_need = dynamic().needBegin();
+  InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
+  for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
+    if (Input::DynObj == (*input)->type()) {
+      // --add-needed
+      if ((*input)->attribute()->isAddNeeded()) {
+        // --no-as-needed
+        if (!(*input)->attribute()->isAsNeeded()) {
+          strcpy((strtab + strtabsize), (*input)->name().c_str());
+          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+          strtabsize += (*input)->name().size() + 1;
+          ++dt_need;
+        }
+        // --as-needed
+        else if ((*input)->isNeeded()) {
+          strcpy((strtab + strtabsize), (*input)->name().c_str());
+          (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+          strtabsize += (*input)->name().size() + 1;
+          ++dt_need;
+        }
+      }
+    }
+  } // for
+
+  // emit soname
+  // initialize value of ELF .dynamic section
+  dynamic().applySoname(strtabsize);
+  dynamic().applyEntries(pLDInfo, *file_format);
+  dynamic().emit(dyn_sect, *dyn_region);
+
+  strcpy((strtab + strtabsize), pOutput.name().c_str());
+  strtabsize += pOutput.name().size() + 1;
+
+  // emit hash table
+  // FIXME: this verion only emit SVR4 hash section.
+  //        Please add GNU new hash section
+
+  // both 32 and 64 bits hash table use 32-bit entry
+  // set up hash_region
+  uint32_t* word_array = (uint32_t*)hash_region->start();
+  uint32_t& nbucket = word_array[0];
+  uint32_t& nchain  = word_array[1];
+
+  nbucket = getHashBucketCount(symtabIdx, false);
+  nchain  = symtabIdx;
+
+  uint32_t* bucket = (word_array + 2);
+  uint32_t* chain  = (bucket + nbucket);
+
+  // initialize bucket
+  bzero((void*)bucket, nbucket);
+
+  StringHash<ELF> hash_func;
+
+  for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) {
+    llvm::StringRef name(strtab + symtab32[sym_idx].st_name);
+    size_t bucket_pos = hash_func(name) % nbucket;
+    chain[sym_idx] = bucket[bucket_pos];
+    bucket[bucket_pos] = sym_idx;
+  }
+
+}
+
+MipsGOT& MipsGNULDBackend::getGOT()
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
+
+const MipsGOT& MipsGNULDBackend::getGOT() const
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
+
+OutputRelocSection& MipsGNULDBackend::getRelDyn()
+{
+  assert(NULL != m_pRelDyn);
+  return *m_pRelDyn;
+}
+
+const OutputRelocSection& MipsGNULDBackend::getRelDyn() const
+{
+  assert(NULL != m_pRelDyn);
+  return *m_pRelDyn;
+}
+
+unsigned int
+MipsGNULDBackend::getTargetSectionOrder(const Output& pOutput,
+                                        const LDSection& pSectHdr) const
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  if (&pSectHdr == &file_format->getGOT())
+    return SHO_DATA;
+
+  return SHO_UNDEFINED;
+}
+
+/// finalizeSymbol - finalize the symbol value
+/// If the symbol's reserved field is not zero, MCLinker will call back this
+/// function to ask the final value of the symbol
+bool MipsGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+{
+  if (&pSymbol == m_pGpDispSymbol) {
+    m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
+    return true;
+  }
+  return false;
+}
+
+/// allocateCommonSymbols - allocate common symbols in the corresponding
+/// sections.
+/// @refer Google gold linker: common.cc: 214
+/// FIXME: Mips needs to allocate small common symbol
+bool
+MipsGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
+{
+  // SymbolCategory contains all symbols that must emit to the output files.
+  // We are not like Google gold linker, we don't remember symbols before symbol
+  // resolution. All symbols in SymbolCategory are already resolved. Therefore, we
+  // don't need to care about some symbols may be changed its category due to symbol
+  // resolution.
+  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
+
+  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
+    return true;
+
+  // addralign := max value of all common symbols
+  uint64_t addralign = 0x0;
+
+  // Due to the visibility, some common symbols may be forcefully local.
+  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
+  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
+    if (ResolveInfo::Common == (*com_sym)->desc()) {
+      if ((*com_sym)->value() > addralign)
+        addralign = (*com_sym)->value();
+    }
+  }
+
+  // global common symbols.
+  com_end = symbol_list.commonEnd();
+  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
+    if ((*com_sym)->value() > addralign)
+      addralign = (*com_sym)->value();
+  }
+
+  // FIXME: If the order of common symbols is defined, then sort common symbols
+  // com_sym = symbol_list.commonBegin();
+  // std::sort(com_sym, com_end, some kind of order);
+
+  // get or create corresponding BSS LDSection
+  LDSection* bss_sect_hdr = NULL;
+  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
+                                   ".tbss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+  }
+  else {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+  }
+
+  // get or create corresponding BSS MCSectionData
+  assert(NULL != bss_sect_hdr);
+  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
+
+  // allocate all common symbols
+  uint64_t offset = bss_sect_hdr->size();
+
+  // allocate all local common symbols
+  com_end = symbol_list.localEnd();
+  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
+    if (ResolveInfo::Common == (*com_sym)->desc()) {
+      alignAddress(offset, (*com_sym)->value());
+      // We have to reset the description of the symbol here. When doing
+      // incremental linking, the output relocatable object may have common
+      // symbols. Therefore, we can not treat common symbols as normal symbols
+      // when emitting the regular name pools. We must change the symbols'
+      // description here.
+      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section);
+      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+      offset += (*com_sym)->size();
+    }
+  }
+
+  // allocate all global common symbols
+  com_end = symbol_list.commonEnd();
+  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
+    alignAddress(offset, (*com_sym)->value());
+
+    // We have to reset the description of the symbol here. When doing
+    // incremental linking, the output relocatable object may have common
+    // symbols. Therefore, we can not treat common symbols as normal symbols
+    // when emitting the regular name pools. We must change the symbols'
+    // description here.
+    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section);
+    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+    offset += (*com_sym)->size();
+  }
+
+  bss_sect_hdr->setSize(offset);
+  symbol_list.changeCommonsToGlobal();
+  return true;
+}
+
+void MipsGNULDBackend::updateAddend(Relocation& pReloc,
+                                   const LDSymbol& pInputSym,
+                                   const Layout& pLayout) const
+{
+  // Update value keep in addend if we meet a section symbol
+  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+    pReloc.setAddend(pLayout.getOutputOffset(
+                     *pInputSym.fragRef()) + pReloc.addend());
+  }
+}
+
+void MipsGNULDBackend::scanLocalReloc(Relocation& pReloc,
+                                      const LDSymbol& pInputSym,
+                                      MCLinker& pLinker,
+                                      const MCLDInfo& pLDInfo,
+                                      const Output& pOutput)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  updateAddend(pReloc, pInputSym, pLinker.getLayout());
+
+  switch (pReloc.type()){
+    case llvm::ELF::R_MIPS_NONE:
+    case llvm::ELF::R_MIPS_16:
+      break;
+    case llvm::ELF::R_MIPS_32:
+      if (Output::DynObj == pOutput.type()) {
+        // TODO: (simon) The gold linker does not create an entry in .rel.dyn
+        // section if the symbol section flags contains SHF_EXECINSTR.
+        // 1. Find the reason of this condition.
+        // 2. Check this condition here.
+        if (NULL == m_pRelDyn)
+          createRelDyn(pLinker, pOutput);
+
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+      }
+      break;
+    case llvm::ELF::R_MIPS_REL32:
+    case llvm::ELF::R_MIPS_26:
+    case llvm::ELF::R_MIPS_HI16:
+    case llvm::ELF::R_MIPS_LO16:
+    case llvm::ELF::R_MIPS_PC16:
+    case llvm::ELF::R_MIPS_SHIFT5:
+    case llvm::ELF::R_MIPS_SHIFT6:
+    case llvm::ELF::R_MIPS_64:
+    case llvm::ELF::R_MIPS_GOT_PAGE:
+    case llvm::ELF::R_MIPS_GOT_OFST:
+    case llvm::ELF::R_MIPS_SUB:
+    case llvm::ELF::R_MIPS_INSERT_A:
+    case llvm::ELF::R_MIPS_INSERT_B:
+    case llvm::ELF::R_MIPS_DELETE:
+    case llvm::ELF::R_MIPS_HIGHER:
+    case llvm::ELF::R_MIPS_HIGHEST:
+    case llvm::ELF::R_MIPS_SCN_DISP:
+    case llvm::ELF::R_MIPS_REL16:
+    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
+    case llvm::ELF::R_MIPS_PJUMP:
+    case llvm::ELF::R_MIPS_RELGOT:
+    case llvm::ELF::R_MIPS_JALR:
+    case llvm::ELF::R_MIPS_GLOB_DAT:
+    case llvm::ELF::R_MIPS_COPY:
+    case llvm::ELF::R_MIPS_JUMP_SLOT:
+      break;
+    case llvm::ELF::R_MIPS_GOT16:
+    case llvm::ELF::R_MIPS_CALL16:
+      if (NULL == m_pGOT)
+        createGOT(pLinker, pOutput);
+
+      if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
+        m_pGOT->reserveLocalEntry();
+        rsym->setReserved(rsym->reserved() | ReserveGot);
+        m_LocalGOTSyms.push_back(rsym->outSymbol());
+      }
+      break;
+    case llvm::ELF::R_MIPS_GPREL32:
+    case llvm::ELF::R_MIPS_GPREL16:
+    case llvm::ELF::R_MIPS_LITERAL:
+      break;
+    case llvm::ELF::R_MIPS_GOT_DISP:
+    case llvm::ELF::R_MIPS_GOT_HI16:
+    case llvm::ELF::R_MIPS_CALL_HI16:
+    case llvm::ELF::R_MIPS_GOT_LO16:
+    case llvm::ELF::R_MIPS_CALL_LO16:
+      break;
+    case llvm::ELF::R_MIPS_TLS_DTPMOD32:
+    case llvm::ELF::R_MIPS_TLS_DTPREL32:
+    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
+    case llvm::ELF::R_MIPS_TLS_DTPREL64:
+    case llvm::ELF::R_MIPS_TLS_GD:
+    case llvm::ELF::R_MIPS_TLS_LDM:
+    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
+    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
+    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
+    case llvm::ELF::R_MIPS_TLS_TPREL32:
+    case llvm::ELF::R_MIPS_TLS_TPREL64:
+    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
+    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
+      break;
+    default:
+      llvm::report_fatal_error(llvm::Twine("Unknown relocation ") +
+                               llvm::Twine(pReloc.type()) +
+                               llvm::Twine("for the local symbol `") +
+                               pReloc.symInfo()->name() +
+                               llvm::Twine("'."));
+  }
+}
+
+void MipsGNULDBackend::scanGlobalReloc(Relocation& pReloc,
+                                       const LDSymbol& pInputSym,
+                                       MCLinker& pLinker,
+                                       const MCLDInfo& pLDInfo,
+                                       const Output& pOutput)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  switch (pReloc.type()){
+    case llvm::ELF::R_MIPS_NONE:
+    case llvm::ELF::R_MIPS_INSERT_A:
+    case llvm::ELF::R_MIPS_INSERT_B:
+    case llvm::ELF::R_MIPS_DELETE:
+    case llvm::ELF::R_MIPS_TLS_DTPMOD64:
+    case llvm::ELF::R_MIPS_TLS_DTPREL64:
+    case llvm::ELF::R_MIPS_REL16:
+    case llvm::ELF::R_MIPS_ADD_IMMEDIATE:
+    case llvm::ELF::R_MIPS_PJUMP:
+    case llvm::ELF::R_MIPS_RELGOT:
+    case llvm::ELF::R_MIPS_TLS_TPREL64:
+      break;
+    case llvm::ELF::R_MIPS_32:
+    case llvm::ELF::R_MIPS_64:
+    case llvm::ELF::R_MIPS_HI16:
+    case llvm::ELF::R_MIPS_LO16:
+      if (isSymbolNeedsDynRel(*rsym, pOutput)) {
+        if (NULL == m_pRelDyn)
+          createRelDyn(pLinker, pOutput);
+
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+      }
+      break;
+    case llvm::ELF::R_MIPS_GOT16:
+    case llvm::ELF::R_MIPS_CALL16:
+    case llvm::ELF::R_MIPS_GOT_DISP:
+    case llvm::ELF::R_MIPS_GOT_HI16:
+    case llvm::ELF::R_MIPS_CALL_HI16:
+    case llvm::ELF::R_MIPS_GOT_LO16:
+    case llvm::ELF::R_MIPS_CALL_LO16:
+    case llvm::ELF::R_MIPS_GOT_PAGE:
+    case llvm::ELF::R_MIPS_GOT_OFST:
+      if (NULL == m_pGOT)
+        createGOT(pLinker, pOutput);
+
+      if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
+        m_pGOT->reserveGlobalEntry();
+        rsym->setReserved(rsym->reserved() | ReserveGot);
+        m_GlobalGOTSyms.push_back(rsym->outSymbol());
+      }
+      break;
+    case llvm::ELF::R_MIPS_LITERAL:
+    case llvm::ELF::R_MIPS_GPREL32:
+      llvm::report_fatal_error(llvm::Twine("Relocation ") +
+                               llvm::Twine(pReloc.type()) +
+                               llvm::Twine(" is not defined for the "
+                                           "global symbol `") +
+                               pReloc.symInfo()->name() +
+                               llvm::Twine("'."));
+      break;
+    case llvm::ELF::R_MIPS_GPREL16:
+      break;
+    case llvm::ELF::R_MIPS_26:
+    case llvm::ELF::R_MIPS_PC16:
+      break;
+    case llvm::ELF::R_MIPS_16:
+    case llvm::ELF::R_MIPS_SHIFT5:
+    case llvm::ELF::R_MIPS_SHIFT6:
+    case llvm::ELF::R_MIPS_SUB:
+    case llvm::ELF::R_MIPS_HIGHER:
+    case llvm::ELF::R_MIPS_HIGHEST:
+    case llvm::ELF::R_MIPS_SCN_DISP:
+      break;
+    case llvm::ELF::R_MIPS_TLS_DTPREL32:
+    case llvm::ELF::R_MIPS_TLS_GD:
+    case llvm::ELF::R_MIPS_TLS_LDM:
+    case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
+    case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
+    case llvm::ELF::R_MIPS_TLS_GOTTPREL:
+    case llvm::ELF::R_MIPS_TLS_TPREL32:
+    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
+    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
+      break;
+    case llvm::ELF::R_MIPS_REL32:
+      break;
+    case llvm::ELF::R_MIPS_JALR:
+      break;
+    case llvm::ELF::R_MIPS_COPY:
+    case llvm::ELF::R_MIPS_GLOB_DAT:
+    case llvm::ELF::R_MIPS_JUMP_SLOT:
+      llvm::report_fatal_error(llvm::Twine("Relocation ") +
+                               llvm::Twine(pReloc.type()) +
+                               llvm::Twine("for the global symbol `") +
+                               pReloc.symInfo()->name() +
+                               llvm::Twine("' should only be seen "
+                                           "by the dynamic linker"));
+      break;
+    default:
+      llvm::report_fatal_error(llvm::Twine("Unknown relocation ") +
+                               llvm::Twine(pReloc.type()) +
+                               llvm::Twine("for the global symbol `") +
+                               pReloc.symInfo()->name() +
+                               llvm::Twine("'."));
+  }
+}
+
+bool MipsGNULDBackend::isSymbolNeedsPLT(ResolveInfo& pSym,
+                                        const Output& pOutput) const
+{
+  return (Output::DynObj == pOutput.type() &&
+         ResolveInfo::Function == pSym.type() &&
+         (pSym.isDyn() || pSym.isUndef()));
+}
+
+bool MipsGNULDBackend::isSymbolNeedsDynRel(ResolveInfo& pSym,
+                                           const Output& pOutput) const
+{
+  if(pSym.isUndef() && Output::Exec == pOutput.type())
+    return false;
+  if(pSym.isAbsolute())
+    return false;
+  if(Output::DynObj == pOutput.type())
+    return true;
+  if(pSym.isDyn() || pSym.isUndef())
+    return true;
+
+  return false;
+}
+
+void MipsGNULDBackend::createGOT(MCLinker& pLinker, const Output& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  LDSection& got = file_format->getGOT();
+  m_pGOT = new MipsGOT(got, pLinker.getOrCreateSectData(got));
+
+  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
+  if( m_pGOTSymbol != NULL ) {
+    pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
+                     "_GLOBAL_OFFSET_TABLE_",
+                     false,
+                     ResolveInfo::Object,
+                     ResolveInfo::Define,
+                     ResolveInfo::Local,
+                     0x0, // size
+                     0x0, // value
+                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     ResolveInfo::Hidden);
+  }
+  else {
+    m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+                     "_GLOBAL_OFFSET_TABLE_",
+                     false,
+                     ResolveInfo::Object,
+                     ResolveInfo::Define,
+                     ResolveInfo::Local,
+                     0x0, // size
+                     0x0, // value
+                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     ResolveInfo::Hidden);
+  }
+}
+
+void MipsGNULDBackend::createRelDyn(MCLinker& pLinker, const Output& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  // get .rel.dyn LDSection and create MCSectionData
+  LDSection& reldyn = file_format->getRelDyn();
+  // create MCSectionData and ARMRelDynSection
+  m_pRelDyn = new OutputRelocSection(reldyn,
+                                     pLinker.getOrCreateSectData(reldyn),
+                                     8);
+}
+
+ELFFileFormat* MipsGNULDBackend::getOutputFormat(const Output& pOutput) const
+{
+  switch (pOutput.type()) {
+    case Output::DynObj:
+      return getDynObjFileFormat();
+    case Output::Exec:
+      return getExecFileFormat();
+    case Output::Object:
+      return NULL;
+    default:
+      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
+                               llvm::Twine(pOutput.type()));
+      return NULL;
+  }
+}
+
+//===----------------------------------------------------------------------===//
+/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
+///
+static TargetLDBackend* createMipsLDBackend(const llvm::Target& pTarget,
+                                            const std::string& pTriple)
+{
+  llvm::Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker is not supported yet");
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker is not supported yet");
+  }
+  return new MipsGNULDBackend();
+}
+
+} // namespace of mcld
+
+//=============================
+// Force static initialization.
+extern "C" void LLVMInitializeMipsLDBackend() {
+  // Register the linker backend
+  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
+                                                mcld::createMipsLDBackend);
+}
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
new file mode 100644
index 0000000..cd9e3cd
--- /dev/null
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -0,0 +1,200 @@
+//===- MipsLDBackend.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MIPS_LDBACKEND_H
+#define MIPS_LDBACKEND_H
+#include "mcld/Target/GNULDBackend.h"
+#include "MipsELFDynamic.h"
+#include "MipsGOT.h"
+
+namespace mcld {
+
+class MCLinker;
+class OutputRelocSection;
+class SectionMap;
+
+//===----------------------------------------------------------------------===//
+/// MipsGNULDBackend - linker backend of Mips target of GNU ELF format
+///
+class MipsGNULDBackend : public GNULDBackend
+{
+public:
+  enum ReservedEntryType {
+    None          = 0,  // no reserved entry
+    ReserveRel    = 1,  // reserve a dynamic relocation entry
+    ReserveGot    = 2,  // reserve a GOT entry
+    ReserveGpDisp = 8   // reserve _gp_disp symbol
+  };
+
+public:
+  MipsGNULDBackend();
+  ~MipsGNULDBackend();
+
+public:
+  /// initTargetSectionMap - initialize target dependent section mapping.
+  bool initTargetSectionMap(SectionMap& pSectionMap);
+
+  /// initTargetSections - initialize target dependent sections in output
+  void initTargetSections(MCLinker& pLinker);
+
+  /// initTargetSymbols - initialize target dependent symbols in output.
+  void initTargetSymbols(MCLinker& pLinker);
+
+  /// initRelocFactory - create and initialize RelocationFactory.
+  bool initRelocFactory(const MCLinker& pLinker);
+
+  /// getRelocFactory - return relocation factory.
+  RelocationFactory* getRelocFactory();
+
+  /// scanRelocation - determine the empty entries are needed or not and
+  /// create the empty entries if needed.
+  /// For Mips, the GOT, GP, and dynamic relocation entries are check to create.
+  void scanRelocation(Relocation& pReloc,
+                      const LDSymbol& pInputSym,
+                      MCLinker& pLinker,
+                      const MCLDInfo& pLDInfo,
+                      const Output& pOutput);
+
+  uint32_t machine() const;
+
+  /// OSABI - the value of e_ident[EI_OSABI]
+  uint8_t OSABI() const;
+
+  /// ABIVersion - the value of e_ident[EI_ABIVRESION]
+  uint8_t ABIVersion() const;
+
+  /// flags - the value of ElfXX_Ehdr::e_flags
+  uint64_t flags() const;
+
+  bool isLittleEndian() const;
+
+  unsigned int bitclass() const;
+
+  /// preLayout - Backend can do any needed modification before layout
+  void doPreLayout(const Output& pOutput,
+                   const MCLDInfo& pInfo,
+                   MCLinker& pLinker);
+
+  /// postLayout -Backend can do any needed modification after layout
+  void doPostLayout(const Output& pOutput,
+                    const MCLDInfo& pInfo,
+                    MCLinker& pLinker);
+
+  /// dynamic - the dynamic section of the target machine.
+  /// Use co-variant return type to return its own dynamic section.
+  MipsELFDynamic& dynamic();
+
+  /// dynamic - the dynamic section of the target machine.
+  /// Use co-variant return type to return its own dynamic section.
+  const MipsELFDynamic& dynamic() const;
+
+  /// emitSectionData - write out the section data into the memory region.
+  /// When writers get a LDSection whose kind is LDFileFormat::Target, writers
+  /// call back target backend to emit the data.
+  ///
+  /// Backends handle the target-special tables (plt, gp,...) by themselves.
+  /// Backend can put the data of the tables in MCSectionData directly
+  ///  - LDSection.getSectionData can get the section data.
+  /// Or, backend can put the data into special data structure
+  ///  - backend can maintain its own map<LDSection, table> to get the table
+  /// from given LDSection.
+  ///
+  /// @param pOutput - the output file
+  /// @param pSection - the given LDSection
+  /// @param pInfo - all options in the command line.
+  /// @param pRegion - the region to write out data
+  /// @return the size of the table in the file.
+  uint64_t emitSectionData(const Output& pOutput,
+                           const LDSection& pSection,
+                           const MCLDInfo& pInfo,
+                           MemoryRegion& pRegion) const;
+
+  /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
+  virtual void emitDynNamePools(Output& pOutput,
+                                SymbolCategory& pSymbols,
+                                const Layout& pLayout,
+                                const MCLDInfo& pLDInfo);
+
+  MipsGOT& getGOT();
+  const MipsGOT& getGOT() const;
+
+  OutputRelocSection& getRelDyn();
+  const OutputRelocSection& getRelDyn() const;
+
+  /// getTargetSectionOrder - compute the layout order of ARM target sections
+  unsigned int getTargetSectionOrder(const Output& pOutput,
+                                     const LDSection& pSectHdr) const;
+
+  /// finalizeSymbol - finalize the symbol value
+  /// If the symbol's reserved field is not zero, MCLinker will call back this
+  /// function to ask the final value of the symbol
+  bool finalizeSymbol(LDSymbol& pSymbol) const;
+
+  /// allocateCommonSymbols - allocate common symbols in the corresponding
+  /// sections.
+  bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
+
+private:
+  void scanLocalReloc(Relocation& pReloc,
+                      const LDSymbol& pInputSym,
+                      MCLinker& pLinker,
+                      const MCLDInfo& pLDInfo,
+                      const Output& pOutput);
+
+  void scanGlobalReloc(Relocation& pReloc,
+                      const LDSymbol& pInputSym,
+                      MCLinker& pLinker,
+                      const MCLDInfo& pLDInfo,
+                      const Output& pOutput);
+
+  bool isSymbolNeedsPLT(ResolveInfo& pSym, const Output& pOutput) const;
+  bool isSymbolNeedsDynRel(ResolveInfo& pSym, const Output& pOutput) const;
+
+  void createGOT(MCLinker& pLinker, const Output& pOutput);
+  void createRelDyn(MCLinker& pLinker, const Output& pOutput);
+
+  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
+
+  /// updateAddend - update addend value of the relocation if the
+  /// the target symbol is a section symbol. Addend is the offset
+  /// in the section. This value should be updated after section
+  /// merged.
+  void updateAddend(Relocation& pReloc,
+                    const LDSymbol& pInputSym,
+                    const Layout& pLayout) const;
+
+private:
+  RelocationFactory* m_pRelocFactory;
+
+  MipsGOT* m_pGOT;                      // .got
+  OutputRelocSection* m_pRelDyn;        // .rel.dyn
+
+  MipsELFDynamic* m_pDynamic;
+  LDSymbol* m_pGOTSymbol;
+  LDSymbol* m_pGpDispSymbol;
+
+  std::vector<LDSymbol*> m_LocalGOTSyms;
+  std::vector<LDSymbol*> m_GlobalGOTSyms;
+
+private:
+  /// isGOTSymbol - return true if the symbol is the GOT entry.
+  bool isGOTSymbol(const LDSymbol& pSymbol) const;
+  /// emitDynamicSymbol - emit dynamic symbol.
+  void emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
+                         Output& pOutput, 
+                         LDSymbol& pSymbol,
+                         const Layout& pLayout,
+                         char* strtab,
+                         size_t strtabsize,
+                         size_t symtabIdx);
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Mips/MipsRelocationFactory.cpp b/lib/Target/Mips/MipsRelocationFactory.cpp
new file mode 100644
index 0000000..e3a7793
--- /dev/null
+++ b/lib/Target/Mips/MipsRelocationFactory.cpp
@@ -0,0 +1,363 @@
+//===- MipsRelocationFactory.cpp  -----------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <mcld/LD/Layout.h>
+#include <mcld/Target/OutputRelocSection.h>
+
+#include "MipsRelocationFactory.h"
+#include "MipsRelocationFunctions.h"
+
+using namespace mcld;
+
+DECL_MIPS_APPLY_RELOC_FUNCS
+
+//==========================
+// MipsRelocationFactory
+MipsRelocationFactory::MipsRelocationFactory(size_t pNum,
+                                             MipsGNULDBackend& pParent)
+  : RelocationFactory(pNum),
+    m_Target(pParent),
+    m_AHL(0)
+{
+}
+
+void 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])) {
+    llvm::report_fatal_error(llvm::Twine("Unknown relocation type. "
+                                         "To symbol `") +
+                             pRelocation.symInfo()->name() +
+                             llvm::Twine("'."));
+  }
+
+  // apply the relocation
+  Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
+
+  // check result
+  if (Overflow == result) {
+    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
+                             llvm::Twine(apply_functions[type].name) +
+                             llvm::Twine("' causes overflow. on symbol: `") +
+                             llvm::Twine(pRelocation.symInfo()->name()) +
+                             llvm::Twine("'."));
+    return;
+  }
+
+  if (BadReloc == result) {
+    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
+                             llvm::Twine(apply_functions[type].name) +
+                             llvm::Twine("' encounters unexpected opcode. "
+                                         "on symbol: `") +
+                             llvm::Twine(pRelocation.symInfo()->name()) +
+                             llvm::Twine("'."));
+    return;
+  }
+}
+
+//=========================================//
+// Relocation helper function              //
+//=========================================//
+
+static const char * const GP_DISP_NAME = "_gp_disp";
+
+// Get an relocation entry in .rel.dyn and set its type to R_MIPS_REL32,
+// its FragmentRef to pReloc->targetFrag() and its ResolveInfo
+// to pReloc->symInfo()
+static
+void helper_SetRelDynEntry(Relocation& pReloc,
+                   MipsRelocationFactory& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  MipsGNULDBackend& ld_backend = pParent.getTarget();
+
+  bool exist;
+  Relocation& rel_entry =
+    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
+
+  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
+  rel_entry.targetRef() = pReloc.targetRef();
+  rel_entry.setSymInfo(0);
+}
+
+// Find next R_MIPS_LO16 relocation paired to pReloc.
+static
+Relocation* helper_FindLo16Reloc(Relocation& pReloc)
+{
+  Relocation* reloc = static_cast<Relocation*>(pReloc.getNextNode());
+  while (NULL != reloc)
+  {
+    if (llvm::ELF::R_MIPS_LO16 == reloc->type() &&
+        reloc->symInfo() == pReloc.symInfo())
+      return reloc;
+
+    reloc = static_cast<Relocation*>(reloc->getNextNode());
+  }
+  return NULL;
+}
+
+// Check the symbol is _gp_disp.
+static
+bool helper_isGpDisp(const Relocation& pReloc)
+{
+  const ResolveInfo* rsym = pReloc.symInfo();
+  return 0 == strcmp(GP_DISP_NAME, rsym->name());
+}
+
+static
+RelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent)
+{
+  return pParent.getTarget().getGOT().getSection().addr() + 0x7FF0;
+}
+
+static
+GOTEntry& helper_GetGOTEntry(Relocation& pReloc,
+                             MipsRelocationFactory& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  MipsGNULDBackend& ld_backend = pParent.getTarget();
+
+  bool exist;
+  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
+
+  if (exist)
+    return got_entry;
+
+  // If we first get this GOT entry, we should initialize it.
+  if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
+    got_entry.setContent(pReloc.symValue());
+  }
+  else {
+    llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+  }
+
+  return got_entry;
+}
+
+static
+RelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc,
+                                               MipsRelocationFactory& pParent)
+{
+  GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
+  return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
+}
+
+static
+int32_t helper_CalcAHL(const Relocation& pHiReloc, const Relocation& pLoReloc)
+{
+  assert((pHiReloc.type() == llvm::ELF::R_MIPS_HI16 ||
+          pHiReloc.type() == llvm::ELF::R_MIPS_GOT16) &&
+         pLoReloc.type() == llvm::ELF::R_MIPS_LO16 &&
+         "Incorrect type of relocation for AHL calculation");
+
+  // Note the addend is section symbol offset here
+  assert (pHiReloc.addend() == pLoReloc.addend());
+
+  int32_t AHI = pHiReloc.target();
+  int32_t ALO = pLoReloc.target();
+  int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + pLoReloc.addend();
+  return AHL;
+}
+
+static
+void helper_DynRel(Relocation& pReloc,
+                   MipsRelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  MipsGNULDBackend& ld_backend = pParent.getTarget();
+
+  bool exist;
+  Relocation& rel_entry =
+    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
+
+  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
+  rel_entry.targetRef() = pReloc.targetRef();
+  rel_entry.setSymInfo(rsym->isLocal() ? NULL : rsym);
+}
+
+//=========================================//
+// Relocation functions implementation     //
+//=========================================//
+
+// R_MIPS_NONE and those unsupported/deprecated relocation type
+static
+MipsRelocationFactory::Result none(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   MipsRelocationFactory& pParent)
+{
+  return MipsRelocationFactory::OK;
+}
+
+// R_MIPS_32: S + A
+static
+MipsRelocationFactory::Result abs32(Relocation& pReloc,
+                                    const MCLDInfo& pLDInfo,
+                                    MipsRelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
+    helper_DynRel(pReloc, pParent);
+  }
+
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  RelocationFactory::DWord S = pReloc.symValue();
+
+  pReloc.target() |= (S + A);
+
+  return MipsRelocationFactory::OK;
+}
+
+// R_MIPS_HI16:
+//   local/external: ((AHL + S) - (short)(AHL + S)) >> 16
+//   _gp_disp      : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
+static
+MipsRelocationFactory::Result hi16(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   MipsRelocationFactory& pParent)
+{
+  Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
+  assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16");
+
+  int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
+  int32_t res = 0;
+
+  pParent.setAHL(AHL);
+
+  if (helper_isGpDisp(pReloc)) {
+    int32_t P = pReloc.place(pParent.getLayout());
+    int32_t GP = helper_GetGP(pParent);
+    res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
+  }
+  else {
+    int32_t S = pReloc.symValue();
+    res = ((AHL + S) - (int16_t)(AHL + S)) >> 16;
+  }
+
+  pReloc.target() &= 0xFFFF0000;
+  pReloc.target() |= (res & 0xFFFF);
+
+  return MipsRelocationFactory::OK;
+}
+
+// R_MIPS_LO16:
+//   local/external: AHL + S
+//   _gp_disp      : AHL + GP - P + 4
+static
+MipsRelocationFactory::Result lo16(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   MipsRelocationFactory& pParent)
+{
+  int32_t AHL = pParent.getAHL();
+  int32_t res = 0;
+
+  if (helper_isGpDisp(pReloc)) {
+    int32_t P = pReloc.place(pParent.getLayout());
+    int32_t GP = helper_GetGP(pParent);
+    res = AHL + GP - P + 4;
+  }
+  else {
+    int32_t S = pReloc.symValue();
+    res = AHL + S;
+  }
+
+  pReloc.target() &= 0xFFFF0000;
+  pReloc.target() |= (res & 0xFFFF);
+
+  return MipsRelocationFactory::OK;
+}
+
+// R_MIPS_GOT16:
+//   local   : G (calculate AHL and put high 16 bit to GOT)
+//   external: G
+static
+MipsRelocationFactory::Result got16(Relocation& pReloc,
+                                    const MCLDInfo& pLDInfo,
+                                    MipsRelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  if (rsym->isLocal()) {
+    Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
+    assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_GOT16");
+
+    int32_t AHL = helper_CalcAHL(pReloc, *lo_reloc);
+    int32_t S = pReloc.symValue();
+
+    pParent.setAHL(AHL);
+
+    GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
+
+    int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
+    got_entry.setContent(res);
+  }
+
+  RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
+
+  pReloc.target() &= 0xFFFF0000;
+  pReloc.target() |= (G & 0xFFFF);
+
+  return MipsRelocationFactory::OK;
+}
+
+// R_MIPS_CALL16: G
+static
+MipsRelocationFactory::Result call16(Relocation& pReloc,
+                                     const MCLDInfo& pLDInfo,
+                                     MipsRelocationFactory& pParent)
+{
+  RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
+
+  pReloc.target() &= 0xFFFF0000;
+  pReloc.target() |= (G & 0xFFFF);
+
+  return MipsRelocationFactory::OK;
+}
+
+// R_MIPS_GPREL32: A + S + GP0 - GP
+static
+MipsRelocationFactory::Result gprel32(Relocation& pReloc,
+                                      const MCLDInfo& pLDInfo,
+                                      MipsRelocationFactory& pParent)
+{
+  int32_t A = pReloc.target();
+  int32_t S = pReloc.symValue();
+  int32_t GP = helper_GetGP(pParent);
+
+  // llvm does not emits SHT_MIPS_REGINFO section.
+  // Assume that GP0 is zero.
+  pReloc.target() = (A + S - GP) & 0xFFFFFFFF;
+
+  return MipsRelocationFactory::OK;
+}
diff --git a/lib/Target/Mips/MipsRelocationFactory.h b/lib/Target/Mips/MipsRelocationFactory.h
new file mode 100644
index 0000000..8f3bf93
--- /dev/null
+++ b/lib/Target/Mips/MipsRelocationFactory.h
@@ -0,0 +1,64 @@
+//===- MipsRelocationFactory.h --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MIPS_RELOCATION_FACTORY_H
+#define MIPS_RELOCATION_FACTORY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/Support/GCFactory.h>
+#include "MipsLDBackend.h"
+
+namespace mcld
+{
+
+/** \class MipsRelocationFactory
+ *  \brief MipsRelocationFactory creates and destroys the Mips relocations.
+ */
+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);
+
+  MipsGNULDBackend& getTarget()
+  { return m_Target; }
+
+  const MipsGNULDBackend& getTarget() const
+  { return m_Target; }
+
+  // Get last calculated AHL.
+  int32_t getAHL() const
+  { return m_AHL; }
+
+  // Set last calculated AHL.
+  void setAHL(int32_t pAHL)
+  { m_AHL = pAHL; }
+
+private:
+  MipsGNULDBackend& m_Target;
+  int32_t m_AHL;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Mips/MipsRelocationFunctions.h b/lib/Target/Mips/MipsRelocationFunctions.h
new file mode 100644
index 0000000..4b60d10
--- /dev/null
+++ b/lib/Target/Mips/MipsRelocationFunctions.h
@@ -0,0 +1,76 @@
+//===- MipsRelocationFunction.h -------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DECL_MIPS_APPLY_RELOC_FUNC(Name) \
+static MipsRelocationFactory::Result Name(Relocation& pEntry, \
+                                          const MCLDInfo& pLDInfo, \
+                                          MipsRelocationFactory& pParent);
+
+#define DECL_MIPS_APPLY_RELOC_FUNCS \
+DECL_MIPS_APPLY_RELOC_FUNC(none) \
+DECL_MIPS_APPLY_RELOC_FUNC(abs32) \
+DECL_MIPS_APPLY_RELOC_FUNC(hi16) \
+DECL_MIPS_APPLY_RELOC_FUNC(lo16) \
+DECL_MIPS_APPLY_RELOC_FUNC(got16) \
+DECL_MIPS_APPLY_RELOC_FUNC(call16) \
+DECL_MIPS_APPLY_RELOC_FUNC(gprel32)
+
+#define DECL_MIPS_APPLY_RELOC_FUNC_PTRS \
+  { &none,     0, "R_MIPS_NONE"            }, \
+  { &none,     1, "R_MIPS_16"              }, \
+  { &abs32,    2, "R_MIPS_32"              }, \
+  { &none,     3, "R_MIPS_REL32"           }, \
+  { &none,     4, "R_MIPS_26"              }, \
+  { &hi16,     5, "R_MIPS_HI16"            }, \
+  { &lo16,     6, "R_MIPS_LO16"            }, \
+  { &none,     7, "R_MIPS_GPREL16"         }, \
+  { &none,     8, "R_MIPS_LITERAL"         }, \
+  { &got16,    9, "R_MIPS_GOT16"           }, \
+  { &none,    10, "R_MIPS_PC16"            }, \
+  { &call16,  11, "R_MIPS_CALL16"          }, \
+  { &gprel32, 12, "R_MIPS_GPREL32"         }, \
+  { &none,    13, "R_MIPS_UNUSED1"         }, \
+  { &none,    14, "R_MIPS_UNUSED2"         }, \
+  { &none,    15, "R_MIPS_UNUSED3"         }, \
+  { &none,    16, "R_MIPS_SHIFT5"          }, \
+  { &none,    17, "R_MIPS_SHIFT6"          }, \
+  { &none,    18, "R_MIPS_64"              }, \
+  { &none,    19, "R_MIPS_GOT_DISP"        }, \
+  { &none,    20, "R_MIPS_GOT_PAGE"        }, \
+  { &none,    21, "R_MIPS_GOT_OFST"        }, \
+  { &none,    22, "R_MIPS_GOT_HI16"        }, \
+  { &none,    23, "R_MIPS_GOT_LO16"        }, \
+  { &none,    24, "R_MIPS_SUB"             }, \
+  { &none,    25, "R_MIPS_INSERT_A"        }, \
+  { &none,    26, "R_MIPS_INSERT_B"        }, \
+  { &none,    27, "R_MIPS_DELETE"          }, \
+  { &none,    28, "R_MIPS_HIGHER"          }, \
+  { &none,    29, "R_MIPS_HIGHEST"         }, \
+  { &none,    30, "R_MIPS_CALL_HI16"       }, \
+  { &none,    31, "R_MIPS_CALL_LO16"       }, \
+  { &none,    32, "R_MIPS_SCN_DISP"        }, \
+  { &none,    33, "R_MIPS_REL16"           }, \
+  { &none,    34, "R_MIPS_ADD_IMMEDIATE"   }, \
+  { &none,    35, "R_MIPS_PJUMP"           }, \
+  { &none,    36, "R_MIPS_RELGOT"          }, \
+  { &none,    37, "R_MIPS_JALR"            }, \
+  { &none,    38, "R_MIPS_TLS_DTPMOD32"    }, \
+  { &none,    39, "R_MIPS_TLS_DTPREL32"    }, \
+  { &none,    40, "R_MIPS_TLS_DTPMOD64"    }, \
+  { &none,    41, "R_MIPS_TLS_DTPREL64"    }, \
+  { &none,    42, "R_MIPS_TLS_GD"          }, \
+  { &none,    43, "R_MIPS_TLS_LDM"         }, \
+  { &none,    44, "R_MIPS_TLS_DTPREL_HI16" }, \
+  { &none,    45, "R_MIPS_TLS_DTPREL_LO16" }, \
+  { &none,    46, "R_MIPS_TLS_GOTTPREL"    }, \
+  { &none,    47, "R_MIPS_TLS_TPREL32"     }, \
+  { &none,    48, "R_MIPS_TLS_TPREL64"     }, \
+  { &none,    49, "R_MIPS_TLS_TPREL_HI16"  }, \
+  { &none,    50, "R_MIPS_TLS_TPREL_LO16"  }, \
+  { &none,    51, "R_MIPS_GLOB_DAT"        }
diff --git a/lib/Target/Mips/MipsSectLinker.cpp b/lib/Target/Mips/MipsSectLinker.cpp
new file mode 100644
index 0000000..af543c9
--- /dev/null
+++ b/lib/Target/Mips/MipsSectLinker.cpp
@@ -0,0 +1,47 @@
+//===- MipsSectLinker.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include "Mips.h"
+#include "MipsAndroidSectLinker.h"
+
+using namespace mcld;
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+/// createMipsSectLinker - the help funtion to create
+/// corresponding MipsSectLinker
+///
+SectLinker* createMipsSectLinker(const std::string &pTriple,
+                                 SectLinkerOption &pOption,
+                                 mcld::TargetLDBackend &pLDBackend)
+{
+  llvm::Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+  }
+
+  // For now, use Android SectLinker directly
+  return new MipsAndroidSectLinker(pOption,
+                                   pLDBackend);
+}
+
+} // namespace of mcld
+
+//==========================
+// MipsSectLinker
+extern "C" void LLVMInitializeMipsSectLinker() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterSectLinker(TheMipselTarget,
+                                           createMipsSectLinker);
+}
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
new file mode 100644
index 0000000..0987585
--- /dev/null
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -0,0 +1,34 @@
+//===- MipsTargetMachine.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsTargetMachine.h"
+#include "mcld/Target/TargetMachine.h"
+#include "mcld/Support/TargetRegistry.h"
+#include "mcld/MC/MCLDInfo.h"
+#include "Mips.h"
+
+extern "C" void LLVMInitializeMipsLDTarget() {
+  // Register createTargetMachine function pointer to mcld::Target
+  mcld::RegisterTargetMachine<mcld::MipsBaseTargetMachine>
+        X(mcld::TheMipselTarget);
+}
+
+mcld::MipsBaseTargetMachine::MipsBaseTargetMachine(llvm::TargetMachine& pPM,
+                                                   const mcld::Target &pTarget,
+                                                   const std::string& pTriple)
+  : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
+  // arg1 - the number of total attributes
+  // arg2 - the most possible number of input files
+  m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+}
+
+mcld::MipsBaseTargetMachine::~MipsBaseTargetMachine()
+{
+  delete m_pLDInfo;
+}
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
new file mode 100644
index 0000000..e9bd5da
--- /dev/null
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -0,0 +1,38 @@
+//===- MipsTargetMachine.h ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MIPS_TARGET_MACHINE_H
+#define MIPS_TARGET_MACHINE_H
+#include "mcld/Target/TargetMachine.h"
+#include "Mips.h"
+
+namespace mcld
+{
+
+class MipsBaseTargetMachine : public LLVMTargetMachine
+{
+protected:
+  MCLDInfo *m_pLDInfo;
+
+public:
+  MipsBaseTargetMachine(llvm::TargetMachine &pTM,
+                        const mcld::Target &pTarget,
+                        const std::string &pTriple);
+
+  virtual ~MipsBaseTargetMachine();
+
+  mcld::MCLDInfo& getLDInfo()
+  { return *m_pLDInfo; }
+
+  const mcld::MCLDInfo& getLDInfo() const
+  { return *m_pLDInfo; }
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/Mips/TargetInfo/Android.mk b/lib/Target/Mips/TargetInfo/Android.mk
new file mode 100644
index 0000000..cf8ae38
--- /dev/null
+++ b/lib/Target/Mips/TargetInfo/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_mips_info_SRC_FILES := \
+  MipsTargetInfo.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_mips_info_SRC_FILES)
+LOCAL_MODULE:= libmcldMipsInfo
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifeq ($(TARGET_ARCH),mips)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_mips_info_SRC_FILES)
+LOCAL_MODULE:= libmcldMipsInfo
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
new file mode 100644
index 0000000..0889973
--- /dev/null
+++ b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
@@ -0,0 +1,21 @@
+//===- MipsTargetInfo.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "mcld/Target/TargetMachine.h"
+#include "mcld/Support/TargetRegistry.h"
+
+namespace mcld {
+
+mcld::Target TheMipselTarget;
+
+extern "C" void LLVMInitializeMipsLDTargetInfo() {
+  // register into mcld::TargetRegistry
+  mcld::RegisterTarget X(TheMipselTarget, "mipsel");
+}
+
+} // namespace of mcld