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;
+}