MCLinker upstream commit e764452.

Change-Id: I5c9ec467ec96a0143e1e67c59365f3b6303e7348
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;
+}