Linkloader improvement: mclinker.

Change-Id: I8805e39ccbc2ee204234fb3e71c70c906f3990bb
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h
new file mode 100644
index 0000000..a128998
--- /dev/null
+++ b/lib/Target/ARM/ARM.h
@@ -0,0 +1,24 @@
+//===- ARM.h --------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ARM_H
+#define MCLD_ARM_H
+#include <string>
+#include "mcld/Target/TargetMachine.h"
+
+namespace mcld {
+class TargetLDBackend;
+
+extern mcld::Target TheARMTarget;
+
+TargetLDBackend *createARMLDBackend(const llvm::Target&, const std::string&);
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMAndroidSectLinker.cpp b/lib/Target/ARM/ARMAndroidSectLinker.cpp
new file mode 100644
index 0000000..a704cfa
--- /dev/null
+++ b/lib/Target/ARM/ARMAndroidSectLinker.cpp
@@ -0,0 +1,35 @@
+//===- ARMAndroidSectLinker.cpp -------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMAndroidSectLinker.h"
+
+#include <mcld/CodeGen/SectLinkerOption.h>
+
+using namespace mcld;
+
+ARMAndroidSectLinker::ARMAndroidSectLinker(SectLinkerOption &pOption,
+                                           TargetLDBackend &pLDBackend)
+  : AndroidSectLinker(pOption,
+                      pLDBackend) {
+  MCLDInfo &info = pOption.info();
+  // set up target-dependent constraints of attributes
+  info.attrFactory().constraint().disableWholeArchive();
+  info.attrFactory().constraint().disableAsNeeded();
+  info.attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  info.attrFactory().predefined().unsetWholeArchive();
+  info.attrFactory().predefined().setDynamic();
+
+}
+
+ARMAndroidSectLinker::~ARMAndroidSectLinker()
+{
+}
+
diff --git a/lib/Target/ARM/ARMAndroidSectLinker.h b/lib/Target/ARM/ARMAndroidSectLinker.h
new file mode 100644
index 0000000..8a47a94
--- /dev/null
+++ b/lib/Target/ARM/ARMAndroidSectLinker.h
@@ -0,0 +1,40 @@
+//===- ARMAndroidSectLinker.h ---------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ARM_ANDROIDSECTLINKER_H
+#define ARM_ANDROIDSECTLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/AndroidSectLinker.h>
+
+namespace mcld
+{
+
+class MCLDInfo;
+
+/** \class ARMAndroidSectLinker
+ *  \brief ARMAndroidSectLinker sets up the environment for linking.
+ *
+ *  \see
+ *  \author Anders Cheng <Anders.Cheng@mediatek.com>
+ */
+class ARMAndroidSectLinker : public AndroidSectLinker
+{
+public:
+  ARMAndroidSectLinker(SectLinkerOption &pOption,
+                       mcld::TargetLDBackend &pLDBackend);
+
+  ~ARMAndroidSectLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMELFArchiveReader.cpp b/lib/Target/ARM/ARMELFArchiveReader.cpp
new file mode 100644
index 0000000..4c6d775
--- /dev/null
+++ b/lib/Target/ARM/ARMELFArchiveReader.cpp
@@ -0,0 +1,14 @@
+//===- ARMELFArchiveReader.cpp --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMELFArchiveReader.h"
+
+using namespace mcld;
+
+//==========================
+// ARMELFArchiveReader
diff --git a/lib/Target/ARM/ARMELFArchiveReader.h b/lib/Target/ARM/ARMELFArchiveReader.h
new file mode 100644
index 0000000..b60a12d
--- /dev/null
+++ b/lib/Target/ARM/ARMELFArchiveReader.h
@@ -0,0 +1,29 @@
+//===- ARMELFArchiveReader.h ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ARMELFARCHIVEREADER_H
+#define ARMELFARCHIVEREADER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include "mcld/MC/MCELFArchiveTargetReader.h"
+
+namespace mcld
+{
+
+/// ARMELFArchiveReader - ARMELFArchiveReader is
+/// a target-dependent reader for ELF archive files.
+class ARMELFArchiveReader : public MCELFArchiveTargetReader
+{
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMELFDynamic.cpp b/lib/Target/ARM/ARMELFDynamic.cpp
new file mode 100644
index 0000000..c81a6f3
--- /dev/null
+++ b/lib/Target/ARM/ARMELFDynamic.cpp
@@ -0,0 +1,37 @@
+//===- ARMELFDynamic.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 "ARMELFDynamic.h"
+
+using namespace mcld;
+
+ARMELFDynamic::ARMELFDynamic(const GNULDBackend& pParent)
+  : ELFDynamic(pParent)
+{
+}
+
+ARMELFDynamic::~ARMELFDynamic()
+{
+}
+
+void ARMELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat)
+{
+  // reservePLTGOT
+  if (pFormat.hasGOT())
+    reserveOne(llvm::ELF::DT_PLTGOT);
+}
+
+void ARMELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat)
+{
+  // applyPLTGOT
+  if (pFormat.hasGOT())
+    applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOT().addr());
+}
+
diff --git a/lib/Target/ARM/ARMELFDynamic.h b/lib/Target/ARM/ARMELFDynamic.h
new file mode 100644
index 0000000..914dcc4
--- /dev/null
+++ b/lib/Target/ARM/ARMELFDynamic.h
@@ -0,0 +1,31 @@
+//===- ARMELFDynamic.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ARM_ELFDYNAMIC_SECTION_H
+#define MCLD_ARM_ELFDYNAMIC_SECTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/ELFDynamic.h>
+
+namespace mcld {
+
+class ARMELFDynamic : public ELFDynamic {
+public:
+  ARMELFDynamic(const GNULDBackend& pParent);
+  ~ARMELFDynamic();
+
+private:
+  void reserveTargetEntries(const ELFFileFormat& pFormat);
+  void applyTargetEntries(const ELFFileFormat& pFormat);
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/ARMELFSectLinker.cpp b/lib/Target/ARM/ARMELFSectLinker.cpp
new file mode 100644
index 0000000..0395606
--- /dev/null
+++ b/lib/Target/ARM/ARMELFSectLinker.cpp
@@ -0,0 +1,34 @@
+//===- ARMELFSectLinker.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMELFSectLinker.h"
+
+#include <mcld/CodeGen/SectLinkerOption.h>
+
+using namespace mcld;
+
+ARMELFSectLinker::ARMELFSectLinker(SectLinkerOption &pOption,
+                                   TargetLDBackend &pLDBackend)
+  : SectLinker(pOption,
+               pLDBackend) {
+  MCLDInfo &info = pOption.info();
+  // set up target-dependent constraints of attributes
+  info.attrFactory().constraint().enableWholeArchive();
+  info.attrFactory().constraint().disableAsNeeded();
+  info.attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  info.attrFactory().predefined().setWholeArchive();
+  info.attrFactory().predefined().setDynamic();
+
+}
+
+ARMELFSectLinker::~ARMELFSectLinker()
+{
+}
+
diff --git a/lib/Target/ARM/ARMELFSectLinker.h b/lib/Target/ARM/ARMELFSectLinker.h
new file mode 100644
index 0000000..7493d59
--- /dev/null
+++ b/lib/Target/ARM/ARMELFSectLinker.h
@@ -0,0 +1,36 @@
+//===- ARMELFSectLinker.h -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ARM_ELFSECTLINKER_H
+#define ARM_ELFSECTLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/CodeGen/SectLinker.h>
+
+namespace mcld
+{
+
+/** \class ARMELFSectLinker
+ *  \brief ARMELFSectLinker sets up the environment for linking.
+ *
+ *  \see
+ */
+class ARMELFSectLinker : public SectLinker
+{
+public:
+  ARMELFSectLinker(SectLinkerOption &pOption,
+                   mcld::TargetLDBackend &pLDBackend);
+
+  ~ARMELFSectLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h
new file mode 100644
index 0000000..f42b940
--- /dev/null
+++ b/lib/Target/ARM/ARMFixupKinds.h
@@ -0,0 +1,98 @@
+//===- ARMFixupKinds.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LIB_TARGET_ARM_ARM_FIXUP_KINDS_H_
+#define MCLD_LIB_TARGET_ARM_ARM_FIXUP_KINDS_H_
+
+#include <llvm/MC/MCFixup.h>
+
+namespace mcld {
+namespace ARM {
+
+enum Fixups {
+  // fixup_arm_ldst_pcrel_12 - 12-bit PC relative relocation for symbol
+  // addresses
+  fixup_arm_ldst_pcrel_12 = FirstTargetFixupKind,
+
+  // fixup_t2_ldst_pcrel_12 - Equivalent to fixup_arm_ldst_pcrel_12, with
+  // the 16-bit halfwords reordered.
+  fixup_t2_ldst_pcrel_12,
+
+  // fixup_arm_pcrel_10 - 10-bit PC relative relocation for symbol addresses
+  // used in VFP instructions where the lower 2 bits are not encoded
+  // (so it's encoded as an 8-bit immediate).
+  fixup_arm_pcrel_10,
+  // fixup_t2_pcrel_10 - Equivalent to fixup_arm_pcrel_10, accounting for
+  // the short-swapped encoding of Thumb2 instructions.
+  fixup_t2_pcrel_10,
+  // fixup_thumb_adr_pcrel_10 - 10-bit PC relative relocation for symbol
+  // addresses where the lower 2 bits are not encoded (so it's encoded as an
+  // 8-bit immediate).
+  fixup_thumb_adr_pcrel_10,
+  // fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
+  // instruction.
+  fixup_arm_adr_pcrel_12,
+  // fixup_t2_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
+  // instruction.
+  fixup_t2_adr_pcrel_12,
+  // fixup_arm_condbranch - 24-bit PC relative relocation for conditional branch
+  // instructions. 
+  fixup_arm_condbranch,
+  // fixup_arm_uncondbranch - 24-bit PC relative relocation for 
+  // branch instructions. (unconditional)
+  fixup_arm_uncondbranch,
+  // fixup_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct
+  // unconditional branch instructions.
+  fixup_t2_condbranch,
+  // fixup_t2_uncondbranch - 20-bit PC relative relocation for Thumb2 direct
+  // branch unconditional branch instructions.
+  fixup_t2_uncondbranch,
+
+  // fixup_arm_thumb_br - 12-bit fixup for Thumb B instructions.
+  fixup_arm_thumb_br,
+
+  // fixup_arm_thumb_bl - Fixup for Thumb BL instructions.
+  fixup_arm_thumb_bl,
+
+  // fixup_arm_thumb_blx - Fixup for Thumb BLX instructions.
+  fixup_arm_thumb_blx,
+
+  // fixup_arm_thumb_cb - Fixup for Thumb branch instructions.
+  fixup_arm_thumb_cb,
+
+  // fixup_arm_thumb_cp - Fixup for Thumb load/store from constant pool instrs.
+  fixup_arm_thumb_cp,
+
+  // fixup_arm_thumb_bcc - Fixup for Thumb conditional branching instructions.
+  fixup_arm_thumb_bcc,
+
+  // The next two are for the movt/movw pair
+  // the 16bit imm field are split into imm{15-12} and imm{11-0}
+  fixup_arm_movt_hi16, // :upper16:
+  fixup_arm_movw_lo16, // :lower16:
+  fixup_t2_movt_hi16, // :upper16:
+  fixup_t2_movw_lo16, // :lower16:
+
+  // It is possible to create an "immediate" that happens to be pcrel.
+  // movw r0, :lower16:Foo-(Bar+8) and movt  r0, :upper16:Foo-(Bar+8)
+  // result in different reloc tags than the above two.
+  // Needed to support ELF::R_ARM_MOVT_PREL and ELF::R_ARM_MOVW_PREL_NC
+  fixup_arm_movt_hi16_pcrel, // :upper16:
+  fixup_arm_movw_lo16_pcrel, // :lower16:
+  fixup_t2_movt_hi16_pcrel, // :upper16:
+  fixup_t2_movw_lo16_pcrel, // :lower16:
+
+  // Marker
+  LastTargetFixupKind,
+  NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
+};
+
+} // namespace ARM
+} // namespace mcld
+
+#endif
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
new file mode 100644
index 0000000..3eb8e4a
--- /dev/null
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -0,0 +1,185 @@
+//===- impl.cpp -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMGOT.h"
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <new>
+
+namespace {
+  const size_t ARMGOTEntrySize = 4;
+} // end of anonymous namespace
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ARMGOT
+ARMGOT::ARMGOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+             : GOT(pSection, pSectionData, ARMGOTEntrySize),
+               m_NormalGOTIterator(), m_GOTPLTIterator(),
+               m_GOTPLTBegin(), m_GOTPLTEnd()
+{
+  GOTEntry* Entry = 0;
+
+  // Create GOT0 entries.
+  for (int i = 0; i < 3; i++) {
+    Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
+                                        &m_SectionData);
+
+    if (!Entry)
+      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+
+    m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
+  }
+
+  // Skip GOT0 entries.
+  iterator it = m_SectionData.begin();
+  iterator ie = m_SectionData.end();
+
+  for (int i = 1; i < ARMGOT0Num; ++i) {
+    if (it == ie)
+      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
+
+    ++it;
+  }
+
+  m_NormalGOTIterator = it;
+  m_GOTPLTIterator = it;
+
+  m_GOTPLTBegin = it;
+  m_GOTPLTEnd = it;
+}
+
+ARMGOT::~ARMGOT()
+{
+}
+
+void ARMGOT::reserveEntry(size_t pNum)
+{
+  GOTEntry* Entry = 0;
+
+  for (size_t i = 0; i < pNum; i++) {
+    Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
+                                        &m_SectionData);
+
+    if (!Entry)
+      llvm::report_fatal_error("Allocating new memory for GOTEntry failed");
+
+    m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
+  }
+}
+
+void ARMGOT::reserveGOTPLTEntry()
+{
+    GOTEntry* got_entry = 0;
+
+    got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
+
+    if (!got_entry)
+      llvm::report_fatal_error("Allocating new memory for GOT failed!");
+
+    m_Section.setSize(m_Section.size() + getEntrySize());
+
+    ++m_GOTPLTEnd;
+    ++m_NormalGOTIterator;
+}
+
+GOTEntry* ARMGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
+{
+  GOTEntry *&Entry = m_NormalGOTMap[&pInfo];
+  pExist = 1;
+
+  if (!Entry) {
+    pExist = 0;
+
+    ++m_NormalGOTIterator;
+    assert(m_NormalGOTIterator != m_SectionData.getFragmentList().end()
+           && "The number of GOT Entries and ResolveInfo doesn't match!");
+
+    Entry = llvm::cast<GOTEntry>(&(*m_NormalGOTIterator));
+  }
+
+  return Entry;
+}
+
+void ARMGOT::applyGOT0(uint64_t pAddress)
+{
+  llvm::cast<GOTEntry>
+    (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
+}
+
+void ARMGOT::applyAllGOTPLT(uint64_t pPLTBase)
+{
+  iterator begin = getGOTPLTBegin();
+  iterator end = getGOTPLTEnd();
+
+  for (;begin != end ;++begin)
+    llvm::cast<GOTEntry>(*begin).setContent(pPLTBase);
+}
+
+GOTEntry*& ARMGOT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
+{
+  return m_GOTPLTMap[&pSymbol];
+}
+
+ARMGOT::iterator ARMGOT::begin()
+{
+  return m_SectionData.getFragmentList().begin();
+}
+
+ARMGOT::const_iterator ARMGOT::begin() const
+{
+  return m_SectionData.getFragmentList().begin();
+}
+
+ARMGOT::iterator ARMGOT::end()
+{
+  return m_SectionData.getFragmentList().end();
+}
+
+ARMGOT::const_iterator ARMGOT::end() const
+{
+  return m_SectionData.getFragmentList().end();
+}
+
+ARMGOT::iterator ARMGOT::getNextGOTPLTEntry()
+{
+  return ++m_GOTPLTIterator;
+}
+
+ARMGOT::iterator ARMGOT::getGOTPLTBegin()
+{
+  // Move to the first GOTPLT entry from last GOT0 entry.
+  iterator begin = m_GOTPLTBegin;
+  return ++begin;
+}
+
+const ARMGOT::iterator ARMGOT::getGOTPLTEnd()
+{
+  // Move to end or the first normal GOT entry from the last GOTPLT entry.
+  iterator end = m_GOTPLTEnd;
+  return ++end;
+}
+
+uint64_t ARMGOT::emit(MemoryRegion& pRegion)
+{
+  uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+
+  GOTEntry* got = 0;
+  unsigned int entry_size = getEntrySize();
+  uint64_t result = 0x0;
+  for (iterator it = begin(), ie = end();
+       it != ie; ++it, ++buffer) {
+      got = &(llvm::cast<GOTEntry>((*it)));
+      *buffer = static_cast<uint32_t>(got->getContent());
+      result += entry_size;
+  }
+  return result;
+}
+
diff --git a/lib/Target/ARM/ARMGOT.h b/lib/Target/ARM/ARMGOT.h
new file mode 100644
index 0000000..90f0f53
--- /dev/null
+++ b/lib/Target/ARM/ARMGOT.h
@@ -0,0 +1,92 @@
+//===- ARMGOT.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ARM_GOT_H
+#define MCLD_ARM_GOT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/GOT.h>
+
+namespace mcld
+{
+class LDSection;
+class MemoryRegion;
+
+/** \class ARMGOT
+ *  \brief ARM Global Offset Table.
+ */
+class ARMGOT : public GOT
+{
+  typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
+
+public:
+  typedef llvm::MCSectionData::iterator iterator;
+  typedef llvm::MCSectionData::const_iterator const_iterator;
+
+  enum {
+    ARMGOT0Num = 3
+  };
+
+public:
+  ARMGOT(LDSection &pSection, llvm::MCSectionData& pSectionData);
+
+  ~ARMGOT();
+
+  iterator begin();
+
+  const_iterator begin() const;
+
+  iterator end();
+
+  const_iterator end() const;
+
+  uint64_t emit(MemoryRegion& pRegion);
+// For GOT0
+public:
+  void applyGOT0(uint64_t pAddress);
+
+// For normal GOT
+public:
+  // Reserve normal GOT entries.
+  void reserveEntry(size_t pNum = 1);
+
+  GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
+
+// For GOTPLT
+public:
+  void reserveGOTPLTEntry();
+
+  void applyAllGOTPLT(uint64_t pPLTBase);
+
+  GOTEntry*& lookupGOTPLTMap(const ResolveInfo& pSymbol);
+
+  iterator getNextGOTPLTEntry();
+
+  iterator getGOTPLTBegin();
+
+  const iterator getGOTPLTEnd();
+
+private:
+  // For normal GOT entries
+  iterator m_NormalGOTIterator;
+  SymbolIndexMapType m_NormalGOTMap;
+
+  // For GOTPLT entries
+  iterator m_GOTPLTIterator;
+  SymbolIndexMapType m_GOTPLTMap;
+
+  iterator m_GOTPLTBegin;
+  iterator m_GOTPLTEnd;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
new file mode 100644
index 0000000..105a957
--- /dev/null
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -0,0 +1,1018 @@
+//===- ARMLDBackend.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/ADT/Twine.h>
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/ErrorHandling.h>
+
+#include <mcld/LD/SectionMap.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDOutput.h>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/MC/MCRegionFragment.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/TargetRegistry.h>
+
+#include <cstring>
+
+#include "ARM.h"
+#include "ARMELFDynamic.h"
+#include "ARMLDBackend.h"
+#include "ARMRelocationFactory.h"
+
+using namespace mcld;
+
+ARMGNULDBackend::ARMGNULDBackend()
+  : m_pRelocFactory(NULL),
+    m_pGOT(NULL),
+    m_pPLT(NULL),
+    m_pRelDyn(NULL),
+    m_pRelPLT(NULL),
+    m_pDynamic(NULL),
+    m_pEXIDX(NULL),
+    m_pEXTAB(NULL),
+    m_pAttributes(NULL) {
+}
+
+ARMGNULDBackend::~ARMGNULDBackend()
+{
+  if (m_pRelocFactory)
+    delete m_pRelocFactory;
+  if(m_pGOT)
+    delete m_pGOT;
+  if(m_pPLT)
+    delete m_pPLT;
+  if(m_pRelDyn)
+    delete m_pRelDyn;
+  if(m_pRelPLT)
+    delete m_pRelPLT;
+  if(m_pDynamic)
+    delete m_pDynamic;
+}
+
+bool ARMGNULDBackend::initRelocFactory(const MCLinker& pLinker)
+{
+  if (NULL == m_pRelocFactory) {
+    m_pRelocFactory = new ARMRelocationFactory(1024, *this);
+    m_pRelocFactory->setLayout(pLinker.getLayout());
+  }
+  return true;
+}
+
+RelocationFactory* ARMGNULDBackend::getRelocFactory()
+{
+  assert(NULL != m_pRelocFactory);
+  return m_pRelocFactory;
+}
+
+bool ARMGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
+{
+  if (!pSectionMap.push_back(".ARM.exidx", ".ARM.exidx") ||
+      !pSectionMap.push_back(".ARM.extab", ".ARM.extab") ||
+      !pSectionMap.push_back(".ARM.attributes", ".ARM.attributes"))
+    return false;
+  return true;
+}
+
+void ARMGNULDBackend::initTargetSections(MCLinker& pLinker)
+{
+ // FIXME: Currently we set exidx and extab to "Exception" and directly emit
+ // them from input
+  m_pEXIDX        = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx",
+                                                      LDFileFormat::Exception,
+                                                      llvm::ELF::SHT_ARM_EXIDX,
+                                                      llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
+                                                      bitclass() / 8);
+  m_pEXTAB        = &pLinker.getOrCreateOutputSectHdr(".ARM.extab",
+                                                      LDFileFormat::Exception,
+                                                      llvm::ELF::SHT_PROGBITS,
+                                                      llvm::ELF::SHF_ALLOC,
+                                                      0x1);
+  m_pAttributes   = &pLinker.getOrCreateOutputSectHdr(".ARM.attributes",
+                                                      LDFileFormat::Target,
+                                                      llvm::ELF::SHT_ARM_ATTRIBUTES,
+                                                      0x0,
+                                                      0x1);
+}
+
+void ARMGNULDBackend::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);
+}
+
+void ARMGNULDBackend::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)) {
+      createARMGOT(pLinker, pOutput);
+  }
+}
+
+void ARMGNULDBackend::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());
+
+  ELFFileFormat *file_format = getOutputFormat(pOutput);
+
+  // apply PLT
+  if (file_format->hasPLT()) {
+    // Since we already have the size of LDSection PLT, m_pPLT should not be
+    // NULL.
+    assert(NULL != m_pPLT);
+    m_pPLT->applyPLT0();
+    m_pPLT->applyPLT1();
+  }
+
+  // apply GOT
+  if (file_format->hasGOT()) {
+    // Since we already have the size of GOT, m_pGOT should not be NULL.
+    assert(NULL != m_pGOT);
+    if (pOutput.type() == Output::DynObj)
+      m_pGOT->applyGOT0(file_format->getDynamic().addr());
+    else {
+      // executable file and object file? should fill with zero.
+      m_pGOT->applyGOT0(0);
+    }
+  }
+}
+
+/// dynamic - the dynamic section of the target machine.
+/// Use co-variant return type to return its own dynamic section.
+ARMELFDynamic& ARMGNULDBackend::dynamic()
+{
+  if (NULL == m_pDynamic)
+    m_pDynamic = new ARMELFDynamic(*this);
+
+  return *m_pDynamic;
+}
+
+/// dynamic - the dynamic section of the target machine.
+/// Use co-variant return type to return its own dynamic section.
+const ARMELFDynamic& ARMGNULDBackend::dynamic() const
+{
+  assert( NULL != m_pDynamic);
+  return *m_pDynamic;
+}
+
+bool ARMGNULDBackend::isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const
+{
+  return (pOutput.type() == Output::DynObj);
+}
+
+void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput)
+{
+  // get .got LDSection and create MCSectionData
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  LDSection& got = file_format->getGOT();
+  m_pGOT = new ARMGOT(got, pLinker.getOrCreateSectData(got));
+
+  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
+  if( m_pGOTSymbol != NULL ) {
+    pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
+                     "_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 ARMGNULDBackend::createARMPLTandRelPLT(MCLinker& pLinker,
+                                            const Output& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  // get .plt and .rel.plt LDSection
+  LDSection& plt = file_format->getPLT();
+  LDSection& relplt = file_format->getRelPlt();
+  // create MCSectionData and ARMPLT
+  m_pPLT = new ARMPLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT);
+  // set info of .rel.plt to .plt
+  relplt.setLink(&plt);
+  // create MCSectionData and ARMRelDynSection
+  m_pRelPLT = new OutputRelocSection(relplt,
+                                     pLinker.getOrCreateSectData(relplt),
+                                     8);
+}
+
+void ARMGNULDBackend::createARMRelDyn(MCLinker& pLinker,
+                                      const Output& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  // get .rel.dyn LDSection and create MCSectionData
+  LDSection& reldyn = file_format->getRelDyn();
+  // create MCSectionData and ARMRelDynSection
+  m_pRelDyn = new OutputRelocSection(reldyn,
+                                     pLinker.getOrCreateSectData(reldyn),
+                                     8);
+}
+
+ELFFileFormat* ARMGNULDBackend::getOutputFormat(const Output& pOutput) const
+{
+  switch (pOutput.type()) {
+    case Output::DynObj:
+      return getDynObjFileFormat();
+    case Output::Exec:
+      return getExecFileFormat();
+    // FIXME: We do not support building .o now
+    case Output::Object:
+    default:
+      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
+                               llvm::Twine(pOutput.type()));
+      return NULL;
+  }
+}
+
+bool ARMGNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym,
+                                       const MCLDInfo& pLDInfo,
+                                       const Output& pOutput) const
+{
+  return (Output::DynObj == pOutput.type() &&
+          ResolveInfo::Function == pSym.type() &&
+          (pSym.isDyn() || pSym.isUndef() ||
+            isSymbolPreemptible(pSym, pLDInfo, pOutput)));
+}
+
+bool ARMGNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym,
+                                          const Output& pOutput,
+                                          bool isAbsReloc) const
+{
+  if(pSym.isUndef() && (Output::Exec == pOutput.type()))
+    return false;
+  if(pSym.isAbsolute())
+    return false;
+  if(Output::DynObj == pOutput.type() && isAbsReloc)
+    return true;
+  if(pSym.isDyn() || pSym.isUndef())
+    return true;
+
+  return false;
+}
+
+bool ARMGNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
+                                          const MCLDInfo& pLDInfo,
+                                          const Output& pOutput) const
+{
+  if(pSym.other() != ResolveInfo::Default)
+    return false;
+
+  if(Output::DynObj != pOutput.type())
+    return false;
+
+  if(pLDInfo.options().Bsymbolic())
+    return false;
+
+  return true;
+}
+
+/// checkValidReloc - When we attempt to generate a dynamic relocation for
+/// ouput file, check if the relocation is supported by dynamic linker.
+void ARMGNULDBackend::checkValidReloc(Relocation& pReloc,
+                                      const MCLDInfo& pLDInfo,
+                                      const Output& pOutput) const
+{
+  // If not building a PIC object, no relocation type is invalid
+  if (!isPIC(pLDInfo, pOutput))
+    return;
+
+  switch(pReloc.type()) {
+    case llvm::ELF::R_ARM_RELATIVE:
+    case llvm::ELF::R_ARM_COPY:
+    case llvm::ELF::R_ARM_GLOB_DAT:
+    case llvm::ELF::R_ARM_JUMP_SLOT:
+    case llvm::ELF::R_ARM_ABS32:
+    case llvm::ELF::R_ARM_ABS32_NOI:
+    case llvm::ELF::R_ARM_PC24:
+    case llvm::ELF::R_ARM_TLS_DTPMOD32:
+    case llvm::ELF::R_ARM_TLS_DTPOFF32:
+    case llvm::ELF::R_ARM_TLS_TPOFF32:
+      break;
+
+    default:
+      llvm::report_fatal_error(llvm::Twine("Attempt to generate unsupported") +
+                               llvm::Twine(" relocation type ") +
+                               llvm::Twine((int)pReloc.type()) +
+                               llvm::Twine(" for symbol '") +
+                               llvm::Twine(pReloc.symInfo()->name()) +
+                               llvm::Twine("', recompile with -fPIC")
+                              );
+      break;
+  }
+}
+
+void ARMGNULDBackend::updateAddend(Relocation& pReloc,
+                                   const LDSymbol& pInputSym,
+                                   const Layout& pLayout) const
+{
+  // Update value keep in addend if we meet a section symbol
+  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+    pReloc.setAddend(pLayout.getOutputOffset(
+                     *pInputSym.fragRef()) + pReloc.addend());
+  }
+}
+
+void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc,
+                                     const LDSymbol& pInputSym,
+                                     MCLinker& pLinker,
+                                     const MCLDInfo& pLDInfo,
+                                     const Output& pOutput)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  updateAddend(pReloc, pInputSym, pLinker.getLayout());
+
+  switch(pReloc.type()){
+
+    // Set R_ARM_TARGET1 to R_ARM_ABS32
+    // Ref: GNU gold 1.11 arm.cc, line 9892
+    case llvm::ELF::R_ARM_TARGET1:
+       pReloc.setType(llvm::ELF::R_ARM_ABS32);
+    case llvm::ELF::R_ARM_ABS32:
+    case llvm::ELF::R_ARM_ABS32_NOI: {
+      // If buiding PIC object (shared library or PIC executable),
+      // a dynamic relocations with RELATIVE type to this location is needed.
+      // Reserve an entry in .rel.dyn
+      if(isPIC(pLDInfo, pOutput)) {
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createARMRelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | 0x1u);
+        }
+      return;
+    }
+
+    case llvm::ELF::R_ARM_ABS16:
+    case llvm::ELF::R_ARM_ABS12:
+    case llvm::ELF::R_ARM_THM_ABS5:
+    case llvm::ELF::R_ARM_ABS8:
+    case llvm::ELF::R_ARM_BASE_ABS:
+    case llvm::ELF::R_ARM_MOVW_ABS_NC:
+    case llvm::ELF::R_ARM_MOVT_ABS:
+    case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
+    case llvm::ELF::R_ARM_THM_MOVT_ABS: {
+      // Update value keep in relocation place if we meet a section symbol
+      if(rsym->type() == ResolveInfo::Section) {
+        pReloc.target() = pLinker.getLayout().getOutputOffset(
+                            *pInputSym.fragRef()) + pReloc.target();
+      }
+
+      // If building PIC object (shared library or PIC executable),
+      // a dynamic relocation for this location is needed.
+      // Reserve an entry in .rel.dyn
+      if(isPIC(pLDInfo, pOutput)) {
+        checkValidReloc(pReloc, pLDInfo, pOutput);
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createARMRelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | 0x1u);
+      }
+      return;
+    }
+    case llvm::ELF::R_ARM_GOTOFF32:
+    case llvm::ELF::R_ARM_GOTOFF12: {
+      // A GOT section is needed
+      if(NULL == m_pGOT)
+        createARMGOT(pLinker, pOutput);
+      return;
+    }
+
+    // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
+    // Ref: GNU gold 1.11 arm.cc, line 9892
+    case llvm::ELF::R_ARM_TARGET2:
+      pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
+    case llvm::ELF::R_ARM_GOT_BREL:
+    case llvm::ELF::R_ARM_GOT_PREL: {
+      // A GOT entry is needed for these relocation type.
+      // return if we already create GOT for this symbol
+      if(rsym->reserved() & 0x6u)
+        return;
+      if(NULL == m_pGOT)
+        createARMGOT(pLinker, pOutput);
+      m_pGOT->reserveEntry();
+      // If building PIC object, a dynamic relocation with
+      // type RELATIVE is needed to relocate this GOT entry.
+      // Reserve an entry in .rel.dyn
+      if(isPIC(pLDInfo, pOutput)) {
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createARMRelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set GOTRel bit
+        rsym->setReserved(rsym->reserved() | 0x4u);
+        return;
+      }
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | 0x2u);
+      return;
+    }
+
+    case llvm::ELF::R_ARM_BASE_PREL: {
+      // FIXME: Currently we only support R_ARM_BASE_PREL against
+      // symbol _GLOBAL_OFFSET_TABLE_
+      if(rsym != m_pGOTSymbol->resolveInfo()) {
+        llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
+                                 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
+                                 llvm::Twine(rsym->name()) +
+                                 llvm::Twine(".'"));
+      }
+      return;
+    }
+    case llvm::ELF::R_ARM_COPY:
+    case llvm::ELF::R_ARM_GLOB_DAT:
+    case llvm::ELF::R_ARM_JUMP_SLOT:
+    case llvm::ELF::R_ARM_RELATIVE: {
+      // These are relocation type for dynamic linker, shold not
+      // appear in object file.
+      llvm::report_fatal_error(llvm::Twine("unexpected reloc ") +
+                               llvm::Twine((int)pReloc.type()) +
+                               llvm::Twine(" in object file"));
+      break;
+    }
+    default: {
+      break;
+    }
+  } // end switch
+}
+
+void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc,
+                                      const LDSymbol& pInputSym,
+                                      MCLinker& pLinker,
+                                      const MCLDInfo& pLDInfo,
+                                      const Output& pOutput)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  switch(pReloc.type()) {
+
+    // Set R_ARM_TARGET1 to R_ARM_ABS32
+    // Ref: GNU gold 1.11 arm.cc, line 9892
+    case llvm::ELF::R_ARM_TARGET1:
+      pReloc.setType(llvm::ELF::R_ARM_ABS32);
+    case llvm::ELF::R_ARM_ABS32:
+    case llvm::ELF::R_ARM_ABS16:
+    case llvm::ELF::R_ARM_ABS12:
+    case llvm::ELF::R_ARM_THM_ABS5:
+    case llvm::ELF::R_ARM_ABS8:
+    case llvm::ELF::R_ARM_BASE_ABS:
+    case llvm::ELF::R_ARM_MOVW_ABS_NC:
+    case llvm::ELF::R_ARM_MOVT_ABS:
+    case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
+    case llvm::ELF::R_ARM_THM_MOVT_ABS:
+    case llvm::ELF::R_ARM_ABS32_NOI: {
+      // Absolute relocation type, symbol may needs PLT entry or
+      // dynamic relocation entry
+      if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+        // create plt for this symbol if it does not have one
+        if(!(rsym->reserved() & 0x8u)){
+          // Create .got section if it doesn't exist
+          if(NULL == m_pGOT)
+            createARMGOT(pLinker, pOutput);
+          // create .plt and .rel.plt if not exist
+          if(NULL == m_pPLT)
+            createARMPLTandRelPLT(pLinker, pOutput);
+          // Symbol needs PLT entry, we need to reserve a PLT entry
+          // and the corresponding GOT and dynamic relocation entry
+          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
+          // when calling ARMPLT->reserveEntry())
+          m_pPLT->reserveEntry();
+          m_pRelPLT->reserveEntry(*m_pRelocFactory);
+          // set PLT bit
+          rsym->setReserved(rsym->reserved() | 0x8u);
+        }
+      }
+
+      if(isSymbolNeedsDynRel(*rsym, pOutput, true)) {
+        checkValidReloc(pReloc, pLDInfo, pOutput);
+        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createARMRelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | 0x1u);
+      }
+      return;
+    }
+
+    case llvm::ELF::R_ARM_GOTOFF32:
+    case llvm::ELF::R_ARM_GOTOFF12: {
+      // A GOT section is needed
+      if(NULL == m_pGOT)
+        createARMGOT(pLinker, pOutput);
+      return;
+    }
+
+    case llvm::ELF::R_ARM_BASE_PREL:
+      // FIXME: Currently we only support R_ARM_BASE_PREL against
+      // symbol _GLOBAL_OFFSET_TABLE_
+      if(rsym != m_pGOTSymbol->resolveInfo()) {
+        llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
+                                 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
+                                 llvm::Twine(rsym->name()) +
+                                 llvm::Twine(".'"));
+      }
+    case llvm::ELF::R_ARM_REL32:
+    case llvm::ELF::R_ARM_LDR_PC_G0:
+    case llvm::ELF::R_ARM_SBREL32:
+    case llvm::ELF::R_ARM_THM_PC8:
+    case llvm::ELF::R_ARM_MOVW_PREL_NC:
+    case llvm::ELF::R_ARM_MOVT_PREL:
+    case llvm::ELF::R_ARM_THM_MOVW_PREL_NC:
+    case llvm::ELF::R_ARM_THM_MOVT_PREL:
+    case llvm::ELF::R_ARM_THM_ALU_PREL_11_0:
+    case llvm::ELF::R_ARM_THM_PC12:
+    case llvm::ELF::R_ARM_REL32_NOI:
+    case llvm::ELF::R_ARM_ALU_PC_G0_NC:
+    case llvm::ELF::R_ARM_ALU_PC_G0:
+    case llvm::ELF::R_ARM_ALU_PC_G1_NC:
+    case llvm::ELF::R_ARM_ALU_PC_G1:
+    case llvm::ELF::R_ARM_ALU_PC_G2:
+    case llvm::ELF::R_ARM_LDR_PC_G1:
+    case llvm::ELF::R_ARM_LDR_PC_G2:
+    case llvm::ELF::R_ARM_LDRS_PC_G0:
+    case llvm::ELF::R_ARM_LDRS_PC_G1:
+    case llvm::ELF::R_ARM_LDRS_PC_G2:
+    case llvm::ELF::R_ARM_LDC_PC_G0:
+    case llvm::ELF::R_ARM_LDC_PC_G1:
+    case llvm::ELF::R_ARM_LDC_PC_G2:
+    case llvm::ELF::R_ARM_ALU_SB_G0_NC:
+    case llvm::ELF::R_ARM_ALU_SB_G0:
+    case llvm::ELF::R_ARM_ALU_SB_G1_NC:
+    case llvm::ELF::R_ARM_ALU_SB_G1:
+    case llvm::ELF::R_ARM_ALU_SB_G2:
+    case llvm::ELF::R_ARM_LDR_SB_G0:
+    case llvm::ELF::R_ARM_LDR_SB_G1:
+    case llvm::ELF::R_ARM_LDR_SB_G2:
+    case llvm::ELF::R_ARM_LDRS_SB_G0:
+    case llvm::ELF::R_ARM_LDRS_SB_G1:
+    case llvm::ELF::R_ARM_LDRS_SB_G2:
+    case llvm::ELF::R_ARM_LDC_SB_G0:
+    case llvm::ELF::R_ARM_LDC_SB_G1:
+    case llvm::ELF::R_ARM_LDC_SB_G2:
+    case llvm::ELF::R_ARM_MOVW_BREL_NC:
+    case llvm::ELF::R_ARM_MOVT_BREL:
+    case llvm::ELF::R_ARM_MOVW_BREL:
+    case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
+    case llvm::ELF::R_ARM_THM_MOVT_BREL:
+    case llvm::ELF::R_ARM_THM_MOVW_BREL: {
+      // Relative addressing relocation, may needs dynamic relocation
+      if(isSymbolNeedsDynRel(*rsym, pOutput, false)) {
+        checkValidReloc(pReloc, pLDInfo, pOutput);
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createARMRelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | 0x1u);
+      }
+      return;
+    }
+
+    case llvm::ELF::R_ARM_THM_CALL:
+    case llvm::ELF::R_ARM_PLT32:
+    case llvm::ELF::R_ARM_CALL:
+    case llvm::ELF::R_ARM_JUMP24:
+    case llvm::ELF::R_ARM_THM_JUMP24:
+    case llvm::ELF::R_ARM_SBREL31:
+    case llvm::ELF::R_ARM_PREL31:
+    case llvm::ELF::R_ARM_THM_JUMP19:
+    case llvm::ELF::R_ARM_THM_JUMP6:
+    case llvm::ELF::R_ARM_THM_JUMP11:
+    case llvm::ELF::R_ARM_THM_JUMP8: {
+      // These are branch relocation (except PREL31)
+      // A PLT entry is needed when building shared library
+
+      // return if we already create plt for this symbol
+      if(rsym->reserved() & 0x8u)
+        return;
+
+      // if symbol is defined in the ouput file and it's not
+      // preemptible, no need plt
+      if(rsym->isDefine() && !rsym->isDyn() &&
+         !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
+        return;
+      }
+
+      // Create .got section if it doesn't exist
+      if(NULL == m_pGOT)
+        createARMGOT(pLinker, pOutput);
+
+      // create .plt and .rel.plt if not exist
+      if(NULL == m_pPLT)
+         createARMPLTandRelPLT(pLinker, pOutput);
+      // Symbol needs PLT entry, we need to reserve a PLT entry
+      // and the corresponding GOT and dynamic relocation entry
+      // in .got and .rel.plt. (GOT entry will be reserved simultaneously
+      // when calling ARMPLT->reserveEntry())
+      m_pPLT->reserveEntry();
+      m_pRelPLT->reserveEntry(*m_pRelocFactory);
+      // set PLT bit
+      rsym->setReserved(rsym->reserved() | 0x8u);
+      return;
+    }
+
+    // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
+    // Ref: GNU gold 1.11 arm.cc, line 9892
+    case llvm::ELF::R_ARM_TARGET2:
+      pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
+    case llvm::ELF::R_ARM_GOT_BREL:
+    case llvm::ELF::R_ARM_GOT_ABS:
+    case llvm::ELF::R_ARM_GOT_PREL: {
+      // Symbol needs GOT entry, reserve entry in .got
+      // return if we already create GOT for this symbol
+      if(rsym->reserved() & 0x6u)
+        return;
+      if(NULL == m_pGOT)
+        createARMGOT(pLinker, pOutput);
+      m_pGOT->reserveEntry();
+      // If building shared object or the symbol is undefined, a dynamic
+      // relocation is needed to relocate this GOT entry. Reserve an
+      // entry in .rel.dyn
+      if(Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createARMRelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set GOTRel bit
+        rsym->setReserved(rsym->reserved() | 0x4u);
+        return;
+      }
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | 0x2u);
+      return;
+    }
+
+    case llvm::ELF::R_ARM_COPY:
+    case llvm::ELF::R_ARM_GLOB_DAT:
+    case llvm::ELF::R_ARM_JUMP_SLOT:
+    case llvm::ELF::R_ARM_RELATIVE: {
+      // These are relocation type for dynamic linker, shold not
+      // appear in object file.
+      llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") +
+                               llvm::Twine((int)pReloc.type()) +
+                               llvm::Twine(" in object file"));
+      break;
+    }
+    default: {
+      break;
+    }
+  } // end switch
+}
+
+void ARMGNULDBackend::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");
+
+  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
+  // entries should be created.
+  // FIXME: Below judgements concern only .so is generated as output
+  // FIXME: Below judgements concern nothing about TLS related relocation
+
+  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section
+  // is needed
+  if(NULL == m_pGOT && NULL != m_pGOTSymbol) {
+    if(rsym == m_pGOTSymbol->resolveInfo()) {
+      createARMGOT(pLinker, pOutput);
+    }
+  }
+
+  // rsym is local
+  if(rsym->isLocal())
+    scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+
+  // rsym is external
+  else
+    scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+
+}
+
+uint64_t ARMGNULDBackend::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 == m_pAttributes) {
+    // FIXME: Currently Emitting .ARM.attributes directly from the input file.
+    const llvm::MCSectionData* sect_data = pSection.getSectionData();
+    assert(sect_data &&
+           "Emit .ARM.attribute failed, MCSectionData doesn't exist!");
+
+    uint8_t* start =
+              llvm::cast<MCRegionFragment>(
+                     sect_data->getFragmentList().front()).getRegion().start();
+
+    memcpy(pRegion.start(), start, pRegion.size());
+    return pRegion.size();
+  }
+
+  if (&pSection == &(file_format->getPLT())) {
+    assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
+    uint64_t result = m_pPLT->emit(pRegion);
+    return result;
+  }
+
+  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 0x0;
+}
+
+/// finalizeSymbol - finalize the symbol value
+/// If the symbol's reserved field is not zero, MCLinker will call back this
+/// function to ask the final value of the symbol
+bool ARMGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+{
+  return false;
+}
+
+/// allocateCommonSymbols - allocate common symbols in the corresponding
+/// sections.
+/// @refer Google gold linker: common.cc: 214
+bool
+ARMGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
+{
+  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
+
+  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
+    return true;
+
+  // addralign := max value of all common symbols
+  uint64_t addralign = 0x0;
+
+  // Due to the visibility, some common symbols may be forcefully local.
+  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
+  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
+    if (ResolveInfo::Common == (*com_sym)->desc()) {
+      if ((*com_sym)->value() > addralign)
+        addralign = (*com_sym)->value();
+    }
+  }
+
+  // global common symbols.
+  com_end = symbol_list.commonEnd();
+  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
+    if ((*com_sym)->value() > addralign)
+      addralign = (*com_sym)->value();
+  }
+
+  // FIXME: If the order of common symbols is defined, then sort common symbols
+  // com_sym = symbol_list.commonBegin();
+  // std::sort(com_sym, com_end, some kind of order);
+
+  // get or create corresponding BSS LDSection
+  LDSection* bss_sect_hdr = NULL;
+  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
+                                   ".tbss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+  }
+  else {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+  }
+
+  // get or create corresponding BSS MCSectionData
+  assert(NULL != bss_sect_hdr);
+  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
+
+  // allocate all common symbols
+  uint64_t offset = bss_sect_hdr->size();
+
+  // allocate all local common symbols
+  com_end = symbol_list.localEnd();
+  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
+    if (ResolveInfo::Common == (*com_sym)->desc()) {
+      // We have to reset the description of the symbol here. When doing
+      // incremental linking, the output relocatable object may have common
+      // symbols. Therefore, we can not treat common symbols as normal symbols
+      // when emitting the regular name pools. We must change the symbols'
+      // description here.
+      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
+      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+      uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                         bss_section,
+                                                         (*com_sym)->value());
+      offset += size;
+    }
+  }
+
+  // allocate all global common symbols
+  com_end = symbol_list.commonEnd();
+  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
+    // We have to reset the description of the symbol here. When doing
+    // incremental linking, the output relocatable object may have common
+    // symbols. Therefore, we can not treat common symbols as normal symbols
+    // when emitting the regular name pools. We must change the symbols'
+    // description here.
+    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
+    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+    uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                       bss_section,
+                                                       (*com_sym)->value());
+    offset += size;
+  }
+
+  bss_sect_hdr->setSize(offset);
+  symbol_list.changeCommonsToGlobal();
+  return true;
+}
+
+bool ARMGNULDBackend::readSection(Input& pInput,
+                                  MCLinker& pLinker,
+                                  LDSection& pInputSectHdr)
+{
+  LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
+                                                         pInputSectHdr.kind(),
+                                                         pInputSectHdr.type(),
+                                                         pInputSectHdr.flag());
+  // FIXME: (Luba)
+  // Handle ARM attributes in the right way.
+  // In current milestone, MCLinker goes through the shortcut.
+  // It reads input's ARM attributes and copies the first ARM attributes
+  // into the output file. The correct way is merge these sections, not
+  // just copy.
+  if ((0 == out_sect.name().compare(".ARM.attributes")) &&
+      (0 != out_sect.size()))
+    return true;
+
+  MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(),
+                                                   pInputSectHdr.size());
+
+  llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
+
+  new MCRegionFragment(*region, &sect_data);
+
+  out_sect.setSize(out_sect.size() + pInputSectHdr.size());
+  return true;
+}
+
+ARMGOT& ARMGNULDBackend::getGOT()
+{
+  assert(NULL != m_pGOT && "GOT section not exist");
+  return *m_pGOT;
+}
+
+const ARMGOT& ARMGNULDBackend::getGOT() const
+{
+  assert(NULL != m_pGOT && "GOT section not exist");
+  return *m_pGOT;
+}
+
+ARMPLT& ARMGNULDBackend::getPLT()
+{
+  assert(NULL != m_pPLT && "PLT section not exist");
+  return *m_pPLT;
+}
+
+const ARMPLT& ARMGNULDBackend::getPLT() const
+{
+  assert(NULL != m_pPLT && "PLT section not exist");
+  return *m_pPLT;
+}
+
+OutputRelocSection& ARMGNULDBackend::getRelDyn()
+{
+  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
+  return *m_pRelDyn;
+}
+
+const OutputRelocSection& ARMGNULDBackend::getRelDyn() const
+{
+  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
+  return *m_pRelDyn;
+}
+
+OutputRelocSection& ARMGNULDBackend::getRelPLT()
+{
+  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
+  return *m_pRelPLT;
+}
+
+const OutputRelocSection& ARMGNULDBackend::getRelPLT() const
+{
+  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
+  return *m_pRelPLT;
+}
+
+unsigned int
+ARMGNULDBackend::getTargetSectionOrder(const Output& pOutput,
+                                       const LDSection& pSectHdr) const
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  if (&pSectHdr == &file_format->getGOT())
+    return SHO_DATA;
+
+  if (&pSectHdr == &file_format->getPLT())
+    return SHO_PLT;
+
+  return SHO_UNDEFINED;
+}
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+/// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
+///
+TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget,
+                                    const std::string& pTriple)
+{
+  Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker is not supported yet");
+    /**
+    return new ARMMachOLDBackend(createARMMachOArchiveReader,
+                               createARMMachOObjectReader,
+                               createARMMachOObjectWriter);
+    **/
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker is not supported yet");
+    /**
+    return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
+                               createARMCOFFObjectReader,
+                               createARMCOFFObjectWriter);
+    **/
+  }
+  return new ARMGNULDBackend();
+}
+
+} // namespace of mcld
+
+//=============================
+// Force static initialization.
+extern "C" void LLVMInitializeARMLDBackend() {
+  // Register the linker backend
+  mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend);
+}
+
diff --git a/lib/Target/ARM/ARMLDBackend.h b/lib/Target/ARM/ARMLDBackend.h
new file mode 100644
index 0000000..440d9ee
--- /dev/null
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -0,0 +1,297 @@
+//===- ARMLDBackend.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ARM_LDBACKEND_H
+#define MCLD_ARM_LDBACKEND_H
+
+#include "ARMELFDynamic.h"
+#include "ARMGOT.h"
+#include "ARMPLT.h"
+#include <mcld/LD/LDSection.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Target/OutputRelocSection.h>
+
+namespace mcld {
+
+class MCLDInfo;
+class MCLinker;
+class Output;
+class SectionMap;
+
+
+//===----------------------------------------------------------------------===//
+/// ARMGNULDBackend - linker backend of ARM target of GNU ELF format
+///
+class ARMGNULDBackend : public GNULDBackend
+{
+public:
+  ARMGNULDBackend();
+  ~ARMGNULDBackend();
+public:
+  typedef std::vector<llvm::ELF::Elf32_Dyn*> ELF32DynList;
+
+  /** \enum ReservedEntryType
+   *  \brief The reserved entry type of reserved space in ResolveInfo.
+   *
+   *  This is used for sacnRelocation to record what kinds of entries are
+   *  reserved for this resolved symbol
+   *
+   *  In ARM, there are three kinds of entries, GOT, PLT, and dynamic reloction.
+   *  GOT may needs a corresponding relocation to relocate itself, so we
+   *  separate GOT to two situations: GOT and GOTRel. Besides, for the same
+   *  symbol, there might be two kinds of entries reserved for different location.
+   *  For example, reference to the same symbol, one may use GOT and the other may
+   *  use dynamic relocation.
+   *
+   *  bit:  3       2      1     0
+   *   | PLT | GOTRel | GOT | Rel |
+   *
+   *  value    Name         - Description
+   *
+   *  0000     None         - no reserved entry
+   *  0001     ReserveRel   - reserve an dynamic relocation entry
+   *  0010     ReserveGOT   - reserve an GOT entry
+   *  0011     GOTandRel    - For different relocation, we've reserved GOT and
+   *                          Rel for different location.
+   *  0100     GOTRel       - reserve an GOT entry and the corresponding Dyncamic
+   *                          relocation entry which relocate this GOT entry
+   *  0101     GOTRelandRel - For different relocation, we've reserved GOTRel
+   *                          and relocation entry for different location.
+   *  1000     ReservePLT   - reserve an PLT entry and the corresponding GOT,
+   *                          Dynamic relocation entries
+   *  1001     PLTandRel    - For different relocation, we've reserved PLT and
+   *                          Rel for different location.
+   */
+  enum ReservedEntryType {
+    None         = 0,
+    ReserveRel   = 1,
+    ReserveGOT   = 2,
+    GOTandRel    = 3,
+    GOTRel       = 4,
+    GOTRelandRel = 5,
+    ReservePLT   = 8,
+    PLTandRel    = 9
+  };
+
+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
+  RelocationFactory* getRelocFactory();
+
+  /// scanRelocation - determine the empty entries are needed or not and create
+  /// the empty entries if needed.
+  /// For ARM, following entries are check to create:
+  /// - GOT entry (for .got section)
+  /// - PLT entry (for .plt section)
+  /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
+  void scanRelocation(Relocation& pReloc,
+                      const LDSymbol& pInputSym,
+                      MCLinker& pLinker,
+                      const MCLDInfo& pLDInfo,
+                      const Output& pOutput);
+
+  uint32_t machine() const
+  { return llvm::ELF::EM_ARM; }
+
+  /// OSABI - the value of e_ident[EI_OSABI]
+  virtual uint8_t OSABI() const
+  { return llvm::ELF::ELFOSABI_NONE; }
+
+  /// ABIVersion - the value of e_ident[EI_ABIVRESION]
+  virtual uint8_t ABIVersion() const
+  { return 0x0; }
+
+  /// flags - the value of ElfXX_Ehdr::e_flags
+  virtual uint64_t flags() const
+  { return (llvm::ELF::EF_ARM_EABIMASK & 0x05000000); }
+
+  bool isLittleEndian() const
+  { return true; }
+
+  unsigned int bitclass() const
+  { return 32; }
+
+  /// doPreLayout - Backend can do any needed modification before layout
+  void doPreLayout(const Output& pOutput,
+                   const MCLDInfo& pInfo,
+                   MCLinker& pLinker);
+
+  /// doPostLayout -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.
+  ARMELFDynamic& dynamic();
+
+  /// dynamic - the dynamic section of the target machine.
+  /// Use co-variant return type to return its own dynamic section.
+  const ARMELFDynamic& 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;
+
+  ARMGOT& getGOT();
+
+  const ARMGOT& getGOT() const;
+
+  ARMPLT& getPLT();
+
+  const ARMPLT& getPLT() const;
+
+  OutputRelocSection& getRelDyn();
+
+  const OutputRelocSection& getRelDyn() const;
+
+  OutputRelocSection& getRelPLT();
+
+  const OutputRelocSection& getRelPLT() 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;
+
+  /// readSection - read target dependent sections
+  bool readSection(Input& pInput,
+                   MCLinker& pLinker,
+                   LDSection& pInputSectHdr);
+
+public:
+  bool isSymbolPreemptible(const ResolveInfo& pSym,
+                           const MCLDInfo& pLDInfo,
+                           const Output& pOutput) const;
+
+  bool isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const;
+
+private:
+  void scanLocalReloc(Relocation& pReloc,
+                      const LDSymbol& pInputSym,
+                      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(const ResolveInfo& pSym,
+                        const MCLDInfo& pLDInfo,
+                        const Output& pOutput) const;
+
+  bool isSymbolNeedsDynRel(const ResolveInfo& pSym,
+                           const Output& pOutput,
+                           bool isAbsReloc) const;
+
+
+  void checkValidReloc(Relocation& pReloc,
+                       const MCLDInfo& pLDInfo,
+                       const Output& pOutput) const;
+
+  /// updateAddend - update addend value of the relocation if the
+  /// the target symbol is a section symbol. Addend is the offset
+  /// in the section. This value should be updated after section
+  /// merged.
+  void updateAddend(Relocation& pReloc,
+                    const LDSymbol& pInputSym,
+                    const Layout& pLayout) const;
+
+  void createARMGOT(MCLinker& pLinker, const Output& pOutput);
+
+  /// createARMPLTandRelPLT - create PLT and RELPLT sections.
+  /// Because in ELF sh_info in .rel.plt is the shndx of .plt, these two
+  /// sections should be create together.
+  void createARMPLTandRelPLT(MCLinker& pLinker, const Output& pOutput);
+
+  void createARMRelDyn(MCLinker& pLinker, const Output& pOutput);
+
+  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
+
+private:
+  RelocationFactory* m_pRelocFactory;
+  ARMGOT* m_pGOT;
+  ARMPLT* m_pPLT;
+  /// m_RelDyn - dynamic relocation table of .rel.dyn
+  OutputRelocSection* m_pRelDyn;
+  /// m_RelPLT - dynamic relocation table of .rel.plt
+  OutputRelocSection* m_pRelPLT;
+
+  ARMELFDynamic* m_pDynamic;
+  LDSymbol* m_pGOTSymbol;
+
+  //     variable name           :  ELF
+  LDSection* m_pEXIDX;           // .ARM.exidx
+  LDSection* m_pEXTAB;           // .ARM.extab
+  LDSection* m_pAttributes;      // .ARM.attributes
+//  LDSection* m_pPreemptMap;      // .ARM.preemptmap
+//  LDSection* m_pDebugOverlay;    // .ARM.debug_overlay
+//  LDSection* m_pOverlayTable;    // .ARM.overlay_table
+};
+
+//===----------------------------------------------------------------------===//
+/// ARMMachOLDBackend - linker backend of ARM target of MachO format
+///
+/**
+class ARMMachOLDBackend : public DarwinARMLDBackend
+{
+public:
+  ARMMachOLDBackend();
+  ~ARMMachOLDBackend();
+
+private:
+  MCMachOTargetArchiveReader *createTargetArchiveReader() const;
+  MCMachOTargetObjectReader *createTargetObjectReader() const;
+  MCMachOTargetObjectWriter *createTargetObjectWriter() const;
+
+};
+**/
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
new file mode 100644
index 0000000..3a79b52
--- /dev/null
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -0,0 +1,250 @@
+//===- ARMPLT.cpp -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMGOT.h"
+#include "ARMPLT.h"
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <new>
+
+namespace {
+
+const uint32_t arm_plt0[] = {
+  0xe52de004, // str   lr, [sp, #-4]!
+  0xe59fe004, // ldr   lr, [pc, #4]
+  0xe08fe00e, // add   lr, pc, lr
+  0xe5bef008, // ldr   pc, [lr, #8]!
+  0x00000000, // &GOT[0] - .
+};
+
+const uint32_t arm_plt1[] = {
+  0xe28fc600, // add   ip, pc, #0xNN00000
+  0xe28cca00, // add   ip, ip, #0xNN000
+  0xe5bcf000, // ldr   pc, [ip, #0xNNN]!
+};
+
+} // anonymous namespace
+
+using namespace mcld;
+
+ARMPLT0::ARMPLT0(llvm::MCSectionData* pParent)
+  : PLTEntry(sizeof(arm_plt0), pParent) {}
+
+ARMPLT1::ARMPLT1(llvm::MCSectionData* pParent)
+  : PLTEntry(sizeof(arm_plt1), pParent) {}
+
+//===----------------------------------------------------------------------===//
+// ARMPLT
+
+ARMPLT::ARMPLT(LDSection& pSection,
+               llvm::MCSectionData& pSectionData,
+               ARMGOT &pGOTPLT)
+  : PLT(pSection, pSectionData), m_GOT(pGOTPLT), m_PLTEntryIterator() {
+  ARMPLT0* plt0_entry = new ARMPLT0(&m_SectionData);
+
+  m_Section.setSize(m_Section.size() + plt0_entry->getEntrySize());
+
+  m_PLTEntryIterator = pSectionData.begin();
+}
+
+ARMPLT::~ARMPLT()
+{
+}
+
+void ARMPLT::reserveEntry(size_t pNum)
+{
+  ARMPLT1* plt1_entry = 0;
+
+  for (size_t i = 0; i < pNum; ++i) {
+    plt1_entry = new (std::nothrow) ARMPLT1(&m_SectionData);
+
+    if (!plt1_entry)
+      llvm::report_fatal_error("Allocating new memory for ARMPLT1 failed!");
+
+    m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
+
+    m_GOT.reserveGOTPLTEntry();
+  }
+}
+
+PLTEntry* ARMPLT::getPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+{
+   ARMPLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
+
+   pExist = 1;
+
+   if (!PLTEntry) {
+     GOTEntry *&GOTPLTEntry = m_GOT.lookupGOTPLTMap(pSymbol);
+     assert(!GOTPLTEntry && "PLT entry and got.plt entry doesn't match!");
+
+     pExist = 0;
+
+     // This will skip PLT0.
+     ++m_PLTEntryIterator;
+     assert(m_PLTEntryIterator != m_SectionData.end() &&
+            "The number of PLT Entries and ResolveInfo doesn't match");
+
+     ARMGOT::iterator got_it = m_GOT.getNextGOTPLTEntry();
+     ARMGOT::iterator got_ie = m_GOT.getGOTPLTEnd();
+     assert(got_it != got_ie && "The number of GOTPLT and PLT doesn't match");
+
+     PLTEntry = llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
+     GOTPLTEntry = llvm::cast<GOTEntry>(&(*got_it));
+   }
+
+   return PLTEntry;
+}
+
+GOTEntry* ARMPLT::getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+{
+   GOTEntry *&GOTPLTEntry = m_GOT.lookupGOTPLTMap(pSymbol);
+
+   pExist = 1;
+
+   if (!GOTPLTEntry) {
+     ARMPLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
+     assert(!PLTEntry && "PLT entry and got.plt entry doesn't match!");
+
+     pExist = 0;
+
+     // This will skip PLT0.
+     ++m_PLTEntryIterator;
+     assert(m_PLTEntryIterator != m_SectionData.end() &&
+            "The number of PLT Entries and ResolveInfo doesn't match");
+
+     ARMGOT::iterator got_it = m_GOT.getNextGOTPLTEntry();
+     ARMGOT::iterator got_ie = m_GOT.getGOTPLTEnd();
+     assert(got_it != got_ie && "The number of GOTPLT and PLT doesn't match");
+
+     PLTEntry = llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
+     GOTPLTEntry = llvm::cast<GOTEntry>(&(*got_it));
+   }
+
+   return GOTPLTEntry;
+}
+
+ARMPLT0* ARMPLT::getPLT0() const {
+
+  iterator first = m_SectionData.getFragmentList().begin();
+  iterator end = m_SectionData.getFragmentList().end();
+
+  assert(first!=end && "FragmentList is empty, getPLT0 failed!");
+
+  ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
+
+  return plt0;
+}
+
+void ARMPLT::applyPLT0() {
+
+  uint64_t plt_base = m_Section.addr();
+  assert(plt_base && ".plt base address is NULL!");
+
+  uint64_t got_base = m_GOT.getSection().addr();
+  assert(got_base && ".got base address is NULL!");
+
+  uint32_t offset = 0;
+
+  if (got_base > plt_base)
+    offset = got_base - (plt_base + 16);
+  else
+    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!");
+
+  ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
+
+  uint32_t* data = 0;
+  data = static_cast<uint32_t*>(malloc(plt0->getEntrySize()));
+
+  if (!data)
+    llvm::report_fatal_error("Allocating new memory for plt0 failed!");
+
+  memcpy(data, arm_plt0, plt0->getEntrySize());
+  data[4] = offset;
+
+  plt0->setContent(reinterpret_cast<unsigned char*>(data));
+}
+
+void ARMPLT::applyPLT1() {
+
+  uint64_t plt_base = m_Section.addr();
+  assert(plt_base && ".plt base address is NULL!");
+
+  uint64_t got_base = m_GOT.getSection().addr();
+  assert(got_base && ".got base address is NULL!");
+
+  ARMPLT::iterator it = m_SectionData.begin();
+  ARMPLT::iterator ie = m_SectionData.end();
+  assert(it!=ie && "FragmentList is empty, applyPLT1 failed!");
+
+  uint32_t GOTEntrySize = m_GOT.getEntrySize();
+  uint32_t GOTEntryAddress =
+    got_base +  GOTEntrySize * 3;
+
+  uint64_t PLTEntryAddress =
+    plt_base + llvm::cast<ARMPLT0>((*it)).getEntrySize(); //Offset of PLT0
+
+  ++it; //skip PLT0
+  uint64_t PLT1EntrySize = llvm::cast<ARMPLT1>((*it)).getEntrySize();
+  ARMPLT1* plt1 = NULL;
+
+  uint32_t* Out = NULL;
+  while (it != ie) {
+    plt1 = &(llvm::cast<ARMPLT1>(*it));
+    Out = static_cast<uint32_t*>(malloc(plt1->getEntrySize()));
+
+    if (!Out)
+      llvm::report_fatal_error("Allocating new memory for plt1 failed!");
+
+    // Offset is the distance between the last PLT entry and the associated
+    // GOT entry.
+    int32_t Offset = (GOTEntryAddress - (PLTEntryAddress + 8));
+
+    Out[0] = arm_plt1[0] | ((Offset >> 20) & 0xFF);
+    Out[1] = arm_plt1[1] | ((Offset >> 12) & 0xFF);
+    Out[2] = arm_plt1[2] | (Offset & 0xFFF);
+
+    plt1->setContent(reinterpret_cast<unsigned char*>(Out));
+    ++it;
+
+    GOTEntryAddress += GOTEntrySize;
+    PLTEntryAddress += PLT1EntrySize;
+  }
+
+  m_GOT.applyAllGOTPLT(plt_base);
+}
+
+uint64_t ARMPLT::emit(MemoryRegion& pRegion)
+{
+  uint64_t result = 0x0;
+  iterator it = begin();
+  unsigned int plt0_size = llvm::cast<ARMPLT0>((*it)).getEntrySize();
+
+  unsigned char* buffer = pRegion.getBuffer();
+  memcpy(buffer, llvm::cast<ARMPLT0>((*it)).getContent(), plt0_size);
+  result += plt0_size;
+  ++it;
+
+  ARMPLT1* plt1 = 0;
+  ARMPLT::iterator ie = end();
+  unsigned int entry_size = 0;
+  while (it != ie) {
+    plt1 = &(llvm::cast<ARMPLT1>(*it));
+    entry_size = plt1->getEntrySize();
+    memcpy(buffer + result, plt1->getContent(), entry_size);
+    result += entry_size;
+    ++it;
+  }
+  return result;
+}
+
diff --git a/lib/Target/ARM/ARMPLT.h b/lib/Target/ARM/ARMPLT.h
new file mode 100644
index 0000000..f55aaa3
--- /dev/null
+++ b/lib/Target/ARM/ARMPLT.h
@@ -0,0 +1,87 @@
+//===- ARMPLT.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ARM_PLT_H
+#define MCLD_ARM_PLT_H
+
+#include <mcld/Target/PLT.h>
+
+namespace mcld {
+
+class ARMGOT;
+class GOTEntry;
+class MemoryRegion;
+
+class ARMPLT0 : public PLTEntry {
+public:
+  ARMPLT0(llvm::MCSectionData* pParent);
+};
+
+class ARMPLT1 : public PLTEntry {
+public:
+  ARMPLT1(llvm::MCSectionData* pParent);
+};
+
+/** \class ARMPLT
+ *  \brief ARM Procedure Linkage Table
+ */
+class ARMPLT : public PLT
+{
+  typedef llvm::DenseMap<const ResolveInfo*, ARMPLT1*> SymbolIndexType;
+
+public:
+  typedef llvm::MCSectionData::iterator iterator;
+  typedef llvm::MCSectionData::const_iterator const_iterator;
+
+public:
+  ARMPLT(LDSection& pSection,
+         llvm::MCSectionData& pSectionData,
+         ARMGOT& pGOTPLT);
+  ~ARMPLT();
+
+// Override virtual function.
+public:
+
+  // reserveEntry is ARMGOT friend function.
+  void reserveEntry(size_t pNum = 1) ;
+
+  PLTEntry* getPLTEntry(const ResolveInfo& pSymbol, bool& pExist) ;
+
+  GOTEntry* getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist);
+
+public:
+  iterator begin() { return m_SectionData.begin(); }
+
+  const_iterator begin() const { return m_SectionData.begin(); }
+
+  iterator end() { return m_SectionData.end(); }
+
+  const_iterator end() const { return m_SectionData.end(); }
+
+  ARMPLT0* getPLT0() const;
+
+  void applyPLT0();
+
+  void applyPLT1();
+
+  uint64_t emit(MemoryRegion& pRegion);
+
+private:
+  ARMGOT& m_GOT;
+
+  // Used by getEntry() for mapping a ResolveInfo
+  // instance to a PLT1 Entry.
+  iterator m_PLTEntryIterator;
+
+  SymbolIndexType m_PLTEntryMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMRelocationFactory.cpp b/lib/Target/ARM/ARMRelocationFactory.cpp
new file mode 100644
index 0000000..2763b3b
--- /dev/null
+++ b/lib/Target/ARM/ARMRelocationFactory.cpp
@@ -0,0 +1,861 @@
+//===- ARMRelocationFactory.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/ErrorHandling.h>
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/ELF.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LD/Layout.h>
+
+#include "ARMRelocationFactory.h"
+#include "ARMRelocationFunctions.h"
+
+using namespace mcld;
+
+DECL_ARM_APPLY_RELOC_FUNCS
+
+//===--------------------------------------------------------------------===//
+// ARMRelocationFactory
+ARMRelocationFactory::ARMRelocationFactory(size_t pNum,
+                                           ARMGNULDBackend& pParent)
+  : RelocationFactory(pNum),
+    m_Target(pParent) {
+}
+
+ARMRelocationFactory::~ARMRelocationFactory()
+{
+}
+
+void ARMRelocationFactory::applyRelocation(Relocation& pRelocation,
+                                           const MCLDInfo& pLDInfo)
+{
+  Relocation::Type type = pRelocation.type();
+  if (type > 130) { // 131-255 doesn't noted in ARM spec
+    llvm::report_fatal_error(llvm::Twine("Unknown relocation type. "
+                                         "To symbol `") +
+                             pRelocation.symInfo()->name() +
+                             llvm::Twine("'."));
+    return;
+  }
+
+  /// 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) {
+    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;
+  }
+  if (Unsupport == result) {
+    llvm::report_fatal_error(llvm::Twine("Encounter unsupported relocation `") +
+                             llvm::Twine(apply_functions[type].name) +
+                             llvm::Twine("' on symbol: `") +
+                             llvm::Twine(pRelocation.symInfo()->name()) +
+                             llvm::Twine("'."));
+    return;
+  }
+}
+
+
+
+//===--------------------------------------------------------------------===//
+// non-member functions
+static RelocationFactory::DWord getThumbBit(const Relocation& pReloc)
+{
+  // Set thumb bit if
+  // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
+  RelocationFactory::DWord thumbBit =
+       ((pReloc.symInfo()->desc() != ResolveInfo::Undefined) &&
+        (pReloc.symInfo()->type() == ResolveInfo::Function) &&
+        ((pReloc.symValue() & 0x1) != 0))?
+        1:0;
+  return thumbBit;
+}
+
+
+
+
+//=========================================//
+// Relocation helper function              //
+//=========================================//
+
+// Using uint64_t to make sure those complicate operations won't cause
+// undefined behavior.
+static
+uint64_t helper_sign_extend(uint64_t pVal, uint64_t pOri_width)
+{
+  assert(pOri_width <= 64);
+  uint64_t sign_bit = 1 << (pOri_width - 1);
+  return (pVal ^ sign_bit) - sign_bit;
+  // Reverse sign bit, then subtract sign bit.
+}
+
+static
+uint64_t helper_bit_select(uint64_t pA, uint64_t pB, uint64_t pMask)
+{
+  return (pA & ~pMask) | (pB & pMask) ;
+}
+
+// Check if symbol can use relocation R_ARM_RELATIVE
+static bool
+helper_use_relative_reloc(const ResolveInfo& pSym,
+                          const MCLDInfo& pLDInfo,
+                          const ARMRelocationFactory& pFactory)
+{
+  // if symbol is dynamic or undefine or preemptible
+  if(pSym.isDyn() ||
+     pSym.isUndef() ||
+     pFactory.getTarget().isSymbolPreemptible(pSym,
+                                              pLDInfo,
+                                              pLDInfo.output()))
+    return false;
+  return true;
+}
+
+static
+GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
+                                  const MCLDInfo& pLDInfo,
+                                  ARMRelocationFactory& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMGNULDBackend& ld_backend = pParent.getTarget();
+
+  bool exist;
+  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
+  if (!exist) {
+    // If we first get this GOT entry, we should initialize it.
+    if (rsym->reserved() & ARMGNULDBackend::ReserveGOT) {
+      // No corresponding dynamic relocation, initialize to the symbol value.
+      got_entry.setContent(pReloc.symValue());
+    }
+    else if (rsym->reserved() & ARMGNULDBackend::GOTRel) {
+
+      // Initialize corresponding dynamic relocation.
+      Relocation& rel_entry =
+        *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
+      assert(!exist && "GOT entry not exist, but DynRel entry exist!");
+      if( rsym->isLocal() ||
+          helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+        // Initialize got entry to target symbol address
+        got_entry.setContent(pReloc.symValue());
+        rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
+        rel_entry.setSymInfo(0);
+      }
+      else {
+        // Initialize got entry to 0 for corresponding dynamic relocation.
+        got_entry.setContent(0);
+        rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
+        rel_entry.setSymInfo(rsym);
+      }
+      rel_entry.targetRef().assign(got_entry);
+    }
+    else {
+      llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+    }
+  }
+  return got_entry;
+}
+
+static
+ARMRelocationFactory::Address helper_GOT_ORG(ARMRelocationFactory& pParent)
+{
+  return pParent.getTarget().getGOT().getSection().addr();
+}
+
+
+static
+ARMRelocationFactory::Address helper_GOT(Relocation& pReloc,
+                                         const MCLDInfo& pLDInfo,
+                                         ARMRelocationFactory& pParent)
+{
+  GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo, pParent);
+  return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry);
+}
+
+
+static
+PLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
+                                  ARMRelocationFactory& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMGNULDBackend& ld_backend = pParent.getTarget();
+
+  bool exist;
+  PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
+  if (!exist) {
+    // If we first get this PLT entry, we should initialize it.
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      GOTEntry& gotplt_entry =
+        *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
+      // Initialize corresponding dynamic relocation.
+      Relocation& rel_entry =
+        *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
+      assert(!exist && "PLT entry not exist, but DynRel entry exist!");
+      rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
+      rel_entry.targetRef().assign(gotplt_entry);
+      rel_entry.setSymInfo(rsym);
+    }
+    else {
+      llvm::report_fatal_error("No PLT entry reserved for PLT type relocation!");
+    }
+  }
+  return plt_entry;
+}
+
+
+
+static
+ARMRelocationFactory::Address helper_PLT_ORG(ARMRelocationFactory& pParent)
+{
+  return pParent.getTarget().getPLT().getSection().addr();
+}
+
+
+static
+ARMRelocationFactory::Address helper_PLT(Relocation& pReloc,
+                                         ARMRelocationFactory& pParent)
+{
+  PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
+  return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry);
+}
+
+// Get an relocation entry in .rel.dyn and set its type to pType,
+// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo()
+static
+void helper_DynRel(Relocation& pReloc,
+                   ARMRelocationFactory::Type pType,
+                   ARMRelocationFactory& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMGNULDBackend& ld_backend = pParent.getTarget();
+  bool exist;
+
+  Relocation& rel_entry =
+    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
+  rel_entry.setType(pType);
+  rel_entry.targetRef() = pReloc.targetRef();
+
+  if(pType == llvm::ELF::R_ARM_RELATIVE)
+    rel_entry.setSymInfo(0);
+  else
+    rel_entry.setSymInfo(rsym);
+}
+
+static ARMRelocationFactory::DWord
+helper_extract_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
+{
+  // imm16: [19-16][11-0]
+  return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU),
+                            16);
+}
+
+static ARMRelocationFactory::DWord
+helper_insert_val_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
+                                 ARMRelocationFactory::DWord pImm)
+{
+  // imm16: [19-16][11-0]
+  pTarget &= 0xfff0f000U;
+  pTarget |= pImm & 0x0fffU;
+  pTarget |= (pImm & 0xf000U) << 4;
+  return pTarget;
+}
+
+static ARMRelocationFactory::DWord
+helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
+{
+  // TODO: By the rsloader experience: If we use 32bit, we need to consider
+  // endianness problem. We'd better have a thumb instruction type.
+  // imm16: [19-16][26][14-12][7-0]
+  return helper_sign_extend((((pTarget >> 4) & 0xf000U) |
+                             ((pTarget >> 15) & 0x0800U) |
+                             ((pTarget >> 4) & 0x0700U) |
+                             (pTarget & 0x00ffU)),
+                            16);
+}
+
+static ARMRelocationFactory::DWord
+helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
+                                       ARMRelocationFactory::DWord pImm)
+{
+  // TODO: By the rsloader experience: If we use 32bit, we need to consider
+  // endianness problem. We'd better have a thumb instruction type.
+  // imm16: [19-16][26][14-12][7-0]
+  pTarget &= 0xfbf08f00U;
+  pTarget |= (pImm & 0xf000U) << 4;
+  pTarget |= (pImm & 0x0800U) << 15;
+  pTarget |= (pImm & 0x0700U) << 4;
+  pTarget |= (pImm & 0x00ffU);
+  return pTarget;
+}
+
+static ARMRelocationFactory::DWord
+helper_thumb32_branch_offset(ARMRelocationFactory::DWord pUpper16,
+                             ARMRelocationFactory::DWord pLower16)
+{
+  ARMRelocationFactory::DWord s = (pUpper16 & (1U << 10)) >> 10,  // 26 bit
+                              u = pUpper16 & 0x3ffU,              // 25-16
+                              l = pLower16 & 0x7ffU,              // 10-0
+                             j1 = (pLower16 & (1U << 13)) >> 13,  // 13
+                             j2 = (pLower16 & (1U << 11)) >> 11;  // 11
+  ARMRelocationFactory::DWord i1 = j1 ^ s? 0: 1,
+                              i2 = j2 ^ s? 0: 1;
+
+  // [31-25][24][23][22][21-12][11-1][0]
+  //      0   s  i1  i2      u     l  0
+  return helper_sign_extend((s << 24) | (i1 << 23) | (i2 << 22) |
+                            (u << 12) | (l << 1),
+                            25);
+}
+
+static ARMRelocationFactory::DWord
+helper_thumb32_branch_upper(ARMRelocationFactory::DWord pUpper16,
+                            ARMRelocationFactory::DWord pOffset)
+{
+  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
+  return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10);
+}
+
+static ARMRelocationFactory::DWord
+helper_thumb32_branch_lower(ARMRelocationFactory::DWord pLower16,
+                            ARMRelocationFactory::DWord pOffset)
+{
+  uint32_t sign = ((pOffset & 0x80000000U) >> 31);
+  return ((pLower16 & ~0x2fffU) |
+          ((((pOffset >> 23) & 1) ^ !sign) << 13) |
+          ((((pOffset >> 22) & 1) ^ !sign) << 11) |
+          ((pOffset >> 1) & 0x7ffU));
+}
+
+// Return true if overflow
+static bool
+helper_check_signed_overflow(ARMRelocationFactory::DWord pValue,
+                             unsigned bits)
+{
+  int32_t signed_val = static_cast<int32_t>(pValue);
+  int32_t max = (1 << (bits - 1)) - 1;
+  int32_t min = -(1 << (bits - 1));
+  if (signed_val > max || signed_val < min) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+
+//=========================================//
+// Each relocation function implementation //
+//=========================================//
+
+// R_ARM_NONE
+ARMRelocationFactory::Result none(Relocation& pReloc,
+                                  const MCLDInfo& pLDInfo,
+                                  ARMRelocationFactory& pParent)
+{
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_ABS32: (S + A) | T
+ARMRelocationFactory::Result abs32(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   ARMRelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  ARMRelocationFactory::DWord S = pReloc.symValue();
+
+  if(rsym->isLocal() && (rsym->reserved() & 0x1u)) {
+    helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
+    pReloc.target() = (S + A) | T ;
+    return ARMRelocationFactory::OK;
+  }
+  else if(!rsym->isLocal()) {
+    if(rsym->reserved() & 0x8u) {
+      S = helper_PLT(pReloc, pParent);
+      T = 0 ; // PLT is not thumb
+      pReloc.target() = (S + A) | T;
+    }
+    // If we generate a dynamic relocation (except R_ARM_RELATIVE)
+    // for a place, we should not perform static relocation on it
+    // in order to keep the addend store in the place correct.
+    if(rsym->reserved() & 0x1u) {
+      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+        helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
+      }
+      else {
+        helper_DynRel(pReloc, pReloc.type(), pParent);
+        return ARMRelocationFactory::OK;
+      }
+    }
+  }
+
+  // perform static relocation
+  pReloc.target() = (S + A) | T;
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_REL32: ((S + A) | T) - P
+ARMRelocationFactory::Result rel32(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   ARMRelocationFactory& pParent)
+{
+  // perform static relocation
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  pReloc.target() = ((pReloc.symValue() + A) | T)
+      - pReloc.place(pParent.getLayout());
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_BASE_PREL: B(S) + A - P
+ARMRelocationFactory::Result base_prel(Relocation& pReloc,
+                                       const MCLDInfo& pLDInfo,
+                                       ARMRelocationFactory& pParent)
+{
+  // perform static relocation
+  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  pReloc.target() = pReloc.symValue() + A - pReloc.place(pParent.getLayout());
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG
+ARMRelocationFactory::Result gotoff32(Relocation& pReloc,
+                                      const MCLDInfo& pLDInfo,
+                                      ARMRelocationFactory& pParent)
+{
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
+  ARMRelocationFactory::Address S = pReloc.symValue();
+
+  pReloc.target() = ((S + A) | T) - GOT_ORG;
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
+ARMRelocationFactory::Result got_brel(Relocation& pReloc,
+                                      const MCLDInfo& pLDInfo,
+                                      ARMRelocationFactory& pParent)
+{
+  if(!(pReloc.symInfo()->reserved() & 0x6u)) {
+    return ARMRelocationFactory::BadReloc;
+  }
+  ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
+  ARMRelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
+  ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
+  // Apply relocation.
+  pReloc.target() = GOT_S + A - GOT_ORG;
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_GOT_PREL: GOT(S) + A - P
+ARMRelocationFactory::Result got_prel(Relocation& pReloc,
+                                      const MCLDInfo& pLDInfo,
+                                      ARMRelocationFactory& pParent)
+{
+  if(!(pReloc.symInfo()->reserved() & 0x6u)) {
+    return ARMRelocationFactory::BadReloc;
+  }
+  ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
+  ARMRelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
+  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+  // Apply relocation.
+  pReloc.target() = GOT_S + A - P;
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_PLT32: ((S + A) | T) - P
+// R_ARM_JUMP24: ((S + A) | T) - P
+// R_ARM_CALL: ((S + A) | T) - P
+ARMRelocationFactory::Result call(Relocation& pReloc,
+                                  const MCLDInfo& pLDInfo,
+                                  ARMRelocationFactory& pParent)
+{
+  // TODO: Some issue have not been considered, e.g. thumb, overflow?
+
+  // If target is undefined weak symbol, we only need to jump to the
+  // next instruction unless it has PLT entry.
+  if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() &&
+      !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
+    // change target to NOP : mov r0, r0
+    pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000;
+    return ARMRelocationFactory::OK;
+  }
+
+  ARMRelocationFactory::Address S; // S dependent on exist PLT or not.
+  ARMRelocationFactory::DWord   T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord   A =
+    helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26)
+    + pReloc.addend();
+  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+
+  S = pReloc.symValue();
+  if( pReloc.symInfo()->reserved() & 0x8u) {
+    S = helper_PLT(pReloc, pParent);
+    T = 0;  // PLT is not thumb.
+  }
+
+  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
+
+  if (X & 0x03u) {  // Lowest two bit is not zero.
+    llvm::report_fatal_error("Target is thumb, need stub!");
+  }
+  // Check X is 24bit sign int. If not, we should use stub or PLT before apply.
+  assert(!helper_check_signed_overflow(X, 26) && "Jump or Call target too far!");
+  //                    Make sure the Imm is 0.          Result Mask.
+  pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2);
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_THM_CALL: ((S + A) | T) - P
+ARMRelocationFactory::Result thm_call(Relocation& pReloc,
+                                      const MCLDInfo& pLDInfo,
+                                      ARMRelocationFactory& pParent)
+{
+  // If target is undefined weak symbol, we only need to jump to the
+  // next instruction unless it has PLT entry.
+  if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() &&
+      !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
+    pReloc.target() = (0xe000U << 16) | 0xbf00U;
+    return ARMRelocationFactory::OK;
+  }
+
+  // TODO: By the rsloader experience: If we use 32bit, we need to consider
+  // endianness problem. Here is an ugly solution. We'd better have a thumb
+  // instruction type.
+  //uint16_t upper16 = *(
+  //    reinterpret_cast<uint16_t*>(&pReloc.target())
+  //  ),
+  //         lower16 = *(
+  //    reinterpret_cast<uint16_t*>(&pReloc.target()) + 1
+  //  );
+  ARMRelocationFactory::DWord upper16 = ((pReloc.target() & 0xffff0000U) >> 16),
+                              lower16 = (pReloc.target() & 0xffffU);
+
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper16,
+                                                               lower16);
+  ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::Address S;
+
+  S = pReloc.symValue();
+  // if symbol has plt
+  if( pReloc.symInfo()->reserved() & 0x8u) {
+    S = helper_PLT(pReloc, pParent);
+    T = 0;  // PLT is not thumb.
+  }
+
+  // TODO: If the target is not thumb, we should rewrite instruction to BLX.
+
+  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
+  X >>= 1;
+
+  // FIXME: Check bit size is 24(thumb2) or 22?
+  if (helper_check_signed_overflow(X, 24)) {
+    assert(!"Offset is too far. We need stub or PLT for it.");
+    return ARMRelocationFactory::Overflow;
+  }
+
+  // For a BLX instruction, make sure that the relocation is rounded up
+  // to a word boundary. This follows the semantics of the instruction
+  // which specifies that bit 1 of the target address will come from bit
+  // 1 of the base address.
+  if ((X & 0x5000U) == 0x4000U) {
+    X = (X + 2) & ~0x3U;
+  }
+
+  upper16 = helper_thumb32_branch_upper(upper16, X);
+  lower16 = helper_thumb32_branch_lower(lower16, X);
+
+  // TODO: By the rsloader experience: If we use 32bit, we need to consider
+  // endianness problem. Here is an ugly solution. We'd better have a thumb
+  // instruction type.
+  //*(reinterpret_cast<uint16_t*>(&preloc.target())) = upper16;
+  //*(reinterpret_cast<uint16_t*>(&preloc.target()) + 1) = lower16;
+  pReloc.target() = (upper16 << 16);
+  pReloc.target() |= lower16;
+
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_MOVW_ABS_NC: (S + A) | T
+ARMRelocationFactory::Result movw_abs_nc(Relocation& pReloc,
+                                         const MCLDInfo& pLDInfo,
+                                         ARMRelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord A =
+      helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  // use plt
+  if(rsym->reserved() & 0x8u) {
+    S = helper_PLT(pReloc, pParent);
+    T = 0 ; // PLT is not thumb
+  }
+  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;
+  }
+}
+
+// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
+ARMRelocationFactory::Result movw_prel_nc(Relocation& pReloc,
+                                          const MCLDInfo& pLDInfo,
+                                          ARMRelocationFactory& pParent)
+{
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord A =
+      helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  X = ((S + A) | T) - P;
+
+  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;
+  }
+}
+
+// R_ARM_MOVT_ABS: S + A
+ARMRelocationFactory::Result movt_abs(Relocation& pReloc,
+                                      const MCLDInfo& pLDInfo,
+                                      ARMRelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord A =
+    helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  // use plt
+  if(rsym->reserved() & 0x8u) {
+    S = helper_PLT(pReloc, pParent);
+  }
+
+  X = S + A;
+  X >>= 16;
+  // perform static relocation
+  pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_MOVT_PREL: S + A - P
+ARMRelocationFactory::Result movt_prel(Relocation& pReloc,
+                                       const MCLDInfo& pLDInfo,
+                                       ARMRelocationFactory& pParent)
+{
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord A =
+      helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  X = S + A - P;
+  X >>= 16;
+
+  pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_THM_MOVW_ABS_NC: (S + A) | T
+ARMRelocationFactory::Result thm_movw_abs_nc(Relocation& pReloc,
+                                             const MCLDInfo& pLDInfo,
+                                             ARMRelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord A =
+      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  // use plt
+  if(rsym->reserved() & 0x8u) {
+    S = helper_PLT(pReloc, pParent);
+    T = 0; // PLT is not thumb
+  }
+  X = (S + A) | T;
+  // check 16-bit overflow
+  if (helper_check_signed_overflow(X, 16)) {
+    return ARMRelocationFactory::Overflow;
+  } else {
+    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                             X);
+    return ARMRelocationFactory::OK;
+  }
+}
+
+// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
+ARMRelocationFactory::Result thm_movw_prel_nc(Relocation& pReloc,
+                                              const MCLDInfo& pLDInfo,
+                                              ARMRelocationFactory& pParent)
+{
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord A =
+      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  X = ((S + A) | T) - P;
+
+  // check 16-bit overflow
+  if (helper_check_signed_overflow(X, 16)) {
+    return ARMRelocationFactory::Overflow;
+  } else {
+    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                             X);
+    return ARMRelocationFactory::OK;
+  }
+}
+
+// R_ARM_THM_MOVT_ABS: S + A
+ARMRelocationFactory::Result thm_movt_abs(Relocation& pReloc,
+                                          const MCLDInfo& pLDInfo,
+                                          ARMRelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord A =
+      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  // use plt
+  if(rsym->reserved() & 0x8u) {
+    S = helper_PLT(pReloc, pParent);
+  }
+  X = S + A;
+  X >>= 16;
+
+  // check 16-bit overflow
+  if (helper_check_signed_overflow(X, 16)) {
+    return ARMRelocationFactory::Overflow;
+  } else {
+    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                             X);
+    return ARMRelocationFactory::OK;
+  }
+}
+
+// R_ARM_THM_MOVT_PREL: S + A - P
+ARMRelocationFactory::Result thm_movt_prel(Relocation& pReloc,
+                                           const MCLDInfo& pLDInfo,
+                                           ARMRelocationFactory& pParent)
+{
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord A =
+      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  X = S + A - P;
+  X >>= 16;
+
+  // check 16-bit overflow
+  if (helper_check_signed_overflow(X, 16)) {
+    return ARMRelocationFactory::Overflow;
+  } else {
+    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                             X);
+    return ARMRelocationFactory::OK;
+  }
+}
+
+// R_ARM_PREL31: (S + A) | T
+ARMRelocationFactory::Result prel31(Relocation& pReloc,
+                                    const MCLDInfo& pLDInfo,
+                                    ARMRelocationFactory& pParent)
+{
+  ARMRelocationFactory::DWord target = pReloc.target();
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord A = helper_sign_extend(target, 31) +
+                                  pReloc.addend();
+  ARMRelocationFactory::Address S;
+
+  S = pReloc.symValue();
+  // if symbol has plt
+  if( pReloc.symInfo()->reserved() & 0x8u) {
+    S = helper_PLT(pReloc, pParent);
+    T = 0;  // PLT is not thumb.
+  }
+
+  ARMRelocationFactory::DWord X = (S + A) | T ;
+  pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
+  if(helper_check_signed_overflow(X, 31))
+    return ARMRelocationFactory::Overflow;
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_TLS_GD32: GOT(S) + A - P
+// R_ARM_TLS_IE32: GOT(S) + A - P
+// R_ARM_TLS_LE32: S + A - tp
+ARMRelocationFactory::Result tls(Relocation& pReloc,
+                                 const MCLDInfo& pLDInfo,
+                                 ARMRelocationFactory& pParent)
+{
+  llvm::report_fatal_error("We don't support TLS relocation yet.");
+  return ARMRelocationFactory::Unsupport;
+}
+
+ARMRelocationFactory::Result unsupport(Relocation& pReloc,
+                                       const MCLDInfo& pLDInfo,
+                                       ARMRelocationFactory& pParent)
+{
+  return ARMRelocationFactory::Unsupport;
+}
diff --git a/lib/Target/ARM/ARMRelocationFactory.h b/lib/Target/ARM/ARMRelocationFactory.h
new file mode 100644
index 0000000..636dbee
--- /dev/null
+++ b/lib/Target/ARM/ARMRelocationFactory.h
@@ -0,0 +1,59 @@
+//===-  ARMRelocationFactory.h --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ARM_RELOCATION_FACTORY_H
+#define ARM_RELOCATION_FACTORY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/Target/GOT.h>
+#include "ARMLDBackend.h"
+
+namespace mcld
+{
+
+/** \class ARMRelocationFactory
+ *  \brief ARMRelocationFactory creates and destroys the ARM relocations.
+ *
+ */
+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);
+
+  ARMGNULDBackend& getTarget()
+  { return m_Target; }
+
+  const ARMGNULDBackend& getTarget() const
+  { return m_Target; }
+
+private:
+  ARMGNULDBackend& m_Target;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMRelocationFunctions.h b/lib/Target/ARM/ARMRelocationFunctions.h
new file mode 100644
index 0000000..10d27a4
--- /dev/null
+++ b/lib/Target/ARM/ARMRelocationFunctions.h
@@ -0,0 +1,169 @@
+//===- ARMRelocationFunction.h --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DECL_ARM_APPLY_RELOC_FUNC(Name) \
+static ARMRelocationFactory::Result Name    (Relocation& pEntry, \
+                                             const MCLDInfo& pLDInfo, \
+                                             ARMRelocationFactory& pParent);
+
+#define DECL_ARM_APPLY_RELOC_FUNCS \
+DECL_ARM_APPLY_RELOC_FUNC(none)             \
+DECL_ARM_APPLY_RELOC_FUNC(abs32)            \
+DECL_ARM_APPLY_RELOC_FUNC(rel32)            \
+DECL_ARM_APPLY_RELOC_FUNC(gotoff32)         \
+DECL_ARM_APPLY_RELOC_FUNC(base_prel)        \
+DECL_ARM_APPLY_RELOC_FUNC(got_brel)         \
+DECL_ARM_APPLY_RELOC_FUNC(call)             \
+DECL_ARM_APPLY_RELOC_FUNC(thm_call)         \
+DECL_ARM_APPLY_RELOC_FUNC(movw_prel_nc)     \
+DECL_ARM_APPLY_RELOC_FUNC(movw_abs_nc)      \
+DECL_ARM_APPLY_RELOC_FUNC(movt_abs)         \
+DECL_ARM_APPLY_RELOC_FUNC(movt_prel)        \
+DECL_ARM_APPLY_RELOC_FUNC(thm_movw_abs_nc)  \
+DECL_ARM_APPLY_RELOC_FUNC(thm_movw_prel_nc) \
+DECL_ARM_APPLY_RELOC_FUNC(thm_movt_abs)     \
+DECL_ARM_APPLY_RELOC_FUNC(thm_movt_prel)    \
+DECL_ARM_APPLY_RELOC_FUNC(prel31)           \
+DECL_ARM_APPLY_RELOC_FUNC(got_prel)         \
+DECL_ARM_APPLY_RELOC_FUNC(tls)              \
+DECL_ARM_APPLY_RELOC_FUNC(unsupport)
+
+
+#define DECL_ARM_APPLY_RELOC_FUNC_PTRS \
+  { &none,               0, "R_ARM_NONE"              },  \
+  { &unsupport,          1, "R_ARM_PC24"              },  \
+  { &abs32,              2, "R_ARM_ABS32"             },  \
+  { &rel32,              3, "R_ARM_REL32"             },  \
+  { &unsupport,          4, "R_ARM_LDR_PC_G0"         },  \
+  { &unsupport,          5, "R_ARM_ABS16"             },  \
+  { &unsupport,          6, "R_ARM_ABS12"             },  \
+  { &unsupport,          7, "R_ARM_THM_ABS5"          },  \
+  { &unsupport,          8, "R_ARM_ABS8"              },  \
+  { &unsupport,          9, "R_ARM_SBREL32"           },  \
+  { &thm_call,          10, "R_ARM_THM_CALL"          },  \
+  { &unsupport,         11, "R_ARM_THM_PC8"           },  \
+  { &unsupport,         12, "R_ARM_BREL_ADJ"          },  \
+  { &unsupport,         13, "R_ARM_TLS_DESC"          },  \
+  { &unsupport,         14, "R_ARM_THM_SWI8"          },  \
+  { &unsupport,         15, "R_ARM_XPC25"             },  \
+  { &unsupport,         16, "R_ARM_THM_XPC22"         },  \
+  { &unsupport,         17, "R_ARM_TLS_DTPMOD32"      },  \
+  { &unsupport,         18, "R_ARM_TLS_DTPOFF32"      },  \
+  { &unsupport,         19, "R_ARM_TLS_TPOFF32"       },  \
+  { &unsupport,         20, "R_ARM_COPY"              },  \
+  { &unsupport,         21, "R_ARM_GLOB_DAT"          },  \
+  { &unsupport,         22, "R_ARM_JUMP_SLOT"         },  \
+  { &unsupport,         23, "R_ARM_RELATIVE"          },  \
+  { &gotoff32,          24, "R_ARM_GOTOFF32"          },  \
+  { &base_prel,         25, "R_ARM_BASE_PREL"         },  \
+  { &got_brel,          26, "R_ARM_GOT_BREL"          },  \
+  { &call,              27, "R_ARM_PLT32"             },  \
+  { &call,              28, "R_ARM_CALL"              },  \
+  { &call,              29, "R_ARM_JUMP24"            },  \
+  { &unsupport,         30, "R_ARM_THM_JUMP24"        },  \
+  { &unsupport,         31, "R_ARM_BASE_ABS"          },  \
+  { &unsupport,         32, "R_ARM_ALU_PCREL_7_0"     },  \
+  { &unsupport,         33, "R_ARM_ALU_PCREL_15_8"    },  \
+  { &unsupport,         34, "R_ARM_ALU_PCREL_23_15"   },  \
+  { &unsupport,         35, "R_ARM_LDR_SBREL_11_0_NC" },  \
+  { &unsupport,         36, "R_ARM_ALU_SBREL_19_12_NC"},  \
+  { &unsupport,         37, "R_ARM_ALU_SBREL_27_20_CK"},  \
+  { &abs32,             38, "R_ARM_TARGET1"           },  \
+  { &unsupport,         39, "R_ARM_SBREL31"           },  \
+  { &unsupport,         40, "R_ARM_V4BX"              },  \
+  { &got_prel,          41, "R_ARM_TARGET2"           },  \
+  { &prel31,            42, "R_ARM_PREL31"            },  \
+  { &movw_abs_nc,       43, "R_ARM_MOVW_ABS_NC"       },  \
+  { &movt_abs,          44, "R_ARM_MOVT_ABS"          },  \
+  { &movw_prel_nc,      45, "R_ARM_MOVW_PREL_NC"      },  \
+  { &movt_prel,         46, "R_ARM_MOVT_PREL"         },  \
+  { &thm_movw_abs_nc,   47, "R_ARM_THM_MOVW_ABS_NC"   },  \
+  { &thm_movt_abs,      48, "R_ARM_THM_MOVT_ABS"      },  \
+  { &thm_movw_prel_nc,  49, "R_ARM_THM_MOVW_PREL_NC"  },  \
+  { &thm_movt_prel,     50, "R_ARM_THM_MOVT_PREL"     },  \
+  { &unsupport,         51, "R_ARM_THM_JUMP19"        },  \
+  { &unsupport,         52, "R_ARM_THM_JUMP6"         },  \
+  { &unsupport,         53, "R_ARM_THM_ALU_PREL_11_0" },  \
+  { &unsupport,         54, "R_ARM_THM_PC12"          },  \
+  { &unsupport,         55, "R_ARM_ABS32_NOI"         },  \
+  { &unsupport,         56, "R_ARM_REL32_NOI"         },  \
+  { &unsupport,         57, "R_ARM_ALU_PC_G0_NC"      },  \
+  { &unsupport,         58, "R_ARM_ALU_PC_G0"         },  \
+  { &unsupport,         59, "R_ARM_ALU_PC_G1_NC"      },  \
+  { &unsupport,         60, "R_ARM_ALU_PC_G1"         },  \
+  { &unsupport,         61, "R_ARM_ALU_PC_G2"         },  \
+  { &unsupport,         62, "R_ARM_LDR_PC_G1"         },  \
+  { &unsupport,         63, "R_ARM_LDR_PC_G2"         },  \
+  { &unsupport,         64, "R_ARM_LDRS_PC_G0"        },  \
+  { &unsupport,         65, "R_ARM_LDRS_PC_G1"        },  \
+  { &unsupport,         66, "R_ARM_LDRS_PC_G2"        },  \
+  { &unsupport,         67, "R_ARM_LDC_PC_G0"         },  \
+  { &unsupport,         68, "R_ARM_LDC_PC_G1"         },  \
+  { &unsupport,         69, "R_ARM_LDC_PC_G2"         },  \
+  { &unsupport,         70, "R_ARM_ALU_SB_G0_NC"      },  \
+  { &unsupport,         71, "R_ARM_ALU_SB_G0"         },  \
+  { &unsupport,         72, "R_ARM_ALU_SB_G1_NC"      },  \
+  { &unsupport,         73, "R_ARM_ALU_SB_G1"         },  \
+  { &unsupport,         74, "R_ARM_ALU_SB_G2"         },  \
+  { &unsupport,         75, "R_ARM_LDR_SB_G0"         },  \
+  { &unsupport,         76, "R_ARM_LDR_SB_G1"         },  \
+  { &unsupport,         77, "R_ARM_LDR_SB_G2"         },  \
+  { &unsupport,         78, "R_ARM_LDRS_SB_G0"        },  \
+  { &unsupport,         79, "R_ARM_LDRS_SB_G1"        },  \
+  { &unsupport,         80, "R_ARM_LDRS_SB_G2"        },  \
+  { &unsupport,         81, "R_ARM_LDC_SB_G0"         },  \
+  { &unsupport,         82, "R_ARM_LDC_SB_G1"         },  \
+  { &unsupport,         83, "R_ARM_LDC_SB_G2"         },  \
+  { &unsupport,         84, "R_ARM_MOVW_BREL_NC"      },  \
+  { &unsupport,         85, "R_ARM_MOVT_BREL"         },  \
+  { &unsupport,         86, "R_ARM_MOVW_BREL"         },  \
+  { &unsupport,         87, "R_ARM_THM_MOVW_BREL_NC"  },  \
+  { &unsupport,         88, "R_ARM_THM_MOVT_BREL"     },  \
+  { &unsupport,         89, "R_ARM_THM_MOVW_BREL"     },  \
+  { &unsupport,         90, "R_ARM_TLS_GOTDESC"       },  \
+  { &unsupport,         91, "R_ARM_TLS_CALL"          },  \
+  { &unsupport,         92, "R_ARM_TLS_DESCSEQ"       },  \
+  { &unsupport,         93, "R_ARM_THM_TLS_CALL"      },  \
+  { &unsupport,         94, "R_ARM_PLT32_ABS"         },  \
+  { &unsupport,         95, "R_ARM_GOT_ABS"           },  \
+  { &got_prel,          96, "R_ARM_GOT_PREL"          },  \
+  { &unsupport,         97, "R_ARM_GOT_PREL12"        },  \
+  { &unsupport,         98, "R_ARM_GOTOFF12"          },  \
+  { &unsupport,         99, "R_ARM_GOTRELAX"          },  \
+  { &unsupport,        100, "R_ARM_GNU_VTENTRY"       },  \
+  { &unsupport,        101, "R_ARM_GNU_VTINERIT"      },  \
+  { &unsupport,        102, "R_ARM_THM_JUMP11"        },  \
+  { &unsupport,        103, "R_ARM_THM_JUMP8"         },  \
+  { &tls,              104, "R_ARM_TLS_GD32"          },  \
+  { &unsupport,        105, "R_ARM_TLS_LDM32"         },  \
+  { &unsupport,        106, "R_ARM_TLS_LDO32"         },  \
+  { &tls,              107, "R_ARM_TLS_IE32"          },  \
+  { &tls,              108, "R_ARM_TLS_LE32"          },  \
+  { &unsupport,        109, "R_ARM_TLS_LDO12"         },  \
+  { &unsupport,        110, "R_ARM_TLS_LE12"          },  \
+  { &unsupport,        111, "R_ARM_TLS_IE12GP"        },  \
+  { &unsupport,        112, "R_ARM_PRIVATE_0"         },  \
+  { &unsupport,        113, "R_ARM_PRIVATE_1"         },  \
+  { &unsupport,        114, "R_ARM_PRIVATE_2"         },  \
+  { &unsupport,        115, "R_ARM_PRIVATE_3"         },  \
+  { &unsupport,        116, "R_ARM_PRIVATE_4"         },  \
+  { &unsupport,        117, "R_ARM_PRIVATE_5"         },  \
+  { &unsupport,        118, "R_ARM_PRIVATE_6"         },  \
+  { &unsupport,        119, "R_ARM_PRIVATE_7"         },  \
+  { &unsupport,        120, "R_ARM_PRIVATE_8"         },  \
+  { &unsupport,        121, "R_ARM_PRIVATE_9"         },  \
+  { &unsupport,        122, "R_ARM_PRIVATE_10"        },  \
+  { &unsupport,        123, "R_ARM_PRIVATE_11"        },  \
+  { &unsupport,        124, "R_ARM_PRIVATE_12"        },  \
+  { &unsupport,        125, "R_ARM_PRIVATE_13"        },  \
+  { &unsupport,        126, "R_ARM_PRIVATE_14"        },  \
+  { &unsupport,        127, "R_ARM_PRIVATE_15"        },  \
+  { &unsupport,        128, "R_ARM_ME_TOO"            },  \
+  { &unsupport,        129, "R_ARM_THM_TLS_DESCSEQ16" },  \
+  { &unsupport,        130, "R_ARM_THM_TLS_DESCSEQ32" }
diff --git a/lib/Target/ARM/ARMSectLinker.cpp b/lib/Target/ARM/ARMSectLinker.cpp
new file mode 100644
index 0000000..d686060
--- /dev/null
+++ b/lib/Target/ARM/ARMSectLinker.cpp
@@ -0,0 +1,47 @@
+//===- ARMSectLinker.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include "ARM.h"
+#include "ARMAndroidSectLinker.h"
+#include "ARMELFSectLinker.h"
+
+
+using namespace mcld;
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createARMSectLinker - the help function to create corresponding ARMSectLinker
+//
+SectLinker* createARMSectLinker(const std::string &pTriple,
+                                SectLinkerOption &pOption,
+                                mcld::TargetLDBackend &pLDBackend)
+{
+  Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+  }
+
+  // For now, use Android SectLinker directly
+  return new ARMAndroidSectLinker(pOption,
+                                  pLDBackend);
+}
+
+} // namespace of mcld
+
+//==========================
+// ARMSectLinker
+extern "C" void LLVMInitializeARMSectLinker() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterSectLinker(TheARMTarget, createARMSectLinker);
+}
+
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
new file mode 100644
index 0000000..530a610
--- /dev/null
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -0,0 +1,33 @@
+//===- ARMTargetMachine.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMTargetMachine.h"
+
+#include "mcld/Support/TargetRegistry.h"
+#include "mcld/MC/MCLDInfo.h"
+#include "ARM.h"
+
+extern "C" void LLVMInitializeARMLDTarget() {
+  // Register createTargetMachine function pointer to mcld::Target
+  mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> X(mcld::TheARMTarget);
+}
+
+mcld::ARMBaseTargetMachine::ARMBaseTargetMachine(llvm::TargetMachine& pPM,
+                                                 const mcld::Target &pTarget,
+                                                 const std::string& pTriple)
+  : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
+  // arg1 - the number of total attributes
+  // arg2 - the most possible number of input files
+  m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+}
+
+mcld::ARMBaseTargetMachine::~ARMBaseTargetMachine()
+{
+  delete m_pLDInfo;
+}
+
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
new file mode 100644
index 0000000..19f8aa2
--- /dev/null
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -0,0 +1,40 @@
+//===- ARMTargetMachine.h -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ARM_TARGET_MACHINE_H
+#define MCLD_ARM_TARGET_MACHINE_H
+#include "mcld/Target/TargetMachine.h"
+#include "ARM.h"
+
+namespace mcld
+{
+
+class ARMBaseTargetMachine : public LLVMTargetMachine
+{
+protected:
+  MCLDInfo *m_pLDInfo;
+
+public:
+  ARMBaseTargetMachine(llvm::TargetMachine &pTM,
+                       const mcld::Target &pTarget,
+                       const std::string &pTriple);
+
+  virtual ~ARMBaseTargetMachine();
+
+  mcld::MCLDInfo& getLDInfo()
+  { return *m_pLDInfo; }
+
+  const mcld::MCLDInfo& getLDInfo() const
+  { return *m_pLDInfo; }
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/Android.mk b/lib/Target/ARM/Android.mk
new file mode 100644
index 0000000..272e9f4
--- /dev/null
+++ b/lib/Target/ARM/Android.mk
@@ -0,0 +1,40 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_arm_target_SRC_FILES := \
+  ARMAndroidSectLinker.cpp  \
+  ARMELFDynamic.cpp \
+  ARMELFSectLinker.cpp  \
+  ARMGOT.cpp  \
+  ARMLDBackend.cpp  \
+  ARMPLT.cpp  \
+  ARMRelocationFactory.cpp  \
+  ARMSectLinker.cpp \
+  ARMTargetMachine.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_arm_target_SRC_FILES)
+LOCAL_MODULE:= libmcldARMTarget
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifeq ($(TARGET_ARCH),arm)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_arm_target_SRC_FILES)
+LOCAL_MODULE:= libmcldARMTarget
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/lib/Target/ARM/README b/lib/Target/ARM/README
new file mode 100644
index 0000000..ea88bfe
--- /dev/null
+++ b/lib/Target/ARM/README
@@ -0,0 +1,2 @@
+ARMLDBackend stands like ARMAsmBackend. It's a backend of linker, 
+and all target-dependent behavior and data are here.
diff --git a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
new file mode 100644
index 0000000..7e6a41a
--- /dev/null
+++ b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
@@ -0,0 +1,22 @@
+//===- ARMTargetInfo.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 TheARMTarget;
+
+extern "C" void LLVMInitializeARMLDTargetInfo() {
+  // register into mcld::TargetRegistry
+  mcld::RegisterTarget X(TheARMTarget, "arm" );
+}
+
+} // namespace of mcld
+
diff --git a/lib/Target/ARM/TargetInfo/Android.mk b/lib/Target/ARM/TargetInfo/Android.mk
new file mode 100644
index 0000000..c4fffa3
--- /dev/null
+++ b/lib/Target/ARM/TargetInfo/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_arm_info_SRC_FILES := \
+  ARMTargetInfo.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_arm_info_SRC_FILES)
+LOCAL_MODULE:= libmcldARMInfo
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifeq ($(TARGET_ARCH),arm)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_arm_info_SRC_FILES)
+LOCAL_MODULE:= libmcldARMInfo
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/lib/Target/Android.mk b/lib/Target/Android.mk
new file mode 100644
index 0000000..8e6e260
--- /dev/null
+++ b/lib/Target/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_target_SRC_FILES := \
+  AndroidSectLinker.cpp \
+  ELFDynamic.cpp  \
+  GNULDBackend.cpp  \
+  GOT.cpp \
+  OutputRelocSection.cpp  \
+  PLT.cpp \
+  Stub.cpp  \
+  Target.cpp  \
+  TargetLDBackend.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_target_SRC_FILES)
+LOCAL_MODULE:= libmcldTarget
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_target_SRC_FILES)
+LOCAL_MODULE:= libmcldTarget
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/lib/Target/AndroidSectLinker.cpp b/lib/Target/AndroidSectLinker.cpp
new file mode 100644
index 0000000..8f3acbf
--- /dev/null
+++ b/lib/Target/AndroidSectLinker.cpp
@@ -0,0 +1,45 @@
+//===- AndroidSectLinker.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/Target/AndroidSectLinker.h>
+
+#include <llvm/Support/ErrorHandling.h>
+#include <mcld/MC/MCLDDirectory.h>
+#include <mcld/CodeGen/SectLinkerOption.h>
+
+using namespace mcld;
+
+//==========================
+// AndroidSectLinker
+
+AndroidSectLinker::AndroidSectLinker(SectLinkerOption &pOption,
+                                     TargetLDBackend &pLDBackend)
+  : SectLinker(pOption, pLDBackend) {
+}
+
+AndroidSectLinker::~AndroidSectLinker()
+{
+  // SectLinker will delete m_pLDBackend and m_pLDDriver;
+}
+
+void AndroidSectLinker::addTargetOptions(llvm::Module &pM,
+                                         SectLinkerOption &pOption)
+{
+  // -----  Set up General Options  ----- //
+  MCLDInfo &info = pOption.info();
+  MCLDDirectory search_path("=/system/lib");
+  search_path.setSysroot(info.options().sysroot());
+  if (exists(search_path.path()) && is_directory(search_path.path()))
+    info.options().directories().add(search_path);
+  else {
+    // FIXME: need a warning function
+    llvm::errs() << "WARNING: can not open search directory: `-L" << search_path.name() << "'.\n";
+  }
+}
+
diff --git a/lib/Target/DarwinLDBackend.cpp b/lib/Target/DarwinLDBackend.cpp
new file mode 100644
index 0000000..5bd55c3
--- /dev/null
+++ b/lib/Target/DarwinLDBackend.cpp
@@ -0,0 +1,15 @@
+//===- DarwinLDBackend.cpp ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <DarwinLDBackend.h>
+
+using namespace mcld;
+
+//==========================
+// DarwinLDBackend
+
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
new file mode 100644
index 0000000..b863ab1
--- /dev/null
+++ b/lib/Target/ELFDynamic.cpp
@@ -0,0 +1,257 @@
+//===- ELFDynamic.cpp -------------    ------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/Support/Host.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <mcld/Target/ELFDynamic.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/LD/ELFFileFormat.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/Support/MemoryRegion.h>
+
+using namespace mcld;
+using namespace elf_dynamic;
+
+//===----------------------------------------------------------------------===//
+// elf_dynamic::EntryIF
+EntryIF::EntryIF()
+{
+}
+
+EntryIF::~EntryIF()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// ELFDynamic
+ELFDynamic::ELFDynamic(const GNULDBackend& pParent)
+  : m_pEntryFactory(NULL), m_Idx(0) {
+  if (32 == pParent.bitclass() && pParent.isLittleEndian()) {
+    m_pEntryFactory = new Entry<32, true>();
+  }
+  // FIXME: support big-endian and 64-bit machine.
+}
+
+
+ELFDynamic::~ELFDynamic()
+{
+  if (NULL != m_pEntryFactory)
+    delete m_pEntryFactory;
+
+  EntryListType::iterator entry, entryEnd = m_EntryList.end();
+  for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) {
+    if (NULL != *entry)
+      delete (*entry);
+  }
+
+  entryEnd = m_NeedList.end();
+  for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) {
+    if (NULL != *entry)
+      delete (*entry);
+  }
+}
+
+size_t ELFDynamic::size() const
+{
+  return (m_NeedList.size() + m_EntryList.size());
+}
+
+size_t ELFDynamic::numOfBytes() const
+{
+  return size()*entrySize();
+}
+
+size_t ELFDynamic::entrySize() const
+{
+  return m_pEntryFactory->size();
+}
+
+void ELFDynamic::reserveOne(uint64_t pTag)
+{
+  assert(NULL != m_pEntryFactory);
+  m_EntryList.push_back(new elf_dynamic::Entry<32, true>());
+}
+
+void ELFDynamic::applyOne(uint64_t pTag, uint64_t pValue)
+{
+  assert(m_Idx < m_EntryList.size());
+  m_EntryList[m_Idx]->setValue(pTag, pValue);
+  ++m_Idx;
+}
+
+
+/// reserveEntries - reserve entries
+void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo,
+                                const ELFFileFormat& pFormat)
+{
+  if (pLDInfo.output().type() == Output::DynObj) {
+    reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
+
+    if (pLDInfo.options().Bsymbolic())
+      reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
+  }
+
+  if (pFormat.hasInit())
+    reserveOne(llvm::ELF::DT_INIT); // DT_INIT
+
+  if (pFormat.hasFini())
+    reserveOne(llvm::ELF::DT_FINI); // DT_FINI
+
+  if (pFormat.hasInitArray()) {
+    reserveOne(llvm::ELF::DT_INIT_ARRAY); // DT_INIT_ARRAY
+    reserveOne(llvm::ELF::DT_INIT_ARRAYSZ); // DT_INIT_ARRAYSZ
+  }
+
+  if (pFormat.hasFiniArray()) {
+    reserveOne(llvm::ELF::DT_FINI_ARRAY); // DT_FINI_ARRAY
+    reserveOne(llvm::ELF::DT_FINI_ARRAYSZ); // DT_FINI_ARRAYSZ
+  }
+
+  if (pFormat.hasHashTab())
+    reserveOne(llvm::ELF::DT_HASH); // DT_HASH
+
+  if (pFormat.hasDynSymTab()) {
+    reserveOne(llvm::ELF::DT_SYMTAB); // DT_SYMTAB
+    reserveOne(llvm::ELF::DT_SYMENT); // DT_SYMENT
+  }
+
+  if (pFormat.hasDynStrTab()) {
+    reserveOne(llvm::ELF::DT_STRTAB); // DT_STRTAB
+    reserveOne(llvm::ELF::DT_STRSZ); // DT_STRSZ
+  }
+
+  reserveTargetEntries(pFormat); // DT_PLTGOT
+
+  if (pFormat.hasRelPlt() || pFormat.hasRelaPlt())
+    reserveOne(llvm::ELF::DT_PLTREL); // DT_PLTREL
+
+  if (pFormat.hasPLT()) {
+    reserveOne(llvm::ELF::DT_JMPREL); // DT_JMPREL
+    reserveOne(llvm::ELF::DT_PLTRELSZ); // DT_PLTRELSZ
+  }
+
+  if (pFormat.hasRelDyn()) {
+    reserveOne(llvm::ELF::DT_REL); // DT_REL
+    reserveOne(llvm::ELF::DT_RELSZ); // DT_RELSZ
+    reserveOne(llvm::ELF::DT_RELENT); // DT_RELENT
+  }
+
+  if (pFormat.hasRelaDyn()) {
+    reserveOne(llvm::ELF::DT_RELA); // DT_RELA
+    reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
+    reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
+  }
+  reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
+}
+
+/// applyEntries - apply entries
+void ELFDynamic::applyEntries(const MCLDInfo& pInfo,
+                              const ELFFileFormat& pFormat)
+{
+  if (pInfo.output().type() == Output::DynObj &&
+      pInfo.options().Bsymbolic()) {
+      applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
+  }
+
+  if (pFormat.hasInit())
+    applyOne(llvm::ELF::DT_INIT, pFormat.getInit().addr()); // DT_INIT
+
+  if (pFormat.hasFini())
+    applyOne(llvm::ELF::DT_FINI, pFormat.getFini().addr()); // DT_FINI
+
+  if (pFormat.hasInitArray()) {
+    // DT_INIT_ARRAY
+    applyOne(llvm::ELF::DT_INIT_ARRAY, pFormat.getInitArray().addr());
+
+    // DT_INIT_ARRAYSZ
+    applyOne(llvm::ELF::DT_INIT_ARRAYSZ, pFormat.getInitArray().size());
+  }
+
+  if (pFormat.hasFiniArray()) {
+    // DT_FINI_ARRAY
+    applyOne(llvm::ELF::DT_FINI_ARRAY, pFormat.getFiniArray().addr());
+
+    // DT_FINI_ARRAYSZ
+    applyOne(llvm::ELF::DT_FINI_ARRAYSZ, pFormat.getFiniArray().size());
+  }
+
+  if (pFormat.hasHashTab())
+    applyOne(llvm::ELF::DT_HASH, pFormat.getHashTab().addr()); // DT_HASH
+
+  if (pFormat.hasDynSymTab()) {
+    applyOne(llvm::ELF::DT_SYMTAB, pFormat.getDynSymTab().addr()); // DT_SYMTAB
+    applyOne(llvm::ELF::DT_SYMENT, symbolSize()); // DT_SYMENT
+  }
+
+  if (pFormat.hasDynStrTab()) {
+    applyOne(llvm::ELF::DT_STRTAB, pFormat.getDynStrTab().addr()); // DT_STRTAB
+    applyOne(llvm::ELF::DT_STRSZ, pFormat.getDynStrTab().size()); // DT_STRSZ
+  }
+
+  applyTargetEntries(pFormat); // DT_PLTGOT
+
+  if (pFormat.hasRelPlt())
+    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_REL); // DT_PLTREL
+  else if (pFormat.hasRelaPlt())
+    applyOne(llvm::ELF::DT_PLTREL, llvm::ELF::DT_RELA); // DT_PLTREL
+
+  if (pFormat.hasRelPlt()) {
+    applyOne(llvm::ELF::DT_JMPREL, pFormat.getRelPlt().addr()); // DT_JMPREL
+    applyOne(llvm::ELF::DT_PLTRELSZ, pFormat.getRelPlt().size()); // DT_PLTRELSZ
+  }
+
+  if (pFormat.hasRelDyn()) {
+    applyOne(llvm::ELF::DT_REL, pFormat.getRelDyn().addr()); // DT_REL
+    applyOne(llvm::ELF::DT_RELSZ, pFormat.getRelDyn().size()); // DT_RELSZ
+    applyOne(llvm::ELF::DT_RELENT, m_pEntryFactory->relSize()); // DT_RELENT
+  }
+
+  if (pFormat.hasRelaDyn()) {
+    applyOne(llvm::ELF::DT_RELA, pFormat.getRelaDyn().addr()); // DT_RELA
+    applyOne(llvm::ELF::DT_RELASZ, pFormat.getRelaDyn().size()); // DT_RELASZ
+    applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
+  }
+
+  applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
+}
+
+/// symbolSize
+size_t ELFDynamic::symbolSize() const
+{
+  return m_pEntryFactory->symbolSize();
+}
+
+/// reserveNeedEntry - reserve on DT_NEED entry.
+void ELFDynamic::reserveNeedEntry()
+{
+  m_NeedList.push_back(m_pEntryFactory->clone());
+}
+
+/// emit
+void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const
+{
+  if (pRegion.size() < pSection.size()) {
+    llvm::report_fatal_error(llvm::Twine("the given memory is smaller") +
+                             llvm::Twine(" than the section's demaind.\n"));
+  }
+
+  uint8_t* address = (uint8_t*)pRegion.start();
+  EntryListType::const_iterator entry, entryEnd = m_NeedList.end();
+  for (entry = m_NeedList.begin(); entry != entryEnd; ++entry)
+    address += (*entry)->emit(address);
+
+  entryEnd = m_EntryList.end();
+  for (entry = m_EntryList.begin(); entry != entryEnd; ++entry)
+    address += (*entry)->emit(address);
+}
+
+void ELFDynamic::applySoname(uint64_t pStrTabIdx)
+{
+  applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
+}
+
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
new file mode 100644
index 0000000..b82af73
--- /dev/null
+++ b/lib/Target/GNULDBackend.cpp
@@ -0,0 +1,1021 @@
+//===- GNULDBackend.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/Support/ELF.h>
+#include <mcld/ADT/SizeTraits.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDOutput.h>
+#include <mcld/MC/MCLDInputTree.h>
+#include <mcld/MC/SymbolCategory.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/Layout.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <string>
+#include <cstring>
+#include <cassert>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// GNULDBackend
+GNULDBackend::GNULDBackend()
+  : m_pArchiveReader(0),
+    m_pObjectReader(0),
+    m_pDynObjReader(0),
+    m_pObjectWriter(0),
+    m_pDynObjWriter(0),
+    m_pDynObjFileFormat(0),
+    m_pExecFileFormat(0),
+    m_ELFSegmentTable(9)// magic number
+{
+  m_pSymIndexMap = new HashTableType(1024);
+}
+
+GNULDBackend::~GNULDBackend()
+{
+  if (m_pArchiveReader)
+    delete m_pArchiveReader;
+  if (m_pObjectReader)
+    delete m_pObjectReader;
+  if (m_pDynObjReader)
+    delete m_pDynObjReader;
+  if (m_pObjectWriter)
+    delete m_pObjectWriter;
+  if (m_pDynObjWriter)
+    delete m_pDynObjWriter;
+  if (m_pDynObjFileFormat)
+    delete m_pDynObjFileFormat;
+  if (m_pExecFileFormat)
+    delete m_pExecFileFormat;
+  if(m_pSymIndexMap)
+    delete m_pSymIndexMap;
+}
+
+size_t GNULDBackend::sectionStartOffset() const
+{
+  // FIXME: use fixed offset, we need 10 segments by default
+  return sizeof(llvm::ELF::Elf64_Ehdr)+10*sizeof(llvm::ELF::Elf64_Phdr);
+}
+
+bool GNULDBackend::initArchiveReader(MCLinker&, MCLDInfo &pInfo)
+{
+  if (0 == m_pArchiveReader)
+  {
+    LDReader::Endian isLittleEndian = LDReader::LittleEndian;
+    m_pArchiveReader = new GNUArchiveReader(pInfo, isLittleEndian);
+  }
+  return true;
+}
+
+bool GNULDBackend::initObjectReader(MCLinker& pLinker)
+{
+  if (0 == m_pObjectReader)
+    m_pObjectReader = new ELFObjectReader(*this, pLinker);
+  return true;
+}
+
+bool GNULDBackend::initDynObjReader(MCLinker& pLinker)
+{
+  if (0 == m_pDynObjReader)
+    m_pDynObjReader = new ELFDynObjReader(*this, pLinker);
+  return true;
+}
+
+bool GNULDBackend::initObjectWriter(MCLinker&)
+{
+  // TODO
+  return true;
+}
+
+bool GNULDBackend::initDynObjWriter(MCLinker& pLinker)
+{
+  if (0 == m_pDynObjWriter)
+    m_pDynObjWriter = new ELFDynObjWriter(*this, pLinker);
+  return true;
+}
+
+bool GNULDBackend::initExecSections(MCLinker& pMCLinker)
+{
+  if (0 == m_pExecFileFormat)
+    m_pExecFileFormat = new ELFExecFileFormat(*this);
+
+  // initialize standard sections
+  m_pExecFileFormat->initStdSections(pMCLinker);
+  return true;
+}
+
+bool GNULDBackend::initDynObjSections(MCLinker& pMCLinker)
+{
+  if (0 == m_pDynObjFileFormat)
+    m_pDynObjFileFormat = new ELFDynObjFileFormat(*this);
+
+  // initialize standard sections
+  m_pDynObjFileFormat->initStdSections(pMCLinker);
+  return true;
+}
+
+bool GNULDBackend::initStandardSymbols(MCLinker& pLinker)
+{
+  return true;
+}
+
+GNUArchiveReader *GNULDBackend::getArchiveReader()
+{
+  assert(0 != m_pArchiveReader);
+  return m_pArchiveReader;
+}
+
+GNUArchiveReader *GNULDBackend::getArchiveReader() const
+{
+  assert(0 != m_pArchiveReader);
+  return m_pArchiveReader;
+}
+
+ELFObjectReader *GNULDBackend::getObjectReader()
+{
+  assert(0 != m_pObjectReader);
+  return m_pObjectReader;
+}
+
+ELFObjectReader *GNULDBackend::getObjectReader() const
+{
+  assert(0 != m_pObjectReader);
+  return m_pObjectReader;
+}
+
+ELFDynObjReader *GNULDBackend::getDynObjReader()
+{
+  assert(0 != m_pDynObjReader);
+  return m_pDynObjReader;
+}
+
+ELFDynObjReader *GNULDBackend::getDynObjReader() const
+{
+  assert(0 != m_pDynObjReader);
+  return m_pDynObjReader;
+}
+
+ELFObjectWriter *GNULDBackend::getObjectWriter()
+{
+  // TODO
+  return NULL;
+}
+
+ELFObjectWriter *GNULDBackend::getObjectWriter() const
+{
+  // TODO
+  return NULL;
+}
+
+ELFDynObjWriter *GNULDBackend::getDynObjWriter()
+{
+  assert(0 != m_pDynObjWriter);
+  return m_pDynObjWriter;
+}
+
+ELFDynObjWriter *GNULDBackend::getDynObjWriter() const
+{
+  assert(0 != m_pDynObjWriter);
+  return m_pDynObjWriter;
+}
+
+ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat()
+{
+  assert(0 != m_pDynObjFileFormat);
+  return m_pDynObjFileFormat;
+}
+
+ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat() const
+{
+  assert(0 != m_pDynObjFileFormat);
+  return m_pDynObjFileFormat;
+}
+
+ELFExecFileFormat* GNULDBackend::getExecFileFormat()
+{
+  assert(0 != m_pExecFileFormat);
+  return m_pExecFileFormat;
+}
+
+ELFExecFileFormat* GNULDBackend::getExecFileFormat() const
+{
+  assert(0 != m_pExecFileFormat);
+  return m_pExecFileFormat;
+}
+
+/// sizeNamePools - compute the size of regular name pools
+/// In ELF executable files, regular name pools are .symtab, .strtab,
+/// .dynsym, .dynstr, and .hash
+void
+GNULDBackend::sizeNamePools(const Output& pOutput,
+                            const SymbolCategory& pSymbols,
+                            const MCLDInfo& pLDInfo)
+{
+  // size of string tables starts from 1 to hold the null character in their
+  // first byte
+  size_t symtab = 1;
+  size_t dynsym = 1;
+  // number of entries in symbol tables starts from 1 to hold the special entry
+  // at index 0 (STN_UNDEF). See ELF Spec Book I, p1-21.
+  size_t strtab = 1;
+  size_t dynstr = 1;
+  size_t hash   = 0;
+
+  // compute size of .symtab, .dynsym and .strtab
+  SymbolCategory::const_iterator symbol;
+  SymbolCategory::const_iterator symEnd = pSymbols.end();
+  for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
+    size_t str_size = (*symbol)->nameSize() + 1;
+    if (isDynamicSymbol(**symbol, pOutput)) {
+      ++dynsym;
+      dynstr += str_size;
+    }
+    ++symtab;
+    strtab += str_size;
+  }
+
+  ELFFileFormat* file_format = NULL;
+  switch(pOutput.type()) {
+    // compute size of .dynstr and .hash
+    case Output::DynObj:
+      file_format = getDynObjFileFormat();
+      break;
+    case Output::Exec:
+      file_format = getExecFileFormat();
+      break;
+    case Output::Object:
+    default:
+      // TODO: not support yet
+      return;
+  }
+
+  switch(pOutput.type()) {
+    // compute size of .dynstr and .hash
+    case Output::DynObj:
+    case Output::Exec: {
+      // add DT_NEED strings into .dynstr and .dynamic
+      // Rules:
+      //   1. ignore --no-add-needed
+      //   2. force count in --no-as-needed
+      //   3. judge --as-needed
+      InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
+      for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
+        if (Input::DynObj == (*input)->type()) {
+          // --add-needed
+          if ((*input)->attribute()->isAddNeeded()) {
+            // --no-as-needed
+            if (!(*input)->attribute()->isAsNeeded()) {
+              dynstr += (*input)->name().size() + 1;
+              dynamic().reserveNeedEntry();
+            }
+            // --as-needed
+            else if ((*input)->isNeeded()) {
+              dynstr += (*input)->name().size() + 1;
+              dynamic().reserveNeedEntry();
+            }
+          }
+        }
+      } // for
+
+      // compute .hash
+      // Both Elf32_Word and Elf64_Word are 4 bytes
+      hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
+             sizeof(llvm::ELF::Elf32_Word);
+
+      // set size
+      dynstr += pOutput.name().size() + 1;
+      if (32 == bitclass())
+        file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf32_Sym));
+      else
+        file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf64_Sym));
+      file_format->getDynStrTab().setSize(dynstr);
+      file_format->getHashTab().setSize(hash);
+
+    }
+    /* fall through */
+    case Output::Object: {
+      if (32 == bitclass())
+        file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf32_Sym));
+      else
+        file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf64_Sym));
+      file_format->getStrTab().setSize(strtab);
+      break;
+    }
+  } // end of switch
+
+  // reserve fixed entries in the .dynamic section.
+  if (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type()) {
+    // Because some entries in .dynamic section need information of .dynsym,
+    // .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
+    // entries until we get the size of the sections mentioned above
+    dynamic().reserveEntries(pLDInfo, *file_format);
+    file_format->getDynamic().setSize(dynamic().numOfBytes());
+  }
+}
+
+/// emitRegNamePools - emit regular name pools - .symtab, .strtab
+///
+/// the size of these tables should be computed before layout
+/// layout should computes the start offset of these tables
+void GNULDBackend::emitRegNamePools(Output& pOutput,
+                                    SymbolCategory& pSymbols,
+                                    const Layout& pLayout,
+                                    const MCLDInfo& pLDInfo)
+{
+
+  assert(pOutput.hasMemArea());
+
+  bool sym_exist = false;
+  HashTableType::entry_type* entry = 0;
+
+  ELFFileFormat* file_format = NULL;
+  switch(pOutput.type()) {
+    // compute size of .dynstr and .hash
+    case Output::DynObj:
+      file_format = getDynObjFileFormat();
+      break;
+    case Output::Exec:
+      file_format = getExecFileFormat();
+      break;
+    case Output::Object:
+    default:
+      // add first symbol into m_pSymIndexMap
+      entry = m_pSymIndexMap->insert(NULL, sym_exist);
+      entry->setValue(0);
+
+      // TODO: not support yet
+      return;
+  }
+
+  LDSection& symtab_sect = file_format->getSymTab();
+  LDSection& strtab_sect = file_format->getStrTab();
+
+  MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
+                                                           symtab_sect.size());
+  MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
+                                                           strtab_sect.size());
+
+  // set up symtab_region
+  llvm::ELF::Elf32_Sym* symtab32 = NULL;
+  llvm::ELF::Elf64_Sym* symtab64 = NULL;
+  if (32 == bitclass())
+    symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
+  else if (64 == bitclass())
+    symtab64 = (llvm::ELF::Elf64_Sym*)symtab_region->start();
+  else
+    llvm::report_fatal_error(llvm::Twine("unsupported bitclass ") +
+                             llvm::Twine(bitclass()) +
+                             llvm::Twine(".\n"));
+  // set up strtab_region
+  char* strtab = (char*)strtab_region->start();
+  strtab[0] = '\0';
+
+  // initialize the first ELF symbol
+  if (32 == bitclass()) {
+    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;
+  }
+  else { // must 64
+    symtab64[0].st_name  = 0;
+    symtab64[0].st_value = 0;
+    symtab64[0].st_size  = 0;
+    symtab64[0].st_info  = 0;
+    symtab64[0].st_other = 0;
+    symtab64[0].st_shndx = 0;
+  }
+
+  size_t symtabIdx = 1;
+  size_t strtabsize = 1;
+  // compute size of .symtab, .dynsym and .strtab
+  SymbolCategory::iterator symbol;
+  SymbolCategory::iterator symEnd = pSymbols.end();
+  for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
+
+     // maintain output's symbol and index map if building .o file
+    if (Output::Object == pOutput.type()) {
+      entry = m_pSymIndexMap->insert(NULL, sym_exist);
+      entry->setValue(symtabIdx);
+    }
+
+    // FIXME: check the endian between host and target
+    // write out symbol
+    if (32 == bitclass()) {
+      symtab32[symtabIdx].st_name  = strtabsize;
+      symtab32[symtabIdx].st_value = getSymbolValue(**symbol);
+      symtab32[symtabIdx].st_size  = getSymbolSize(**symbol);
+      symtab32[symtabIdx].st_info  = getSymbolInfo(**symbol);
+      symtab32[symtabIdx].st_other = (*symbol)->visibility();
+      symtab32[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
+    }
+    else { // must 64
+      symtab64[symtabIdx].st_name  = strtabsize;
+      symtab64[symtabIdx].st_value = getSymbolValue(**symbol);
+      symtab64[symtabIdx].st_size  = getSymbolSize(**symbol);
+      symtab64[symtabIdx].st_info  = getSymbolInfo(**symbol);
+      symtab64[symtabIdx].st_other = (*symbol)->visibility();
+      symtab64[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
+    }
+    // write out string
+    strcpy((strtab + strtabsize), (*symbol)->name());
+
+    // write out
+    // sum up counters
+    ++symtabIdx;
+    strtabsize += (*symbol)->nameSize() + 1;
+  }
+}
+
+/// 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 GNULDBackend::emitDynNamePools(Output& pOutput,
+                                    SymbolCategory& pSymbols,
+                                    const Layout& pLayout,
+                                    const MCLDInfo& pLDInfo)
+{
+  assert(pOutput.hasMemArea());
+  ELFFileFormat* file_format = NULL;
+
+  bool sym_exist = false;
+  HashTableType::entry_type* entry = 0;
+
+  switch(pOutput.type()) {
+    // compute size of .dynstr and .hash
+    case Output::DynObj:
+      file_format = getDynObjFileFormat();
+      break;
+    case Output::Exec:
+      file_format = getExecFileFormat();
+      break;
+    case Output::Object:
+    default:
+      // TODO: not support yet
+      return;
+  }
+
+  LDSection& symtab_sect = file_format->getDynSymTab();
+  LDSection& strtab_sect = file_format->getDynStrTab();
+  LDSection& hash_sect   = file_format->getHashTab();
+  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;
+  llvm::ELF::Elf64_Sym* symtab64 = NULL;
+  if (32 == bitclass())
+    symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
+  else if (64 == bitclass())
+    symtab64 = (llvm::ELF::Elf64_Sym*)symtab_region->start();
+  else
+    llvm::report_fatal_error(llvm::Twine("unsupported bitclass ") +
+                             llvm::Twine(bitclass()) +
+                             llvm::Twine(".\n"));
+
+  // initialize the first ELF symbol
+  if (32 == bitclass()) {
+    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;
+  }
+  else { // must 64
+    symtab64[0].st_name  = 0;
+    symtab64[0].st_value = 0;
+    symtab64[0].st_size  = 0;
+    symtab64[0].st_info  = 0;
+    symtab64[0].st_other = 0;
+    symtab64[0].st_shndx = 0;
+  }
+  // set up strtab_region
+  char* strtab = (char*)strtab_region->start();
+  strtab[0] = '\0';
+
+  // add the first symbol into m_pSymIndexMap
+  entry = m_pSymIndexMap->insert(NULL, sym_exist);
+  entry->setValue(0);
+
+  size_t symtabIdx = 1;
+  size_t strtabsize = 1;
+
+  // emit of .dynsym, and .dynstr
+  SymbolCategory::iterator symbol;
+  SymbolCategory::iterator symEnd = pSymbols.end();
+  for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
+    if (!isDynamicSymbol(**symbol, pOutput))
+      continue;
+
+    // maintain output's symbol and index map
+    entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+    entry->setValue(symtabIdx);
+
+    // FIXME: check the endian between host and target
+    // write out symbol
+    if (32 == bitclass()) {
+      symtab32[symtabIdx].st_name  = strtabsize;
+      symtab32[symtabIdx].st_value = (*symbol)->value();
+      symtab32[symtabIdx].st_size  = getSymbolSize(**symbol);
+      symtab32[symtabIdx].st_info  = getSymbolInfo(**symbol);
+      symtab32[symtabIdx].st_other = (*symbol)->visibility();
+      symtab32[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
+    }
+    else { // must 64
+      symtab64[symtabIdx].st_name  = strtabsize;
+      symtab64[symtabIdx].st_value = (*symbol)->value();
+      symtab64[symtabIdx].st_size  = getSymbolSize(**symbol);
+      symtab64[symtabIdx].st_info  = getSymbolInfo(**symbol);
+      symtab64[symtabIdx].st_other = (*symbol)->visibility();
+      symtab64[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
+    }
+    // write out string
+    strcpy((strtab + strtabsize), (*symbol)->name());
+
+    // sum up counters
+    ++symtabIdx;
+    strtabsize += (*symbol)->nameSize() + 1;
+  }
+
+  // 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;
+
+  if (32 == bitclass()) {
+    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;
+    }
+  }
+  else if (64 == bitclass()) {
+    for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) {
+      llvm::StringRef name(strtab + symtab64[sym_idx].st_name);
+      size_t bucket_pos = hash_func(name) % nbucket;
+      chain[sym_idx] = bucket[bucket_pos];
+      bucket[bucket_pos] = sym_idx;
+    }
+  }
+}
+
+/// getSectionOrder
+unsigned int GNULDBackend::getSectionOrder(const Output& pOutput,
+                                           const LDSection& pSectHdr) const
+{
+  // NULL section should be the "1st" section
+  if (LDFileFormat::Null == pSectHdr.kind())
+    return 0;
+
+  // if the section is not ALLOC, lay it out until the last possible moment
+  if (0 == (pSectHdr.flag() & llvm::ELF::SHF_ALLOC))
+    return SHO_UNDEFINED;
+
+  bool is_write = (pSectHdr.flag() & llvm::ELF::SHF_WRITE) != 0;
+  bool is_exec = (pSectHdr.flag() & llvm::ELF::SHF_EXECINSTR) != 0;
+  ELFFileFormat* file_format = NULL;
+  switch (pOutput.type()) {
+    case Output::DynObj:
+      file_format = getDynObjFileFormat();
+      break;
+    case Output::Exec:
+      file_format = getExecFileFormat();
+      break;
+    case Output::Object:
+    default:
+      assert(0 && "Not support yet.\n");
+      break;
+  }
+
+  // TODO: need to take care other possible output sections
+  switch (pSectHdr.kind()) {
+    case LDFileFormat::Regular:
+      if (is_exec) {
+        if (&pSectHdr == &file_format->getInit())
+          return SHO_INIT;
+        if (&pSectHdr == &file_format->getFini())
+          return SHO_FINI;
+        return SHO_TEXT;
+      } else if (!is_write) {
+        return SHO_RO;
+      } else {
+        if (pSectHdr.type() == llvm::ELF::SHT_PREINIT_ARRAY ||
+            pSectHdr.type() == llvm::ELF::SHT_INIT_ARRAY ||
+            pSectHdr.type() == llvm::ELF::SHT_FINI_ARRAY ||
+            &pSectHdr == &file_format->getCtors() ||
+            &pSectHdr == &file_format->getDtors())
+          return SHO_RELRO;
+
+        return SHO_DATA;
+      }
+
+    case LDFileFormat::BSS:
+      return SHO_BSS;
+
+    case LDFileFormat::NamePool:
+      if (&pSectHdr == &file_format->getDynamic())
+        return SHO_RELRO;
+      return SHO_NAMEPOOL;
+
+    case LDFileFormat::Relocation:
+      if (&pSectHdr == &file_format->getRelPlt() ||
+          &pSectHdr == &file_format->getRelaPlt())
+        return SHO_REL_PLT;
+      return SHO_RELOCATION;
+
+    // get the order from target for target specific sections
+    case LDFileFormat::Target:
+      return getTargetSectionOrder(pOutput, pSectHdr);
+
+    // handle .interp
+    case LDFileFormat::Note:
+      return SHO_INTERP;
+
+    case LDFileFormat::Exception:
+      return SHO_EHFRAME;
+
+    case LDFileFormat::MetaData:
+    case LDFileFormat::Debug:
+    default:
+      return SHO_UNDEFINED;
+  }
+}
+
+/// getSymbolSize
+uint64_t GNULDBackend::getSymbolSize(const LDSymbol& pSymbol) const
+{
+  // @ref Google gold linker: symtab.cc: 2780
+  // undefined and dynamic symbols should have zero size.
+  if (pSymbol.isDyn() || pSymbol.desc() == ResolveInfo::Undefined)
+    return 0x0;
+  return pSymbol.resolveInfo()->size();
+}
+
+/// getSymbolInfo
+uint64_t GNULDBackend::getSymbolInfo(const LDSymbol& pSymbol) const
+{
+  // set binding
+  uint8_t bind = 0x0;
+  if (pSymbol.resolveInfo()->isLocal())
+    bind = llvm::ELF::STB_LOCAL;
+  else if (pSymbol.resolveInfo()->isGlobal())
+    bind = llvm::ELF::STB_GLOBAL;
+  else if (pSymbol.resolveInfo()->isWeak())
+    bind = llvm::ELF::STB_WEAK;
+  else if (pSymbol.resolveInfo()->isAbsolute()) {
+    // (Luba) Is a absolute but not global (weak or local) symbol meaningful?
+    bind = llvm::ELF::STB_GLOBAL;
+  }
+
+  if (pSymbol.visibility() == llvm::ELF::STV_INTERNAL ||
+      pSymbol.visibility() == llvm::ELF::STV_HIDDEN)
+    bind = llvm::ELF::STB_LOCAL;
+
+  return (pSymbol.resolveInfo()->type() | (bind << 4));
+}
+
+/// getSymbolValue - this function is called after layout()
+uint64_t GNULDBackend::getSymbolValue(const LDSymbol& pSymbol) const
+{
+  if (pSymbol.isDyn())
+    return 0x0;
+
+  return pSymbol.value();
+}
+
+/// getSymbolShndx - this function is called after layout()
+uint64_t
+GNULDBackend::getSymbolShndx(const LDSymbol& pSymbol, const Layout& pLayout) const
+{
+  if (pSymbol.resolveInfo()->isAbsolute())
+    return llvm::ELF::SHN_ABS;
+  if (pSymbol.resolveInfo()->isCommon())
+    return llvm::ELF::SHN_COMMON;
+  if (pSymbol.resolveInfo()->isUndef() || pSymbol.isDyn())
+    return llvm::ELF::SHN_UNDEF;
+
+  if (pSymbol.resolveInfo()->isLocal()) {
+    switch (pSymbol.type()) {
+      case ResolveInfo::NoType:
+      case ResolveInfo::File:
+        return llvm::ELF::SHN_ABS;
+    }
+  }
+
+  assert(pSymbol.hasFragRef());
+  return pLayout.getOutputLDSection(*pSymbol.fragRef()->frag())->index();
+}
+
+/// getSymbolIdx - called by emitRelocation to get the ouput symbol table index
+size_t GNULDBackend::getSymbolIdx(LDSymbol* pSymbol) const
+{
+   HashTableType::iterator entry = m_pSymIndexMap->find(pSymbol);
+   return entry.getEntry()->value();
+}
+
+/// emitProgramHdrs - emit ELF program headers
+void GNULDBackend::emitProgramHdrs(Output& pOutput)
+{
+  assert(NULL != pOutput.context());
+  createProgramHdrs(*pOutput.context());
+
+  if (32 == bitclass())
+    writeELF32ProgramHdrs(pOutput);
+  else
+    writeELF64ProgramHdrs(pOutput);
+}
+
+/// createProgramHdrs - base on output sections to create the program headers
+void GNULDBackend::createProgramHdrs(LDContext& pContext)
+{
+  // make PT_PHDR
+  m_ELFSegmentTable.produce(llvm::ELF::PT_PHDR);
+
+  // make PT_INTERP
+  LDSection* interp = pContext.getSection(".interp");
+  if (NULL != interp) {
+    ELFSegment* interp_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_INTERP);
+    interp_seg->addSection(interp);
+    interp_seg->setAlign(bitclass() / 8);
+  }
+
+  uint32_t cur_seg_flag, prev_seg_flag = getSegmentFlag(0);
+  uint64_t padding = 0;
+  ELFSegment* load_seg = NULL;
+  // make possible PT_LOAD segments
+  LDContext::sect_iterator sect, sect_end = pContext.sectEnd();
+  for (sect = pContext.sectBegin(); sect != sect_end; ++sect) {
+    if (0 == ((*sect)->flag() & llvm::ELF::SHF_ALLOC) &&
+        LDFileFormat::Null != (*sect)->kind())
+      continue;
+
+    // FIXME: Now only separate writable and non-writable PT_LOAD
+    cur_seg_flag = getSegmentFlag((*sect)->flag());
+    if ((prev_seg_flag & llvm::ELF::PF_W) ^ (cur_seg_flag & llvm::ELF::PF_W) ||
+         LDFileFormat::Null == (*sect)->kind()) {
+      // create new PT_LOAD segment
+      load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD);
+      load_seg->setAlign(pagesize());
+
+      // check if this segment needs padding
+      padding = 0;
+      if (((*sect)->offset() & (load_seg->align() - 1)) != 0)
+        padding = load_seg->align();
+    }
+
+    assert(NULL != load_seg);
+    load_seg->addSection(*sect);
+    load_seg->updateFlag(cur_seg_flag);
+
+    // FIXME: set section's vma
+    // need to handle start vma for user-defined one or for executable.
+    (*sect)->setAddr((*sect)->offset() + padding);
+
+    prev_seg_flag = cur_seg_flag;
+  }
+
+  // make PT_DYNAMIC
+  LDSection* dynamic = pContext.getSection(".dynamic");
+  if (NULL != dynamic) {
+    ELFSegment* dyn_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_DYNAMIC);
+    dyn_seg->setFlag(llvm::ELF::PF_R | llvm::ELF::PF_W);
+    dyn_seg->addSection(dynamic);
+    dyn_seg->setAlign(bitclass() / 8);
+  }
+
+  // update segment info
+  uint64_t file_size = 0;
+  ELFSegmentFactory::iterator seg, seg_end = m_ELFSegmentTable.end();
+  for (seg = m_ELFSegmentTable.begin(); seg != seg_end; ++seg) {
+    ELFSegment& segment = *seg;
+
+    // update PT_PHDR
+    if (llvm::ELF::PT_PHDR == segment.type()) {
+      uint64_t offset, phdr_size;
+      if (32 == bitclass()) {
+        offset = sizeof(llvm::ELF::Elf32_Ehdr);
+        phdr_size = sizeof(llvm::ELF::Elf32_Phdr);
+      }
+      else {
+        offset = sizeof(llvm::ELF::Elf64_Ehdr);
+        phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
+      }
+      segment.setOffset(offset);
+      segment.setVaddr(offset);
+      segment.setPaddr(segment.vaddr());
+      segment.setFilesz(numOfSegments() * phdr_size);
+      segment.setMemsz(numOfSegments() * phdr_size);
+      segment.setAlign(bitclass() / 8);
+      continue;
+    }
+
+    assert(NULL != segment.getFirstSection());
+    segment.setOffset(segment.getFirstSection()->offset());
+    segment.setVaddr(segment.getFirstSection()->addr());
+    segment.setPaddr(segment.vaddr());
+
+    const LDSection* last_sect = segment.getLastSection();
+    assert(NULL != last_sect);
+    file_size = last_sect->offset() - segment.offset();
+    if (LDFileFormat::BSS != last_sect->kind())
+      file_size += last_sect->size();
+    segment.setFilesz(file_size);
+
+    segment.setMemsz(last_sect->addr() - segment.vaddr() + last_sect->size());
+  }
+}
+
+/// writeELF32ProgramHdrs - write out the ELF32 program headers
+void GNULDBackend::writeELF32ProgramHdrs(Output& pOutput)
+{
+  assert(pOutput.hasMemArea());
+
+  uint64_t start_offset, phdr_size;
+
+  start_offset = sizeof(llvm::ELF::Elf32_Ehdr);
+  phdr_size = sizeof(llvm::ELF::Elf32_Phdr);
+  // Program header must start directly after ELF header
+  MemoryRegion *region = pOutput.memArea()->request(start_offset,
+                                                    numOfSegments()*phdr_size);
+
+  llvm::ELF::Elf32_Phdr* phdr = (llvm::ELF::Elf32_Phdr*)region->start();
+
+  size_t index = 0;
+  ELFSegmentFactory::iterator seg, segEnd = m_ELFSegmentTable.end();
+  for (seg = m_ELFSegmentTable.begin(); seg != segEnd; ++seg, ++index) {
+    phdr[index].p_type   = (*seg).type();
+    phdr[index].p_flags  = (*seg).flag();
+    phdr[index].p_offset = (*seg).offset();
+    phdr[index].p_vaddr  = (*seg).vaddr();
+    phdr[index].p_paddr  = (*seg).paddr();
+    phdr[index].p_filesz = (*seg).filesz();
+    phdr[index].p_memsz  = (*seg).memsz();
+    phdr[index].p_align  = (*seg).align();
+  }
+}
+
+/// writeELF64ProgramHdrs - write out the ELF64 program headers
+void GNULDBackend::writeELF64ProgramHdrs(Output& pOutput)
+{
+  assert(pOutput.hasMemArea());
+
+  uint64_t start_offset, phdr_size;
+
+  start_offset = sizeof(llvm::ELF::Elf64_Ehdr);
+  phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
+  // Program header must start directly after ELF header
+  MemoryRegion *region = pOutput.memArea()->request(start_offset,
+                                                    numOfSegments() *phdr_size);
+  llvm::ELF::Elf64_Phdr* phdr = (llvm::ELF::Elf64_Phdr*)region->start();
+
+  size_t index = 0;
+  ELFSegmentFactory::iterator seg, segEnd = m_ELFSegmentTable.end();
+  for (seg = m_ELFSegmentTable.begin(); seg != segEnd; ++seg, ++index) {
+    phdr[index].p_type   = (*seg).type();
+    phdr[index].p_flags  = (*seg).flag();
+    phdr[index].p_offset = (*seg).offset();
+    phdr[index].p_vaddr  = (*seg).vaddr();
+    phdr[index].p_paddr  = (*seg).paddr();
+    phdr[index].p_filesz = (*seg).filesz();
+    phdr[index].p_memsz  = (*seg).memsz();
+    phdr[index].p_align  = (*seg).align();
+  }
+}
+
+/// preLayout - Backend can do any needed modification before layout
+void GNULDBackend::preLayout(const Output& pOutput,
+                             const MCLDInfo& pLDInfo,
+                             MCLinker& pLinker)
+{
+  // prelayout target first
+  doPreLayout(pOutput, pLDInfo, pLinker);
+}
+
+/// postLayout -Backend can do any needed modification after layout
+void GNULDBackend::postLayout(const Output& pOutput,
+                              const MCLDInfo& pInfo,
+                              MCLinker& pLinker)
+{
+  // post layout target first
+  doPostLayout(pOutput, pInfo, pLinker);
+}
+
+/// getHashBucketCount - calculate hash bucket count.
+/// @ref Google gold linker, dynobj.cc:791
+unsigned GNULDBackend::getHashBucketCount(unsigned pNumOfSymbols,
+                                          bool pIsGNUStyle)
+{
+  // @ref Google gold, dynobj.cc:loc 791
+  static const unsigned int buckets[] =
+  {
+    1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 1031, 2053, 4099, 8209,
+    16411, 32771, 65537, 131101, 262147
+  };
+  const unsigned buckets_count = sizeof buckets / sizeof buckets[0];
+
+  unsigned int result = 1;
+  for (unsigned i = 0; i < buckets_count; ++i) {
+    if (pNumOfSymbols < buckets[i])
+      break;
+    result = buckets[i];
+  }
+
+  if (pIsGNUStyle && result < 2)
+    result = 2;
+
+  return result;
+}
+
+/// isDynamicSymbol
+/// @ref Google gold linker: symtab.cc:311
+bool GNULDBackend::isDynamicSymbol(const LDSymbol& pSymbol,
+                                   const Output& pOutput)
+{
+  // If a local symbol is in the LDContext's symbol table, it's a real local
+  // symbol. We should not add it
+  if (pSymbol.binding() == ResolveInfo::Local)
+    return false;
+
+  // If we are building shared object, and the visibility is external, we
+  // need to add it.
+  if (Output::DynObj == pOutput.type())
+    if (pSymbol.resolveInfo()->visibility() == ResolveInfo::Default ||
+        pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected)
+      return true;
+
+  return false;
+}
diff --git a/lib/Target/GOT.cpp b/lib/Target/GOT.cpp
new file mode 100644
index 0000000..a05b574
--- /dev/null
+++ b/lib/Target/GOT.cpp
@@ -0,0 +1,45 @@
+//===- GOT.cpp ------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Target/GOT.h>
+#include <cstring>
+#include <cstdlib>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// GOTEntry
+GOTEntry::GOTEntry(uint64_t pContent, size_t pEntrySize,
+                   llvm::MCSectionData* pParent)
+  : MCTargetFragment(llvm::MCFragment::FT_Target, pParent),
+    f_Content(pContent), m_EntrySize(pEntrySize) {
+}
+
+GOTEntry::~GOTEntry()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// GOT
+GOT::GOT(LDSection& pSection,
+         llvm::MCSectionData& pSectionData,
+         size_t pEntrySize)
+  : m_Section(pSection),
+    m_SectionData(pSectionData),
+    f_EntrySize(pEntrySize) {
+}
+
+GOT::~GOT()
+{
+}
+
+size_t GOT::getEntrySize() const
+{
+  return f_EntrySize;
+}
+
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
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
new file mode 100644
index 0000000..89b4f52
--- /dev/null
+++ b/lib/Target/OutputRelocSection.cpp
@@ -0,0 +1,84 @@
+//===- OutputRelocSection.cpp ---------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/LDSection.h>
+#include <mcld/Target/OutputRelocSection.h>
+
+using namespace mcld;
+
+//==========================
+// OutputRelocSection
+
+
+OutputRelocSection::OutputRelocSection(LDSection& pSection,
+                                       llvm::MCSectionData& pSectionData,
+                                       unsigned int pEntrySize)
+  : m_pSection(&pSection),
+    m_pSectionData(&pSectionData),
+    m_EntryBytes(pEntrySize),
+    m_isVisit(false),
+    m_ValidEntryIterator(){
+}
+
+OutputRelocSection::~OutputRelocSection()
+{
+}
+
+void OutputRelocSection::reserveEntry(RelocationFactory& pRelFactory,
+                                      size_t pNum)
+{
+  for(size_t i=0; i<pNum; i++) {
+    m_pSectionData->getFragmentList().push_back(pRelFactory.produceEmptyEntry());
+    // update section size
+    m_pSection->setSize(m_pSection->size() + m_EntryBytes);
+  }
+}
+
+Relocation* OutputRelocSection::getEntry(const ResolveInfo& pSymbol,
+                                         bool isForGOT,
+                                         bool& pExist)
+{
+  // first time visit this function, set m_ValidEntryIterator to
+  // Fragments.begin()
+  if(!m_isVisit) {
+    assert( !m_pSectionData->getFragmentList().empty() &&
+             "DynRelSection contains no entries.");
+    m_ValidEntryIterator = m_pSectionData->getFragmentList().begin();
+    m_isVisit = true;
+  }
+
+  assert(m_ValidEntryIterator != m_pSectionData->end() &&
+         "No empty relocation entry for the incoming symbol.");
+
+  // if this relocation is used to relocate GOT (.got or .got.plt),
+  // check if we've gotten an entry for this symbol before. If yes,
+  // return the found entry in map.
+  // Otherwise, this relocation is used to relocate general section
+  // (data or text section), return an empty entry directly.
+  Relocation* result;
+
+  if(isForGOT) {
+    // get or create entry in m_SymRelMap
+    Relocation *&Entry = m_SymRelMap[&pSymbol];
+    pExist = 1;
+
+    if(!Entry) {
+      pExist = 0;
+      Entry = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
+      ++m_ValidEntryIterator;
+    }
+    result = Entry;
+  }
+  else {
+    pExist = 0;
+    result = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
+    ++m_ValidEntryIterator;
+  }
+  return result;
+}
+
diff --git a/lib/Target/PLT.cpp b/lib/Target/PLT.cpp
new file mode 100644
index 0000000..a29dfd8
--- /dev/null
+++ b/lib/Target/PLT.cpp
@@ -0,0 +1,42 @@
+//===- PLT.cpp ------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Target/PLT.h>
+
+using namespace mcld;
+
+class GOT;
+
+//===--------------------------------------------------------------------===//
+// PLTEntry
+PLTEntry::PLTEntry(size_t pSize, llvm::MCSectionData* pParent)
+   : MCTargetFragment(llvm::MCFragment::FT_Target, pParent),
+     m_EntrySize(pSize), m_pContent(NULL)
+{
+}
+
+PLTEntry::~PLTEntry()
+{
+  if (m_pContent) {
+    free(m_pContent);
+    m_pContent = NULL;
+  }
+}
+
+//===--------------------------------------------------------------------===//
+// PLT
+PLT::PLT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+  :m_Section(pSection),
+   m_SectionData(pSectionData)
+{
+}
+
+PLT::~PLT()
+{
+}
+
diff --git a/lib/Target/Stub.cpp b/lib/Target/Stub.cpp
new file mode 100644
index 0000000..4b59acf
--- /dev/null
+++ b/lib/Target/Stub.cpp
@@ -0,0 +1,15 @@
+//===- Stub.cpp -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "mcld/Target/Stub.h"
+
+using namespace mcld;
+
+//==========================
+// Stub
+
diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp
new file mode 100644
index 0000000..58178ec
--- /dev/null
+++ b/lib/Target/Target.cpp
@@ -0,0 +1,25 @@
+//===- Target.cpp ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "mcld/Support/TargetRegistry.h"
+#include "mcld/Target/TargetMachine.h"
+#include <llvm/Support/TargetRegistry.h>
+#include <llvm/Target/TargetMachine.h>
+
+using namespace llvm;
+using namespace mcld;
+
+/* ** */
+mcld::Target::Target()
+  : TargetMachineCtorFn(0),
+    SectLinkerCtorFn(0),
+    TargetLDBackendCtorFn(0),
+    m_pT(0)
+{
+}
+
diff --git a/lib/Target/TargetLDBackend.cpp b/lib/Target/TargetLDBackend.cpp
new file mode 100644
index 0000000..1a8ab6b
--- /dev/null
+++ b/lib/Target/TargetLDBackend.cpp
@@ -0,0 +1,23 @@
+//===- TargetLDBackend.cpp ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "mcld/LD/Relocation.h"
+#include "mcld/LD/Layout.h"
+#include "mcld/Target/TargetLDBackend.h"
+
+using namespace mcld;
+
+/* ** */
+TargetLDBackend::TargetLDBackend()
+{
+}
+
+TargetLDBackend::~TargetLDBackend()
+{
+}
+
diff --git a/lib/Target/X86/Android.mk b/lib/Target/X86/Android.mk
new file mode 100644
index 0000000..e9a051b
--- /dev/null
+++ b/lib/Target/X86/Android.mk
@@ -0,0 +1,41 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_x86_target_SRC_FILES := \
+  X86AndroidSectLinker.cpp  \
+  X86ELFDynamic.cpp \
+  X86ELFSectLinker.cpp  \
+  X86GOT.cpp  \
+  X86GOTPLT.cpp  \
+  X86LDBackend.cpp  \
+  X86PLT.cpp  \
+  X86RelocationFactory.cpp  \
+  X86SectLinker.cpp \
+  X86TargetMachine.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_x86_target_SRC_FILES)
+LOCAL_MODULE:= libmcldX86Target
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifeq ($(TARGET_ARCH),x86)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_x86_target_SRC_FILES)
+LOCAL_MODULE:= libmcldX86Target
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/lib/Target/X86/TargetInfo/Android.mk b/lib/Target/X86/TargetInfo/Android.mk
new file mode 100644
index 0000000..3664933
--- /dev/null
+++ b/lib/Target/X86/TargetInfo/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_x86_info_SRC_FILES := \
+  X86TargetInfo.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_x86_info_SRC_FILES)
+LOCAL_MODULE:= libmcldX86Info
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+ifeq ($(TARGET_ARCH),x86)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_x86_info_SRC_FILES)
+LOCAL_MODULE:= libmcldX86Info
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
new file mode 100644
index 0000000..afe349e
--- /dev/null
+++ b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
@@ -0,0 +1,22 @@
+//===- X86TargetInfo.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 TheX86Target;
+
+extern "C" void LLVMInitializeX86LDTargetInfo() {
+  // register into mcld::TargetRegistry
+  mcld::RegisterTarget X(TheX86Target, "x86");
+}
+
+} // namespace of mcld
+
diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h
new file mode 100644
index 0000000..2d07314
--- /dev/null
+++ b/lib/Target/X86/X86.h
@@ -0,0 +1,24 @@
+//===- X86.h --------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_X86_H
+#define MCLD_X86_H
+#include <string>
+#include "mcld/Target/TargetMachine.h"
+
+namespace mcld {
+class TargetLDBackend;
+
+extern mcld::Target TheX86Target;
+
+TargetLDBackend *createX86LDBackend(const llvm::Target&, const std::string&);
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86AndroidSectLinker.cpp b/lib/Target/X86/X86AndroidSectLinker.cpp
new file mode 100644
index 0000000..91b466c
--- /dev/null
+++ b/lib/Target/X86/X86AndroidSectLinker.cpp
@@ -0,0 +1,35 @@
+//===- X86AndroidSectLinker.cpp -------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86AndroidSectLinker.h"
+
+#include <mcld/CodeGen/SectLinkerOption.h>
+
+using namespace mcld;
+
+X86AndroidSectLinker::X86AndroidSectLinker(SectLinkerOption &pOption,
+                                           TargetLDBackend &pLDBackend)
+  : AndroidSectLinker(pOption,
+                      pLDBackend) {
+  MCLDInfo &info = pOption.info();
+  // set up target-dependent constraints of attibutes
+  info.attrFactory().constraint().disableWholeArchive();
+  info.attrFactory().constraint().disableAsNeeded();
+  info.attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  info.attrFactory().predefined().unsetWholeArchive();
+  info.attrFactory().predefined().setDynamic();
+
+}
+
+X86AndroidSectLinker::~X86AndroidSectLinker()
+{
+}
+
diff --git a/lib/Target/X86/X86AndroidSectLinker.h b/lib/Target/X86/X86AndroidSectLinker.h
new file mode 100644
index 0000000..b275aca
--- /dev/null
+++ b/lib/Target/X86/X86AndroidSectLinker.h
@@ -0,0 +1,38 @@
+//===- X86AndroidSectLinker.h ---------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef X86_ANDROIDSECTLINKER_H
+#define X86_ANDROIDSECTLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/AndroidSectLinker.h>
+
+namespace mcld
+{
+
+/** \class X86AndroidSectLinker
+ *  \brief X86AndroidSectLinker sets up the environment for linking.
+ *
+ *  \see
+ *  \author Anders Cheng <Anders.Cheng@mediatek.com>
+ */
+class X86AndroidSectLinker : public AndroidSectLinker
+{
+public:
+  X86AndroidSectLinker(SectLinkerOption &pOption,
+                       mcld::TargetLDBackend &pLDBackend);
+
+  ~X86AndroidSectLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86ELFDynamic.cpp b/lib/Target/X86/X86ELFDynamic.cpp
new file mode 100644
index 0000000..c32cfa8
--- /dev/null
+++ b/lib/Target/X86/X86ELFDynamic.cpp
@@ -0,0 +1,41 @@
+//===- X86ELFDynamic.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 "X86ELFDynamic.h"
+
+using namespace mcld;
+
+X86ELFDynamic::X86ELFDynamic(const GNULDBackend& pParent)
+  : ELFDynamic(pParent), m_HasGOTPLT(false)
+{
+}
+
+X86ELFDynamic::~X86ELFDynamic()
+{
+}
+
+void X86ELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat)
+{
+  // reservePLTGOT
+  if (m_HasGOTPLT ? pFormat.hasGOTPLT() : pFormat.hasGOT())
+    reserveOne(llvm::ELF::DT_PLTGOT);
+}
+
+void X86ELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat)
+{
+  // applyPLTGOT
+  if (m_HasGOTPLT) {
+      if (pFormat.hasGOTPLT())
+	applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOTPLT().addr());
+  }
+  else if (pFormat.hasGOT())
+    applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOT().addr());
+}
+
diff --git a/lib/Target/X86/X86ELFDynamic.h b/lib/Target/X86/X86ELFDynamic.h
new file mode 100644
index 0000000..b9e70ce
--- /dev/null
+++ b/lib/Target/X86/X86ELFDynamic.h
@@ -0,0 +1,38 @@
+//===- X86ELFDynamic.h ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_X86_ELFDYNAMIC_SECTION_H
+#define MCLD_X86_ELFDYNAMIC_SECTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Target/ELFDynamic.h>
+
+namespace mcld {
+
+class X86ELFDynamic : public ELFDynamic
+{
+public:
+  X86ELFDynamic(const GNULDBackend& pParent);
+  ~X86ELFDynamic();
+
+private:
+  void reserveTargetEntries(const ELFFileFormat& pFormat);
+  void applyTargetEntries(const ELFFileFormat& pFormat);
+
+private:
+  // True if we have .got.plt section, which will avoid GOT0 entries
+  // when PLT isn't used.  To support .got.plt section, we must combine
+  // .got section and .got.plt section into a single GOT.
+  bool m_HasGOTPLT;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/X86/X86ELFSectLinker.cpp b/lib/Target/X86/X86ELFSectLinker.cpp
new file mode 100644
index 0000000..009293c
--- /dev/null
+++ b/lib/Target/X86/X86ELFSectLinker.cpp
@@ -0,0 +1,34 @@
+//===- X86ELFSectLinker.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86ELFSectLinker.h"
+
+#include <mcld/CodeGen/SectLinkerOption.h>
+
+using namespace mcld;
+
+X86ELFSectLinker::X86ELFSectLinker(SectLinkerOption &pOption,
+                                   TargetLDBackend &pLDBackend)
+  : SectLinker(pOption,
+               pLDBackend) {
+  MCLDInfo &info = pOption.info();
+  // set up target-dependent constraints of attibutes
+  info.attrFactory().constraint().enableWholeArchive();
+  info.attrFactory().constraint().disableAsNeeded();
+  info.attrFactory().constraint().setSharedSystem();
+
+  // set up the predefined attributes
+  info.attrFactory().predefined().setWholeArchive();
+  info.attrFactory().predefined().setDynamic();
+
+}
+
+X86ELFSectLinker::~X86ELFSectLinker()
+{
+}
+
diff --git a/lib/Target/X86/X86ELFSectLinker.h b/lib/Target/X86/X86ELFSectLinker.h
new file mode 100644
index 0000000..5e7abfd
--- /dev/null
+++ b/lib/Target/X86/X86ELFSectLinker.h
@@ -0,0 +1,36 @@
+//===- X86ELFSectLinker.h -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef X86_ELFSECTLINKER_H
+#define X86_ELFSECTLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/CodeGen/SectLinker.h>
+
+namespace mcld
+{
+
+/** \class X86ELFSectLinker
+ *  \brief X86ELFSectLinker sets up the environment for linking.
+ *
+ *  \see
+ */
+class X86ELFSectLinker : public SectLinker
+{
+public:
+  X86ELFSectLinker(SectLinkerOption &pOption,
+                   mcld::TargetLDBackend &pLDBackend);
+
+  ~X86ELFSectLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
new file mode 100644
index 0000000..2784989
--- /dev/null
+++ b/lib/Target/X86/X86GOT.cpp
@@ -0,0 +1,129 @@
+//===- impl.cpp -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86GOT.h"
+#include <mcld/LD/LDFileFormat.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <new>
+
+namespace {
+  const size_t X86GOTEntrySize = 4;
+}
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// X86GOT
+X86GOT::X86GOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+             : GOT(pSection, pSectionData, X86GOTEntrySize),
+               m_GeneralGOTNum(0), m_GOTPLTNum(0), m_GeneralGOTIterator(),
+               m_GOTPLTIterator(), m_LastGOT0()
+{
+  GOTEntry* Entry = 0;
+
+  // Create GOT0 entries.
+  for (unsigned int i = 0; i < X86GOT0Num; i++) {
+    Entry = new (std::nothrow) GOTEntry(0, X86GOTEntrySize,
+                                        &m_SectionData);
+
+    if (!Entry)
+      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+
+    m_Section.setSize(m_Section.size() + X86GOTEntrySize);
+  }
+
+  // Skip GOT0 entries.
+  iterator it = m_SectionData.begin();
+  iterator ie = m_SectionData.end();
+
+  for (unsigned int i = 1; i < X86GOT0Num; ++i) {
+    if (it == ie)
+      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
+
+    ++it;
+  }
+
+  m_LastGOT0 = it;
+  m_GeneralGOTIterator = it;
+  m_GOTPLTIterator = it;
+}
+
+X86GOT::~X86GOT()
+{
+}
+
+void X86GOT::reserveEntry(size_t pNum)
+{
+  GOTEntry* Entry = 0;
+
+  for (size_t i = 0; i < pNum; i++) {
+    Entry = new (std::nothrow) GOTEntry(0, X86GOTEntrySize,
+                                        &m_SectionData);
+
+    if (!Entry)
+      llvm::report_fatal_error("Allocating new memory for GOTEntry failed");
+
+    m_Section.setSize(m_Section.size() + X86GOTEntrySize);
+    ++m_GeneralGOTNum;
+  }
+}
+
+
+GOTEntry* X86GOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
+{
+  GOTEntry *&Entry = m_GeneralGOTMap[&pInfo];
+  pExist = 1;
+
+  if (!Entry) {
+    pExist = 0;
+
+    ++m_GeneralGOTIterator;
+    assert(m_GeneralGOTIterator != m_SectionData.getFragmentList().end()
+           && "The number of GOT Entries and ResolveInfo doesn't match!");
+
+    Entry = llvm::cast<GOTEntry>(&(*m_GeneralGOTIterator));
+  }
+
+  return Entry;
+}
+
+void X86GOT::applyGOT0(uint64_t pAddress)
+{
+  llvm::cast<GOTEntry>
+    (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
+}
+
+X86GOT::iterator X86GOT::begin()
+{
+  return m_SectionData.getFragmentList().begin();
+}
+
+X86GOT::const_iterator X86GOT::begin() const
+{
+  return m_SectionData.getFragmentList().begin();
+}
+
+X86GOT::iterator X86GOT::end()
+{
+  return m_SectionData.getFragmentList().end();
+}
+
+X86GOT::const_iterator X86GOT::end() const
+{
+  return m_SectionData.getFragmentList().end();
+}
+
+unsigned int X86GOT::getGOTPLTNum() const
+{ return m_GOTPLTNum; }
+
+X86GOT::iterator X86GOT::getLastGOT0()
+{ return m_LastGOT0; }
+
+const X86GOT::iterator X86GOT::getLastGOT0() const
+{ return m_LastGOT0; }
+
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
new file mode 100644
index 0000000..018aa24
--- /dev/null
+++ b/lib/Target/X86/X86GOT.h
@@ -0,0 +1,91 @@
+//===- X86GOT.h -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_X86_GOT_H
+#define MCLD_X86_GOT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include "X86PLT.h"
+#include <mcld/Target/GOT.h>
+
+namespace mcld
+{
+class LDSection;
+
+/** \class X86GOT
+ *  \brief X86 Global Offset Table.
+ */
+
+const unsigned int X86GOT0Num = 3;
+
+class X86GOT : public GOT
+{
+  friend void mcld::X86PLT::reserveEntry(size_t pNum);
+
+  friend mcld::PLTEntry* mcld::X86PLT::getPLTEntry(
+         const mcld::ResolveInfo& pSymbol,bool& pExist);
+
+  friend mcld::GOTEntry* mcld::X86PLT::getGOTPLTEntry(
+         const mcld::ResolveInfo& pSymbol,bool& pExist);
+
+  typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
+
+public:
+  typedef llvm::MCSectionData::iterator iterator;
+  typedef llvm::MCSectionData::const_iterator const_iterator;
+
+public:
+  X86GOT(LDSection& pSection, llvm::MCSectionData& pSectionData);
+
+  ~X86GOT();
+
+  //Reserve general GOT entries.
+  void reserveEntry(size_t pNum = 1);
+
+  GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
+
+  void applyGOT0(uint64_t pAddress);
+
+  iterator begin();
+
+  const_iterator begin() const;
+
+  iterator end();
+
+  const_iterator end() const;
+
+  unsigned int getGOTPLTNum() const;
+
+  iterator getLastGOT0();
+
+  const iterator getLastGOT0() const;
+
+private:
+
+  unsigned int m_GeneralGOTNum;
+  unsigned int m_GOTPLTNum;
+
+  // Used by getGeneralGOTEntry()
+  iterator m_GeneralGOTIterator;
+
+  // Used by getGOTPLTEntry()
+  iterator m_GOTPLTIterator;
+
+  // The last GOT0 entry
+  iterator m_LastGOT0;
+
+  SymbolIndexMapType m_GOTPLTMap;
+  SymbolIndexMapType m_GeneralGOTMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
new file mode 100644
index 0000000..55596e3
--- /dev/null
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -0,0 +1,113 @@
+//===- X86GOTPLT.cpp ------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86GOTPLT.h"
+#include "mcld/LD/LDFileFormat.h"
+#include <llvm/Support/ErrorHandling.h>
+#include <new>
+
+namespace {
+  const uint64_t X86GOTPLTEntrySize = 4;
+}
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+// X86GOTPLT
+X86GOTPLT::X86GOTPLT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+  : GOT(pSection, pSectionData, X86GOTPLTEntrySize), m_GOTPLTIterator()
+{
+  GOTEntry* Entry = 0;
+
+  // Create GOT0 entries.
+  for (int i = 0; i < 3; i++) {
+    Entry = new (std::nothrow) GOTEntry(0, X86GOTPLTEntrySize,
+                                        &m_SectionData);
+
+    if (!Entry)
+      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+
+    m_Section.setSize(m_Section.size() + X86GOTPLTEntrySize);
+  }
+
+  // Skip GOT0 entries.
+  iterator it = m_SectionData.begin();
+  iterator ie = m_SectionData.end();
+
+  for (size_t i = 1; i < X86GOT0Num; ++i) {
+    if (it == ie)
+      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
+
+    ++it;
+  }
+
+  m_GOTPLTIterator = it;
+}
+
+X86GOTPLT::~X86GOTPLT()
+{
+}
+
+X86GOTPLT::iterator X86GOTPLT::begin()
+{
+  return m_SectionData.begin();
+}
+
+X86GOTPLT::const_iterator X86GOTPLT::begin() const
+{
+  return m_SectionData.begin();
+}
+
+X86GOTPLT::iterator X86GOTPLT::end()
+{
+  return m_SectionData.end();
+}
+
+X86GOTPLT::const_iterator X86GOTPLT::end() const
+{
+  return m_SectionData.end();
+}
+
+void X86GOTPLT::applyGOT0(const uint64_t pAddress)
+{
+  llvm::cast<GOTEntry>
+    (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
+}
+
+void X86GOTPLT::reserveGOTPLTEntry()
+{
+    GOTEntry* got_entry = 0;
+
+    got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
+
+    if (!got_entry)
+      llvm::report_fatal_error("Allocating new memory for GOT failed!");
+
+    m_Section.setSize(m_Section.size() + getEntrySize());
+}
+
+void X86GOTPLT::applyAllGOTPLT(const uint64_t pPLTBase)
+{
+  iterator gotplt_it = begin();
+  iterator gotplt_ie = end();
+
+  for (; gotplt_it != gotplt_ie; ++gotplt_it)
+    llvm::cast<GOTEntry>(*gotplt_it).setContent(pPLTBase);
+}
+
+GOTEntry*& X86GOTPLT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
+{
+  return m_GOTPLTMap[&pSymbol];
+}
+
+X86GOTPLT::iterator X86GOTPLT::getNextGOTPLTEntry()
+{
+  return ++m_GOTPLTIterator;
+}
+
+} //end mcld namespace
diff --git a/lib/Target/X86/X86GOTPLT.h b/lib/Target/X86/X86GOTPLT.h
new file mode 100644
index 0000000..9882cc4
--- /dev/null
+++ b/lib/Target/X86/X86GOTPLT.h
@@ -0,0 +1,70 @@
+//===- X86GOTPLT.h --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_X86_GOTPLT_H
+#define MCLD_X86_GOTPLT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include "mcld/Target/GOT.h"
+
+namespace mcld
+{
+class LDSection;
+
+/** \class X86GOTPLT
+ *  \brief X86 .got.plt section.
+ */
+
+const unsigned int X86GOT0Num = 3;
+
+class X86GOTPLT : public GOT
+{
+  typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
+
+public:
+  typedef llvm::MCSectionData::iterator iterator;
+  typedef llvm::MCSectionData::const_iterator const_iterator;
+
+public:
+  X86GOTPLT(LDSection &pSection, llvm::MCSectionData& pSectionData);
+
+  ~X86GOTPLT();
+
+  iterator begin();
+
+  const_iterator begin() const;
+
+  iterator end();
+
+  const_iterator end() const;
+
+// For GOT0
+public:
+  void applyGOT0(const uint64_t pAddress);
+
+// For GOTPLT
+public:
+  void reserveGOTPLTEntry();
+
+  void applyAllGOTPLT(const uint64_t pPLTBase);
+
+  GOTEntry*& lookupGOTPLTMap(const ResolveInfo& pSymbol);
+
+  iterator getNextGOTPLTEntry();
+
+private:
+  iterator m_GOTPLTIterator;
+  SymbolIndexMapType m_GOTPLTMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
new file mode 100644
index 0000000..354cd51
--- /dev/null
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -0,0 +1,752 @@
+//===- X86LDBackend.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86.h"
+#include "X86ELFDynamic.h"
+#include "X86LDBackend.h"
+#include "X86RelocationFactory.h"
+
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDOutput.h>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/LD/SectionMap.h>
+#include <mcld/MC/MCRegionFragment.h>
+
+#include <cstring>
+
+using namespace mcld;
+
+X86GNULDBackend::X86GNULDBackend()
+  : m_pRelocFactory(NULL),
+    m_pGOT(NULL),
+    m_pPLT(NULL),
+    m_pRelDyn(NULL),
+    m_pRelPLT(NULL),
+    m_pDynamic(NULL) {
+}
+
+X86GNULDBackend::~X86GNULDBackend()
+{
+  if (NULL != m_pRelocFactory)
+    delete m_pRelocFactory;
+  if (NULL != m_pGOT)
+    delete m_pGOT;
+  if (NULL != m_pPLT)
+    delete m_pPLT;
+  if (NULL !=m_pRelDyn)
+    delete m_pRelDyn;
+  if (NULL != m_pRelPLT)
+    delete m_pRelPLT;
+  if (NULL != m_pDynamic)
+    delete m_pDynamic;
+}
+
+RelocationFactory* X86GNULDBackend::getRelocFactory()
+{
+  assert(NULL != m_pRelocFactory);
+  return m_pRelocFactory;
+}
+
+bool X86GNULDBackend::initRelocFactory(const MCLinker& pLinker)
+{
+  if (NULL == m_pRelocFactory) {
+    m_pRelocFactory = new X86RelocationFactory(1024, *this);
+    m_pRelocFactory->setLayout(pLinker.getLayout());
+  }
+  return true;
+}
+
+void X86GNULDBackend::doPreLayout(const Output& pOutput,
+                                  const MCLDInfo& pInfo,
+                                  MCLinker& pLinker)
+{
+  // when building shared object, the .got section is needed
+  if(pOutput.type() == Output::DynObj && (NULL == m_pGOT))
+      createX86GOT(pLinker, pOutput);
+}
+
+void X86GNULDBackend::doPostLayout(const Output& pOutput,
+                                   const MCLDInfo& pInfo,
+                                   MCLinker& pLinker)
+{
+  // emit program headers
+  if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
+    emitProgramHdrs(pLinker.getLDInfo().output());
+}
+
+/// dynamic - the dynamic section of the target machine.
+/// Use co-variant return type to return its own dynamic section.
+X86ELFDynamic& X86GNULDBackend::dynamic()
+{
+  if (NULL == m_pDynamic)
+    m_pDynamic = new X86ELFDynamic(*this);
+
+  return *m_pDynamic;
+}
+
+/// dynamic - the dynamic section of the target machine.
+/// Use co-variant return type to return its own dynamic section.
+const X86ELFDynamic& X86GNULDBackend::dynamic() const
+{
+  assert( NULL != m_pDynamic);
+  return *m_pDynamic;
+}
+
+void X86GNULDBackend::createX86GOT(MCLinker& pLinker, const Output& pOutput)
+{
+  // get .got LDSection and create MCSectionData
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  LDSection& got = file_format->getGOT();
+  m_pGOT = new X86GOT(got, pLinker.getOrCreateSectData(got));
+
+  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
+  if( m_pGOTSymbol != NULL ) {
+    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 X86GNULDBackend::createX86PLTandRelPLT(MCLinker& pLinker,
+                                            const Output& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  LDSection& plt = file_format->getPLT();
+  LDSection& relplt = file_format->getRelPlt();
+  // create MCSectionData and X86PLT
+  m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT, pOutput);
+
+  // set info of .rel.plt to .plt
+  relplt.setLink(&plt);
+  // create MCSectionData and X86RelDynSection
+  m_pRelPLT = new OutputRelocSection(relplt,
+                                     pLinker.getOrCreateSectData(relplt),
+                                     8);
+}
+
+void X86GNULDBackend::createX86RelDyn(MCLinker& pLinker,
+                                      const Output& pOutput)
+{
+  // get .rel.dyn LDSection and create MCSectionData
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  LDSection& reldyn = file_format->getRelDyn();
+  // create MCSectionData and X86RelDynSection
+  m_pRelDyn = new OutputRelocSection(reldyn,
+                                     pLinker.getOrCreateSectData(reldyn),
+                                     8);
+}
+
+ELFFileFormat* X86GNULDBackend::getOutputFormat(const Output& pOutput) const
+{
+  switch (pOutput.type()) {
+    case Output::DynObj:
+      return getDynObjFileFormat();
+    case Output::Exec:
+      return getExecFileFormat();
+    // FIXME: We do not support building .o now
+    case Output::Object:
+    default:
+      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
+                               llvm::Twine(pOutput.type()));
+      return NULL;
+  }
+}
+
+bool X86GNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym,
+                                       const MCLDInfo& pLDInfo,
+                                       const Output& pOutput) const
+{
+  return((Output::DynObj == pOutput.type())
+         &&(ResolveInfo::Function == pSym.type())
+         &&(pSym.isDyn() || pSym.isUndef() ||
+            isSymbolPreemptible(pSym, pLDInfo, pOutput))
+        );
+}
+
+bool X86GNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym,
+                                          const Output& pOutput,
+                                          bool isAbsReloc) const
+{
+  if(pSym.isUndef() && (pOutput.type()==Output::Exec))
+    return false;
+  if(pSym.isAbsolute())
+    return false;
+  if(pOutput.type()==Output::DynObj && isAbsReloc)
+    return true;
+  if(pSym.isDyn() || pSym.isUndef())
+    return true;
+
+  return false;
+}
+
+bool X86GNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
+                                         const MCLDInfo& pLDInfo,
+                                         const Output& pOutput) const
+{
+  if(pSym.other() != ResolveInfo::Default)
+    return false;
+
+  if(pOutput.type() != Output::DynObj)
+    return false;
+
+  if(pLDInfo.options().Bsymbolic())
+    return false;
+
+  return true;
+}
+
+void X86GNULDBackend::updateAddend(Relocation& pReloc,
+                                   const LDSymbol& pInputSym,
+                                   const Layout& pLayout) const
+{
+  // Update value keep in addend if we meet a section symbol
+  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+    pReloc.setAddend(pLayout.getOutputOffset(
+                     *pInputSym.fragRef()) + pReloc.addend());
+  }
+}
+
+void X86GNULDBackend::scanLocalReloc(Relocation& pReloc,
+                                     const LDSymbol& pInputSym,
+                                     MCLinker& pLinker,
+                                     const MCLDInfo& pLDInfo,
+                                     const Output& pOutput)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  updateAddend(pReloc, pInputSym, pLinker.getLayout());
+
+  switch(pReloc.type()){
+
+    case llvm::ELF::R_386_32:
+      // If buiding PIC object (shared library or PIC executable),
+      // a dynamic relocations with RELATIVE type to this location is needed.
+      // Reserve an entry in .rel.dyn
+      if(Output::DynObj == pOutput.type()) {
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createX86RelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+      }
+      return;
+
+    case llvm::ELF::R_386_GOTOFF:
+    case llvm::ELF::R_386_GOTPC:
+      // A GOT section is needed
+      if(NULL == m_pGOT)
+        createX86GOT(pLinker, pOutput);
+      return;
+
+    case llvm::ELF::R_386_PC32:
+      return;
+
+    default:
+      llvm::report_fatal_error(llvm::Twine("unexpected reloc ") +
+                               llvm::Twine((int) pReloc.type()) +
+                               llvm::Twine(" in object file"));
+      break;
+  } // end switch
+}
+
+void X86GNULDBackend::scanGlobalReloc(Relocation& pReloc,
+                                      const LDSymbol& pInputSym,
+                                      MCLinker& pLinker,
+                                      const MCLDInfo& pLDInfo,
+                                      const Output& pOutput)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+
+  switch(pReloc.type()) {
+    case llvm::ELF::R_386_32:
+      // Absolute relocation type, symbol may needs PLT entry or
+      // dynamic relocation entry
+      if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+        // create plt for this symbol if it does not have one
+        if(!(rsym->reserved() & ReservePLT)){
+          // Create .got section if it dosen't exist
+          if(NULL == m_pGOT)
+             createX86GOT(pLinker, pOutput);
+          // create .plt and .rel.plt if not exist
+          if(NULL == m_pPLT)
+            createX86PLTandRelPLT(pLinker, pOutput);
+          // Symbol needs PLT entry, we need to reserve a PLT entry
+          // and the corresponding GOT and dynamic relocation entry
+          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
+          // when calling X86PLT->reserveEntry())
+          m_pPLT->reserveEntry();
+          m_pRelPLT->reserveEntry(*m_pRelocFactory);
+          // set PLT bit
+          rsym->setReserved(rsym->reserved() | ReservePLT);
+        }
+      }
+
+      if(isSymbolNeedsDynRel(*rsym, pOutput, true)) {
+        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createX86RelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set Rel bit
+        rsym->setReserved(rsym->reserved() | ReserveRel);
+      }
+      return;
+
+    case llvm::ELF::R_386_GOTOFF:
+    case llvm::ELF::R_386_GOTPC: {
+      // A GOT section is needed
+      if(NULL == m_pGOT)
+        createX86GOT(pLinker, pOutput);
+      return;
+    }
+
+    case llvm::ELF::R_386_PLT32:
+      // A PLT entry is needed when building shared library
+
+      // return if we already create plt for this symbol
+      if(rsym->reserved() & ReservePLT)
+        return;
+
+      // if symbol is defined in the ouput file and it's not
+      // preemptible, no need plt
+      if(rsym->isDefine() && !rsym->isDyn() &&
+         !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
+        return;
+      }
+
+      // Create .got section if it dosen't exist
+      if(NULL == m_pGOT)
+         createX86GOT(pLinker, pOutput);
+      // create .plt and .rel.plt if not exist
+      if(NULL == m_pPLT)
+         createX86PLTandRelPLT(pLinker, pOutput);
+      // Symbol needs PLT entry, we need to reserve a PLT entry
+      // and the corresponding GOT and dynamic relocation entry
+      // in .got and .rel.plt. (GOT entry will be reserved simultaneously
+      // when calling X86PLT->reserveEntry())
+      m_pPLT->reserveEntry();
+      m_pRelPLT->reserveEntry(*m_pRelocFactory);
+      // set PLT bit
+      rsym->setReserved(rsym->reserved() | ReservePLT);
+      return;
+
+    case llvm::ELF::R_386_GOT32:
+      // Symbol needs GOT entry, reserve entry in .got
+      // return if we already create GOT for this symbol
+      if(rsym->reserved() & (ReserveGOT | GOTRel))
+        return;
+      if(NULL == m_pGOT)
+        createX86GOT(pLinker, pOutput);
+      m_pGOT->reserveEntry();
+      // If building shared object or the symbol is undefined, a dynamic
+      // relocation is needed to relocate this GOT entry. Reserve an
+      // entry in .rel.dyn
+      if(Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
+        // create .rel.dyn section if not exist
+        if(NULL == m_pRelDyn)
+          createX86RelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        // set GOTRel bit
+        rsym->setReserved(rsym->reserved() | GOTRel);
+        return;
+      }
+      // set GOT bit
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
+      return;
+
+    case llvm::ELF::R_386_PC32:
+      // We allow R_386_PC32 only if it isn't preemptible.  Otherwise
+      // we will generate writable text section in output.
+      if (!isSymbolPreemptible(*rsym, pLDInfo, pOutput))
+	return;
+
+    default: {
+      llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") +
+                               llvm::Twine((int) pReloc.type()) +
+                               llvm::Twine(" in object file"));
+      break;
+    }
+  } // end switch
+}
+
+void X86GNULDBackend::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");
+
+  // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
+  // entries should be created.
+  // FIXME: Below judgements concern only .so is generated as output
+  // FIXME: Below judgements concren nothing about TLS related relocation
+
+  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section
+  // is needed
+  if(NULL == m_pGOT && NULL != m_pGOTSymbol) {
+    if(rsym == m_pGOTSymbol->resolveInfo()) {
+      createX86GOT(pLinker, pOutput);
+    }
+  }
+
+  // rsym is local
+  if(rsym->isLocal())
+    scanLocalReloc(pReloc, pInputSym,  pLinker, pLDInfo, pOutput);
+
+  // rsym is external
+  else
+    scanGlobalReloc(pReloc, pInputSym ,pLinker, pLDInfo, pOutput);
+
+}
+
+uint64_t X86GNULDBackend::emitSectionData(const Output& pOutput,
+                                          const LDSection& pSection,
+                                          const MCLDInfo& pInfo,
+                                          MemoryRegion& pRegion) const
+{
+  assert(pRegion.size() && "Size of MemoryRegion is zero!");
+
+  ELFFileFormat* FileFormat = getOutputFormat(pOutput);
+  assert(FileFormat &&
+         "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
+
+  unsigned int EntrySize = 0;
+  uint64_t RegionSize = 0;
+
+  if (&pSection == &(FileFormat->getPLT())) {
+    assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
+
+    unsigned char* buffer = pRegion.getBuffer();
+
+    m_pPLT->applyPLT0();
+    m_pPLT->applyPLT1();
+
+    X86PLT::iterator it = m_pPLT->begin();
+    unsigned int plt0_size = llvm::cast<X86PLT0>((*it)).getEntrySize();
+
+    memcpy(buffer, llvm::cast<X86PLT0>((*it)).getContent(), plt0_size);
+    RegionSize += plt0_size;
+    ++it;
+
+    X86PLT1* plt1 = 0;
+    X86PLT::iterator ie = m_pPLT->end();
+    while (it != ie) {
+      plt1 = &(llvm::cast<X86PLT1>(*it));
+      EntrySize = plt1->getEntrySize();
+      memcpy(buffer + RegionSize, plt1->getContent(), EntrySize);
+      RegionSize += EntrySize;
+      ++it;
+    }
+  }
+
+  else if (&pSection == &(FileFormat->getGOT())) {
+    assert(m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
+
+    m_pGOT->applyGOT0(FileFormat->getDynamic().addr());
+
+    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+
+    GOTEntry* got = 0;
+    EntrySize = m_pGOT->getEntrySize();
+
+    for (X86GOT::iterator it = m_pGOT->begin(),
+         ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
+      got = &(llvm::cast<GOTEntry>((*it)));
+      *buffer = static_cast<uint32_t>(got->getContent());
+      RegionSize += EntrySize;
+    }
+  }
+
+  else
+    llvm::report_fatal_error("unsupported section name "
+                             + pSection.name() + " !");
+
+  return RegionSize;
+}
+uint32_t X86GNULDBackend::machine() const
+{
+  return llvm::ELF::EM_386;
+}
+
+X86GOT& X86GNULDBackend::getGOT()
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
+
+const X86GOT& X86GNULDBackend::getGOT() const
+{
+  assert(NULL != m_pGOT);
+  return *m_pGOT;
+}
+
+X86PLT& X86GNULDBackend::getPLT()
+{
+  assert(NULL != m_pPLT && "PLT section not exist");
+  return *m_pPLT;
+}
+
+const X86PLT& X86GNULDBackend::getPLT() const
+{
+  assert(NULL != m_pPLT && "PLT section not exist");
+  return *m_pPLT;
+}
+
+OutputRelocSection& X86GNULDBackend::getRelDyn()
+{
+  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
+  return *m_pRelDyn;
+}
+
+const OutputRelocSection& X86GNULDBackend::getRelDyn() const
+{
+  assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
+  return *m_pRelDyn;
+}
+
+OutputRelocSection& X86GNULDBackend::getRelPLT()
+{
+  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
+  return *m_pRelPLT;
+}
+
+const OutputRelocSection& X86GNULDBackend::getRelPLT() const
+{
+  assert(NULL != m_pRelPLT && ".rel.plt section not exist");
+  return *m_pRelPLT;
+}
+
+unsigned int
+X86GNULDBackend::getTargetSectionOrder(const Output& pOutput,
+                                       const LDSection& pSectHdr) const
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  // FIXME: if command line option, "-z now", is given, we can let the order of
+  // .got and .got.plt be the same as RELRO sections
+  if (&pSectHdr == &file_format->getGOT())
+    return SHO_RELRO_LAST;
+
+  if (&pSectHdr == &file_format->getGOTPLT())
+    return SHO_NON_RELRO_FIRST;
+
+  if (&pSectHdr == &file_format->getPLT())
+    return SHO_PLT;
+
+  return SHO_UNDEFINED;
+}
+
+unsigned int X86GNULDBackend::bitclass() const
+{
+  return 32;
+}
+
+bool X86GNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
+{
+  return true;
+}
+
+void X86GNULDBackend::initTargetSections(MCLinker& pLinker)
+{
+}
+
+void X86GNULDBackend::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);
+}
+
+/// finalizeSymbol - finalize the symbol value
+/// If the symbol's reserved field is not zero, MCLinker will call back this
+/// function to ask the final value of the symbol
+bool X86GNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+{
+  return false;
+}
+
+/// allocateCommonSymbols - allocate common symbols in the corresponding
+/// sections.
+/// @refer Google gold linker: common.cc: 214
+bool
+X86GNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
+{
+  // SymbolCategory contains all symbols that must emit to the output files.
+  // We are not like Google gold linker, we don't remember symbols before symbol
+  // resolution. All symbols in SymbolCategory are already resolved. Therefore, we
+  // don't need to care about some symbols may be changed its category due to symbol
+  // resolution.
+  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
+
+  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
+    return true;
+
+  // addralign := max value of all common symbols
+  uint64_t addralign = 0x0;
+
+  // Due to the visibility, some common symbols may be forcefully local.
+  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
+  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
+    if (ResolveInfo::Common == (*com_sym)->desc()) {
+      if ((*com_sym)->value() > addralign)
+        addralign = (*com_sym)->value();
+    }
+  }
+
+  // global common symbols.
+  com_end = symbol_list.commonEnd();
+  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
+    if ((*com_sym)->value() > addralign)
+      addralign = (*com_sym)->value();
+  }
+
+  // FIXME: If the order of common symbols is defined, then sort common symbols
+  // com_sym = symbol_list.commonBegin();
+  // std::sort(com_sym, com_end, some kind of order);
+
+  // get or create corresponding BSS LDSection
+  LDSection* bss_sect_hdr = NULL;
+  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
+                                   ".tbss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+  }
+  else {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+  }
+
+  // get or create corresponding BSS MCSectionData
+  assert(NULL != bss_sect_hdr);
+  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
+
+  // allocate all common symbols
+  uint64_t offset = bss_sect_hdr->size();
+
+  // allocate all local common symbols
+  com_end = symbol_list.localEnd();
+  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
+    if (ResolveInfo::Common == (*com_sym)->desc()) {
+      // We have to reset the description of the symbol here. When doing
+      // incremental linking, the output relocatable object may have common
+      // symbols. Therefore, we can not treat common symbols as normal symbols
+      // when emitting the regular name pools. We must change the symbols'
+      // description here.
+      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
+      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+      uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                         bss_section,
+                                                         (*com_sym)->value());
+      offset += size;
+    }
+  }
+
+  // allocate all global common symbols
+  com_end = symbol_list.commonEnd();
+  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
+    // We have to reset the description of the symbol here. When doing
+    // incremental linking, the output relocatable object may have common
+    // symbols. Therefore, we can not treat common symbols as normal symbols
+    // when emitting the regular name pools. We must change the symbols'
+    // description here.
+    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
+    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+    uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                       bss_section,
+                                                       (*com_sym)->value());
+    offset += size;
+  }
+
+  bss_sect_hdr->setSize(offset);
+  symbol_list.changeCommonsToGlobal();
+  return true;
+}
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+/// createX86LDBackend - the help funtion to create corresponding X86LDBackend
+///
+TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget,
+                                    const std::string& pTriple)
+{
+  Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker is not supported yet");
+    /**
+    return new X86MachOLDBackend(createX86MachOArchiveReader,
+                               createX86MachOObjectReader,
+                               createX86MachOObjectWriter);
+    **/
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker is not supported yet");
+    /**
+    return new X86COFFLDBackend(createX86COFFArchiveReader,
+                               createX86COFFObjectReader,
+                               createX86COFFObjectWriter);
+    **/
+  }
+  return new X86GNULDBackend();
+}
+
+} // namespace of mcld
+
+//=============================
+// Force static initialization.
+extern "C" void LLVMInitializeX86LDBackend() {
+  // Register the linker backend
+  mcld::TargetRegistry::RegisterTargetLDBackend(TheX86Target, createX86LDBackend);
+}
diff --git a/lib/Target/X86/X86LDBackend.h b/lib/Target/X86/X86LDBackend.h
new file mode 100644
index 0000000..d9a4d56
--- /dev/null
+++ b/lib/Target/X86/X86LDBackend.h
@@ -0,0 +1,257 @@
+//===- X86LDBackend.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef X86_LDBACKEND_H
+#define X86_LDBACKEND_H
+
+#include "X86ELFDynamic.h"
+#include "X86GOT.h"
+#include "X86PLT.h"
+#include <mcld/LD/LDSection.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Target/OutputRelocSection.h>
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+/// X86GNULDBackend - linker backend of X86 target of GNU ELF format
+///
+class X86GNULDBackend : public GNULDBackend
+{
+public:
+  /** \enum ReservedEntryType
+   *  \brief The reserved entry type of reserved space in ResolveInfo.
+   *
+   *  This is used for sacnRelocation to record what kinds of entries are
+   *  reserved for this resolved symbol
+   *
+   *  In X86, there are three kinds of entries, GOT, PLT, and dynamic reloction.
+   *  GOT may needs a corresponding relocation to relocate itself, so we
+   *  separate GOT to two situations: GOT and GOTRel. Besides, for the same
+   *  symbol, there might be two kinds of entries reserved for different location.
+   *  For example, reference to the same symbol, one may use GOT and the other may
+   *  use dynamic relocation.
+   *
+   *  bit:  3       2      1     0
+   *   | PLT | GOTRel | GOT | Rel |
+   *
+   *  value    Name         - Description
+   *
+   *  0000     None         - no reserved entry
+   *  0001     ReserveRel   - reserve an dynamic relocation entry
+   *  0010     ReserveGOT   - reserve an GOT entry
+   *  0011     GOTandRel    - For different relocation, we've reserved GOT and
+   *                          Rel for different location.
+   *  0100     GOTRel       - reserve an GOT entry and the corresponding Dyncamic
+   *                          relocation entry which relocate this GOT entry
+   *  0101     GOTRelandRel - For different relocation, we've reserved GOTRel
+   *                          and relocation entry for different location.
+   *  1000     ReservePLT   - reserve an PLT entry and the corresponding GOT,
+   *                          Dynamic relocation entries
+   *  1001     PLTandRel    - For different relocation, we've reserved PLT and
+   *                          Rel for different location.
+   */
+  enum ReservedEntryType {
+    None         = 0,
+    ReserveRel   = 1,
+    ReserveGOT   = 2,
+    GOTandRel    = 3,
+    GOTRel       = 4,
+    GOTRelandRel = 5,
+    ReservePLT   = 8,
+    PLTandRel    = 9
+  };
+
+  X86GNULDBackend();
+
+  ~X86GNULDBackend();
+
+  RelocationFactory* getRelocFactory();
+
+  uint32_t machine() const;
+
+  bool isLittleEndian() const
+  { return true; }
+
+  X86GOT& getGOT();
+
+  const X86GOT& getGOT() const;
+
+  X86PLT& getPLT();
+
+  const X86PLT& getPLT() 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.
+  X86ELFDynamic& dynamic();
+
+  /// dynamic - the dynamic section of the target machine.
+  /// Use co-variant return type to return its own dynamic section.
+  const X86ELFDynamic& 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;
+
+  /// OSABI - the value of e_ident[EI_OSABI]
+  /// FIXME
+  uint8_t OSABI() const
+  { return llvm::ELF::ELFOSABI_NONE; }
+
+  /// ABIVersion - the value of e_ident[EI_ABIVRESION]
+  /// FIXME
+  uint8_t ABIVersion() const
+  { return 0x0; }
+
+  /// flags - the value of ElfXX_Ehdr::e_flags
+  /// FIXME
+  uint64_t flags() const
+  { return 0x0; }
+
+  /// initTargetSectionMap - initialize target dependent section mapping
+  bool initTargetSectionMap(SectionMap& pSectionMap);
+
+  // initRelocFactory - create and initialize RelocationFactory
+  bool initRelocFactory(const MCLinker& pLinker);
+
+  void initTargetSections(MCLinker& pLinker);
+
+  void initTargetSymbols(MCLinker& pLinker);
+
+  /// scanRelocation - determine the empty entries are needed or not and create
+  /// the empty entries if needed.
+  /// For X86, following entries are check to create:
+  /// - GOT entry (for .got and .got.plt sections)
+  /// - PLT entry (for .plt section)
+  /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
+  void scanRelocation(Relocation& pReloc,
+                      const LDSymbol& pInputSym,
+                      MCLinker& pLinker,
+                      const MCLDInfo& pLDInfo,
+                      const Output& pOutput);
+
+  OutputRelocSection& getRelDyn();
+
+  const OutputRelocSection& getRelDyn() const;
+
+  OutputRelocSection& getRelPLT();
+
+  const OutputRelocSection& getRelPLT() const;
+
+  /// getTargetSectionOrder - compute the layout order of X86 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;
+
+public:
+  bool isSymbolPreemptible(const ResolveInfo& pSym,
+                           const MCLDInfo& pLDInfo,
+                           const Output& pOutput) 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(const ResolveInfo& pSym,
+                        const MCLDInfo& pLDInfo,
+                        const Output& pOutput) const;
+
+  bool isSymbolNeedsDynRel(const ResolveInfo& pSym,
+                           const Output& pOutput,
+                           bool isAbsReloc) const;
+
+  void updateAddend(Relocation& pReloc,
+                    const LDSymbol& pInputSym,
+                    const Layout& pLayout) const;
+
+  void createX86GOT(MCLinker& pLinker, const Output& pOutput);
+  void createX86PLTandRelPLT(MCLinker& pLinker, const Output& pOutput);
+  void createX86RelDyn(MCLinker& pLinker, const Output& pOutput);
+
+  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
+
+private:
+  RelocationFactory* m_pRelocFactory;
+  X86GOT* m_pGOT;
+  X86PLT* m_pPLT;
+  /// m_RelDyn - dynamic relocation table of .rel.dyn
+  OutputRelocSection* m_pRelDyn;
+  /// m_RelPLT - dynamic relocation table of .rel.plt
+  OutputRelocSection* m_pRelPLT;
+
+  X86ELFDynamic* m_pDynamic;
+  LDSymbol* m_pGOTSymbol;
+};
+
+//===----------------------------------------------------------------------===//
+/// X86MachOLDBackend - linker backend of X86 target of MachO format
+///
+/**
+class X86MachOLDBackend : public DarwinX86LDBackend
+{
+public:
+  X86MachOLDBackend();
+  ~X86MachOLDBackend();
+
+private:
+  MCMachOTargetArchiveReader *createTargetArchiveReader() const;
+  MCMachOTargetObjectReader *createTargetObjectReader() const;
+  MCMachOTargetObjectWriter *createTargetObjectWriter() const;
+
+};
+**/
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
new file mode 100644
index 0000000..c5e05f9
--- /dev/null
+++ b/lib/Target/X86/X86PLT.cpp
@@ -0,0 +1,279 @@
+//===- X86PLT.cpp -----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86GOT.h"
+#include "X86PLT.h"
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <llvm/Support/ELF.h>
+#include <mcld/MC/MCLDOutput.h>
+#include <new>
+
+namespace {
+
+const uint8_t x86_dyn_plt0[] = {
+  0xff, 0xb3, 0x04, 0, 0, 0,		// pushl  0x4(%ebx)
+  0xff, 0xa3, 0x08, 0, 0, 0,		// jmp    *0x8(%ebx)
+  0xf, 0x1f, 0x4, 0			// nopl   0(%eax)
+};
+
+const uint8_t x86_dyn_plt1[] = {
+  0xff, 0xa3, 0, 0, 0, 0,		// jmp    *sym@GOT(%ebx)
+  0x68, 0, 0, 0, 0,			// pushl  $offset
+  0xe9, 0, 0, 0, 0			// jmp    plt0
+};
+
+const uint8_t x86_exec_plt0[] = {
+  0xff, 0x35, 0, 0, 0, 0,		// pushl  .got + 4
+  0xff, 0x25, 0, 0, 0, 0,		// jmp    *(.got + 8)
+  0xf, 0x1f, 0x4, 0			// nopl   0(%eax)
+};
+
+const uint8_t x86_exec_plt1[] = {
+  0xff, 0x25, 0, 0, 0, 0,		// jmp    *(sym in .got)
+  0x68, 0, 0, 0, 0,			// pushl  $offset
+  0xe9, 0, 0, 0, 0			// jmp    plt0
+};
+
+}
+
+namespace mcld {
+
+X86PLT0::X86PLT0(llvm::MCSectionData* pParent, unsigned int pSize)
+  : PLTEntry(pSize, pParent) { }
+
+X86PLT1::X86PLT1(llvm::MCSectionData* pParent, unsigned int pSize)
+  : PLTEntry(pSize, pParent) { }
+
+//===----------------------------------------------------------------------===//
+// X86PLT
+
+X86PLT::X86PLT(LDSection& pSection,
+               llvm::MCSectionData& pSectionData,
+               X86GOT &pGOTPLT,
+	       const Output& pOutput)
+  : PLT(pSection, pSectionData), m_GOT(pGOTPLT), m_PLTEntryIterator()
+{
+  assert (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type());
+  if (Output::DynObj == pOutput.type()) {
+      m_PLT0 = x86_dyn_plt0;
+      m_PLT1 = x86_dyn_plt1;
+      m_PLT0Size = sizeof (x86_dyn_plt0);
+      m_PLT1Size = sizeof (x86_dyn_plt1);
+  }
+  else {
+      m_PLT0 = x86_exec_plt0;
+      m_PLT1 = x86_exec_plt1;
+      m_PLT0Size = sizeof (x86_exec_plt0);
+      m_PLT1Size = sizeof (x86_exec_plt1);
+  }
+  X86PLT0* plt0_entry = new X86PLT0(&m_SectionData, m_PLT0Size);
+
+  m_Section.setSize(m_Section.size() + plt0_entry->getEntrySize());
+
+  m_PLTEntryIterator = pSectionData.begin();
+}
+
+X86PLT::~X86PLT()
+{
+}
+
+void X86PLT::reserveEntry(size_t pNum)
+{
+  X86PLT1* plt1_entry = 0;
+  GOTEntry* got_entry = 0;
+
+  for (size_t i = 0; i < pNum; ++i) {
+    plt1_entry = new (std::nothrow) X86PLT1(&m_SectionData, m_PLT1Size);
+
+    if (!plt1_entry)
+      llvm::report_fatal_error("Allocating new memory for X86PLT1 failed!");
+
+    m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
+
+    got_entry= new (std::nothrow) GOTEntry(0, m_GOT.getEntrySize(),
+                                           &(m_GOT.m_SectionData));
+
+    if (!got_entry)
+      llvm::report_fatal_error("Allocating new memory for GOT failed!");
+
+    m_GOT.m_Section.setSize(m_GOT.m_Section.size() + m_GOT.f_EntrySize);
+
+    ++(m_GOT.m_GOTPLTNum);
+    ++(m_GOT.m_GeneralGOTIterator);
+  }
+}
+
+PLTEntry* X86PLT::getPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+{
+   X86PLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
+
+   pExist = 1;
+
+   if (!PLTEntry) {
+     GOTEntry *&GOTPLTEntry = m_GOT.m_GOTPLTMap[&pSymbol];
+     assert(!GOTPLTEntry && "PLT entry and got.plt entry doesn't match!");
+
+     pExist = 0;
+
+     // This will skip PLT0.
+     ++m_PLTEntryIterator;
+     assert(m_PLTEntryIterator != m_SectionData.end() &&
+            "The number of PLT Entries and ResolveInfo doesn't match");
+     ++(m_GOT.m_GOTPLTIterator);
+
+     PLTEntry = llvm::cast<X86PLT1>(&(*m_PLTEntryIterator));
+     GOTPLTEntry = llvm::cast<GOTEntry>(&(*(m_GOT.m_GOTPLTIterator)));
+   }
+
+   return PLTEntry;
+}
+
+GOTEntry* X86PLT::getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+{
+   GOTEntry *&GOTPLTEntry = m_GOT.m_GOTPLTMap[&pSymbol];
+
+   pExist = 1;
+
+   if (!GOTPLTEntry) {
+     X86PLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
+     assert(!PLTEntry && "PLT entry and got.plt entry doesn't match!");
+
+     pExist = 0;
+
+     // This will skip PLT0.
+     ++m_PLTEntryIterator;
+     assert(m_PLTEntryIterator != m_SectionData.end() &&
+            "The number of PLT Entries and ResolveInfo doesn't match");
+     ++(m_GOT.m_GOTPLTIterator);
+
+     PLTEntry = llvm::cast<X86PLT1>(&(*m_PLTEntryIterator));
+     GOTPLTEntry = llvm::cast<GOTEntry>(&(*(m_GOT.m_GOTPLTIterator)));
+   }
+
+   return GOTPLTEntry;
+}
+
+X86PLT0* X86PLT::getPLT0() const {
+
+  iterator first = m_SectionData.getFragmentList().begin();
+  iterator end = m_SectionData.getFragmentList().end();
+
+  assert(first!=end && "FragmentList is empty, getPLT0 failed!");
+
+  X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
+
+  return plt0;
+}
+
+// FIXME: It only works on little endian machine.
+void X86PLT::applyPLT0() {
+
+  iterator first = m_SectionData.getFragmentList().begin();
+  iterator end = m_SectionData.getFragmentList().end();
+
+  assert(first!=end && "FragmentList is empty, applyPLT0 failed!");
+
+  X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
+
+  unsigned char* data = 0;
+  data = static_cast<unsigned char*>(malloc(plt0->getEntrySize()));
+
+  if (!data)
+    llvm::report_fatal_error("Allocating new memory for plt0 failed!");
+
+  memcpy(data, m_PLT0, plt0->getEntrySize());
+
+  if (m_PLT0 == x86_exec_plt0) {
+    uint64_t got_base = m_GOT.getSection().addr();
+    assert(got_base && ".got base address is NULL!");
+    uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
+    *offset = got_base + 4;
+    offset = reinterpret_cast<uint32_t*>(data + 8);
+    *offset = got_base + 8;
+  }
+
+  plt0->setContent(data);
+}
+
+// FIXME: It only works on little endian machine.
+void X86PLT::applyPLT1() {
+
+  uint64_t plt_base = m_Section.addr();
+  assert(plt_base && ".plt base address is NULL!");
+
+  uint64_t got_base = m_GOT.getSection().addr();
+  assert(got_base && ".got base address is NULL!");
+
+  X86PLT::iterator it = m_SectionData.begin();
+  X86PLT::iterator ie = m_SectionData.end();
+  assert(it!=ie && "FragmentList is empty, applyPLT1 failed!");
+
+  uint64_t GOTEntrySize = m_GOT.getEntrySize();
+
+  // Skip GOT0
+  uint64_t GOTEntryOffset = GOTEntrySize * X86GOT0Num;
+
+  //skip PLT0
+  uint64_t PLTEntryOffset = m_PLT0Size;
+  ++it;
+
+  X86PLT1* plt1 = 0;
+
+  uint64_t PLTRelOffset = 0;
+
+  while (it != ie) {
+    plt1 = &(llvm::cast<X86PLT1>(*it));
+    unsigned char *data;
+    data = static_cast<unsigned char*>(malloc(plt1->getEntrySize()));
+
+    if (!data)
+      llvm::report_fatal_error("Allocating new memory for plt1 failed!");
+
+    memcpy(data, m_PLT1, plt1->getEntrySize());
+
+    uint32_t* offset;
+
+    offset = reinterpret_cast<uint32_t*>(data + 2);
+    *offset = GOTEntryOffset;
+    GOTEntryOffset += GOTEntrySize;
+
+    offset = reinterpret_cast<uint32_t*>(data + 7);
+    *offset = PLTRelOffset;
+    PLTRelOffset += sizeof (llvm::ELF::Elf32_Rel);
+
+    offset = reinterpret_cast<uint32_t*>(data + 12);
+    *offset = -(PLTEntryOffset + 12 + 4);
+    PLTEntryOffset += m_PLT1Size;
+
+    plt1->setContent(data);
+    ++it;
+  }
+
+  unsigned int GOTPLTNum = m_GOT.getGOTPLTNum();
+
+  if (GOTPLTNum != 0) {
+    X86GOT::iterator gotplt_it = m_GOT.getLastGOT0();
+    X86GOT::iterator list_ie = m_GOT.getSectionData().getFragmentList().end();
+
+    ++gotplt_it;
+    uint64_t PLTEntryAddress = plt_base + m_PLT0Size;
+    for (unsigned int i = 0; i < GOTPLTNum; ++i) {
+      if (gotplt_it == list_ie)
+        llvm::report_fatal_error(
+          "The number of got.plt entries is inconsistent!");
+
+      llvm::cast<GOTEntry>(*gotplt_it).setContent(PLTEntryAddress + 6);
+      PLTEntryAddress += m_PLT1Size;
+      ++gotplt_it;
+    }
+  }
+}
+
+} // end namespace mcld
+
diff --git a/lib/Target/X86/X86PLT.h b/lib/Target/X86/X86PLT.h
new file mode 100644
index 0000000..dd72f52
--- /dev/null
+++ b/lib/Target/X86/X86PLT.h
@@ -0,0 +1,91 @@
+//===- X86PLT.h -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef X86_PLT_H
+#define X86_PLT_H
+
+#include <mcld/Target/PLT.h>
+
+namespace mcld {
+
+class X86GOT;
+class GOTEntry;
+class Output;
+
+class X86PLT0 : public PLTEntry {
+public:
+  X86PLT0(llvm::MCSectionData* pParent, unsigned int pSize);
+};
+
+class X86PLT1 : public PLTEntry {
+public:
+  X86PLT1(llvm::MCSectionData* pParent, unsigned int pSize);
+};
+
+/** \class X86PLT
+ *  \brief X86 Procedure Linkage Table
+ */
+class X86PLT : public PLT
+{
+  typedef llvm::DenseMap<const ResolveInfo*, X86PLT1*> SymbolIndexType;
+
+public:
+  typedef llvm::MCSectionData::iterator iterator;
+  typedef llvm::MCSectionData::const_iterator const_iterator;
+
+public:
+  X86PLT(LDSection& pSection,
+         llvm::MCSectionData& pSectionData,
+         X86GOT& pGOTPLT,
+	 const Output& pOutput);
+  ~X86PLT();
+
+// Override virtual function.
+public:
+
+  // reserveEntry is X86GOT friend function.
+  void reserveEntry(size_t pNum = 1) ;
+
+  PLTEntry* getPLTEntry(const ResolveInfo& pSymbol, bool& pExist) ;
+
+  GOTEntry* getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist);
+
+public:
+
+  iterator begin() { return m_SectionData.begin(); }
+
+  const_iterator begin() const { return m_SectionData.begin(); }
+
+  iterator end() { return m_SectionData.end(); }
+
+  const_iterator end() const { return m_SectionData.end(); }
+
+  X86PLT0* getPLT0() const;
+
+  void applyPLT0();
+
+  void applyPLT1();
+
+private:
+  X86GOT& m_GOT;
+
+  // Used by getEntry() for mapping a ResolveInfo
+  // instance to a PLT1 Entry.
+  iterator m_PLTEntryIterator;
+
+  SymbolIndexType m_PLTEntryMap;
+
+  const uint8_t *m_PLT0;
+  const uint8_t *m_PLT1;
+  unsigned int m_PLT0Size;
+  unsigned int m_PLT1Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/X86/X86RelocationFactory.cpp b/lib/Target/X86/X86RelocationFactory.cpp
new file mode 100644
index 0000000..15b9a6b
--- /dev/null
+++ b/lib/Target/X86/X86RelocationFactory.cpp
@@ -0,0 +1,361 @@
+//===- X86RelocationFactory.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/ErrorHandling.h>
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/ELF.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LD/Layout.h>
+
+#include "X86RelocationFactory.h"
+#include "X86RelocationFunctions.h"
+
+using namespace mcld;
+
+DECL_X86_APPLY_RELOC_FUNCS
+
+//===--------------------------------------------------------------------===//
+// X86RelocationFactory
+X86RelocationFactory::X86RelocationFactory(size_t pNum,
+                                           X86GNULDBackend& pParent)
+  : RelocationFactory(pNum),
+    m_Target(pParent) {
+}
+
+X86RelocationFactory::~X86RelocationFactory()
+{
+}
+
+void 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]) ) {
+    llvm::report_fatal_error(llvm::Twine("Unknown relocation type ") +
+			     llvm::Twine((int) type) +
+			     llvm::Twine(" to symbol `") +
+                             pRelocation.symInfo()->name() +
+                             llvm::Twine("'."));
+    return;
+  }
+
+  // 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;
+  }
+}
+
+
+
+// non-member functions
+
+//=========================================//
+// Relocation helper function              //
+//=========================================//
+
+// Check if symbol can use relocation R_386_RELATIVE
+static bool
+helper_use_relative_reloc(const ResolveInfo& pSym,
+                          const MCLDInfo& pLDInfo,
+                          const X86RelocationFactory& pFactory)
+
+{
+  // if symbol is dynamic or undefine or preemptible
+  if(pSym.isDyn() ||
+     pSym.isUndef() ||
+     pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output()))
+    return false;
+  return true;
+}
+
+static
+GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
+                                  const MCLDInfo& pLDInfo,
+                                  X86RelocationFactory& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86GNULDBackend& ld_backend = pParent.getTarget();
+
+  bool exist;
+  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
+  if (!exist) {
+    // If we first get this GOT entry, we should initialize it.
+    if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
+      // No corresponding dynamic relocation, initialize to the symbol value.
+      got_entry.setContent(pReloc.symValue());
+    }
+    else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
+      // Initialize corresponding dynamic relocation.
+      Relocation& rel_entry =
+        *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
+      assert(!exist && "GOT entry not exist, but DynRel entry exist!");
+      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+        // Initialize got entry to target symbol address
+        got_entry.setContent(pReloc.symValue());
+        rel_entry.setType(llvm::ELF::R_386_RELATIVE);
+        rel_entry.setSymInfo(0);
+      }
+      else {
+        got_entry.setContent(0);
+        rel_entry.setType(llvm::ELF::R_386_GLOB_DAT);
+        rel_entry.setSymInfo(rsym);
+      }
+      rel_entry.targetRef().assign(got_entry);
+    }
+    else {
+      llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+    }
+  }
+  return got_entry;
+}
+
+
+static
+X86RelocationFactory::Address helper_GOT_ORG(X86RelocationFactory& pParent)
+{
+  return pParent.getTarget().getGOT().getSection().addr();
+}
+
+
+static
+X86RelocationFactory::Address helper_GOT(Relocation& pReloc,
+                                         const MCLDInfo& pLDInfo,
+                                         X86RelocationFactory& pParent)
+{
+  GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo,  pParent);
+  return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry);
+}
+
+
+static
+PLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
+                                  X86RelocationFactory& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86GNULDBackend& ld_backend = pParent.getTarget();
+
+  bool exist;
+  PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
+  if (!exist) {
+    // If we first get this PLT entry, we should initialize it.
+    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
+      GOTEntry& gotplt_entry =
+        *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
+      // Initialize corresponding dynamic relocation.
+      Relocation& rel_entry =
+        *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
+      assert(!exist && "PLT entry not exist, but DynRel entry exist!");
+      rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
+      rel_entry.targetRef().assign(gotplt_entry);
+      rel_entry.setSymInfo(rsym);
+    }
+    else {
+      llvm::report_fatal_error("No PLT entry reserved for PLT type relocation!");
+    }
+  }
+  return plt_entry;
+}
+
+
+
+static
+X86RelocationFactory::Address helper_PLT_ORG(X86RelocationFactory& pParent)
+{
+  return pParent.getTarget().getPLT().getSection().addr();
+}
+
+
+static
+X86RelocationFactory::Address helper_PLT(Relocation& pReloc,
+                                         X86RelocationFactory& pParent)
+{
+  PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
+  return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry);
+}
+
+// Get an relocation entry in .rel.dyn and set its type to pType,
+// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo()
+static
+void helper_DynRel(Relocation& pReloc,
+                   X86RelocationFactory::Type pType,
+                   X86RelocationFactory& pParent)
+{
+  // rsym - The relocation target symbol
+  ResolveInfo* rsym = pReloc.symInfo();
+  X86GNULDBackend& ld_backend = pParent.getTarget();
+  bool exist;
+
+  Relocation& rel_entry =
+    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
+  rel_entry.setType(pType);
+  rel_entry.targetRef() = pReloc.targetRef();
+
+  if(pType == llvm::ELF::R_386_RELATIVE)
+    rel_entry.setSymInfo(0);
+  else
+    rel_entry.setSymInfo(rsym);
+}
+
+
+//=========================================//
+// Each relocation function implementation //
+//=========================================//
+
+// R_386_NONE
+X86RelocationFactory::Result none(Relocation& pReloc,
+                                  const MCLDInfo& pLDInfo,
+                                  X86RelocationFactory& pParent)
+{
+  return X86RelocationFactory::OK;
+}
+
+// R_386_32: S + A
+X86RelocationFactory::Result abs32(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   X86RelocationFactory& pParent)
+{
+  ResolveInfo* rsym = pReloc.symInfo();
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  RelocationFactory::DWord S = pReloc.symValue();
+
+  if(rsym->isLocal() && (rsym->reserved() & X86GNULDBackend::ReserveRel)) {
+    helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+    pReloc.target() = S + A;
+    return X86RelocationFactory::OK;
+  }
+  else if(!rsym->isLocal()) {
+    if(rsym->reserved() & X86GNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+      pReloc.target() = S + A;
+    }
+    if(rsym->reserved() & X86GNULDBackend::ReserveRel) {
+      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
+        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+      }
+      else {
+        helper_DynRel(pReloc, pReloc.type(), pParent);
+        return X86RelocationFactory::OK;
+      }
+    }
+  }
+
+  // perform static relocation
+  pReloc.target() = S + A;
+  return X86RelocationFactory::OK;
+}
+
+// R_386_PC32: S + A - P
+X86RelocationFactory::Result rel32(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   X86RelocationFactory& pParent)
+{
+  // perform static relocation
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  pReloc.target() = pReloc.symValue() + A
+      - pReloc.place(pParent.getLayout());
+  return X86RelocationFactory::OK;
+}
+
+// R_386_GOTOFF: S + A - GOT_ORG
+X86RelocationFactory::Result gotoff32(Relocation& pReloc,
+                                      const MCLDInfo& pLDInfo,
+                                      X86RelocationFactory& pParent)
+{
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
+  X86RelocationFactory::Address S = pReloc.symValue();
+
+  pReloc.target() = S + A - GOT_ORG;
+  return X86RelocationFactory::OK;
+}
+
+// R_386_GOTPC: GOT_ORG + A - P
+X86RelocationFactory::Result gotpc32(Relocation& pReloc,
+                                     const MCLDInfo& pLDInfo,
+                                     X86RelocationFactory& pParent)
+{
+  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
+  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
+  // Apply relocation.
+  pReloc.target() = GOT_ORG + A - pReloc.place(pParent.getLayout());
+  return X86RelocationFactory::OK;
+}
+
+// R_386_GOT32: GOT(S) + A - GOT_ORG
+X86RelocationFactory::Result got32(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   X86RelocationFactory& pParent)
+{
+  if(!(pReloc.symInfo()->reserved()
+       & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
+    return X86RelocationFactory::BadReloc;
+  }
+  X86RelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
+  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
+  X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
+  // Apply relocation.
+  pReloc.target() = GOT_S + A - GOT_ORG;
+  return X86RelocationFactory::OK;
+}
+
+// R_386_PLT32: PLT(S) + A - P
+X86RelocationFactory::Result plt32(Relocation& pReloc,
+                                   const MCLDInfo& pLDInfo,
+                                   X86RelocationFactory& pParent)
+{
+  // PLT_S depends on if there is a PLT entry.
+  X86RelocationFactory::Address PLT_S;
+  if((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
+    PLT_S = helper_PLT(pReloc, pParent);
+  else
+    PLT_S = pReloc.symValue();
+  RelocationFactory::DWord   A       = pReloc.target() + pReloc.addend();
+  X86RelocationFactory::Address P = pReloc.place(pParent.getLayout());
+  pReloc.target() = PLT_S + A - P;
+  return X86RelocationFactory::OK;
+}
diff --git a/lib/Target/X86/X86RelocationFactory.h b/lib/Target/X86/X86RelocationFactory.h
new file mode 100644
index 0000000..6a6c372
--- /dev/null
+++ b/lib/Target/X86/X86RelocationFactory.h
@@ -0,0 +1,58 @@
+//===-  X86RelocationFactory.h --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef X86_RELOCATION_FACTORY_H
+#define X86_RELOCATION_FACTORY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/Target/GOT.h>
+#include "X86LDBackend.h"
+
+namespace mcld
+{
+
+/** \class X86RelocationFactory
+ *  \brief X86RelocationFactory creates and destroys the X86 relocations.
+ *
+ */
+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);
+
+  X86GNULDBackend& getTarget()
+  { return m_Target; }
+
+  const X86GNULDBackend& getTarget() const
+  { return m_Target; }
+
+private:
+  X86GNULDBackend& m_Target;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86RelocationFunctions.h b/lib/Target/X86/X86RelocationFunctions.h
new file mode 100644
index 0000000..46d4f34
--- /dev/null
+++ b/lib/Target/X86/X86RelocationFunctions.h
@@ -0,0 +1,36 @@
+//===- X86RelocationFunction.h --------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DECL_X86_APPLY_RELOC_FUNC(Name) \
+static X86RelocationFactory::Result Name    (Relocation& pEntry, \
+					     const MCLDInfo& pLDInfo, \
+					     X86RelocationFactory& pParent);
+
+#define DECL_X86_APPLY_RELOC_FUNCS \
+DECL_X86_APPLY_RELOC_FUNC(none)             \
+DECL_X86_APPLY_RELOC_FUNC(abs32)            \
+DECL_X86_APPLY_RELOC_FUNC(rel32)            \
+DECL_X86_APPLY_RELOC_FUNC(plt32)            \
+DECL_X86_APPLY_RELOC_FUNC(got32)            \
+DECL_X86_APPLY_RELOC_FUNC(gotoff32)	    \
+DECL_X86_APPLY_RELOC_FUNC(gotpc32)
+
+
+#define DECL_X86_APPLY_RELOC_FUNC_PTRS \
+  { &none,               0, "R_386_NONE"              },  \
+  { &abs32,              1, "R_386_32"                },  \
+  { &rel32,              2, "R_386_PC32"              },  \
+  { &got32,              3, "R_386_GOT32"             },  \
+  { &plt32,              4, "R_386_PLT32"             },  \
+  { &none,               5, "R_386_COPY"              },  \
+  { &none,               6, "R_386_GLOB_DAT"          },  \
+  { &none,               7, "R_386_JMP_SLOT"          },  \
+  { &none,               8, "R_386_RELATIVE"          },  \
+  { &gotoff32,           9, "R_386_GOTOFF"            },  \
+  { &gotpc32,           10, "R_386_GOTPC"             }
diff --git a/lib/Target/X86/X86SectLinker.cpp b/lib/Target/X86/X86SectLinker.cpp
new file mode 100644
index 0000000..793b97b
--- /dev/null
+++ b/lib/Target/X86/X86SectLinker.cpp
@@ -0,0 +1,47 @@
+//===- X86SectLinker.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+
+#include "X86.h"
+#include "X86AndroidSectLinker.h"
+#include "X86ELFSectLinker.h"
+
+using namespace mcld;
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+/// createX86SectLinker - the help funtion to create corresponding X86SectLinker
+///
+SectLinker* createX86SectLinker(const std::string &pTriple,
+                                SectLinkerOption &pOption,
+                                mcld::TargetLDBackend &pLDBackend)
+{
+  Triple theTriple(pTriple);
+  if (theTriple.isOSDarwin()) {
+    assert(0 && "MachO linker has not supported yet");
+  }
+  if (theTriple.isOSWindows()) {
+    assert(0 && "COFF linker has not supported yet");
+  }
+
+  // For now, use Android SectLinker directly
+  return new X86AndroidSectLinker(pOption,
+                                  pLDBackend);
+}
+
+} // namespace of mcld
+
+//==========================
+// X86SectLinker
+extern "C" void LLVMInitializeX86SectLinker() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterSectLinker(TheX86Target, createX86SectLinker);
+}
+
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
new file mode 100644
index 0000000..b036137
--- /dev/null
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -0,0 +1,34 @@
+//===- X86TargetMachine.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86TargetMachine.h"
+
+#include "mcld/Target/TargetMachine.h"
+#include "mcld/Support/TargetRegistry.h"
+#include "mcld/MC/MCLDInfo.h"
+#include "X86.h"
+
+extern "C" void LLVMInitializeX86LDTarget() {
+  // Register createTargetMachine function pointer to mcld::Target
+  mcld::RegisterTargetMachine<mcld::X86TargetMachine> X(mcld::TheX86Target);
+}
+
+mcld::X86TargetMachine::X86TargetMachine(llvm::TargetMachine& pPM,
+                                         const mcld::Target &pTarget,
+                                         const std::string& pTriple)
+  : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
+  // arg1 - the number of total attributes
+  // arg2 - the most possible number of input files
+  m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+}
+
+mcld::X86TargetMachine::~X86TargetMachine()
+{
+  delete m_pLDInfo;
+}
+
diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h
new file mode 100644
index 0000000..3ba9e59
--- /dev/null
+++ b/lib/Target/X86/X86TargetMachine.h
@@ -0,0 +1,40 @@
+//===- X86TargetMachine.h -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_X86_TARGET_MACHINE_H
+#define MCLD_X86_TARGET_MACHINE_H
+#include "mcld/Target/TargetMachine.h"
+#include "X86.h"
+
+namespace mcld
+{
+
+class X86TargetMachine : public LLVMTargetMachine
+{
+protected:
+  MCLDInfo *m_pLDInfo;
+
+public:
+  X86TargetMachine(llvm::TargetMachine &pTM,
+                       const mcld::Target &pTarget,
+                       const std::string &pTriple);
+
+  virtual ~X86TargetMachine();
+
+  mcld::MCLDInfo& getLDInfo()
+  { return *m_pLDInfo; }
+
+  const mcld::MCLDInfo& getLDInfo() const
+  { return *m_pLDInfo; }
+
+};
+
+} // namespace of mcld
+
+#endif
+