MCLinker upstream commit e764452.

Change-Id: I5c9ec467ec96a0143e1e67c59365f3b6303e7348
diff --git a/lib/ADT/StringEntry.cpp b/lib/ADT/StringEntry.cpp
new file mode 100644
index 0000000..c853f83
--- /dev/null
+++ b/lib/ADT/StringEntry.cpp
@@ -0,0 +1,48 @@
+//===- StringEntry.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/ADT/StringEntry.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// StringEntry<llvm::StringRef>
+StringEntry<llvm::StringRef>::StringEntry()
+{
+}
+
+StringEntry<llvm::StringRef>::StringEntry(const StringEntry::key_type& pKey)
+{
+}
+
+StringEntry<llvm::StringRef>::StringEntry(const StringEntry<llvm::StringRef>& pCopy)
+{
+  assert("Copy constructor of StringEntry should not be called!");
+}
+
+StringEntry<llvm::StringRef>::~StringEntry()
+{
+  if (!m_Value.empty())
+    free(const_cast<char*>(m_Value.data()));
+}
+
+void StringEntry<llvm::StringRef>::setValue(llvm::StringRef& pVal)
+{
+  char* data = (char*)malloc(pVal.size()+1);
+  strcpy(data, pVal.data());
+  m_Value = llvm::StringRef(data, pVal.size());
+}
+
+void StringEntry<llvm::StringRef>::setValue(const char* pVal)
+{
+  size_t length = strlen(pVal);
+  char* data = (char*)malloc(length+1);
+  strcpy(data, pVal);
+  m_Value = llvm::StringRef(data, length);
+}
+
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index 13efa96..e24596c 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -231,10 +231,6 @@
     pPM.add(createGCInfoDeleter()); // not in addPassesToMC
     break;
   }
-  case CGFT_ARCFile: {
-    assert(0 && "Output to archive file has not been supported yet!");
-    break;
-  }
   case CGFT_EXEFile: {
     if (pLinkerOpt == NULL)
       return true;
@@ -378,7 +374,7 @@
     return true;
   pPM.add(printer);
 #endif
-  TargetLDBackend* ldBackend = getTarget().createLDBackend(*getTarget().get(), m_Triple);
+  TargetLDBackend* ldBackend = getTarget().createLDBackend(m_Triple);
   if (0 == ldBackend)
     return true;
 
@@ -410,3 +406,4 @@
   pPM.add(funcPass);
   return false;
 }
+
diff --git a/lib/CodeGen/SectLinker.cpp b/lib/CodeGen/SectLinker.cpp
index 95e9e4f..4f32c4f 100644
--- a/lib/CodeGen/SectLinker.cpp
+++ b/lib/CodeGen/SectLinker.cpp
@@ -10,19 +10,20 @@
 // This file implements the SectLinker class.
 //
 //===----------------------------------------------------------------------===//
-
-#include <mcld/ADT/BinTree.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/MC/InputTree.h>
+#include <mcld/MC/MCLDDriver.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/DerivedPositionDependentOptions.h>
+#include <mcld/Target/TargetLDBackend.h>
 #include <mcld/CodeGen/SectLinker.h>
 #include <mcld/CodeGen/SectLinkerOption.h>
-#include <mcld/MC/MCLDInputTree.h>
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/Support/DerivedPositionDependentOptions.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Target/TargetLDBackend.h>
 
 #include <llvm/Module.h>
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/Support/raw_ostream.h>
 
 #include <algorithm>
 #include <stack>
@@ -44,11 +45,16 @@
   : MachineFunctionPass(m_ID),
     m_pOption(&pOption),
     m_pLDBackend(&pLDBackend),
-    m_pLDDriver(NULL) { }
+    m_pLDDriver(NULL),
+    m_pMemAreaFactory(NULL)
+{
+  m_pMemAreaFactory = new MemoryAreaFactory(32);
+}
 
 SectLinker::~SectLinker()
 {
   delete m_pLDDriver;
+
   // FIXME: current implementation can not change the order of delete.
   //
   // Instance of TargetLDBackend was created outside and is not managed by
@@ -57,36 +63,19 @@
   // objects it used during the processing, we destroy the object of
   // TargetLDBackend here.
   delete m_pLDBackend;
+
+  delete m_pMemAreaFactory;
 }
 
 bool SectLinker::doInitialization(Module &pM)
 {
   MCLDInfo &info = m_pOption->info();
 
-  // setup the output
-  info.output().setContext(info.contextFactory().produce(info.output().path()));
-
-  int mode = (Output::Object == info.output().type())? 0544 : 0755;
-  info.output().setMemArea(
-      info.memAreaFactory().produce(info.output().path(),
-                                    O_RDWR | O_CREAT | O_TRUNC,
-                                    mode));
-
-  //   make sure output is openend successfully.
-  if (!info.output().hasMemArea())
-    report_fatal_error("output is not given on the command line\n");
-
-  if (!info.output().memArea()->isGood())
-    report_fatal_error("can not open output file :"+info.output().path().native());
-
-  // let the target override the target-specific parameters
-  addTargetOptions(pM, *m_pOption);
-
   // ----- convert position dependent options into tree of input files  ----- //
   PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options();
   std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption);
   initializeInputTree(PosDepOpts);
-
+  initializeInputOutput(info);
   // Now, all input arguments are prepared well, send it into MCLDDriver
   m_pLDDriver = new MCLDDriver(info, *m_pLDBackend);
 
@@ -97,42 +86,45 @@
 {
   const MCLDInfo &info = m_pOption->info();
 
-  // 3. - initialize output's standard segments and sections
+  // 2. - initialize MCLinker
   if (!m_pLDDriver->initMCLinker())
     return true;
 
+  // 3. - initialize output's standard sections
+  if (!m_pLDDriver->initStdSections())
+    return true;
+
   // 4. - normalize the input tree
   m_pLDDriver->normalize();
 
-  if (info.options().verbose()) {
-    outs() << "MCLinker (LLVM Sub-project) - ";
-    outs() << MCLDInfo::version();
-    outs() << "\n";
-  }
-
   if (info.options().trace()) {
     static int counter = 0;
-    outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
+    mcld::outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
     InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end();
     for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) {
-      outs() << counter++ << " *  " << (*input)->name();
+      mcld::outs() << counter++ << " *  " << (*input)->name();
       switch((*input)->type()) {
       case Input::Archive:
-        outs() << "\tarchive\t(";
+        mcld::outs() << "\tarchive\t(";
         break;
       case Input::Object:
-        outs() << "\tobject\t(";
+        mcld::outs() << "\tobject\t(";
         break;
       case Input::DynObj:
-        outs() << "\tshared\t(";
+        mcld::outs() << "\tshared\t(";
         break;
       case Input::Script:
-        outs() << "\tscript\t(";
+        mcld::outs() << "\tscript\t(";
+        break;
+      case Input::External:
+        mcld::outs() << "\textern\t(";
         break;
       default:
-        report_fatal_error("** Trace a unsupported file. It must be an internal bug!");
+        unreachable(diag::err_cannot_trace_file) << (*input)->type()
+                                                 << (*input)->name()
+                                                 << (*input)->path();
       }
-      outs() << (*input)->path().c_str() << ")\n";
+      mcld::outs() << (*input)->path() << ")\n";
     }
   }
 
@@ -147,8 +139,7 @@
     return true;
 
   // 7. - read all symbol tables of input files and resolve them
-  if (!m_pLDDriver->readSymbolTables() ||
-      !m_pLDDriver->mergeSymbolTables())
+  if (!m_pLDDriver->readSymbolTables())
     return true;
 
   // 7.a - add standard symbols and target-dependent symbols
@@ -173,7 +164,7 @@
   m_pLDDriver->finalizeSymbolValue();
 
   // 12. - apply relocations
-  m_pLDDriver->relocate();
+  m_pLDDriver->relocation();
 
   // 13. - write out output
   m_pLDDriver->emitOutput();
@@ -189,86 +180,188 @@
   return false;
 }
 
+void SectLinker::initializeInputOutput(MCLDInfo &pLDInfo)
+{
+  // -----  initialize output file  ----- //
+  FileHandle::Permission perm;
+  if (Output::Object == pLDInfo.output().type())
+    perm = 0544;
+  else
+    perm = 0755;
+
+  MemoryArea* out_area = memAreaFactory()->produce(pLDInfo.output().path(),
+                                                 FileHandle::ReadWrite,
+                                                 perm);
+
+  if (!out_area->handler()->isGood()) {
+    // make sure output is openend successfully.
+    fatal(diag::err_cannot_open_output_file) << pLDInfo.output().name()
+                                             << pLDInfo.output().path();
+  }
+
+  pLDInfo.output().setMemArea(out_area);
+  pLDInfo.output().setContext(pLDInfo.contextFactory().produce());
+
+  // -----  initialize input files  ----- //
+  InputTree::dfs_iterator input, inEnd = pLDInfo.inputs().dfs_end();
+  for (input = pLDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
+    // already got type - for example, bitcode
+    if ((*input)->type() == Input::Script ||
+        (*input)->type() == Input::Object ||
+        (*input)->type() == Input::DynObj  ||
+        (*input)->type() == Input::Archive)
+      continue;
+
+    MemoryArea *input_memory =
+        memAreaFactory()->produce((*input)->path(), FileHandle::ReadOnly);
+
+    if (input_memory->handler()->isGood()) {
+      (*input)->setMemArea(input_memory);
+    }
+    else {
+      error(diag::err_cannot_open_input) << (*input)->name() << (*input)->path();
+      return;
+    }
+
+    LDContext *input_context =
+        pLDInfo.contextFactory().produce((*input)->path());
+
+    (*input)->setContext(input_context);
+  }
+}
+
 void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const
 {
   if (pPosDepOptions.empty())
-    return;
+    fatal(diag::err_no_inputs);
 
   MCLDInfo &info = m_pOption->info();
-  PositionDependentOptions::const_iterator cur_char = pPosDepOptions.begin();
+  PositionDependentOptions::const_iterator option = pPosDepOptions.begin();
   if (1 == pPosDepOptions.size() &&
-      ((*cur_char)->type() != PositionDependentOption::INPUT_FILE &&
-       (*cur_char)->type() != PositionDependentOption::NAMESPEC))
-    return;
+      ((*option)->type() != PositionDependentOption::INPUT_FILE &&
+       (*option)->type() != PositionDependentOption::NAMESPEC) &&
+       (*option)->type() != PositionDependentOption::BITCODE) {
+    // if we only have one positional options, and the option is
+    // not an input file, then emit error message.
+    fatal(diag::err_no_inputs);
+  }
 
-  InputTree::Connector *prev_ward = &InputTree::Downward;
+  // -----  Input tree insertion algorithm  ----- //
+  //   The type of the previsou node indicates the direction of the current
+  //   insertion.
+  //
+  //     root   : the parent node who being inserted.
+  //     mover  : the direcion of current movement.
+  //
+  //   for each positional options:
+  //     insert the options in current root.
+  //     calculate the next movement
 
+  // Initialization
+  InputTree::Mover *move = &InputTree::Downward;
+  InputTree::iterator root = info.inputs().root();
+  PositionDependentOptions::const_iterator optionEnd = pPosDepOptions.end();
   std::stack<InputTree::iterator> returnStack;
-  InputTree::iterator cur_node = info.inputs().root();
 
-  PositionDependentOptions::const_iterator charEnd = pPosDepOptions.end();
-  while (cur_char != charEnd ) {
-    switch ((*cur_char)->type()) {
-    case PositionDependentOption::BITCODE: {
-      // threat bitcode as a script in this version.
-      const BitcodeOption *bitcode_option =
-          static_cast<const BitcodeOption*>(*cur_char);
-      info.inputs().insert(cur_node,
-                           *prev_ward,
-                           bitcode_option->path()->native(),
-                           *(bitcode_option->path()),
-                           Input::Script);
-      info.setBitcode(**cur_node);
-      prev_ward->move(cur_node);
-      prev_ward = &InputTree::Afterward;
-      break;
-    }
-    case PositionDependentOption::INPUT_FILE: {
-      const InputFileOption *input_file_option =
-          static_cast<const InputFileOption*>(*cur_char);
-      info.inputs().insert(cur_node,
-                           *prev_ward,
-                           input_file_option->path()->native(),
-                           *(input_file_option->path()));
-      prev_ward->move(cur_node);
-      prev_ward = &InputTree::Afterward;
-      break;
-    }
+  while (option != optionEnd ) {
+
+    switch ((*option)->type()) {
+      /** bitcode **/
+      case PositionDependentOption::BITCODE: {
+
+        const BitcodeOption *bitcode_option =
+            static_cast<const BitcodeOption*>(*option);
+
+        // threat bitcode as an external IR in this version.
+        info.inputs().insert(root, *move,
+                             bitcode_option->path()->native(),
+                             *(bitcode_option->path()),
+                             Input::External);
+
+        info.setBitcode(**root);
+
+        // move root on the new created node.
+        move->move(root);
+
+        // the next file is appended after bitcode file.
+        move = &InputTree::Afterward;
+        break;
+      }
+
+      /** input object file **/
+      case PositionDependentOption::INPUT_FILE: {
+        const InputFileOption *input_file_option =
+            static_cast<const InputFileOption*>(*option);
+
+        info.inputs().insert(root, *move,
+                             input_file_option->path()->native(),
+                             *(input_file_option->path()));
+
+        // move root on the new created node.
+        move->move(root);
+
+        // the next file is appended after object file.
+        move = &InputTree::Afterward;
+        break;
+      }
+
+    /** -lnamespec **/
     case PositionDependentOption::NAMESPEC: {
-      sys::fs::Path* path = 0;
+      sys::fs::Path* path = NULL;
       const NamespecOption *namespec_option =
-          static_cast<const NamespecOption*>(*cur_char);
-      if (info.attrFactory().last().isStatic()) {
+          static_cast<const NamespecOption*>(*option);
+
+      // find out the real path of the namespec.
+      if (info.attrFactory().constraint().isSharedSystem()) {
+        // In the system with shared object support, we can find both archive
+        // and shared object.
+
+        if (info.attrFactory().last().isStatic()) {
+          // with --static, we must search an archive.
+          path = info.options().directories().find(namespec_option->namespec(),
+                                                   Input::Archive);
+        }
+        else {
+          // otherwise, with --Bdynamic, we can find either an archive or a
+          // shared object.
+          path = info.options().directories().find(namespec_option->namespec(),
+                                                   Input::DynObj);
+        }
+      }
+      else {
+        // In the system without shared object support, we only look for an
+        // archive.
         path = info.options().directories().find(namespec_option->namespec(),
                                                  Input::Archive);
       }
-      else {
-        path = info.options().directories().find(namespec_option->namespec(),
-                                                 Input::DynObj);
-      }
 
-      if (0 == path) {
-        llvm::report_fatal_error(std::string("Can't find namespec: ")+
-                                 namespec_option->namespec());
-      }
-      info.inputs().insert(cur_node,
-                           *prev_ward,
+      if (NULL == path)
+        fatal(diag::err_cannot_find_namespec) << namespec_option->namespec();
+
+      info.inputs().insert(root, *move,
                            namespec_option->namespec(),
                            *path);
-      prev_ward->move(cur_node);
-      prev_ward = &InputTree::Afterward;
+
+      // iterate root on the new created node.
+      move->move(root);
+
+      // the file after a namespec must be appended afterward.
+      move = &InputTree::Afterward;
       break;
     }
+
+    /** start group **/
     case PositionDependentOption::START_GROUP:
-      info.inputs().enterGroup(cur_node, *prev_ward);
-      prev_ward->move(cur_node);
-      returnStack.push(cur_node);
-      prev_ward = &InputTree::Downward;
+      info.inputs().enterGroup(root, *move);
+      move->move(root);
+      returnStack.push(root);
+      move = &InputTree::Downward;
       break;
+    /** end group **/
     case PositionDependentOption::END_GROUP:
-      cur_node = returnStack.top();
+      root = returnStack.top();
       returnStack.pop();
-      prev_ward = &InputTree::Afterward;
+      move = &InputTree::Afterward;
       break;
     case PositionDependentOption::WHOLE_ARCHIVE:
       info.attrFactory().last().setWholeArchive();
@@ -295,10 +388,11 @@
       info.attrFactory().last().setDynamic();
       break;
     default:
-      report_fatal_error("can not find the type of input file");
-    }
-    ++cur_char;
-  }
+      fatal(diag::err_cannot_identify_option) << (*option)->position()
+                                              << (uint32_t)(*option)->type();
+    } // end of switch
+    ++option;
+  } // end of while
 
   if (!returnStack.empty()) {
     report_fatal_error("no matched --start-group and --end-group");
diff --git a/lib/LD/BSDArchiveReader.cpp b/lib/LD/BSDArchiveReader.cpp
index 1264824..079153b 100644
--- a/lib/LD/BSDArchiveReader.cpp
+++ b/lib/LD/BSDArchiveReader.cpp
@@ -6,9 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInput.h"
-#include "mcld/MC/MCLDInputTree.h"
-#include "mcld/LD/BSDArchiveReader.h"
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/InputTree.h>
+#include <mcld/LD/BSDArchiveReader.h>
 
 using namespace mcld;
 
diff --git a/lib/LD/CIE.cpp b/lib/LD/CIE.cpp
new file mode 100644
index 0000000..c2f4317
--- /dev/null
+++ b/lib/LD/CIE.cpp
@@ -0,0 +1,23 @@
+//===- CIE.cpp ------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/CIE.h>
+
+using namespace mcld;
+
+//==========================
+// CIE
+
+CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
+  : MCRegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+}
+
+CIE::~CIE()
+{
+}
diff --git a/lib/LD/DWARFLineInfo.cpp b/lib/LD/DWARFLineInfo.cpp
new file mode 100644
index 0000000..63c588d
--- /dev/null
+++ b/lib/LD/DWARFLineInfo.cpp
@@ -0,0 +1,15 @@
+//===- DWARFLineInfo.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DWARFLineInfo.h>
+
+using namespace mcld;
+
+//==========================
+// DWARFLineInfo
+
diff --git a/lib/LD/Diagnostic.cpp b/lib/LD/Diagnostic.cpp
new file mode 100644
index 0000000..5175ebd
--- /dev/null
+++ b/lib/LD/Diagnostic.cpp
@@ -0,0 +1,173 @@
+//===- Diagnostic.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/Diagnostic.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/ADT/Twine.h>
+#include <ctype.h>
+#include <algorithm>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+//  Diagnostic
+Diagnostic::Diagnostic(DiagnosticEngine& pEngine)
+  : m_Engine(pEngine) {
+}
+
+Diagnostic::~Diagnostic()
+{
+}
+
+// format - format this diagnostic into string, subsituting the formal
+// arguments. The result is appended at on the pOutStr.
+void Diagnostic::format(std::string& pOutStr) const
+{
+  // we've not implemented DWARF LOC messages yet. So, keep pIsLoC false 
+  llvm::StringRef desc = m_Engine.infoMap().getDescription(getID(), false);
+
+  format(desc.begin(), desc.end(), pOutStr);
+}
+
+const char* Diagnostic::findMatch(char pVal,
+                                  const char* pBegin, const char* pEnd ) const
+{
+  unsigned int depth = 0;
+  for (; pBegin != pEnd; ++pBegin) {
+    if (0 == depth && *pBegin == pVal)
+      return pBegin;
+    if (0 != depth && *pBegin == '}')
+      --depth;
+
+    if ('%' == *pBegin) {
+      ++pBegin;
+      if (pBegin == pEnd)
+        break;
+
+      if (!isdigit(*pBegin) && !ispunct(*pBegin)) {
+        ++pBegin;
+        while (pBegin != pEnd && !isdigit(*pBegin) && *pBegin != '{')
+          ++pBegin;
+
+        if (pBegin == pEnd)
+          break;
+        if ('{' == *pBegin)
+          ++depth;
+      }
+    }
+  } // end of for
+  return pEnd;
+}
+
+// format - format the given formal string, subsituting the formal
+// arguments. The result is appended at on the pOutStr.
+void Diagnostic::format(const char* pBegin, const char* pEnd,
+                        std::string& pOutStr) const
+{
+  const char* cur_char = pBegin;
+  while (cur_char != pEnd) {
+    if ('%' != *cur_char) {
+      const char* new_end = std::find(cur_char, pEnd, '%');
+      pOutStr.append(cur_char, new_end);
+      cur_char = new_end;
+      continue;
+    }
+    else if (ispunct(cur_char[1])) {
+      pOutStr.push_back(cur_char[1]);  // %% -> %.
+      cur_char += 2;
+      continue;
+    }
+
+    // skip the %.
+    ++cur_char;
+
+    const char* modifier = NULL, *argument = NULL;
+    size_t modifier_len = 0, argument_len = 0;
+
+    // we get a modifier
+    if (!isdigit(*cur_char)) {
+      modifier = cur_char;
+      while (*cur_char == '-' || (*cur_char >= 'a' && *cur_char <= 'z'))
+        ++cur_char;
+      modifier_len = cur_char - modifier;
+
+      // we get an argument
+      if ('{' == *cur_char) {
+        ++cur_char; // skip '{'
+        argument = cur_char;
+        cur_char = findMatch('}', cur_char, pEnd);
+
+        if (cur_char == pEnd) {
+          // DIAG's format error
+          llvm::report_fatal_error(llvm::Twine("Mismatched {} in the diagnostic: ") +
+                                   llvm::Twine(getID()));
+        }
+
+        argument_len = cur_char - argument;
+        ++cur_char; // skip '}'
+      }
+    }
+    if (!isdigit(*cur_char)) {
+      llvm::report_fatal_error(llvm::Twine("In diagnostic: ") +
+                               llvm::Twine(getID()) + llvm::Twine(": ") +
+                               llvm::Twine(pBegin) +
+                               llvm::Twine("\nNo given arugment number:\n"));
+    }
+
+    unsigned int arg_no = *cur_char - '0';
+    ++cur_char; // skip argument number
+
+    DiagnosticEngine::ArgumentKind kind = getArgKind(arg_no);
+    switch (kind) {
+      case DiagnosticEngine::ak_std_string: {
+        if (0 != modifier_len) {
+          llvm::report_fatal_error(llvm::Twine("In diagnostic: ") +
+                                   llvm::Twine(getID()) +
+                                   llvm::Twine(": ") + llvm::Twine(pBegin) +
+                                   llvm::Twine("\nNo modifiers for strings yet\n"));
+        }
+        const std::string& str = getArgStdStr(arg_no);
+        pOutStr.append(str.begin(), str.end());
+        break;
+      }
+      case DiagnosticEngine::ak_c_string: {
+        if (0 != modifier_len) {
+          llvm::report_fatal_error(llvm::Twine("In diagnostic: ") +
+                                   llvm::Twine(getID()) +
+                                   llvm::Twine(": ") + llvm::Twine(pBegin) +
+                                   llvm::Twine("\nNo modifiers for strings yet\n"));
+        }
+        const char* str = getArgCStr(arg_no);
+        if (NULL == str)
+          str = "(null)";
+        pOutStr.append(str);
+        break;
+      }
+      case DiagnosticEngine::ak_sint: {
+        int val = getArgSInt(arg_no);
+        llvm::raw_string_ostream(pOutStr) << val;
+        break;
+      }
+      case DiagnosticEngine::ak_uint: {
+        unsigned int val = getArgUInt(arg_no);
+        llvm::raw_string_ostream(pOutStr) << val;
+        break;
+      }
+      case DiagnosticEngine::ak_bool: {
+        bool val = getArgBool(arg_no);
+        if (val)
+          pOutStr.append("true");
+        else
+          pOutStr.append("false");
+        break;
+      }
+    } // end of switch
+  } // end of while
+}
+
diff --git a/lib/LD/DiagnosticEngine.cpp b/lib/LD/DiagnosticEngine.cpp
new file mode 100644
index 0000000..11dbe1b
--- /dev/null
+++ b/lib/LD/DiagnosticEngine.cpp
@@ -0,0 +1,58 @@
+//===- DiagnosticEngine.cpp -----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticEngine.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/MC/MCLDInfo.h>
+
+using namespace mcld;
+
+//==========================
+// DiagnosticEngine
+DiagnosticEngine::DiagnosticEngine(const MCLDInfo& pLDInfo,
+                                   DiagnosticLineInfo* pLineInfo,
+                                   DiagnosticPrinter* pPrinter,
+                                   bool pShouldOwnPrinter)
+  : m_LDInfo(pLDInfo),
+    m_pLineInfo(pLineInfo),
+    m_pPrinter(pPrinter),
+    m_InfoMap(pLDInfo),
+    m_OwnPrinter(pShouldOwnPrinter) {
+  if (NULL == m_pPrinter) {
+    m_pPrinter = new DiagnosticPrinter(); // Dumb printer
+    m_OwnPrinter = true;
+  }
+}
+
+DiagnosticEngine::~DiagnosticEngine()
+{
+  if (m_OwnPrinter && m_pPrinter != NULL)
+    delete m_pPrinter;
+
+  if (NULL != m_pLineInfo)
+    delete m_pLineInfo;
+}
+
+void DiagnosticEngine::setPrinter(DiagnosticPrinter& pPrinter,
+                                  bool pShouldOwnPrinter)
+{
+  if (m_OwnPrinter && m_pPrinter != NULL)
+    delete m_pPrinter;
+  m_pPrinter = &pPrinter;
+  m_OwnPrinter = pShouldOwnPrinter;
+}
+
+// emit - process current diagnostic.
+bool DiagnosticEngine::emit()
+{
+  bool emitted = m_InfoMap.process(*this);
+  m_State.reset();
+  return emitted;
+}
+
diff --git a/lib/LD/DiagnosticInfos.cpp b/lib/LD/DiagnosticInfos.cpp
new file mode 100644
index 0000000..b9a6fa9
--- /dev/null
+++ b/lib/LD/DiagnosticInfos.cpp
@@ -0,0 +1,149 @@
+//===- DiagnosticInfo.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
+
+#include <mcld/ADT/SizeTraits.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LD/Diagnostic.h>
+#include <mcld/LD/DiagnosticInfos.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+
+using namespace mcld;
+
+namespace {
+
+struct DiagStaticInfo
+{
+public:
+  uint16_t ID;
+  DiagnosticEngine::Severity Severity;
+  uint16_t DescriptionLen;
+  const char* DescriptionStr;
+
+public:
+  llvm::StringRef getDescription() const
+  { return llvm::StringRef(DescriptionStr, DescriptionLen); }
+
+  bool operator<(const DiagStaticInfo& pRHS) const
+  { return (ID < pRHS.ID); }
+};
+
+} // namespace anonymous
+
+static const DiagStaticInfo DiagCommonInfo[] = {
+#define DIAG(ENUM, CLASS, ADDRDESC, LOCDESC) \
+  { diag::ENUM, CLASS, STR_SIZE(ADDRDESC, uint16_t), ADDRDESC },
+#include "mcld/LD/DiagCommonKinds.inc"
+#include "mcld/LD/DiagReaders.inc"
+#include "mcld/LD/DiagSymbolResolutions.inc"
+#include "mcld/LD/DiagRelocations.inc"
+#include "mcld/LD/DiagLayouts.inc"
+#include "mcld/LD/DiagGOTPLT.inc"
+#undef DIAG
+  { 0, DiagnosticEngine::None, 0, 0}
+};
+
+static const unsigned int DiagCommonInfoSize =
+  sizeof(DiagCommonInfo)/sizeof(DiagCommonInfo[0])-1;
+
+static const DiagStaticInfo DiagLoCInfo[] = {
+#define DIAG(ENUM, CLASS, ADDRDESC, LOCDESC) \
+  { diag::ENUM, CLASS, STR_SIZE(LOCDESC, uint16_t), LOCDESC },
+#include "mcld/LD/DiagReaders.inc"
+#include "mcld/LD/DiagSymbolResolutions.inc"
+#include "mcld/LD/DiagRelocations.inc"
+#include "mcld/LD/DiagLayouts.inc"
+#include "mcld/LD/DiagGOTPLT.inc"
+#undef DIAG
+  { 0, DiagnosticEngine::None, 0, 0}
+};
+
+static const unsigned int DiagLoCInfoSize =
+  sizeof(DiagLoCInfo)/sizeof(DiagLoCInfo[0])-1;
+
+
+static const DiagStaticInfo* getDiagInfo(unsigned int pID, bool pInLoC = false)
+{
+  const DiagStaticInfo* static_info = (pInLoC)?DiagLoCInfo:DiagCommonInfo;
+  unsigned int info_size = (pInLoC)?DiagLoCInfoSize:DiagCommonInfoSize;
+
+  DiagStaticInfo key = { static_cast<uint16_t>(pID), DiagnosticEngine::None, 0, 0 };
+  const DiagStaticInfo *result = std::lower_bound(static_info, static_info + info_size, key);
+
+  if (result == (static_info + info_size) || result->ID != pID)
+    return NULL;
+
+  return result;
+}
+
+//===----------------------------------------------------------------------===//
+//  DiagnosticInfos
+DiagnosticInfos::DiagnosticInfos(const MCLDInfo& pLDInfo)
+  : m_LDInfo(pLDInfo) {
+}
+
+DiagnosticInfos::~DiagnosticInfos()
+{
+}
+
+llvm::StringRef DiagnosticInfos::getDescription(unsigned int pID, bool pInLoC) const
+{
+  return getDiagInfo(pID, pInLoC)->getDescription();
+}
+
+bool DiagnosticInfos::process(DiagnosticEngine& pEngine) const
+{
+  Diagnostic info(pEngine);
+
+  unsigned int ID = info.getID();
+
+  // we are not implement LineInfo, so keep pIsLoC false.
+  const DiagStaticInfo* static_info = getDiagInfo(ID);
+
+  DiagnosticEngine::Severity severity = static_info->Severity;
+
+  switch (ID) {
+    case diag::multiple_definitions: {
+      if (m_LDInfo.options().hasMulDefs()) {
+        severity = DiagnosticEngine::Ignore;
+      }
+      break;
+    }
+    case diag::undefined_reference: {
+      // we have not implement --unresolved-symbols=method yet. So far, MCLinker
+      // provides the easier --allow-shlib-undefined and --no-undefined (i.e. -z defs)
+      switch(m_LDInfo.output().type()) {
+        case Output::Object:
+          if (m_LDInfo.options().isNoUndefined())
+            severity = DiagnosticEngine::Error;
+          else
+            severity = DiagnosticEngine::Ignore;
+        break;
+        case Output::DynObj:
+          if (m_LDInfo.options().isNoUndefined() || !m_LDInfo.options().isAllowShlibUndefined())
+            severity = DiagnosticEngine::Error;
+          else
+            severity = DiagnosticEngine::Ignore;
+        break;
+        case Output::Exec:
+          severity = DiagnosticEngine::Error;
+        break;
+      }
+      break;
+    }
+    default:
+      break;
+  } // end of switch
+
+  // finally, report it.
+  pEngine.getPrinter()->handleDiagnostic(severity, info);
+  return true;
+}
+
diff --git a/lib/LD/DiagnosticLineInfo.cpp b/lib/LD/DiagnosticLineInfo.cpp
new file mode 100644
index 0000000..d3c9190
--- /dev/null
+++ b/lib/LD/DiagnosticLineInfo.cpp
@@ -0,0 +1,15 @@
+//===- DiagnosticLineInfo.cpp ---------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticLineInfo.h>
+
+using namespace mcld;
+
+//==========================
+// DiagnosticLineInfo
+
diff --git a/lib/LD/DiagnosticPrinter.cpp b/lib/LD/DiagnosticPrinter.cpp
new file mode 100644
index 0000000..7bbf473
--- /dev/null
+++ b/lib/LD/DiagnosticPrinter.cpp
@@ -0,0 +1,34 @@
+//===- DiagnosticPrinter.cpp ----------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticPrinter.h>
+
+using namespace mcld;
+
+//==========================
+// DiagnosticPrinter
+DiagnosticPrinter::DiagnosticPrinter()
+  : m_NumErrors(0), m_NumWarnings(0) {
+}
+
+DiagnosticPrinter::~DiagnosticPrinter()
+{
+  clear();
+}
+
+/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+/// capturing it to a log as needed.
+void DiagnosticPrinter::handleDiagnostic(DiagnosticEngine::Severity pSeverity,
+                                         const Diagnostic& pInfo)
+{
+  if (pSeverity == DiagnosticEngine::Warning)
+    ++m_NumWarnings;
+  else if (pSeverity <= DiagnosticEngine::Error)
+    ++m_NumErrors;
+}
+
diff --git a/lib/LD/ELFDynObjFileFormat.cpp b/lib/LD/ELFDynObjFileFormat.cpp
index 77034eb..30183cc 100644
--- a/lib/LD/ELFDynObjFileFormat.cpp
+++ b/lib/LD/ELFDynObjFileFormat.cpp
@@ -6,11 +6,11 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <llvm/Support/ELF.h>
 #include <mcld/LD/ELFDynObjFileFormat.h>
 #include <mcld/LD/LDFileFormat.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/MC/MCLinker.h>
-#include <llvm/Support/ELF.h>
 #include <mcld/Target/GNULDBackend.h>
 
 using namespace mcld;
@@ -77,5 +77,10 @@
                                            llvm::ELF::SHT_PROGBITS,
                                            llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                            f_Backend.bitclass() / 8);
+  f_pEhFrameHdr     = &pLinker.getOrCreateOutputSectHdr(".eh_frame_hdr",
+                                              LDFileFormat::EhFrameHdr,
+                                              llvm::ELF::SHT_PROGBITS,
+                                              llvm::ELF::SHF_ALLOC,
+                                              0x4);
 }
 
diff --git a/lib/LD/ELFDynObjReader.cpp b/lib/LD/ELFDynObjReader.cpp
index 12e6d7c..de36104 100644
--- a/lib/LD/ELFDynObjReader.cpp
+++ b/lib/LD/ELFDynObjReader.cpp
@@ -69,9 +69,13 @@
   MemoryRegion* region = pInput.memArea()->request(0, hdr_size);
   uint8_t* ELF_hdr = region->start();
 
-  bool result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
+  bool shdr_result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
   pInput.memArea()->release(region);
-  return result;
+
+  // read .dynamic to get the correct SONAME
+  bool dyn_result = m_pELFReader->readDynamic(pInput);
+
+  return (shdr_result && dyn_result);
 }
 
 /// readSymbols
@@ -80,9 +84,20 @@
   assert(pInput.hasMemArea());
 
   LDSection* symtab_shdr = pInput.context()->getSection(".dynsym");
+  if (NULL == symtab_shdr) {
+    note(diag::note_has_no_symtab) << pInput.name()
+                                   << pInput.path()
+                                   << ".dynsym";
+    return true;
+  }
+
   LDSection* strtab_shdr = symtab_shdr->getLink();
-  if (NULL == symtab_shdr || NULL == strtab_shdr)
+  if (NULL == strtab_shdr) {
+    fatal(diag::fatal_cannot_read_strtab) << pInput.name()
+                                          << pInput.path()
+                                          << ".dynsym";
     return false;
+  }
 
   MemoryRegion* symtab_region = pInput.memArea()->request(symtab_shdr->offset(),
                                                           symtab_shdr->size());
diff --git a/lib/LD/ELFDynObjWriter.cpp b/lib/LD/ELFDynObjWriter.cpp
index 21cd8e4..cabc9e9 100644
--- a/lib/LD/ELFDynObjWriter.cpp
+++ b/lib/LD/ELFDynObjWriter.cpp
@@ -58,7 +58,10 @@
     switch(sect->kind()) {
       case LDFileFormat::Regular:
       case LDFileFormat::Relocation:
-      case LDFileFormat::Target: {
+      case LDFileFormat::Target:
+      case LDFileFormat::Debug:
+      case LDFileFormat::GCCExceptTable:
+      case LDFileFormat::EhFrame: {
         region = pOutput.memArea()->request(sect->offset(), sect->size());
         if (NULL == region) {
           llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") +
@@ -72,11 +75,10 @@
       case LDFileFormat::Null:
       case LDFileFormat::NamePool:
       case LDFileFormat::BSS:
-      case LDFileFormat::Debug:
       case LDFileFormat::Note:
       case LDFileFormat::MetaData:
-      case LDFileFormat::Exception:
       case LDFileFormat::Version:
+      case LDFileFormat::EhFrameHdr:
         // ignore these sections
         continue;
       default: {
@@ -91,7 +93,12 @@
 
     // write out sections with data
     switch(sect->kind()) {
-      case LDFileFormat::Regular: {
+      case LDFileFormat::Regular:
+      case LDFileFormat::Debug:
+      case LDFileFormat::GCCExceptTable:
+      case LDFileFormat::EhFrame: {
+        // FIXME: if optimization of exception handling sections is enabled,
+        // then we should emit these sections by the other way.
         emitSectionData(m_Linker.getLayout(), *sect, *region);
         break;
       }
@@ -99,11 +106,16 @@
         emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
         break;
       case LDFileFormat::Target:
-        target().emitSectionData(pOutput, *sect, m_Linker.getLDInfo(), *region);
+        target().emitSectionData(pOutput,
+                                 *sect,
+                                 m_Linker.getLDInfo(),
+                                 m_Linker.getLayout(),
+                                 *region);
         break;
       default:
         continue;
     }
+
   } // end of for loop
 
   if (32 == target().bitclass()) {
@@ -116,6 +128,8 @@
                      target(),
                      pOutput);
 
+    emitELF32ProgramHeader(pOutput, target());
+
     emitELF32SectionHeader(pOutput, m_Linker);
   }
   else if (64 == target().bitclass()) {
@@ -128,11 +142,13 @@
                      target(),
                      pOutput);
 
+    emitELF64ProgramHeader(pOutput, target());
+
     emitELF64SectionHeader(pOutput, m_Linker);
   }
   else
     return make_error_code(errc::not_supported);
-
+  pOutput.memArea()->clear();
   return llvm::make_error_code(llvm::errc::success);
 }
 
diff --git a/lib/LD/ELFExecFileFormat.cpp b/lib/LD/ELFExecFileFormat.cpp
index f10d764..8ae0de0 100644
--- a/lib/LD/ELFExecFileFormat.cpp
+++ b/lib/LD/ELFExecFileFormat.cpp
@@ -6,8 +6,81 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <llvm/Support/ELF.h>
 #include <mcld/LD/ELFExecFileFormat.h>
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/LD/LDSection.h>
 #include <mcld/MC/MCLinker.h>
+#include <mcld/Target/GNULDBackend.h>
 
 using namespace mcld;
 
+void ELFExecFileFormat::initObjectType(MCLinker& pLinker)
+{
+  // FIXME: make sure ELF executable files has these sections.
+  f_pDynSymTab    = &pLinker.getOrCreateOutputSectHdr(".dynsym",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_DYNSYM,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pDynStrTab    = &pLinker.getOrCreateOutputSectHdr(".dynstr",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_STRTAB,
+                                           llvm::ELF::SHF_ALLOC,
+                                           0x1);
+  f_pInterp       = &pLinker.getOrCreateOutputSectHdr(".interp",
+                                           LDFileFormat::Note,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC,
+                                           0x1);
+  f_pHashTab      = &pLinker.getOrCreateOutputSectHdr(".hash",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_HASH,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pDynamic      = &pLinker.getOrCreateOutputSectHdr(".dynamic",
+                                           LDFileFormat::NamePool,
+                                           llvm::ELF::SHT_DYNAMIC,
+                                           llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+                                           f_Backend.bitclass() / 8);
+  f_pRelaDyn      = &pLinker.getOrCreateOutputSectHdr(".rela.dyn",
+                                           LDFileFormat::Relocation,
+                                           llvm::ELF::SHT_RELA,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pRelaPlt      = &pLinker.getOrCreateOutputSectHdr(".rela.plt",
+                                           LDFileFormat::Relocation,
+                                           llvm::ELF::SHT_RELA,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pRelDyn      = &pLinker.getOrCreateOutputSectHdr(".rel.dyn",
+                                           LDFileFormat::Relocation,
+                                           llvm::ELF::SHT_REL,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pRelPlt      = &pLinker.getOrCreateOutputSectHdr(".rel.plt",
+                                           LDFileFormat::Relocation,
+                                           llvm::ELF::SHT_REL,
+                                           llvm::ELF::SHF_ALLOC,
+                                           f_Backend.bitclass() / 8);
+  f_pGOT          = &pLinker.getOrCreateOutputSectHdr(".got",
+                                           LDFileFormat::Target,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+                                           f_Backend.bitclass() / 8);
+  f_pPLT          = &pLinker.getOrCreateOutputSectHdr(".plt",
+                                           LDFileFormat::Target,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
+                                           f_Backend.bitclass() / 8);
+  f_pGOTPLT       = &pLinker.getOrCreateOutputSectHdr(".got.plt",
+                                           LDFileFormat::Target,
+                                           llvm::ELF::SHT_PROGBITS,
+                                           llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+                                           f_Backend.bitclass() / 8);
+  f_pEhFrameHdr     = &pLinker.getOrCreateOutputSectHdr(".eh_frame_hdr",
+                                              LDFileFormat::EhFrameHdr,
+                                              llvm::ELF::SHT_PROGBITS,
+                                              llvm::ELF::SHF_ALLOC,
+                                              0x4);
+}
diff --git a/lib/LD/ELFExecWriter.cpp b/lib/LD/ELFExecWriter.cpp
new file mode 100644
index 0000000..7438180
--- /dev/null
+++ b/lib/LD/ELFExecWriter.cpp
@@ -0,0 +1,157 @@
+//===- ELFExecWriter.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFExecWriter.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/MCLDOutput.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLinker.h>
+#include <llvm/Support/ELF.h>
+#include <vector>
+
+using namespace llvm;
+using namespace mcld;
+
+
+//==========================
+// ELFExecWriter
+ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker)
+  : ExecWriter(pBackend),
+    ELFWriter(pBackend),
+    m_Backend(pBackend),
+    m_Linker(pLinker) {
+
+}
+
+ELFExecWriter::~ELFExecWriter()
+{
+}
+
+llvm::error_code ELFExecWriter::writeExecutable(Output& pOutput)
+{
+  // write out the interpreter section: .interp
+  target().emitInterp(pOutput, m_Linker.getLDInfo());
+
+  // Write out name pool sections: .dynsym, .dynstr, .hash
+  target().emitDynNamePools(pOutput,
+                            m_Linker.getOutputSymbols(),
+                            m_Linker.getLayout(),
+                            m_Linker.getLDInfo());
+
+  // Write out name pool sections: .symtab, .strtab
+  target().emitRegNamePools(pOutput,
+                            m_Linker.getOutputSymbols(),
+                            m_Linker.getLayout(),
+                            m_Linker.getLDInfo());
+
+  // Write out regular ELF sections
+  unsigned int secIdx = 0;
+  unsigned int secEnd = pOutput.context()->numOfSections();
+  for (secIdx = 0; secIdx < secEnd; ++secIdx) {
+    LDSection* sect = pOutput.context()->getSection(secIdx);
+    MemoryRegion* region = NULL;
+    // request output region
+    switch(sect->kind()) {
+      case LDFileFormat::Regular:
+      case LDFileFormat::Relocation:
+      case LDFileFormat::Target:
+      case LDFileFormat::Debug:
+      case LDFileFormat::GCCExceptTable:
+      case LDFileFormat::EhFrame: {
+        region = pOutput.memArea()->request(sect->offset(), sect->size());
+        if (NULL == region) {
+          llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") +
+                                   llvm::Twine(secIdx) +
+                                   llvm::Twine("] - `") +
+                                   sect->name() +
+                                   llvm::Twine("'.\n"));
+        }
+        break;
+      }
+      case LDFileFormat::Null:
+      case LDFileFormat::NamePool:
+      case LDFileFormat::BSS:
+      case LDFileFormat::Note:
+      case LDFileFormat::MetaData:
+      case LDFileFormat::Version:
+      case LDFileFormat::EhFrameHdr:
+        // ignore these sections
+        continue;
+      default: {
+        llvm::errs() << "WARNING: unsupported section kind: "
+                     << sect->kind()
+                     << " of section "
+                     << sect->name()
+                     << ".\n";
+        continue;
+      }
+    }
+
+    // write out sections with data
+    switch(sect->kind()) {
+      case LDFileFormat::Regular:
+      case LDFileFormat::Debug:
+      case LDFileFormat::GCCExceptTable:
+      case LDFileFormat::EhFrame: {
+        // FIXME: if optimization of exception handling sections is enabled,
+        // then we should emit these sections by the other way.
+        emitSectionData(m_Linker.getLayout(), *sect, *region);
+        break;
+      }
+      case LDFileFormat::Relocation:
+        emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
+        break;
+      case LDFileFormat::Target:
+        target().emitSectionData(pOutput,
+                                 *sect,
+                                 m_Linker.getLDInfo(),
+                                 m_Linker.getLayout(),
+                                 *region);
+        break;
+      default:
+        continue;
+    }
+  } // end of for loop
+
+  if (32 == target().bitclass()) {
+    // Write out ELF header
+    // Write out section header table
+    emitELF32ShStrTab(pOutput, m_Linker);
+
+    writeELF32Header(m_Linker.getLDInfo(),
+                     m_Linker.getLayout(),
+                     target(),
+                     pOutput);
+
+    emitELF32ProgramHeader(pOutput, target());
+
+    emitELF32SectionHeader(pOutput, m_Linker);
+  }
+  else if (64 == target().bitclass()) {
+    // Write out ELF header
+    // Write out section header table
+    emitELF64ShStrTab(pOutput, m_Linker);
+
+    writeELF64Header(m_Linker.getLDInfo(),
+                     m_Linker.getLayout(),
+                     target(),
+                     pOutput);
+
+    emitELF64ProgramHeader(pOutput, target());
+
+    emitELF64SectionHeader(pOutput, m_Linker);
+  }
+  else
+    return make_error_code(errc::not_supported);
+
+  pOutput.memArea()->clear();
+  return llvm::make_error_code(llvm::errc::success);
+}
+
diff --git a/lib/LD/ELFFileFormat.cpp b/lib/LD/ELFFileFormat.cpp
index 9394e44..f1c39cb 100644
--- a/lib/LD/ELFFileFormat.cpp
+++ b/lib/LD/ELFFileFormat.cpp
@@ -57,7 +57,8 @@
     f_pJCR(NULL),
     f_pNoteABITag(NULL),
     f_pStab(NULL),
-    f_pStabStr(NULL) {
+    f_pStabStr(NULL),
+    f_pStack(NULL) {
 
 }
 
@@ -186,7 +187,7 @@
   f_pDataRelRo      = &pLinker.getOrCreateOutputSectHdr(".data.rel.ro",
                                               LDFileFormat::Regular,
                                               llvm::ELF::SHT_PROGBITS,
-                                              llvm::ELF::SHF_ALLOC,
+                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
   f_pDtors          = &pLinker.getOrCreateOutputSectHdr(".dtors",
                                               LDFileFormat::Regular,
@@ -194,20 +195,15 @@
                                               llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                               0x1);
   f_pEhFrame        = &pLinker.getOrCreateOutputSectHdr(".eh_frame",
-                                              LDFileFormat::Exception,
+                                              LDFileFormat::EhFrame,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
-                                              0x1);
-  f_pEhFrameHdr     = &pLinker.getOrCreateOutputSectHdr(".eh_frame_hdr",
-                                              LDFileFormat::Exception,
-                                              llvm::ELF::SHT_PROGBITS,
-                                              llvm::ELF::SHF_ALLOC,
-                                              0x1);
+                                              0x4);
   f_pGCCExceptTable = &pLinker.getOrCreateOutputSectHdr(".gcc_except_table",
-                                              LDFileFormat::Exception,
+                                              LDFileFormat::GCCExceptTable,
                                               llvm::ELF::SHT_PROGBITS,
                                               llvm::ELF::SHF_ALLOC,
-                                              0x1);
+                                              0x4);
   f_pGNUVersion     = &pLinker.getOrCreateOutputSectHdr(".gnu.version",
                                               LDFileFormat::Version,
                                               llvm::ELF::SHT_GNU_versym,
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index abc3d30..1ea81e2 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -8,13 +8,13 @@
 //===----------------------------------------------------------------------===//
 #include <llvm/Support/ELF.h>
 #include <llvm/ADT/Twine.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/LD/ELFObjectReader.h>
 #include <mcld/LD/ELFReader.h>
 #include <mcld/MC/MCLDInput.h>
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/MCRegionFragment.h>
 #include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MsgHandling.h>
 
 #include <string>
 #include <cassert>
@@ -99,7 +99,14 @@
                                        (*section)->getInfo());
 
         bool exist = false;
-        signatures().insert(signature->name(), exist);
+        if (0 == std::strlen(signature->name()) &&
+            ResolveInfo::Section == signature->type()) {
+          // if the signature is a section symbol in input object, we use the
+          // section name as group signature.
+          signatures().insert((*section)->name(), exist);
+        } else {
+          signatures().insert(signature->name(), exist);
+        }
 
         if (exist) {
           // if this is not the first time we see this group signature, then
@@ -132,28 +139,32 @@
         break;
       }
       /** normal sections **/
-      // FIXME: support Debug, Exception and Version Kinds
-      case LDFileFormat::Debug:
-      case LDFileFormat::Exception:
+      // FIXME: support Version Kinds
       case LDFileFormat::Version:
       /** Fall through **/
       case LDFileFormat::Regular:
       case LDFileFormat::Note:
+      case LDFileFormat::Debug:
       case LDFileFormat::MetaData: {
         if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
-          llvm::report_fatal_error(
-                                llvm::Twine("can not read regular section `") +
-                                (*section)->name() +
-                                llvm::Twine("'.\n"));
+          fatal(diag::err_cannot_read_section) << (*section)->name();
+        break;
+      }
+      case LDFileFormat::EhFrame: {
+        if (!m_pELFReader->readEhFrame(pInput, m_Linker, **section))
+          fatal(diag::err_cannot_read_section) <<(*section)->name();
+        break;
+      }
+      case LDFileFormat::GCCExceptTable: {
+        //if (!m_pELFReader->readExceptionSection(pInput, m_Linker, **section))
+        if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
+          fatal(diag::err_cannot_read_section) << (*section)->name();
         break;
       }
       /** target dependent sections **/
       case LDFileFormat::Target: {
         if (!m_pELFReader->readTargetSection(pInput, m_Linker, **section))
-          llvm::report_fatal_error(
-                        llvm::Twine("can not read target dependentsection `") +
-                        (*section)->name() +
-                        llvm::Twine("'.\n"));
+          fatal(diag::err_cannot_read_target_section) << (*section)->name();
         break;
       }
       /** BSS sections **/
@@ -179,7 +190,14 @@
       case LDFileFormat::Null:
       case LDFileFormat::NamePool:
         continue;
-
+      // warning
+      case LDFileFormat::EhFrameHdr:
+      default: {
+        warning(diag::warn_illegal_input_section) << (*section)->name()
+                                                  << pInput.name()
+                                                  << pInput.path();
+        break;
+      }
     }
   } // end of for all sections
 
@@ -192,9 +210,20 @@
   assert(pInput.hasMemArea());
 
   LDSection* symtab_shdr = pInput.context()->getSection(".symtab");
+  if (NULL == symtab_shdr) {
+    note(diag::note_has_no_symtab) << pInput.name()
+                                   << pInput.path()
+                                   << ".symtab";
+    return true;
+  }
+
   LDSection* strtab_shdr = symtab_shdr->getLink();
-  if (NULL == symtab_shdr || NULL == strtab_shdr)
+  if (NULL == strtab_shdr) {
+    fatal(diag::fatal_cannot_read_strtab) << pInput.name()
+                                          << pInput.path()
+                                          << ".symtab";
     return false;
+  }
 
   MemoryRegion* symtab_region = pInput.memArea()->request(symtab_shdr->offset(),
                                                           symtab_shdr->size());
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index 1fd2a13..6aacc08 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -7,15 +7,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <llvm/Support/ELF.h>
 #include <llvm/ADT/StringRef.h>
 #include <llvm/ADT/Twine.h>
+#include <llvm/Support/ELF.h>
 #include <llvm/Support/Host.h>
 #include <mcld/MC/MCLinker.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
 #include <mcld/LD/ELFReader.h>
 #include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include <cstring>
 
 using namespace mcld;
@@ -28,16 +29,22 @@
 {
   // name rules
   llvm::StringRef name(pName);
-  if (llvm::StringRef::npos != name.find(".debug"))
+  if (name.startswith(".debug") ||
+      name.startswith(".zdebug") ||
+      name.startswith(".gnu.linkonce.wi.") ||
+      name.startswith(".line") ||
+      name.startswith(".stab"))
     return LDFileFormat::Debug;
   if (name.startswith(".comment"))
     return LDFileFormat::MetaData;
   if (name.startswith(".interp") || name.startswith(".dynamic"))
     return LDFileFormat::Note;
-  if (name.startswith(".eh_frame") ||
-      name.startswith(".eh_frame_hdr") ||
-      name.startswith(".gcc_except_table"))
-    return LDFileFormat::Exception;
+  if (name.startswith(".eh_frame"))
+    return LDFileFormat::EhFrame;
+  if (name.startswith(".eh_frame_hdr"))
+    return LDFileFormat::EhFrameHdr;
+  if (name.startswith(".gcc_except_table"))
+    return LDFileFormat::GCCExceptTable;
 
   // type rules
   switch(pType) {
@@ -74,8 +81,7 @@
         (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) ||
         (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER))
       return LDFileFormat::Target;
-    llvm::report_fatal_error(llvm::Twine("unsupported ELF section type: ") +
-                             llvm::Twine(pType) + llvm::Twine(".\n"));
+    fatal(diag::err_unsupported_section) << pName << pType;
   }
   return LDFileFormat::MetaData;
 }
@@ -141,13 +147,9 @@
 
   LDSection* sect_hdr = pInput.context()->getSection(pShndx);
 
-  if (NULL == sect_hdr) {
-    llvm::report_fatal_error(llvm::Twine("section[") +
-                             llvm::Twine(pShndx) +
-                             llvm::Twine("] is invalid in file `") +
-                             pInput.path().native() +
-                             llvm::Twine("'.\n"));
-  }
+  if (NULL == sect_hdr)
+    unreachable(diag::unreachable_invalid_section_idx) << pShndx
+                                                       << pInput.path().native();
   
   MCFragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset);
   return result;
@@ -186,3 +188,17 @@
   return 0x0;
 }
 
+bool ELFReaderIF::readEhFrame(Input& pInput,
+                              MCLinker& pLinker,
+                              LDSection& pInputSectHdr) const
+{
+  LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
+                                                         pInputSectHdr.kind(),
+                                                         pInputSectHdr.type(),
+                                                         pInputSectHdr.flag());
+
+  size_t size = pLinker.addEhFrame(pInputSectHdr, *pInput.memArea());
+
+  out_sect.setSize(out_sect.size() + size);
+  return true;
+}
diff --git a/lib/LD/ELFSegment.cpp b/lib/LD/ELFSegment.cpp
index a08641b..dbefbc5 100644
--- a/lib/LD/ELFSegment.cpp
+++ b/lib/LD/ELFSegment.cpp
@@ -19,7 +19,8 @@
                        uint64_t pPaddr,
                        uint64_t pFilesz,
                        uint64_t pMemsz,
-                       uint64_t pAlign)
+                       uint64_t pAlign,
+                       uint64_t pMaxSectAlign)
   : m_Type(pType),
     m_Flag(pFlag),
     m_Offset(pOffset),
@@ -27,7 +28,8 @@
     m_Paddr(pPaddr),
     m_Filesz(pFilesz),
     m_Memsz(pMemsz),
-    m_Align(pAlign) {
+    m_Align(pAlign),
+    m_MaxSectionAlign(pMaxSectAlign) {
 }
 
 ELFSegment::~ELFSegment()
diff --git a/lib/LD/ELFSegmentFactory.cpp b/lib/LD/ELFSegmentFactory.cpp
index d8ad3cc..af0f588 100644
--- a/lib/LD/ELFSegmentFactory.cpp
+++ b/lib/LD/ELFSegmentFactory.cpp
@@ -25,16 +25,40 @@
 /// produce - produce an empty ELF segment information.
 /// this function will create an ELF segment
 /// @param pType - p_type in ELF program header
-ELFSegment* ELFSegmentFactory::produce(uint32_t pType)
+ELFSegment* ELFSegmentFactory::produce(uint32_t pType, uint32_t pFlag)
 {
   ELFSegment* segment = allocate();
-  new (segment) ELFSegment(pType);
+  new (segment) ELFSegment(pType, pFlag);
   return segment;
 }
 
-/// destroy - destruct the ELF segment
-void ELFSegmentFactory::destroy(ELFSegment*& pSegment)
+ELFSegment*
+ELFSegmentFactory::find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear)
 {
-  deallocate(pSegment);
+  iterator segment, segEnd = end();
+  for (segment = begin(); segment != segEnd; ++segment) {
+    if ((*segment).type() == pType &&
+        ((*segment).flag() & pFlagSet) == pFlagSet &&
+        ((*segment).flag() & pFlagClear) == 0x0) {
+      return &(*segment);
+    }
+  }
+  return NULL;
+}
+
+const ELFSegment*
+ELFSegmentFactory::find(uint32_t pType,
+                        uint32_t pFlagSet,
+                        uint32_t pFlagClear) const
+{
+  const_iterator segment, segEnd = end();
+  for (segment = begin(); segment != segEnd; ++segment) {
+    if ((*segment).type() == pType &&
+        ((*segment).flag() & pFlagSet) == pFlagSet &&
+        ((*segment).flag() & pFlagClear) == 0x0) {
+      return &(*segment);
+    }
+  }
+  return NULL;
 }
 
diff --git a/lib/LD/ELFWriter.cpp b/lib/LD/ELFWriter.cpp
index a94fd5c..2f2d898 100644
--- a/lib/LD/ELFWriter.cpp
+++ b/lib/LD/ELFWriter.cpp
@@ -18,6 +18,8 @@
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/LDSection.h>
 #include <mcld/LD/Layout.h>
+#include <mcld/LD/ELFSegment.h>
+#include <mcld/LD/ELFSegmentFactory.h>
 #include <mcld/Target/GNULDBackend.h>
 #include <cstdlib>
 #include <cstring>
@@ -146,7 +148,7 @@
                        && (pOutput.type() != Output::Object)
                        && (pOutput.type() != Output::DynObj));
 
-  const LDSymbol* entry_symbol = pLDInfo.getStrSymPool().findSymbol(entry_name);
+  const LDSymbol* entry_symbol = pLDInfo.getNamePool().findSymbol(entry_name);
 
   // found the symbol
   if (NULL != entry_symbol) {
@@ -244,6 +246,70 @@
   }
 }
 
+
+/// emitELF32ProgramHeader - emit Elf32_Phdr
+void ELFWriter::emitELF32ProgramHeader(Output& pOutput,
+                                       const GNULDBackend& pBackend) const
+{
+  assert(pOutput.hasMemArea());
+
+  uint64_t start_offset, phdr_size;
+
+  start_offset = sizeof(Elf32_Ehdr);
+  phdr_size = sizeof(Elf32_Phdr);
+  // Program header must start directly after ELF header
+  MemoryRegion *region = pOutput.memArea()->request(start_offset,
+                                          pBackend.numOfSegments() * phdr_size);
+
+  Elf32_Phdr* phdr = (Elf32_Phdr*)region->start();
+
+  // Iterate the elf segment table in GNULDBackend
+  size_t index = 0;
+  ELFSegmentFactory::const_iterator seg = pBackend.elfSegmentTable().begin(),
+                                 segEnd = pBackend.elfSegmentTable().end();
+  for (; seg != segEnd; ++seg, ++index) {
+    phdr[index].p_type   = (*seg).type();
+    phdr[index].p_flags  = (*seg).flag();
+    phdr[index].p_offset = (*seg).offset();
+    phdr[index].p_vaddr  = (*seg).vaddr();
+    phdr[index].p_paddr  = (*seg).paddr();
+    phdr[index].p_filesz = (*seg).filesz();
+    phdr[index].p_memsz  = (*seg).memsz();
+    phdr[index].p_align  = (*seg).align();
+  }
+}
+
+/// emitELF64ProgramHeader - emit ElfR64Phdr
+void ELFWriter::emitELF64ProgramHeader(Output& pOutput,
+                                       const GNULDBackend& pBackend) const
+{
+  assert(pOutput.hasMemArea());
+
+  uint64_t start_offset, phdr_size;
+
+  start_offset = sizeof(Elf64_Ehdr);
+  phdr_size = sizeof(Elf64_Phdr);
+  // Program header must start directly after ELF header
+  MemoryRegion *region = pOutput.memArea()->request(start_offset,
+                                          pBackend.numOfSegments() * phdr_size);
+  Elf64_Phdr* phdr = (Elf64_Phdr*)region->start();
+
+  // Iterate the elf segment table in GNULDBackend
+  size_t index = 0;
+  ELFSegmentFactory::const_iterator seg = pBackend.elfSegmentTable().begin(),
+                                 segEnd = pBackend.elfSegmentTable().end();
+  for (; seg != segEnd; ++seg, ++index) {
+    phdr[index].p_type   = (*seg).type();
+    phdr[index].p_flags  = (*seg).flag();
+    phdr[index].p_offset = (*seg).offset();
+    phdr[index].p_vaddr  = (*seg).vaddr();
+    phdr[index].p_paddr  = (*seg).paddr();
+    phdr[index].p_filesz = (*seg).filesz();
+    phdr[index].p_memsz  = (*seg).memsz();
+    phdr[index].p_align  = (*seg).align();
+  }
+}
+
 /// emitELF32ShStrTab - emit section string table
 void ELFWriter::emitELF32ShStrTab(Output& pOutput, MCLinker& pLinker) const
 {
diff --git a/lib/LD/EhFrame.cpp b/lib/LD/EhFrame.cpp
new file mode 100644
index 0000000..76af403
--- /dev/null
+++ b/lib/LD/EhFrame.cpp
@@ -0,0 +1,373 @@
+//===- EhFrame.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrame.h>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <llvm/Support/Dwarf.h>
+#include <llvm/Support/Host.h>
+
+using namespace mcld;
+
+//==========================
+// EhFrame
+EhFrame::EhFrame()
+ : m_fCanRecognizeAll(true) {
+}
+
+EhFrame::~EhFrame()
+{
+}
+
+uint64_t EhFrame::readEhFrame(Layout& pLayout,
+                              const TargetLDBackend& pBackend,
+                              llvm::MCSectionData& pSD,
+                              LDSection& pSection,
+                              MemoryArea& pArea)
+{
+  MemoryRegion* region = pArea.request(pSection.offset(),
+                                       pSection.size());
+  // an empty .eh_frame
+  if (NULL == region) {
+    note(diag::note_ehframe) << "an empty eh_frame";
+    return 0;
+  }
+
+  ConstAddress eh_start = region->start();
+  ConstAddress eh_end = region->end();
+  ConstAddress p = eh_start;
+
+  // read the Length filed
+  uint32_t len = readVal(p, pBackend.isLittleEndian());
+
+  // This CIE is a terminator if the Length field is 0, return 0 to handled it
+  // as an ordinary input.
+  if (0 == len) {
+    note(diag::note_ehframe) << "a terminator";
+    pArea.release(region);
+    return 0;
+  }
+
+  if (0xffffffff == len) {
+    debug(diag::debug_eh_unsupport) << "64-bit eh_frame";
+    pArea.release(region);
+    m_fCanRecognizeAll = false;
+    return 0;
+  }
+
+  // record the order of the CIE and FDE fragments
+  FragListType frag_list;
+
+  while (p < eh_end) {
+
+    if (eh_end - p < 4) {
+      debug(diag::debug_eh_unsupport) << "CIE or FDE size smaller than 4";
+      m_fCanRecognizeAll = false;
+      break;
+    }
+    // read the Length field
+    len = readVal(p, pBackend.isLittleEndian());
+    p += 4;
+
+    // the zero length entry should be the end of the section
+    if (0 == len) {
+      if (p < eh_end) {
+        debug(diag::debug_eh_unsupport) << "Non-end entry with zero length";
+        m_fCanRecognizeAll = false;
+      }
+      break;
+    }
+    if (0xffffffff == len) {
+      debug(diag::debug_eh_unsupport) << "64-bit eh_frame";
+      m_fCanRecognizeAll = false;
+      break;
+    }
+
+    if (eh_end - p < 4) {
+      debug(diag::debug_eh_unsupport) <<
+        "CIE:ID field / FDE: CIE Pointer field";
+      m_fCanRecognizeAll = false;
+      break;
+    }
+
+    // compute the section offset of this entry
+    uint32_t ent_offset = static_cast<uint32_t>(p - eh_start - 4);
+
+    // get the MemoryRegion for this entry
+    MemoryRegion* ent_region = pArea.request(pSection.offset() + ent_offset,
+                                             len + 4);
+
+    // create and add a CIE or FDE entry
+    uint32_t id = readVal(p, pBackend.isLittleEndian());
+    // CIE
+    if (0 == id) {
+      if (!addCIE(*ent_region, pBackend, frag_list)) {
+        m_fCanRecognizeAll = false;
+        pArea.release(ent_region);
+        break;
+      }
+    }
+
+    // FDE
+    else {
+      if (!addFDE(*ent_region, pBackend, frag_list)) {
+        m_fCanRecognizeAll = false;
+        pArea.release(ent_region);
+        break;
+      }
+    }
+    p += len;
+  }
+
+  if (!m_fCanRecognizeAll) {
+    pArea.release(region);
+    deleteFragments(frag_list, pArea);
+    return 0;
+  }
+
+  // append all CIE and FDE fragments to Layout after we successfully read
+  // this eh_frame
+  size_t section_size = 0;
+  for (FragListType::iterator it = frag_list.begin();
+         it != frag_list.end(); ++it)
+    section_size += pLayout.appendFragment(**it, pSD, pSection.align());
+
+  pArea.release(region);
+  return section_size;
+}
+
+bool EhFrame::addCIE(MemoryRegion& pRegion,
+                     const TargetLDBackend& pBackend,
+                     FragListType& pFragList)
+{
+  ConstAddress cie_start = pRegion.start();
+  ConstAddress cie_end = pRegion.end();
+  ConstAddress p = cie_start;
+
+  // skip the Length (4 byte) and CIE ID (4 byte) fields
+  p += 8;
+
+  // the version should be 1
+  if (1 != *p) {
+    debug(diag::debug_eh_unsupport) << "CIE version";
+    return false;
+  }
+  ++p;
+
+  // get the Augumentation String
+  ConstAddress aug_str = p;
+  ConstAddress aug_str_end = static_cast<ConstAddress>(
+                               memchr(p, '\0', cie_end - p));
+
+  // skip the Augumentation String field
+  p = aug_str_end + 1;
+
+  // skip the Code Alignment Factor
+  if (!skipLEB128(&p, cie_end)) {
+    debug(diag::debug_eh_unsupport) << "unrecognized Code Alignment Factor";
+    return false;
+  }
+  // skip the Data Alignment Factor
+  if (!skipLEB128(&p, cie_end)) {
+    debug(diag::debug_eh_unsupport) << "unrecognized Data Alignment Factor";
+    return false;
+  }
+  // skip the Return Address Register
+  if (cie_end - p < 1) {
+    debug(diag::debug_eh_unsupport) << "unrecognized Return Address Register";
+    return false;
+  }
+  ++p;
+
+  // the Augmentation String start with 'eh' is a CIE from gcc before 3.0,
+  // in LSB Core Spec 3.0RC1. We do not support it.
+  if (aug_str[0] == 'e' && aug_str[1] == 'h') {
+    debug(diag::debug_eh_unsupport) << "augmentation string `eh`";
+    return false;
+  }
+
+  // parse the Augmentation String to get the FDE encodeing if 'z' existed
+  std::string aug_str_data;
+  uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr;
+  if (*aug_str == 'z') {
+
+    aug_str_data += *aug_str;
+    ++aug_str;
+
+    // skip the Augumentation Data Length
+    if (!skipLEB128(&p, cie_end)) {
+      debug(diag::debug_eh_unsupport) <<
+        "unrecognized Augmentation Data Length";
+      return false;
+    }
+
+    while (aug_str != aug_str_end) {
+      switch (*aug_str) {
+        default:
+          debug(diag::debug_eh_unsupport) << "augmentation string";
+          return false;
+
+        // LDSA encoding (1 byte)
+        case 'L':
+          if (cie_end - p < 1) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `L`";
+            return false;
+          }
+          ++p;
+          break;
+
+        // Two arguments, the first one represents the encoding of the second
+        // argument (1 byte). The second one is the address of personality
+        // routine.
+        case 'P': {
+          // the first argument
+          if (cie_end - p < 1) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+            return false;
+          }
+          uint8_t per_encode = *p;
+          ++p;
+          // get the length of the second argument
+          uint32_t per_length = 0;
+          if (0x60 == (per_encode & 0x60)) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+            return false;
+          }
+          switch (per_encode & 7) {
+            default:
+              debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+              return false;
+            case llvm::dwarf::DW_EH_PE_udata2:
+              per_length = 2;
+              break;
+            case llvm::dwarf::DW_EH_PE_udata4:
+              per_length = 4;
+              break;
+            case llvm::dwarf::DW_EH_PE_udata8:
+              per_length = 8;
+              break;
+            case llvm::dwarf::DW_EH_PE_absptr:
+              per_length = pBackend.bitclass() / 8;
+              break;
+          }
+          // skip the alignment
+          if (llvm::dwarf::DW_EH_PE_aligned == (per_encode & 0xf0)) {
+            uint32_t per_align = p - cie_end;
+            per_align += per_length - 1;
+            per_align &= ~(per_length -1);
+            if (static_cast<uint32_t>(cie_end - p) < per_align) {
+              debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+              return false;
+            }
+            p += per_align;
+          }
+          // skip the second argument
+          if (static_cast<uint32_t>(cie_end - p) < per_length) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `P`";
+            return false;
+          }
+          p += per_length;
+        }
+        break;
+
+        // FDE encoding (1 byte)
+        case 'R':
+          if (cie_end - p < 1) {
+            debug(diag::debug_eh_unsupport) << "augmentation string `R`";
+            return false;
+          }
+          fde_encoding = *p;
+          switch (fde_encoding & 7) {
+            case llvm::dwarf::DW_EH_PE_udata2:
+            case llvm::dwarf::DW_EH_PE_udata4:
+            case llvm::dwarf::DW_EH_PE_udata8:
+            case llvm::dwarf::DW_EH_PE_absptr:
+              break;
+            default:
+              debug(diag::debug_eh_unsupport) << "FDE encoding";
+              return false;
+          }
+          ++p;
+          break;
+      } // end switch
+      aug_str_data += *aug_str;
+      ++aug_str;
+    } // end while
+  }
+
+  note(diag::note_eh_cie) << pRegion.size()
+                          << aug_str_data
+                          << (fde_encoding & 7);
+
+  // create and push back the CIE entry
+  CIE* entry = new CIE(pRegion, fde_encoding);
+  m_CIEs.push_back(entry);
+  pFragList.push_back(static_cast<llvm::MCFragment*>(entry));
+  return true;
+}
+
+bool EhFrame::addFDE(MemoryRegion& pRegion,
+                     const TargetLDBackend& pBackend,
+                     FragListType& pFragList)
+{
+  ConstAddress fde_start = pRegion.start();
+  ConstAddress fde_end = pRegion.end();
+  ConstAddress p = fde_start;
+
+  // skip the Length (4 byte) and CIE Pointer (4 byte) fields
+  p += 8;
+
+  // get the entry offset of the PC Begin
+  if (fde_end - p < 1) {
+    debug(diag::debug_eh_unsupport) << "FDE PC Begin";
+    return false;
+  }
+  FDE::Offset pc_offset = static_cast<FDE::Offset>(p - fde_start);
+
+  note(diag::note_eh_fde) << pRegion.size() << pc_offset;
+  // create and push back the FDE entry
+  FDE* entry = new FDE(pRegion, **(m_CIEs.end() -1), pc_offset);
+  m_FDEs.push_back(entry);
+  pFragList.push_back(static_cast<llvm::MCFragment*>(entry));
+  return true;
+}
+
+uint32_t EhFrame::readVal(ConstAddress pAddr, bool pIsTargetLittleEndian)
+{
+  const uint32_t* p = reinterpret_cast<const uint32_t*>(pAddr);
+  uint32_t val = *p;
+
+  // byte swapping if the host and target have different endian
+  if (llvm::sys::isLittleEndianHost() != pIsTargetLittleEndian)
+    val = bswap32(val);
+  return val;
+}
+
+bool EhFrame::skipLEB128(ConstAddress* pp, ConstAddress pend)
+{
+  for (ConstAddress p = *pp; p < pend; ++p) {
+    if (0 == (*p & 0x80)) {
+      *pp = p + 1;
+      return true;
+    }
+  }
+  return false;
+}
+
+void EhFrame::deleteFragments(FragListType& pList, MemoryArea& pArea)
+{
+  MCRegionFragment* frag = NULL;
+  for (FragListType::iterator it = pList.begin(); it != pList.end(); ++it) {
+    frag = static_cast<MCRegionFragment*>(*it);
+    pArea.release(&(frag->getRegion()));
+    delete *it;
+  }
+  pList.clear();
+}
+
diff --git a/lib/LD/EhFrameHdr.cpp b/lib/LD/EhFrameHdr.cpp
new file mode 100644
index 0000000..8806af4
--- /dev/null
+++ b/lib/LD/EhFrameHdr.cpp
@@ -0,0 +1,49 @@
+//===- EhFrameHdr.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrameHdr.h>
+
+using namespace mcld;
+
+//==========================
+// EhFrameHdr
+EhFrameHdr::EhFrameHdr(const EhFrame& pEhFrameData,
+                       const LDSection& pEhFrameSect,
+                       LDSection& pEhFrameHdrSect)
+  : m_EhFrameData(pEhFrameData),
+    m_EhFrameSect(pEhFrameSect),
+    m_EhFrameHdrSect(pEhFrameHdrSect)
+{
+}
+
+EhFrameHdr::~EhFrameHdr()
+{
+}
+
+/// @ref lsb core generic 4.1
+/// .eh_frame_hdr section format
+/// uint8_t : version
+/// uint8_t : eh_frame_ptr_enc
+/// uint8_t : fde_count_enc
+/// uint8_t : table_enc
+/// uint32_t : eh_frame_ptr
+/// uint32_t : fde_count
+/// __________________________ when fde_count > 0
+/// <uint32_t, uint32_t>+ : binary search table
+
+/// sizeOutput - base on the fde count to size output
+void EhFrameHdr::sizeOutput()
+{
+  size_t size = 12;
+  if (m_EhFrameData.canRecognizeAllEhFrame()) {
+    size_t fde_count = m_EhFrameData.getFDECount();
+    size += 8 * fde_count;
+  }
+  m_EhFrameHdrSect.setSize(size);
+}
+
diff --git a/lib/LD/ExecWriter.cpp b/lib/LD/ExecWriter.cpp
new file mode 100644
index 0000000..d66cd17
--- /dev/null
+++ b/lib/LD/ExecWriter.cpp
@@ -0,0 +1,16 @@
+//===- ExecWriter.cpp ---------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "mcld/LD/ExecWriter.h"
+#include "mcld/Target/TargetLDBackend.h"
+#include "mcld/MC/MCLDInput.h"
+
+using namespace mcld;
+
+//==========================
+// ExecWriter
diff --git a/lib/LD/FDE.cpp b/lib/LD/FDE.cpp
new file mode 100644
index 0000000..b70f7e1
--- /dev/null
+++ b/lib/LD/FDE.cpp
@@ -0,0 +1,24 @@
+//===- FDE.cpp ------------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/FDE.h>
+
+using namespace mcld;
+
+//==========================
+// FDE
+
+FDE::FDE(MemoryRegion& pRegion, const CIE& pCIE, Offset pPCBeginOffset)
+  : MCRegionFragment(pRegion), m_CIE(pCIE), m_PCBeginOffset(pPCBeginOffset) {
+}
+
+FDE::~FDE()
+{
+}
+
diff --git a/lib/LD/GNUArchiveReader.cpp b/lib/LD/GNUArchiveReader.cpp
index 3fa00b8..0a64752 100644
--- a/lib/LD/GNUArchiveReader.cpp
+++ b/lib/LD/GNUArchiveReader.cpp
@@ -6,42 +6,35 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInfo.h"
-#include "mcld/MC/MCLDInput.h"
-#include "mcld/MC/MCLDInputTree.h"
-#include "mcld/LD/GNUArchiveReader.h"
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/InputTree.h>
+#include <mcld/LD/GNUArchiveReader.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/ADT/SizeTraits.h>
 
-#include <llvm/Support/MemoryBuffer.h>
 #include <llvm/Support/system_error.h>
+#include <llvm/Support/Host.h>
 
 #include <sstream>
 #include <string>
 #include <vector>
 #include <cstdlib>
 
-using namespace std;
 using namespace mcld;
 
-typedef size_t sectionSizeTy;
 typedef uint32_t elfWord;
 
-/// Archive Header, Magic number, etc..
 
-const unsigned archiveMagicSize = 8;
-const char archiveMagic[archiveMagicSize] = { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' };
-const char thinArchiveMagic[archiveMagicSize] = { '!', '<', 't', 'h', 'i', 'n', '>', '\n' };
-const char archiveFinalMagic[2] = { '`', '\n' };
+/// Archive Header, Magic number
+const char GNUArchiveReader::ArchiveMagic[ArchiveMagicSize] = { '!', '<', 'a', 'r', 'c', 'h', '>', '\n' };
+const char GNUArchiveReader::ThinArchiveMagic[ArchiveMagicSize] = { '!', '<', 't', 'h', 'i', 'n', '>', '\n' };
+const char GNUArchiveReader::HeaderFinalMagic[HeaderFinalMagicSize] = { '`', '\n' };
 
-struct GNUArchiveReader::ArchiveMemberHeader
-{
-  char name[16];
-  char date[12];
-  char uid[6];
-  char gid[6];
-  char mode[8];
-  char size[10];
-  char finalMagic[2];
-};
 
 struct GNUArchiveReader::SymbolTableEntry
 {
@@ -49,13 +42,6 @@
   std::string name;
 };
 
-inline void endian_swap(unsigned int& x)
-{
-  x = (x>>24) |
-      ((x<<8) & 0x00FF0000) |
-      ((x>>8) & 0x0000FF00) |
-      (x<<24);
-}
 
 
 /// convert string to size_t
@@ -73,22 +59,25 @@
 /// Public API
 bool GNUArchiveReader::isMyFormat(Input &pInput) const
 {
-  llvm::OwningPtr<llvm::MemoryBuffer> mapFile;
-  llvm::MemoryBuffer::getFile(pInput.path().c_str(), mapFile);
-  const char* pFile = mapFile->getBufferStart();
+  assert(pInput.hasMemArea());
+
+  MemoryRegion *region = pInput.memArea()->request(0, ArchiveMagicSize);
+  if (!region)
+    llvm::report_fatal_error("can't request MemoryRegion for archive magic");
+
+  const char *p_buffer = reinterpret_cast<char *> (region->getBuffer());
 
   /// check archive format.
-  if(mapFile->getBufferSize() <= archiveMagicSize)
+  if (memcmp(p_buffer, ArchiveMagic, ArchiveMagicSize) != 0
+      && memcmp(p_buffer, ThinArchiveMagic, ArchiveMagicSize) != 0) {
     return false;
-  bool isThinArchive = memcmp(pFile, thinArchiveMagic, archiveMagicSize) == 0;
-  if(!isThinArchive && memcmp(pFile, archiveMagic, archiveMagicSize) != 0)
-    return false;
+  }
   return true;
 }
 
 LDReader::Endian GNUArchiveReader::endian(Input& pFile) const
 {
-  return m_endian;
+  return LDReader::BigEndian;
 }
 
 InputTree *GNUArchiveReader::readArchive(Input &pInput)
@@ -103,62 +92,59 @@
 InputTree *GNUArchiveReader::setupNewArchive(Input &pInput,
                                             size_t off)
 {
-  llvm::OwningPtr<llvm::MemoryBuffer> mapFile;
-  if(llvm::MemoryBuffer::getFile(pInput.path().c_str(), mapFile))
-  {
-    assert(0 && "GNUArchiveReader:can't map a file to MemoryBuffer\n");
-    return NULL;
-  }
+  assert(pInput.hasMemArea());
+  MemoryRegion *region = pInput.memArea()->request(off, ArchiveMagicSize);
+
+  if (!region)
+    llvm::report_fatal_error("can't request MemoryRegion for archive magic");
+
+  const char *pFile = reinterpret_cast<char *> (region->getBuffer());
+
+  /// check archive format.
+  bool isThinArchive;
+  isThinArchive = memcmp(pFile, ThinArchiveMagic, ArchiveMagicSize) == 0;
+  if(!isThinArchive && memcmp(pFile, ArchiveMagic, ArchiveMagicSize) != 0)
+    llvm::report_fatal_error("Fail : archive magic number is not matched");
 
   InputTree *resultTree = new InputTree(m_pLDInfo.inputFactory());
   std::vector<SymbolTableEntry> symbolTable;
   std::string archiveMemberName;
   std::string extendedName;
-  bool isThinArchive;
-  const char *pFile = mapFile->getBufferStart();
 
-  /// check archive format.
-  if(mapFile->getBufferSize() <= archiveMagicSize)
-    return NULL;
-  else
-  {
-    isThinArchive = memcmp(pFile, thinArchiveMagic, archiveMagicSize) == 0;
-    if(!isThinArchive && memcmp(pFile, archiveMagic, archiveMagicSize) != 0)
-      return NULL;
-  }
-
-  off += archiveMagicSize ;
-  size_t symbolTableSize = parseMemberHeader(mapFile, off, &archiveMemberName,
+  off += ArchiveMagicSize ;
+  size_t symbolTableSize = readMemberHeader(*pInput.memArea(), off, &archiveMemberName,
                                             NULL, extendedName);
   /// read archive symbol table
   if(archiveMemberName.empty())
   {
-    readSymbolTable(mapFile, symbolTable,
-                    off+sizeof(GNUArchiveReader::ArchiveMemberHeader), symbolTableSize);
-    off = off + sizeof(GNUArchiveReader::ArchiveMemberHeader) + symbolTableSize;
+    readSymbolTable(*pInput.memArea(), symbolTable,
+                    off+sizeof(ArchiveMemberHeader), symbolTableSize);
+    off = off + sizeof(ArchiveMemberHeader) + symbolTableSize;
   }
   else
   {
-    assert(0 && "fatal error : need symbol table\n");
+    llvm::report_fatal_error("fatal error : need symbol table\n");
     return NULL;
   }
 
   if((off&1) != 0)
     ++off;
 
-  size_t extendedSize = parseMemberHeader(mapFile, off, &archiveMemberName,
+  size_t extendedSize = readMemberHeader(*pInput.memArea(), off, &archiveMemberName,
                                           NULL, extendedName);
   /// read long Name table if exist
   if(archiveMemberName == "/")
   {
-    off += sizeof(GNUArchiveReader::ArchiveMemberHeader);
-    pFile += off;
-    extendedName.assign(pFile,extendedSize);
+    off += sizeof(ArchiveMemberHeader);
+    MemoryRegion *extended_name_region = pInput.memArea()->request(off, extendedSize);
+    pFile = reinterpret_cast<char *>(extended_name_region->getBuffer());
+    extendedName.assign(pFile, extendedSize);
+
   }
 
   /// traverse all the archive members
   InputTree::iterator node = resultTree->root();
-  set<string> haveSeen;
+  std::set<std::string> haveSeen;
   for(unsigned i=0 ; i<symbolTable.size() ; ++i)
   {
     /// We shall get each member at this archive.
@@ -166,7 +152,7 @@
     /// the original InputTree, resultTree.
     off_t nestedOff = 0;
 
-    parseMemberHeader(mapFile, symbolTable[i].fileOffset, &archiveMemberName,
+    readMemberHeader(*pInput.memArea(), symbolTable[i].fileOffset, &archiveMemberName,
                       &nestedOff, extendedName);
 
     if(haveSeen.find(archiveMemberName)==haveSeen.end())
@@ -191,8 +177,13 @@
 
       continue;
     }
-
-    /// create the real path
+    
+    /// TODO:(Duo)
+    /// adjust the relative pathname
+    /// For example
+    /// thin archive pathname : "/usr/lib/thin.a"
+    ///           Member name : "member.a"
+    /// pathname after adjust : "/usr/lib/member.a"
     sys::fs::RealPath realPath(archiveMemberName);
     if(nestedOff > 0)
     {
@@ -237,20 +228,20 @@
 /// "filename.o/        " - regular file with short name
 /// "/5566              " - name at offset 5566 at long name table
 
-size_t GNUArchiveReader::parseMemberHeader(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile,
+size_t GNUArchiveReader::readMemberHeader(MemoryArea &pArea,
                                            off_t off,
                                            std::string *p_Name,
                                            off_t *p_NestedOff,
                                            std::string &p_ExtendedName)
 {
-  const char *pFile = mapFile->getBufferStart();
-  pFile += off;
+  MemoryRegion *region = pArea.request(off, sizeof(ArchiveMemberHeader));
+  const char *pFile = reinterpret_cast<char *>(region->getBuffer());
   const ArchiveMemberHeader *header = reinterpret_cast<const ArchiveMemberHeader *>(pFile);
 
   /// check magic number of member header
-  if(memcmp(header->finalMagic, archiveFinalMagic, sizeof archiveFinalMagic))
+  if(memcmp(header->finalMagic, HeaderFinalMagic, sizeof HeaderFinalMagic))
   {
-    assert(0 && "archive member header magic number false");
+    llvm::report_fatal_error("archive member header magic number false");
     return 0;
   }
 
@@ -259,7 +250,7 @@
   size_t memberSize = stringToType<size_t>(sizeString);
   if(memberSize == 0)
   {
-    assert(0 && "member Size Error");
+    llvm::report_fatal_error("member Size Error");
     return 0;
   }
 
@@ -270,7 +261,7 @@
     size_t nameLen = ((nameEnd == NULL) ? 0 : (nameEnd - header->name));
     if((nameLen <= 0) || (nameLen >= sizeof(header->name)))
     {
-      assert(0 && "header name format error\n");
+      llvm::report_fatal_error("header name format error\n");
       return 0;
     }
     p_Name->assign(header->name, nameLen);
@@ -302,7 +293,7 @@
        || extendedNameOff < 0
        || static_cast<size_t>(extendedNameOff) >= p_ExtendedName.size())
     {
-      assert(0 && "extended name");
+      llvm::report_fatal_error("extended name");
       return 0;
     }
 
@@ -311,7 +302,7 @@
     if(nameEnd[-1] != '/'
        || static_cast<size_t>(nameEnd-name) > p_ExtendedName.size())
     {
-      assert(0 && "p_ExtendedName substring is not end with / \n");
+      llvm::report_fatal_error("p_ExtendedName substring is not end with / \n");
       return 0;
     }
     p_Name->assign(name, nameEnd-name-1);
@@ -322,35 +313,40 @@
   return memberSize;
 }
 
-void GNUArchiveReader::readSymbolTable(llvm::OwningPtr<llvm::MemoryBuffer> &mapFile,
+void GNUArchiveReader::readSymbolTable(MemoryArea &pArea,
                                        std::vector<SymbolTableEntry> &pSymbolTable,
                                        off_t start,
                                        size_t size)
 {
-  const char *startPtr = mapFile->getBufferStart() + start;
-  const elfWord *p_Word = reinterpret_cast<const elfWord *>(startPtr);
+  MemoryRegion *region = pArea.request(start, size);
+  const char *pFile = reinterpret_cast<char *>(region->getBuffer());
+  const elfWord *p_Word = reinterpret_cast<const elfWord *>(pFile);
   unsigned int symbolNum = *p_Word;
 
   /// Portable Issue on Sparc platform
   /// Intel, ARM and Mips are littel-endian , Sparc is little-endian after verion 9
   /// symbolNum in symbol table is always big-endian
-  if(m_endian == LDReader::LittleEndian)
-    endian_swap(symbolNum);
+  if(llvm::sys::isLittleEndianHost())
+    symbolNum = bswap32(symbolNum);
   ++p_Word;
 
   const char *p_Name = reinterpret_cast<const char *>(p_Word + symbolNum);
 
-  pSymbolTable.resize(symbolNum);
   for(unsigned int i=0 ; i<symbolNum ; ++i)
   {
-    /// assign member offset
+    SymbolTableEntry entry;
+    /// member offset
     unsigned int memberOffset = *p_Word;
-    endian_swap(memberOffset);
-    pSymbolTable[i].fileOffset = static_cast<off_t>(memberOffset);
+    if(llvm::sys::isLittleEndianHost())
+      memberOffset = bswap32(memberOffset);
+    entry.fileOffset = static_cast<off_t>(memberOffset);
     ++p_Word;
-    /// assign member name
+    /// member name
     off_t nameEnd = strlen(p_Name) + 1;
-    pSymbolTable[i].name.assign(p_Name, nameEnd);
+    entry.name.assign(p_Name, nameEnd);
     p_Name += nameEnd;
+    /// the symbol is found in symbol pool
+    if (m_pLDInfo.getNamePool().findSymbol(entry.name))
+      pSymbolTable.push_back(entry);
   }
 }
diff --git a/lib/LD/InputSymbolTable.cpp b/lib/LD/InputSymbolTable.cpp
deleted file mode 100644
index e34679c..0000000
--- a/lib/LD/InputSymbolTable.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- InputSymbolTable.cpp -----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/InputSymbolTable.h"
-#include <vector>
-
-using namespace mcld;
-
-//==========================
-// InputSymbolTable
-
-InputSymbolTable::InputSymbolTable(StrSymPool &pStrSymPool,
-                                   size_t pNumOfSymbols,
-                                   StringTable &pEntireStringTable,
-                                   StringTable &pDynamicStringTable)
-  : SymbolTableIF(pStrSymPool)
-{
-  f_StrSymPool.addIndirectClient(*this);
-
-  f_pCategorySet->at(CategorySet::Entire).reserve(pNumOfSymbols);
-
-  f_pCategorySet->at(CategorySet::Entire).interpose(&pEntireStringTable);
-  f_pCategorySet->at(CategorySet::Dynamic).interpose(&pDynamicStringTable);
-}
-
-void InputSymbolTable::doInsertSymbol(LDSymbol *pSym)
-{
-  f_pCategorySet->insertSymbolPointer(pSym);
-}
-
-void InputSymbolTable::doMerge(const SymbolTableIF &pSymTab)
-{
-  if (this == &pSymTab)
-     return;
-  for (size_t i = 0; i < CategorySet::NumOfCategories; ++i)
-    f_pCategorySet->at(i).insert(f_pCategorySet->at(i).end(),
-                                 pSymTab.begin(i),
-                                 pSymTab.end(i));
-}
-
-InputSymbolTable::~InputSymbolTable()
-{
-}
diff --git a/lib/LD/Layout.cpp b/lib/LD/Layout.cpp
index 9328d74..bc91cee 100644
--- a/lib/LD/Layout.cpp
+++ b/lib/LD/Layout.cpp
@@ -8,14 +8,14 @@
 //===----------------------------------------------------------------------===//
 
 #include <llvm/ADT/Twine.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/ADT/SizeTraits.h>
 #include <mcld/LD/Layout.h>
+#include <mcld/LD/LDContext.h>
 #include <mcld/LD/LDFileFormat.h>
+#include <mcld/LD/LDSection.h>
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/LDContext.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Target/TargetLDBackend.h>
 #include <cassert>
 
@@ -132,16 +132,6 @@
   }
   else {
     range_list = m_SDRangeMap[&pSD];
-#ifdef MCLD_DEBUG
-    RangeList::iterator rangeIter, rangeEnd = range_list->end();
-    for (rangeIter = range_list->begin(); rangeIter != rangeEnd; ++rangeIter) {
-      if (&pInputHdr == rangeIter->header) {
-        llvm::report_fatal_error(llvm::Twine("Trying to map the same LDSection: ") +
-                                 pInputHdr.name() +
-                                 llvm::Twine(" into the different ranges.\n"));
-      }
-    }
-#endif
   }
 
   // make a range and push it into the range list
@@ -425,9 +415,7 @@
 
   // range not found
   if (range == rangeEnd) {
-    llvm::report_fatal_error(llvm::Twine("section ") +
-                             pInputSection.name() +
-                             llvm::Twine(" never be in the range list.\n"));
+    fatal(diag::err_section_not_laid_out) << pInputSection.name();
   }
 
   return getFragmentRef(*range, pOffset);
@@ -481,7 +469,7 @@
                              llvm::Twine(" never be in the range list.\n"));
   }
 
-  return getFragmentRef(*range, target_offset);
+  return getFragmentRef(*range, pBigOffset);
 }
 
 uint64_t Layout::getOutputOffset(const llvm::MCFragment& pFrag)
@@ -516,7 +504,8 @@
 }
 
 void Layout::sortSectionOrder(const Output& pOutput,
-                              const TargetLDBackend& pBackend)
+                              const TargetLDBackend& pBackend,
+                              const MCLDInfo& pInfo)
 {
   typedef std::pair<LDSection*, unsigned int> SectOrder;
   typedef std::vector<SectOrder > SectListTy;
@@ -525,7 +514,7 @@
   for (size_t index = 0; index < m_SectionOrder.size(); ++index)
     sect_list.push_back(std::make_pair(
                     m_SectionOrder[index],
-                    pBackend.getSectionOrder(pOutput, *m_SectionOrder[index])));
+                    pBackend.getSectionOrder(pOutput, *m_SectionOrder[index], pInfo)));
 
   // simple insertion sort should be fine for general cases such as so and exec
   for (unsigned int i = 1; i < sect_list.size(); ++i) {
@@ -545,7 +534,9 @@
   }
 }
 
-bool Layout::layout(Output& pOutput, const TargetLDBackend& pBackend)
+bool Layout::layout(Output& pOutput,
+                    const TargetLDBackend& pBackend,
+                    const MCLDInfo& pInfo)
 {
   // determine what sections in output context will go into final output, and
   // push the needed sections into m_SectionOrder for later processing
@@ -558,10 +549,12 @@
     switch (sect->kind()) {
       // ignore if there is no SectionData for certain section kinds
       case LDFileFormat::Regular:
-      case LDFileFormat::Note:
       case LDFileFormat::Target:
       case LDFileFormat::MetaData:
       case LDFileFormat::BSS:
+      case LDFileFormat::Debug:
+      case LDFileFormat::EhFrame:
+      case LDFileFormat::GCCExceptTable:
         if (0 != sect->size()) {
           if (NULL != sect->getSectionData() &&
               !sect->getSectionData()->getFragmentList().empty()) {
@@ -581,6 +574,8 @@
       // ignore if section size is 0
       case LDFileFormat::NamePool:
       case LDFileFormat::Relocation:
+      case LDFileFormat::Note:
+      case LDFileFormat::EhFrameHdr:
         if (0 != sect->size())
           m_SectionOrder.push_back(sect);
         break;
@@ -590,47 +585,22 @@
           ;
         }
         break;
-      case LDFileFormat::Debug:
-        if (0 != sect->size()) {
-          m_SectionOrder.push_back(sect);
-          llvm::errs() << "WARNING: DWRAF debugging has not been fully supported yet.\n"
-                       << "section `" << sect->name() << "'.\n";
-        }
-        break;
-      case LDFileFormat::Exception:
-        if (0 != sect->size()) {
-          llvm::errs() << "WARNING: Exception handling has not been fully supported yet.\n"
-                       << "section `" << sect->name() << "'.\n";
-          if (NULL != sect->getSectionData() &&
-              !sect->getSectionData()->getFragmentList().empty()) {
-            // make sure that all fragments are valid
-            llvm::MCFragment& frag =
-              sect->getSectionData()->getFragmentList().back();
-            setFragmentLayoutOrder(&frag);
-            setFragmentLayoutOffset(&frag);
-          }
-          m_SectionOrder.push_back(sect);
-        }
-        break;
       case LDFileFormat::Version:
         if (0 != sect->size()) {
           m_SectionOrder.push_back(sect);
-          llvm::errs() << "WARNING: Symbolic versioning has not been fully supported yet.\n"
-                       << "section `" << sect->name() << "'.\n";
+          warning(diag::warn_unsupported_symbolic_versioning) << sect->name();
         }
         break;
       default:
-        llvm::report_fatal_error(llvm::Twine("Unsupported section kind of `") +
-                                 sect->name() +
-                                 llvm::Twine("': ") +
-                                 llvm::Twine(sect->kind()) +
-                                 llvm::Twine(".\n"));
+        if (0 != sect->size()) {
+          error(diag::err_unsupported_section) << sect->name() << sect->kind();
+        }
         break;
     }
   }
 
   // perform sorting on m_SectionOrder to get a ordering for final layout
-  sortSectionOrder(pOutput, pBackend);
+  sortSectionOrder(pOutput, pBackend, pInfo);
 
   // Backend defines the section start offset for section 1.
   uint64_t offset = pBackend.sectionStartOffset();
diff --git a/lib/LD/MsgHandler.cpp b/lib/LD/MsgHandler.cpp
new file mode 100644
index 0000000..96310a2
--- /dev/null
+++ b/lib/LD/MsgHandler.cpp
@@ -0,0 +1,52 @@
+//===- MsgHandler.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/MsgHandler.h>
+#include <mcld/LD/DiagnosticEngine.h>
+
+using namespace mcld;
+
+MsgHandler::MsgHandler(DiagnosticEngine& pEngine)
+ : m_Engine(pEngine), m_NumArgs(0) {
+}
+
+MsgHandler::~MsgHandler()
+{
+  emit();
+}
+
+bool MsgHandler::emit()
+{
+  flushCounts();
+  return m_Engine.emit();
+}
+
+void MsgHandler::addString(llvm::StringRef pStr) const
+{
+  assert(m_NumArgs < DiagnosticEngine::MaxArguments &&
+         "Too many arguments to diagnostic!");
+  m_Engine.state().ArgumentKinds[m_NumArgs] = DiagnosticEngine::ak_std_string;
+  m_Engine.state().ArgumentStrs[m_NumArgs++] = pStr.data();
+}
+
+void MsgHandler::addString(const std::string& pStr) const
+{
+  assert(m_NumArgs < DiagnosticEngine::MaxArguments &&
+         "Too many arguments to diagnostic!");
+  m_Engine.state().ArgumentKinds[m_NumArgs] = DiagnosticEngine::ak_std_string;
+  m_Engine.state().ArgumentStrs[m_NumArgs++] = pStr;
+}
+
+void MsgHandler::addTaggedVal(intptr_t pValue, DiagnosticEngine::ArgumentKind pKind) const
+{
+  assert(m_NumArgs < DiagnosticEngine::MaxArguments &&
+         "Too many arguments to diagnostic!");
+  m_Engine.state().ArgumentKinds[m_NumArgs] = pKind;
+  m_Engine.state().ArgumentVals[m_NumArgs++] = pValue;
+}
+
diff --git a/lib/LD/StrSymPool.cpp b/lib/LD/NamePool.cpp
similarity index 69%
rename from lib/LD/StrSymPool.cpp
rename to lib/LD/NamePool.cpp
index abe3fb7..1247057 100644
--- a/lib/LD/StrSymPool.cpp
+++ b/lib/LD/NamePool.cpp
@@ -1,4 +1,4 @@
-//===- StrSymPool.cpp -----------------------------------------------------===//
+//===- NamePool.cpp -------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,27 +6,24 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
-#include "mcld/LD/StrSymPool.h"
-#include "mcld/LD/Resolver.h"
 #include <llvm/Support/raw_ostream.h>
+#include <mcld/LD/NamePool.h>
+#include <mcld/LD/Resolver.h>
 
 using namespace mcld;
 
 //==========================
-// StrSymPool
-StrSymPool::StrSymPool(const Resolver& pResolver, StrSymPool::size_type pSize)
-  : m_pResolver(pResolver.clone()), m_Table(pSize) {
+// NamePool
+NamePool::NamePool(const Resolver& pResolver, NamePool::size_type pSize)
+  : m_pResolver(&pResolver), m_Table(pSize) {
 }
 
-StrSymPool::~StrSymPool()
+NamePool::~NamePool()
 {
-  if (0 != m_pResolver)
-    delete m_pResolver;
 }
 
 /// createSymbol - create a symbol
-ResolveInfo* StrSymPool::createSymbol(const llvm::StringRef& pName,
+ResolveInfo* NamePool::createSymbol(const llvm::StringRef& pName,
                                       bool pIsDyn,
                                       ResolveInfo::Type pType,
                                       ResolveInfo::Desc pDesc,
@@ -48,7 +45,7 @@
 /// insertSymbol - insert a symbol and resolve it immediately
 /// @return the pointer of resolved ResolveInfo
 /// @return is the symbol existent?
-void StrSymPool::insertSymbol(const llvm::StringRef& pName,
+void NamePool::insertSymbol(const llvm::StringRef& pName,
                               bool pIsDyn,
                               ResolveInfo::Type pType,
                               ResolveInfo::Desc pDesc,
@@ -98,69 +95,49 @@
   // symbol resolution
   bool override = false;
   unsigned int action = Resolver::LastAction;
-  switch(m_pResolver->resolve(*old_symbol, *new_symbol, override)) {
-    case Resolver::Success: {
-      pResult.info      = old_symbol;
-      pResult.existent  = true;
-      pResult.overriden = override;
-      break;
-    }
-    case Resolver::Warning: {
-      llvm::errs() << "WARNING: " << m_pResolver->mesg() << "\n";
-      m_pResolver->clearMesg();
-      pResult.info      = old_symbol;
-      pResult.existent  = true;
-      pResult.overriden = override;
-      break;
-    }
-    case Resolver::Abort: {
-      llvm::report_fatal_error(m_pResolver->mesg());
-      pResult.info      = old_symbol;
-      pResult.existent  = true;
-      pResult.overriden = override;
-      break;
-    }
-    default: {
-      m_pResolver->resolveAgain(*this, action, *old_symbol, *new_symbol, pResult);
-      break;
-    }
+  if (m_pResolver->resolve(*old_symbol, *new_symbol, override)) {
+    pResult.info      = old_symbol;
+    pResult.existent  = true;
+    pResult.overriden = override;
   }
+  else
+      m_pResolver->resolveAgain(*this, action, *old_symbol, *new_symbol, pResult);
   return;
 }
 
-llvm::StringRef StrSymPool::insertString(const llvm::StringRef& pString)
+llvm::StringRef NamePool::insertString(const llvm::StringRef& pString)
 {
   bool exist = false;
   ResolveInfo* resolve_info = m_Table.insert(pString, exist);
   return llvm::StringRef(resolve_info->name(), resolve_info->nameSize());
 }
 
-void StrSymPool::reserve(StrSymPool::size_type pSize)
+void NamePool::reserve(NamePool::size_type pSize)
 {
   m_Table.rehash(pSize);
 }
 
-StrSymPool::size_type StrSymPool::capacity() const
+NamePool::size_type NamePool::capacity() const
 {
   return (m_Table.numOfBuckets() - m_Table.numOfEntries());
 }
 
 /// findInfo - find the resolved ResolveInfo
-ResolveInfo* StrSymPool::findInfo(const llvm::StringRef& pName)
+ResolveInfo* NamePool::findInfo(const llvm::StringRef& pName)
 {
   Table::iterator iter = m_Table.find(pName);
   return iter.getEntry();
 }
 
 /// findInfo - find the resolved ResolveInfo
-const ResolveInfo* StrSymPool::findInfo(const llvm::StringRef& pName) const
+const ResolveInfo* NamePool::findInfo(const llvm::StringRef& pName) const
 {
   Table::const_iterator iter = m_Table.find(pName);
   return iter.getEntry();
 }
 
 /// findSymbol - find the resolved output LDSymbol
-LDSymbol* StrSymPool::findSymbol(const llvm::StringRef& pName)
+LDSymbol* NamePool::findSymbol(const llvm::StringRef& pName)
 {
   ResolveInfo* info = findInfo(pName);
   if (NULL == info)
@@ -169,7 +146,7 @@
 }
 
 /// findSymbol - find the resolved output LDSymbol
-const LDSymbol* StrSymPool::findSymbol(const llvm::StringRef& pName) const
+const LDSymbol* NamePool::findSymbol(const llvm::StringRef& pName) const
 {
   const ResolveInfo* info = findInfo(pName);
   if (NULL == info)
diff --git a/lib/LD/OutputSymbolTable.cpp b/lib/LD/OutputSymbolTable.cpp
deleted file mode 100644
index a17a211..0000000
--- a/lib/LD/OutputSymbolTable.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- OutputSymbolTable.cpp ----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/OutputSymbolTable.h"
-
-using namespace mcld;
-
-//==========================
-// OutputSymbolTable
-
-
-OutputSymbolTable::OutputSymbolTable(StrSymPool &pStrSymPool,
-                                     size_t pNumOfSymbols,
-                                     StringTable &pEntireStringTable,
-                                     StringTable &pDynamicStringTable)
-  : SymbolTableIF(pStrSymPool)
-{
-  f_StrSymPool.addDirectClient(*this);
-
-  f_pCategorySet->at(CategorySet::Entire).reserve(pNumOfSymbols);
-
-  f_pCategorySet->at(CategorySet::Entire).interpose(&pEntireStringTable);
-  f_pCategorySet->at(CategorySet::Dynamic).interpose(&pDynamicStringTable);
-}
-
-void OutputSymbolTable::doInsertSymbol(LDSymbol *sym)
-{
-  // OutputSymbolTable didn't have any real containers,
-  // so no need to do anything.
-}
-
-void OutputSymbolTable::doMerge(const SymbolTableIF &pSymTab)
-{
-  // OutputSymbolTable didn't have any real containers,
-  // so no need to do anything.
-}
diff --git a/lib/LD/Relocation.cpp b/lib/LD/Relocation.cpp
index 73db39b..0b84ad0 100644
--- a/lib/LD/Relocation.cpp
+++ b/lib/LD/Relocation.cpp
@@ -40,7 +40,7 @@
 
 Relocation::Address Relocation::symValue() const
 {
-  if(m_pSymInfo->type() == ResolveInfo::Section &&
+  if (m_pSymInfo->type() == ResolveInfo::Section &&
      m_pSymInfo->outSymbol()->hasFragRef()) {
     return llvm::cast<LDSection>(
       m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection()).addr();
diff --git a/lib/LD/Resolver.cpp b/lib/LD/Resolver.cpp
index 0f7f06e..aa39b13 100644
--- a/lib/LD/Resolver.cpp
+++ b/lib/LD/Resolver.cpp
@@ -6,28 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/LD/Resolver.h"
-#include <cassert>
+#include <mcld/LD/Resolver.h>
 
 using namespace mcld;
 
 //==========================
 // Resolver
-Resolver::Resolver()
-  : m_Mesg() {
-}
-
-Resolver::Resolver(const Resolver& pCopy)
-  : m_Mesg(pCopy.m_Mesg) {
-}
-
 Resolver::~Resolver()
 {
-  m_Mesg.clear();
-}
-
-void Resolver::clearMesg()
-{
-  m_Mesg.clear();
 }
 
diff --git a/lib/LD/SectionMap.cpp b/lib/LD/SectionMap.cpp
index d81dfdd..9d32391 100644
--- a/lib/LD/SectionMap.cpp
+++ b/lib/LD/SectionMap.cpp
@@ -12,9 +12,8 @@
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // SectionMap
-
 SectionMap::SectionMap()
 {
 }
@@ -38,13 +37,11 @@
   // if still no matching, just let a output seciton has the same input name
   if (it == end())
     return pInput;
-  
   return (*it).outputStr;
 }
 
 bool SectionMap::push_back(const std::string& pInput,
-                           const std::string& pOutput,
-                           const uint64_t pOffset)
+                           const std::string& pOutput)
 {
   // Now only check if the mapping exists in the map already
   // TODO: handle the cases such as overriding the exist mapping and drawing
@@ -57,7 +54,6 @@
   struct Mapping mapping = {
     pInput,
     pOutput,
-    pOffset,
   };
   m_SectMap.push_back(mapping);
   return true;
diff --git a/lib/LD/SectionMerger.cpp b/lib/LD/SectionMerger.cpp
index f6aef9e..f3a5b65 100644
--- a/lib/LD/SectionMerger.cpp
+++ b/lib/LD/SectionMerger.cpp
@@ -18,7 +18,7 @@
 SectionMerger::SectionMerger(SectionMap& pSectionMap, LDContext& pContext)
 : m_SectionNameMap(pSectionMap),
   m_Output(pContext),
-  m_LDSectionMap(pSectionMap.size())
+  m_LDSectionMap()
 {
 }
 
diff --git a/lib/LD/StaticResolver.cpp b/lib/LD/StaticResolver.cpp
index 3ba49e2..09cbc11 100644
--- a/lib/LD/StaticResolver.cpp
+++ b/lib/LD/StaticResolver.cpp
@@ -8,28 +8,19 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/StaticResolver.h>
 #include <mcld/LD/LDSymbol.h>
-#include <cassert>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
-
 //==========================
 // StaticResolver
-StaticResolver::StaticResolver()
-{
-}
-
 StaticResolver::~StaticResolver()
 {
 }
 
-StaticResolver::StaticResolver(const StaticResolver& pCopy)
-  : Resolver(pCopy) {
-}
-
-unsigned int StaticResolver::resolve(ResolveInfo& __restrict__ pOld,
-                                     const ResolveInfo& __restrict__ pNew,
-                                     bool &pOverride)
+bool StaticResolver::resolve(ResolveInfo& __restrict__ pOld,
+                             const ResolveInfo& __restrict__ pNew,
+                             bool &pOverride) const
 {
 
   /* The state table itself.
@@ -41,13 +32,13 @@
   static const enum LinkAction link_action[LAST_ORD][LAST_ORD] =
   {
     /* new\old  U       w_U     d_U    wd_U   D      w_D    d_D    wd_D   C      w_C,   Cs,    Is   */
-    /* U    */ {NOACT,  UND,    UND,   UND,   NOACT, NOACT, DUND,  DUNDW, NOACT, NOACT, NOACT, REFC },
-    /* w_U  */ {NOACT,  NOACT,  NOACT, WEAK,  NOACT, NOACT, DUND,  DUNDW, NOACT, NOACT, NOACT, REFC },
+    /* U    */ {NOACT,  UND,    UND,   UND,   NOACT, NOACT, DUND,  DUND,  NOACT, NOACT, NOACT, REFC },
+    /* w_U  */ {NOACT,  NOACT,  NOACT, WEAK,  NOACT, NOACT, DUNDW, DUNDW, NOACT, NOACT, NOACT, REFC },
     /* d_U  */ {NOACT,  NOACT,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
     /* wd_U */ {NOACT,  NOACT,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
     /* D    */ {DEF,    DEF,    DEF,   DEF,   MDEF,  DEF,   DEF,   DEF,   CDEF,  CDEF,  CDEF,  MDEF },
     /* w_D  */ {DEFW,   DEFW,   DEFW,  DEFW,  NOACT, NOACT, DEFW,  DEFW,  NOACT, NOACT, NOACT, NOACT},
-    /* d_D  */ {DEFD,   MDEFD,  DEFD,  DEFD,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF },
+    /* d_D  */ {MDEFD,  MDEFD,  DEFD,  DEFD,  NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, MDEF },
     /* wd_D */ {MDEFWD, MDEFWD, DEFWD, DEFWD, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT},
     /* C    */ {COM,    COM,    COM,   COM,   CREF,  COM,   COM,   COM,   MBIG,  COM,   BIG,   REFC },
     /* w_C  */ {COM,    COM,    COM,   COM,   NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, NOACT, REFC },
@@ -71,26 +62,23 @@
   unsigned int col = getOrdinate(pOld);
 
   bool cycle = false;
-  unsigned int result = Resolver::Success;
   pOverride = false;
   ResolveInfo* old = &pOld;
   LinkAction action;
   do {
-    result = Resolver::Success;
     cycle = false;
     action = link_action[row][col];
 
     switch(action) {
       case FAIL: {       /* abort.  */
-        m_Mesg = std::string("internal error [StaticResolver.cpp:loc 86].\n") +
-                 std::string("Please report to `[email protected]'.\n");
-        result = Resolver::Abort;
-        break;
+        fatal(diag::fail_sym_resolution)
+                << __FILE__ << __LINE__
+                << "[email protected]";
+        return false;
       }
       case NOACT: {      /* no action.  */
         pOverride = false;
         old->overrideVisibility(pNew);
-        result = Resolver::Success;
         break;
       }
       case UND:          /* override by symbol undefined symbol.  */
@@ -102,7 +90,6 @@
       case COM: {        /* override by symbol common defined.  */
         pOverride = true;
         old->override(pNew);
-        result = Resolver::Success;
         break;
       }
       case MDEFD:        /* mark symbol dynamic defined.  */
@@ -110,31 +97,22 @@
         uint32_t binding = old->binding();
         old->override(pNew);
         old->setBinding(binding);
-        m_Mesg = std::string("symbol `") +
-                 old->name() +
-                 std::string("' uses the type, dynamic, size and type in the dynamic symbol.");
+        ignore(diag::mark_dynamic_defined) << old->name();
         pOverride = true;
-        result = Resolver::Warning;
         break;
       }
       case DUND:
       case DUNDW: {
-        if (old->binding() == ResolveInfo::Weak &&
-            pNew.binding() != ResolveInfo::Weak) {
-          old->setBinding(pNew.binding());
-        }
+        old->override(pNew);
         old->overrideVisibility(pNew);
+        old->setDynamic();
         pOverride = false;
-        result = Resolver::Success;
         break;
       }
       case CREF: {       /* Possibly warn about common reference to defined symbol.  */
         // A common symbol does not override a definition.
-        m_Mesg = std::string("common '") +
-                 pNew.name() +
-                 std::string("' overriden by previous definition.");
+        ignore(diag::comm_refer_to_define) << old->name();
         pOverride = false;
-        result = Resolver::Warning;
         break;
       }
       case CDEF: {       /* redefine existing common symbol.  */
@@ -142,12 +120,9 @@
         // definition overrides.
         //
 	// NOTE: m_Mesg uses 'name' instead of `name' for being compatible to GNU ld.
-        m_Mesg = std::string("definition of '") +
-                 old->name() +
-                 std::string("' is overriding common.");
+        ignore(diag::redefine_common) << old->name();
         old->override(pNew);
         pOverride = true;
-        result = Resolver::Warning;
         break;
       }
       case BIG: {        /* override by symbol common using largest size.  */
@@ -156,7 +131,6 @@
         old->overrideAttributes(pNew);
         old->overrideVisibility(pNew);
         pOverride = true;
-        result = Resolver::Success;
         break;
       }
       case MBIG: {       /* mark common symbol by larger size. */
@@ -164,22 +138,15 @@
           old->setSize(pNew.size());
         old->overrideVisibility(pNew);
         pOverride = false;
-        result = Resolver::Success;
         break;
       }
       case CIND: {       /* mark indirect symbol from existing common symbol.  */
-         m_Mesg = std::string("indirect symbol `") +
-                  pNew.name()+
-                  std::string("' point to a common symbol.\n");
-         result = Resolver::Warning;
+         ignore(diag::indirect_refer_to_common) << old->name();
       }
       /* Fall through */
       case IND: {        /* override by indirect symbol.  */
-        if (0 == pNew.link()) {
-          m_Mesg = std::string("indirect symbol `") +
-                   pNew.name() +
-                   std::string("' point to a inexistent symbol.");
-          result = Resolver::Abort;
+        if (NULL == pNew.link()) {
+          fatal(diag::indirect_refer_to_inexist) << pNew.name();
           break;
         }
 
@@ -203,18 +170,12 @@
       }
       /* Fall through */
       case MDEF: {       /* multiple definition error.  */
-        m_Mesg = std::string("multiple definitions of `") +
-                 pNew.name() +
-                 std::string("'.");
-        result = Resolver::Abort;
+        error(diag::multiple_definitions) << pNew.name();
         break;
       }
       case REFC: {       /* Mark indirect symbol referenced and then CYCLE.  */
-        if (0 == old->link()) {
-          m_Mesg = std::string("indirect symbol `") +
-                   old->name() +
-                   std::string("' point to a inexistent symbol.");
-          result = Resolver::Abort;
+        if (NULL == old->link()) {
+          fatal(diag::indirect_refer_to_inexist) << old->name();
           break;
         }
 
@@ -223,8 +184,12 @@
         cycle = true;
         break;
       }
+      default: {
+        error(diag::undefined_situation) << action << old->name() << pNew.name();
+        return false;
+      }
     } // end of the big switch (action)
   } while(cycle);
-  return result;
+  return true;
 }
 
diff --git a/lib/LD/SymbolTableFactory.cpp b/lib/LD/SymbolTableFactory.cpp
deleted file mode 100644
index 180a4a9..0000000
--- a/lib/LD/SymbolTableFactory.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- SymbolTableFactory.cpp ---------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/SymbolTableFactory.h"
-
-using namespace mcld;
-
-//==========================
-// SymbolTableFactory
-
-SymbolTableFactory::SymbolTableFactory(size_t pNumOfSymbolTables,
-                                       StrSymPool& pStrSymPool)
-  : m_StrSymPool(pStrSymPool),
-    m_InputFactory(pNumOfSymbolTables),
-    m_OutputFactory(pNumOfSymbolTables)
-{
-}
-
-SymbolTableFactory::~SymbolTableFactory()
-{
-}
-
-SymbolTableIF *SymbolTableFactory::
-createInputTable(StringTable &pEntireStringTable,
-                 StringTable &pDynamicStringTable,
-                 size_t pReserve)
-{
-  InputSymbolTable *inputSymTab = m_InputFactory.allocate();
-  new (inputSymTab) InputSymbolTable(m_StrSymPool,
-                                     pReserve,
-                                     pEntireStringTable,
-                                     pDynamicStringTable);
-  return inputSymTab;
-}
-
-SymbolTableIF *SymbolTableFactory::
-createOutputTable(StringTable &pEntireStringTable,
-                  StringTable &pDynamicStringTable,
-                  size_t pReserve)
-{
-  OutputSymbolTable *outputSymTab = m_OutputFactory.allocate();
-  new (outputSymTab) OutputSymbolTable(m_StrSymPool,
-                                       pReserve,
-                                       pEntireStringTable,
-                                       pDynamicStringTable);
-  return outputSymTab;
-}
diff --git a/lib/LD/TextDiagnosticPrinter.cpp b/lib/LD/TextDiagnosticPrinter.cpp
new file mode 100644
index 0000000..466d16d
--- /dev/null
+++ b/lib/LD/TextDiagnosticPrinter.cpp
@@ -0,0 +1,167 @@
+//===- TextDiagnosticPrinter.cpp ------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/TextDiagnosticPrinter.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <llvm/Support/Signals.h>
+#include <string>
+
+using namespace mcld;
+
+static const enum llvm::raw_ostream::Colors UnreachableColor = llvm::raw_ostream::RED;
+static const enum llvm::raw_ostream::Colors FatalColor       = llvm::raw_ostream::YELLOW;
+static const enum llvm::raw_ostream::Colors ErrorColor       = llvm::raw_ostream::RED;
+static const enum llvm::raw_ostream::Colors WarningColor     = llvm::raw_ostream::MAGENTA;
+static const enum llvm::raw_ostream::Colors DebugColor       = llvm::raw_ostream::CYAN;
+static const enum llvm::raw_ostream::Colors NoteColor        = llvm::raw_ostream::GREEN;
+static const enum llvm::raw_ostream::Colors IgnoreColor      = llvm::raw_ostream::BLUE;
+
+// Used for changing only the bold attribute.
+static const enum llvm::raw_ostream::Colors SavedColor = llvm::raw_ostream::SAVEDCOLOR;
+
+//===----------------------------------------------------------------------===//
+// TextDiagnosticPrinter
+TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream& pOStream,
+                                             const MCLDInfo& pLDInfo)
+  : m_OStream(pOStream), m_LDInfo(pLDInfo), m_pInput(NULL) {
+}
+
+TextDiagnosticPrinter::~TextDiagnosticPrinter()
+{
+}
+
+/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
+/// capturing it to a log as needed.
+void
+TextDiagnosticPrinter::handleDiagnostic(DiagnosticEngine::Severity pSeverity,
+                                        const Diagnostic& pInfo)
+{
+  DiagnosticPrinter::handleDiagnostic(pSeverity, pInfo);
+
+  std::string out_string;
+  pInfo.format(out_string);
+
+  switch (pSeverity) {
+    case DiagnosticEngine::Unreachable: {
+      m_OStream.changeColor(UnreachableColor, true);
+      m_OStream << "Unreachable: ";
+      m_OStream.resetColor();
+      m_OStream << out_string << "\n";
+      break;
+    }
+    case DiagnosticEngine::Fatal: {
+      m_OStream.changeColor(FatalColor, true);
+      m_OStream << "Fatal: ";
+      m_OStream.resetColor();
+      m_OStream << out_string << "\n";
+      break;
+    }
+    case DiagnosticEngine::Error: {
+      m_OStream.changeColor(ErrorColor, true);
+      m_OStream << "Error: ";
+      m_OStream.resetColor();
+      m_OStream << out_string << "\n";
+      break;
+    }
+    case DiagnosticEngine::Warning: {
+      m_OStream.changeColor(WarningColor, true);
+      m_OStream << "Warning: ";
+      m_OStream.resetColor();
+      m_OStream << out_string << "\n";
+      break;
+    }
+    case DiagnosticEngine::Debug: {
+      // show debug message only if verbose >= 0
+      if (0 <= m_LDInfo.options().verbose()) {
+        m_OStream.changeColor(DebugColor, true);
+        m_OStream << "Debug: ";
+        m_OStream.resetColor();
+        m_OStream << out_string << "\n";
+      }
+      break;
+    }
+    case DiagnosticEngine::Note: {
+      // show ignored message only if verbose >= 1
+      if (1 <= m_LDInfo.options().verbose()) {
+        m_OStream.changeColor(NoteColor, true);
+        m_OStream << "Note: ";
+        m_OStream.resetColor();
+        m_OStream << out_string << "\n";
+      }
+      break;
+    }
+    case DiagnosticEngine::Ignore: {
+      // show ignored message only if verbose >= 2
+      if (2 <= m_LDInfo.options().verbose()) {
+        m_OStream.changeColor(IgnoreColor, true);
+        m_OStream << "Ignore: ";
+        m_OStream.resetColor();
+        m_OStream << out_string << "\n";
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  switch (pSeverity) {
+    case DiagnosticEngine::Unreachable: {
+      m_OStream << "\n\n";
+      m_OStream.changeColor(llvm::raw_ostream::YELLOW);
+      m_OStream << "You encounter a bug of MCLinker, please report to:\n"
+                << "  [email protected]\n";
+      m_OStream.resetColor();
+    }
+    /** fall through **/
+    case DiagnosticEngine::Fatal: {
+      // If we reached here, we are failing ungracefully. Run the interrupt handlers
+      // to make sure any special cleanups get done, in particular that we remove
+      // files registered with RemoveFileOnSignal.
+      llvm::sys::RunInterruptHandlers();
+      exit(1);
+      break;
+    }
+    case DiagnosticEngine::Error: {
+      int16_t error_limit = m_LDInfo.options().maxErrorNum();
+      if ((error_limit != -1) &&
+          (getNumErrors() > static_cast<unsigned>(error_limit))) {
+        m_OStream << "\n\n";
+        m_OStream.changeColor(llvm::raw_ostream::YELLOW);
+        m_OStream << "too many error messages (>" << error_limit << ")...\n";
+        m_OStream.resetColor();
+        llvm::sys::RunInterruptHandlers();
+        exit(1);
+      }
+      break;
+    }
+    case DiagnosticEngine::Warning: {
+      int16_t warning_limit = m_LDInfo.options().maxWarnNum();
+      if ((warning_limit != -1) &&
+          (getNumWarnings() > static_cast<unsigned>(warning_limit))) {
+        m_OStream << "\n\n";
+        m_OStream.changeColor(llvm::raw_ostream::YELLOW);
+        m_OStream << "too many warning messages (>" << warning_limit << ")...\n";
+        m_OStream.resetColor();
+        llvm::sys::RunInterruptHandlers();
+        exit(1);
+      }
+    }
+    default:
+      break;
+  }
+}
+
+void TextDiagnosticPrinter::beginInput(const Input& pInput, const MCLDInfo& pLDInfo)
+{
+  m_pInput = &pInput;
+}
+
+void TextDiagnosticPrinter::endInput()
+{
+  m_pInput = NULL;
+}
diff --git a/lib/MC/ContextFactory.cpp b/lib/MC/ContextFactory.cpp
index d32ea8b..5b698c7 100644
--- a/lib/MC/ContextFactory.cpp
+++ b/lib/MC/ContextFactory.cpp
@@ -33,3 +33,10 @@
   return result;
 }
 
+LDContext* ContextFactory::produce()
+{
+  LDContext* result = allocate();
+  new (result) LDContext();
+  return result;
+}
+
diff --git a/lib/MC/MCLDInputTree.cpp b/lib/MC/InputTree.cpp
similarity index 70%
rename from lib/MC/MCLDInputTree.cpp
rename to lib/MC/InputTree.cpp
index b423988..a1d1449 100644
--- a/lib/MC/MCLDInputTree.cpp
+++ b/lib/MC/InputTree.cpp
@@ -1,4 +1,4 @@
-//===- MCLDInputTree.cpp --------------------------------------------------===//
+//===- InputTree.cpp ------------------------------------------------------===//
 //
 //                     The MCLinker Project
 //
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInputTree.h"
-#include "mcld/MC/InputFactory.h"
+#include <mcld/MC/InputTree.h>
+#include <mcld/MC/InputFactory.h>
 
 using namespace mcld;
 
@@ -24,15 +24,15 @@
 {
 }
 
-InputTree& InputTree::merge(InputTree::iterator pPosition, 
-                            const InputTree::Connector& pConnector,
+InputTree& InputTree::merge(InputTree::iterator pRoot, 
+                            const InputTree::Mover& pMover,
                             InputTree& pTree)
 {
   if (this == &pTree)
     return *this;
 
   if (!pTree.empty()) {
-    pConnector.connect(pPosition, iterator(pTree.m_Root.node.right));
+    pMover.connect(pRoot, iterator(pTree.m_Root.node.right));
     BinaryTreeBase<Input>::m_Root.summon(
         pTree.BinaryTreeBase<Input>::m_Root);
     BinaryTreeBase<Input>::m_Root.delegate(pTree.m_Root);
@@ -41,33 +41,33 @@
   return *this;
 }
 
-InputTree& InputTree::insert(InputTree::iterator pPosition,
-                             const InputTree::Connector& pConnector,
+InputTree& InputTree::insert(InputTree::iterator pRoot,
+                             const InputTree::Mover& pMover,
                              const std::string& pNamespec,
                              const sys::fs::Path& pPath,
                              unsigned int pType)
 {
   BinaryTree<Input>::node_type* node = createNode();
   node->data = m_FileFactory.produce(pNamespec, pPath, pType);
-  pConnector.connect(pPosition, iterator(node));
+  pMover.connect(pRoot, iterator(node));
   return *this;
 }
 
-InputTree& InputTree::enterGroup(InputTree::iterator pPosition,
-                                 const InputTree::Connector& pConnector)
+InputTree& InputTree::enterGroup(InputTree::iterator pRoot,
+                                 const InputTree::Mover& pMover)
 {
   NodeBase* node = createNode();
-  pConnector.connect(pPosition, iterator(node));
+  pMover.connect(pRoot, iterator(node));
   return *this;
 }
 
-InputTree& InputTree::insert(InputTree::iterator pPosition,
-                             const InputTree::Connector& pConnector,
+InputTree& InputTree::insert(InputTree::iterator pRoot,
+                             const InputTree::Mover& pMover,
                              const mcld::Input& pInput)
 {
   BinaryTree<Input>::node_type* node = createNode();
   node->data = const_cast<mcld::Input*>(&pInput);
-  pConnector.connect(pPosition, iterator(node));
+  pMover.connect(pRoot, iterator(node));
   return *this;
 }
 
diff --git a/lib/MC/MCLDAttribute.cpp b/lib/MC/MCLDAttribute.cpp
index a361691..f7b7e47 100644
--- a/lib/MC/MCLDAttribute.cpp
+++ b/lib/MC/MCLDAttribute.cpp
@@ -6,40 +6,40 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDAttribute.h"
-#include "mcld/MC/AttributeFactory.h"
+#include <mcld/MC/MCLDAttribute.h>
+#include <mcld/MC/AttributeFactory.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
 //==========================
 // AttrConstraint
-bool AttrConstraint::isLegal(const Attribute& pAttr, std::string &pErrMesg) const
+bool AttrConstraint::isLegal(const Attribute& pAttr) const
 {
   if (!isWholeArchive() && pAttr.isWholeArchive()) {
-    pErrMesg = std::string("Target does not support --whole-archive");
+    error(diag::err_unsupported_whole_archive);
     return false;
   }
   if (!isAsNeeded() && pAttr.isAsNeeded()) {
-    pErrMesg = std::string("Target does not support --as-needed");
+    error(diag::err_unsupported_as_needed);
     return false;
   }
   if (!isAddNeeded() && pAttr.isAddNeeded()) {
-    pErrMesg = std::string("Target does not support --add-needed");
+    error(diag::err_unsupported_add_needed);
     return false;
   }
   if (isStaticSystem() && pAttr.isDynamic()) {
-    pErrMesg = std::string("Target does not support --Bdynamic");
+    error(diag::err_unsupported_Bdynamic);
     return false;
   }
-  // FIXME: may be it's legal, but ignored by GNU ld.
   if (isStaticSystem() && pAttr.isAsNeeded()) {
-    pErrMesg = std::string("Can't enable --as-needed on a target which does not support dynamic linking");
-    return false;
+    warning(diag::err_enable_as_needed_on_static_system);
+    return true;
   }
   // FIXME: may be it's legal, but ignored by GNU ld.
   if (pAttr.isAsNeeded() && pAttr.isStatic()) {
-    pErrMesg = std::string("Can't mix --static with --as-needed");
-    return false;
+    warning(diag::err_mix_static_as_needed);
+    return true;
   }
   return true;
 }
diff --git a/lib/MC/MCLDDriver.cpp b/lib/MC/MCLDDriver.cpp
index 5e89097..a86983d 100644
--- a/lib/MC/MCLDDriver.cpp
+++ b/lib/MC/MCLDDriver.cpp
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/MC/InputTree.h>
 #include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCLDInputTree.h>
 #include <mcld/MC/MCLDDriver.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/LD/ArchiveReader.h>
@@ -15,10 +15,12 @@
 #include <mcld/LD/DynObjReader.h>
 #include <mcld/LD/ObjectWriter.h>
 #include <mcld/LD/DynObjWriter.h>
+#include <mcld/LD/ExecWriter.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/Support/RealPath.h>
+#include <mcld/Support/MemoryAreaFactory.h>
 #include <mcld/Target/TargetLDBackend.h>
-#include <llvm/Support/ErrorHandling.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace llvm;
 using namespace mcld;
@@ -26,91 +28,83 @@
 MCLDDriver::MCLDDriver(MCLDInfo& pLDInfo, TargetLDBackend& pLDBackend)
   : m_LDInfo(pLDInfo),
     m_LDBackend(pLDBackend),
-    m_pLinker(0) {
+    m_pLinker(NULL) {
+
 }
 
 MCLDDriver::~MCLDDriver()
 {
-  if (0 != m_pLinker)
+  if (NULL != m_pLinker)
     delete m_pLinker;
+
 }
 
-void MCLDDriver::normalize() {
-
+void MCLDDriver::normalize()
+{
+  // -----  set up inputs  ----- //
   InputTree::dfs_iterator input, inEnd = m_LDInfo.inputs().dfs_end();
   for (input = m_LDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
-    // already got type - for example, bitcode
+    // already got type - for example, bitcode or external OIR (object
+    // intermediate representation)
     if ((*input)->type() == Input::Script ||
         (*input)->type() == Input::Object ||
         (*input)->type() == Input::DynObj  ||
-        (*input)->type() == Input::Archive)
+        (*input)->type() == Input::Archive ||
+        (*input)->type() == Input::External)
       continue;
 
-
-    MemoryArea *input_memory =
-        m_LDInfo.memAreaFactory().produce((*input)->path(), O_RDONLY);
-    if ((input_memory != NULL) && input_memory->isGood()) {
-      (*input)->setMemArea(input_memory);
-    }
-    else {
-      llvm::report_fatal_error("can not open file: " + (*input)->path().native());
-      return;
-    }
-
     // is a relocatable object file
     if (m_LDBackend.getObjectReader()->isMyFormat(**input)) {
       (*input)->setType(Input::Object);
-      (*input)->setContext(m_LDInfo.contextFactory().produce((*input)->path()));
       m_LDBackend.getObjectReader()->readObject(**input);
     }
     // is a shared object file
     else if (m_LDBackend.getDynObjReader()->isMyFormat(**input)) {
       (*input)->setType(Input::DynObj);
-      (*input)->setContext(m_LDInfo.contextFactory().produce((*input)->path()));
-      (*input)->setSOName((*input)->path().native());
       m_LDBackend.getDynObjReader()->readDSO(**input);
     }
     // is an archive
     else if (m_LDBackend.getArchiveReader()->isMyFormat(*(*input))) {
       (*input)->setType(Input::Archive);
-      mcld::InputTree* archive_member = m_LDBackend.getArchiveReader()->readArchive(**input);
-      if(!archive_member)  {
-        llvm::report_fatal_error("wrong format archive" + (*input)->path().string());
+      mcld::InputTree* archive_member =
+                          m_LDBackend.getArchiveReader()->readArchive(**input);
+      if(NULL == archive_member)  {
+        error(diag::err_empty_input) << (*input)->name() << (*input)->path();
         return;
       }
 
       m_LDInfo.inputs().merge<InputTree::Inclusive>(input, *archive_member);
     }
     else {
-      llvm::report_fatal_error(llvm::Twine("can not recognize file format: ") +
-                               (*input)->path().native() +
-                               llvm::Twine("\nobject format or target machine is wrong\n"));
+      fatal(diag::err_unrecognized_input_file) << (*input)->path()
+                                               << m_LDInfo.triple().str();
     }
-  }
+  } // end of for
 }
 
-
 bool MCLDDriver::linkable() const
 {
+  // check we have input and output files
+  if (m_LDInfo.inputs().empty()) {
+    error(diag::err_no_inputs);
+    return false;
+  }
+
   // check all attributes are legal
   mcld::AttributeFactory::const_iterator attr, attrEnd = m_LDInfo.attrFactory().end();
   for (attr=m_LDInfo.attrFactory().begin(); attr!=attrEnd; ++attr) {
-    std::string error_code;
-    if (!m_LDInfo.attrFactory().constraint().isLegal((**attr), error_code)) {
-      report_fatal_error(error_code);
+    if (!m_LDInfo.attrFactory().constraint().isLegal((**attr))) {
       return false;
     }
   }
 
-
-  bool hasDynObj = false;
   // can not mix -static with shared objects
   mcld::InputTree::const_bfs_iterator input, inEnd = m_LDInfo.inputs().bfs_end();
   for (input=m_LDInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
-    if ((*input)->type() == mcld::Input::DynObj ) {
-      hasDynObj = true;
+    if ((*input)->type() == mcld::Input::DynObj) {
       if((*input)->attribute()->isStatic()) {
-        report_fatal_error("Can't link shared object with -static option");
+        error(diag::err_mixed_shared_static_objects)
+                                        << (*input)->name() << (*input)->path();
         return false;
       }
     }
@@ -127,7 +121,6 @@
   if (0 == m_pLinker)
     m_pLinker = new MCLinker(m_LDBackend,
                              m_LDInfo,
-                             *m_LDInfo.output().context(),
                              m_SectionMap);
 
   // initialize the readers and writers
@@ -137,16 +130,32 @@
       !m_LDBackend.initObjectReader(*m_pLinker) ||
       !m_LDBackend.initDynObjReader(*m_pLinker) ||
       !m_LDBackend.initObjectWriter(*m_pLinker) ||
-      !m_LDBackend.initDynObjWriter(*m_pLinker))
+      !m_LDBackend.initDynObjWriter(*m_pLinker) ||
+      !m_LDBackend.initExecWriter(*m_pLinker))
     return false;
 
+  // initialize RelocationFactory
+  m_LDBackend.initRelocFactory(*m_pLinker);
+  return true;
+}
+
+/// initStdSections - initialize standard sections
+bool MCLDDriver::initStdSections()
+{
   /// initialize section mapping for standard format, target-dependent section,
   /// (and user-defined mapping)
   if (!m_SectionMap.initStdSectionMap() ||
       !m_LDBackend.initTargetSectionMap(m_SectionMap))
     return false;
 
-  // initialize standard segments and sections
+  /// A technical debt. We need to initialize section map here because
+  /// we do not separate output file and temporary data structure. So far,
+  /// MCLinker directly use output file's LDContext as the temporary data
+  /// structure. We will create a new data structure mcld::Module to collect
+  /// all temporary data structures togather.
+  m_pLinker->initSectionMap();
+
+  // initialize standard sections
   switch (m_LDInfo.output().type()) {
     case Output::DynObj: {
       // intialize standard and target-dependent sections
@@ -174,12 +183,9 @@
     }
   } // end of switch
 
-  // initialize target-dependent segments and sections
+  // initialize target-dependent sections
   m_LDBackend.initTargetSections(*m_pLinker);
 
-  // initialize RelocationFactory
-  m_LDBackend.initRelocFactory(*m_pLinker);
-
   return true;
 }
 
@@ -226,25 +232,13 @@
   return true;
 }
 
-/// mergeSymbolTables - merge the symbol tables of input files into the
-/// output's symbol table.
-bool MCLDDriver::mergeSymbolTables()
-{
-  mcld::InputTree::dfs_iterator input, inEnd = m_LDInfo.inputs().dfs_end();
-  for (input=m_LDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
-    if (!m_pLinker->mergeSymbolTable(**input))
-      return false;
-  }
-  return true;
-}
-
 /// addStandardSymbols - shared object and executable files need some
 /// standard symbols
 ///   @return if there are some input symbols with the same name to the
 ///   standard symbols, return false
 bool MCLDDriver::addStandardSymbols()
 {
-  return m_LDBackend.initStandardSymbols(*m_pLinker);
+  return m_LDBackend.initStandardSymbols(*m_pLinker, m_LDInfo.output());
 }
 
 /// addTargetSymbols - some targets, such as MIPS and ARM, need some
@@ -253,7 +247,7 @@
 ///   target symbols, return false
 bool MCLDDriver::addTargetSymbols()
 {
-  m_LDBackend.initTargetSymbols(*m_pLinker);
+  m_LDBackend.initTargetSymbols(*m_pLinker, m_LDInfo.output());
   return true;
 }
 
@@ -284,6 +278,11 @@
 
   m_LDBackend.allocateCommonSymbols(m_LDInfo, *m_pLinker);
 
+  /// check program interpreter - computer the name size of the runtime dyld
+  /// FIXME: check if we are doing static linking!
+  if (m_LDInfo.output().type() == Output::Exec)
+    m_LDBackend.sizeInterp(m_LDInfo.output(), m_LDInfo);
+
   /// measure NamePools - compute the size of name pool sections
   /// In ELF, will compute  the size of.symtab, .strtab, .dynsym, .dynstr,
   /// and .hash sections.
@@ -314,16 +313,6 @@
   return true;
 }
 
-/// relocate - applying relocation entries and create relocation
-/// section in the output files
-/// Create relocation section, asking TargetLDBackend to
-/// read the relocation information into RelocationEntry
-/// and push_back into the relocation section
-bool MCLDDriver::relocate()
-{
-  return m_pLinker->applyRelocations();
-}
-
 /// finalizeSymbolValue - finalize the resolved symbol value.
 ///   Before relocate(), after layout(), MCLinker should correct value of all
 ///   symbol.
@@ -332,6 +321,16 @@
   return m_pLinker->finalizeSymbols();
 }
 
+/// relocate - applying relocation entries and create relocation
+/// section in the output files
+/// Create relocation section, asking TargetLDBackend to
+/// read the relocation information into RelocationEntry
+/// and push_back into the relocation section
+bool MCLDDriver::relocation()
+{
+  return m_pLinker->applyRelocations();
+}
+
 /// emitOutput - emit the output file.
 bool MCLDDriver::emitOutput()
 {
@@ -342,10 +341,9 @@
     case Output::DynObj:
       m_LDBackend.getDynObjWriter()->writeDynObj(m_LDInfo.output());
       return true;
-    /** TODO: open the executable file writer **/
-    // case Output::Exec:
-      // m_LDBackend.getExecWriter()->writeObject(m_LDInfo.output());
-      // return true;
+    case Output::Exec:
+      m_LDBackend.getExecWriter()->writeExecutable(m_LDInfo.output());
+      return true;
   }
   return false;
 }
@@ -354,5 +352,9 @@
 bool MCLDDriver::postProcessing()
 {
   m_pLinker->syncRelocationResult();
+
+  m_LDBackend.postProcessing(m_LDInfo.output(),
+                             m_LDInfo,
+                             *m_pLinker);
   return true;
 }
diff --git a/lib/MC/MCLDInfo.cpp b/lib/MC/MCLDInfo.cpp
index 3cd0838..7ac154c 100644
--- a/lib/MC/MCLDInfo.cpp
+++ b/lib/MC/MCLDInfo.cpp
@@ -6,12 +6,14 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
+#include <mcld/Config/Config.h>
 #include <mcld/MC/MCLDInfo.h>
-#include <mcld/Support/FileSystem.h>
 #include <mcld/MC/InputFactory.h>
 #include <mcld/MC/AttributeFactory.h>
 #include <mcld/MC/ContextFactory.h>
-#include <mcld/Config/Config.h>
+#include <mcld/LD/NamePool.h>
+#include <mcld/LD/StaticResolver.h>
+#include <mcld/Support/FileSystem.h>
 #include <string>
 
 using namespace mcld;
@@ -22,16 +24,17 @@
                    size_t pAttrNum,
                    size_t pInputNum)
   : m_Options(),
-    m_pBitcode(0),
-    m_Triple(pTripleString),
-    m_pStrSymPool(0)
+    m_Scripts(),
+    m_pBitcode(NULL),
+    m_Triple(pTripleString)
 {
   m_pAttrFactory = new AttributeFactory(pAttrNum);
   m_pCntxtFactory = new ContextFactory(pInputNum);
-  m_pMemAreaFactory = new MemoryAreaFactory(pInputNum);
   m_pInputFactory = new InputFactory(pInputNum, *m_pAttrFactory);
   m_pInputTree = new InputTree(*m_pInputFactory);
   m_pOutput = new mcld::Output();
+  m_pResolver = new StaticResolver();
+  m_pNamePool = new NamePool(*m_pResolver, 1024);
 }
 
 MCLDInfo::~MCLDInfo()
@@ -39,9 +42,10 @@
   delete m_pOutput;
   delete m_pAttrFactory;
   delete m_pCntxtFactory;
-  delete m_pMemAreaFactory;
   delete m_pInputFactory;
   delete m_pInputTree;
+  delete m_pResolver;
+  delete m_pNamePool;
 }
 
 void MCLDInfo::setBitcode(const Input& pInput)
@@ -63,5 +67,5 @@
 
 const char* MCLDInfo::version()
 {
-  return mcld::internal::version;
+  return MCLD_VERSION;
 }
diff --git a/lib/MC/MCLDOptions.cpp b/lib/MC/MCLDOptions.cpp
index ae07f26..47dbc35 100644
--- a/lib/MC/MCLDOptions.cpp
+++ b/lib/MC/MCLDOptions.cpp
@@ -6,13 +6,59 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDOptions.h"
-#include "mcld/MC/MCLDInput.h"
+#include <mcld/MC/MCLDOptions.h>
+#include <mcld/MC/MCLDInput.h>
 
 using namespace mcld;
 
-//==========================
-// MCLDOptions
+//===----------------------------------------------------------------------===//
+// ScriptOptions
+ScriptOptions::ScriptOptions()
+{
+}
+
+ScriptOptions::~ScriptOptions()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// GeneralOptions
+GeneralOptions::GeneralOptions()
+  : m_pDefaultBitcode(NULL),
+    m_Verbose(-1),
+    m_MaxErrorNum(-1),
+    m_MaxWarnNum(-1),
+    m_ExecStack(Unknown),
+    m_CommPageSize(0x0),
+    m_MaxPageSize(0x0),
+    m_bCombReloc(true),
+    m_bNoUndefined(false),
+    m_bInitFirst(false),
+    m_bInterPose(false),
+    m_bLoadFltr(false),
+    m_bMulDefs(false),
+    m_bNoCopyReloc(false),
+    m_bNoDefaultLib(false),
+    m_bNoDelete(false),
+    m_bNoDLOpen(false),
+    m_bNoDump(false),
+    m_bRelro(false),
+    m_bNow(false),
+    m_bOrigin(false),
+    m_bTrace(false),
+    m_Bsymbolic(false),
+    m_Bgroup(false),
+    m_bPIE(false),
+    m_bColor(true),
+    m_bAllowShlibUndefined(true),
+    m_bCreateEhFrameHdr(false)
+{
+}
+
+GeneralOptions::~GeneralOptions()
+{
+}
+
 bool GeneralOptions::hasDefaultLDScript() const
 {
   return true;
@@ -32,3 +78,75 @@
   m_Sysroot.assign(pSysroot);
 }
 
+void GeneralOptions::addZOption(const ZOption& pOption)
+{
+  switch (pOption.kind()) {
+    case ZOption::CombReloc:
+      m_bCombReloc = true;
+      break;
+    case ZOption::NoCombReloc:
+      m_bCombReloc = false;
+      break;
+    case ZOption::Defs:
+      m_bNoUndefined = true;
+      break;
+    case ZOption::ExecStack:
+      m_ExecStack = YES;
+      break;
+    case ZOption::NoExecStack:
+      m_ExecStack = NO;
+      break;
+    case ZOption::InitFirst:
+      m_bInitFirst = true;
+      break;
+    case ZOption::InterPose:
+      m_bInterPose = true;
+      break;
+    case ZOption::LoadFltr:
+      m_bLoadFltr = true;
+      break;
+    case ZOption::MulDefs:
+      m_bMulDefs = true;
+      break;
+    case ZOption::NoCopyReloc:
+      m_bNoCopyReloc = true;
+      break;
+    case ZOption::NoDefaultLib:
+      m_bNoDefaultLib = true;
+      break;
+    case ZOption::NoDelete:
+      m_bNoDelete = true;
+      break;
+    case ZOption::NoDLOpen:
+      m_bNoDLOpen = true;
+      break;
+    case ZOption::NoDump:
+      m_bNoDump = true;
+      break;
+    case ZOption::NoRelro:
+      m_bRelro = false;
+      break;
+    case ZOption::Relro:
+      m_bRelro = true;
+      break;
+    case ZOption::Lazy:
+      m_bNow = false;
+      break;
+    case ZOption::Now:
+      m_bNow = true;
+      break;
+    case ZOption::Origin:
+      m_bOrigin = true;
+      break;
+    case ZOption::CommPageSize:
+      m_CommPageSize = pOption.pageSize();
+      break;
+    case ZOption::MaxPageSize:
+      m_MaxPageSize = pOption.pageSize();
+      break;
+    case ZOption::Unknown:
+    default:
+      assert(false && "Not a recognized -z option.");
+      break;
+  }
+}
diff --git a/lib/MC/MCLinker.cpp b/lib/MC/MCLinker.cpp
index e5327e8..4b9c50f 100644
--- a/lib/MC/MCLinker.cpp
+++ b/lib/MC/MCLinker.cpp
@@ -10,7 +10,6 @@
 // This file implements the MCLinker class
 //
 //===----------------------------------------------------------------------===//
-
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/MCLDInput.h>
 #include <mcld/MC/MCLDInfo.h>
@@ -20,7 +19,10 @@
 #include <mcld/LD/LDSectionFactory.h>
 #include <mcld/LD/SectionMap.h>
 #include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/EhFrameHdr.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Target/TargetLDBackend.h>
 #include <llvm/Support/Host.h>
 #include <llvm/Support/raw_ostream.h>
@@ -30,25 +32,22 @@
 /// Constructor
 MCLinker::MCLinker(TargetLDBackend& pBackend,
                    MCLDInfo& pInfo,
-                   LDContext& pContext,
-                   SectionMap& pSectionMap,
-                   const Resolver& pResolver)
+                   SectionMap& pSectionMap)
 : m_Backend(pBackend),
-  m_Info(pInfo),
-  m_Output(pContext),
+  m_LDInfo(pInfo),
   m_SectionMap(pSectionMap),
   m_LDSymbolFactory(128),
   m_LDSectHdrFactory(10), // the average number of sections. (assuming 10.)
   m_LDSectDataFactory(10),
-  m_SectionMerger(pSectionMap, pContext),
-  m_StrSymPool(pResolver, 128)
+  m_pSectionMerger(NULL)
 {
-  m_Info.setNamePool(m_StrSymPool);
 }
 
 /// Destructor
 MCLinker::~MCLinker()
 {
+  if (NULL != m_pSectionMerger)
+    delete m_pSectionMerger;
 }
 
 /// addSymbolFromObject - add a symbol from object file and resolve it
@@ -70,7 +69,7 @@
   if (pBinding == ResolveInfo::Local) {
     // if the symbol is a local symbol, create a LDSymbol for input, but do not
     // resolve them.
-    resolved_result.info     = m_StrSymPool.createSymbol(pName,
+    resolved_result.info     = m_LDInfo.getNamePool().createSymbol(pName,
                                                          false,
                                                          pType,
                                                          pDesc,
@@ -85,8 +84,9 @@
   }
   else {
     // if the symbol is not local, insert and resolve it immediately
-    m_StrSymPool.insertSymbol(pName, false, pType, pDesc, pBinding, pSize,
-                              pVisibility, &old_info, resolved_result);
+    m_LDInfo.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
+                                        pSize, pVisibility,
+                                        &old_info, resolved_result);
   }
 
   // the return ResolveInfo should not NULL
@@ -188,7 +188,8 @@
   // insert symbol and resolve it immediately
   // resolved_result is a triple <resolved_info, existent, override>
   Resolver::Result resolved_result;
-  m_StrSymPool.insertSymbol(pName, true, pType, pDesc, pBinding, pSize, pVisibility,
+  m_LDInfo.getNamePool().insertSymbol(pName, true, pType, pDesc,
+                            pBinding, pSize, pVisibility,
                             NULL, resolved_result);
 
   // the return ResolveInfo should not NULL
@@ -238,14 +239,15 @@
                                            MCFragmentRef* pFragmentRef,
                                            ResolveInfo::Visibility pVisibility)
 {
-  ResolveInfo* info = m_StrSymPool.findInfo(pName);
+  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
   LDSymbol* output_sym = NULL;
   if (NULL == info) {
     // the symbol is not in the pool, create a new one.
     // create a ResolveInfo
     Resolver::Result result;
-    m_StrSymPool.insertSymbol(pName, pIsDyn, pType, pDesc, pBinding, pSize, pVisibility,
-                              NULL, result);
+    m_LDInfo.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc,
+                                        pBinding, pSize, pVisibility,
+                                        NULL, result);
     assert(!result.existent);
 
     // create a output LDSymbol
@@ -307,7 +309,7 @@
                                            MCFragmentRef* pFragmentRef,
                                            ResolveInfo::Visibility pVisibility)
 {
-  ResolveInfo* info = m_StrSymPool.findInfo(pName);
+  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
 
   if (NULL == info || !info->isUndef()) {
     // only undefined symbol can make a reference.
@@ -361,8 +363,9 @@
   // Result is <info, existent, override>
   Resolver::Result result;
   ResolveInfo old_info;
-  m_StrSymPool.insertSymbol(pName, pIsDyn, pType, pDesc, pBinding, pSize, pVisibility,
-                            &old_info, result);
+  m_LDInfo.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc, pBinding,
+                                      pSize, pVisibility,
+                                      &old_info, result);
 
   LDSymbol* output_sym = result.info->outSymbol();
   bool has_output_sym = (NULL != output_sym);
@@ -403,7 +406,7 @@
                                                     MCFragmentRef* pFragmentRef,
                                                     ResolveInfo::Visibility pVisibility)
 {
-  ResolveInfo* info = m_StrSymPool.findInfo(pName);
+  ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
 
   if (NULL == info || !info->isUndef()) {
     // only undefined symbol can make a reference
@@ -427,20 +430,22 @@
                                    uint32_t pType,
                                    uint32_t pFlag)
 {
+  assert(m_LDInfo.output().hasContext());
+
   // for user such as reader, standard/target fromat
   LDSection* result =
     m_LDSectHdrFactory.produce(pName, pKind, pType, pFlag);
 
   // check if we need to create a output section for output LDContext
   std::string sect_name = m_SectionMap.getOutputSectName(pName);
-  LDSection* output_sect = m_Output.getSection(sect_name);
+  LDSection* output_sect = m_LDInfo.output().context()->getSection(sect_name);
 
   if (NULL == output_sect) {
   // create a output section and push it into output LDContext
     output_sect =
       m_LDSectHdrFactory.produce(sect_name, pKind, pType, pFlag);
-    m_Output.getSectionTable().push_back(output_sect);
-    m_SectionMerger.addMapping(pName, output_sect);
+    m_LDInfo.output().context()->getSectionTable().push_back(output_sect);
+    m_pSectionMerger->addMapping(pName, output_sect);
   }
   return *result;
 }
@@ -453,17 +458,19 @@
                                               uint32_t pFlag,
                                               uint32_t pAlign)
 {
+  assert(m_LDInfo.output().hasContext());
+
   // check if we need to create a output section for output LDContext
   std::string sect_name = m_SectionMap.getOutputSectName(pName);
-  LDSection* output_sect = m_Output.getSection(sect_name);
+  LDSection* output_sect = m_LDInfo.output().context()->getSection(sect_name);
 
   if (NULL == output_sect) {
   // create a output section and push it into output LDContext
     output_sect =
       m_LDSectHdrFactory.produce(sect_name, pKind, pType, pFlag);
     output_sect->setAlign(pAlign);
-    m_Output.getSectionTable().push_back(output_sect);
-    m_SectionMerger.addMapping(pName, output_sect);
+    m_LDInfo.output().context()->getSectionTable().push_back(output_sect);
+    m_pSectionMerger->addMapping(pName, output_sect);
   }
   return *output_sect;
 }
@@ -481,7 +488,7 @@
 
   // try to get one from output LDSection
   LDSection* output_sect =
-    m_SectionMerger.getOutputSectHdr(pSection.name());
+    m_pSectionMerger->getOutputSectHdr(pSection.name());
 
   assert(NULL != output_sect);
 
@@ -509,8 +516,17 @@
                                     const LDSymbol& pSym,
                                     ResolveInfo& pResolveInfo,
                                     MCFragmentRef& pFragmentRef,
+                                    const LDSection& pSection,
                                     Relocation::Address pAddend)
 {
+  // FIXME: we should dicard sections and symbols first instead
+  // if the symbol is in the discarded input section, then we also need to
+  // discard this relocation.
+  if (pSym.fragRef() == NULL &&
+      pResolveInfo.type() == ResolveInfo::Section &&
+      pResolveInfo.desc() == ResolveInfo::Undefined)
+    return NULL;
+
   Relocation* relocation = m_Backend.getRelocFactory()->produce(pType,
                                                                 pFragmentRef,
                                                                 pAddend);
@@ -519,9 +535,11 @@
 
   m_RelocationList.push_back(relocation);
 
-  m_Backend.scanRelocation(*relocation, pSym, *this, m_Info,
-                           m_Info.output());
+  m_Backend.scanRelocation(*relocation, pSym, *this, m_LDInfo,
+                           m_LDInfo.output(), pSection);
 
+  if (pResolveInfo.isUndef() && !pResolveInfo.isDyn() && !pResolveInfo.isWeak())
+    fatal(diag::undefined_reference) << pResolveInfo.name();
   return relocation;
 }
 
@@ -531,7 +549,7 @@
 
   for (relocIter = m_RelocationList.begin(); relocIter != relocEnd; ++relocIter) {
     llvm::MCFragment* frag = (llvm::MCFragment*)relocIter;
-    static_cast<Relocation*>(frag)->apply(*m_Backend.getRelocFactory(), m_Info);
+    static_cast<Relocation*>(frag)->apply(*m_Backend.getRelocFactory(), m_LDInfo);
   }
   return true;
 }
@@ -539,9 +557,8 @@
 void MCLinker::syncRelocationResult()
 {
 
-  m_Info.output().memArea()->clean();
-  MemoryRegion* region = m_Info.output().memArea()->request(0,
-                              m_Info.output().memArea()->size());
+  MemoryRegion* region = m_LDInfo.output().memArea()->request(0,
+                              m_LDInfo.output().memArea()->handler()->size());
 
   uint8_t* data = region->getBuffer();
 
@@ -580,13 +597,19 @@
     }
   } // end of for
 
-  m_Info.output().memArea()->sync();
+  m_LDInfo.output().memArea()->clear();
 }
 
+void MCLinker::initSectionMap()
+{
+  assert(m_LDInfo.output().hasContext());
+  if (NULL == m_pSectionMerger)
+    m_pSectionMerger = new SectionMerger(m_SectionMap, *m_LDInfo.output().context());
+}
 
 bool MCLinker::layout()
 {
-  return m_Layout.layout(m_Info.output(), m_Backend);
+  return m_Layout.layout(m_LDInfo.output(), m_Backend, m_LDInfo);
 }
 
 bool MCLinker::finalizeSymbols()
@@ -594,18 +617,9 @@
   SymbolCategory::iterator symbol, symEnd = m_OutputSymbols.end();
   for (symbol = m_OutputSymbols.begin(); symbol != symEnd; ++symbol) {
 
-    if (0x0 != (*symbol)->resolveInfo()->reserved()) {
-      // if the symbol is target reserved, target backend is responsible
-      // for finalizing the value.
-      // if target backend does not know this symbol, it will return false
-      // and we have to take over the symbol.
-      if (m_Backend.finalizeSymbol(**symbol))
-        continue;
-    }
-
     if ((*symbol)->resolveInfo()->isAbsolute() ||
         (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
-      // absolute symbols and symbols with function type should have
+      // absolute symbols or symbols with function type should have
       // zero value
       (*symbol)->setValue(0x0);
       continue;
@@ -623,7 +637,8 @@
     }
   }
 
-  return true;
+  // finialize target-dependent symbols
+  return m_Backend.finalizeSymbols(*this, m_LDInfo.output());
 }
 
 bool MCLinker::shouldForceLocal(const ResolveInfo& pInfo) const
@@ -633,7 +648,7 @@
   // 2. The symbol is with Hidden or Internal visibility.
   // 3. The symbol should be global or weak. Otherwise, local symbol is local.
   // 4. The symbol is defined or common
-  if (m_Info.output().type() != Output::Object &&
+  if (m_LDInfo.output().type() != Output::Object &&
       (pInfo.visibility() == ResolveInfo::Hidden ||
          pInfo.visibility() == ResolveInfo::Internal) &&
       (pInfo.isGlobal() || pInfo.isWeak()) &&
@@ -642,3 +657,44 @@
   return false;
 }
 
+/// addEhFrame - add an exception handling section
+/// @param pSection - the input section
+/// @param pArea - the memory area which pSection is within.
+uint64_t MCLinker::addEhFrame(LDSection& pSection, MemoryArea& pArea)
+{
+  uint64_t size = 0;
+
+  // get the SectionData of this eh_frame
+  llvm::MCSectionData& sect_data = getOrCreateSectData(pSection);
+
+  // parse the eh_frame if the option --eh-frame-hdr is given
+  if (m_LDInfo.options().hasEhFrameHdr()) {
+    EhFrame* ehframe = m_Backend.getEhFrame();
+    assert(NULL != ehframe);
+    if (ehframe->canRecognizeAllEhFrame()) {
+      size = ehframe->readEhFrame(m_Layout, m_Backend, sect_data, pSection,
+                                       pArea);
+      // zero size indicate that this is an empty section or we can't recognize
+      // this eh_frame, handle it as a regular section.
+      if (0 != size)
+        return size;
+    }
+  }
+
+  // handle eh_frame as a regular section
+  MemoryRegion* region = pArea.request(pSection.offset(),
+                                       pSection.size());
+
+  llvm::MCFragment* frag = NULL;
+  if (NULL == region) {
+    // If the input section's size is zero, we got a NULL region.
+    // use a virtual fill fragment
+    frag = new llvm::MCFillFragment(0x0, 0, 0);
+  }
+  else
+    frag = new MCRegionFragment(*region);
+
+  size = m_Layout.appendFragment(*frag, sect_data, pSection.align());
+  return size;
+}
+
diff --git a/lib/MC/README b/lib/MC/README
deleted file mode 100644
index f020b50..0000000
--- a/lib/MC/README
+++ /dev/null
@@ -1,8 +0,0 @@
-MCLDStreamer is similar to MCObjectStreamer
-MCLinker is similar to MCAssembler
-MCLDWriter is similar to MCObjectWriter
-
-MCELFObjectReader parses ELF object files
-to MCInst classes
-
-
diff --git a/lib/MC/SearchDirs.cpp b/lib/MC/SearchDirs.cpp
index 0d21e46..40d625b 100644
--- a/lib/MC/SearchDirs.cpp
+++ b/lib/MC/SearchDirs.cpp
@@ -6,16 +6,13 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/ADT/Twine.h>
-
-#include "mcld/MC/SearchDirs.h"
-#include "mcld/Support/FileSystem.h"
-#include "mcld/MC/MCLDDirectory.h"
+#include <mcld/MC/SearchDirs.h>
+#include <mcld/MC/MCLDDirectory.h>
+#include <mcld/Support/FileSystem.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // Non-member functions
 static void SpecToFilename(const std::string& pSpec, std::string& pFile)
 {
@@ -23,7 +20,7 @@
   pFile += pSpec;
 }
 
-//==========================
+//===----------------------------------------------------------------------===//
 // SearchDirs
 SearchDirs::SearchDirs()
 {
@@ -47,6 +44,8 @@
 
 mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec, mcld::Input::Type pType)
 {
+  assert(Input::DynObj == pType || Input::Archive == pType);
+
   std::string file;
   SpecToFilename(pNamespec, file);
   // for all MCLDDirectorys
@@ -64,11 +63,10 @@
               return entry.path();
             }
           }
-
           ++entry;
         }
       }
-
+      /** Fall through **/
       case Input::Archive : {
         entry = (*mcld_dir)->begin();
         enEnd = (*mcld_dir)->end();
@@ -78,15 +76,12 @@
             return entry.path();
           }
           ++entry;
-       }
-     }
-     default: {
-       llvm::report_fatal_error(llvm::Twine("SearchDir can not recoginize namespec: `") +
-                                pNamespec +
-                                llvm::Twine("'."));
-     }
-    }
-  }
-  return 0;
+        }
+      }
+      default:
+        break;
+    } // end of switch
+  } // end of while
+  return NULL;
 }
 
diff --git a/lib/MC/ZOption.cpp b/lib/MC/ZOption.cpp
new file mode 100644
index 0000000..a58562d
--- /dev/null
+++ b/lib/MC/ZOption.cpp
@@ -0,0 +1,25 @@
+//===- ZOption.cpp --------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/ZOption.h>
+
+using namespace mcld;
+
+//==========================
+// ZOption
+
+ZOption::ZOption()
+  : m_Kind(Unknown),
+    m_PageSize(0x0)
+{
+}
+
+ZOption::~ZOption()
+{
+}
+
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 57b82df..cc15e37 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -6,12 +6,16 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/CommandLine.h"
+#include <mcld/Support/CommandLine.h>
 #include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/ErrorHandling.h>
 
 using namespace llvm;
 using namespace llvm::cl;
 
+using namespace mcld;
+
 //--------------------------------------------------
 // parser<mcld::sys::fs::Path>
 //
@@ -82,3 +86,81 @@
   // do nothing
 }
 
+//--------------------------------------------------
+// parser<mcld::ZOption>
+//
+bool parser<mcld::ZOption>::parse(llvm::cl::Option &O,
+                                  llvm::StringRef ArgName,
+                                  llvm::StringRef Arg,
+                                  mcld::ZOption &Val)
+{
+  if (0 == Arg.compare("combreloc"))
+    Val.setKind(ZOption::CombReloc);
+  else if (0 == Arg.compare("nocombreloc"))
+    Val.setKind(ZOption::NoCombReloc);
+  else if (0 == Arg.compare("defs"))
+    Val.setKind(ZOption::Defs);
+  else if (0 == Arg.compare("execstack"))
+    Val.setKind(ZOption::ExecStack);
+  else if (0 == Arg.compare("noexecstack"))
+    Val.setKind(ZOption::NoExecStack);
+  else if (0 == Arg.compare("initfirst"))
+    Val.setKind(ZOption::InitFirst);
+  else if (0 == Arg.compare("interpose"))
+    Val.setKind(ZOption::InterPose);
+  else if (0 == Arg.compare("loadfltr"))
+    Val.setKind(ZOption::LoadFltr);
+  else if (0 == Arg.compare("muldefs"))
+    Val.setKind(ZOption::MulDefs);
+  else if (0 == Arg.compare("nocopyreloc"))
+    Val.setKind(ZOption::NoCopyReloc);
+  else if (0 == Arg.compare("nodefaultlib"))
+    Val.setKind(ZOption::NoDefaultLib);
+  else if (0 == Arg.compare("nodelete"))
+    Val.setKind(ZOption::NoDelete);
+  else if (0 == Arg.compare("nodlopen"))
+    Val.setKind(ZOption::NoDLOpen);
+  else if (0 == Arg.compare("nodump"))
+    Val.setKind(ZOption::NoDump);
+  else if (0 == Arg.compare("relro"))
+    Val.setKind(ZOption::Relro);
+  else if (0 == Arg.compare("norelro"))
+    Val.setKind(ZOption::NoRelro);
+  else if (0 == Arg.compare("lazy"))
+    Val.setKind(ZOption::Lazy);
+  else if (0 == Arg.compare("now"))
+    Val.setKind(ZOption::Now);
+  else if (0 == Arg.compare("origin"))
+    Val.setKind(ZOption::Origin);
+  else if (Arg.startswith("common-page-size=")) {
+    Val.setKind(ZOption::CommPageSize);
+    long long unsigned size = 0;
+    Arg.drop_front(17).getAsInteger(0, size);
+    Val.setPageSize(static_cast<uint64_t>(size));
+  } else if (Arg.startswith("max-page-size=")) {
+    Val.setKind(ZOption::MaxPageSize);
+    long long unsigned size = 0;
+    Arg.drop_front(14).getAsInteger(0, size);
+    Val.setPageSize(static_cast<uint64_t>(size));
+  }
+
+  if (ZOption::Unknown == Val.kind())
+    llvm::report_fatal_error(llvm::Twine("unknown -z option: `") +
+                             Arg +
+                             llvm::Twine("'\n"));
+  return false;
+}
+
+void parser<mcld::ZOption>::printOptionDiff(const llvm::cl::Option &O,
+                                            const mcld::ZOption &V,
+                                            parser<mcld::ZOption>::OptVal Default,
+                                            size_t GlobalWidth) const
+{
+  // TODO
+}
+
+void parser<mcld::ZOption>::anchor()
+{
+  // do nothing
+}
+
diff --git a/lib/Support/Directory.cpp b/lib/Support/Directory.cpp
index 211b42a..78bb761 100644
--- a/lib/Support/Directory.cpp
+++ b/lib/Support/Directory.cpp
@@ -32,7 +32,7 @@
   : m_Path(),
     m_FileStatus(),
     m_SymLinkStatus(),
-    m_Handler(NULL),
+    m_Handler(0),
     m_Cache(),
     m_CacheFull(false) {
 }
@@ -43,7 +43,7 @@
   : m_Path(pPath),
     m_FileStatus(st),
     m_SymLinkStatus(symlink_st),
-    m_Handler(NULL),
+    m_Handler(0),
     m_Cache(),
     m_CacheFull(false) {
   if (m_Path.native() == ".")
@@ -56,7 +56,7 @@
   : m_Path(pCopy.m_Path),
     m_FileStatus(pCopy.m_FileStatus),
     m_SymLinkStatus(pCopy.m_SymLinkStatus),
-    m_Handler(NULL),
+    m_Handler(0),
     m_Cache(),
     m_CacheFull(false) {
   mcld::sys::fs::detail::open_dir(*this);
diff --git a/lib/Support/FileHandle.cpp b/lib/Support/FileHandle.cpp
new file mode 100644
index 0000000..f6b898c
--- /dev/null
+++ b/lib/Support/FileHandle.cpp
@@ -0,0 +1,332 @@
+//===- FileHandle.cpp -----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/FileSystem.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// FileHandle
+FileHandle::FileHandle()
+  : m_Path(),
+    m_Handler(-1),
+    m_Size(0),
+    m_State(GoodBit),
+    m_OpenMode(NotOpen) {
+}
+
+FileHandle::~FileHandle()
+{
+  if (isOpened())
+    close();
+}
+
+inline static int oflag(FileHandle::OpenMode pMode)
+{
+  int result = 0x0;
+  if (FileHandle::Unknown == pMode)
+    return result;
+
+  if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
+    result |= O_RDWR;
+  else if (pMode & FileHandle::ReadOnly)
+    result |= O_RDONLY;
+  else if (pMode & FileHandle::WriteOnly)
+    result |= O_WRONLY;
+
+  if (pMode & FileHandle::Append)
+    result |= O_APPEND;
+
+  if (pMode & FileHandle::Create)
+    result |= O_CREAT;
+
+  if (pMode & FileHandle::Truncate)
+    result |= O_TRUNC;
+
+  return result;
+}
+
+inline static bool get_size(int pHandler, unsigned int &pSize)
+{
+  struct ::stat file_stat;
+  if (-1 == ::fstat(pHandler, &file_stat)) {
+    pSize = 0;
+    return false;
+  }
+  pSize = file_stat.st_size;
+  return true;
+}
+
+bool FileHandle::open(const sys::fs::Path& pPath,
+                      FileHandle::OpenMode pMode)
+{
+  if (isOpened() || Unknown == pMode) {
+    setState(BadBit);
+    return false;
+  }
+
+  m_OpenMode = pMode;
+  m_Handler = ::open(pPath.native().c_str(), oflag(pMode));
+  m_Path = pPath;
+  if (-1 == m_Handler) {
+    m_OpenMode = NotOpen;
+    setState(FailBit);
+    return false;
+  }
+
+  if (!get_size(m_Handler, m_Size)) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+bool FileHandle::open(const sys::fs::Path& pPath,
+                      FileHandle::OpenMode pMode,
+                      FileHandle::Permission pPerm)
+{
+  if (isOpened() || Unknown == pMode) {
+    setState(BadBit);
+    return false;
+  }
+
+  m_OpenMode = pMode;
+  m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
+  m_Path = pPath;
+  if (-1 == m_Handler) {
+    m_OpenMode = NotOpen;
+    setState(FailBit);
+    return false;
+  }
+
+  if (!get_size(m_Handler, m_Size)) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+bool FileHandle::delegate(int pFD, FileHandle::OpenMode pMode)
+{
+  if (isOpened()) {
+    setState(BadBit);
+    return false;
+  }
+
+  m_Handler = pFD;
+  m_OpenMode = pMode;
+  m_State = GoodBit;
+
+  if (!get_size(m_Handler, m_Size)) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+bool FileHandle::close()
+{
+  if (!isOpened()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (-1 == ::close(m_Handler)) {
+    setState(FailBit);
+    return false;
+  }
+
+  m_Path.native().clear();
+  m_Size = 0;
+  m_OpenMode = NotOpen;
+  cleanState();
+  return true;
+}
+
+bool FileHandle::truncate(size_t pSize)
+{
+  if (!isOpened() || !isWritable()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (-1 == sys::fs::detail::ftruncate(m_Handler, pSize)) {
+    setState(FailBit);
+    return false;
+  }
+
+  m_Size = pSize;
+  return true;
+}
+
+bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+  if (!isOpened() || !isReadable()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (0 == pLength)
+    return true;
+
+  ssize_t read_bytes = sys::fs::detail::pread(m_Handler,
+                                              pMemBuffer,
+                                              pLength,
+                                              pStartOffset);
+
+  if (-1 == read_bytes) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+bool FileHandle::write(const void* pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+  if (!isOpened() || !isWritable()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (0 == pLength)
+    return true;
+
+
+  ssize_t write_bytes = sys::fs::detail::pwrite(m_Handler,
+                                                pMemBuffer,
+                                                pLength,
+                                                pStartOffset);
+
+  if (-1 == write_bytes) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+#include <iostream>
+using namespace std;
+
+bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+  if (!isOpened()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (0 == pLength)
+    return true;
+
+  int prot, flag;
+  if (isReadable() && !isWritable()) {
+    // read-only
+    prot = PROT_READ;
+    flag = MAP_FILE | MAP_PRIVATE;
+  }
+  else if (!isReadable() && isWritable()) {
+    // write-only
+    prot = PROT_WRITE;
+    flag = MAP_FILE | MAP_SHARED;
+  }
+  else if (isReadWrite()) {
+    // read and write
+    prot = PROT_READ | PROT_WRITE;
+    flag = MAP_FILE | MAP_SHARED;
+  }
+  else {
+    // can not read/write
+    setState(BadBit);
+    return false;
+  }
+
+  pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset);
+
+  if (MAP_FAILED == pMemBuffer) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+bool FileHandle::munmap(void* pMemBuffer, size_t pLength)
+{
+  if (!isOpened()) {
+    setState(BadBit);
+    return false;
+  }
+
+  if (-1 == ::munmap(pMemBuffer, pLength)) {
+    setState(FailBit);
+    return false;
+  }
+
+  return true;
+}
+
+void FileHandle::setState(FileHandle::IOState pState)
+{
+  m_State |= pState;
+}
+
+void FileHandle::cleanState(FileHandle::IOState pState)
+{
+  m_State = pState;
+}
+
+bool FileHandle::isOpened() const
+{
+  if (-1 != m_Handler && m_OpenMode != NotOpen && isGood())
+    return true;
+
+  return false;
+}
+
+// Assume Unknown OpenMode is readable
+bool FileHandle::isReadable() const
+{
+  return (m_OpenMode & ReadOnly);
+}
+
+// Assume Unknown OpenMode is writable
+bool FileHandle::isWritable() const
+{
+  return (m_OpenMode & WriteOnly);
+}
+
+// Assume Unknown OpenMode is both readable and writable
+bool FileHandle::isReadWrite() const
+{
+  return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite));
+}
+
+bool FileHandle::isGood() const
+{
+  return !(m_State & (BadBit | FailBit));
+}
+
+bool FileHandle::isBad() const
+{
+  return (m_State & BadBit);
+}
+
+bool FileHandle::isFailed() const
+{
+  return (m_State & (BadBit | FailBit));
+}
+
diff --git a/lib/Support/FileSystem.cpp b/lib/Support/FileSystem.cpp
index d3366c0..fb2633d 100644
--- a/lib/Support/FileSystem.cpp
+++ b/lib/Support/FileSystem.cpp
@@ -9,10 +9,6 @@
 #include "mcld/Support/FileSystem.h"
 #include "mcld/Support/Path.h"
 
-#if defined(ANDROID)
-#include <llvm/Config/config.h>
-#endif
-
 using namespace mcld::sys::fs;
 
 
@@ -22,12 +18,12 @@
 //===--------------------------------------------------------------------===//
 // non-member functions
 
-// Include the truly platform-specific parts.
-#if defined(LLVM_ON_UNIX)
+// Include the truly platform-specific parts. 
+#if defined(MCLD_ON_UNIX)
 #include "Unix/FileSystem.inc"
-#include "Unix/PathV3.inc"
-#endif
-#if defined(LLVM_ON_WIN32)
+#include "Unix/PathV3.inc" 
+#endif 
+#if defined(MCLD_ON_WIN32)
 #include "Windows/FileSystem.inc"
-#include "Windows/PathV3.inc"
-#endif
+#include "Windows/PathV3.inc" 
+#endif 
diff --git a/lib/Support/HandleToArea.cpp b/lib/Support/HandleToArea.cpp
new file mode 100644
index 0000000..f580e64
--- /dev/null
+++ b/lib/Support/HandleToArea.cpp
@@ -0,0 +1,94 @@
+//===- HandleToArea.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/HandleToArea.h>
+#include <mcld/Support/MemoryArea.h>
+#include <llvm/ADT/StringRef.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// HandleToArea
+bool HandleToArea::push_back(FileHandle* pHandle, MemoryArea* pArea)
+{
+  if (NULL == pHandle || NULL == pArea)
+    return false;
+
+  Bucket bucket;
+  bucket.hash_value = HashFunction()(
+                              llvm::StringRef(pHandle->path().native().c_str(),
+                                              pHandle->path().native().size()));
+
+  bucket.handle = pHandle;
+  bucket.area = pArea;
+  m_AreaMap.push_back(bucket);
+  return true;
+}
+
+bool HandleToArea::erase(MemoryArea* pArea)
+{
+  if (NULL == pArea || NULL == pArea->handler())
+    return false;
+
+  return erase(pArea->handler()->path());
+}
+
+bool HandleToArea::erase(const sys::fs::Path& pPath)
+{
+  unsigned int hash_value = HashFunction()(
+                                  llvm::StringRef(pPath.native().c_str(),
+                                                  pPath.native().size()));
+
+  HandleToAreaMap::iterator bucket, bEnd = m_AreaMap.end();
+  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+    if (bucket->hash_value == hash_value && bucket->handle->path() == pPath) {
+      // found
+      m_AreaMap.erase(bucket);
+      return true;
+    }
+  }
+
+  return false;
+}
+
+HandleToArea::Result HandleToArea::findFirst(const sys::fs::Path& pPath)
+{
+  unsigned int hash_value = HashFunction()(llvm::StringRef(pPath.native().c_str(),
+                                                         pPath.native().size()));
+
+  HandleToAreaMap::iterator bucket, bEnd = m_AreaMap.end();
+
+  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+    if (bucket->hash_value == hash_value) {
+      if (bucket->handle->path() == pPath) {
+        return Result(bucket->handle, bucket->area);
+      }
+    }
+  }
+
+  return Result(NULL, NULL);
+}
+
+HandleToArea::ConstResult HandleToArea::findFirst(const sys::fs::Path& pPath) const
+{
+  unsigned int hash_value = HashFunction()(llvm::StringRef(pPath.native().c_str(),
+                                                         pPath.native().size()));
+
+  HandleToAreaMap::const_iterator bucket, bEnd = m_AreaMap.end();
+
+  for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+    if (bucket->hash_value == hash_value) {
+      if (bucket->handle->path() == pPath) {
+        return ConstResult(bucket->handle, bucket->area);
+      }
+    }
+  }
+
+  return ConstResult(NULL, NULL);
+}
+
diff --git a/lib/Support/MemoryArea.cpp b/lib/Support/MemoryArea.cpp
index f388e94..78a9d36 100644
--- a/lib/Support/MemoryArea.cpp
+++ b/lib/Support/MemoryArea.cpp
@@ -6,164 +6,31 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/ADT/Twine.h>
-
 #include <mcld/Support/RegionFactory.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/FileSystem.h>
-
-#include <cerrno>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
 //===--------------------------------------------------------------------===//
 // MemoryArea
-MemoryArea::MemoryArea(RegionFactory& pRegionFactory)
-  : m_RegionFactory(pRegionFactory),
-    m_FileDescriptor(-1),
-    m_FileSize(0),
-    m_AccessFlags(ReadOnly),
-    m_State(BadBit) {
+
+// MemoryArea - special constructor
+// This constructor is used for *SPECIAL* situation. I'm sorry I can not
+// reveal what is the special situation.
+MemoryArea::MemoryArea(RegionFactory& pRegionFactory, Space& pUniverse)
+  : m_RegionFactory(pRegionFactory), m_pFileHandle(NULL) {
+  m_SpaceList.push_back(&pUniverse);
+}
+
+MemoryArea::MemoryArea(RegionFactory& pRegionFactory, FileHandle& pFileHandle)
+  : m_RegionFactory(pRegionFactory), m_pFileHandle(&pFileHandle) {
 }
 
 MemoryArea::~MemoryArea()
 {
-  // truncate the file to real size
-  if (isWritable())
-    truncate(m_FileSize);
-
-  unmap();
-}
-
-void MemoryArea::truncate(size_t pLength)
-{
-  if (!isWritable())
-    return;
-
-  if (-1 == ::ftruncate(m_FileDescriptor, static_cast<off_t>(pLength))) {
-    llvm::report_fatal_error(llvm::Twine("Cannot truncate `") +
-                             m_FilePath.native() +
-                             llvm::Twine("' to size: ") +
-                             llvm::Twine(pLength) +
-                             llvm::Twine(".\n"));
-  }
-}
-
-void MemoryArea::map(const sys::fs::Path& pPath, int pFlags)
-{
-  m_AccessFlags = pFlags;
-  m_FilePath = pPath;
-  m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags);
-
-  if (-1 == m_FileDescriptor) {
-    m_State |= FailBit;
-  }
-  else {
-    struct stat st;
-    int stat_result = ::stat(m_FilePath.native().c_str(), &st);
-    if (0x0 == stat_result) {
-      m_FileSize = static_cast<size_t>(st.st_size);
-      m_State = GoodBit;
-    }
-    else {
-      m_FileSize = 0x0;
-      m_State |= FailBit;
-      m_State |= BadBit;
-    }
-  }
-}
-
-void MemoryArea::map(const sys::fs::Path& pPath, int pFlags, int pMode)
-{
-  m_AccessFlags = pFlags;
-  m_FilePath = pPath;
-  m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags, pMode);
-
-  if (-1 == m_FileDescriptor) {
-    m_State |= FailBit;
-  }
-  else {
-    struct stat st;
-    int stat_result = ::stat(m_FilePath.native().c_str(), &st);
-    if (0x0 == stat_result) {
-      m_FileSize = static_cast<size_t>(st.st_size);
-      m_State = GoodBit;
-    }
-    else {
-      m_FileSize = 0x0;
-      m_State |= FailBit;
-      m_State |= BadBit;
-    }
-  }
-}
-
-void MemoryArea::unmap()
-{
-  if (isMapped()) {
-    if (-1 == ::close(m_FileDescriptor))
-      m_State |= FailBit;
-    else {
-      m_FileDescriptor = -1;
-      m_AccessFlags = ReadOnly;
-    }
-  }
-}
-
-bool MemoryArea::isMapped() const
-{
-  return (-1 != m_FileDescriptor);
-}
-
-bool MemoryArea::isGood() const
-{
-  return 0x0 == (m_State & (BadBit | FailBit));
-}
-
-bool MemoryArea::isBad() const
-{
-  return 0x0 != (m_State & BadBit);
-}
-
-bool MemoryArea::isFailed() const
-{
-  return 0x0 != (m_State & FailBit);
-}
-
-bool MemoryArea::isEOF() const
-{
-  return 0x0 != (m_State & EOFBit);
-}
-
-bool MemoryArea::isReadable() const
-{
-  return (((m_AccessFlags & AccessMask) == ReadOnly) ||
-         ((m_AccessFlags & AccessMask) == ReadWrite));
-}
-
-bool MemoryArea::isWritable() const
-{
-  return (((m_AccessFlags & AccessMask) == WriteOnly) ||
-         ((m_AccessFlags & AccessMask) == ReadWrite));
-}
-
-int MemoryArea::rdstate() const
-{
-  return m_State;
-}
-
-void MemoryArea::setState(MemoryArea::IOState pState)
-{
-  m_State |= pState;
-}
-
-void MemoryArea::clear(MemoryArea::IOState pState)
-{
-  m_State = pState;
 }
 
 // The layout of MemorySpace in the virtual memory space
@@ -185,242 +52,100 @@
 //
 MemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength)
 {
-  if (!isMapped() || !isGood())
-    return NULL;
-
-  if (0x0 == pLength)
-    return NULL;
-
-  if (!isWritable() && (pOffset + pLength) > m_FileSize)
-    return NULL;
-
-  if (isWritable() && (pOffset + pLength) > m_FileSize) {
-    // If the memory area is writable, user can expand the size of file by
-    // request a region larger than the file.
-    // MemoryArea should enlarge the file if the requested region is larger
-    // than the file.
-    m_FileSize = page_boundary(pOffset + pLength + 1);
-    truncate(m_FileSize);
-  }
-
   Space* space = find(pOffset, pLength);
-  MemoryArea::Address r_start = 0;
   if (NULL == space) {
-    // the space does not exist, create a new space.
-    space = new Space(this, pOffset, pLength);
+
+    // not found
+    if (NULL == m_pFileHandle) {
+      // if m_pFileHandle is NULL, clients delegate us an universal Space and
+      // we never remove it. In that way, space can not be NULL.
+      unreachable(diag::err_out_of_range_region);
+    }
+
+    space = Space::createSpace(*m_pFileHandle, pOffset, pLength);
     m_SpaceList.push_back(space);
-    switch(space->type = policy(pOffset, pLength)) {
-      case Space::MMAPED: {
-        int mm_prot, mm_flag;
-        if (isWritable()) {
-          mm_prot = PROT_READ | PROT_WRITE;
-          mm_flag = MAP_FILE | MAP_SHARED;
-        }
-        else {
-          mm_prot = PROT_READ;
-          mm_flag = MAP_FILE | MAP_PRIVATE;
-        }
-
-        space->file_offset = page_offset(pOffset);
-
-        // The space's size may be larger than filesize.
-        space->size = page_boundary(pLength + pOffset + 1 - space->file_offset);
-        space->data = (Address) ::mmap(NULL,
-                                       space->size,
-                                       mm_prot, mm_flag,
-                                       m_FileDescriptor,
-                                       space->file_offset);
-
-        if (space->data == MAP_FAILED) {
-          llvm::report_fatal_error(llvm::Twine("cannot open memory map file :") +
-                                   m_FilePath.native() +
-                                   llvm::Twine(" (") +
-                                   sys::fs::detail::strerror(errno) +
-                                   llvm::Twine(").\n"));
-        }
-
-        r_start = space->data + (pOffset - space->file_offset);
-        break;
-      }
-      case Space::ALLOCATED_ARRAY: {
-        // space->offset and space->size are set in constructor. We only need
-        // to set up data.
-        space->data = new unsigned char[pLength];
-        r_start = space->data;
-        if ((m_AccessFlags & AccessMask) != WriteOnly) {
-          // Read data from the backend file.
-          if (!read(*space)) {
-            llvm::report_fatal_error(llvm::Twine("Failed to read data from ") +
-                                     m_FilePath.native() +
-                                     llvm::Twine(" (") +
-                                     sys::fs::detail::strerror(errno) +
-                                     llvm::Twine(") at offset ") +
-                                     llvm::Twine(pOffset) +
-                                     llvm::Twine(" lenght ") +
-                                     llvm::Twine(pLength) + llvm::Twine(".\n"));
-          }
-        }
-        break;
-      } // case
-      default: {
-        llvm::report_fatal_error("unhandled space type\n");
-      }
-    } // switch
   }
-  else { // found
-    off_t distance = pOffset - space->file_offset;
-    r_start = space->data + distance;
-  }
+
+  // adjust r_start
+  off_t distance = pOffset - space->start();
+  void* r_start = space->memory() + distance;
 
   // now, we have a legal space to hold the new MemoryRegion
-  return m_RegionFactory.produce(space, r_start, pLength);
+  return m_RegionFactory.produce(*space, r_start, pLength);
 }
 
 // release - release a MemoryRegion
 void MemoryArea::release(MemoryRegion* pRegion)
 {
-  if (!isMapped() || !isGood())
+  if (NULL == pRegion)
     return;
 
   Space *space = pRegion->parent();
   m_RegionFactory.destruct(pRegion);
 
-  if (0 == space->region_num) {
-    write(*space);
-    m_SpaceList.remove(*space);
-    release(space);
+  if (0 == space->numOfRegions()) {
+
+    if (NULL != m_pFileHandle) {
+      // if m_pFileHandle is NULL, clients delegate us an universal Space and
+      // we never remove it. Otherwise, we have to synchronize and release
+      // Space.
+      if (m_pFileHandle->isWritable()) {
+        // synchronize writable space before we release it.
+        Space::syncSpace(space, *m_pFileHandle);
+      }
+      Space::releaseSpace(space, *m_pFileHandle);
+    }
+    m_SpaceList.erase(space);
   }
 }
 
-void MemoryArea::clean()
+// clear - release all MemoryRegions
+void MemoryArea::clear()
 {
-  m_RegionFactory.clear();
+  if (NULL == m_pFileHandle)
+    return;
 
-  SpaceList::iterator sIter, sEnd = m_SpaceList.end();
-  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
-    write(*sIter);
-    release(sIter);
+  if (m_pFileHandle->isWritable()) {
+    SpaceList::iterator space, sEnd = m_SpaceList.end();
+    for (space = m_SpaceList.begin(); space != sEnd; ++space) {
+      Space::syncSpace(space, *m_pFileHandle);
+      Space::releaseSpace(space, *m_pFileHandle);
+    }
   }
+  else {
+    SpaceList::iterator space, sEnd = m_SpaceList.end();
+    for (space = m_SpaceList.begin(); space != sEnd; ++space)
+      Space::releaseSpace(space, *m_pFileHandle);
+  }
+
   m_SpaceList.clear();
 }
 
-void MemoryArea::sync()
+//===--------------------------------------------------------------------===//
+// SpaceList methods
+Space* MemoryArea::find(size_t pOffset, size_t pLength)
 {
   SpaceList::iterator sIter, sEnd = m_SpaceList.end();
   for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
-    write(*sIter);
-  }
-}
-
-MemoryArea::Space* MemoryArea::find(size_t pOffset, size_t pLength)
-{
-  SpaceList::iterator sIter, sEnd = m_SpaceList.end();
-  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
-    if (sIter->file_offset <= pOffset &&
-       (pOffset+pLength) <= (sIter->file_offset+sIter->size) ) { // within
+    if (sIter->start() <= pOffset &&
+       (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
+      // within
       return sIter;
     }
   }
   return NULL;
 }
 
-void MemoryArea::release(MemoryArea::Space* pSpace)
+const Space* MemoryArea::find(size_t pOffset, size_t pLength) const
 {
-  switch (pSpace->type) {
-    case Space::ALLOCATED_ARRAY: {
-      delete [] pSpace->data;
-      break;
-    }
-    case Space::MMAPED: {
-      ::munmap(pSpace->data, pSpace->size);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-MemoryArea::Space::Type MemoryArea::policy(off_t pOffset, size_t pLength)
-{
-  const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux
-  if (pLength < threshold)
-    return Space::ALLOCATED_ARRAY;
-  else
-    return Space::MMAPED;
-}
-
-ssize_t MemoryArea::readToBuffer(sys::fs::detail::Address pBuf,
-                                 size_t pSize, size_t pOffset) {
-  assert(((m_AccessFlags & AccessMask) != WriteOnly) &&
-         "Write-only file cannot be read!");
-
-  ssize_t read_bytes = sys::fs::detail::pread(m_FileDescriptor, pBuf,
-                                              pSize, pOffset);
-  if (static_cast<size_t>(read_bytes) != pSize) {
-    // Some error occurred during pread().
-    if (read_bytes < 0) {
-      m_State |= FailBit;
-    }
-    else if (static_cast<size_t>(read_bytes) < pSize) {
-      m_State |= EOFBit;
-      if ((m_AccessFlags & AccessMask) != ReadWrite) {
-        // Files which is not read-write are not allowed read beyonds the EOF
-        // marker.
-        m_State |= BadBit;
-      }
-    }
-    else {
-      m_State |= BadBit;
+  SpaceList::const_iterator sIter, sEnd = m_SpaceList.end();
+  for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
+    if (sIter->start() <= pOffset &&
+       (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
+      // within
+      return sIter;
     }
   }
-  return read_bytes;
-}
-
-bool MemoryArea::read(Space& pSpace) {
-  if (!isGood() || !isReadable())
-    return false;
-
-  if (pSpace.type == Space::ALLOCATED_ARRAY) {
-    readToBuffer(pSpace.data, pSpace.size, pSpace.file_offset);
-    return isGood();
-  }
-  else {
-    // Data associated with mmap()'ed space is already at the position the
-    // pSpace points to.
-    assert((pSpace.type == Space::MMAPED) && "Unknown type of Space!");
-    return true;
-  }
-}
-
-
-void MemoryArea::write(const Space& pSpace)
-{
-  if (!isMapped() || !isGood() || !isWritable())
-    return;
-
-  switch(pSpace.type) {
-    case Space::MMAPED: {
-      if(-1 == ::msync(pSpace.data, pSpace.size, MS_SYNC))
-        m_State |= FailBit;
-      return;
-    }
-    case Space::ALLOCATED_ARRAY: {
-      ssize_t write_bytes = sys::fs::detail::pwrite(m_FileDescriptor,
-                                                    pSpace.data,
-                                                    pSpace.size,
-                                                    pSpace.file_offset);
-      if (0 > write_bytes) {
-        m_State |= FailBit;
-        return;
-      }
-      if (0 == write_bytes && 0 != pSpace.size)
-        m_State |= BadBit;
-      if ( pSpace.size > static_cast<size_t>(write_bytes) )
-        m_State |= EOFBit;
-      return;
-    }
-    default:
-      return;
-  }
+  return NULL;
 }
 
diff --git a/lib/Support/MemoryAreaFactory.cpp b/lib/Support/MemoryAreaFactory.cpp
index 1f7e523..3da07d5 100644
--- a/lib/Support/MemoryAreaFactory.cpp
+++ b/lib/Support/MemoryAreaFactory.cpp
@@ -6,15 +6,18 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/MemoryAreaFactory.h"
-#include "mcld/Support/RegionFactory.h"
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/RegionFactory.h>
+#include <mcld/Support/SystemUtils.h>
+#include <mcld/Support/Space.h>
 
 using namespace mcld;
 
-//==========================
+//===----------------------------------------------------------------------===//
 // MemoryAreaFactory
 MemoryAreaFactory::MemoryAreaFactory(size_t pNum)
-  : UniqueGCFactoryBase<sys::fs::Path, MemoryArea, 0>(pNum) {
+  : GCFactory<MemoryArea, 0>(pNum) {
   // For each loaded file, MCLinker must load ELF header, section header,
   // symbol table, and string table. So, we set the size of chunk quadruple
   // larger than the number of input files.
@@ -23,30 +26,91 @@
 
 MemoryAreaFactory::~MemoryAreaFactory()
 {
+  HandleToArea::iterator rec, rEnd = m_HandleToArea.end();
+  for (rec = m_HandleToArea.begin(); rec != rEnd; ++rec) {
+    if (rec->handle->isOpened()) {
+      rec->handle->close();
+    }
+    delete rec->handle;
+  }
+
   delete m_pRegionFactory;
 }
 
-MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath, int pFlags)
+MemoryArea*
+MemoryAreaFactory::produce(const sys::fs::Path& pPath,
+                           FileHandle::OpenMode pMode)
 {
-  MemoryArea* result = find(pPath);
-  if (0 == result) {
-    result = allocate();
-    new (result) MemoryArea(*m_pRegionFactory);
-    result->map(pPath, pFlags);
-    f_KeyMap.insert(std::make_pair(pPath, result));
+  HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
+  if (NULL == map_result.area) {
+    // can not found
+    FileHandle* handler = new FileHandle();
+    if (!handler->open(pPath, pMode)) {
+      error(diag::err_cannot_open_file) << pPath
+                                        << sys::strerror(handler->error());
+    }
+
+    MemoryArea* result = allocate();
+    new (result) MemoryArea(*m_pRegionFactory, *handler);
+
+    m_HandleToArea.push_back(handler, result);
+    return result;
   }
+
+  return map_result.area;
+}
+
+MemoryArea*
+MemoryAreaFactory::produce(const sys::fs::Path& pPath,
+                           FileHandle::OpenMode pMode,
+                           FileHandle::Permission pPerm)
+{
+  HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
+  if (NULL == map_result.area) {
+    // can not found
+    FileHandle* handler = new FileHandle();
+    if (!handler->open(pPath, pMode, pPerm)) {
+      error(diag::err_cannot_open_file) << pPath
+                                        << sys::strerror(handler->error());
+    }
+
+    MemoryArea* result = allocate();
+    new (result) MemoryArea(*m_pRegionFactory, *handler);
+
+    m_HandleToArea.push_back(handler, result);
+    return result;
+  }
+
+  return map_result.area;
+}
+
+void MemoryAreaFactory::destruct(MemoryArea* pArea)
+{
+  m_HandleToArea.erase(pArea);
+  pArea->clear();
+  pArea->handler()->close();
+  destroy(pArea);
+  deallocate(pArea);
+}
+
+MemoryArea*
+MemoryAreaFactory::create(void* pMemBuffer, size_t pSize)
+{
+  Space* space = new Space(Space::EXTERNAL, pMemBuffer, pSize);
+  MemoryArea* result = allocate();
+  new (result) MemoryArea(*m_pRegionFactory, *space);
   return result;
 }
 
-MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath, int pFlags, mode_t pMode)
+MemoryArea*
+MemoryAreaFactory::create(int pFD, FileHandle::OpenMode pMode)
 {
-  MemoryArea* result = find(pPath);
-  if (0 == result) {
-    result = allocate();
-    new (result) MemoryArea(*m_pRegionFactory);
-    result->map(pPath, pFlags, pMode);
-    f_KeyMap.insert(std::make_pair(pPath, result));
-  }
+  FileHandle* handler = new FileHandle();
+  handler->delegate(pFD, pMode);
+  
+  MemoryArea* result = allocate();
+  new (result) MemoryArea(*m_pRegionFactory, *handler);
+
   return result;
 }
 
diff --git a/lib/Support/MemoryRegion.cpp b/lib/Support/MemoryRegion.cpp
index 3a35f4e..32e790b 100644
--- a/lib/Support/MemoryRegion.cpp
+++ b/lib/Support/MemoryRegion.cpp
@@ -12,23 +12,13 @@
 
 //==========================
 // MemoryRegion
-MemoryRegion::MemoryRegion(MemoryArea::Space *pParentSpace,
-                           const MemoryRegion::Address pVMAStart,
+MemoryRegion::MemoryRegion(Space& pParent,
+                           MemoryRegion::Address pVMAStart,
                            size_t pSize)
-  : m_pParentSpace(pParentSpace), m_VMAStart(pVMAStart), m_Length(pSize) {
-  m_pParentSpace->region_num++;
+  : m_Parent(pParent), m_VMAStart(pVMAStart), m_Length(pSize) {
 }
 
 MemoryRegion::~MemoryRegion()
 {
-  drift();
-}
-
-void MemoryRegion::drift()
-{
-  if (NULL == m_pParentSpace)
-    return;
-  m_pParentSpace->region_num--;
-  m_pParentSpace = NULL;
 }
 
diff --git a/lib/Support/MsgHandling.cpp b/lib/Support/MsgHandling.cpp
new file mode 100644
index 0000000..5b45289
--- /dev/null
+++ b/lib/Support/MsgHandling.cpp
@@ -0,0 +1,74 @@
+//===- MsgHandling.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticEngine.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/MsgHandler.h>
+#include <mcld/Support/MsgHandling.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/raw_ostream.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// DiagnosticInitializer
+class DiagnosticInitializer : public llvm::ManagedStaticBase
+{
+public:
+  DiagnosticEngine* initialize(const MCLDInfo& pLDInfo,
+                               DiagnosticLineInfo* pLineInfo,
+                               DiagnosticPrinter* pPrinter)
+  {
+    RegisterManagedStatic(NULL, llvm::object_deleter<DiagnosticEngine>::call);
+    if (llvm::llvm_is_multithreaded()) {
+      llvm::llvm_acquire_global_lock();
+      void* tmp = NULL;
+      if (NULL != pPrinter)
+        tmp = new DiagnosticEngine(pLDInfo, pLineInfo, pPrinter, false);
+      else
+        tmp = new DiagnosticEngine(pLDInfo, pLineInfo, NULL, false);
+
+      TsanHappensBefore(this);
+      llvm::sys::MemoryFence();
+      TsanIgnoreWritesBegin();
+      Ptr = tmp;
+      TsanIgnoreWritesEnd();
+      llvm::llvm_release_global_lock();
+    }
+    else {
+      if (NULL != pPrinter)
+        Ptr = new DiagnosticEngine(pLDInfo, pLineInfo, pPrinter, false);
+      else
+        Ptr = new DiagnosticEngine(pLDInfo, pLineInfo, NULL, false);
+    }
+    return static_cast<DiagnosticEngine*>(Ptr);
+  }
+};
+
+static DiagnosticInitializer g_DiagInitializer;
+static DiagnosticEngine* g_pDiagnosticEngine = NULL;
+
+void mcld::InitializeDiagnosticEngine(const mcld::MCLDInfo& pLDInfo,
+                                DiagnosticLineInfo* pLineInfo,
+                                DiagnosticPrinter* pPrinter)
+{
+  if (NULL == g_pDiagnosticEngine) {
+    g_pDiagnosticEngine = g_DiagInitializer.initialize(pLDInfo,
+                                                       pLineInfo,
+                                                       pPrinter);
+  }
+}
+
+DiagnosticEngine& mcld::getDiagnosticEngine()
+{
+  assert(NULL != g_pDiagnosticEngine &&
+         "mcld::InitializeDiagnostics() is not called");
+  return *g_pDiagnosticEngine;
+}
+
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index ffb449f..8cc384d 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -11,11 +11,8 @@
 #include <llvm/ADT/StringRef.h>
 
 #include <locale>
-#include <stdio.h>
 #include <string.h>
 
-#include <iostream>
-
 using namespace mcld;
 using namespace mcld::sys::fs;
 
@@ -119,7 +116,7 @@
 Path::StringType::size_type Path::m_append_separator_if_needed()
 {
   if (!m_PathName.empty() &&
-#ifdef LLVM_ON_WIN32
+#if defined(MCLD_ON_WIN32)
       *(m_PathName.end()-1) != colon &&
 #endif
       !is_separator(*(m_PathName.end()-1))) {
@@ -171,7 +168,7 @@
 bool mcld::sys::fs::is_separator(char value)
 {
   return (value == separator
-#ifdef LLVM_ON_WIN32
+#if defined(MCLD_ON_WIN32)
           || value == preferred_separator
 #endif
           );
diff --git a/lib/Support/RegionFactory.cpp b/lib/Support/RegionFactory.cpp
index e87d389..ddce433 100644
--- a/lib/Support/RegionFactory.cpp
+++ b/lib/Support/RegionFactory.cpp
@@ -6,8 +6,9 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/RegionFactory.h"
-#include "mcld/Support/MemoryArea.h"
+#include <mcld/Support/RegionFactory.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/Space.h>
 
 using namespace mcld;
 
@@ -21,18 +22,19 @@
 {
 }
 
-MemoryRegion* RegionFactory::produce(MemoryArea::Space* pSpace,
-                                     const sys::fs::detail::Address pVMAStart,
-                                     size_t pSize)
+MemoryRegion* RegionFactory::produce(Space& pSpace, void* pVMAStart, size_t pSize)
 {
   MemoryRegion* result = Alloc::allocate();
-  new (result) MemoryRegion(pSpace, pVMAStart, pSize);
+  new (result) MemoryRegion(pSpace,
+                            static_cast<const MemoryRegion::Address>(pVMAStart),
+                            pSize);
+  pSpace.addRegion(*result);
   return result;
 }
 
 void RegionFactory::destruct(MemoryRegion* pRegion)
 {
-  pRegion->drift();
+  pRegion->parent()->removeRegion(*pRegion);
   destroy(pRegion);
   deallocate(pRegion);
 }
diff --git a/lib/Support/Space.cpp b/lib/Support/Space.cpp
new file mode 100644
index 0000000..4024da1
--- /dev/null
+++ b/lib/Support/Space.cpp
@@ -0,0 +1,179 @@
+//===- Space.cpp ----------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/Space.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MsgHandling.h>
+#include <cstdlib>
+#include <unistd.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// constant data
+static const off_t PageSize = getpagesize();
+
+//===----------------------------------------------------------------------===//
+// Non-member functions
+//
+// low address      A page             high address
+// |--------------------|------------------|
+// ^ page_offset        ^ pFileOffset      ^ page_boundary
+
+// Given a file offset, return the page offset.
+// return the first page boundary \b before pFileOffset
+inline static off_t page_offset(off_t pFileOffset)
+{ return pFileOffset & ~ (PageSize - 1); }
+
+// page_boundary - Given a file size, return the size to read integral pages.
+// return the first page boundary \b after pFileOffset
+inline static off_t page_boundary(off_t pFileOffset)
+{ return (pFileOffset + (PageSize - 1)) & ~ (PageSize - 1); }
+
+inline static Space::Type policy(off_t pOffset, size_t pLength)
+{
+  const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux
+  if (pLength < threshold)
+    return Space::ALLOCATED_ARRAY;
+  else
+    return Space::MMAPED;
+}
+
+//===----------------------------------------------------------------------===//
+// Space
+Space::Space()
+  : m_Data(NULL), m_StartOffset(0), m_Size(0),
+    m_RegionCount(0), m_Type(UNALLOCATED) {
+}
+
+Space::Space(Space::Type pType, void* pMemBuffer, size_t pSize)
+  : m_Data(static_cast<Address>(pMemBuffer)), m_StartOffset(0), m_Size(pSize),
+    m_RegionCount(0), m_Type(pType)
+{
+}
+
+Space::~Space()
+{
+  // do nothing. m_Data is deleted by @ref releaseSpace
+}
+
+Space* Space::createSpace(FileHandle& pHandler,
+                          size_t pStart, size_t pSize)
+{
+  Type type;
+  void* memory;
+  Space* result = NULL;
+  size_t start, size = 0, total_offset;
+  switch(type = policy(pStart, pSize)) {
+    case ALLOCATED_ARRAY: {
+      // adjust total_offset, start and size
+      total_offset = pStart + pSize;
+      start = pStart;
+      if (total_offset > pHandler.size()) {
+        if (pHandler.isWritable()) {
+          size = pSize;
+          pHandler.truncate(total_offset);
+        }
+        else if (pHandler.size() > start)
+          size = pHandler.size() - start;
+        else {
+          // create a space out of a read-only file.
+          fatal(diag::err_cannot_read_small_file) << pHandler.path()
+                                                  << pHandler.size()
+                                                  << start << size;
+        }
+      }
+      else
+        size = pSize;
+
+      // malloc
+      memory = (void*)malloc(size);
+      if (!pHandler.read(memory, start, size))
+        error(diag::err_cannot_read_file) << pHandler.path() << start << size;
+
+      break;
+    }
+    case MMAPED: {
+      // adjust total_offset, start and size
+      total_offset = page_boundary(pStart + pSize);
+      start = page_offset(pStart);
+      if (total_offset > pHandler.size()) {
+        if (pHandler.isWritable()) {
+          size = page_boundary((pStart - start) + pSize);
+          pHandler.truncate(total_offset);
+        }
+        else if (pHandler.size() > start)
+          size = pHandler.size() - start;
+        else {
+          // create a space out of a read-only file.
+          fatal(diag::err_cannot_read_small_file) << pHandler.path()
+                                                  << pHandler.size()
+                                                  << start << size;
+        }
+      }
+      else
+        size = page_boundary((pStart - start) + pSize);
+
+      // mmap
+      if (!pHandler.mmap(memory, start, size))
+        error(diag::err_cannot_mmap_file) << pHandler.path() << start << size;
+
+      break;
+    }
+    default:
+      break;
+  } // end of switch
+
+  result = new Space(type, memory, size);
+  result->setStart(start);
+  return result;
+}
+
+void Space::releaseSpace(Space* pSpace, FileHandle& pHandler)
+{
+  if (NULL == pSpace)
+    return;
+
+  switch(pSpace->type()) {
+    case ALLOCATED_ARRAY:
+      free(pSpace->memory());
+      break;
+    case MMAPED:
+      if (!pHandler.munmap(pSpace->memory(), pSpace->size()))
+        error(diag::err_cannot_munmap_file) << pHandler.path();
+      break;
+    default: // external and unallocated memory buffers
+      break;
+  } // end of switch
+}
+
+void Space::syncSpace(Space* pSpace, FileHandle& pHandler)
+{
+  if (NULL == pSpace || !pHandler.isWritable())
+    return;
+
+  switch(pSpace->type()) {
+    case Space::ALLOCATED_ARRAY: {
+      if (!pHandler.write(pSpace->memory(),
+                          pSpace->start(),
+                          pSpace->size())) {
+        error(diag::err_cannot_write_file) << pHandler.path()
+                                           << pSpace->start()
+                                           << pSpace->size();
+      }
+      return;
+    }
+    case Space::MMAPED:
+    default: {
+      // system will eventually write bakc the memory after
+      // calling ::munmap
+      return;
+    }
+  } // end of switch
+}
+
diff --git a/lib/Support/SystemUtils.cpp b/lib/Support/SystemUtils.cpp
new file mode 100644
index 0000000..5dfea36
--- /dev/null
+++ b/lib/Support/SystemUtils.cpp
@@ -0,0 +1,20 @@
+//===- SystemUtils.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/SystemUtils.h>
+
+using namespace mcld::sys;
+
+//===----------------------------------------------------------------------===//
+// Non-member functions
+#if defined(MCLD_ON_UNIX)
+#include "Unix/System.inc"
+#endif
+#if defined(MCLD_ON_WIN32)
+#include "Windows/System.inc"
+#endif 
diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index 246cbe8..8bfa235 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/lib/Support/TargetRegistry.cpp
@@ -6,13 +6,11 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/TargetRegistry.h"
+#include <mcld/Support/TargetRegistry.h>
 
 
 mcld::TargetRegistry::TargetListTy mcld::TargetRegistry::s_TargetList;
 
-/* ** */
-
 void mcld::TargetRegistry::RegisterTarget(mcld::Target &T)
 {
   s_TargetList.push_back(&T);
@@ -34,7 +32,7 @@
 const mcld::Target *mcld::TargetRegistry::lookupTarget(const std::string &pTriple,
                                                        std::string &pError) 
 {
-  const llvm::Target* target = llvm::TargetRegistry::lookupTarget( pTriple, pError );
+  const llvm::Target* target = llvm::TargetRegistry::lookupTarget(pTriple, pError);
   if (!target)
     return 0;
   return lookupTarget( *target );
diff --git a/lib/Support/Unix/FileSystem.inc b/lib/Support/Unix/FileSystem.inc
index 6499d66..ce6d0df 100644
--- a/lib/Support/Unix/FileSystem.inc
+++ b/lib/Support/Unix/FileSystem.inc
@@ -9,6 +9,7 @@
 #include <string>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include <fcntl.h>
 
 namespace mcld{
@@ -23,19 +24,29 @@
 std::string assembly_extension = ".s";
 std::string bitcode_extension = ".bc";
 
-size_t pread(int pFD, Address pBuf, size_t pCount, off_t pOffset)
+int open(const Path& pPath, int pOFlag)
 {
-  return ::pread(pFD, (void*) pBuf, pCount, pOffset);
+  return ::open(pPath.native().c_str(), pOFlag);
 }
 
-size_t pwrite(int pFD, const Address pBuf, size_t pCount, off_t pOffset)
+int open(const Path& pPath, int pOFlag, int pPerm)
 {
-  return ::pwrite(pFD, (const void*) pBuf, pCount, pOffset);
+  return ::open(pPath.native().c_str(), pOFlag, pPerm);
 }
 
-char *strerror(int errnum)
+ssize_t pread(int pFD, void* pBuf, size_t pCount, size_t pOffset)
 {
-  return ::strerror(errnum);
+  return ::pread(pFD, pBuf, pCount, pOffset);
+}
+
+ssize_t pwrite(int pFD, const void* pBuf, size_t pCount, size_t pOffset)
+{
+  return ::pwrite(pFD, pBuf, pCount, pOffset);
+}
+
+int ftruncate(int pFD, size_t pLength)
+{
+  return ::ftruncate(pFD, pLength);
 }
 
 } // namespace of detail
diff --git a/lib/Support/Unix/PathV3.inc b/lib/Support/Unix/PathV3.inc
index 2e8e6d0..68b0c36 100644
--- a/lib/Support/Unix/PathV3.inc
+++ b/lib/Support/Unix/PathV3.inc
@@ -282,7 +282,7 @@
 {
   if (pDir.m_Handler)
     closedir(reinterpret_cast<DIR *>(pDir.m_Handler));
-  pDir.m_Handler = NULL;
+  pDir.m_Handler = 0;
 }
 
 void get_pwd(std::string& pPWD)
diff --git a/lib/Support/Unix/System.inc b/lib/Support/Unix/System.inc
new file mode 100644
index 0000000..716aaa2
--- /dev/null
+++ b/lib/Support/Unix/System.inc
@@ -0,0 +1,24 @@
+//===- System.inc ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace mcld{
+namespace sys{
+
+char *strerror(int errnum)
+{
+  return ::strerror(errnum);
+}
+
+} // namespace of sys
+} // namespace of mcld
+
diff --git a/lib/Support/Windows/System.inc b/lib/Support/Windows/System.inc
new file mode 100644
index 0000000..bfd75ee
--- /dev/null
+++ b/lib/Support/Windows/System.inc
@@ -0,0 +1,19 @@
+//===- System.inc ---------------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace mcld{
+namespace sys{
+
+} // namespace of sys
+} // namespace of mcld
+
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
new file mode 100644
index 0000000..2453c2c
--- /dev/null
+++ b/lib/Support/raw_ostream.cpp
@@ -0,0 +1,95 @@
+//===- raw_ostream.cpp ----------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/raw_ostream.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// raw_ostream
+mcld::raw_fd_ostream::raw_fd_ostream(const char *pFilename,
+                               std::string &pErrorInfo,
+                               unsigned int pFlags,
+                               const MCLDInfo* pLDInfo)
+  : llvm::raw_fd_ostream(pFilename, pErrorInfo, pFlags), m_pLDInfo(pLDInfo) {
+}
+
+mcld::raw_fd_ostream::raw_fd_ostream(int pFD,
+                               bool pShouldClose,
+                               bool pUnbuffered,
+                               const MCLDInfo* pLDInfo)
+  : llvm::raw_fd_ostream(pFD, pShouldClose, pUnbuffered), m_pLDInfo(pLDInfo) {
+}
+
+mcld::raw_fd_ostream::~raw_fd_ostream()
+{
+}
+
+void mcld::raw_fd_ostream::setLDInfo(const MCLDInfo& pLDInfo)
+{
+  m_pLDInfo = &pLDInfo;
+}
+
+llvm::raw_ostream &
+mcld::raw_fd_ostream::changeColor(enum llvm::raw_ostream::Colors pColor,
+                                  bool pBold,
+                                  bool pBackground)
+{
+  if (!is_displayed())
+    return *this;
+  return llvm::raw_fd_ostream::changeColor(pColor, pBold, pBackground);
+}
+
+llvm::raw_ostream& mcld::raw_fd_ostream::resetColor()
+{
+  if (!is_displayed())
+    return *this;
+  return llvm::raw_fd_ostream::resetColor();
+}
+
+// FIXME: migrate to newer LLVM
+/**
+llvm::raw_ostream& mcld::raw_fd_ostream::reverseColor()
+{
+  if (!is_displayed())
+    return *this;
+  return llvm::raw_ostream::reverseColor();
+}
+**/
+
+bool mcld::raw_fd_ostream::is_displayed() const
+{
+  if (NULL == m_pLDInfo)
+    return llvm::raw_fd_ostream::is_displayed();
+
+  return m_pLDInfo->options().color();
+}
+
+//===----------------------------------------------------------------------===//
+//  outs(), errs(), nulls()
+//===----------------------------------------------------------------------===//
+mcld::raw_fd_ostream& mcld::outs() {
+  // Set buffer settings to model stdout behavior.
+  // Delete the file descriptor when the program exists, forcing error
+  // detection. If you don't want this behavior, don't use outs().
+  static mcld::raw_fd_ostream S(STDOUT_FILENO, true, NULL);
+  return S;
+}
+
+mcld::raw_fd_ostream& mcld::errs() {
+  // Set standard error to be unbuffered by default.
+  static mcld::raw_fd_ostream S(STDERR_FILENO, false, true, NULL);
+  return S;
+}
+
+void mcld::InitializeOStreams(const MCLDInfo& pLDInfo)
+{
+  outs().setLDInfo(pLDInfo);
+  errs().setLDInfo(pLDInfo);
+}
+
diff --git a/lib/Target/ARM/ARM.h b/lib/Target/ARM/ARM.h
index b833151..53e4795 100644
--- a/lib/Target/ARM/ARM.h
+++ b/lib/Target/ARM/ARM.h
@@ -9,15 +9,17 @@
 #ifndef MCLD_ARM_H
 #define MCLD_ARM_H
 #include <string>
-#include "mcld/Target/TargetMachine.h"
+#include <mcld/Target/TargetMachine.h>
 
 namespace mcld {
 class TargetLDBackend;
 
 extern mcld::Target TheARMTarget;
+extern mcld::Target TheThumbTarget;
 
 TargetLDBackend *createARMLDBackend(const llvm::Target&, const std::string&);
 
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMAndroidSectLinker.cpp b/lib/Target/ARM/ARMAndroidSectLinker.cpp
deleted file mode 100644
index a704cfa..0000000
--- a/lib/Target/ARM/ARMAndroidSectLinker.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- ARMAndroidSectLinker.cpp -------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ARMAndroidSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-ARMAndroidSectLinker::ARMAndroidSectLinker(SectLinkerOption &pOption,
-                                           TargetLDBackend &pLDBackend)
-  : AndroidSectLinker(pOption,
-                      pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attributes
-  info.attrFactory().constraint().disableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().unsetWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-
-}
-
-ARMAndroidSectLinker::~ARMAndroidSectLinker()
-{
-}
-
diff --git a/lib/Target/ARM/ARMAndroidSectLinker.h b/lib/Target/ARM/ARMAndroidSectLinker.h
deleted file mode 100644
index 8a47a94..0000000
--- a/lib/Target/ARM/ARMAndroidSectLinker.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- ARMAndroidSectLinker.h ---------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ARM_ANDROIDSECTLINKER_H
-#define ARM_ANDROIDSECTLINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/Target/AndroidSectLinker.h>
-
-namespace mcld
-{
-
-class MCLDInfo;
-
-/** \class ARMAndroidSectLinker
- *  \brief ARMAndroidSectLinker sets up the environment for linking.
- *
- *  \see
- *  \author Anders Cheng <[email protected]>
- */
-class ARMAndroidSectLinker : public AndroidSectLinker
-{
-public:
-  ARMAndroidSectLinker(SectLinkerOption &pOption,
-                       mcld::TargetLDBackend &pLDBackend);
-
-  ~ARMAndroidSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/ARM/ARMDiagnostic.cpp b/lib/Target/ARM/ARMDiagnostic.cpp
new file mode 100644
index 0000000..1ecf7df
--- /dev/null
+++ b/lib/Target/ARM/ARMDiagnostic.cpp
@@ -0,0 +1,39 @@
+//===- ARMDiagnostic.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/DWARFLineInfo.h>
+#include "ARM.h"
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ARMDiagnostic
+
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createARMDiagnostic - the help function to create corresponding ARMDiagnostic
+//
+DiagnosticLineInfo* createARMDiagLineInfo(const llvm::Target& pTarget,
+                                          const std::string &pTriple)
+{
+  return new DWARFLineInfo();
+}
+
+} // namespace of mcld
+
+//==========================
+// InitializeARMDiagnostic
+extern "C" void LLVMInitializeARMDiagnosticLineInfo() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheARMTarget, createARMDiagLineInfo);
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheThumbTarget, createARMDiagLineInfo);
+}
+
diff --git a/lib/Target/ARM/ARMELFArchiveReader.h b/lib/Target/ARM/ARMELFArchiveReader.h
index b60a12d..2fa9ce2 100644
--- a/lib/Target/ARM/ARMELFArchiveReader.h
+++ b/lib/Target/ARM/ARMELFArchiveReader.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef ARMELFARCHIVEREADER_H
-#define ARMELFARCHIVEREADER_H
+#ifndef MCLD_ARM_ELF_ARCHIVE_READER_H
+#define MCLD_ARM_ELF_ARCHIVE_READER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/lib/Target/ARM/ARMELFSectLinker.h b/lib/Target/ARM/ARMELFSectLinker.h
index 7493d59..ab626b9 100644
--- a/lib/Target/ARM/ARMELFSectLinker.h
+++ b/lib/Target/ARM/ARMELFSectLinker.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef ARM_ELFSECTLINKER_H
-#define ARM_ELFSECTLINKER_H
+#ifndef ARM_ELF_SECTION_LINKER_H
+#define ARM_ELF_SECTION_LINKER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h
index 1bf82f5..f42b940 100644
--- a/lib/Target/ARM/ARMFixupKinds.h
+++ b/lib/Target/ARM/ARMFixupKinds.h
@@ -41,9 +41,9 @@
   // instruction.
   fixup_t2_adr_pcrel_12,
   // fixup_arm_condbranch - 24-bit PC relative relocation for conditional branch
-  // instructions.
+  // instructions. 
   fixup_arm_condbranch,
-  // fixup_arm_uncondbranch - 24-bit PC relative relocation for
+  // fixup_arm_uncondbranch - 24-bit PC relative relocation for 
   // branch instructions. (unconditional)
   fixup_arm_uncondbranch,
   // fixup_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
index 37d8e6b..7430203 100644
--- a/lib/Target/ARM/ARMGOT.cpp
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -9,7 +9,7 @@
 #include "ARMGOT.h"
 #include <mcld/LD/LDFileFormat.h>
 #include <mcld/Support/MemoryRegion.h>
-#include <llvm/Support/ErrorHandling.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
@@ -33,7 +33,7 @@
                                         &m_SectionData);
 
     if (!Entry)
-      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+      fatal(diag::fail_allocate_memory) << "GOT0";
 
     m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
   }
@@ -43,9 +43,7 @@
   iterator ie = m_SectionData.end();
 
   for (int i = 1; i < ARMGOT0Num; ++i) {
-    if (it == ie)
-      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
-
+    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
     ++it;
   }
 
@@ -69,7 +67,7 @@
                                         &m_SectionData);
 
     if (!Entry)
-      llvm::report_fatal_error("Allocating new memory for GOTEntry failed");
+      fatal(diag::fail_allocate_memory) << "GOTEntry";
 
     m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
   }
@@ -82,7 +80,7 @@
     got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
 
     if (!got_entry)
-      llvm::report_fatal_error("Allocating new memory for GOT failed!");
+      fatal(diag::fail_allocate_memory) << "GOTEntry";
 
     m_Section.setSize(m_Section.size() + getEntrySize());
 
@@ -182,3 +180,4 @@
   }
   return result;
 }
+
diff --git a/lib/Target/ARM/ARMGOT.h b/lib/Target/ARM/ARMGOT.h
index 4667421..90f0f53 100644
--- a/lib/Target/ARM/ARMGOT.h
+++ b/lib/Target/ARM/ARMGOT.h
@@ -89,3 +89,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index fe57fd6..e0f5dcf 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -9,7 +9,6 @@
 #include <llvm/ADT/Triple.h>
 #include <llvm/ADT/Twine.h>
 #include <llvm/Support/ELF.h>
-#include <llvm/Support/ErrorHandling.h>
 
 #include <mcld/LD/SectionMap.h>
 #include <mcld/MC/MCLDInfo.h>
@@ -17,6 +16,7 @@
 #include <mcld/MC/MCLinker.h>
 #include <mcld/MC/MCRegionFragment.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
 
 #include <cstring>
@@ -42,17 +42,17 @@
 
 ARMGNULDBackend::~ARMGNULDBackend()
 {
-  if (m_pRelocFactory)
+  if (NULL != m_pRelocFactory)
     delete m_pRelocFactory;
-  if(m_pGOT)
+  if (NULL != m_pGOT)
     delete m_pGOT;
-  if(m_pPLT)
+  if (NULL != m_pPLT)
     delete m_pPLT;
-  if(m_pRelDyn)
+  if (NULL != m_pRelDyn)
     delete m_pRelDyn;
-  if(m_pRelPLT)
+  if (NULL != m_pRelPLT)
     delete m_pRelPLT;
-  if(m_pDynamic)
+  if (NULL != m_pDynamic)
     delete m_pDynamic;
 }
 
@@ -85,12 +85,12 @@
  // FIXME: Currently we set exidx and extab to "Exception" and directly emit
  // them from input
   m_pEXIDX        = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx",
-                                                      LDFileFormat::Exception,
+                                                      LDFileFormat::Target,
                                                       llvm::ELF::SHT_ARM_EXIDX,
                                                       llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
                                                       bitclass() / 8);
   m_pEXTAB        = &pLinker.getOrCreateOutputSectHdr(".ARM.extab",
-                                                      LDFileFormat::Exception,
+                                                      LDFileFormat::Target,
                                                       llvm::ELF::SHT_PROGBITS,
                                                       llvm::ELF::SHF_ALLOC,
                                                       0x1);
@@ -101,7 +101,7 @@
                                                       0x1);
 }
 
-void ARMGNULDBackend::initTargetSymbols(MCLinker& pLinker)
+void ARMGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
@@ -122,7 +122,7 @@
                                   MCLinker& pLinker)
 {
   // when building shared object, the .got section is must.
-  if(pOutput.type() == Output::DynObj && (NULL == m_pGOT)) {
+  if (pOutput.type() == Output::DynObj && (NULL == m_pGOT)) {
       createARMGOT(pLinker, pOutput);
   }
 }
@@ -131,11 +131,7 @@
                                    const MCLDInfo& pInfo,
                                    MCLinker& pLinker)
 {
-  // emit program headers
-  if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
-    emitProgramHdrs(pLinker.getLDInfo().output());
-
-  ELFFileFormat *file_format = getOutputFormat(pOutput);
+  const ELFFileFormat *file_format = getOutputFormat(pOutput);
 
   // apply PLT
   if (file_format->hasPLT()) {
@@ -177,11 +173,6 @@
   return *m_pDynamic;
 }
 
-bool ARMGNULDBackend::isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const
-{
-  return (pOutput.type() == Output::DynObj);
-}
-
 void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput)
 {
   // get .got LDSection and create MCSectionData
@@ -191,7 +182,7 @@
   m_pGOT = new ARMGOT(got, pLinker.getOrCreateSectData(got));
 
   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
-  if( m_pGOTSymbol != NULL ) {
+  if (m_pGOTSymbol != NULL) {
     pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
@@ -249,62 +240,73 @@
                                      8);
 }
 
-ELFFileFormat* ARMGNULDBackend::getOutputFormat(const Output& pOutput) const
+void ARMGNULDBackend::addCopyReloc(ResolveInfo& pSym)
 {
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      return getDynObjFileFormat();
-    case Output::Exec:
-      return getExecFileFormat();
-    // FIXME: We do not support building .o now
-    case Output::Object:
-    default:
-      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
-                               llvm::Twine(pOutput.type()));
-      return NULL;
+  bool exist;
+  Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
+  rel_entry.setType(llvm::ELF::R_ARM_COPY);
+  assert(pSym.outSymbol()->hasFragRef());
+  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
+  rel_entry.setSymInfo(&pSym);
+}
+
+LDSymbol& ARMGNULDBackend::defineSymbolforCopyReloc(MCLinker& pLinker,
+                                                    const ResolveInfo& pSym)
+{
+  // For a symbol needing copy relocation, define a copy symbol in the BSS
+  // section and all other reference to this symbol should refer to this
+  // copy.
+
+  // get or create corresponding BSS LDSection
+  LDSection* bss_sect_hdr = NULL;
+  if (ResolveInfo::ThreadLocal == pSym.type()) {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
+                                   ".tbss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
   }
-}
+  else {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+  }
 
-bool ARMGNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym,
-                                       const MCLDInfo& pLDInfo,
-                                       const Output& pOutput) const
-{
-  return (Output::DynObj == pOutput.type() &&
-          ResolveInfo::Function == pSym.type() &&
-          (pSym.isDyn() || pSym.isUndef() ||
-            isSymbolPreemptible(pSym, pLDInfo, pOutput)));
-}
+  // get or create corresponding BSS MCSectionData
+  assert(NULL != bss_sect_hdr);
+  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(
+                                     *bss_sect_hdr);
 
-bool ARMGNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym,
-                                          const Output& pOutput,
-                                          bool isAbsReloc) const
-{
-  if(pSym.isUndef() && (Output::Exec == pOutput.type()))
-    return false;
-  if(pSym.isAbsolute())
-    return false;
-  if(Output::DynObj == pOutput.type() && isAbsReloc)
-    return true;
-  if(pSym.isDyn() || pSym.isUndef())
-    return true;
+  // Determine the alignment by the symbol value
+  // FIXME: here we use the largest alignment
+  uint32_t addralign = bitclass() / 8;
 
-  return false;
-}
+  // allocate space in BSS for the copy symbol
+  llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, pSym.size());
+  uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                     bss_section,
+                                                     addralign);
+  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
 
-bool ARMGNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
-                                          const MCLDInfo& pLDInfo,
-                                          const Output& pOutput) const
-{
-  if(pSym.other() != ResolveInfo::Default)
-    return false;
+  // change symbol binding to Global if it's a weak symbol
+  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
+  if (binding == ResolveInfo::Weak)
+    binding = ResolveInfo::Global;
 
-  if(Output::DynObj != pOutput.type())
-    return false;
+  // Define the copy symbol in the bss section and resolve it
+  LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+                      pSym.name(),
+                      false,
+                      (ResolveInfo::Type)pSym.type(),
+                      ResolveInfo::Define,
+                      binding,
+                      pSym.size(),  // size
+                      0x0,          // value
+                      pLinker.getLayout().getFragmentRef(*frag, 0x0),
+                      (ResolveInfo::Visibility)pSym.other());
 
-  if(pLDInfo.options().Bsymbolic())
-    return false;
-
-  return true;
+  return *cpy_sym;
 }
 
 /// checkValidReloc - When we attempt to generate a dynamic relocation for
@@ -314,7 +316,7 @@
                                       const Output& pOutput) const
 {
   // If not building a PIC object, no relocation type is invalid
-  if (!isPIC(pLDInfo, pOutput))
+  if (!isOutputPIC(pOutput, pLDInfo))
     return;
 
   switch(pReloc.type()) {
@@ -331,13 +333,8 @@
       break;
 
     default:
-      llvm::report_fatal_error(llvm::Twine("Attempt to generate unsupported") +
-                               llvm::Twine(" relocation type ") +
-                               llvm::Twine((int)pReloc.type()) +
-                               llvm::Twine(" for symbol '") +
-                               llvm::Twine(pReloc.symInfo()->name()) +
-                               llvm::Twine("', recompile with -fPIC")
-                              );
+      error(diag::non_pic_relocation) << (int)pReloc.type()
+                                      << pReloc.symInfo()->name();
       break;
   }
 }
@@ -347,7 +344,7 @@
                                    const Layout& pLayout) const
 {
   // Update value keep in addend if we meet a section symbol
-  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
     pReloc.setAddend(pLayout.getOutputOffset(
                      *pInputSym.fragRef()) + pReloc.addend());
   }
@@ -368,6 +365,8 @@
 
     // Set R_ARM_TARGET1 to R_ARM_ABS32
     // Ref: GNU gold 1.11 arm.cc, line 9892
+    // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
+    // or --target1-rel
     case llvm::ELF::R_ARM_TARGET1:
        pReloc.setType(llvm::ELF::R_ARM_ABS32);
     case llvm::ELF::R_ARM_ABS32:
@@ -375,13 +374,13 @@
       // If buiding PIC object (shared library or PIC executable),
       // a dynamic relocations with RELATIVE type to this location is needed.
       // Reserve an entry in .rel.dyn
-      if(isPIC(pLDInfo, pOutput)) {
-        // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+      if (isOutputPIC(pOutput, pLDInfo)) {
+        //create .rel.dyn section if not exist
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set Rel bit
-        rsym->setReserved(rsym->reserved() | 0x1u);
+        rsym->setReserved(rsym->reserved() | ReserveRel);
         }
       return;
     }
@@ -395,53 +394,41 @@
     case llvm::ELF::R_ARM_MOVT_ABS:
     case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
     case llvm::ELF::R_ARM_THM_MOVT_ABS: {
-      // Update value keep in relocation place if we meet a section symbol
-      if(rsym->type() == ResolveInfo::Section) {
-        pReloc.target() = pLinker.getLayout().getOutputOffset(
-                            *pInputSym.fragRef()) + pReloc.target();
-      }
-
-      // If building PIC object (shared library or PIC executable),
-      // a dynamic relocation for this location is needed.
-      // Reserve an entry in .rel.dyn
-      if(isPIC(pLDInfo, pOutput)) {
-        checkValidReloc(pReloc, pLDInfo, pOutput);
-        // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
-          createARMRelDyn(pLinker, pOutput);
-        m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | 0x1u);
+      // PIC code should not contain these kinds of relocation
+      if (isOutputPIC(pOutput, pLDInfo)) {
+        error(diag::non_pic_relocation) << (int)pReloc.type()
+                                        << pReloc.symInfo()->name();
       }
       return;
     }
     case llvm::ELF::R_ARM_GOTOFF32:
     case llvm::ELF::R_ARM_GOTOFF12: {
       // A GOT section is needed
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
       return;
     }
 
     // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
     // Ref: GNU gold 1.11 arm.cc, line 9892
+    // FIXME: R_ARM_TARGET2 should be set by option --target2
     case llvm::ELF::R_ARM_TARGET2:
       pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
     case llvm::ELF::R_ARM_GOT_BREL:
     case llvm::ELF::R_ARM_GOT_PREL: {
       // A GOT entry is needed for these relocation type.
       // return if we already create GOT for this symbol
-      if(rsym->reserved() & 0x6u)
+      if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
       m_pGOT->reserveEntry();
       // If building PIC object, a dynamic relocation with
       // type RELATIVE is needed to relocate this GOT entry.
       // Reserve an entry in .rel.dyn
-      if(isPIC(pLDInfo, pOutput)) {
+      if (isOutputPIC(pOutput, pLDInfo)) {
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
@@ -456,12 +443,9 @@
     case llvm::ELF::R_ARM_BASE_PREL: {
       // FIXME: Currently we only support R_ARM_BASE_PREL against
       // symbol _GLOBAL_OFFSET_TABLE_
-      if(rsym != m_pGOTSymbol->resolveInfo()) {
-        llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
-                                 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
-                                 llvm::Twine(rsym->name()) +
-                                 llvm::Twine(".'"));
-      }
+      if (rsym != m_pGOTSymbol->resolveInfo())
+        fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
+                                     << "[email protected]";
       return;
     }
     case llvm::ELF::R_ARM_COPY:
@@ -470,9 +454,7 @@
     case llvm::ELF::R_ARM_RELATIVE: {
       // These are relocation type for dynamic linker, shold not
       // appear in object file.
-      llvm::report_fatal_error(llvm::Twine("unexpected reloc ") +
-                               llvm::Twine((int)pReloc.type()) +
-                               llvm::Twine(" in object file"));
+      fatal(diag::dynamic_relocation) << (int)pReloc.type();
       break;
     }
     default: {
@@ -494,6 +476,8 @@
 
     // Set R_ARM_TARGET1 to R_ARM_ABS32
     // Ref: GNU gold 1.11 arm.cc, line 9892
+    // FIXME: R_ARM_TARGET1 should be set by option --target1-rel
+    // or --target1-rel
     case llvm::ELF::R_ARM_TARGET1:
       pReloc.setType(llvm::ELF::R_ARM_ABS32);
     case llvm::ELF::R_ARM_ABS32:
@@ -509,14 +493,14 @@
     case llvm::ELF::R_ARM_ABS32_NOI: {
       // Absolute relocation type, symbol may needs PLT entry or
       // dynamic relocation entry
-      if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
         // create plt for this symbol if it does not have one
-        if(!(rsym->reserved() & 0x8u)){
+        if (!(rsym->reserved() & ReservePLT)){
           // Create .got section if it doesn't exist
-          if(NULL == m_pGOT)
+          if (NULL == m_pGOT)
             createARMGOT(pLinker, pOutput);
           // create .plt and .rel.plt if not exist
-          if(NULL == m_pPLT)
+          if (NULL == m_pPLT)
             createARMPLTandRelPLT(pLinker, pOutput);
           // Symbol needs PLT entry, we need to reserve a PLT entry
           // and the corresponding GOT and dynamic relocation entry
@@ -525,19 +509,27 @@
           m_pPLT->reserveEntry();
           m_pRelPLT->reserveEntry(*m_pRelocFactory);
           // set PLT bit
-          rsym->setReserved(rsym->reserved() | 0x8u);
+          rsym->setReserved(rsym->reserved() | ReservePLT);
         }
       }
 
-      if(isSymbolNeedsDynRel(*rsym, pOutput, true)) {
-        checkValidReloc(pReloc, pLDInfo, pOutput);
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                            pLDInfo, pOutput, true)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | 0x1u);
+        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
+                          pOutput)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          checkValidReloc(pReloc, pLDInfo, pOutput);
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+        }
       }
       return;
     }
@@ -545,19 +537,20 @@
     case llvm::ELF::R_ARM_GOTOFF32:
     case llvm::ELF::R_ARM_GOTOFF12: {
       // A GOT section is needed
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
       return;
     }
 
     case llvm::ELF::R_ARM_BASE_PREL:
-      // FIXME: Currently we only support R_ARM_BASE_PREL against
+    case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
+    case llvm::ELF::R_ARM_THM_MOVW_BREL:
+    case llvm::ELF::R_ARM_THM_MOVT_BREL:
+      // FIXME: Currently we only support these relocations against
       // symbol _GLOBAL_OFFSET_TABLE_
-      if(rsym != m_pGOTSymbol->resolveInfo()) {
-        llvm::report_fatal_error(llvm::Twine("Do not support relocation '") +
-                                 llvm::Twine("R_ARM_BASE_PREL' against symbol '") +
-                                 llvm::Twine(rsym->name()) +
-                                 llvm::Twine(".'"));
+      if (rsym != m_pGOTSymbol->resolveInfo()) {
+        fatal(diag::base_relocation) << (int)pReloc.type() << rsym->name()
+                                     << "[email protected]";
       }
     case llvm::ELF::R_ARM_REL32:
     case llvm::ELF::R_ARM_LDR_PC_G0:
@@ -599,19 +592,25 @@
     case llvm::ELF::R_ARM_LDC_SB_G2:
     case llvm::ELF::R_ARM_MOVW_BREL_NC:
     case llvm::ELF::R_ARM_MOVT_BREL:
-    case llvm::ELF::R_ARM_MOVW_BREL:
-    case llvm::ELF::R_ARM_THM_MOVW_BREL_NC:
-    case llvm::ELF::R_ARM_THM_MOVT_BREL:
-    case llvm::ELF::R_ARM_THM_MOVW_BREL: {
+    case llvm::ELF::R_ARM_MOVW_BREL: {
       // Relative addressing relocation, may needs dynamic relocation
-      if(isSymbolNeedsDynRel(*rsym, pOutput, false)) {
-        checkValidReloc(pReloc, pLDInfo, pOutput);
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                            pLDInfo, pOutput, false)) {
+        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | 0x1u);
+        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
+                          pOutput)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          checkValidReloc(pReloc, pLDInfo, pOutput);
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+        }
       }
       return;
     }
@@ -631,22 +630,22 @@
       // A PLT entry is needed when building shared library
 
       // return if we already create plt for this symbol
-      if(rsym->reserved() & 0x8u)
+      if (rsym->reserved() & ReservePLT)
         return;
 
       // if symbol is defined in the ouput file and it's not
       // preemptible, no need plt
-      if(rsym->isDefine() && !rsym->isDyn() &&
+      if (rsym->isDefine() && !rsym->isDyn() &&
          !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
         return;
       }
 
       // Create .got section if it doesn't exist
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
 
       // create .plt and .rel.plt if not exist
-      if(NULL == m_pPLT)
+      if (NULL == m_pPLT)
          createARMPLTandRelPLT(pLinker, pOutput);
       // Symbol needs PLT entry, we need to reserve a PLT entry
       // and the corresponding GOT and dynamic relocation entry
@@ -655,12 +654,13 @@
       m_pPLT->reserveEntry();
       m_pRelPLT->reserveEntry(*m_pRelocFactory);
       // set PLT bit
-      rsym->setReserved(rsym->reserved() | 0x8u);
+      rsym->setReserved(rsym->reserved() | ReservePLT);
       return;
     }
 
     // Set R_ARM_TARGET2 to R_ARM_GOT_PREL
     // Ref: GNU gold 1.11 arm.cc, line 9892
+    // FIXME: R_ARM_TARGET2 should be set by option --target2
     case llvm::ELF::R_ARM_TARGET2:
       pReloc.setType(llvm::ELF::R_ARM_GOT_PREL);
     case llvm::ELF::R_ARM_GOT_BREL:
@@ -668,25 +668,25 @@
     case llvm::ELF::R_ARM_GOT_PREL: {
       // Symbol needs GOT entry, reserve entry in .got
       // return if we already create GOT for this symbol
-      if(rsym->reserved() & 0x6u)
+      if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createARMGOT(pLinker, pOutput);
       m_pGOT->reserveEntry();
       // If building shared object or the symbol is undefined, a dynamic
       // relocation is needed to relocate this GOT entry. Reserve an
       // entry in .rel.dyn
-      if(Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
+      if (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createARMRelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
-        rsym->setReserved(rsym->reserved() | 0x4u);
+        rsym->setReserved(rsym->reserved() | GOTRel);
         return;
       }
       // set GOT bit
-      rsym->setReserved(rsym->reserved() | 0x2u);
+      rsym->setReserved(rsym->reserved() | ReserveGOT);
       return;
     }
 
@@ -696,9 +696,7 @@
     case llvm::ELF::R_ARM_RELATIVE: {
       // These are relocation type for dynamic linker, shold not
       // appear in object file.
-      llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") +
-                               llvm::Twine((int)pReloc.type()) +
-                               llvm::Twine(" in object file"));
+      fatal(diag::dynamic_relocation) << (int)pReloc.type();
       break;
     }
     default: {
@@ -711,12 +709,21 @@
                                      const LDSymbol& pInputSym,
                                      MCLinker& pLinker,
                                      const MCLDInfo& pLDInfo,
-                                     const Output& pOutput)
+                                     const Output& pOutput,
+                                     const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
 
+  assert(NULL != pSection.getLink());
+  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
+    if (rsym->isLocal()) {
+      updateAddend(pReloc, pInputSym, pLinker.getLayout());
+    }
+    return;
+  }
+
   // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
   // entries should be created.
   // FIXME: Below judgements concern only .so is generated as output
@@ -724,14 +731,14 @@
 
   // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section
   // is needed
-  if(NULL == m_pGOT && NULL != m_pGOTSymbol) {
-    if(rsym == m_pGOTSymbol->resolveInfo()) {
+  if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
+    if (rsym == m_pGOTSymbol->resolveInfo()) {
       createARMGOT(pLinker, pOutput);
     }
   }
 
   // rsym is local
-  if(rsym->isLocal())
+  if (rsym->isLocal())
     scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
 
   // rsym is external
@@ -743,25 +750,54 @@
 uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput,
                                           const LDSection& pSection,
                                           const MCLDInfo& pInfo,
+                                          const Layout& pLayout,
                                           MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
-  if (&pSection == m_pAttributes) {
-    // FIXME: Currently Emitting .ARM.attributes directly from the input file.
+  if (&pSection == m_pAttributes ||
+      &pSection == m_pEXIDX ||
+      &pSection == m_pEXTAB) {
+    // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
+    // directly from the input file.
     const llvm::MCSectionData* sect_data = pSection.getSectionData();
-    assert(sect_data &&
-           "Emit .ARM.attribute failed, MCSectionData doesn't exist!");
-
-    uint8_t* start =
-              llvm::cast<MCRegionFragment>(
-                     sect_data->getFragmentList().front()).getRegion().start();
-
-    memcpy(pRegion.start(), start, pRegion.size());
+    llvm::MCSectionData::const_iterator frag_iter, frag_end = sect_data->end();
+    uint8_t* out_offset = pRegion.start();
+    for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
+      size_t size = computeFragmentSize(pLayout, *frag_iter);
+      switch(frag_iter->getKind()) {
+        case llvm::MCFragment::FT_Region: {
+          const MCRegionFragment& region_frag =
+            llvm::cast<MCRegionFragment>(*frag_iter);
+          const uint8_t* start = region_frag.getRegion().start();
+          memcpy(out_offset, start, size);
+          break;
+        }
+        case llvm::MCFragment::FT_Align: {
+          llvm::MCAlignFragment& align_frag =
+            llvm::cast<llvm::MCAlignFragment>(*frag_iter);
+          uint64_t count = size / align_frag.getValueSize();
+          switch (align_frag.getValueSize()) {
+            case 1u:
+              std::memset(out_offset, align_frag.getValue(), count);
+              break;
+            default:
+              llvm::report_fatal_error(
+                "unsupported value size for align fragment emission yet.\n");
+              break;
+          } // end switch
+          break;
+        }
+        default:
+          llvm::report_fatal_error("unsupported fragment type.\n");
+          break;
+      } // end switch
+      out_offset += size;
+    } // end for
     return pRegion.size();
-  }
+  } // end if
 
   if (&pSection == &(file_format->getPLT())) {
     assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
@@ -774,116 +810,15 @@
     uint64_t result = m_pGOT->emit(pRegion);
     return result;
   }
-
-  llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
-                           pSection.name() +
-                           llvm::Twine("'.\n"));
+  fatal(diag::unrecognized_output_sectoin)
+          << pSection.name()
+          << "[email protected]";
   return 0x0;
 }
 
 /// finalizeSymbol - finalize the symbol value
-/// If the symbol's reserved field is not zero, MCLinker will call back this
-/// function to ask the final value of the symbol
-bool ARMGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+bool ARMGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
-  return false;
-}
-
-/// allocateCommonSymbols - allocate common symbols in the corresponding
-/// sections.
-/// @refer Google gold linker: common.cc: 214
-bool
-ARMGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
-{
-  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
-
-  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
-    return true;
-
-  // addralign := max value of all common symbols
-  uint64_t addralign = 0x0;
-
-  // Due to the visibility, some common symbols may be forcefully local.
-  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      if ((*com_sym)->value() > addralign)
-        addralign = (*com_sym)->value();
-    }
-  }
-
-  // global common symbols.
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    if ((*com_sym)->value() > addralign)
-      addralign = (*com_sym)->value();
-  }
-
-  // FIXME: If the order of common symbols is defined, then sort common symbols
-  // com_sym = symbol_list.commonBegin();
-  // std::sort(com_sym, com_end, some kind of order);
-
-  // get or create corresponding BSS LDSection
-  LDSection* bss_sect_hdr = NULL;
-  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
-                                   ".tbss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
-  else {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
-
-  // get or create corresponding BSS MCSectionData
-  assert(NULL != bss_sect_hdr);
-  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
-
-  // allocate all common symbols
-  uint64_t offset = bss_sect_hdr->size();
-
-  // allocate all local common symbols
-  com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      // We have to reset the description of the symbol here. When doing
-      // incremental linking, the output relocatable object may have common
-      // symbols. Therefore, we can not treat common symbols as normal symbols
-      // when emitting the regular name pools. We must change the symbols'
-      // description here.
-      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-      uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                         bss_section,
-                                                         (*com_sym)->value());
-      offset += size;
-    }
-  }
-
-  // allocate all global common symbols
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    // We have to reset the description of the symbol here. When doing
-    // incremental linking, the output relocatable object may have common
-    // symbols. Therefore, we can not treat common symbols as normal symbols
-    // when emitting the regular name pools. We must change the symbols'
-    // description here.
-    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-    uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                       bss_section,
-                                                       (*com_sym)->value());
-    offset += size;
-  }
-
-  bss_sect_hdr->setSize(offset);
-  symbol_list.changeCommonsToGlobal();
   return true;
 }
 
@@ -910,9 +845,20 @@
 
   llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
 
-  new MCRegionFragment(*region, &sect_data);
+  llvm::MCFragment* frag = NULL;
+  if (NULL == region) {
+    // If the input section's size is zero, we got a NULL region.
+    // use a virtual fill fragment
+    frag = new llvm::MCFillFragment(0x0, 0, 0);
+  }
+  else
+    frag = new MCRegionFragment(*region);
 
-  out_sect.setSize(out_sect.size() + pInputSectHdr.size());
+  uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                     sect_data,
+                                                     pInputSectHdr.align());
+
+  out_sect.setSize(out_sect.size() + size);
   return true;
 }
 
@@ -966,16 +912,25 @@
 
 unsigned int
 ARMGNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr) const
+                                       const LDSection& pSectHdr,
+                                       const MCLDInfo& pInfo) const
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
-  if (&pSectHdr == &file_format->getGOT())
+  if (&pSectHdr == &file_format->getGOT()) {
+    if (pInfo.options().hasNow())
+      return SHO_RELRO_LAST;
     return SHO_DATA;
+  }
 
   if (&pSectHdr == &file_format->getPLT())
     return SHO_PLT;
 
+  if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) {
+    // put ARM.exidx and ARM.extab in the same order of .eh_frame
+    return SHO_EXCEPTION;
+  }
+
   return SHO_UNDEFINED;
 }
 
@@ -1014,4 +969,6 @@
 extern "C" void LLVMInitializeARMLDBackend() {
   // Register the linker backend
   mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend);
+  mcld::TargetRegistry::RegisterTargetLDBackend(TheThumbTarget, createARMLDBackend);
 }
+
diff --git a/lib/Target/ARM/ARMLDBackend.h b/lib/Target/ARM/ARMLDBackend.h
index 27acdf1..3e46cd7 100644
--- a/lib/Target/ARM/ARMLDBackend.h
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -86,7 +86,7 @@
   void initTargetSections(MCLinker& pLinker);
 
   /// initTargetSymbols - initialize target dependent symbols in output.
-  void initTargetSymbols(MCLinker& pLinker);
+  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// initRelocFactory - create and initialize RelocationFactory
   bool initRelocFactory(const MCLinker& pLinker);
@@ -104,7 +104,8 @@
                       const LDSymbol& pInputSym,
                       MCLinker& pLinker,
                       const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+                      const Output& pOutput,
+                      const LDSection& pSection);
 
   uint32_t machine() const
   { return llvm::ELF::EM_ARM; }
@@ -127,6 +128,9 @@
   unsigned int bitclass() const
   { return 32; }
 
+  uint64_t defaultTextSegmentAddr() const
+  { return 0x8000; }
+
   /// doPreLayout - Backend can do any needed modification before layout
   void doPreLayout(const Output& pOutput,
                    const MCLDInfo& pInfo,
@@ -160,11 +164,13 @@
   /// @param pOutput - the output file
   /// @param pSection - the given LDSection
   /// @param pInfo - all options in the command line.
+  /// @param pLayout - for comouting the size of fragment
   /// @param pRegion - the region to write out data
   /// @return the size of the table in the file.
   uint64_t emitSectionData(const Output& pOutput,
                            const LDSection& pSection,
                            const MCLDInfo& pInfo,
+                           const Layout& pLayout,
                            MemoryRegion& pRegion) const;
 
   ARMGOT& getGOT();
@@ -185,29 +191,17 @@
 
   /// getTargetSectionOrder - compute the layout order of ARM target sections
   unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr) const;
+                                     const LDSection& pSectHdr,
+                                     const MCLDInfo& pInfo) const;
 
-  /// finalizeSymbol - finalize the symbol value
-  /// If the symbol's reserved field is not zero, MCLinker will call back this
-  /// function to ask the final value of the symbol
-  bool finalizeSymbol(LDSymbol& pSymbol) const;
-
-  /// allocateCommonSymbols - allocate common symbols in the corresponding
-  /// sections.
-  bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
+  /// finalizeTargetSymbols - finalize the symbol value
+  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// readSection - read target dependent sections
   bool readSection(Input& pInput,
                    MCLinker& pLinker,
                    LDSection& pInputSectHdr);
 
-public:
-  bool isSymbolPreemptible(const ResolveInfo& pSym,
-                           const MCLDInfo& pLDInfo,
-                           const Output& pOutput) const;
-
-  bool isPIC(const MCLDInfo& pLDInfo, const Output& pOutput) const;
-
 private:
   void scanLocalReloc(Relocation& pReloc,
                       const LDSymbol& pInputSym,
@@ -221,19 +215,20 @@
                        const MCLDInfo& pLDInfo,
                        const Output& pOutput);
 
-  bool isSymbolNeedsPLT(const ResolveInfo& pSym,
-                        const MCLDInfo& pLDInfo,
-                        const Output& pOutput) const;
-
-  bool isSymbolNeedsDynRel(const ResolveInfo& pSym,
-                           const Output& pOutput,
-                           bool isAbsReloc) const;
-
-
   void checkValidReloc(Relocation& pReloc,
                        const MCLDInfo& pLDInfo,
                        const Output& pOutput) const;
 
+  /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
+  /// @param pSym - A resolved copy symbol that defined in BSS section
+  void addCopyReloc(ResolveInfo& pSym);
+
+  /// defineSymbolforCopyReloc - allocate a space in BSS section and
+  /// and force define the copy of pSym to BSS section
+  /// @return the output LDSymbol of the copy symbol
+  LDSymbol& defineSymbolforCopyReloc(MCLinker& pLinker,
+                                     const ResolveInfo& pSym);
+
   /// updateAddend - update addend value of the relocation if the
   /// the target symbol is a section symbol. Addend is the offset
   /// in the section. This value should be updated after section
@@ -251,8 +246,6 @@
 
   void createARMRelDyn(MCLinker& pLinker, const Output& pOutput);
 
-  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
-
 private:
   RelocationFactory* m_pRelocFactory;
   ARMGOT* m_pGOT;
@@ -294,3 +287,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
index b3461d0..5528ef7 100644
--- a/lib/Target/ARM/ARMPLT.cpp
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -9,8 +9,8 @@
 #include "ARMGOT.h"
 #include "ARMPLT.h"
 #include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
@@ -65,7 +65,7 @@
     plt1_entry = new (std::nothrow) ARMPLT1(&m_SectionData);
 
     if (!plt1_entry)
-      llvm::report_fatal_error("Allocating new memory for ARMPLT1 failed!");
+      fatal(diag::fail_allocate_memory) << "ARMPLT1";
 
     m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
 
@@ -167,7 +167,7 @@
   data = static_cast<uint32_t*>(malloc(plt0->getEntrySize()));
 
   if (!data)
-    llvm::report_fatal_error("Allocating new memory for plt0 failed!");
+    fatal(diag::fail_allocate_memory) << "plt0";
 
   memcpy(data, arm_plt0, plt0->getEntrySize());
   data[4] = offset;
@@ -204,7 +204,7 @@
     Out = static_cast<uint32_t*>(malloc(plt1->getEntrySize()));
 
     if (!Out)
-      llvm::report_fatal_error("Allocating new memory for plt1 failed!");
+      fatal(diag::fail_allocate_memory) << "plt1";
 
     // Offset is the distance between the last PLT entry and the associated
     // GOT entry.
@@ -247,3 +247,4 @@
   }
   return result;
 }
+
diff --git a/lib/Target/ARM/ARMPLT.h b/lib/Target/ARM/ARMPLT.h
index 11d0bd0..f55aaa3 100644
--- a/lib/Target/ARM/ARMPLT.h
+++ b/lib/Target/ARM/ARMPLT.h
@@ -84,3 +84,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMRelocationFactory.cpp b/lib/Target/ARM/ARMRelocationFactory.cpp
index 2763b3b..4911658 100644
--- a/lib/Target/ARM/ARMRelocationFactory.cpp
+++ b/lib/Target/ARM/ARMRelocationFactory.cpp
@@ -8,11 +8,12 @@
 //===--------------------------------------------------------------------===//
 
 #include <llvm/ADT/Twine.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <llvm/Support/DataTypes.h>
 #include <llvm/Support/ELF.h>
+#include <llvm/Support/Host.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/LD/Layout.h>
+#include <mcld/Support/MsgHandling.h>
 
 #include "ARMRelocationFactory.h"
 #include "ARMRelocationFunctions.h"
@@ -38,10 +39,8 @@
 {
   Relocation::Type type = pRelocation.type();
   if (type > 130) { // 131-255 doesn't noted in ARM spec
-    llvm::report_fatal_error(llvm::Twine("Unknown relocation type. "
-                                         "To symbol `") +
-                             pRelocation.symInfo()->name() +
-                             llvm::Twine("'."));
+    fatal(diag::unknown_relocation) << (int)type
+                                    << pRelocation.symInfo()->name();
     return;
   }
 
@@ -70,29 +69,18 @@
     return;
   }
   if (Overflow == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' causes overflow. on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_overflow) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
-
   if (BadReloc == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' encounters unexpected opcode. "
-                                         "on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_badreloc) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
   if (Unsupport == result) {
-    llvm::report_fatal_error(llvm::Twine("Encounter unsupported relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    fatal(diag::unsupported_relocation) << type
+                                        << "[email protected]";
     return;
   }
 }
@@ -106,7 +94,7 @@
   // Set thumb bit if
   // - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
   RelocationFactory::DWord thumbBit =
-       ((pReloc.symInfo()->desc() != ResolveInfo::Undefined) &&
+       ((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
         (pReloc.symInfo()->type() == ResolveInfo::Function) &&
         ((pReloc.symValue() & 0x1) != 0))?
         1:0;
@@ -144,11 +132,11 @@
                           const ARMRelocationFactory& pFactory)
 {
   // if symbol is dynamic or undefine or preemptible
-  if(pSym.isDyn() ||
-     pSym.isUndef() ||
-     pFactory.getTarget().isSymbolPreemptible(pSym,
-                                              pLDInfo,
-                                              pLDInfo.output()))
+  if (pSym.isDyn() ||
+      pSym.isUndef() ||
+      pFactory.getTarget().isSymbolPreemptible(pSym,
+                                               pLDInfo,
+                                               pLDInfo.output()))
     return false;
   return true;
 }
@@ -176,7 +164,7 @@
       Relocation& rel_entry =
         *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
       assert(!exist && "GOT entry not exist, but DynRel entry exist!");
-      if( rsym->isLocal() ||
+      if ( rsym->isLocal() ||
           helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
         // Initialize got entry to target symbol address
         got_entry.setContent(pReloc.symValue());
@@ -192,7 +180,7 @@
       rel_entry.targetRef().assign(got_entry);
     }
     else {
-      llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+      fatal(diag::reserve_entry_number_mismatch) << "GOT";
     }
   }
   return got_entry;
@@ -239,7 +227,7 @@
       rel_entry.setSymInfo(rsym);
     }
     else {
-      llvm::report_fatal_error("No PLT entry reserved for PLT type relocation!");
+      fatal(diag::reserve_entry_number_mismatch) << "PLT";
     }
   }
   return plt_entry;
@@ -279,7 +267,7 @@
   rel_entry.setType(pType);
   rel_entry.targetRef() = pReloc.targetRef();
 
-  if(pType == llvm::ELF::R_ARM_RELATIVE)
+  if (pType == llvm::ELF::R_ARM_RELATIVE)
     rel_entry.setSymInfo(0);
   else
     rel_entry.setSymInfo(rsym);
@@ -307,13 +295,17 @@
 static ARMRelocationFactory::DWord
 helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
 {
-  // TODO: By the rsloader experience: If we use 32bit, we need to consider
-  // endianness problem. We'd better have a thumb instruction type.
+  // Consider the endianness problem, get the target data value from lower
+  // and upper 16 bits
+  ARMRelocationFactory::DWord val =
+    (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) |
+    *(reinterpret_cast<uint16_t*>(&pTarget) + 1);
+
   // imm16: [19-16][26][14-12][7-0]
-  return helper_sign_extend((((pTarget >> 4) & 0xf000U) |
-                             ((pTarget >> 15) & 0x0800U) |
-                             ((pTarget >> 4) & 0x0700U) |
-                             (pTarget & 0x00ffU)),
+  return helper_sign_extend((((val >> 4) & 0xf000U) |
+                             ((val >> 15) & 0x0800U) |
+                             ((val >> 4) & 0x0700U) |
+                             (val & 0x00ffU)),
                             16);
 }
 
@@ -321,15 +313,19 @@
 helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
                                        ARMRelocationFactory::DWord pImm)
 {
-  // TODO: By the rsloader experience: If we use 32bit, we need to consider
-  // endianness problem. We'd better have a thumb instruction type.
+  ARMRelocationFactory::DWord val;
   // imm16: [19-16][26][14-12][7-0]
   pTarget &= 0xfbf08f00U;
   pTarget |= (pImm & 0xf000U) << 4;
   pTarget |= (pImm & 0x0800U) << 15;
   pTarget |= (pImm & 0x0700U) << 4;
   pTarget |= (pImm & 0x00ffU);
-  return pTarget;
+
+  // Consider the endianness problem, write back data from lower and
+  // upper 16 bits
+  val = (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) |
+        *(reinterpret_cast<uint16_t*>(&pTarget) + 1);
+  return val;
 }
 
 static ARMRelocationFactory::DWord
@@ -408,13 +404,27 @@
   ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   ARMRelocationFactory::DWord S = pReloc.symValue();
 
-  if(rsym->isLocal() && (rsym->reserved() & 0x1u)) {
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    pReloc.target() = (S + A) | T;
+    return ARMRelocationFactory::OK;
+  }
+
+  // A local symbol may need REL Type dynamic relocation
+  if (rsym->isLocal() && (rsym->reserved() & ARMGNULDBackend::ReserveRel)) {
     helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
     pReloc.target() = (S + A) | T ;
     return ARMRelocationFactory::OK;
   }
-  else if(!rsym->isLocal()) {
-    if(rsym->reserved() & 0x8u) {
+
+  // An external symbol may need PLT and dynamic relocation
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
       T = 0 ; // PLT is not thumb
       pReloc.target() = (S + A) | T;
@@ -422,8 +432,8 @@
     // If we generate a dynamic relocation (except R_ARM_RELATIVE)
     // for a place, we should not perform static relocation on it
     // in order to keep the addend store in the place correct.
-    if(rsym->reserved() & 0x1u) {
-      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+    if (rsym->reserved() & ARMGNULDBackend::ReserveRel) {
+      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
         helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
       }
       else {
@@ -433,6 +443,7 @@
     }
   }
 
+
   // perform static relocation
   pReloc.target() = (S + A) | T;
   return ARMRelocationFactory::OK;
@@ -481,7 +492,8 @@
                                       const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
-  if(!(pReloc.symInfo()->reserved() & 0x6u)) {
+  if (!(pReloc.symInfo()->reserved() &
+      (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
     return ARMRelocationFactory::BadReloc;
   }
   ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
@@ -497,7 +509,8 @@
                                       const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
-  if(!(pReloc.symInfo()->reserved() & 0x6u)) {
+  if (!(pReloc.symInfo()->reserved() &
+      (ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
     return ARMRelocationFactory::BadReloc;
   }
   ARMRelocationFactory::Address GOT_S   = helper_GOT(pReloc, pLDInfo, pParent);
@@ -515,18 +528,23 @@
                                   const MCLDInfo& pLDInfo,
                                   ARMRelocationFactory& pParent)
 {
-  // TODO: Some issue have not been considered, e.g. thumb, overflow?
+  // TODO: Some issue have not been considered:
+  // 1. Add stub when switching mode or jump target too far
+  // 2. We assume the blx is available
 
   // If target is undefined weak symbol, we only need to jump to the
-  // next instruction unless it has PLT entry.
-  if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() &&
+  // next instruction unless it has PLT entry. Rewrite instruction
+  // to NOP.
+  if (pReloc.symInfo()->isWeak() &&
+      pReloc.symInfo()->isUndef() &&
+      !pReloc.symInfo()->isDyn() &&
       !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
     // change target to NOP : mov r0, r0
     pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000;
     return ARMRelocationFactory::OK;
   }
 
-  ARMRelocationFactory::Address S; // S dependent on exist PLT or not.
+  ARMRelocationFactory::Address S; // S depends on PLT exists or not.
   ARMRelocationFactory::DWord   T = getThumbBit(pReloc);
   ARMRelocationFactory::DWord   A =
     helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26)
@@ -534,16 +552,23 @@
   ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
 
   S = pReloc.symValue();
-  if( pReloc.symInfo()->reserved() & 0x8u) {
+  if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
     S = helper_PLT(pReloc, pParent);
     T = 0;  // PLT is not thumb.
   }
 
-  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
-
-  if (X & 0x03u) {  // Lowest two bit is not zero.
-    llvm::report_fatal_error("Target is thumb, need stub!");
+  // If the jump target is thumb instruction, switch mode is needed, rewrite
+  // the instruction to BLX
+  if (T != 0) {
+    // cannot rewrite R_ARM_JUMP24 instruction to blx
+    assert((pReloc.type() != llvm::ELF::R_ARM_JUMP24)&&
+      "Invalid instruction to rewrite to blx for switching mode.");
+    pReloc.target() = (pReloc.target() & 0xffffff) |
+                      0xfa000000 |
+                      (((S + A - P) & 2) << 23);
   }
+
+  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
   // Check X is 24bit sign int. If not, we should use stub or PLT before apply.
   assert(!helper_check_signed_overflow(X, 26) && "Jump or Call target too far!");
   //                    Make sure the Imm is 0.          Result Mask.
@@ -552,29 +577,25 @@
 }
 
 // R_ARM_THM_CALL: ((S + A) | T) - P
+// R_ARM_THM_JUMP24: (((S + A) | T) - P)
 ARMRelocationFactory::Result thm_call(Relocation& pReloc,
                                       const MCLDInfo& pLDInfo,
                                       ARMRelocationFactory& pParent)
 {
   // If target is undefined weak symbol, we only need to jump to the
-  // next instruction unless it has PLT entry.
-  if (pReloc.symInfo()->isWeak() && pReloc.symInfo()->isUndef() &&
+  // next instruction unless it has PLT entry. Rewrite instruction
+  // to NOP.
+  if (pReloc.symInfo()->isWeak() &&
+      pReloc.symInfo()->isUndef() &&
+      !pReloc.symInfo()->isDyn() &&
       !(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
     pReloc.target() = (0xe000U << 16) | 0xbf00U;
     return ARMRelocationFactory::OK;
   }
 
-  // TODO: By the rsloader experience: If we use 32bit, we need to consider
-  // endianness problem. Here is an ugly solution. We'd better have a thumb
-  // instruction type.
-  //uint16_t upper16 = *(
-  //    reinterpret_cast<uint16_t*>(&pReloc.target())
-  //  ),
-  //         lower16 = *(
-  //    reinterpret_cast<uint16_t*>(&pReloc.target()) + 1
-  //  );
-  ARMRelocationFactory::DWord upper16 = ((pReloc.target() & 0xffff0000U) >> 16),
-                              lower16 = (pReloc.target() & 0xffffU);
+  // get lower and upper 16 bit instructions from relocation targetData
+  uint16_t upper16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+  uint16_t lower16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
 
   ARMRelocationFactory::DWord T = getThumbBit(pReloc);
   ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper16,
@@ -582,44 +603,52 @@
   ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
   ARMRelocationFactory::Address S;
 
-  S = pReloc.symValue();
   // if symbol has plt
-  if( pReloc.symInfo()->reserved() & 0x8u) {
+  if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
     S = helper_PLT(pReloc, pParent);
     T = 0;  // PLT is not thumb.
   }
-
-  // TODO: If the target is not thumb, we should rewrite instruction to BLX.
-
-  ARMRelocationFactory::DWord X = ((S + A) | T) - P;
-  X >>= 1;
-
-  // FIXME: Check bit size is 24(thumb2) or 22?
-  if (helper_check_signed_overflow(X, 24)) {
-    assert(!"Offset is too far. We need stub or PLT for it.");
-    return ARMRelocationFactory::Overflow;
+  else {
+    S = pReloc.symValue();
   }
 
-  // For a BLX instruction, make sure that the relocation is rounded up
-  // to a word boundary. This follows the semantics of the instruction
-  // which specifies that bit 1 of the target address will come from bit
-  // 1 of the base address.
-  if ((X & 0x5000U) == 0x4000U) {
-    X = (X + 2) & ~0x3U;
+  S = S + A;
+
+  // FIXME: check if we can use BLX instruction (check from .ARM.attribute
+  // CPU ARCH TAG, which should be ARMv5 or above)
+
+  // If the jump target is not thumb, switch mode is needed, rewrite
+  // instruction to BLX
+  if (T == 0) {
+    // for BLX, select bit 1 from relocation base address to jump target
+    // address
+    S = helper_bit_select(S, P, 0x2);
+    // rewrite instruction to BLX
+    lower16 &= ~0x1000U;
+  }
+  else {
+    // otherwise, the instruction should be BL
+    lower16 |= 0x1000U;
+  }
+
+  ARMRelocationFactory::DWord X = (S | T) - P;
+
+  // TODO: check if we need stub when building non-shared object,
+  // overflow or switch-mode.
+
+  // FIXME: Check bit size is 24(thumb2) or 22?
+  if (helper_check_signed_overflow(X, 25)) {
+    assert(!"Offset is too far. We need stub or PLT for it.");
+    return ARMRelocationFactory::Overflow;
   }
 
   upper16 = helper_thumb32_branch_upper(upper16, X);
   lower16 = helper_thumb32_branch_lower(lower16, X);
 
-  // TODO: By the rsloader experience: If we use 32bit, we need to consider
-  // endianness problem. Here is an ugly solution. We'd better have a thumb
-  // instruction type.
-  //*(reinterpret_cast<uint16_t*>(&preloc.target())) = upper16;
-  //*(reinterpret_cast<uint16_t*>(&preloc.target()) + 1) = lower16;
-  pReloc.target() = (upper16 << 16);
-  pReloc.target() |= lower16;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper16;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower16;
 
-  return ARMRelocationFactory::OK;
+ return ARMRelocationFactory::OK;
 }
 
 // R_ARM_MOVW_ABS_NC: (S + A) | T
@@ -634,11 +663,19 @@
       helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  // use plt
-  if(rsym->reserved() & 0x8u) {
-    S = helper_PLT(pReloc, pParent);
-    T = 0 ; // PLT is not thumb
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    // use plt
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+      T = 0 ; // PLT is not thumb
+    }
   }
+
   X = (S + A) | T ;
   // perform static relocation
   pReloc.target() = (S + A) | T;
@@ -683,9 +720,16 @@
     helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  // use plt
-  if(rsym->reserved() & 0x8u) {
-    S = helper_PLT(pReloc, pParent);
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    // use plt
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+    }
   }
 
   X = S + A;
@@ -725,20 +769,22 @@
       helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  // use plt
-  if(rsym->reserved() & 0x8u) {
-    S = helper_PLT(pReloc, pParent);
-    T = 0; // PLT is not thumb
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    // use plt
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+      T = 0; // PLT is not thumb
+    }
   }
   X = (S + A) | T;
-  // check 16-bit overflow
-  if (helper_check_signed_overflow(X, 16)) {
-    return ARMRelocationFactory::Overflow;
-  } else {
-    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                             X);
-    return ARMRelocationFactory::OK;
-  }
+  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                           X);
+  return ARMRelocationFactory::OK;
 }
 
 // R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
@@ -756,13 +802,30 @@
   X = ((S + A) | T) - P;
 
   // check 16-bit overflow
-  if (helper_check_signed_overflow(X, 16)) {
-    return ARMRelocationFactory::Overflow;
-  } else {
-    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
-                                                             X);
-    return ARMRelocationFactory::OK;
-  }
+  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                           X);
+  return ARMRelocationFactory::OK;
+}
+
+// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
+// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
+ARMRelocationFactory::Result thm_movw_brel(Relocation& pReloc,
+                                              const MCLDInfo& pLDInfo,
+                                              ARMRelocationFactory& pParent)
+{
+  ARMRelocationFactory::Address S = pReloc.symValue();
+  ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+  ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+  ARMRelocationFactory::DWord A =
+      helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+  ARMRelocationFactory::DWord X;
+
+  X = ((S + A) | T) - P;
+
+  // check 16-bit overflow
+  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+                                                           X);
+  return ARMRelocationFactory::OK;
 }
 
 // R_ARM_THM_MOVT_ABS: S + A
@@ -776,10 +839,18 @@
       helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
   ARMRelocationFactory::DWord X;
 
-  // use plt
-  if(rsym->reserved() & 0x8u) {
-    S = helper_PLT(pReloc, pParent);
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    // use plt
+    if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+      S = helper_PLT(pReloc, pParent);
+    }
   }
+
   X = S + A;
   X >>= 16;
 
@@ -794,6 +865,7 @@
 }
 
 // R_ARM_THM_MOVT_PREL: S + A - P
+// R_ARM_THM_MOVT_BREL: S + A - B(S)
 ARMRelocationFactory::Result thm_movt_prel(Relocation& pReloc,
                                            const MCLDInfo& pLDInfo,
                                            ARMRelocationFactory& pParent)
@@ -806,15 +878,9 @@
 
   X = S + A - P;
   X >>= 16;
-
-  // check 16-bit overflow
-  if (helper_check_signed_overflow(X, 16)) {
-    return ARMRelocationFactory::Overflow;
-  } else {
-    pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
+  pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
                                                              X);
-    return ARMRelocationFactory::OK;
-  }
+  return ARMRelocationFactory::OK;
 }
 
 // R_ARM_PREL31: (S + A) | T
@@ -830,14 +896,14 @@
 
   S = pReloc.symValue();
   // if symbol has plt
-  if( pReloc.symInfo()->reserved() & 0x8u) {
+  if ( pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
     S = helper_PLT(pReloc, pParent);
     T = 0;  // PLT is not thumb.
   }
 
   ARMRelocationFactory::DWord X = (S + A) | T ;
   pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
-  if(helper_check_signed_overflow(X, 31))
+  if (helper_check_signed_overflow(X, 31))
     return ARMRelocationFactory::Overflow;
   return ARMRelocationFactory::OK;
 }
@@ -849,7 +915,6 @@
                                  const MCLDInfo& pLDInfo,
                                  ARMRelocationFactory& pParent)
 {
-  llvm::report_fatal_error("We don't support TLS relocation yet.");
   return ARMRelocationFactory::Unsupport;
 }
 
diff --git a/lib/Target/ARM/ARMRelocationFactory.h b/lib/Target/ARM/ARMRelocationFactory.h
index 0426100..636dbee 100644
--- a/lib/Target/ARM/ARMRelocationFactory.h
+++ b/lib/Target/ARM/ARMRelocationFactory.h
@@ -56,3 +56,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/ARMRelocationFunctions.h b/lib/Target/ARM/ARMRelocationFunctions.h
index 10d27a4..bb6e727 100644
--- a/lib/Target/ARM/ARMRelocationFunctions.h
+++ b/lib/Target/ARM/ARMRelocationFunctions.h
@@ -27,6 +27,7 @@
 DECL_ARM_APPLY_RELOC_FUNC(movt_prel)        \
 DECL_ARM_APPLY_RELOC_FUNC(thm_movw_abs_nc)  \
 DECL_ARM_APPLY_RELOC_FUNC(thm_movw_prel_nc) \
+DECL_ARM_APPLY_RELOC_FUNC(thm_movw_brel)    \
 DECL_ARM_APPLY_RELOC_FUNC(thm_movt_abs)     \
 DECL_ARM_APPLY_RELOC_FUNC(thm_movt_prel)    \
 DECL_ARM_APPLY_RELOC_FUNC(prel31)           \
@@ -66,7 +67,7 @@
   { &call,              27, "R_ARM_PLT32"             },  \
   { &call,              28, "R_ARM_CALL"              },  \
   { &call,              29, "R_ARM_JUMP24"            },  \
-  { &unsupport,         30, "R_ARM_THM_JUMP24"        },  \
+  { &thm_call,          30, "R_ARM_THM_JUMP24"        },  \
   { &unsupport,         31, "R_ARM_BASE_ABS"          },  \
   { &unsupport,         32, "R_ARM_ALU_PCREL_7_0"     },  \
   { &unsupport,         33, "R_ARM_ALU_PCREL_15_8"    },  \
@@ -123,9 +124,9 @@
   { &unsupport,         84, "R_ARM_MOVW_BREL_NC"      },  \
   { &unsupport,         85, "R_ARM_MOVT_BREL"         },  \
   { &unsupport,         86, "R_ARM_MOVW_BREL"         },  \
-  { &unsupport,         87, "R_ARM_THM_MOVW_BREL_NC"  },  \
-  { &unsupport,         88, "R_ARM_THM_MOVT_BREL"     },  \
-  { &unsupport,         89, "R_ARM_THM_MOVW_BREL"     },  \
+  { &thm_movw_brel,     87, "R_ARM_THM_MOVW_BREL_NC"  },  \
+  { &thm_movt_prel,     88, "R_ARM_THM_MOVT_BREL"     },  \
+  { &thm_movw_brel,     89, "R_ARM_THM_MOVW_BREL"     },  \
   { &unsupport,         90, "R_ARM_TLS_GOTDESC"       },  \
   { &unsupport,         91, "R_ARM_TLS_CALL"          },  \
   { &unsupport,         92, "R_ARM_TLS_DESCSEQ"       },  \
diff --git a/lib/Target/ARM/ARMSectLinker.cpp b/lib/Target/ARM/ARMSectLinker.cpp
index 16d2126..06dba05 100644
--- a/lib/Target/ARM/ARMSectLinker.cpp
+++ b/lib/Target/ARM/ARMSectLinker.cpp
@@ -9,7 +9,6 @@
 #include <llvm/ADT/Triple.h>
 #include <mcld/Support/TargetRegistry.h>
 #include "ARM.h"
-#include "ARMAndroidSectLinker.h"
 #include "ARMELFSectLinker.h"
 
 
@@ -32,8 +31,7 @@
   }
 
   // For now, use Android SectLinker directly
-  return new ARMAndroidSectLinker(pOption,
-                                  pLDBackend);
+  return new ARMELFSectLinker(pOption, pLDBackend);
 }
 
 } // namespace of mcld
@@ -43,4 +41,6 @@
 extern "C" void LLVMInitializeARMSectLinker() {
   // Register the linker frontend
   mcld::TargetRegistry::RegisterSectLinker(TheARMTarget, createARMSectLinker);
+  mcld::TargetRegistry::RegisterSectLinker(TheThumbTarget, createARMSectLinker);
 }
+
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index 3cb7793..54e1b3d 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -15,6 +15,7 @@
 extern "C" void LLVMInitializeARMLDTarget() {
   // Register createTargetMachine function pointer to mcld::Target
   mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> X(mcld::TheARMTarget);
+  mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> Y(mcld::TheThumbTarget);
 }
 
 mcld::ARMBaseTargetMachine::ARMBaseTargetMachine(llvm::TargetMachine& pPM,
@@ -30,3 +31,4 @@
 {
   delete m_pLDInfo;
 }
+
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index 419826c..19f8aa2 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -37,3 +37,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/ARM/README b/lib/Target/ARM/README
index 2110344..ea88bfe 100644
--- a/lib/Target/ARM/README
+++ b/lib/Target/ARM/README
@@ -1,2 +1,2 @@
-ARMLDBackend stands like ARMAsmBackend. It's a backend of linker,
+ARMLDBackend stands like ARMAsmBackend. It's a backend of linker, 
 and all target-dependent behavior and data are here.
diff --git a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
index 7e6a41a..4f2f815 100644
--- a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
+++ b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
@@ -12,10 +12,12 @@
 namespace mcld {
 
 mcld::Target TheARMTarget;
+mcld::Target TheThumbTarget;
 
 extern "C" void LLVMInitializeARMLDTargetInfo() {
   // register into mcld::TargetRegistry
   mcld::RegisterTarget X(TheARMTarget, "arm" );
+  mcld::RegisterTarget Y(TheThumbTarget, "thumb" );
 }
 
 } // namespace of mcld
diff --git a/lib/Target/AndroidSectLinker.cpp b/lib/Target/AndroidSectLinker.cpp
deleted file mode 100644
index 8f3acbf..0000000
--- a/lib/Target/AndroidSectLinker.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- AndroidSectLinker.cpp ----------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <mcld/Target/AndroidSectLinker.h>
-
-#include <llvm/Support/ErrorHandling.h>
-#include <mcld/MC/MCLDDirectory.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-//==========================
-// AndroidSectLinker
-
-AndroidSectLinker::AndroidSectLinker(SectLinkerOption &pOption,
-                                     TargetLDBackend &pLDBackend)
-  : SectLinker(pOption, pLDBackend) {
-}
-
-AndroidSectLinker::~AndroidSectLinker()
-{
-  // SectLinker will delete m_pLDBackend and m_pLDDriver;
-}
-
-void AndroidSectLinker::addTargetOptions(llvm::Module &pM,
-                                         SectLinkerOption &pOption)
-{
-  // -----  Set up General Options  ----- //
-  MCLDInfo &info = pOption.info();
-  MCLDDirectory search_path("=/system/lib");
-  search_path.setSysroot(info.options().sysroot());
-  if (exists(search_path.path()) && is_directory(search_path.path()))
-    info.options().directories().add(search_path);
-  else {
-    // FIXME: need a warning function
-    llvm::errs() << "WARNING: can not open search directory: `-L" << search_path.name() << "'.\n";
-  }
-}
-
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
index b863ab1..cb7c435 100644
--- a/lib/Target/ELFDynamic.cpp
+++ b/lib/Target/ELFDynamic.cpp
@@ -84,7 +84,6 @@
   ++m_Idx;
 }
 
-
 /// reserveEntries - reserve entries
 void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo,
                                 const ELFFileFormat& pFormat)
@@ -146,6 +145,28 @@
     reserveOne(llvm::ELF::DT_RELASZ); // DT_RELASZ
     reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
   }
+
+  if (pLDInfo.options().hasOrigin() ||
+      pLDInfo.options().Bsymbolic() ||
+      pLDInfo.options().hasNow()) {
+    // TODO: add checks for DF_TEXTREL and DF_STATIC_TLS
+    reserveOne(llvm::ELF::DT_FLAGS); // DT_FLAGS
+  }
+
+  if (pLDInfo.options().hasNow()          ||
+      pLDInfo.options().hasLoadFltr()     ||
+      pLDInfo.options().hasOrigin()       ||
+      pLDInfo.options().hasInterPose()    ||
+      pLDInfo.options().hasNoDefaultLib() ||
+      pLDInfo.options().hasNoDump()       ||
+      pLDInfo.options().Bgroup()          ||
+      ((pLDInfo.output().type() == Output::DynObj) &&
+       (pLDInfo.options().hasNoDelete()  ||
+        pLDInfo.options().hasInitFirst() ||
+        pLDInfo.options().hasNoDLOpen()))) {
+    reserveOne(llvm::ELF::DT_FLAGS_1); // DT_FLAGS_1
+  }
+
   reserveOne(llvm::ELF::DT_NULL); // for DT_NULL
 }
 
@@ -217,6 +238,44 @@
     applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
   }
 
+  uint64_t dt_flags = 0x0;
+  if (pInfo.options().hasOrigin())
+    dt_flags |= llvm::ELF::DF_ORIGIN;
+  if (pInfo.options().Bsymbolic())
+    dt_flags |= llvm::ELF::DF_SYMBOLIC;
+  if (pInfo.options().hasNow())
+    dt_flags |= llvm::ELF::DF_BIND_NOW;
+  // TODO: add checks for DF_TEXTREL and DF_STATIC_TLS
+  if (0x0 != dt_flags) {
+    applyOne(llvm::ELF::DT_FLAGS, dt_flags); // DT_FLAGS
+  }
+
+  uint64_t dt_flags_1 = 0x0;
+  if (pInfo.options().hasNow())
+    dt_flags_1 |= llvm::ELF::DF_1_NOW;
+  if (pInfo.options().hasLoadFltr())
+    dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
+  if (pInfo.options().hasOrigin())
+    dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
+  if (pInfo.options().hasInterPose())
+    dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
+  if (pInfo.options().hasNoDefaultLib())
+    dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
+  if (pInfo.options().hasNoDump())
+    dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
+  if (pInfo.options().Bgroup())
+    dt_flags_1 |= llvm::ELF::DF_1_GROUP;
+  if (pInfo.output().type() == Output::DynObj) {
+    if (pInfo.options().hasNoDelete())
+      dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
+    if (pInfo.options().hasInitFirst())
+      dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
+    if (pInfo.options().hasNoDLOpen())
+      dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
+  }
+  if (0x0 != dt_flags_1)
+    applyOne(llvm::ELF::DT_FLAGS_1, dt_flags_1); // DT_FLAGS_1
+
   applyOne(llvm::ELF::DT_NULL, 0x0); // for DT_NULL
 }
 
diff --git a/lib/Target/ELFSectLinker.cpp b/lib/Target/ELFSectLinker.cpp
new file mode 100644
index 0000000..b95ed0b
--- /dev/null
+++ b/lib/Target/ELFSectLinker.cpp
@@ -0,0 +1,25 @@
+//===- ELFSectLinker.cpp ------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Target/ELFSectLinker.h>
+#include <mcld/CodeGen/SectLinkerOption.h>
+
+using namespace mcld;
+
+//==========================
+// ELFSectLinker
+ELFSectLinker::ELFSectLinker(SectLinkerOption &pOption,
+                             TargetLDBackend &pLDBackend)
+  : SectLinker(pOption, pLDBackend) {
+}
+
+ELFSectLinker::~ELFSectLinker()
+{
+  // SectLinker will delete m_pLDBackend and m_pLDDriver;
+}
+
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
index b82af73..9fff9e3 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -11,12 +11,14 @@
 #include <mcld/Target/GNULDBackend.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLDInputTree.h>
+#include <mcld/MC/InputTree.h>
 #include <mcld/MC/SymbolCategory.h>
 #include <mcld/LD/LDSymbol.h>
 #include <mcld/LD/Layout.h>
 #include <mcld/Support/MemoryArea.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/MC/MCLinker.h>
 #include <string>
 #include <cstring>
 #include <cassert>
@@ -26,36 +28,57 @@
 //===----------------------------------------------------------------------===//
 // GNULDBackend
 GNULDBackend::GNULDBackend()
-  : m_pArchiveReader(0),
-    m_pObjectReader(0),
-    m_pDynObjReader(0),
-    m_pObjectWriter(0),
-    m_pDynObjWriter(0),
-    m_pDynObjFileFormat(0),
-    m_pExecFileFormat(0),
-    m_ELFSegmentTable(9)// magic number
-{
+  : m_pArchiveReader(NULL),
+    m_pObjectReader(NULL),
+    m_pDynObjReader(NULL),
+    m_pObjectWriter(NULL),
+    m_pDynObjWriter(NULL),
+    m_pExecWriter(NULL),
+    m_pDynObjFileFormat(NULL),
+    m_pExecFileFormat(NULL),
+    m_ELFSegmentTable(9), // magic number
+    m_pEhFrameHdr(NULL),
+    f_pPreInitArrayStart(NULL),
+    f_pPreInitArrayEnd(NULL),
+    f_pInitArrayStart(NULL),
+    f_pInitArrayEnd(NULL),
+    f_pFiniArrayStart(NULL),
+    f_pFiniArrayEnd(NULL),
+    f_pStack(NULL),
+    f_pExecutableStart(NULL),
+    f_pEText(NULL),
+    f_p_EText(NULL),
+    f_p__EText(NULL),
+    f_pEData(NULL),
+    f_p_EData(NULL),
+    f_pBSSStart(NULL),
+    f_pEnd(NULL),
+    f_p_End(NULL) {
   m_pSymIndexMap = new HashTableType(1024);
 }
 
 GNULDBackend::~GNULDBackend()
 {
-  if (m_pArchiveReader)
+  if (NULL != m_pArchiveReader)
     delete m_pArchiveReader;
-  if (m_pObjectReader)
+  if (NULL != m_pObjectReader)
     delete m_pObjectReader;
-  if (m_pDynObjReader)
+  if (NULL != m_pDynObjReader)
     delete m_pDynObjReader;
-  if (m_pObjectWriter)
+  if (NULL != m_pObjectWriter)
     delete m_pObjectWriter;
-  if (m_pDynObjWriter)
+  if (NULL != m_pDynObjWriter)
     delete m_pDynObjWriter;
-  if (m_pDynObjFileFormat)
+  if (NULL != m_pExecWriter)
+    delete m_pExecWriter;
+  if (NULL != m_pDynObjFileFormat)
     delete m_pDynObjFileFormat;
-  if (m_pExecFileFormat)
+  if (NULL != m_pExecFileFormat)
     delete m_pExecFileFormat;
-  if(m_pSymIndexMap)
+  if (NULL != m_pSymIndexMap)
     delete m_pSymIndexMap;
+  if (NULL != m_pEhFrameHdr)
+    delete m_pEhFrameHdr;
 }
 
 size_t GNULDBackend::sectionStartOffset() const
@@ -64,13 +87,20 @@
   return sizeof(llvm::ELF::Elf64_Ehdr)+10*sizeof(llvm::ELF::Elf64_Phdr);
 }
 
+uint64_t GNULDBackend::segmentStartAddr(const Output& pOutput,
+                                        const MCLDInfo& pInfo) const
+{
+  // TODO: handle the user option: -TText=
+  if (isOutputPIC(pOutput, pInfo))
+    return 0x0;
+  else
+    return defaultTextSegmentAddr();
+}
+
 bool GNULDBackend::initArchiveReader(MCLinker&, MCLDInfo &pInfo)
 {
   if (0 == m_pArchiveReader)
-  {
-    LDReader::Endian isLittleEndian = LDReader::LittleEndian;
-    m_pArchiveReader = new GNUArchiveReader(pInfo, isLittleEndian);
-  }
+    m_pArchiveReader = new GNUArchiveReader(pInfo);
   return true;
 }
 
@@ -96,11 +126,18 @@
 
 bool GNULDBackend::initDynObjWriter(MCLinker& pLinker)
 {
-  if (0 == m_pDynObjWriter)
+  if (NULL == m_pDynObjWriter)
     m_pDynObjWriter = new ELFDynObjWriter(*this, pLinker);
   return true;
 }
 
+bool GNULDBackend::initExecWriter(MCLinker& pLinker)
+{
+  if (NULL == m_pExecWriter)
+    m_pExecWriter = new ELFExecWriter(*this, pLinker);
+  return true;
+}
+
 bool GNULDBackend::initExecSections(MCLinker& pMCLinker)
 {
   if (0 == m_pExecFileFormat)
@@ -121,8 +158,395 @@
   return true;
 }
 
-bool GNULDBackend::initStandardSymbols(MCLinker& pLinker)
+bool GNULDBackend::initStandardSymbols(MCLinker& pLinker, const Output& pOutput)
 {
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  // -----  section symbols  ----- //
+  // .preinit_array
+  MCFragmentRef* preinit_array = NULL;
+  if (file_format->hasPreInitArray()) {
+    preinit_array = pLinker.getLayout().getFragmentRef(
+                   *(file_format->getPreInitArray().getSectionData()->begin()),
+                   0x0);
+  }
+  f_pPreInitArrayStart =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__preinit_array_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             preinit_array, // FragRef
+                                             ResolveInfo::Hidden);
+  f_pPreInitArrayEnd =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__preinit_array_end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Hidden);
+
+  // .init_array
+  MCFragmentRef* init_array = NULL;
+  if (file_format->hasInitArray()) {
+    init_array = pLinker.getLayout().getFragmentRef(
+                      *(file_format->getInitArray().getSectionData()->begin()),
+                      0x0);
+  }
+
+  f_pInitArrayStart =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__init_array_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             init_array, // FragRef
+                                             ResolveInfo::Hidden);
+  f_pInitArrayEnd =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__init_array_end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             init_array, // FragRef
+                                             ResolveInfo::Hidden);
+
+  // .fini_array
+  MCFragmentRef* fini_array = NULL;
+  if (file_format->hasFiniArray()) {
+    fini_array = pLinker.getLayout().getFragmentRef(
+                     *(file_format->getFiniArray().getSectionData()->begin()),
+                     0x0);
+  }
+
+  f_pFiniArrayStart =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__fini_array_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             fini_array, // FragRef
+                                             ResolveInfo::Hidden);
+  f_pFiniArrayEnd =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__fini_array_end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             fini_array, // FragRef
+                                             ResolveInfo::Hidden);
+
+  // .stack
+  MCFragmentRef* stack = NULL;
+  if (file_format->hasStack()) {
+    stack = pLinker.getLayout().getFragmentRef(
+                          *(file_format->getStack().getSectionData()->begin()),
+                          0x0);
+  }
+  f_pStack =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__stack",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Global,
+                                             0x0, // size
+                                             0x0, // value
+                                             stack, // FragRef
+                                             ResolveInfo::Hidden);
+
+  // -----  segment symbols  ----- //
+  f_pExecutableStart =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__executable_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+  f_pEText =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("etext",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+  f_p_EText =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("_etext",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+  f_p__EText =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("__etext",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+  f_pEData =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("edata",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+
+  f_pEnd =
+     pLinker.defineSymbol<MCLinker::AsRefered,
+                          MCLinker::Resolve>("end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+
+  // _edata is defined forcefully.
+  // @ref Google gold linker: defstd.cc: 186
+  f_p_EData =
+     pLinker.defineSymbol<MCLinker::Force,
+                          MCLinker::Resolve>("_edata",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+
+  // __bss_start is defined forcefully.
+  // @ref Google gold linker: defstd.cc: 214
+  f_pBSSStart =
+     pLinker.defineSymbol<MCLinker::Force,
+                          MCLinker::Resolve>("__bss_start",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+
+  // _end is defined forcefully.
+  // @ref Google gold linker: defstd.cc: 228
+  f_p_End =
+     pLinker.defineSymbol<MCLinker::Force,
+                          MCLinker::Resolve>("_end",
+                                             false, // isDyn
+                                             ResolveInfo::NoType,
+                                             ResolveInfo::Define,
+                                             ResolveInfo::Absolute,
+                                             0x0, // size
+                                             0x0, // value
+                                             NULL, // FragRef
+                                             ResolveInfo::Default);
+
+  return true;
+}
+
+bool
+GNULDBackend::finalizeStandardSymbols(MCLinker& pLinker, const Output& pOutput)
+{
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  // -----  section symbols  ----- //
+  if (NULL != f_pPreInitArrayStart) {
+    if (!f_pPreInitArrayStart->hasFragRef()) {
+      f_pPreInitArrayStart->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pPreInitArrayStart->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pPreInitArrayEnd) {
+    if (f_pPreInitArrayEnd->hasFragRef()) {
+      f_pPreInitArrayEnd->setValue(f_pPreInitArrayEnd->value() +
+                                   file_format->getPreInitArray().size());
+    }
+    else {
+      f_pPreInitArrayEnd->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pPreInitArrayEnd->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pInitArrayStart) {
+    if (!f_pInitArrayStart->hasFragRef()) {
+      f_pInitArrayStart->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pInitArrayStart->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pInitArrayEnd) {
+    if (f_pInitArrayEnd->hasFragRef()) {
+      f_pInitArrayEnd->setValue(f_pInitArrayEnd->value() +
+                                file_format->getInitArray().size());
+    }
+    else {
+      f_pInitArrayEnd->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pInitArrayEnd->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pFiniArrayStart) {
+    if (!f_pFiniArrayStart->hasFragRef()) {
+      f_pFiniArrayStart->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pFiniArrayStart->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pFiniArrayEnd) {
+    if (f_pFiniArrayEnd->hasFragRef()) {
+      f_pFiniArrayEnd->setValue(f_pFiniArrayEnd->value() +
+                                file_format->getFiniArray().size());
+    }
+    else {
+      f_pFiniArrayEnd->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pFiniArrayEnd->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pStack) {
+    if (!f_pStack->hasFragRef()) {
+      f_pStack->resolveInfo()->setBinding(ResolveInfo::Absolute);
+      f_pStack->setValue(0x0);
+    }
+  }
+
+  // -----  segment symbols  ----- //
+  if (NULL != f_pExecutableStart) {
+    ELFSegment* exec_start = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD, 0x0, 0x0);
+    if (NULL != exec_start) {
+      if (ResolveInfo::ThreadLocal != f_pExecutableStart->type()) {
+        f_pExecutableStart->setValue(f_pExecutableStart->value() +
+                                     exec_start->vaddr());
+      }
+    }
+    else
+      f_pExecutableStart->setValue(0x0);
+  }
+
+  if (NULL != f_pEText || NULL != f_p_EText || NULL !=f_p__EText) {
+    ELFSegment* etext = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD,
+                                               llvm::ELF::PF_X,
+                                               llvm::ELF::PF_W);
+    if (NULL != etext) {
+      if (NULL != f_pEText && ResolveInfo::ThreadLocal != f_pEText->type()) {
+        f_pEText->setValue(f_pEText->value() +
+                           etext->vaddr() +
+                           etext->memsz());
+      }
+      if (NULL != f_p_EText && ResolveInfo::ThreadLocal != f_p_EText->type()) {
+        f_p_EText->setValue(f_p_EText->value() +
+                            etext->vaddr() +
+                            etext->memsz());
+      }
+      if (NULL != f_p__EText && ResolveInfo::ThreadLocal != f_p__EText->type()) {
+        f_p__EText->setValue(f_p__EText->value() +
+                            etext->vaddr() +
+                            etext->memsz());
+      }
+    }
+    else {
+      if (NULL != f_pEText)
+        f_pEText->setValue(0x0);
+      if (NULL != f_p_EText)
+        f_p_EText->setValue(0x0);
+      if (NULL != f_p__EText)
+        f_p__EText->setValue(0x0);
+    }
+  }
+
+  if (NULL != f_pEData || NULL != f_p_EData || NULL != f_pBSSStart ||
+      NULL != f_pEnd || NULL != f_p_End) {
+    ELFSegment* edata = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD,
+                                               llvm::ELF::PF_W,
+                                               0x0);
+    if (NULL != edata) {
+      if (NULL != f_pEData && ResolveInfo::ThreadLocal != f_pEData->type()) {
+        f_pEData->setValue(f_pEData->value() +
+                            edata->vaddr() +
+                            edata->filesz());
+      }
+      if (NULL != f_p_EData && ResolveInfo::ThreadLocal != f_p_EData->type()) {
+        f_p_EData->setValue(f_p_EData->value() +
+                            edata->vaddr() +
+                            edata->filesz());
+      }
+      if (NULL != f_pBSSStart && ResolveInfo::ThreadLocal != f_pBSSStart->type()) {
+        f_pBSSStart->setValue(f_pBSSStart->value() +
+                              edata->vaddr() +
+                              edata->filesz());
+      }
+
+      if (NULL != f_pEnd && ResolveInfo::ThreadLocal != f_pEnd->type()) {
+        f_pEnd->setValue(f_pEnd->value() +
+                         edata->vaddr() +
+                         edata->memsz());
+      }
+      if (NULL != f_p_End && ResolveInfo::ThreadLocal != f_p_End->type()) {
+        f_p_End->setValue(f_p_End->value() +
+                          edata->vaddr() +
+                          edata->memsz());
+      }
+    }
+    else {
+      if (NULL != f_pEData)
+        f_pEData->setValue(0x0);
+      if (NULL != f_p_EData)
+        f_p_EData->setValue(0x0);
+      if (NULL != f_pBSSStart)
+        f_pBSSStart->setValue(0x0);
+
+      if (NULL != f_pEnd)
+        f_pEnd->setValue(0x0);
+      if (NULL != f_p_End)
+        f_p_End->setValue(0x0);
+    }
+  }
+
   return true;
 }
 
@@ -132,7 +556,7 @@
   return m_pArchiveReader;
 }
 
-GNUArchiveReader *GNULDBackend::getArchiveReader() const
+const GNUArchiveReader *GNULDBackend::getArchiveReader() const
 {
   assert(0 != m_pArchiveReader);
   return m_pArchiveReader;
@@ -144,7 +568,7 @@
   return m_pObjectReader;
 }
 
-ELFObjectReader *GNULDBackend::getObjectReader() const
+const ELFObjectReader *GNULDBackend::getObjectReader() const
 {
   assert(0 != m_pObjectReader);
   return m_pObjectReader;
@@ -156,7 +580,7 @@
   return m_pDynObjReader;
 }
 
-ELFDynObjReader *GNULDBackend::getDynObjReader() const
+const ELFDynObjReader *GNULDBackend::getDynObjReader() const
 {
   assert(0 != m_pDynObjReader);
   return m_pDynObjReader;
@@ -168,7 +592,7 @@
   return NULL;
 }
 
-ELFObjectWriter *GNULDBackend::getObjectWriter() const
+const ELFObjectWriter *GNULDBackend::getObjectWriter() const
 {
   // TODO
   return NULL;
@@ -180,19 +604,61 @@
   return m_pDynObjWriter;
 }
 
-ELFDynObjWriter *GNULDBackend::getDynObjWriter() const
+const ELFDynObjWriter *GNULDBackend::getDynObjWriter() const
 {
   assert(0 != m_pDynObjWriter);
   return m_pDynObjWriter;
 }
 
+ELFExecWriter *GNULDBackend::getExecWriter()
+{
+  assert(NULL != m_pExecWriter);
+  return m_pExecWriter;
+}
+
+const ELFExecWriter *GNULDBackend::getExecWriter() const
+{
+  assert(NULL != m_pExecWriter);
+  return m_pExecWriter;
+}
+
+ELFFileFormat* GNULDBackend::getOutputFormat(const Output& pOutput)
+{
+  switch (pOutput.type()) {
+    case Output::DynObj:
+      return getDynObjFileFormat();
+    case Output::Exec:
+      return getExecFileFormat();
+    // FIXME: We do not support building .o now
+    case Output::Object:
+    default:
+      fatal(diag::unrecognized_output_file) << pOutput.type();
+      return NULL;
+  }
+}
+
+const ELFFileFormat* GNULDBackend::getOutputFormat(const Output& pOutput) const
+{
+  switch (pOutput.type()) {
+    case Output::DynObj:
+      return getDynObjFileFormat();
+    case Output::Exec:
+      return getExecFileFormat();
+    // FIXME: We do not support building .o now
+    case Output::Object:
+    default:
+      fatal(diag::unrecognized_output_file) << pOutput.type();
+      return NULL;
+  }
+}
+
 ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat()
 {
   assert(0 != m_pDynObjFileFormat);
   return m_pDynObjFileFormat;
 }
 
-ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat() const
+const ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat() const
 {
   assert(0 != m_pDynObjFileFormat);
   return m_pDynObjFileFormat;
@@ -204,7 +670,7 @@
   return m_pExecFileFormat;
 }
 
-ELFExecFileFormat* GNULDBackend::getExecFileFormat() const
+const ELFExecFileFormat* GNULDBackend::getExecFileFormat() const
 {
   assert(0 != m_pExecFileFormat);
   return m_pExecFileFormat;
@@ -241,20 +707,7 @@
     strtab += str_size;
   }
 
-  ELFFileFormat* file_format = NULL;
-  switch(pOutput.type()) {
-    // compute size of .dynstr and .hash
-    case Output::DynObj:
-      file_format = getDynObjFileFormat();
-      break;
-    case Output::Exec:
-      file_format = getExecFileFormat();
-      break;
-    case Output::Object:
-    default:
-      // TODO: not support yet
-      return;
-  }
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   switch(pOutput.type()) {
     // compute size of .dynstr and .hash
@@ -335,23 +788,14 @@
   bool sym_exist = false;
   HashTableType::entry_type* entry = 0;
 
-  ELFFileFormat* file_format = NULL;
-  switch(pOutput.type()) {
-    // compute size of .dynstr and .hash
-    case Output::DynObj:
-      file_format = getDynObjFileFormat();
-      break;
-    case Output::Exec:
-      file_format = getExecFileFormat();
-      break;
-    case Output::Object:
-    default:
-      // add first symbol into m_pSymIndexMap
-      entry = m_pSymIndexMap->insert(NULL, sym_exist);
-      entry->setValue(0);
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  if (pOutput.type() == Output::Object) {
+    // add first symbol into m_pSymIndexMap
+    entry = m_pSymIndexMap->insert(NULL, sym_exist);
+    entry->setValue(0);
 
-      // TODO: not support yet
-      return;
+    // TODO: not support yet
+    return;
   }
 
   LDSection& symtab_sect = file_format->getSymTab();
@@ -446,25 +890,11 @@
                                     const MCLDInfo& pLDInfo)
 {
   assert(pOutput.hasMemArea());
-  ELFFileFormat* file_format = NULL;
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   bool sym_exist = false;
   HashTableType::entry_type* entry = 0;
 
-  switch(pOutput.type()) {
-    // compute size of .dynstr and .hash
-    case Output::DynObj:
-      file_format = getDynObjFileFormat();
-      break;
-    case Output::Exec:
-      file_format = getExecFileFormat();
-      break;
-    case Output::Object:
-    default:
-      // TODO: not support yet
-      return;
-  }
-
   LDSection& symtab_sect = file_format->getDynSymTab();
   LDSection& strtab_sect = file_format->getDynStrTab();
   LDSection& hash_sect   = file_format->getHashTab();
@@ -587,7 +1017,8 @@
 
   // emit soname
   // initialize value of ELF .dynamic section
-  dynamic().applySoname(strtabsize);
+  if (Output::DynObj == pOutput.type())
+    dynamic().applySoname(strtabsize);
   dynamic().applyEntries(pLDInfo, *file_format);
   dynamic().emit(dyn_sect, *dyn_region);
 
@@ -633,9 +1064,44 @@
   }
 }
 
+/// sizeInterp - compute the size of the .interp section
+void GNULDBackend::sizeInterp(const Output& pOutput, const MCLDInfo& pLDInfo)
+{
+  assert(pOutput.type() == Output::Exec);
+
+  const char* dyld_name;
+  if (pLDInfo.options().hasDyld())
+    dyld_name = pLDInfo.options().dyld().c_str();
+  else
+    dyld_name = dyld();
+
+  LDSection& interp = getExecFileFormat()->getInterp();
+  interp.setSize(std::strlen(dyld_name) + 1);
+}
+
+/// emitInterp - emit the .interp
+void GNULDBackend::emitInterp(Output& pOutput, const MCLDInfo& pLDInfo)
+{
+  assert(pOutput.type() == Output::Exec &&
+         getExecFileFormat()->hasInterp() &&
+         pOutput.hasMemArea());
+
+  const LDSection& interp = getExecFileFormat()->getInterp();
+  MemoryRegion *region = pOutput.memArea()->request(
+                                              interp.offset(), interp.size());
+  const char* dyld_name;
+  if (pLDInfo.options().hasDyld())
+    dyld_name = pLDInfo.options().dyld().c_str();
+  else
+    dyld_name = dyld();
+
+  std::memcpy(region->start(), dyld_name, interp.size());
+}
+
 /// getSectionOrder
 unsigned int GNULDBackend::getSectionOrder(const Output& pOutput,
-                                           const LDSection& pSectHdr) const
+                                           const LDSection& pSectHdr,
+                                           const MCLDInfo& pInfo) const
 {
   // NULL section should be the "1st" section
   if (LDFileFormat::Null == pSectHdr.kind())
@@ -647,19 +1113,7 @@
 
   bool is_write = (pSectHdr.flag() & llvm::ELF::SHF_WRITE) != 0;
   bool is_exec = (pSectHdr.flag() & llvm::ELF::SHF_EXECINSTR) != 0;
-  ELFFileFormat* file_format = NULL;
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      file_format = getDynObjFileFormat();
-      break;
-    case Output::Exec:
-      file_format = getExecFileFormat();
-      break;
-    case Output::Object:
-    default:
-      assert(0 && "Not support yet.\n");
-      break;
-  }
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   // TODO: need to take care other possible output sections
   switch (pSectHdr.kind()) {
@@ -673,13 +1127,18 @@
       } else if (!is_write) {
         return SHO_RO;
       } else {
-        if (pSectHdr.type() == llvm::ELF::SHT_PREINIT_ARRAY ||
-            pSectHdr.type() == llvm::ELF::SHT_INIT_ARRAY ||
-            pSectHdr.type() == llvm::ELF::SHT_FINI_ARRAY ||
-            &pSectHdr == &file_format->getCtors() ||
-            &pSectHdr == &file_format->getDtors())
-          return SHO_RELRO;
-
+        if (pInfo.options().hasRelro()) {
+          if (pSectHdr.type() == llvm::ELF::SHT_PREINIT_ARRAY ||
+              pSectHdr.type() == llvm::ELF::SHT_INIT_ARRAY ||
+              pSectHdr.type() == llvm::ELF::SHT_FINI_ARRAY ||
+              &pSectHdr == &file_format->getCtors() ||
+              &pSectHdr == &file_format->getDtors() ||
+              &pSectHdr == &file_format->getJCR() ||
+              0 == pSectHdr.name().compare(".data.rel.ro"))
+            return SHO_RELRO;
+          if (0 == pSectHdr.name().compare(".data.rel.ro.local"))
+            return SHO_RELRO_LOCAL;
+        }
         return SHO_DATA;
       }
 
@@ -699,14 +1158,16 @@
 
     // get the order from target for target specific sections
     case LDFileFormat::Target:
-      return getTargetSectionOrder(pOutput, pSectHdr);
+      return getTargetSectionOrder(pOutput, pSectHdr, pInfo);
 
     // handle .interp
     case LDFileFormat::Note:
       return SHO_INTERP;
 
-    case LDFileFormat::Exception:
-      return SHO_EHFRAME;
+    case LDFileFormat::EhFrame:
+    case LDFileFormat::EhFrameHdr:
+    case LDFileFormat::GCCExceptTable:
+      return SHO_EXCEPTION;
 
     case LDFileFormat::MetaData:
     case LDFileFormat::Debug:
@@ -745,7 +1206,12 @@
       pSymbol.visibility() == llvm::ELF::STV_HIDDEN)
     bind = llvm::ELF::STB_LOCAL;
 
-  return (pSymbol.resolveInfo()->type() | (bind << 4));
+  uint32_t type = pSymbol.resolveInfo()->type();
+  // if the IndirectFunc symbol (i.e., STT_GNU_IFUNC) is from dynobj, change
+  // its type to Function
+  if (type == ResolveInfo::IndirectFunc && pSymbol.isDyn())
+    type = ResolveInfo::Function;
+  return (type | (bind << 4));
 }
 
 /// getSymbolValue - this function is called after layout()
@@ -776,7 +1242,7 @@
     }
   }
 
-  assert(pSymbol.hasFragRef());
+  assert(pSymbol.hasFragRef() && "symbols must have fragment reference to get its index");
   return pLayout.getOutputLDSection(*pSymbol.fragRef()->frag())->index();
 }
 
@@ -787,38 +1253,154 @@
    return entry.getEntry()->value();
 }
 
-/// emitProgramHdrs - emit ELF program headers
-void GNULDBackend::emitProgramHdrs(Output& pOutput)
+/// allocateCommonSymbols - allocate common symbols in the corresponding
+/// sections.
+/// @refer Google gold linker: common.cc: 214
+bool
+GNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
 {
-  assert(NULL != pOutput.context());
-  createProgramHdrs(*pOutput.context());
+  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
 
-  if (32 == bitclass())
-    writeELF32ProgramHdrs(pOutput);
-  else
-    writeELF64ProgramHdrs(pOutput);
+  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
+    return true;
+
+  SymbolCategory::iterator com_sym, com_end;
+
+  // FIXME: If the order of common symbols is defined, then sort common symbols
+  // std::sort(com_sym, com_end, some kind of order);
+
+  // get or create corresponding BSS LDSection
+  LDSection* bss_sect = &pLinker.getOrCreateOutputSectHdr(".bss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+
+  LDSection* tbss_sect = &pLinker.getOrCreateOutputSectHdr(
+                                   ".tbss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+
+  assert(NULL != bss_sect && NULL !=tbss_sect);
+
+  // get or create corresponding BSS MCSectionData
+  llvm::MCSectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
+  llvm::MCSectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
+
+  // remember original BSS size
+  uint64_t bss_offset  = bss_sect->size();
+  uint64_t tbss_offset = tbss_sect->size();
+
+  // allocate all local common symbols
+  com_end = symbol_list.localEnd();
+
+  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
+    if (ResolveInfo::Common == (*com_sym)->desc()) {
+      // We have to reset the description of the symbol here. When doing
+      // incremental linking, the output relocatable object may have common
+      // symbols. Therefore, we can not treat common symbols as normal symbols
+      // when emitting the regular name pools. We must change the symbols'
+      // description here.
+      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
+      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+
+      if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
+        // allocate TLS common symbol in tbss section
+        tbss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                          tbss_sect_data,
+                                                          (*com_sym)->value());
+      }
+      else {
+        bss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                         bss_sect_data,
+                                                         (*com_sym)->value());
+      }
+    }
+  }
+
+  // allocate all global common symbols
+  com_end = symbol_list.commonEnd();
+  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
+    // We have to reset the description of the symbol here. When doing
+    // incremental linking, the output relocatable object may have common
+    // symbols. Therefore, we can not treat common symbols as normal symbols
+    // when emitting the regular name pools. We must change the symbols'
+    // description here.
+    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
+    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
+    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+
+    if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
+      // allocate TLS common symbol in tbss section
+      tbss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                        tbss_sect_data,
+                                                        (*com_sym)->value());
+    }
+    else {
+      bss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                       bss_sect_data,
+                                                       (*com_sym)->value());
+    }
+  }
+
+  bss_sect->setSize(bss_offset);
+  tbss_sect->setSize(tbss_offset);
+  symbol_list.changeCommonsToGlobal();
+  return true;
 }
 
+
 /// createProgramHdrs - base on output sections to create the program headers
-void GNULDBackend::createProgramHdrs(LDContext& pContext)
+void GNULDBackend::createProgramHdrs(Output& pOutput, const MCLDInfo& pInfo)
 {
+  assert(pOutput.hasContext());
+  ELFFileFormat *file_format = getOutputFormat(pOutput);
+
   // make PT_PHDR
   m_ELFSegmentTable.produce(llvm::ELF::PT_PHDR);
 
   // make PT_INTERP
-  LDSection* interp = pContext.getSection(".interp");
-  if (NULL != interp) {
+  if (file_format->hasInterp()) {
     ELFSegment* interp_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_INTERP);
-    interp_seg->addSection(interp);
-    interp_seg->setAlign(bitclass() / 8);
+    interp_seg->addSection(&file_format->getInterp());
+  }
+
+  if (pInfo.options().hasRelro()) {
+    // if -z relro is given, we need to adjust sections' offset again, and let
+    // PT_GNU_RELRO end on a common page boundary
+    LDContext::SectionTable& sect_table = pOutput.context()->getSectionTable();
+    size_t idx = 0;
+    while (idx < pOutput.context()->numOfSections()) {
+      // find the first non-relro section, and align its offset to a page
+      // boundary
+      if (getSectionOrder(pOutput, *sect_table[idx], pInfo) > SHO_RELRO_LAST) {
+        uint64_t offset = sect_table[idx]->offset();
+        alignAddress(offset, commonPageSize(pInfo));
+        sect_table[idx]->setOffset(offset);
+        ++idx;
+        break;
+      }
+      ++idx;
+    }
+    while (idx < pOutput.context()->numOfSections()) {
+      // adjust the remaining sections' offset
+      uint64_t offset = sect_table[idx - 1]->offset();
+      if (LDFileFormat::BSS != sect_table[idx - 1]->kind())
+        offset += sect_table[idx - 1]->size();
+      alignAddress(offset, sect_table[idx]->align());
+      sect_table[idx]->setOffset(offset);
+      ++idx;
+    }
   }
 
   uint32_t cur_seg_flag, prev_seg_flag = getSegmentFlag(0);
   uint64_t padding = 0;
   ELFSegment* load_seg = NULL;
   // make possible PT_LOAD segments
-  LDContext::sect_iterator sect, sect_end = pContext.sectEnd();
-  for (sect = pContext.sectBegin(); sect != sect_end; ++sect) {
+  LDContext::sect_iterator sect, sect_end = pOutput.context()->sectEnd();
+  for (sect = pOutput.context()->sectBegin(); sect != sect_end; ++sect) {
+
     if (0 == ((*sect)->flag() & llvm::ELF::SHF_ALLOC) &&
         LDFileFormat::Null != (*sect)->kind())
       continue;
@@ -829,36 +1411,60 @@
          LDFileFormat::Null == (*sect)->kind()) {
       // create new PT_LOAD segment
       load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD);
-      load_seg->setAlign(pagesize());
+      load_seg->setAlign(commonPageSize(pInfo));
 
       // check if this segment needs padding
       padding = 0;
-      if (((*sect)->offset() & (load_seg->align() - 1)) != 0)
-        padding = load_seg->align();
+      if (((*sect)->offset() & (abiPageSize(pInfo) - 1)) != 0)
+        padding = abiPageSize(pInfo);
     }
 
     assert(NULL != load_seg);
-    load_seg->addSection(*sect);
-    load_seg->updateFlag(cur_seg_flag);
+    load_seg->addSection((*sect));
+    if (cur_seg_flag != prev_seg_flag)
+      load_seg->updateFlag(cur_seg_flag);
 
-    // FIXME: set section's vma
-    // need to handle start vma for user-defined one or for executable.
-    (*sect)->setAddr((*sect)->offset() + padding);
+    if (LDFileFormat::Null != (*sect)->kind())
+      (*sect)->setAddr(segmentStartAddr(pOutput, pInfo) +
+                       (*sect)->offset() +
+                       padding);
 
     prev_seg_flag = cur_seg_flag;
   }
 
   // make PT_DYNAMIC
-  LDSection* dynamic = pContext.getSection(".dynamic");
-  if (NULL != dynamic) {
-    ELFSegment* dyn_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_DYNAMIC);
-    dyn_seg->setFlag(llvm::ELF::PF_R | llvm::ELF::PF_W);
-    dyn_seg->addSection(dynamic);
-    dyn_seg->setAlign(bitclass() / 8);
+  if (file_format->hasDynamic()) {
+    ELFSegment* dyn_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_DYNAMIC,
+                                                    llvm::ELF::PF_R |
+                                                    llvm::ELF::PF_W);
+    dyn_seg->addSection(&file_format->getDynamic());
   }
 
+  if (pInfo.options().hasRelro()) {
+    // make PT_GNU_RELRO
+    ELFSegment* relro_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_RELRO);
+    for (LDContext::sect_iterator sect = pOutput.context()->sectBegin();
+         sect != pOutput.context()->sectEnd(); ++sect) {
+      unsigned int order = getSectionOrder(pOutput, **sect, pInfo);
+      if (SHO_RELRO_LOCAL == order ||
+          SHO_RELRO == order ||
+          SHO_RELRO_LAST == order) {
+        relro_seg->addSection(*sect);
+      }
+    }
+  }
+
+  // make PT_GNU_EH_FRAME
+  if (file_format->hasEhFrameHdr()) {
+    ELFSegment* eh_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_EH_FRAME);
+    eh_seg->addSection(&file_format->getEhFrameHdr());
+  }
+}
+
+/// setupProgramHdrs - set up the attributes of segments
+void GNULDBackend:: setupProgramHdrs(const Output& pOutput, const MCLDInfo& pInfo)
+{
   // update segment info
-  uint64_t file_size = 0;
   ELFSegmentFactory::iterator seg, seg_end = m_ELFSegmentTable.end();
   for (seg = m_ELFSegmentTable.begin(); seg != seg_end; ++seg) {
     ELFSegment& segment = *seg;
@@ -875,7 +1481,7 @@
         phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
       }
       segment.setOffset(offset);
-      segment.setVaddr(offset);
+      segment.setVaddr(segmentStartAddr(pOutput, pInfo) + offset);
       segment.setPaddr(segment.vaddr());
       segment.setFilesz(numOfSegments() * phdr_size);
       segment.setMemsz(numOfSegments() * phdr_size);
@@ -883,14 +1489,21 @@
       continue;
     }
 
-    assert(NULL != segment.getFirstSection());
+    // bypass if there is no section in this segment (e.g., PT_GNU_STACK)
+    if (segment.numOfSections() == 0)
+      continue;
+
     segment.setOffset(segment.getFirstSection()->offset());
-    segment.setVaddr(segment.getFirstSection()->addr());
+    if (llvm::ELF::PT_LOAD == segment.type() &&
+        LDFileFormat::Null == segment.getFirstSection()->kind())
+      segment.setVaddr(segmentStartAddr(pOutput, pInfo));
+    else
+      segment.setVaddr(segment.getFirstSection()->addr());
     segment.setPaddr(segment.vaddr());
 
     const LDSection* last_sect = segment.getLastSection();
     assert(NULL != last_sect);
-    file_size = last_sect->offset() - segment.offset();
+    uint64_t file_size = last_sect->offset() - segment.offset();
     if (LDFileFormat::BSS != last_sect->kind())
       file_size += last_sect->size();
     segment.setFilesz(file_size);
@@ -899,61 +1512,58 @@
   }
 }
 
-/// writeELF32ProgramHdrs - write out the ELF32 program headers
-void GNULDBackend::writeELF32ProgramHdrs(Output& pOutput)
+/// createGNUStackInfo - create an output GNU stack section or segment if needed
+/// @ref gold linker: layout.cc:2608
+void GNULDBackend::createGNUStackInfo(const Output& pOutput,
+                                      const MCLDInfo& pInfo,
+                                      MCLinker& pLinker)
 {
-  assert(pOutput.hasMemArea());
+  uint32_t flag = 0x0;
+  if (pInfo.options().hasStackSet()) {
+    // 1. check the command line option (-z execstack or -z noexecstack)
+    if (pInfo.options().hasExecStack())
+      flag = llvm::ELF::SHF_EXECINSTR;
+  } else {
+    // 2. check the stack info from the input objects
+    size_t object_count = 0, stack_note_count = 0;
+    mcld::InputTree::const_bfs_iterator input, inEnd = pInfo.inputs().bfs_end();
+    for (input=pInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
+      if ((*input)->type() == Input::Object) {
+        ++object_count;
+        const LDSection* sect = (*input)->context()->getSection(
+                                                             ".note.GNU-stack");
+        if (NULL != sect) {
+          ++stack_note_count;
+          // 2.1 found a stack note that is set as executable
+          if (0 != (llvm::ELF::SHF_EXECINSTR & sect->flag())) {
+            flag = llvm::ELF::SHF_EXECINSTR;
+            break;
+          }
+        }
+      }
+    }
 
-  uint64_t start_offset, phdr_size;
+    // 2.2 there are no stack note sections in all input objects
+    if (0 == stack_note_count)
+      return;
 
-  start_offset = sizeof(llvm::ELF::Elf32_Ehdr);
-  phdr_size = sizeof(llvm::ELF::Elf32_Phdr);
-  // Program header must start directly after ELF header
-  MemoryRegion *region = pOutput.memArea()->request(start_offset,
-                                                    numOfSegments()*phdr_size);
-
-  llvm::ELF::Elf32_Phdr* phdr = (llvm::ELF::Elf32_Phdr*)region->start();
-
-  size_t index = 0;
-  ELFSegmentFactory::iterator seg, segEnd = m_ELFSegmentTable.end();
-  for (seg = m_ELFSegmentTable.begin(); seg != segEnd; ++seg, ++index) {
-    phdr[index].p_type   = (*seg).type();
-    phdr[index].p_flags  = (*seg).flag();
-    phdr[index].p_offset = (*seg).offset();
-    phdr[index].p_vaddr  = (*seg).vaddr();
-    phdr[index].p_paddr  = (*seg).paddr();
-    phdr[index].p_filesz = (*seg).filesz();
-    phdr[index].p_memsz  = (*seg).memsz();
-    phdr[index].p_align  = (*seg).align();
+    // 2.3 a special case. Use the target default to decide if the stack should
+    //     be executable
+    if (llvm::ELF::SHF_EXECINSTR != flag && object_count != stack_note_count)
+      if (isDefaultExecStack())
+        flag = llvm::ELF::SHF_EXECINSTR;
   }
-}
 
-/// writeELF64ProgramHdrs - write out the ELF64 program headers
-void GNULDBackend::writeELF64ProgramHdrs(Output& pOutput)
-{
-  assert(pOutput.hasMemArea());
-
-  uint64_t start_offset, phdr_size;
-
-  start_offset = sizeof(llvm::ELF::Elf64_Ehdr);
-  phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
-  // Program header must start directly after ELF header
-  MemoryRegion *region = pOutput.memArea()->request(start_offset,
-                                                    numOfSegments() *phdr_size);
-  llvm::ELF::Elf64_Phdr* phdr = (llvm::ELF::Elf64_Phdr*)region->start();
-
-  size_t index = 0;
-  ELFSegmentFactory::iterator seg, segEnd = m_ELFSegmentTable.end();
-  for (seg = m_ELFSegmentTable.begin(); seg != segEnd; ++seg, ++index) {
-    phdr[index].p_type   = (*seg).type();
-    phdr[index].p_flags  = (*seg).flag();
-    phdr[index].p_offset = (*seg).offset();
-    phdr[index].p_vaddr  = (*seg).vaddr();
-    phdr[index].p_paddr  = (*seg).paddr();
-    phdr[index].p_filesz = (*seg).filesz();
-    phdr[index].p_memsz  = (*seg).memsz();
-    phdr[index].p_align  = (*seg).align();
-  }
+  if (pOutput.type() != Output::Object)
+    m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_STACK,
+                              llvm::ELF::PF_R |
+                              llvm::ELF::PF_W |
+                              getSegmentFlag(flag));
+  else
+    pLinker.getOrCreateOutputSectHdr(".note.GNU-stack",
+                                     LDFileFormat::Note,
+                                     llvm::ELF::SHT_PROGBITS,
+                                     flag);
 }
 
 /// preLayout - Backend can do any needed modification before layout
@@ -963,6 +1573,16 @@
 {
   // prelayout target first
   doPreLayout(pOutput, pLDInfo, pLinker);
+
+  if (pLDInfo.options().hasEhFrameHdr()) {
+    // init EhFrameHdr and size the output section
+    ELFFileFormat* format = getOutputFormat(pOutput);
+    assert(NULL != getEhFrame());
+    m_pEhFrameHdr = new EhFrameHdr(*getEhFrame(),
+                                   format->getEhFrame(),
+                                   format->getEhFrameHdr());
+    m_pEhFrameHdr->sizeOutput();
+  }
 }
 
 /// postLayout -Backend can do any needed modification after layout
@@ -970,10 +1590,36 @@
                               const MCLDInfo& pInfo,
                               MCLinker& pLinker)
 {
-  // post layout target first
+  // 1. emit program headers
+  if (pOutput.type() != Output::Object) {
+    // 1.1 create program headers
+    createProgramHdrs(pLinker.getLDInfo().output(), pInfo);
+  }
+
+  // 1.2 create special GNU Stack note section or segment
+  createGNUStackInfo(pOutput, pInfo, pLinker);
+
+  if (pOutput.type() != Output::Object) {
+    // 1.3 set up the attributes of program headers
+    setupProgramHdrs(pOutput, pInfo);
+  }
+
+  // 2. target specific post layout
   doPostLayout(pOutput, pInfo, pLinker);
 }
 
+void GNULDBackend::postProcessing(const Output& pOutput,
+                                  const MCLDInfo& pInfo,
+                                  MCLinker& pLinker)
+{
+  if (pInfo.options().hasEhFrameHdr()) {
+    // emit eh_frame_hdr
+    if (bitclass() == 32)
+      m_pEhFrameHdr->emitOutput<32>(pLinker.getLDInfo().output(),
+                                    pLinker);
+  }
+}
+
 /// getHashBucketCount - calculate hash bucket count.
 /// @ref Google gold linker, dynobj.cc:791
 unsigned GNULDBackend::getHashBucketCount(unsigned pNumOfSymbols,
@@ -1012,10 +1658,147 @@
 
   // If we are building shared object, and the visibility is external, we
   // need to add it.
-  if (Output::DynObj == pOutput.type())
+  if (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type())
     if (pSymbol.resolveInfo()->visibility() == ResolveInfo::Default ||
         pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected)
       return true;
+  return false;
+}
+
+/// commonPageSize - the common page size of the target machine.
+/// @ref gold linker: target.h:135
+uint64_t GNULDBackend::commonPageSize(const MCLDInfo& pInfo) const
+{
+  if (pInfo.options().commPageSize() > 0)
+    return std::min(pInfo.options().commPageSize(), abiPageSize(pInfo));
+  else
+    return std::min(static_cast<uint64_t>(0x1000), abiPageSize(pInfo));
+}
+
+/// abiPageSize - the abi page size of the target machine.
+/// @ref gold linker: target.h:125
+uint64_t GNULDBackend::abiPageSize(const MCLDInfo& pInfo) const
+{
+  if (pInfo.options().maxPageSize() > 0)
+    return pInfo.options().maxPageSize();
+  else
+    return static_cast<uint64_t>(0x1000);
+}
+
+/// isOutputPIC - return whether the output is position-independent
+bool GNULDBackend::isOutputPIC(const Output& pOutput,
+                               const MCLDInfo& pInfo) const
+{
+  if (Output::DynObj == pOutput.type() || pInfo.options().isPIE())
+    return true;
+  return false;
+}
+
+/// isStaticLink - return whether we're doing static link
+bool GNULDBackend::isStaticLink(const Output& pOutput,
+                                const MCLDInfo& pInfo) const
+{
+  InputTree::const_iterator it = pInfo.inputs().begin();
+  if (!isOutputPIC(pOutput, pInfo) && (*it)->attribute()->isStatic())
+    return true;
+  return false;
+}
+
+/// isSymbolPreemtible - whether the symbol can be preemted by other
+/// link unit
+/// @ref Google gold linker, symtab.h:551
+bool GNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
+                                       const MCLDInfo& pLDInfo,
+                                       const Output& pOutput) const
+{
+  if (pSym.other() != ResolveInfo::Default)
+    return false;
+
+  if (Output::DynObj != pOutput.type())
+    return false;
+
+  if (pLDInfo.options().Bsymbolic())
+    return false;
+
+  return true;
+}
+
+/// symbolNeedsPLT - return whether the symbol needs a PLT entry
+/// @ref Google gold linker, symtab.h:596
+bool GNULDBackend::symbolNeedsPLT(const ResolveInfo& pSym,
+                                  const MCLDInfo& pLDInfo,
+                                  const Output& pOutput) const
+{
+  if (pSym.isUndef() && !pSym.isDyn() && pOutput.type() != Output::DynObj)
+    return false;
+
+  // An IndirectFunc symbol (i.e., STT_GNU_IFUNC) always needs a plt entry
+  if (pSym.type() == ResolveInfo::IndirectFunc)
+    return true;
+
+  if (pSym.type() != ResolveInfo::Function)
+    return false;
+
+  if (isStaticLink(pOutput, pLDInfo) || pLDInfo.options().isPIE())
+    return false;
+
+  return (pSym.isDyn() ||
+          pSym.isUndef() ||
+          isSymbolPreemptible(pSym, pLDInfo, pOutput));
+}
+
+/// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
+/// @ref Google gold linker, symtab.h:645
+bool GNULDBackend::symbolNeedsDynRel(const ResolveInfo& pSym,
+                                     bool pSymHasPLT,
+                                     const MCLDInfo& pLDInfo,
+                                     const Output& pOutput,
+                                     bool isAbsReloc) const
+{
+  // an undefined reference in the executables should be statically
+  // resolved to 0 and no need a dynamic relocation
+  if (pSym.isUndef() && !pSym.isDyn() && (Output::Exec == pOutput.type()))
+    return false;
+  if (pSym.isAbsolute())
+    return false;
+  if (isOutputPIC(pOutput, pLDInfo) && isAbsReloc)
+    return true;
+  if (pSymHasPLT && ResolveInfo::Function == pSym.type())
+    return false;
+  if (!isOutputPIC(pOutput, pLDInfo) && pSymHasPLT)
+    return false;
+  if (pSym.isDyn() || pSym.isUndef() ||
+      isSymbolPreemptible(pSym, pLDInfo, pOutput))
+    return true;
 
   return false;
 }
+
+/// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
+bool GNULDBackend::symbolNeedsCopyReloc(const Layout& pLayout,
+                                        const Relocation& pReloc,
+                                        const ResolveInfo& pSym,
+                                        const MCLDInfo& pLDInfo,
+                                        const Output& pOutput) const
+{
+  // only the reference from dynamic executable to non-function symbol in
+  // the dynamic objects may need copy relocation
+  if (isOutputPIC(pOutput, pLDInfo) ||
+      !pSym.isDyn() ||
+      pSym.type() == ResolveInfo::Function ||
+      pSym.size() == 0)
+    return false;
+
+  // check if the option -z nocopyreloc is given
+  if (pLDInfo.options().hasNoCopyReloc())
+    return false;
+
+  // TODO: Is this check necessary?
+  // if relocation target place is readonly, a copy relocation is needed
+  if ((pLayout.getOutputLDSection(*pReloc.targetRef().frag())->flag() &
+      llvm::ELF::SHF_WRITE) == 0)
+    return true;
+
+  return false;
+}
+
diff --git a/lib/Target/Mips/MipsAndroidSectLinker.cpp b/lib/Target/Mips/MipsAndroidSectLinker.cpp
deleted file mode 100644
index e697fbc..0000000
--- a/lib/Target/Mips/MipsAndroidSectLinker.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- MipsAndroidSectLinker.cpp ------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsAndroidSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-MipsAndroidSectLinker::MipsAndroidSectLinker(SectLinkerOption &pOption,
-                                             TargetLDBackend &pLDBackend)
-  : AndroidSectLinker(pOption,
-                      pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attibutes
-  info.attrFactory().constraint().disableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().unsetWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-}
-
-MipsAndroidSectLinker::~MipsAndroidSectLinker()
-{
-}
diff --git a/lib/Target/Mips/MipsAndroidSectLinker.h b/lib/Target/Mips/MipsAndroidSectLinker.h
deleted file mode 100644
index ba216e4..0000000
--- a/lib/Target/Mips/MipsAndroidSectLinker.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- MipsAndroidSectLinker.h --------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MIPS_ANDROIDSECTLINKER_H
-#define MIPS_ANDROIDSECTLINKER_H
-
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include "mcld/Target/AndroidSectLinker.h"
-
-namespace mcld
-{
-
-/** \class MipsAndroidSectLinker
- *  \brief MipsAndroidSectLinker sets up the environment for linking.
- *
- */
-class MipsAndroidSectLinker : public AndroidSectLinker
-{
-public:
-  MipsAndroidSectLinker(SectLinkerOption &pOption,
-                        mcld::TargetLDBackend &pLDBackend);
-
-  ~MipsAndroidSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
diff --git a/lib/Target/Mips/MipsDiagnostic.cpp b/lib/Target/Mips/MipsDiagnostic.cpp
new file mode 100644
index 0000000..c90c6ef
--- /dev/null
+++ b/lib/Target/Mips/MipsDiagnostic.cpp
@@ -0,0 +1,35 @@
+//===- MipsDiagnostic.cpp -------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/DWARFLineInfo.h>
+#include "Mips.h"
+
+using namespace mcld;
+
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createMipsDiagnostic - the help function to create corresponding
+// MipsDiagnostic
+DiagnosticLineInfo* createMipsDiagLineInfo(const llvm::Target& pTarget,
+                                           const std::string &pTriple)
+{
+  return new DWARFLineInfo();
+}
+
+} // namespace of mcld
+
+//==========================
+// InitializeMipsDiagnostic
+extern "C" void LLVMInitializeMipsDiagnosticLineInfo() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheMipselTarget, createMipsDiagLineInfo);
+}
+
diff --git a/lib/Target/Mips/MipsELFSectLinker.cpp b/lib/Target/Mips/MipsELFSectLinker.cpp
index aa41f36..dedf505 100644
--- a/lib/Target/Mips/MipsELFSectLinker.cpp
+++ b/lib/Target/Mips/MipsELFSectLinker.cpp
@@ -6,7 +6,6 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-
 #include "MipsELFSectLinker.h"
 
 #include <mcld/CodeGen/SectLinkerOption.h>
@@ -31,3 +30,4 @@
 MipsELFSectLinker::~MipsELFSectLinker()
 {
 }
+
diff --git a/lib/Target/Mips/MipsELFSectLinker.h b/lib/Target/Mips/MipsELFSectLinker.h
index 949508d..1aacfef 100644
--- a/lib/Target/Mips/MipsELFSectLinker.h
+++ b/lib/Target/Mips/MipsELFSectLinker.h
@@ -6,8 +6,8 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#ifndef MIPS_ELFSECTLINKER_H
-#define MIPS_ELFSECTLINKER_H
+#ifndef MIPS_ELF_SECTION_LINKER_H
+#define MIPS_ELF_SECTION_LINKER_H
 #ifdef ENABLE_UNITTEST
 #include <gtest.h>
 #endif
@@ -31,3 +31,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
index e1185ca..9baa033 100644
--- a/lib/Target/Mips/MipsGOT.cpp
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -7,9 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/LD/ResolveInfo.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include "MipsGOT.h"
 
 namespace {
@@ -31,7 +31,7 @@
       new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
 
     if (NULL == entry)
-      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+      fatal(diag::fail_allocate_memory) << "GOT0";
 
     m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
   }
@@ -41,8 +41,7 @@
   iterator ie = m_SectionData.end();
 
   for (size_t i = 1; i < MipsGOT0Num; ++i) {
-    if (it == ie)
-      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
+    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
 
     ++it;
   }
@@ -95,7 +94,7 @@
       new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
 
     if (NULL == entry)
-      llvm::report_fatal_error("Allocating new GOTEntry failed");
+      fatal(diag::fail_allocate_memory) << "GOTEntry";
 
     m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
   }
@@ -118,12 +117,22 @@
 
 GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
 {
+  if (isLocal(&pInfo) && pInfo.type() == ResolveInfo::Section) {
+    pExist = false;
+    iterator& it = m_LocalGOTIterator;
+    ++it;
+    assert(it != m_SectionData.getFragmentList().end() &&
+           "The number of GOT Entries and ResolveInfo doesn't match");
+    GOTEntry* entry = llvm::cast<GOTEntry>(&(*it));
+    return entry;
+  }
+
   GOTEntry*& entry = m_GeneralGOTMap[&pInfo];
 
   pExist = NULL != entry;
 
   if (!pExist) {
-    iterator& it = pInfo.isLocal() ? m_LocalGOTIterator : m_GlobalGOTIterator;
+    iterator& it = isLocal(&pInfo)  ? m_LocalGOTIterator : m_GlobalGOTIterator;
 
     ++it;
 
@@ -145,3 +154,4 @@
 {
   return m_pLocalNum;
 }
+
diff --git a/lib/Target/Mips/MipsGOT.h b/lib/Target/Mips/MipsGOT.h
index dc8a23e..2f04ef4 100644
--- a/lib/Target/Mips/MipsGOT.h
+++ b/lib/Target/Mips/MipsGOT.h
@@ -26,6 +26,7 @@
 {
 private:
   typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
+  typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolTypeMapType;
 
 public:
   typedef llvm::MCSectionData::iterator iterator;
@@ -50,8 +51,26 @@
   size_t getTotalNum() const;
   size_t getLocalNum() const;
 
+  void setLocal(const ResolveInfo* pInfo) {
+    m_GOTTypeMap[pInfo] = false;
+  }
+
+  void setGlobal(const ResolveInfo* pInfo) {
+    m_GOTTypeMap[pInfo] = true;
+  }
+
+  bool isLocal(const ResolveInfo* pInfo) {
+    return m_GOTTypeMap[pInfo] == false;
+  }
+
+  bool isGlobal(const ResolveInfo* pInfo) {
+    return m_GOTTypeMap[pInfo] == true;
+  }
+
 private:
-  SymbolIndexMapType m_GeneralGOTMap;
+  SymbolIndexMapType m_GeneralGOTMap; // Map ResolveInfo* to GOTEntry *.
+  SymbolTypeMapType m_GOTTypeMap;
+
   iterator m_LocalGOTIterator;  // last local GOT entries
   iterator m_GlobalGOTIterator; // last global GOT entries
   size_t m_pLocalNum;
@@ -64,3 +83,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
index c7a6b23..87e43b8 100644
--- a/lib/Target/Mips/MipsLDBackend.cpp
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -14,6 +14,7 @@
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/MC/MCLinker.h>
 #include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/Target/OutputRelocSection.h>
 
@@ -66,11 +67,24 @@
 
 void MipsGNULDBackend::initTargetSections(MCLinker& pLinker)
 {
-  // Nothing to do because we do not support
-  // any MIPS specific sections now.
+  // Set up .dynamic
+  ELFFileFormat* file_format = NULL;
+  switch(pLinker.getLDInfo().output().type()) {
+    case Output::DynObj:
+      file_format = getDynObjFileFormat();
+      break;
+    case Output::Exec:
+      file_format = getExecFileFormat();
+      break;
+    case Output::Object:
+    default:
+      // TODO: not support yet
+      return;
+  }
+  file_format->getDynamic().setFlag(llvm::ELF::SHF_ALLOC);
 }
 
-void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker)
+void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
@@ -120,12 +134,21 @@
                                       const LDSymbol& pInputSym,
                                       MCLinker& pLinker,
                                       const MCLDInfo& pLDInfo,
-                                      const Output& pOutput)
+                                      const Output& pOutput,
+                                      const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
 
+  assert(NULL != pSection.getLink());
+  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
+    if (rsym->isLocal()) {
+      updateAddend(pReloc, pInputSym, pLinker.getLayout());
+    }
+    return;
+  }
+
   // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies
   // that a .got section is needed.
   if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
@@ -134,7 +157,15 @@
     }
   }
 
-  if (rsym->isLocal())
+  // Skip relocation against _gp_disp
+  if (strcmp("_gp_disp", pInputSym.name()) == 0)
+    return;
+
+  // We test isLocal or if pInputSym is not a dynamic symbol
+  // We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
+  // Don't put undef symbols into local entries.
+  if ((rsym->isLocal() || !isDynamicSymbol(pInputSym, pOutput) ||
+      !rsym->isDyn()) && !rsym->isUndef())
     scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
   else
     scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
@@ -177,6 +208,11 @@
   return 32;
 }
 
+uint64_t MipsGNULDBackend::defaultTextSegmentAddr() const
+{
+  return 0x80000;
+}
+
 void MipsGNULDBackend::doPreLayout(const Output& pOutput,
                                    const MCLDInfo& pInfo,
                                    MCLinker& pLinker)
@@ -191,9 +227,6 @@
                                     const MCLDInfo& pInfo,
                                     MCLinker& pLinker)
 {
-  // emit program headers
-  if (pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
-    emitProgramHdrs(pLinker.getLDInfo().output());
 }
 
 /// dynamic - the dynamic section of the target machine.
@@ -217,11 +250,12 @@
 uint64_t MipsGNULDBackend::emitSectionData(const Output& pOutput,
                                            const LDSection& pSection,
                                            const MCLDInfo& pInfo,
+                                           const Layout& pLayout,
                                            MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   if (&pSection == &(file_format->getGOT())) {
     assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
@@ -229,17 +263,15 @@
     return result;
   }
 
-  llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
-                           pSection.name() +
-                           llvm::Twine("'.\n"));
+  fatal(diag::unrecognized_output_sectoin)
+          << pSection.name()
+          << "[email protected]";
   return 0;
 }
-/// isGOTSymbol - return true if the symbol is the GOT entry.
-bool MipsGNULDBackend::isGOTSymbol(const LDSymbol& pSymbol) const
+/// isGlobalGOTSymbol - return true if the symbol is the global GOT entry.
+bool MipsGNULDBackend::isGlobalGOTSymbol(const LDSymbol& pSymbol) const
 {
-  return std::find(m_LocalGOTSyms.begin(),
-                   m_LocalGOTSyms.end(), &pSymbol) != m_LocalGOTSyms.end() ||
-         std::find(m_GlobalGOTSyms.begin(),
+  return std::find(m_GlobalGOTSyms.begin(),
                    m_GlobalGOTSyms.end(), &pSymbol) != m_GlobalGOTSyms.end();
 }
 
@@ -326,7 +358,7 @@
     if (!isDynamicSymbol(**symbol, pOutput))
       continue;
 
-    if (isGOTSymbol(**symbol))
+    if (isGlobalGOTSymbol(**symbol))
       continue;
 
     emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
@@ -342,6 +374,12 @@
        symbol_end = m_GlobalGOTSyms.end();
        symbol != symbol_end; ++symbol) {
 
+    // Make sure this golbal GOT entry is a dynamic symbol.
+    // If not, something is wrong earlier when putting this symbol into
+    //  global GOT.
+    if (!isDynamicSymbol(**symbol, pOutput))
+      fatal(diag::mips_got_symbol) << (*symbol)->name();
+
     emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
                       strtabsize, symtabIdx);
 
@@ -382,7 +420,8 @@
 
   // emit soname
   // initialize value of ELF .dynamic section
-  dynamic().applySoname(strtabsize);
+  if (Output::DynObj == pOutput.type())
+    dynamic().applySoname(strtabsize);
   dynamic().applyEntries(pLDInfo, *file_format);
   dynamic().emit(dyn_sect, *dyn_region);
 
@@ -445,9 +484,10 @@
 
 unsigned int
 MipsGNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                        const LDSection& pSectHdr) const
+                                        const LDSection& pSectHdr,
+                                        const MCLDInfo& pInfo) const
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
   if (&pSectHdr == &file_format->getGOT())
     return SHO_DATA;
@@ -456,15 +496,10 @@
 }
 
 /// finalizeSymbol - finalize the symbol value
-/// If the symbol's reserved field is not zero, MCLinker will call back this
-/// function to ask the final value of the symbol
-bool MipsGNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+bool MipsGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
-  if (&pSymbol == m_pGpDispSymbol) {
-    m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
-    return true;
-  }
-  return false;
+  m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
+  return true;
 }
 
 /// allocateCommonSymbols - allocate common symbols in the corresponding
@@ -474,96 +509,112 @@
 bool
 MipsGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
 {
-  // SymbolCategory contains all symbols that must emit to the output files.
-  // We are not like Google gold linker, we don't remember symbols before symbol
-  // resolution. All symbols in SymbolCategory are already resolved. Therefore, we
-  // don't need to care about some symbols may be changed its category due to symbol
-  // resolution.
   SymbolCategory& symbol_list = pLinker.getOutputSymbols();
 
   if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
     return true;
 
-  // addralign := max value of all common symbols
-  uint64_t addralign = 0x0;
-
-  // Due to the visibility, some common symbols may be forcefully local.
-  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      if ((*com_sym)->value() > addralign)
-        addralign = (*com_sym)->value();
-    }
-  }
-
-  // global common symbols.
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    if ((*com_sym)->value() > addralign)
-      addralign = (*com_sym)->value();
-  }
+  SymbolCategory::iterator com_sym, com_end;
 
   // FIXME: If the order of common symbols is defined, then sort common symbols
-  // com_sym = symbol_list.commonBegin();
   // std::sort(com_sym, com_end, some kind of order);
 
   // get or create corresponding BSS LDSection
-  LDSection* bss_sect_hdr = NULL;
-  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
+  LDSection* bss_sect = &pLinker.getOrCreateOutputSectHdr(".bss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+
+  LDSection* tbss_sect = &pLinker.getOrCreateOutputSectHdr(
                                    ".tbss",
                                    LDFileFormat::BSS,
                                    llvm::ELF::SHT_NOBITS,
                                    llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
-  else {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
+
+  // FIXME: .sbss amd .lbss currently unused.
+  /*
+  LDSection* sbss_sect = &pLinker.getOrCreateOutputSectHdr(
+                                   ".sbss",
                                    LDFileFormat::BSS,
                                    llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC |
+                                   llvm::ELF::SHF_MIPS_GPREL);
+
+  LDSection* lbss_sect = &pLinker.getOrCreateOutputSectHdr(
+                                   ".lbss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC |
+                                   llvm::ELF::SHF_MIPS_LOCAL);
+  */
+
+  assert(NULL != bss_sect && NULL != tbss_sect);
 
   // get or create corresponding BSS MCSectionData
-  assert(NULL != bss_sect_hdr);
-  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
+  llvm::MCSectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
+  llvm::MCSectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
 
-  // allocate all common symbols
-  uint64_t offset = bss_sect_hdr->size();
+  // remember original BSS size
+  uint64_t bss_offset  = bss_sect->size();
+  uint64_t tbss_offset = tbss_sect->size();
 
   // allocate all local common symbols
   com_end = symbol_list.localEnd();
+
   for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
     if (ResolveInfo::Common == (*com_sym)->desc()) {
-      alignAddress(offset, (*com_sym)->value());
       // We have to reset the description of the symbol here. When doing
       // incremental linking, the output relocatable object may have common
       // symbols. Therefore, we can not treat common symbols as normal symbols
       // when emitting the regular name pools. We must change the symbols'
       // description here.
       (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section);
+      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
       (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-      offset += (*com_sym)->size();
+
+      if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
+        // allocate TLS common symbol in tbss section
+        tbss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                          tbss_sect_data,
+                                                          (*com_sym)->value());
+      }
+      // FIXME: how to identify small and large common symbols?
+      else {
+        bss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                         bss_sect_data,
+                                                         (*com_sym)->value());
+      }
     }
   }
 
   // allocate all global common symbols
   com_end = symbol_list.commonEnd();
   for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    alignAddress(offset, (*com_sym)->value());
-
     // We have to reset the description of the symbol here. When doing
     // incremental linking, the output relocatable object may have common
     // symbols. Therefore, we can not treat common symbols as normal symbols
     // when emitting the regular name pools. We must change the symbols'
     // description here.
     (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size(), &bss_section);
+    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
     (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-    offset += (*com_sym)->size();
+
+    if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
+      // allocate TLS common symbol in tbss section
+      tbss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                        tbss_sect_data,
+                                                        (*com_sym)->value());
+    }
+    // FIXME: how to identify small and large common symbols?
+    else {
+      bss_offset += pLinker.getLayout().appendFragment(*frag,
+                                                       bss_sect_data,
+                                                       (*com_sym)->value());
+    }
   }
 
-  bss_sect_hdr->setSize(offset);
+  bss_sect->setSize(bss_offset);
+  tbss_sect->setSize(tbss_offset);
   symbol_list.changeCommonsToGlobal();
   return true;
 }
@@ -573,7 +624,7 @@
                                    const Layout& pLayout) const
 {
   // Update value keep in addend if we meet a section symbol
-  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
     pReloc.setAddend(pLayout.getOutputOffset(
                      *pInputSym.fragRef()) + pReloc.addend());
   }
@@ -604,6 +655,12 @@
 
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         rsym->setReserved(rsym->reserved() | ReserveRel);
+
+        // Remeber this rsym is a local GOT entry (as if it needs an entry).
+        // Actually we don't allocate an GOT entry.
+        if (NULL == m_pGOT)
+          createGOT(pLinker, pOutput);
+        m_pGOT->setLocal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_REL32:
@@ -637,10 +694,19 @@
       if (NULL == m_pGOT)
         createGOT(pLinker, pOutput);
 
+      // For got16 section based relocations, we need to reserve got entries.
+      if (rsym->type() == ResolveInfo::Section) {
+        m_pGOT->reserveLocalEntry();
+        // Remeber this rsym is a local GOT entry
+        m_pGOT->setLocal(rsym);
+        return;
+      }
+
       if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
         m_pGOT->reserveLocalEntry();
         rsym->setReserved(rsym->reserved() | ReserveGot);
-        m_LocalGOTSyms.push_back(rsym->outSymbol());
+        // Remeber this rsym is a local GOT entry
+        m_pGOT->setLocal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_GPREL32:
@@ -668,11 +734,8 @@
     case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
       break;
     default:
-      llvm::report_fatal_error(llvm::Twine("Unknown relocation ") +
-                               llvm::Twine(pReloc.type()) +
-                               llvm::Twine("for the local symbol `") +
-                               pReloc.symInfo()->name() +
-                               llvm::Twine("'."));
+      fatal(diag::unknown_relocation) << (int)pReloc.type()
+                                      << pReloc.symInfo()->name();
   }
 }
 
@@ -701,12 +764,18 @@
     case llvm::ELF::R_MIPS_64:
     case llvm::ELF::R_MIPS_HI16:
     case llvm::ELF::R_MIPS_LO16:
-      if (isSymbolNeedsDynRel(*rsym, pOutput)) {
+      if (symbolNeedsDynRel(*rsym, false, pLDInfo, pOutput, true)) {
         if (NULL == m_pRelDyn)
           createRelDyn(pLinker, pOutput);
 
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         rsym->setReserved(rsym->reserved() | ReserveRel);
+
+        // Remeber this rsym is a global GOT entry (as if it needs an entry).
+        // Actually we don't allocate an GOT entry.
+        if (NULL == m_pGOT)
+          createGOT(pLinker, pOutput);
+        m_pGOT->setGlobal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_GOT16:
@@ -725,16 +794,14 @@
         m_pGOT->reserveGlobalEntry();
         rsym->setReserved(rsym->reserved() | ReserveGot);
         m_GlobalGOTSyms.push_back(rsym->outSymbol());
+        // Remeber this rsym is a global GOT entry
+        m_pGOT->setGlobal(rsym);
       }
       break;
     case llvm::ELF::R_MIPS_LITERAL:
     case llvm::ELF::R_MIPS_GPREL32:
-      llvm::report_fatal_error(llvm::Twine("Relocation ") +
-                               llvm::Twine(pReloc.type()) +
-                               llvm::Twine(" is not defined for the "
-                                           "global symbol `") +
-                               pReloc.symInfo()->name() +
-                               llvm::Twine("'."));
+      fatal(diag::invalid_global_relocation) << (int)pReloc.type()
+                                             << pReloc.symInfo()->name();
       break;
     case llvm::ELF::R_MIPS_GPREL16:
       break;
@@ -766,45 +833,14 @@
     case llvm::ELF::R_MIPS_COPY:
     case llvm::ELF::R_MIPS_GLOB_DAT:
     case llvm::ELF::R_MIPS_JUMP_SLOT:
-      llvm::report_fatal_error(llvm::Twine("Relocation ") +
-                               llvm::Twine(pReloc.type()) +
-                               llvm::Twine("for the global symbol `") +
-                               pReloc.symInfo()->name() +
-                               llvm::Twine("' should only be seen "
-                                           "by the dynamic linker"));
+      fatal(diag::dynamic_relocation) << (int)pReloc.type();
       break;
     default:
-      llvm::report_fatal_error(llvm::Twine("Unknown relocation ") +
-                               llvm::Twine(pReloc.type()) +
-                               llvm::Twine("for the global symbol `") +
-                               pReloc.symInfo()->name() +
-                               llvm::Twine("'."));
+      fatal(diag::unknown_relocation) << (int)pReloc.type()
+                                      << pReloc.symInfo()->name();
   }
 }
 
-bool MipsGNULDBackend::isSymbolNeedsPLT(ResolveInfo& pSym,
-                                        const Output& pOutput) const
-{
-  return (Output::DynObj == pOutput.type() &&
-         ResolveInfo::Function == pSym.type() &&
-         (pSym.isDyn() || pSym.isUndef()));
-}
-
-bool MipsGNULDBackend::isSymbolNeedsDynRel(ResolveInfo& pSym,
-                                           const Output& pOutput) const
-{
-  if(pSym.isUndef() && Output::Exec == pOutput.type())
-    return false;
-  if(pSym.isAbsolute())
-    return false;
-  if(Output::DynObj == pOutput.type())
-    return true;
-  if(pSym.isDyn() || pSym.isUndef())
-    return true;
-
-  return false;
-}
-
 void MipsGNULDBackend::createGOT(MCLinker& pLinker, const Output& pOutput)
 {
   ELFFileFormat* file_format = getOutputFormat(pOutput);
@@ -813,7 +849,7 @@
   m_pGOT = new MipsGOT(got, pLinker.getOrCreateSectData(got));
 
   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
-  if( m_pGOTSymbol != NULL ) {
+  if ( m_pGOTSymbol != NULL ) {
     pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
@@ -851,22 +887,6 @@
                                      8);
 }
 
-ELFFileFormat* MipsGNULDBackend::getOutputFormat(const Output& pOutput) const
-{
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      return getDynObjFileFormat();
-    case Output::Exec:
-      return getExecFileFormat();
-    case Output::Object:
-      return NULL;
-    default:
-      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
-                               llvm::Twine(pOutput.type()));
-      return NULL;
-  }
-}
-
 //===----------------------------------------------------------------------===//
 /// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
 ///
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
index c4f1d46..f9742ed 100644
--- a/lib/Target/Mips/MipsLDBackend.h
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -43,7 +43,7 @@
   void initTargetSections(MCLinker& pLinker);
 
   /// initTargetSymbols - initialize target dependent symbols in output.
-  void initTargetSymbols(MCLinker& pLinker);
+  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// initRelocFactory - create and initialize RelocationFactory.
   bool initRelocFactory(const MCLinker& pLinker);
@@ -58,7 +58,8 @@
                       const LDSymbol& pInputSym,
                       MCLinker& pLinker,
                       const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+                      const Output& pOutput,
+                      const LDSection& pSection);
 
   uint32_t machine() const;
 
@@ -75,6 +76,8 @@
 
   unsigned int bitclass() const;
 
+  uint64_t defaultTextSegmentAddr() const;
+
   /// preLayout - Backend can do any needed modification before layout
   void doPreLayout(const Output& pOutput,
                    const MCLDInfo& pInfo,
@@ -107,11 +110,13 @@
   /// @param pOutput - the output file
   /// @param pSection - the given LDSection
   /// @param pInfo - all options in the command line.
+  /// @param pLayout - for comouting the size of fragment
   /// @param pRegion - the region to write out data
   /// @return the size of the table in the file.
   uint64_t emitSectionData(const Output& pOutput,
                            const LDSection& pSection,
                            const MCLDInfo& pInfo,
+                           const Layout& pLayout,
                            MemoryRegion& pRegion) const;
 
   /// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
@@ -128,12 +133,11 @@
 
   /// getTargetSectionOrder - compute the layout order of ARM target sections
   unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr) const;
+                                     const LDSection& pSectHdr,
+                                     const MCLDInfo& pInfo) const;
 
   /// finalizeSymbol - finalize the symbol value
-  /// If the symbol's reserved field is not zero, MCLinker will call back this
-  /// function to ask the final value of the symbol
-  bool finalizeSymbol(LDSymbol& pSymbol) const;
+  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// allocateCommonSymbols - allocate common symbols in the corresponding
   /// sections.
@@ -152,14 +156,9 @@
                       const MCLDInfo& pLDInfo,
                       const Output& pOutput);
 
-  bool isSymbolNeedsPLT(ResolveInfo& pSym, const Output& pOutput) const;
-  bool isSymbolNeedsDynRel(ResolveInfo& pSym, const Output& pOutput) const;
-
   void createGOT(MCLinker& pLinker, const Output& pOutput);
   void createRelDyn(MCLinker& pLinker, const Output& pOutput);
 
-  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
-
   /// updateAddend - update addend value of the relocation if the
   /// the target symbol is a section symbol. Addend is the offset
   /// in the section. This value should be updated after section
@@ -178,12 +177,11 @@
   LDSymbol* m_pGOTSymbol;
   LDSymbol* m_pGpDispSymbol;
 
-  std::vector<LDSymbol*> m_LocalGOTSyms;
   std::vector<LDSymbol*> m_GlobalGOTSyms;
 
 private:
-  /// isGOTSymbol - return true if the symbol is the GOT entry.
-  bool isGOTSymbol(const LDSymbol& pSymbol) const;
+  /// isGlobalGOTSymbol - return true if the symbol is the global GOT entry.
+  bool isGlobalGOTSymbol(const LDSymbol& pSymbol) const;
   /// emitDynamicSymbol - emit dynamic symbol.
   void emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
                          Output& pOutput,
@@ -197,3 +195,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/Mips/MipsRelocationFactory.cpp b/lib/Target/Mips/MipsRelocationFactory.cpp
index e3a7793..948e026 100644
--- a/lib/Target/Mips/MipsRelocationFactory.cpp
+++ b/lib/Target/Mips/MipsRelocationFactory.cpp
@@ -9,9 +9,9 @@
 
 #include <llvm/ADT/Twine.h>
 #include <llvm/Support/ELF.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <mcld/LD/Layout.h>
 #include <mcld/Target/OutputRelocSection.h>
+#include <mcld/Support/MsgHandling.h>
 
 #include "MipsRelocationFactory.h"
 #include "MipsRelocationFunctions.h"
@@ -54,32 +54,26 @@
   Relocation::Type type = pRelocation.type();
 
   if (type >= sizeof(apply_functions) / sizeof(apply_functions[0])) {
-    llvm::report_fatal_error(llvm::Twine("Unknown relocation type. "
-                                         "To symbol `") +
-                             pRelocation.symInfo()->name() +
-                             llvm::Twine("'."));
+    fatal(diag::unknown_relocation) << (int)type
+                                    << pRelocation.symInfo()->name();
   }
 
   // apply the relocation
   Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
 
   // check result
+  if (OK == result) {
+    return;
+  }
   if (Overflow == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' causes overflow. on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_overflow) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
 
   if (BadReloc == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' encounters unexpected opcode. "
-                                         "on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_badreloc) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
 }
@@ -90,26 +84,6 @@
 
 static const char * const GP_DISP_NAME = "_gp_disp";
 
-// Get an relocation entry in .rel.dyn and set its type to R_MIPS_REL32,
-// its FragmentRef to pReloc->targetFrag() and its ResolveInfo
-// to pReloc->symInfo()
-static
-void helper_SetRelDynEntry(Relocation& pReloc,
-                   MipsRelocationFactory& pParent)
-{
-  // rsym - The relocation target symbol
-  ResolveInfo* rsym = pReloc.symInfo();
-  MipsGNULDBackend& ld_backend = pParent.getTarget();
-
-  bool exist;
-  Relocation& rel_entry =
-    *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
-
-  rel_entry.setType(llvm::ELF::R_MIPS_REL32);
-  rel_entry.targetRef() = pReloc.targetRef();
-  rel_entry.setSymInfo(0);
-}
-
 // Find next R_MIPS_LO16 relocation paired to pReloc.
 static
 Relocation* helper_FindLo16Reloc(Relocation& pReloc)
@@ -142,24 +116,27 @@
 
 static
 GOTEntry& helper_GetGOTEntry(Relocation& pReloc,
-                             MipsRelocationFactory& pParent)
+                             MipsRelocationFactory& pParent,
+                             bool& pExist, int32_t value)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   MipsGNULDBackend& ld_backend = pParent.getTarget();
+  MipsGOT& got = ld_backend.getGOT();
 
-  bool exist;
-  GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
+  GOTEntry& got_entry = *got.getEntry(*rsym, pExist);
 
-  if (exist)
+  if (pExist)
     return got_entry;
 
   // If we first get this GOT entry, we should initialize it.
-  if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
-    got_entry.setContent(pReloc.symValue());
-  }
-  else {
-    llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+  if (!(got.isLocal(rsym) && rsym->type() == ResolveInfo::Section)) {
+    if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
+      got_entry.setContent(pReloc.symValue());
+    }
+    else {
+      fatal(diag::reserve_entry_number_mismatch) << "GOT";
+    }
   }
 
   return got_entry;
@@ -169,7 +146,8 @@
 RelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc,
                                                MipsRelocationFactory& pParent)
 {
-  GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
+  bool exist;
+  GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
   return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
 }
 
@@ -196,6 +174,7 @@
 {
   ResolveInfo* rsym = pReloc.symInfo();
   MipsGNULDBackend& ld_backend = pParent.getTarget();
+  MipsGOT& got = ld_backend.getGOT();
 
   bool exist;
   Relocation& rel_entry =
@@ -203,7 +182,19 @@
 
   rel_entry.setType(llvm::ELF::R_MIPS_REL32);
   rel_entry.targetRef() = pReloc.targetRef();
-  rel_entry.setSymInfo(rsym->isLocal() ? NULL : rsym);
+
+  RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+  RelocationFactory::DWord S = pReloc.symValue();
+
+  if (got.isLocal(rsym)) {
+    rel_entry.setSymInfo(NULL);
+    pReloc.target() = A + S;
+  }
+  else {
+    rel_entry.setSymInfo(rsym);
+    // Don't add symbol value that will be resolved by the dynamic linker
+    pReloc.target() = A;
+  }
 }
 
 //=========================================//
@@ -227,14 +218,26 @@
 {
   ResolveInfo* rsym = pReloc.symInfo();
 
-  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
-    helper_DynRel(pReloc, pParent);
-  }
-
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   RelocationFactory::DWord S = pReloc.symValue();
 
-  pReloc.target() |= (S + A);
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    pReloc.target() = S + A;
+    return MipsRelocationFactory::OK;
+  }
+
+  if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
+    helper_DynRel(pReloc, pParent);
+
+    return MipsRelocationFactory::OK;
+  }
+
+  pReloc.target() = (S + A);
 
   return MipsRelocationFactory::OK;
 }
@@ -279,17 +282,21 @@
                                    const MCLDInfo& pLDInfo,
                                    MipsRelocationFactory& pParent)
 {
-  int32_t AHL = pParent.getAHL();
   int32_t res = 0;
 
   if (helper_isGpDisp(pReloc)) {
     int32_t P = pReloc.place(pParent.getLayout());
     int32_t GP = helper_GetGP(pParent);
+    int32_t AHL = pParent.getAHL();
     res = AHL + GP - P + 4;
   }
   else {
     int32_t S = pReloc.symValue();
-    res = AHL + S;
+    // The previous AHL may be for other hi/lo pairs.
+    // We need to calcuate the lo part now.  It is easy.
+    // Remember to add the section offset to ALO.
+    int32_t ALO = (pReloc.target() & 0xFFFF) + pReloc.addend();
+    res = ALO + S;
   }
 
   pReloc.target() &= 0xFFFF0000;
@@ -307,6 +314,7 @@
                                     MipsRelocationFactory& pParent)
 {
   ResolveInfo* rsym = pReloc.symInfo();
+  RelocationFactory::Address G = 0;
 
   if (rsym->isLocal()) {
     Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
@@ -317,13 +325,16 @@
 
     pParent.setAHL(AHL);
 
-    GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent);
-
     int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
-    got_entry.setContent(res);
-  }
+    bool exist;
+    GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
 
-  RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
+    got_entry.setContent(res);
+    G = pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
+  }
+  else {
+    G = helper_GetGOTOffset(pReloc, pParent);
+  }
 
   pReloc.target() &= 0xFFFF0000;
   pReloc.target() |= (G & 0xFFFF);
@@ -351,7 +362,8 @@
                                       const MCLDInfo& pLDInfo,
                                       MipsRelocationFactory& pParent)
 {
-  int32_t A = pReloc.target();
+  // Remember to add the section offset to A.
+  int32_t A = pReloc.target() + pReloc.addend();
   int32_t S = pReloc.symValue();
   int32_t GP = helper_GetGP(pParent);
 
diff --git a/lib/Target/Mips/MipsSectLinker.cpp b/lib/Target/Mips/MipsSectLinker.cpp
index af543c9..7a3082c 100644
--- a/lib/Target/Mips/MipsSectLinker.cpp
+++ b/lib/Target/Mips/MipsSectLinker.cpp
@@ -10,7 +10,7 @@
 #include <llvm/ADT/Triple.h>
 #include <mcld/Support/TargetRegistry.h>
 #include "Mips.h"
-#include "MipsAndroidSectLinker.h"
+#include "MipsELFSectLinker.h"
 
 using namespace mcld;
 
@@ -31,9 +31,7 @@
     assert(0 && "COFF linker has not supported yet");
   }
 
-  // For now, use Android SectLinker directly
-  return new MipsAndroidSectLinker(pOption,
-                                   pLDBackend);
+  return new MipsELFSectLinker(pOption, pLDBackend);
 }
 
 } // namespace of mcld
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
index 89b4f52..dbb8194 100644
--- a/lib/Target/OutputRelocSection.cpp
+++ b/lib/Target/OutputRelocSection.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include <mcld/LD/LDSection.h>
 #include <mcld/Target/OutputRelocSection.h>
+#include <mcld/Support/MsgHandling.h>
 
 using namespace mcld;
 
@@ -64,18 +65,18 @@
 
   if(isForGOT) {
     // get or create entry in m_SymRelMap
-    Relocation *&Entry = m_SymRelMap[&pSymbol];
-    pExist = 1;
+    Relocation *&entry = m_SymRelMap[&pSymbol];
+    pExist = true;
 
-    if(!Entry) {
-      pExist = 0;
-      Entry = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
+    if(NULL == entry) {
+      pExist = false;
+      entry = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
       ++m_ValidEntryIterator;
     }
-    result = Entry;
+    result = entry;
   }
   else {
-    pExist = 0;
+    pExist = false;
     result = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
     ++m_ValidEntryIterator;
   }
diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp
index 58178ec..ec8dc87 100644
--- a/lib/Target/Target.cpp
+++ b/lib/Target/Target.cpp
@@ -6,20 +6,19 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/Target/TargetMachine.h"
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Target/TargetMachine.h>
 #include <llvm/Support/TargetRegistry.h>
 #include <llvm/Target/TargetMachine.h>
 
 using namespace llvm;
-using namespace mcld;
 
-/* ** */
 mcld::Target::Target()
-  : TargetMachineCtorFn(0),
-    SectLinkerCtorFn(0),
-    TargetLDBackendCtorFn(0),
-    m_pT(0)
+  : TargetMachineCtorFn(NULL),
+    SectLinkerCtorFn(NULL),
+    TargetLDBackendCtorFn(NULL),
+    DiagnosticLineInfoCtorFn(NULL),
+    m_pT(NULL)
 {
 }
 
diff --git a/lib/Target/TargetLDBackend.cpp b/lib/Target/TargetLDBackend.cpp
index 1a8ab6b..4eda0a6 100644
--- a/lib/Target/TargetLDBackend.cpp
+++ b/lib/Target/TargetLDBackend.cpp
@@ -14,10 +14,24 @@
 
 /* ** */
 TargetLDBackend::TargetLDBackend()
-{
+  : m_pEhFrame(NULL) {
 }
 
 TargetLDBackend::~TargetLDBackend()
 {
+  if (NULL != m_pEhFrame)
+    delete m_pEhFrame;
 }
 
+EhFrame* TargetLDBackend::getEhFrame()
+{
+  if (NULL == m_pEhFrame)
+    m_pEhFrame = new EhFrame();
+  return m_pEhFrame;
+}
+
+const EhFrame* TargetLDBackend::getEhFrame() const
+{
+  assert(NULL == m_pEhFrame);
+  return m_pEhFrame;
+}
diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h
index c575d80..2d07314 100644
--- a/lib/Target/X86/X86.h
+++ b/lib/Target/X86/X86.h
@@ -21,3 +21,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86AndroidSectLinker.cpp b/lib/Target/X86/X86AndroidSectLinker.cpp
deleted file mode 100644
index fe7a2cc..0000000
--- a/lib/Target/X86/X86AndroidSectLinker.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- X86AndroidSectLinker.cpp -------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86AndroidSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-X86AndroidSectLinker::X86AndroidSectLinker(SectLinkerOption &pOption,
-                                           TargetLDBackend &pLDBackend)
-  : AndroidSectLinker(pOption,
-                      pLDBackend) {
-  MCLDInfo &info = pOption.info();
-  // set up target-dependent constraints of attibutes
-  info.attrFactory().constraint().disableWholeArchive();
-  info.attrFactory().constraint().disableAsNeeded();
-  info.attrFactory().constraint().setSharedSystem();
-
-  // set up the predefined attributes
-  info.attrFactory().predefined().unsetWholeArchive();
-  info.attrFactory().predefined().setDynamic();
-
-}
-
-X86AndroidSectLinker::~X86AndroidSectLinker() {
-}
diff --git a/lib/Target/X86/X86AndroidSectLinker.h b/lib/Target/X86/X86AndroidSectLinker.h
deleted file mode 100644
index b275aca..0000000
--- a/lib/Target/X86/X86AndroidSectLinker.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- X86AndroidSectLinker.h ---------------------------------------------===//
-//
-//                     The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef X86_ANDROIDSECTLINKER_H
-#define X86_ANDROIDSECTLINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/Target/AndroidSectLinker.h>
-
-namespace mcld
-{
-
-/** \class X86AndroidSectLinker
- *  \brief X86AndroidSectLinker sets up the environment for linking.
- *
- *  \see
- *  \author Anders Cheng <[email protected]>
- */
-class X86AndroidSectLinker : public AndroidSectLinker
-{
-public:
-  X86AndroidSectLinker(SectLinkerOption &pOption,
-                       mcld::TargetLDBackend &pLDBackend);
-
-  ~X86AndroidSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/X86/X86Diagnostic.cpp b/lib/Target/X86/X86Diagnostic.cpp
new file mode 100644
index 0000000..db12dde
--- /dev/null
+++ b/lib/Target/X86/X86Diagnostic.cpp
@@ -0,0 +1,38 @@
+//===- X86Diagnostic.cpp --------------------------------------------------===//
+//
+//                     The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <llvm/ADT/Triple.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/DWARFLineInfo.h>
+#include "X86.h"
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// X86Diagnostic
+
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createX86Diagnostic - the help function to create corresponding X86Diagnostic
+//
+DiagnosticLineInfo* createX86DiagLineInfo(const llvm::Target& pTarget,
+                                          const std::string &pTriple)
+{
+  return new DWARFLineInfo();
+}
+
+} // namespace of mcld
+
+//==========================
+// InitializeX86Diagnostic
+extern "C" void LLVMInitializeX86DiagnosticLineInfo() {
+  // Register the linker frontend
+  mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheX86Target, createX86DiagLineInfo);
+}
+
diff --git a/lib/Target/X86/X86ELFDynamic.cpp b/lib/Target/X86/X86ELFDynamic.cpp
index ee6b1f6..af86b2c 100644
--- a/lib/Target/X86/X86ELFDynamic.cpp
+++ b/lib/Target/X86/X86ELFDynamic.cpp
@@ -13,24 +13,25 @@
 using namespace mcld;
 
 X86ELFDynamic::X86ELFDynamic(const GNULDBackend& pParent)
-  : ELFDynamic(pParent), m_HasGOTPLT(false) {
+  : ELFDynamic(pParent)
+{
 }
 
-X86ELFDynamic::~X86ELFDynamic() {
+X86ELFDynamic::~X86ELFDynamic()
+{
 }
 
-void X86ELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat) {
+void X86ELFDynamic::reserveTargetEntries(const ELFFileFormat& pFormat)
+{
   // reservePLTGOT
-  if (m_HasGOTPLT ? pFormat.hasGOTPLT() : pFormat.hasGOT())
+  if (pFormat.hasGOTPLT())
     reserveOne(llvm::ELF::DT_PLTGOT);
 }
 
-void X86ELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat) {
+void X86ELFDynamic::applyTargetEntries(const ELFFileFormat& pFormat)
+{
   // applyPLTGOT
-  if (m_HasGOTPLT) {
-      if (pFormat.hasGOTPLT())
-	applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOTPLT().addr());
-  }
-  else if (pFormat.hasGOT())
-    applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOT().addr());
+  if (pFormat.hasGOTPLT())
+	  applyOne(llvm::ELF::DT_PLTGOT, pFormat.getGOTPLT().addr());
 }
+
diff --git a/lib/Target/X86/X86ELFDynamic.h b/lib/Target/X86/X86ELFDynamic.h
index b9e70ce..7053a0b 100644
--- a/lib/Target/X86/X86ELFDynamic.h
+++ b/lib/Target/X86/X86ELFDynamic.h
@@ -25,12 +25,6 @@
 private:
   void reserveTargetEntries(const ELFFileFormat& pFormat);
   void applyTargetEntries(const ELFFileFormat& pFormat);
-
-private:
-  // True if we have .got.plt section, which will avoid GOT0 entries
-  // when PLT isn't used.  To support .got.plt section, we must combine
-  // .got section and .got.plt section into a single GOT.
-  bool m_HasGOTPLT;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
index 544b5e9..91c7d65 100644
--- a/lib/Target/X86/X86GOT.cpp
+++ b/lib/Target/X86/X86GOT.cpp
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include "X86GOT.h"
 #include <mcld/LD/LDFileFormat.h>
-#include <llvm/Support/ErrorHandling.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
@@ -21,36 +21,8 @@
 // X86GOT
 X86GOT::X86GOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
              : GOT(pSection, pSectionData, X86GOTEntrySize),
-               m_GeneralGOTNum(0), m_GOTPLTNum(0), m_GeneralGOTIterator(),
-               m_GOTPLTIterator(), m_LastGOT0()
+               m_GOTIterator(), m_fIsVisit(false)
 {
-  GOTEntry* Entry = 0;
-
-  // Create GOT0 entries.
-  for (unsigned int i = 0; i < X86GOT0Num; i++) {
-    Entry = new (std::nothrow) GOTEntry(0, X86GOTEntrySize,
-                                        &m_SectionData);
-
-    if (!Entry)
-      llvm::report_fatal_error("Allocating GOT0 entries failed!");
-
-    m_Section.setSize(m_Section.size() + X86GOTEntrySize);
-  }
-
-  // Skip GOT0 entries.
-  iterator it = m_SectionData.begin();
-  iterator ie = m_SectionData.end();
-
-  for (unsigned int i = 1; i < X86GOT0Num; ++i) {
-    if (it == ie)
-      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
-
-    ++it;
-  }
-
-  m_LastGOT0 = it;
-  m_GeneralGOTIterator = it;
-  m_GOTPLTIterator = it;
 }
 
 X86GOT::~X86GOT()
@@ -66,38 +38,37 @@
                                         &m_SectionData);
 
     if (!Entry)
-      llvm::report_fatal_error("Allocating new memory for GOTEntry failed");
+      fatal(diag::fail_allocate_memory) << "GOTEntry";
 
     m_Section.setSize(m_Section.size() + X86GOTEntrySize);
-    ++m_GeneralGOTNum;
   }
 }
 
 
 GOTEntry* X86GOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
 {
-  GOTEntry *&Entry = m_GeneralGOTMap[&pInfo];
+  // first time visit this function, set m_GOTIterator
+  if(!m_fIsVisit) {
+    assert( !m_SectionData.getFragmentList().empty() &&
+             "DynRelSection contains no entries.");
+    m_GOTIterator = m_SectionData.getFragmentList().begin();
+    m_fIsVisit = true;
+  }
+
+
+  GOTEntry *&Entry = m_GOTMap[&pInfo];
   pExist = 1;
 
   if (!Entry) {
     pExist = 0;
-
-    ++m_GeneralGOTIterator;
-    assert(m_GeneralGOTIterator != m_SectionData.getFragmentList().end()
-           && "The number of GOT Entries and ResolveInfo doesn't match!");
-
-    Entry = llvm::cast<GOTEntry>(&(*m_GeneralGOTIterator));
+    assert(m_GOTIterator != m_SectionData.getFragmentList().end()
+             && "The number of GOT Entries and ResolveInfo doesn't match!");
+    Entry = llvm::cast<GOTEntry>(&(*m_GOTIterator));
+    ++m_GOTIterator;
   }
-
   return Entry;
 }
 
-void X86GOT::applyGOT0(uint64_t pAddress)
-{
-  llvm::cast<GOTEntry>
-    (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
-}
-
 X86GOT::iterator X86GOT::begin()
 {
   return m_SectionData.getFragmentList().begin();
@@ -118,11 +89,3 @@
   return m_SectionData.getFragmentList().end();
 }
 
-unsigned int X86GOT::getGOTPLTNum() const
-{ return m_GOTPLTNum; }
-
-X86GOT::iterator X86GOT::getLastGOT0()
-{ return m_LastGOT0; }
-
-const X86GOT::iterator X86GOT::getLastGOT0() const
-{ return m_LastGOT0; }
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
index 37b48a3..d758de0 100644
--- a/lib/Target/X86/X86GOT.h
+++ b/lib/Target/X86/X86GOT.h
@@ -23,18 +23,8 @@
  *  \brief X86 Global Offset Table.
  */
 
-const unsigned int X86GOT0Num = 3;
-
 class X86GOT : public GOT
 {
-  friend void mcld::X86PLT::reserveEntry(size_t pNum);
-
-  friend mcld::PLTEntry* mcld::X86PLT::getPLTEntry(
-         const mcld::ResolveInfo& pSymbol,bool& pExist);
-
-  friend mcld::GOTEntry* mcld::X86PLT::getGOTPLTEntry(
-         const mcld::ResolveInfo& pSymbol,bool& pExist);
-
   typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
 
 public:
@@ -51,8 +41,6 @@
 
   GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
 
-  void applyGOT0(uint64_t pAddress);
-
   iterator begin();
 
   const_iterator begin() const;
@@ -61,30 +49,17 @@
 
   const_iterator end() const;
 
-  unsigned int getGOTPLTNum() const;
-
-  iterator getLastGOT0();
-
-  const iterator getLastGOT0() const;
-
 private:
+  /// m_GOTIterator - point to the first valid entry in GOT list
+  iterator m_GOTIterator;
 
-  unsigned int m_GeneralGOTNum;
-  unsigned int m_GOTPLTNum;
+  /// m_fIsVisit - first time visit the function getEntry() or not
+  bool m_fIsVisit;
 
-  // Used by getGeneralGOTEntry()
-  iterator m_GeneralGOTIterator;
-
-  // Used by getGOTPLTEntry()
-  iterator m_GOTPLTIterator;
-
-  // The last GOT0 entry
-  iterator m_LastGOT0;
-
-  SymbolIndexMapType m_GOTPLTMap;
-  SymbolIndexMapType m_GeneralGOTMap;
+  SymbolIndexMapType m_GOTMap;
 };
 
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index 55596e3..960c86b 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 #include "X86GOTPLT.h"
-#include "mcld/LD/LDFileFormat.h"
-#include <llvm/Support/ErrorHandling.h>
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
@@ -25,12 +25,12 @@
   GOTEntry* Entry = 0;
 
   // Create GOT0 entries.
-  for (int i = 0; i < 3; i++) {
+  for (size_t i = 0; i < X86GOTPLT0Num; i++) {
     Entry = new (std::nothrow) GOTEntry(0, X86GOTPLTEntrySize,
                                         &m_SectionData);
 
     if (!Entry)
-      llvm::report_fatal_error("Allocating GOT0 entries failed!");
+      fatal(diag::fail_allocate_memory) << "GOT0";
 
     m_Section.setSize(m_Section.size() + X86GOTPLTEntrySize);
   }
@@ -39,9 +39,8 @@
   iterator it = m_SectionData.begin();
   iterator ie = m_SectionData.end();
 
-  for (size_t i = 1; i < X86GOT0Num; ++i) {
-    if (it == ie)
-      llvm::report_fatal_error("Generation of GOT0 entries is incomplete!");
+  for (size_t i = 1; i < X86GOTPLT0Num; ++i) {
+    assert((it != ie) && "Generation of GOT0 entries is incomplete!");
 
     ++it;
   }
@@ -73,31 +72,38 @@
   return m_SectionData.end();
 }
 
-void X86GOTPLT::applyGOT0(const uint64_t pAddress)
+void X86GOTPLT::applyGOT0(uint64_t pAddress)
 {
   llvm::cast<GOTEntry>
     (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
 }
 
-void X86GOTPLT::reserveGOTPLTEntry()
+void X86GOTPLT::reserveEntry(size_t pNum)
 {
-    GOTEntry* got_entry = 0;
-
-    got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
-
+  GOTEntry* got_entry = NULL;
+  for (size_t i = 0; i < pNum; ++i) {
+    got_entry = new GOTEntry(0, getEntrySize(),&(getSectionData()));
     if (!got_entry)
-      llvm::report_fatal_error("Allocating new memory for GOT failed!");
+      fatal(diag::fail_allocate_memory) << "GOT";
 
     m_Section.setSize(m_Section.size() + getEntrySize());
+  }
 }
 
-void X86GOTPLT::applyAllGOTPLT(const uint64_t pPLTBase)
+void X86GOTPLT::applyAllGOTPLT(uint64_t pPLTBase,
+                               unsigned int pPLT0Size,
+                               unsigned int pPLT1Size)
 {
-  iterator gotplt_it = begin();
-  iterator gotplt_ie = end();
-
-  for (; gotplt_it != gotplt_ie; ++gotplt_it)
-    llvm::cast<GOTEntry>(*gotplt_it).setContent(pPLTBase);
+  iterator it = begin();
+  // skip GOT0
+  for (size_t i = 0; i < X86GOTPLT0Num; ++i)
+    ++it;
+  // address of corresponding plt entry
+  uint64_t plt_addr = pPLTBase + pPLT0Size;
+  for (; it != end() ; ++it) {
+    llvm::cast<GOTEntry>(*it).setContent(plt_addr + 6);
+    plt_addr += pPLT1Size;
+  }
 }
 
 GOTEntry*& X86GOTPLT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
@@ -105,9 +111,22 @@
   return m_GOTPLTMap[&pSymbol];
 }
 
-X86GOTPLT::iterator X86GOTPLT::getNextGOTPLTEntry()
+GOTEntry* X86GOTPLT::getEntry(const ResolveInfo& pInfo, bool& pExist)
 {
-  return ++m_GOTPLTIterator;
+  GOTEntry *&Entry = m_GOTPLTMap[&pInfo];
+  pExist = 1;
+
+  if (!Entry) {
+    pExist = 0;
+
+    ++m_GOTPLTIterator;
+    assert(m_GOTPLTIterator != m_SectionData.getFragmentList().end()
+           && "The number of GOT Entries and ResolveInfo doesn't match!");
+
+    Entry = llvm::cast<GOTEntry>(&(*m_GOTPLTIterator));
+  }
+
+  return Entry;
 }
 
 } //end mcld namespace
diff --git a/lib/Target/X86/X86GOTPLT.h b/lib/Target/X86/X86GOTPLT.h
index 04bfad0..ae9f0f7 100644
--- a/lib/Target/X86/X86GOTPLT.h
+++ b/lib/Target/X86/X86GOTPLT.h
@@ -12,7 +12,7 @@
 #include <gtest.h>
 #endif
 
-#include "mcld/Target/GOT.h"
+#include <mcld/Target/GOT.h>
 
 namespace mcld
 {
@@ -22,7 +22,7 @@
  *  \brief X86 .got.plt section.
  */
 
-const unsigned int X86GOT0Num = 3;
+const unsigned int X86GOTPLT0Num = 3;
 
 class X86GOTPLT : public GOT
 {
@@ -47,18 +47,20 @@
 
 // For GOT0
 public:
-  void applyGOT0(const uint64_t pAddress);
+  void applyGOT0(uint64_t pAddress);
 
 // For GOTPLT
 public:
-  void reserveGOTPLTEntry();
+  void reserveEntry(size_t pNum = 1);
 
-  void applyAllGOTPLT(const uint64_t pPLTBase);
+  GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
+
+  void applyAllGOTPLT(uint64_t pPLTBase,
+                      unsigned int pPLT0Size,
+                      unsigned int pPLT1Size);
 
   GOTEntry*& lookupGOTPLTMap(const ResolveInfo& pSymbol);
 
-  iterator getNextGOTPLTEntry();
-
 private:
   iterator m_GOTPLTIterator;
   SymbolIndexMapType m_GOTPLTMap;
@@ -67,3 +69,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index 354cd51..79d160e 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -13,13 +13,14 @@
 #include "X86RelocationFactory.h"
 
 #include <llvm/ADT/Triple.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/TargetRegistry.h>
+#include <mcld/LD/SectionMap.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/MC/MCLDOutput.h>
 #include <mcld/MC/MCLinker.h>
-#include <mcld/LD/SectionMap.h>
 #include <mcld/MC/MCRegionFragment.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/TargetRegistry.h>
 
 #include <cstring>
 
@@ -29,6 +30,7 @@
   : m_pRelocFactory(NULL),
     m_pGOT(NULL),
     m_pPLT(NULL),
+    m_pGOTPLT(NULL),
     m_pRelDyn(NULL),
     m_pRelPLT(NULL),
     m_pDynamic(NULL) {
@@ -42,6 +44,8 @@
     delete m_pGOT;
   if (NULL != m_pPLT)
     delete m_pPLT;
+  if (NULL != m_pGOTPLT)
+    delete m_pGOTPLT;
   if (NULL !=m_pRelDyn)
     delete m_pRelDyn;
   if (NULL != m_pRelPLT)
@@ -70,17 +74,15 @@
                                   MCLinker& pLinker)
 {
   // when building shared object, the .got section is needed
-  if(pOutput.type() == Output::DynObj && (NULL == m_pGOT))
-      createX86GOT(pLinker, pOutput);
+  if (Output::DynObj == pOutput.type() && (NULL == m_pGOTPLT)) {
+    createX86GOTPLT(pLinker, pOutput);
+  }
 }
 
 void X86GNULDBackend::doPostLayout(const Output& pOutput,
                                    const MCLDInfo& pInfo,
                                    MCLinker& pLinker)
 {
-  // emit program headers
-  if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec)
-    emitProgramHdrs(pLinker.getLDInfo().output());
 }
 
 /// dynamic - the dynamic section of the target machine.
@@ -108,9 +110,18 @@
 
   LDSection& got = file_format->getGOT();
   m_pGOT = new X86GOT(got, pLinker.getOrCreateSectData(got));
+}
 
-  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
-  if( m_pGOTSymbol != NULL ) {
+void X86GNULDBackend::createX86GOTPLT(MCLinker& pLinker, const Output& pOutput)
+{
+  // get .got.plt LDSection and create MCSectionData
+  ELFFileFormat* file_format = getOutputFormat(pOutput);
+
+  LDSection& gotplt = file_format->getGOTPLT();
+  m_pGOTPLT = new X86GOTPLT(gotplt, pLinker.getOrCreateSectData(gotplt));
+
+  // define symbol _GLOBAL_OFFSET_TABLE_ when .got.plt create
+  if (m_pGOTSymbol != NULL) {
     pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
                      "_GLOBAL_OFFSET_TABLE_",
                      false,
@@ -119,7 +130,8 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
+                                                         0x0),
                      ResolveInfo::Hidden);
   }
   else {
@@ -131,7 +143,8 @@
                      ResolveInfo::Local,
                      0x0, // size
                      0x0, // value
-                     pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+                     pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
+                                                          0x0),
                      ResolveInfo::Hidden);
   }
 }
@@ -143,8 +156,9 @@
 
   LDSection& plt = file_format->getPLT();
   LDSection& relplt = file_format->getRelPlt();
+  assert(m_pGOTPLT != NULL);
   // create MCSectionData and X86PLT
-  m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT, pOutput);
+  m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOTPLT, pOutput);
 
   // set info of .rel.plt to .plt
   relplt.setLink(&plt);
@@ -167,63 +181,73 @@
                                      8);
 }
 
-ELFFileFormat* X86GNULDBackend::getOutputFormat(const Output& pOutput) const
+void X86GNULDBackend::addCopyReloc(ResolveInfo& pSym)
 {
-  switch (pOutput.type()) {
-    case Output::DynObj:
-      return getDynObjFileFormat();
-    case Output::Exec:
-      return getExecFileFormat();
-    // FIXME: We do not support building .o now
-    case Output::Object:
-    default:
-      llvm::report_fatal_error(llvm::Twine("Unsupported output file format: ") +
-                               llvm::Twine(pOutput.type()));
-      return NULL;
+  bool exist;
+  Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
+  rel_entry.setType(llvm::ELF::R_386_COPY);
+  assert(pSym.outSymbol()->hasFragRef());
+  rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
+  rel_entry.setSymInfo(&pSym);
+}
+
+LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(MCLinker& pLinker,
+                                                    const ResolveInfo& pSym)
+{
+  // For a symbol needing copy relocation, define a copy symbol in the BSS
+  // section and all other reference to this symbol should refer to this
+  // copy.
+
+  // get or create corresponding BSS LDSection
+  LDSection* bss_sect_hdr = NULL;
+  if (ResolveInfo::ThreadLocal == pSym.type()) {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
+                                   ".tbss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
   }
-}
+  else {
+    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
+                                   LDFileFormat::BSS,
+                                   llvm::ELF::SHT_NOBITS,
+                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
+  }
 
-bool X86GNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym,
-                                       const MCLDInfo& pLDInfo,
-                                       const Output& pOutput) const
-{
-  return((Output::DynObj == pOutput.type())
-         &&(ResolveInfo::Function == pSym.type())
-         &&(pSym.isDyn() || pSym.isUndef() ||
-            isSymbolPreemptible(pSym, pLDInfo, pOutput))
-        );
-}
+  // get or create corresponding BSS MCSectionData
+  assert(NULL != bss_sect_hdr);
+  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(
+                                     *bss_sect_hdr);
 
-bool X86GNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym,
-                                          const Output& pOutput,
-                                          bool isAbsReloc) const
-{
-  if(pSym.isUndef() && (pOutput.type()==Output::Exec))
-    return false;
-  if(pSym.isAbsolute())
-    return false;
-  if(pOutput.type()==Output::DynObj && isAbsReloc)
-    return true;
-  if(pSym.isDyn() || pSym.isUndef())
-    return true;
+  // Determine the alignment by the symbol value
+  // FIXME: here we use the largest alignment
+  uint32_t addralign = bitclass() / 8;
 
-  return false;
-}
+  // allocate space in BSS for the copy symbol
+  llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, pSym.size());
+  uint64_t size = pLinker.getLayout().appendFragment(*frag,
+                                                     bss_section,
+                                                     addralign);
+  bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
 
-bool X86GNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
-                                         const MCLDInfo& pLDInfo,
-                                         const Output& pOutput) const
-{
-  if(pSym.other() != ResolveInfo::Default)
-    return false;
+  // change symbol binding to Global if it's a weak symbol
+  ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding();
+  if (binding == ResolveInfo::Weak)
+    binding = ResolveInfo::Global;
 
-  if(pOutput.type() != Output::DynObj)
-    return false;
+  // Define the copy symbol in the bss section and resolve it
+  LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+                      pSym.name(),
+                      false,
+                      (ResolveInfo::Type)pSym.type(),
+                      ResolveInfo::Define,
+                      binding,
+                      pSym.size(),  // size
+                      0x0,          // value
+                      pLinker.getLayout().getFragmentRef(*frag, 0x0),
+                      (ResolveInfo::Visibility)pSym.other());
 
-  if(pLDInfo.options().Bsymbolic())
-    return false;
-
-  return true;
+  return *cpy_sym;
 }
 
 void X86GNULDBackend::updateAddend(Relocation& pReloc,
@@ -231,7 +255,7 @@
                                    const Layout& pLayout) const
 {
   // Update value keep in addend if we meet a section symbol
-  if(pReloc.symInfo()->type() == ResolveInfo::Section) {
+  if (pReloc.symInfo()->type() == ResolveInfo::Section) {
     pReloc.setAddend(pLayout.getOutputOffset(
                      *pInputSym.fragRef()) + pReloc.addend());
   }
@@ -254,9 +278,9 @@
       // If buiding PIC object (shared library or PIC executable),
       // a dynamic relocations with RELATIVE type to this location is needed.
       // Reserve an entry in .rel.dyn
-      if(Output::DynObj == pOutput.type()) {
+      if (isOutputPIC(pOutput, pLDInfo)) {
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createX86RelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set Rel bit
@@ -267,7 +291,7 @@
     case llvm::ELF::R_386_GOTOFF:
     case llvm::ELF::R_386_GOTPC:
       // A GOT section is needed
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createX86GOT(pLinker, pOutput);
       return;
 
@@ -275,9 +299,8 @@
       return;
 
     default:
-      llvm::report_fatal_error(llvm::Twine("unexpected reloc ") +
-                               llvm::Twine((int) pReloc.type()) +
-                               llvm::Twine(" in object file"));
+      fatal(diag::unsupported_relocation) << (int)pReloc.type()
+                                          << "[email protected]";
       break;
   } // end switch
 }
@@ -295,14 +318,14 @@
     case llvm::ELF::R_386_32:
       // Absolute relocation type, symbol may needs PLT entry or
       // dynamic relocation entry
-      if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
         // create plt for this symbol if it does not have one
-        if(!(rsym->reserved() & ReservePLT)){
+        if (!(rsym->reserved() & ReservePLT)){
           // Create .got section if it dosen't exist
-          if(NULL == m_pGOT)
-             createX86GOT(pLinker, pOutput);
+          if (NULL == m_pGOTPLT)
+            createX86GOTPLT(pLinker, pOutput);
           // create .plt and .rel.plt if not exist
-          if(NULL == m_pPLT)
+          if (NULL == m_pPLT)
             createX86PLTandRelPLT(pLinker, pOutput);
           // Symbol needs PLT entry, we need to reserve a PLT entry
           // and the corresponding GOT and dynamic relocation entry
@@ -315,21 +338,29 @@
         }
       }
 
-      if(isSymbolNeedsDynRel(*rsym, pOutput, true)) {
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                            pLDInfo, pOutput, true)) {
         // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createX86RelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
-        // set Rel bit
-        rsym->setReserved(rsym->reserved() | ReserveRel);
+        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
+                          pOutput)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+        }
       }
       return;
 
     case llvm::ELF::R_386_GOTOFF:
     case llvm::ELF::R_386_GOTPC: {
       // A GOT section is needed
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createX86GOT(pLinker, pOutput);
       return;
     }
@@ -338,21 +369,21 @@
       // A PLT entry is needed when building shared library
 
       // return if we already create plt for this symbol
-      if(rsym->reserved() & ReservePLT)
+      if (rsym->reserved() & ReservePLT)
         return;
 
       // if symbol is defined in the ouput file and it's not
       // preemptible, no need plt
-      if(rsym->isDefine() && !rsym->isDyn() &&
+      if (rsym->isDefine() && !rsym->isDyn() &&
          !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
         return;
       }
 
       // Create .got section if it dosen't exist
-      if(NULL == m_pGOT)
-         createX86GOT(pLinker, pOutput);
+      if (NULL == m_pGOTPLT)
+         createX86GOTPLT(pLinker, pOutput);
       // create .plt and .rel.plt if not exist
-      if(NULL == m_pPLT)
+      if (NULL == m_pPLT)
          createX86PLTandRelPLT(pLinker, pOutput);
       // Symbol needs PLT entry, we need to reserve a PLT entry
       // and the corresponding GOT and dynamic relocation entry
@@ -367,17 +398,17 @@
     case llvm::ELF::R_386_GOT32:
       // Symbol needs GOT entry, reserve entry in .got
       // return if we already create GOT for this symbol
-      if(rsym->reserved() & (ReserveGOT | GOTRel))
+      if (rsym->reserved() & (ReserveGOT | GOTRel))
         return;
-      if(NULL == m_pGOT)
+      if (NULL == m_pGOT)
         createX86GOT(pLinker, pOutput);
       m_pGOT->reserveEntry();
       // If building shared object or the symbol is undefined, a dynamic
       // relocation is needed to relocate this GOT entry. Reserve an
       // entry in .rel.dyn
-      if(Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
+      if (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
         // create .rel.dyn section if not exist
-        if(NULL == m_pRelDyn)
+        if (NULL == m_pRelDyn)
           createX86RelDyn(pLinker, pOutput);
         m_pRelDyn->reserveEntry(*m_pRelocFactory);
         // set GOTRel bit
@@ -389,15 +420,49 @@
       return;
 
     case llvm::ELF::R_386_PC32:
-      // We allow R_386_PC32 only if it isn't preemptible.  Otherwise
-      // we will generate writable text section in output.
-      if (!isSymbolPreemptible(*rsym, pLDInfo, pOutput))
-	return;
 
+      if (symbolNeedsPLT(*rsym, pLDInfo, pOutput) &&
+          pOutput.type() != Output::DynObj) {
+        // create plt for this symbol if it does not have one
+        if (!(rsym->reserved() & ReservePLT)){
+          // Create .got section if it dosen't exist
+          if (NULL == m_pGOTPLT)
+            createX86GOTPLT(pLinker, pOutput);
+          // create .plt and .rel.plt if not exist
+          if (NULL == m_pPLT)
+            createX86PLTandRelPLT(pLinker, pOutput);
+          // Symbol needs PLT entry, we need to reserve a PLT entry
+          // and the corresponding GOT and dynamic relocation entry
+          // in .got and .rel.plt. (GOT entry will be reserved simultaneously
+          // when calling X86PLT->reserveEntry())
+          m_pPLT->reserveEntry();
+          m_pRelPLT->reserveEntry(*m_pRelocFactory);
+          // set PLT bit
+          rsym->setReserved(rsym->reserved() | ReservePLT);
+        }
+      }
+
+      if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
+                            pLDInfo, pOutput, false)) {
+        // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
+        // create .rel.dyn section if not exist
+        if (NULL == m_pRelDyn)
+          createX86RelDyn(pLinker, pOutput);
+        m_pRelDyn->reserveEntry(*m_pRelocFactory);
+        if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
+                          pOutput)) {
+          LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
+          addCopyReloc(*cpy_sym.resolveInfo());
+        }
+        else {
+          // set Rel bit
+          rsym->setReserved(rsym->reserved() | ReserveRel);
+        }
+      }
+      return;
     default: {
-      llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") +
-                               llvm::Twine((int) pReloc.type()) +
-                               llvm::Twine(" in object file"));
+      fatal(diag::unsupported_relocation) << (int)pReloc.type()
+                                          << "[email protected]";
       break;
     }
   } // end switch
@@ -407,27 +472,36 @@
                                      const LDSymbol& pInputSym,
                                      MCLinker& pLinker,
                                      const MCLDInfo& pLDInfo,
-                                     const Output& pOutput)
+                                     const Output& pOutput,
+                                     const LDSection& pSection)
 {
   // rsym - The relocation target symbol
   ResolveInfo* rsym = pReloc.symInfo();
   assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
 
+  assert(NULL != pSection.getLink());
+  if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
+    if (rsym->isLocal()) {
+      updateAddend(pReloc, pInputSym, pLinker.getLayout());
+    }
+    return;
+  }
+
   // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
   // entries should be created.
   // FIXME: Below judgements concern only .so is generated as output
   // FIXME: Below judgements concren nothing about TLS related relocation
 
-  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section
-  // is needed
-  if(NULL == m_pGOT && NULL != m_pGOTSymbol) {
-    if(rsym == m_pGOTSymbol->resolveInfo()) {
-      createX86GOT(pLinker, pOutput);
+  // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got.plt
+  // section is needed
+  if (NULL == m_pGOTPLT && NULL != m_pGOTSymbol) {
+    if (rsym == m_pGOTSymbol->resolveInfo()) {
+      createX86GOTPLT(pLinker, pOutput);
     }
   }
 
   // rsym is local
-  if(rsym->isLocal())
+  if (rsym->isLocal())
     scanLocalReloc(pReloc, pInputSym,  pLinker, pLDInfo, pOutput);
 
   // rsym is external
@@ -439,11 +513,12 @@
 uint64_t X86GNULDBackend::emitSectionData(const Output& pOutput,
                                           const LDSection& pSection,
                                           const MCLDInfo& pInfo,
+                                          const Layout& pLayout,
                                           MemoryRegion& pRegion) const
 {
   assert(pRegion.size() && "Size of MemoryRegion is zero!");
 
-  ELFFileFormat* FileFormat = getOutputFormat(pOutput);
+  const ELFFileFormat* FileFormat = getOutputFormat(pOutput);
   assert(FileFormat &&
          "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
 
@@ -479,8 +554,6 @@
   else if (&pSection == &(FileFormat->getGOT())) {
     assert(m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
 
-    m_pGOT->applyGOT0(FileFormat->getDynamic().addr());
-
     uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
 
     GOTEntry* got = 0;
@@ -494,10 +567,28 @@
     }
   }
 
-  else
-    llvm::report_fatal_error("unsupported section name "
-                             + pSection.name() + " !");
+  else if (&pSection == &(FileFormat->getGOTPLT())) {
+    assert(m_pGOTPLT && "emitSectionData failed, m_pGOTPLT is NULL!");
+    m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
 
+    uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
+
+    GOTEntry* got = 0;
+    EntrySize = m_pGOTPLT->getEntrySize();
+
+    for (X86GOTPLT::iterator it = m_pGOTPLT->begin(),
+         ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
+      got = &(llvm::cast<GOTEntry>((*it)));
+      *buffer = static_cast<uint32_t>(got->getContent());
+      RegionSize += EntrySize;
+    }
+  }
+
+  else {
+    fatal(diag::unrecognized_output_sectoin)
+            << pSection.name()
+            << "[email protected]";
+  }
   return RegionSize;
 }
 uint32_t X86GNULDBackend::machine() const
@@ -517,6 +608,18 @@
   return *m_pGOT;
 }
 
+X86GOTPLT& X86GNULDBackend::getGOTPLT()
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
+const X86GOTPLT& X86GNULDBackend::getGOTPLT() const
+{
+  assert(NULL != m_pGOTPLT);
+  return *m_pGOTPLT;
+}
+
 X86PLT& X86GNULDBackend::getPLT()
 {
   assert(NULL != m_pPLT && "PLT section not exist");
@@ -555,17 +658,22 @@
 
 unsigned int
 X86GNULDBackend::getTargetSectionOrder(const Output& pOutput,
-                                       const LDSection& pSectHdr) const
+                                       const LDSection& pSectHdr,
+                                       const MCLDInfo& pInfo) const
 {
-  ELFFileFormat* file_format = getOutputFormat(pOutput);
+  const ELFFileFormat* file_format = getOutputFormat(pOutput);
 
-  // FIXME: if command line option, "-z now", is given, we can let the order of
-  // .got and .got.plt be the same as RELRO sections
-  if (&pSectHdr == &file_format->getGOT())
+  if (&pSectHdr == &file_format->getGOT()) {
+    if (pInfo.options().hasNow())
+      return SHO_RELRO;
     return SHO_RELRO_LAST;
+  }
 
-  if (&pSectHdr == &file_format->getGOTPLT())
+  if (&pSectHdr == &file_format->getGOTPLT()) {
+    if (pInfo.options().hasNow())
+      return SHO_RELRO;
     return SHO_NON_RELRO_FIRST;
+  }
 
   if (&pSectHdr == &file_format->getPLT())
     return SHO_PLT;
@@ -587,7 +695,7 @@
 {
 }
 
-void X86GNULDBackend::initTargetSymbols(MCLinker& pLinker)
+void X86GNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
   // same name in input
@@ -604,113 +712,8 @@
 }
 
 /// finalizeSymbol - finalize the symbol value
-/// If the symbol's reserved field is not zero, MCLinker will call back this
-/// function to ask the final value of the symbol
-bool X86GNULDBackend::finalizeSymbol(LDSymbol& pSymbol) const
+bool X86GNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
 {
-  return false;
-}
-
-/// allocateCommonSymbols - allocate common symbols in the corresponding
-/// sections.
-/// @refer Google gold linker: common.cc: 214
-bool
-X86GNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
-{
-  // SymbolCategory contains all symbols that must emit to the output files.
-  // We are not like Google gold linker, we don't remember symbols before symbol
-  // resolution. All symbols in SymbolCategory are already resolved. Therefore, we
-  // don't need to care about some symbols may be changed its category due to symbol
-  // resolution.
-  SymbolCategory& symbol_list = pLinker.getOutputSymbols();
-
-  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
-    return true;
-
-  // addralign := max value of all common symbols
-  uint64_t addralign = 0x0;
-
-  // Due to the visibility, some common symbols may be forcefully local.
-  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      if ((*com_sym)->value() > addralign)
-        addralign = (*com_sym)->value();
-    }
-  }
-
-  // global common symbols.
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    if ((*com_sym)->value() > addralign)
-      addralign = (*com_sym)->value();
-  }
-
-  // FIXME: If the order of common symbols is defined, then sort common symbols
-  // com_sym = symbol_list.commonBegin();
-  // std::sort(com_sym, com_end, some kind of order);
-
-  // get or create corresponding BSS LDSection
-  LDSection* bss_sect_hdr = NULL;
-  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
-                                   ".tbss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
-  else {
-    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
-                                   LDFileFormat::BSS,
-                                   llvm::ELF::SHT_NOBITS,
-                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-  }
-
-  // get or create corresponding BSS MCSectionData
-  assert(NULL != bss_sect_hdr);
-  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);
-
-  // allocate all common symbols
-  uint64_t offset = bss_sect_hdr->size();
-
-  // allocate all local common symbols
-  com_end = symbol_list.localEnd();
-  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
-    if (ResolveInfo::Common == (*com_sym)->desc()) {
-      // We have to reset the description of the symbol here. When doing
-      // incremental linking, the output relocatable object may have common
-      // symbols. Therefore, we can not treat common symbols as normal symbols
-      // when emitting the regular name pools. We must change the symbols'
-      // description here.
-      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
-      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-      uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                         bss_section,
-                                                         (*com_sym)->value());
-      offset += size;
-    }
-  }
-
-  // allocate all global common symbols
-  com_end = symbol_list.commonEnd();
-  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
-    // We have to reset the description of the symbol here. When doing
-    // incremental linking, the output relocatable object may have common
-    // symbols. Therefore, we can not treat common symbols as normal symbols
-    // when emitting the regular name pools. We must change the symbols'
-    // description here.
-    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
-    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
-    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
-    uint64_t size = pLinker.getLayout().appendFragment(*frag,
-                                                       bss_section,
-                                                       (*com_sym)->value());
-    offset += size;
-  }
-
-  bss_sect_hdr->setSize(offset);
-  symbol_list.changeCommonsToGlobal();
   return true;
 }
 
diff --git a/lib/Target/X86/X86LDBackend.h b/lib/Target/X86/X86LDBackend.h
index a745999..7264c40 100644
--- a/lib/Target/X86/X86LDBackend.h
+++ b/lib/Target/X86/X86LDBackend.h
@@ -11,6 +11,7 @@
 
 #include "X86ELFDynamic.h"
 #include "X86GOT.h"
+#include "X86GOTPLT.h"
 #include "X86PLT.h"
 #include <mcld/LD/LDSection.h>
 #include <mcld/Target/GNULDBackend.h>
@@ -82,6 +83,10 @@
 
   const X86GOT& getGOT() const;
 
+  X86GOTPLT& getGOTPLT();
+
+  const X86GOTPLT& getGOTPLT() const;
+
   X86PLT& getPLT();
 
   const X86PLT& getPLT() const;
@@ -120,11 +125,13 @@
   /// @param pOutput - the output file
   /// @param pSection - the given LDSection
   /// @param pInfo - all options in the command line.
+  /// @param pLayout - for comouting the size of fragment
   /// @param pRegion - the region to write out data
   /// @return the size of the table in the file.
   uint64_t emitSectionData(const Output& pOutput,
                            const LDSection& pSection,
                            const MCLDInfo& pInfo,
+                           const Layout& pLayout,
                            MemoryRegion& pRegion) const;
 
   /// OSABI - the value of e_ident[EI_OSABI]
@@ -142,6 +149,9 @@
   uint64_t flags() const
   { return 0x0; }
 
+  uint64_t defaultTextSegmentAddr() const
+  { return 0x08048000; }
+
   /// initTargetSectionMap - initialize target dependent section mapping
   bool initTargetSectionMap(SectionMap& pSectionMap);
 
@@ -150,7 +160,7 @@
 
   void initTargetSections(MCLinker& pLinker);
 
-  void initTargetSymbols(MCLinker& pLinker);
+  void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
   /// scanRelocation - determine the empty entries are needed or not and create
   /// the empty entries if needed.
@@ -162,7 +172,8 @@
                       const LDSymbol& pInputSym,
                       MCLinker& pLinker,
                       const MCLDInfo& pLDInfo,
-                      const Output& pOutput);
+                      const Output& pOutput,
+                      const LDSection& pSection);
 
   OutputRelocSection& getRelDyn();
 
@@ -174,21 +185,11 @@
 
   /// getTargetSectionOrder - compute the layout order of X86 target sections
   unsigned int getTargetSectionOrder(const Output& pOutput,
-                                     const LDSection& pSectHdr) const;
+                                     const LDSection& pSectHdr,
+                                     const MCLDInfo& pInfo) const;
 
-  /// finalizeSymbol - finalize the symbol value
-  /// If the symbol's reserved field is not zero, MCLinker will call back this
-  /// function to ask the final value of the symbol
-  bool finalizeSymbol(LDSymbol& pSymbol) const;
-
-  /// allocateCommonSymbols - allocate common symbols in the corresponding
-  /// sections.
-  bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
-
-public:
-  bool isSymbolPreemptible(const ResolveInfo& pSym,
-                           const MCLDInfo& pLDInfo,
-                           const Output& pOutput) const;
+  /// finalizeTargetSymbols - finalize the symbol value
+  bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
 
 private:
   void scanLocalReloc(Relocation& pReloc,
@@ -203,28 +204,30 @@
                        const MCLDInfo& pLDInfo,
                        const Output& pOutput);
 
-  bool isSymbolNeedsPLT(const ResolveInfo& pSym,
-                        const MCLDInfo& pLDInfo,
-                        const Output& pOutput) const;
+  /// addCopyReloc - add a copy relocation into .rel.dyn for pSym
+  /// @param pSym - A resolved copy symbol that defined in BSS section
+  void addCopyReloc(ResolveInfo& pSym);
 
-  bool isSymbolNeedsDynRel(const ResolveInfo& pSym,
-                           const Output& pOutput,
-                           bool isAbsReloc) const;
+  /// defineSymbolforCopyReloc - allocate a space in BSS section and
+  /// and force define the copy of pSym to BSS section
+  /// @return the output LDSymbol of the copy symbol
+  LDSymbol& defineSymbolforCopyReloc(MCLinker& pLinker,
+                                     const ResolveInfo& pSym);
 
   void updateAddend(Relocation& pReloc,
                     const LDSymbol& pInputSym,
                     const Layout& pLayout) const;
 
   void createX86GOT(MCLinker& pLinker, const Output& pOutput);
+  void createX86GOTPLT(MCLinker& pLinker, const Output& pOutput);
   void createX86PLTandRelPLT(MCLinker& pLinker, const Output& pOutput);
   void createX86RelDyn(MCLinker& pLinker, const Output& pOutput);
 
-  ELFFileFormat* getOutputFormat(const Output& pOutput) const;
-
 private:
   RelocationFactory* m_pRelocFactory;
   X86GOT* m_pGOT;
   X86PLT* m_pPLT;
+  X86GOTPLT* m_pGOTPLT;
   /// m_RelDyn - dynamic relocation table of .rel.dyn
   OutputRelocSection* m_pRelDyn;
   /// m_RelPLT - dynamic relocation table of .rel.plt
@@ -254,3 +257,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index e9f9db1..caf6f32 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -6,38 +6,38 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-#include "X86GOT.h"
+#include "X86GOTPLT.h"
 #include "X86PLT.h"
 #include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <llvm/Support/ELF.h>
 #include <mcld/MC/MCLDOutput.h>
+#include <mcld/Support/MsgHandling.h>
 #include <new>
 
 namespace {
 
 const uint8_t x86_dyn_plt0[] = {
-  0xff, 0xb3, 0x04, 0, 0, 0,		// pushl  0x4(%ebx)
-  0xff, 0xa3, 0x08, 0, 0, 0,		// jmp    *0x8(%ebx)
-  0xf, 0x1f, 0x4, 0			// nopl   0(%eax)
+  0xff, 0xb3, 0x04, 0, 0, 0, // pushl  0x4(%ebx)
+  0xff, 0xa3, 0x08, 0, 0, 0, // jmp    *0x8(%ebx)
+  0x0f, 0x1f, 0x4,  0        // nopl   0(%eax)
 };
 
 const uint8_t x86_dyn_plt1[] = {
-  0xff, 0xa3, 0, 0, 0, 0,		// jmp    *sym@GOT(%ebx)
-  0x68, 0, 0, 0, 0,			// pushl  $offset
-  0xe9, 0, 0, 0, 0			// jmp    plt0
+  0xff, 0xa3, 0, 0, 0, 0,    // jmp    *sym@GOT(%ebx)
+  0x68, 0, 0, 0, 0,          // pushl  $offset
+  0xe9, 0, 0, 0, 0           // jmp    plt0
 };
 
 const uint8_t x86_exec_plt0[] = {
-  0xff, 0x35, 0, 0, 0, 0,		// pushl  .got + 4
-  0xff, 0x25, 0, 0, 0, 0,		// jmp    *(.got + 8)
-  0xf, 0x1f, 0x4, 0			// nopl   0(%eax)
+  0xff, 0x35, 0, 0, 0, 0,    // pushl  .got + 4
+  0xff, 0x25, 0, 0, 0, 0,    // jmp    *(.got + 8)
+  0x0f, 0x1f, 0x4, 0         // nopl   0(%eax)
 };
 
 const uint8_t x86_exec_plt1[] = {
-  0xff, 0x25, 0, 0, 0, 0,		// jmp    *(sym in .got)
-  0x68, 0, 0, 0, 0,			// pushl  $offset
-  0xe9, 0, 0, 0, 0			// jmp    plt0
+  0xff, 0x25, 0, 0, 0, 0,    // jmp    *(sym in .got)
+  0x68, 0, 0, 0, 0,          // pushl  $offset
+  0xe9, 0, 0, 0, 0           // jmp    plt0
 };
 
 }
@@ -55,9 +55,12 @@
 
 X86PLT::X86PLT(LDSection& pSection,
                llvm::MCSectionData& pSectionData,
-               X86GOT &pGOTPLT,
-	       const Output& pOutput)
-  : PLT(pSection, pSectionData), m_GOT(pGOTPLT), m_PLTEntryIterator()
+               X86GOTPLT &pGOTPLT,
+               const Output& pOutput)
+  : PLT(pSection, pSectionData),
+    m_GOTPLT(pGOTPLT),
+    m_PLTEntryIterator(),
+    m_Output(pOutput)
 {
   assert (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type());
   if (Output::DynObj == pOutput.type()) {
@@ -86,26 +89,17 @@
 void X86PLT::reserveEntry(size_t pNum)
 {
   X86PLT1* plt1_entry = 0;
-  GOTEntry* got_entry = 0;
 
   for (size_t i = 0; i < pNum; ++i) {
     plt1_entry = new (std::nothrow) X86PLT1(&m_SectionData, m_PLT1Size);
 
     if (!plt1_entry)
-      llvm::report_fatal_error("Allocating new memory for X86PLT1 failed!");
+      fatal(diag::fail_allocate_memory) << "X86PLT1";
 
     m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
 
-    got_entry= new (std::nothrow) GOTEntry(0, m_GOT.getEntrySize(),
-                                           &(m_GOT.m_SectionData));
-
-    if (!got_entry)
-      llvm::report_fatal_error("Allocating new memory for GOT failed!");
-
-    m_GOT.m_Section.setSize(m_GOT.m_Section.size() + m_GOT.f_EntrySize);
-
-    ++(m_GOT.m_GOTPLTNum);
-    ++(m_GOT.m_GeneralGOTIterator);
+    // reserve corresponding entry in .got.plt
+    m_GOTPLT.reserveEntry(pNum);
   }
 }
 
@@ -116,47 +110,20 @@
    pExist = 1;
 
    if (!PLTEntry) {
-     GOTEntry *&GOTPLTEntry = m_GOT.m_GOTPLTMap[&pSymbol];
-     assert(!GOTPLTEntry && "PLT entry and got.plt entry doesn't match!");
-
      pExist = 0;
 
      // This will skip PLT0.
      ++m_PLTEntryIterator;
      assert(m_PLTEntryIterator != m_SectionData.end() &&
             "The number of PLT Entries and ResolveInfo doesn't match");
-     ++(m_GOT.m_GOTPLTIterator);
-
      PLTEntry = llvm::cast<X86PLT1>(&(*m_PLTEntryIterator));
-     GOTPLTEntry = llvm::cast<GOTEntry>(&(*(m_GOT.m_GOTPLTIterator)));
    }
-
    return PLTEntry;
 }
 
 GOTEntry* X86PLT::getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
 {
-   GOTEntry *&GOTPLTEntry = m_GOT.m_GOTPLTMap[&pSymbol];
-
-   pExist = 1;
-
-   if (!GOTPLTEntry) {
-     X86PLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
-     assert(!PLTEntry && "PLT entry and got.plt entry doesn't match!");
-
-     pExist = 0;
-
-     // This will skip PLT0.
-     ++m_PLTEntryIterator;
-     assert(m_PLTEntryIterator != m_SectionData.end() &&
-            "The number of PLT Entries and ResolveInfo doesn't match");
-     ++(m_GOT.m_GOTPLTIterator);
-
-     PLTEntry = llvm::cast<X86PLT1>(&(*m_PLTEntryIterator));
-     GOTPLTEntry = llvm::cast<GOTEntry>(&(*(m_GOT.m_GOTPLTIterator)));
-   }
-
-   return GOTPLTEntry;
+   return m_GOTPLT.getEntry(pSymbol, pExist);
 }
 
 X86PLT0* X86PLT::getPLT0() const {
@@ -185,12 +152,12 @@
   data = static_cast<unsigned char*>(malloc(plt0->getEntrySize()));
 
   if (!data)
-    llvm::report_fatal_error("Allocating new memory for plt0 failed!");
+    fatal(diag::fail_allocate_memory) << "plt0";
 
   memcpy(data, m_PLT0, plt0->getEntrySize());
 
   if (m_PLT0 == x86_exec_plt0) {
-    uint64_t got_base = m_GOT.getSection().addr();
+    uint64_t got_base = m_GOTPLT.getSection().addr();
     assert(got_base && ".got base address is NULL!");
     uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
     *offset = got_base + 4;
@@ -207,17 +174,17 @@
   uint64_t plt_base = m_Section.addr();
   assert(plt_base && ".plt base address is NULL!");
 
-  uint64_t got_base = m_GOT.getSection().addr();
+  uint64_t got_base = m_GOTPLT.getSection().addr();
   assert(got_base && ".got base address is NULL!");
 
   X86PLT::iterator it = m_SectionData.begin();
   X86PLT::iterator ie = m_SectionData.end();
   assert(it!=ie && "FragmentList is empty, applyPLT1 failed!");
 
-  uint64_t GOTEntrySize = m_GOT.getEntrySize();
+  uint64_t GOTEntrySize = m_GOTPLT.getEntrySize();
 
   // Skip GOT0
-  uint64_t GOTEntryOffset = GOTEntrySize * X86GOT0Num;
+  uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
 
   //skip PLT0
   uint64_t PLTEntryOffset = m_PLT0Size;
@@ -233,14 +200,19 @@
     data = static_cast<unsigned char*>(malloc(plt1->getEntrySize()));
 
     if (!data)
-      llvm::report_fatal_error("Allocating new memory for plt1 failed!");
+      fatal(diag::fail_allocate_memory) << "plt1";
 
     memcpy(data, m_PLT1, plt1->getEntrySize());
 
     uint32_t* offset;
 
     offset = reinterpret_cast<uint32_t*>(data + 2);
-    *offset = GOTEntryOffset;
+    if (m_Output.type() == Output::DynObj) {
+      *offset = GOTEntryOffset;
+    } else {
+      // Exec
+      *offset = got_base + GOTEntryOffset;
+    }
     GOTEntryOffset += GOTEntrySize;
 
     offset = reinterpret_cast<uint32_t*>(data + 7);
@@ -255,24 +227,9 @@
     ++it;
   }
 
-  unsigned int GOTPLTNum = m_GOT.getGOTPLTNum();
-
-  if (GOTPLTNum != 0) {
-    X86GOT::iterator gotplt_it = m_GOT.getLastGOT0();
-    X86GOT::iterator list_ie = m_GOT.getSectionData().getFragmentList().end();
-
-    ++gotplt_it;
-    uint64_t PLTEntryAddress = plt_base + m_PLT0Size;
-    for (unsigned int i = 0; i < GOTPLTNum; ++i) {
-      if (gotplt_it == list_ie)
-        llvm::report_fatal_error(
-          "The number of got.plt entries is inconsistent!");
-
-      llvm::cast<GOTEntry>(*gotplt_it).setContent(PLTEntryAddress + 6);
-      PLTEntryAddress += m_PLT1Size;
-      ++gotplt_it;
-    }
-  }
+  // apply .got.plt
+  m_GOTPLT.applyAllGOTPLT(plt_base, m_PLT0Size, m_PLT1Size);
 }
 
 } // end namespace mcld
+
diff --git a/lib/Target/X86/X86PLT.h b/lib/Target/X86/X86PLT.h
index dd72f52..6c7002a 100644
--- a/lib/Target/X86/X86PLT.h
+++ b/lib/Target/X86/X86PLT.h
@@ -13,7 +13,7 @@
 
 namespace mcld {
 
-class X86GOT;
+class X86GOTPLT;
 class GOTEntry;
 class Output;
 
@@ -41,8 +41,8 @@
 public:
   X86PLT(LDSection& pSection,
          llvm::MCSectionData& pSectionData,
-         X86GOT& pGOTPLT,
-	 const Output& pOutput);
+         X86GOTPLT& pGOTPLT,
+         const Output& pOutput);
   ~X86PLT();
 
 // Override virtual function.
@@ -72,7 +72,7 @@
   void applyPLT1();
 
 private:
-  X86GOT& m_GOT;
+  X86GOTPLT& m_GOTPLT;
 
   // Used by getEntry() for mapping a ResolveInfo
   // instance to a PLT1 Entry.
@@ -84,6 +84,8 @@
   const uint8_t *m_PLT1;
   unsigned int m_PLT0Size;
   unsigned int m_PLT1Size;
+
+  const Output& m_Output;
 };
 
 } // namespace of mcld
diff --git a/lib/Target/X86/X86RelocationFactory.cpp b/lib/Target/X86/X86RelocationFactory.cpp
index 15b9a6b..9090d1a 100644
--- a/lib/Target/X86/X86RelocationFactory.cpp
+++ b/lib/Target/X86/X86RelocationFactory.cpp
@@ -8,11 +8,11 @@
 //===----------------------------------------------------------------------===//
 
 #include <llvm/ADT/Twine.h>
-#include <llvm/Support/ErrorHandling.h>
 #include <llvm/Support/DataTypes.h>
 #include <llvm/Support/ELF.h>
 #include <mcld/MC/MCLDInfo.h>
 #include <mcld/LD/Layout.h>
+#include <mcld/Support/MsgHandling.h>
 
 #include "X86RelocationFactory.h"
 #include "X86RelocationFunctions.h"
@@ -56,11 +56,8 @@
   };
 
   if (type >= sizeof (apply_functions) / sizeof (apply_functions[0]) ) {
-    llvm::report_fatal_error(llvm::Twine("Unknown relocation type ") +
-			     llvm::Twine((int) type) +
-			     llvm::Twine(" to symbol `") +
-                             pRelocation.symInfo()->name() +
-                             llvm::Twine("'."));
+    fatal(diag::unknown_relocation) << (int)type <<
+                                       pRelocation.symInfo()->name();
     return;
   }
 
@@ -68,22 +65,18 @@
   Result result = apply_functions[type].func(pRelocation, pLDInfo, *this);
 
   // check result
+  if (OK == result) {
+    return;
+  }
   if (Overflow == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' causes overflow. on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_overflow) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
 
   if (BadReloc == result) {
-    llvm::report_fatal_error(llvm::Twine("Applying relocation `") +
-                             llvm::Twine(apply_functions[type].name) +
-                             llvm::Twine("' encounters unexpected opcode. "
-                                         "on symbol: `") +
-                             llvm::Twine(pRelocation.symInfo()->name()) +
-                             llvm::Twine("'."));
+    error(diag::result_badreloc) << apply_functions[type].name
+                                 << pRelocation.symInfo()->name();
     return;
   }
 }
@@ -104,7 +97,7 @@
 
 {
   // if symbol is dynamic or undefine or preemptible
-  if(pSym.isDyn() ||
+  if (pSym.isDyn() ||
      pSym.isUndef() ||
      pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output()))
     return false;
@@ -133,7 +126,7 @@
       Relocation& rel_entry =
         *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
       assert(!exist && "GOT entry not exist, but DynRel entry exist!");
-      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
         // Initialize got entry to target symbol address
         got_entry.setContent(pReloc.symValue());
         rel_entry.setType(llvm::ELF::R_386_RELATIVE);
@@ -147,7 +140,7 @@
       rel_entry.targetRef().assign(got_entry);
     }
     else {
-      llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!");
+      fatal(diag::reserve_entry_number_mismatch) << "GOT";
     }
   }
   return got_entry;
@@ -157,7 +150,7 @@
 static
 X86RelocationFactory::Address helper_GOT_ORG(X86RelocationFactory& pParent)
 {
-  return pParent.getTarget().getGOT().getSection().addr();
+  return pParent.getTarget().getGOTPLT().getSection().addr();
 }
 
 
@@ -167,7 +160,9 @@
                                          X86RelocationFactory& pParent)
 {
   GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo,  pParent);
-  return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry);
+  X86RelocationFactory::Address got_addr =
+    pParent.getTarget().getGOT().getSection().addr();
+  return got_addr + pParent.getLayout().getOutputOffset(got_entry);
 }
 
 
@@ -195,7 +190,7 @@
       rel_entry.setSymInfo(rsym);
     }
     else {
-      llvm::report_fatal_error("No PLT entry reserved for PLT type relocation!");
+      fatal(diag::reserve_entry_number_mismatch) << "PLT";
     }
   }
   return plt_entry;
@@ -235,7 +230,7 @@
   rel_entry.setType(pType);
   rel_entry.targetRef() = pReloc.targetRef();
 
-  if(pType == llvm::ELF::R_386_RELATIVE)
+  if (pType == llvm::ELF::R_386_RELATIVE)
     rel_entry.setSymInfo(0);
   else
     rel_entry.setSymInfo(rsym);
@@ -263,18 +258,34 @@
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
   RelocationFactory::DWord S = pReloc.symValue();
 
-  if(rsym->isLocal() && (rsym->reserved() & X86GNULDBackend::ReserveRel)) {
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    pReloc.target() = S + A;
+    return X86RelocationFactory::OK;
+  }
+
+  // A local symbol may need REL Type dynamic relocation
+  if (rsym->isLocal() && (rsym->reserved() & X86GNULDBackend::ReserveRel)) {
     helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
     pReloc.target() = S + A;
     return X86RelocationFactory::OK;
   }
-  else if(!rsym->isLocal()) {
-    if(rsym->reserved() & X86GNULDBackend::ReservePLT) {
+
+  // An external symbol may need PLT and dynamic relocation
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
       S = helper_PLT(pReloc, pParent);
       pReloc.target() = S + A;
     }
-    if(rsym->reserved() & X86GNULDBackend::ReserveRel) {
-      if(helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
+    // If we generate a dynamic relocation (except R_386_RELATIVE)
+    // for a place, we should not perform static relocation on it
+    // in order to keep the addend store in the place correct.
+    if (rsym->reserved() & X86GNULDBackend::ReserveRel) {
+      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
         helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
       }
       else {
@@ -294,10 +305,42 @@
                                    const MCLDInfo& pLDInfo,
                                    X86RelocationFactory& pParent)
 {
-  // perform static relocation
+  ResolveInfo* rsym = pReloc.symInfo();
   RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
-  pReloc.target() = pReloc.symValue() + A
-      - pReloc.place(pParent.getLayout());
+  RelocationFactory::DWord S = pReloc.symValue();
+  RelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+
+  const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
+                                                  *(pReloc.targetRef().frag()));
+  assert(NULL != target_sect);
+  // If the flag of target section is not ALLOC, we will not scan this relocation
+  // but perform static relocation. (e.g., applying .debug section)
+  if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+    pReloc.target() = S + A - P;
+    return X86RelocationFactory::OK;
+  }
+
+  // An external symbol may need PLT and dynamic relocation
+  if (!rsym->isLocal()) {
+    if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
+       S = helper_PLT(pReloc, pParent);
+       pReloc.target() = S + A - P;
+    }
+    if (pParent.getTarget().symbolNeedsDynRel(
+          *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo,
+                  pLDInfo.output(), false)) {
+      if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
+        helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+      }
+      else {
+        helper_DynRel(pReloc, pReloc.type(), pParent);
+          return X86RelocationFactory::OK;
+      }
+    }
+  }
+
+   // perform static relocation
+  pReloc.target() = S + A - P;
   return X86RelocationFactory::OK;
 }
 
@@ -331,7 +374,7 @@
                                    const MCLDInfo& pLDInfo,
                                    X86RelocationFactory& pParent)
 {
-  if(!(pReloc.symInfo()->reserved()
+  if (!(pReloc.symInfo()->reserved()
        & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
     return X86RelocationFactory::BadReloc;
   }
@@ -350,7 +393,7 @@
 {
   // PLT_S depends on if there is a PLT entry.
   X86RelocationFactory::Address PLT_S;
-  if((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
+  if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
     PLT_S = helper_PLT(pReloc, pParent);
   else
     PLT_S = pReloc.symValue();
diff --git a/lib/Target/X86/X86RelocationFactory.h b/lib/Target/X86/X86RelocationFactory.h
index 779a21d..6a6c372 100644
--- a/lib/Target/X86/X86RelocationFactory.h
+++ b/lib/Target/X86/X86RelocationFactory.h
@@ -55,3 +55,4 @@
 } // namespace of mcld
 
 #endif
+
diff --git a/lib/Target/X86/X86SectLinker.cpp b/lib/Target/X86/X86SectLinker.cpp
index 14621f3..a25a4c3 100644
--- a/lib/Target/X86/X86SectLinker.cpp
+++ b/lib/Target/X86/X86SectLinker.cpp
@@ -10,7 +10,6 @@
 #include <mcld/Support/TargetRegistry.h>
 
 #include "X86.h"
-#include "X86AndroidSectLinker.h"
 #include "X86ELFSectLinker.h"
 
 using namespace mcld;
@@ -31,9 +30,10 @@
     assert(0 && "COFF linker has not supported yet");
   }
 
-  // For now, use Android SectLinker directly
-  return new X86AndroidSectLinker(pOption,
-                                  pLDBackend);
+  if (theTriple.isArch32Bit())
+    return new X86ELFSectLinker(pOption, pLDBackend);
+
+  assert(0 && "X86_64 has not supported yet");
 }
 
 } // namespace of mcld
@@ -44,3 +44,4 @@
   // Register the linker frontend
   mcld::TargetRegistry::RegisterSectLinker(TheX86Target, createX86SectLinker);
 }
+
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index b3d7779..b036137 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -31,3 +31,4 @@
 {
   delete m_pLDInfo;
 }
+