MCLinker upstream commit 9628cfb76b5a.
Change-Id: I6d12c63bdae94299558dc1cf42b489bb98748851
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp
index e24596c..822ff36 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/LLVMTargetMachine.cpp
@@ -7,14 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "mcld/CodeGen/SectLinker.h"
-#include "mcld/CodeGen/SectLinkerOption.h"
-#include "mcld/MC/MCBitcodeInterceptor.h"
-#include "mcld/MC/MCLDFile.h"
-#include "mcld/Support/RealPath.h"
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/Target/TargetMachine.h"
-#include "mcld/Target/TargetLDBackend.h"
+#include <mcld/CodeGen/SectLinker.h>
+#include <mcld/CodeGen/SectLinkerOption.h>
+#include <mcld/MC/MCLDFile.h>
+#include <mcld/Support/RealPath.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Target/TargetMachine.h>
+#include <mcld/Target/TargetLDBackend.h>
#include <llvm/ADT/OwningPtr.h>
#include <llvm/Analysis/Passes.h>
@@ -55,6 +54,7 @@
//===----------------------------------------------------------------------===//
/// Arguments
+//===----------------------------------------------------------------------===//
// Enable or disable FastISel. Both options are needed, because
// FastISel is enabled by default with -fast, and we wish to be
// able to enable or disable fast-isel independently from -O0.
@@ -91,6 +91,7 @@
//===---------------------------------------------------------------------===//
/// LLVMTargetMachine
+//===----------------------------------------------------------------------===//
mcld::LLVMTargetMachine::LLVMTargetMachine(llvm::TargetMachine &pTM,
const mcld::Target& pTarget,
const std::string& pTriple )
@@ -265,17 +266,19 @@
llvm::MCContext *&Context)
{
const MCAsmInfo &MAI = *getTM().getMCAsmInfo();
+ const MCInstrInfo &MII = *getTM().getInstrInfo();
+ const MCRegisterInfo &MRI = *getTM().getRegisterInfo();
const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
MCInstPrinter *InstPrinter =
getTarget().get()->createMCInstPrinter(MAI.getAssemblerDialect(), MAI,
- *(getTM().getInstrInfo()),
+ MII,
Context->getRegisterInfo(), STI);
MCCodeEmitter* MCE = 0;
MCAsmBackend *MAB = 0;
if (ArgShowMCEncoding) {
- MCE = getTarget().get()->createMCCodeEmitter(*(getTM().getInstrInfo()), STI, *Context);
+ MCE = getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context);
MAB = getTarget().get()->createMCAsmBackend(m_Triple);
}
@@ -308,8 +311,11 @@
llvm::MCContext *&Context)
{
// MCCodeEmitter
+ const MCInstrInfo &MII = *getTM().getInstrInfo();
+ const MCRegisterInfo &MRI = *getTM().getRegisterInfo();
const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
- MCCodeEmitter* MCE = getTarget().get()->createMCCodeEmitter(*getTM().getInstrInfo(), STI, *Context);
+ MCCodeEmitter* MCE =
+ getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context);
// MCAsmBackend
MCAsmBackend* MAB = getTarget().get()->createMCAsmBackend(m_Triple);
@@ -342,50 +348,10 @@
MCLDFile::Type pOutputLinkType,
llvm::MCContext *&Context)
{
-// FIXME: when MCLinker can directly turn bitcode into shared object, turn on this
-// block of code.
-#if 0
- // Initialize MCAsmStreamer first, than chain its output into SectLinker.
- // MCCodeEmitter
- const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
- MCCodeEmitter* MCE = getTarget().get()->createMCCodeEmitter(*getTM().getInstrInfo(),
- STI,
- *Context);
- // MCAsmBackend
- MCAsmBackend *MAB = getTarget().get()->createMCAsmBackend(m_Triple);
- if (MCE == 0 || MAB == 0)
- return true;
-
- // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
- MCStreamer* AsmStreamer =
- getTarget().get()->createMCObjectStreamer(m_Triple,
- *Context,
- *MAB,
- llvm::nulls(),
- MCE,
- getTM().hasMCRelaxAll(),
- getTM().hasMCNoExecStack());
- if (0 == AsmStreamer)
- return true;
-
- AsmStreamer->InitSections();
- AsmPrinter* printer = getTarget().get()->createAsmPrinter(getTM(), *AsmStreamer);
- if (0 == printer)
- return true;
- pPM.add(printer);
-#endif
TargetLDBackend* ldBackend = getTarget().createLDBackend(m_Triple);
if (0 == ldBackend)
return true;
-// FIXME: when MCLinker can directly turn bitcode into shared object, turn on this
-// block of code.
-#if 0
- MCBitcodeInterceptor* objReader = new MCBitcodeInterceptor(
- static_cast<MCObjectStreamer&>(*AsmStreamer),
- *ldBackend,
- getLDInfo());
-#endif
// set up output's SOName
if (pOutputLinkType == MCLDFile::DynObj &&
pLinkerOpt->info().output().name().empty()) {
diff --git a/lib/CodeGen/SectLinker.cpp b/lib/CodeGen/SectLinker.cpp
index 4f32c4f..0e4c3ad 100644
--- a/lib/CodeGen/SectLinker.cpp
+++ b/lib/CodeGen/SectLinker.cpp
@@ -77,7 +77,7 @@
initializeInputTree(PosDepOpts);
initializeInputOutput(info);
// Now, all input arguments are prepared well, send it into MCLDDriver
- m_pLDDriver = new MCLDDriver(info, *m_pLDBackend);
+ m_pLDDriver = new MCLDDriver(info, *m_pLDBackend, *memAreaFactory());
return false;
}
@@ -133,16 +133,11 @@
return true;
- // 6. - read all sections
- if (!m_pLDDriver->readSections() ||
- !m_pLDDriver->mergeSections())
+ // 6. - merge all sections
+ if (!m_pLDDriver->mergeSections())
return true;
- // 7. - read all symbol tables of input files and resolve them
- if (!m_pLDDriver->readSymbolTables())
- return true;
-
- // 7.a - add standard symbols and target-dependent symbols
+ // 7. - add standard symbols and target-dependent symbols
// m_pLDDriver->addUndefSymbols();
if (!m_pLDDriver->addStandardSymbols() ||
!m_pLDDriver->addTargetSymbols())
@@ -157,7 +152,7 @@
// 10. - linear layout
m_pLDDriver->layout();
- // 10.b - post-layout
+ // 10.b - post-layout (create segment, instruction relaxing)
m_pLDDriver->postlayout();
// 11. - finalize symbol value
diff --git a/lib/LD/AlignFragment.cpp b/lib/LD/AlignFragment.cpp
new file mode 100644
index 0000000..5154b0b
--- /dev/null
+++ b/lib/LD/AlignFragment.cpp
@@ -0,0 +1,27 @@
+//===- AlignFragment.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/AlignFragment.h>
+
+#include <mcld/LD/SectionData.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// AlignFragment
+//===----------------------------------------------------------------------===//
+AlignFragment::AlignFragment(unsigned int pAlignment,
+ int64_t pValue,
+ unsigned int pValueSize,
+ unsigned int pMaxBytesToEmit,
+ SectionData *pSD)
+ : Fragment(Fragment::Alignment, pSD), m_Alignment(pAlignment),
+ m_Value(pValue), m_ValueSize(pValueSize), m_MaxBytesToEmit(pMaxBytesToEmit),
+ m_bEmitNops(false) {
+}
+
diff --git a/lib/LD/Android.mk b/lib/LD/Android.mk
index d7cccfa..d3c9dd8 100644
--- a/lib/LD/Android.mk
+++ b/lib/LD/Android.mk
@@ -5,6 +5,8 @@
# =====================================================
mcld_ld_SRC_FILES := \
+ AlignFragment.cpp \
+ Archive.cpp \
ArchiveReader.cpp \
BranchIsland.cpp \
CIE.cpp \
@@ -22,6 +24,9 @@
EhFrameHdr.cpp \
ExecWriter.cpp \
FDE.cpp \
+ FillFragment.cpp \
+ Fragment.cpp \
+ FragmentRef.cpp \
Layout.cpp \
LDContext.cpp \
LDFileFormat.cpp \
@@ -33,11 +38,13 @@
MsgHandler.cpp \
NamePool.cpp \
ObjectWriter.cpp \
+ RegionFragment.cpp \
Relocation.cpp \
RelocationFactory.cpp \
ResolveInfo.cpp \
ResolveInfoFactory.cpp \
Resolver.cpp \
+ SectionData.cpp \
SectionMap.cpp \
SectionMerger.cpp \
StaticResolver.cpp \
diff --git a/lib/LD/Archive.cpp b/lib/LD/Archive.cpp
new file mode 100644
index 0000000..2805541
--- /dev/null
+++ b/lib/LD/Archive.cpp
@@ -0,0 +1,229 @@
+//===- Archive.cpp --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/Archive.h>
+#include <mcld/MC/InputFactory.h>
+#include <llvm/ADT/StringRef.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Archive
+const char Archive::MAGIC[] = "!<arch>\n";
+const char Archive::THIN_MAGIC[] = "!<thin>\n";
+const size_t Archive::MAGIC_LEN = sizeof(Archive::MAGIC) - 1;
+const char Archive::SVR4_SYMTAB_NAME[] = "/ ";
+const char Archive::STRTAB_NAME[] = "// ";
+const char Archive::PAD[] = "\n";
+const char Archive::MEMBER_MAGIC[] = "`\n";
+
+Archive::Archive(Input& pInputFile, InputFactory& pInputFactory)
+ : m_ArchiveFile(pInputFile),
+ m_pInputTree(NULL),
+ m_SymbolFactory(32)
+{
+ m_pInputTree = new InputTree(pInputFactory);
+}
+
+Archive::~Archive()
+{
+ delete m_pInputTree;
+}
+
+/// getARFile - get the Input& of the archive file
+Input& Archive::getARFile()
+{
+ return m_ArchiveFile;
+}
+
+/// getARFile - get the Input& of the archive file
+const Input& Archive::getARFile() const
+{
+ return m_ArchiveFile;
+}
+
+/// inputs - get the input tree built from this archive
+InputTree& Archive::inputs()
+{
+ return *m_pInputTree;
+}
+
+/// inputs - get the input tree built from this archive
+const InputTree& Archive::inputs() const
+{
+ return *m_pInputTree;
+}
+
+/// getObjectMemberMap - get the map that contains the included object files
+Archive::ObjectMemberMapType& Archive::getObjectMemberMap()
+{
+ return m_ObjectMemberMap;
+}
+
+/// getObjectMemberMap - get the map that contains the included object files
+const Archive::ObjectMemberMapType& Archive::getObjectMemberMap() const
+{
+ return m_ObjectMemberMap;
+}
+
+/// numOfObjectMember - return the number of included object files
+size_t Archive::numOfObjectMember() const
+{
+ return m_ObjectMemberMap.numOfEntries();
+}
+
+/// addObjectMember - add a object in the object member map
+/// @param pFileOffset - file offset in symtab represents a object file
+/// @param pIter - the iterator in the input tree built from this archive
+bool Archive::addObjectMember(uint32_t pFileOffset, InputTree::iterator pIter)
+{
+ bool exist;
+ ObjectMemberEntryType* entry = m_ObjectMemberMap.insert(pFileOffset, exist);
+ if (!exist)
+ entry->setValue(pIter);
+ return !exist;
+}
+
+/// hasObjectMember - check if a object file is included or not
+/// @param pFileOffset - file offset in symtab represents a object file
+bool Archive::hasObjectMember(uint32_t pFileOffset) const
+{
+ return (m_ObjectMemberMap.find(pFileOffset) != m_ObjectMemberMap.end());
+}
+
+/// getArchiveMemberMap - get the map that contains the included archive files
+Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap()
+{
+ return m_ArchiveMemberMap;
+}
+
+/// getArchiveMemberMap - get the map that contains the included archive files
+const Archive::ArchiveMemberMapType& Archive::getArchiveMemberMap() const
+{
+ return m_ArchiveMemberMap;
+}
+
+/// addArchiveMember - add an archive in the archive member map
+/// @param pName - the name of the new archive member
+/// @param pLastPos - this records the point to insert the next node in the
+/// subtree of this archive member
+/// @param pMove - this records the direction to insert the next node in the
+/// subtree of this archive member
+bool Archive::addArchiveMember(const llvm::StringRef& pName,
+ InputTree::iterator pLastPos,
+ InputTree::Mover* pMove)
+{
+ bool exist;
+ ArchiveMemberEntryType* entry = m_ArchiveMemberMap.insert(pName, exist);
+ if (!exist) {
+ ArchiveMember& ar = entry->value();
+ ar.file = *pLastPos;
+ ar.lastPos = pLastPos;
+ ar.move = pMove;
+ }
+ return !exist;
+}
+
+/// hasArchiveMember - check if an archive file is included or not
+bool Archive::hasArchiveMember(const llvm::StringRef& pName) const
+{
+ return (m_ArchiveMemberMap.find(pName) != m_ArchiveMemberMap.end());
+}
+
+/// getArchiveMember - get a archive member
+Archive::ArchiveMember* Archive::getArchiveMember(const llvm::StringRef& pName)
+{
+ ArchiveMemberMapType::iterator it = m_ArchiveMemberMap.find(pName);
+ if (it != m_ArchiveMemberMap.end())
+ return &(it.getEntry()->value());
+ return NULL;
+}
+
+/// getSymbolTable - get the symtab
+Archive::SymTabType& Archive::getSymbolTable()
+{
+ return m_SymTab;
+}
+
+/// getSymbolTable - get the symtab
+const Archive::SymTabType& Archive::getSymbolTable() const
+{
+ return m_SymTab;
+}
+
+/// setSymTabSize - set the memory size of symtab
+void Archive::setSymTabSize(size_t pSize)
+{
+ m_SymTabSize = pSize;
+}
+
+/// getSymTabSize - get the memory size of symtab
+size_t Archive::getSymTabSize() const
+{
+ return m_SymTabSize;
+}
+
+/// numOfSymbols - return the number of symbols in symtab
+size_t Archive::numOfSymbols() const
+{
+ return m_SymTab.size();
+}
+
+/// addSymbol - add a symtab entry to symtab
+/// @param pName - symbol name
+/// @param pFileOffset - file offset in symtab represents a object file
+void Archive::addSymbol(const char* pName,
+ uint32_t pFileOffset,
+ enum Archive::Symbol::Status pStatus)
+{
+ Symbol* entry = m_SymbolFactory.allocate();
+ new (entry) Symbol(pName, pFileOffset, pStatus);
+ m_SymTab.push_back(entry);
+}
+
+/// getSymbolName - get the symbol name with the given index
+const std::string& Archive::getSymbolName(size_t pSymIdx) const
+{
+ assert(pSymIdx < numOfSymbols());
+ return m_SymTab[pSymIdx]->name;
+}
+
+/// getObjFileOffset - get the file offset that represent a object file
+uint32_t Archive::getObjFileOffset(size_t pSymIdx) const
+{
+ assert(pSymIdx < numOfSymbols());
+ return m_SymTab[pSymIdx]->fileOffset;
+}
+
+/// getSymbolStatus - get the status of a symbol
+enum Archive::Symbol::Status Archive::getSymbolStatus(size_t pSymIdx) const
+{
+ assert(pSymIdx < numOfSymbols());
+ return m_SymTab[pSymIdx]->status;
+}
+
+/// setSymbolStatus - set the status of a symbol
+void Archive::setSymbolStatus(size_t pSymIdx,
+ enum Archive::Symbol::Status pStatus)
+{
+ assert(pSymIdx < numOfSymbols());
+ m_SymTab[pSymIdx]->status = pStatus;
+}
+
+/// getStrTable - get the extended name table
+std::string& Archive::getStrTable()
+{
+ return m_StrTab;
+}
+
+/// getStrTable - get the extended name table
+const std::string& Archive::getStrTable() const
+{
+ return m_StrTab;
+}
+
diff --git a/lib/LD/BSDArchiveReader.cpp b/lib/LD/BSDArchiveReader.cpp
index 079153b..bd59844 100644
--- a/lib/LD/BSDArchiveReader.cpp
+++ b/lib/LD/BSDArchiveReader.cpp
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/InputTree.h>
#include <mcld/LD/BSDArchiveReader.h>
+#include <mcld/LD/Archive.h>
using namespace mcld;
@@ -20,10 +20,10 @@
{
}
-InputTree *BSDArchiveReader::readArchive(Input &input)
+bool BSDArchiveReader::readArchive(Archive& pArchive)
{
// TODO
- return NULL;
+ return true;
}
bool BSDArchiveReader::isMyFormat(Input& pInput) const
diff --git a/lib/LD/CIE.cpp b/lib/LD/CIE.cpp
index c2f4317..5ddb166 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/LD/CIE.cpp
@@ -11,11 +11,11 @@
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// CIE
-
+//===----------------------------------------------------------------------===//
CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
- : MCRegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+ : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
}
CIE::~CIE()
diff --git a/lib/LD/DiagnosticEngine.cpp b/lib/LD/DiagnosticEngine.cpp
index 8b209c9..173b4f2 100644
--- a/lib/LD/DiagnosticEngine.cpp
+++ b/lib/LD/DiagnosticEngine.cpp
@@ -25,9 +25,6 @@
{
if (m_OwnPrinter && m_pPrinter != NULL)
delete m_pPrinter;
-
- if (NULL != m_pLineInfo)
- delete m_pLineInfo;
}
void DiagnosticEngine::reset(const MCLDInfo& pLDInfo)
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index c69149c..e645567 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -6,20 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <llvm/Support/ELF.h>
-#include <llvm/ADT/Twine.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>
-using namespace llvm;
+#include <llvm/Support/ELF.h>
+#include <llvm/ADT/Twine.h>
+
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/LD/RegionFragment.h>
+#include <mcld/LD/ELFReader.h>
+#include <mcld/LD/ELFObjectReader.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MsgHandling.h>
+
using namespace mcld;
//==========================
@@ -176,10 +177,9 @@
llvm::ELF::SHT_NOBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE);
- llvm::MCSectionData& sect_data = m_Linker.getOrCreateSectData(**section);
- /* value, valsize, size*/
- llvm::MCFillFragment* frag =
- new llvm::MCFillFragment(0x0, 1, (*section)->size());
+ SectionData& sect_data = m_Linker.getOrCreateSectData(**section);
+ /* value, valsize, size*/
+ FillFragment* frag = new FillFragment(0x0, 1, (*section)->size());
uint64_t size = m_Linker.getLayout().appendFragment(*frag,
sect_data,
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index d74d314..fce4e8b 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -11,6 +11,7 @@
#include <llvm/ADT/Twine.h>
#include <llvm/Support/ELF.h>
#include <llvm/Support/Host.h>
+
#include <mcld/MC/MCLinker.h>
#include <mcld/LD/ELFReader.h>
#include <mcld/Target/GNULDBackend.h>
@@ -86,6 +87,21 @@
return LDFileFormat::MetaData;
}
+/// getSymType
+ResolveInfo::Type ELFReaderIF::getSymType(uint8_t pInfo, uint16_t pShndx) const
+{
+ ResolveInfo::Type result = static_cast<ResolveInfo::Type>(pInfo & 0xF);
+ if (llvm::ELF::SHN_ABS == pShndx && ResolveInfo::Section == result) {
+ // In Mips, __gp_disp is a special section symbol. Its name comes from
+ // .strtab, not .shstrtab. However, it is unique. Only it is also a ABS
+ // symbol. So here is a tricky to identify __gp_disp and convert it to
+ // Object symbol.
+ return ResolveInfo::Object;
+ }
+
+ return result;
+}
+
/// getSymDesc
ResolveInfo::Desc ELFReaderIF::getSymDesc(uint16_t pShndx, const Input& pInput) const
{
@@ -135,7 +151,7 @@
}
/// getSymFragmentRef
-MCFragmentRef*
+FragmentRef*
ELFReaderIF::getSymFragmentRef(Input& pInput,
MCLinker& pLinker,
uint16_t pShndx,
@@ -151,7 +167,7 @@
unreachable(diag::unreachable_invalid_section_idx) << pShndx
<< pInput.path().native();
- MCFragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset);
+ FragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset);
return result;
}
diff --git a/lib/LD/ELFSectionMap.cpp b/lib/LD/ELFSectionMap.cpp
new file mode 100644
index 0000000..9d433d7
--- /dev/null
+++ b/lib/LD/ELFSectionMap.cpp
@@ -0,0 +1,87 @@
+//===- ELFSectionMap.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/LD/ELFSectionMap.h>
+
+using namespace mcld;
+
+struct NameMap {
+ const char* from;
+ const char* to;
+};
+
+// Common mappings of ELF and other formants. Now only ELF specific mappings
+// are added
+static const NameMap map[] =
+{
+ {".text", ".text"},
+ {".rodata", ".rodata"},
+ {".data.rel.ro.local", ".data.rel.ro.local"},
+ {".data.rel.ro", ".data.rel.ro"},
+ {".data", ".data"},
+ {".bss", ".bss"},
+ {".tdata", ".tdata"},
+ {".tbss", ".tbss"},
+ {".init_array", ".init_array"},
+ {".fini_array", ".fini_array"},
+ // TODO: Support DT_INIT_ARRAY for all constructors?
+ {".ctors", ".ctors"},
+ {".dtors", ".dtors"},
+ {".sdata", ".sdata"},
+ {".sbss", ".sbss"},
+ // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
+ // sections would be handled differently.
+ {".sdata2", ".sdata"},
+ {".sbss2", ".sbss"},
+ {".lrodata", ".lrodata"},
+ {".ldata", ".ldata"},
+ {".lbss", ".lbss"},
+ {".gcc_except_table", ".gcc_except_table"},
+ {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
+ {".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
+ {".gnu.linkonce.t", ".text"},
+ {".gnu.linkonce.r", ".rodata"},
+ {".gnu.linkonce.d", ".data"},
+ {".gnu.linkonce.b", ".bss"},
+ {".gnu.linkonce.s", ".sdata"},
+ {".gnu.linkonce.sb", ".sbss"},
+ {".gnu.linkonce.s2", ".sdata"},
+ {".gnu.linkonce.sb2", ".sbss"},
+ {".gnu.linkonce.wi", ".debug_info"},
+ {".gnu.linkonce.td", ".tdata"},
+ {".gnu.linkonce.tb", ".tbss"},
+ {".gnu.linkonce.lr", ".lrodata"},
+ {".gnu.linkonce.l", ".ldata"},
+ {".gnu.linkonce.lb", ".lbss"},
+};
+
+static const int map_size = (sizeof(map) / sizeof(map[0]));
+
+ELFSectionMap::ELFSectionMap()
+{
+}
+
+ELFSectionMap::~ELFSectionMap()
+{
+}
+
+void ELFSectionMap::initStandardMaps()
+{
+ for (unsigned int i = 0; i < map_size; ++i) {
+ bool exist = false;
+ NamePair& pair = append(map[i].from, map[i].to, exist);
+ if (exist) {
+ warning(diag::warn_duplicate_std_sectmap) << map[i].from
+ << map[i].to
+ << pair.from
+ << pair.to;
+ }
+ }
+}
+
diff --git a/lib/LD/ELFWriter.cpp b/lib/LD/ELFWriter.cpp
index 2f2d898..bf3152a 100644
--- a/lib/LD/ELFWriter.cpp
+++ b/lib/LD/ELFWriter.cpp
@@ -6,14 +6,19 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
+#include <cstdlib>
+#include <cstring>
+
#include <llvm/Support/ELF.h>
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/MC/MCAssembler.h>
+#include <llvm/Support/Casting.h>
+
#include <mcld/ADT/SizeTraits.h>
-#include <mcld/Support/MemoryRegion.h>
#include <mcld/MC/MCLDInfo.h>
#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCRegionFragment.h>
+#include <mcld/LD/AlignFragment.h>
+#include <mcld/LD/FillFragment.h>
+#include <mcld/LD/RegionFragment.h>
#include <mcld/LD/ELFWriter.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/LD/LDSection.h>
@@ -21,8 +26,7 @@
#include <mcld/LD/ELFSegment.h>
#include <mcld/LD/ELFSegmentFactory.h>
#include <mcld/Target/GNULDBackend.h>
-#include <cstdlib>
-#include <cstring>
+#include <mcld/Support/MemoryRegion.h>
using namespace llvm::ELF;
using namespace mcld;
@@ -397,21 +401,21 @@
const LDSection& pSection,
MemoryRegion& pRegion) const
{
- const llvm::MCSectionData* data = pSection.getSectionData();
- llvm::MCSectionData::const_iterator fragIter, fragEnd = data->end();
+ const SectionData* data = pSection.getSectionData();
+ SectionData::const_iterator fragIter, fragEnd = data->end();
size_t cur_offset = 0;
for (fragIter = data->begin(); fragIter != fragEnd; ++fragIter) {
size_t size = computeFragmentSize(pLayout, *fragIter);
switch(fragIter->getKind()) {
- case llvm::MCFragment::FT_Region: {
- const MCRegionFragment& region_frag = llvm::cast<MCRegionFragment>(*fragIter);
+ case Fragment::Region: {
+ const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
const uint8_t* from = region_frag.getRegion().start();
memcpy(pRegion.getBuffer(cur_offset), from, size);
break;
}
- case llvm::MCFragment::FT_Align: {
+ case Fragment::Alignment: {
// TODO: emit values with different sizes (> 1 byte), and emit nops
- llvm::MCAlignFragment& align_frag = llvm::cast<llvm::MCAlignFragment>(*fragIter);
+ AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
uint64_t count = size / align_frag.getValueSize();
switch (align_frag.getValueSize()) {
case 1u:
@@ -425,8 +429,8 @@
}
break;
}
- case llvm::MCFragment::FT_Fill: {
- llvm::MCFillFragment& fill_frag = llvm::cast<llvm::MCFillFragment>(*fragIter);
+ case Fragment::Fillment: {
+ FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
if (0 == size ||
0 == fill_frag.getValueSize() ||
0 == fill_frag.getSize()) {
@@ -442,19 +446,10 @@
}
break;
}
- case llvm::MCFragment::FT_Data:
- case llvm::MCFragment::FT_Inst:
- case llvm::MCFragment::FT_Org:
- case llvm::MCFragment::FT_Dwarf:
- case llvm::MCFragment::FT_DwarfFrame:
- case llvm::MCFragment::FT_LEB: {
- llvm::report_fatal_error("unsupported fragment yet.\n");
- break;
- }
- case llvm::MCFragment::FT_Reloc:
+ case Fragment::Relocation:
llvm::report_fatal_error("relocation fragment should not be in a regular section.\n");
break;
- case llvm::MCFragment::FT_Target:
+ case Fragment::Target:
llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
break;
default:
@@ -471,13 +466,13 @@
const LDSection& pSection,
MemoryRegion& pRegion) const
{
- const llvm::MCSectionData* SectionData = pSection.getSectionData();
- assert(SectionData && "SectionData is NULL in emitRelocation!");
+ const SectionData* sect_data = pSection.getSectionData();
+ assert(NULL != sect_data && "SectionData is NULL in emitRelocation!");
if (pSection.type() == SHT_REL)
- emitRel(pLayout, pOutput, *SectionData, pRegion);
+ emitRel(pLayout, pOutput, *sect_data, pRegion);
else if (pSection.type() == SHT_RELA)
- emitRela(pLayout, pOutput, *SectionData, pRegion);
+ emitRela(pLayout, pOutput, *sect_data, pRegion);
else
llvm::report_fatal_error("unsupported relocation section type!");
}
@@ -486,31 +481,29 @@
/// emitRel
void ELFWriter::emitRel(const Layout& pLayout,
const Output& pOutput,
- const llvm::MCSectionData& pSectionData,
+ const SectionData& pSectionData,
MemoryRegion& pRegion) const
{
Elf32_Rel* rel = reinterpret_cast<Elf32_Rel*>(pRegion.start());
Relocation* relocation = 0;
- MCFragmentRef* FragmentRef = 0;
+ FragmentRef* frag_ref = 0;
- for (llvm::MCSectionData::const_iterator it = pSectionData.begin(),
+ for (SectionData::const_iterator it = pSectionData.begin(),
ie = pSectionData.end(); it != ie; ++it, ++rel) {
relocation = &(llvm::cast<Relocation>(*it));
- FragmentRef = &(relocation->targetRef());
+ frag_ref = &(relocation->targetRef());
if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) {
rel->r_offset = static_cast<Elf32_Addr>(
- llvm::cast<LDSection>(
- FragmentRef->frag()->getParent()->getSection()).addr() +
- pLayout.getOutputOffset(*FragmentRef));
+ frag_ref->frag()->getParent()->getSection().addr() +
+ pLayout.getOutputOffset(*frag_ref));
}
else {
rel->r_offset = static_cast<Elf32_Addr>(
- llvm::cast<LDSection>(
- FragmentRef->frag()->getParent()->getSection()).offset() +
- pLayout.getOutputOffset(*FragmentRef));
+ frag_ref->frag()->getParent()->getSection().offset() +
+ pLayout.getOutputOffset(*frag_ref));
}
Elf32_Word Index;
@@ -527,31 +520,29 @@
/// emitRela
void ELFWriter::emitRela(const Layout& pLayout,
const Output& pOutput,
- const llvm::MCSectionData& pSectionData,
+ const SectionData& pSectionData,
MemoryRegion& pRegion) const
{
Elf32_Rela* rel = reinterpret_cast<Elf32_Rela*>(pRegion.start());
Relocation* relocation = 0;
- MCFragmentRef* FragmentRef = 0;
+ FragmentRef* frag_ref = 0;
- for (llvm::MCSectionData::const_iterator it = pSectionData.begin(),
+ for (SectionData::const_iterator it = pSectionData.begin(),
ie = pSectionData.end(); it != ie; ++it, ++rel) {
relocation = &(llvm::cast<Relocation>(*it));
- FragmentRef = &(relocation->targetRef());
+ frag_ref = &(relocation->targetRef());
if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) {
rel->r_offset = static_cast<Elf32_Addr>(
- llvm::cast<LDSection>(
- FragmentRef->frag()->getParent()->getSection()).addr() +
- pLayout.getOutputOffset(*FragmentRef));
+ frag_ref->frag()->getParent()->getSection().addr() +
+ pLayout.getOutputOffset(*frag_ref));
}
else {
rel->r_offset = static_cast<Elf32_Addr>(
- llvm::cast<LDSection>(
- FragmentRef->frag()->getParent()->getSection()).offset() +
- pLayout.getOutputOffset(*FragmentRef));
+ frag_ref->frag()->getParent()->getSection().offset() +
+ pLayout.getOutputOffset(*frag_ref));
}
Elf32_Word Index;
diff --git a/lib/LD/EhFrame.cpp b/lib/LD/EhFrame.cpp
index 4a84b00..bc5ed1d 100644
--- a/lib/LD/EhFrame.cpp
+++ b/lib/LD/EhFrame.cpp
@@ -6,13 +6,16 @@
// 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>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/Support/MsgHandling.h>
+
using namespace mcld;
//==========================
@@ -27,7 +30,7 @@
uint64_t EhFrame::readEhFrame(Layout& pLayout,
const TargetLDBackend& pBackend,
- llvm::MCSectionData& pSD,
+ SectionData& pSD,
const Input& pInput,
LDSection& pSection,
MemoryArea& pArea)
@@ -36,7 +39,6 @@
pInput.fileOffset() + pSection.offset(), pSection.size());
// an empty .eh_frame
if (NULL == region) {
- note(diag::note_ehframe) << "an empty eh_frame";
return 0;
}
@@ -50,13 +52,12 @@
// 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";
+ debug(diag::debug_eh_unsupport) << pInput.name();
pArea.release(region);
m_fCanRecognizeAll = false;
return 0;
@@ -68,7 +69,7 @@
while (p < eh_end) {
if (eh_end - p < 4) {
- debug(diag::debug_eh_unsupport) << "CIE or FDE size smaller than 4";
+ debug(diag::debug_eh_unsupport) << pInput.name();
m_fCanRecognizeAll = false;
break;
}
@@ -79,20 +80,19 @@
// 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";
+ debug(diag::debug_eh_unsupport) << pInput.name();
m_fCanRecognizeAll = false;
}
break;
}
if (0xffffffff == len) {
- debug(diag::debug_eh_unsupport) << "64-bit eh_frame";
+ debug(diag::debug_eh_unsupport) << pInput.name();
m_fCanRecognizeAll = false;
break;
}
if (eh_end - p < 4) {
- debug(diag::debug_eh_unsupport) <<
- "CIE:ID field / FDE: CIE Pointer field";
+ debug(diag::debug_eh_unsupport) << pInput.name();
m_fCanRecognizeAll = false;
break;
}
@@ -127,6 +127,7 @@
}
if (!m_fCanRecognizeAll) {
+ debug(diag::debug_eh_unsupport) << pInput.name();
pArea.release(region);
deleteFragments(frag_list, pArea);
return 0;
@@ -156,7 +157,6 @@
// the version should be 1
if (1 != *p) {
- debug(diag::debug_eh_unsupport) << "CIE version";
return false;
}
++p;
@@ -171,17 +171,14 @@
// 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;
@@ -189,7 +186,6 @@
// 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;
}
@@ -203,21 +199,17 @@
// 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;
@@ -229,7 +221,6 @@
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;
@@ -237,12 +228,10 @@
// 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;
@@ -263,14 +252,12 @@
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;
@@ -280,7 +267,6 @@
// FDE encoding (1 byte)
case 'R':
if (cie_end - p < 1) {
- debug(diag::debug_eh_unsupport) << "augmentation string `R`";
return false;
}
fde_encoding = *p;
@@ -291,7 +277,6 @@
case llvm::dwarf::DW_EH_PE_absptr:
break;
default:
- debug(diag::debug_eh_unsupport) << "FDE encoding";
return false;
}
++p;
@@ -309,7 +294,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));
+ pFragList.push_back(static_cast<Fragment*>(entry));
return true;
}
@@ -326,7 +311,6 @@
// 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);
@@ -335,7 +319,7 @@
// 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));
+ pFragList.push_back(static_cast<Fragment*>(entry));
return true;
}
@@ -363,9 +347,9 @@
void EhFrame::deleteFragments(FragListType& pList, MemoryArea& pArea)
{
- MCRegionFragment* frag = NULL;
+ RegionFragment* frag = NULL;
for (FragListType::iterator it = pList.begin(); it != pList.end(); ++it) {
- frag = static_cast<MCRegionFragment*>(*it);
+ frag = static_cast<RegionFragment*>(*it);
pArea.release(&(frag->getRegion()));
delete *it;
}
diff --git a/lib/LD/FDE.cpp b/lib/LD/FDE.cpp
index b70f7e1..1aa196b 100644
--- a/lib/LD/FDE.cpp
+++ b/lib/LD/FDE.cpp
@@ -6,19 +6,19 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
+
#include <mcld/LD/FDE.h>
+#include <mcld/LD/EhFrame.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// FDE
-
+//===----------------------------------------------------------------------===//
FDE::FDE(MemoryRegion& pRegion, const CIE& pCIE, Offset pPCBeginOffset)
- : MCRegionFragment(pRegion), m_CIE(pCIE), m_PCBeginOffset(pPCBeginOffset) {
+ : RegionFragment(pRegion), m_CIE(pCIE), m_PCBeginOffset(pPCBeginOffset) {
}
FDE::~FDE()
{
}
-
diff --git a/lib/LD/FillFragment.cpp b/lib/LD/FillFragment.cpp
new file mode 100644
index 0000000..8f127ca
--- /dev/null
+++ b/lib/LD/FillFragment.cpp
@@ -0,0 +1,28 @@
+//===- FillFragment.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/LD/FillFragment.h>
+#include <mcld/LD/SectionData.h>
+#include <cassert>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// FillFragment
+//===----------------------------------------------------------------------===//
+FillFragment::FillFragment(int64_t pValue,
+ unsigned int pValueSize,
+ uint64_t pSize,
+ SectionData* pSD)
+ : Fragment(Fragment::Fillment, pSD), m_Value(pValue), m_ValueSize(pValueSize),
+ m_Size(pSize) {
+ assert((!m_ValueSize || (m_Size % m_ValueSize) == 0) &&
+ "Fill size must be a multiple of the value size!");
+}
+
diff --git a/lib/LD/Fragment.cpp b/lib/LD/Fragment.cpp
new file mode 100644
index 0000000..6e1e3a7
--- /dev/null
+++ b/lib/LD/Fragment.cpp
@@ -0,0 +1,34 @@
+//===- Fragment.cpp -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/LD/Fragment.h>
+
+#include <llvm/Support/DataTypes.h>
+
+#include <mcld/LD/SectionData.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Fragment
+//===----------------------------------------------------------------------===//
+Fragment::Fragment()
+ : m_Kind(Type(~0)), m_pParent(NULL), m_Offset(~uint64_t(0)), m_LayoutOrder(~(0U)) {
+}
+
+Fragment::Fragment(Type pKind, SectionData *pParent)
+ : m_Kind(pKind), m_pParent(pParent), m_Offset(~uint64_t(0)), m_LayoutOrder(~(0U)) {
+ if (NULL != m_pParent)
+ m_pParent->getFragmentList().push_back(this);
+}
+
+Fragment::~Fragment()
+{
+}
+
diff --git a/lib/LD/FragmentRef.cpp b/lib/LD/FragmentRef.cpp
new file mode 100644
index 0000000..9ae8e4d
--- /dev/null
+++ b/lib/LD/FragmentRef.cpp
@@ -0,0 +1,150 @@
+//===- FragmentRef.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/LD/FragmentRef.h>
+
+#include <cstring>
+#include <cassert>
+
+#include <llvm/Support/MathExtras.h>
+#include <llvm/Support/Casting.h>
+
+#include <mcld/LD/AlignFragment.h>
+#include <mcld/LD/FillFragment.h>
+#include <mcld/LD/RegionFragment.h>
+#include <mcld/LD/TargetFragment.h>
+#include <mcld/LD/Layout.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Helper Functions
+//===----------------------------------------------------------------------===//
+/// compunteFragmentSize - compute the specific Fragment size
+uint64_t mcld::computeFragmentSize(const Layout& pLayout,
+ const Fragment& pFrag)
+{
+ switch (pFrag.getKind()) {
+ case Fragment::Fillment:
+ return static_cast<const FillFragment&>(pFrag).getSize();
+
+ case Fragment::Alignment: {
+ uint64_t offset = pLayout.getOutputOffset(pFrag);
+ const AlignFragment& align_frag = llvm::cast<AlignFragment>(pFrag);
+ uint64_t size = llvm::OffsetToAlignment(offset, align_frag.getAlignment());
+ if (size > align_frag.getMaxBytesToEmit())
+ return 0;
+ return size;
+ }
+
+ case Fragment::Region:
+ return llvm::cast<RegionFragment>(pFrag).getRegion().size();
+
+ case Fragment::Target:
+ return llvm::cast<TargetFragment>(pFrag).getSize();
+
+ case Fragment::Relocation:
+ assert(0 && "the size of FT_Reloc fragment is handled by backend");
+ return 0;
+
+ default:
+ assert(0 && "invalid fragment kind");
+ return 0;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// FragmentRef
+//===----------------------------------------------------------------------===//
+FragmentRef::FragmentRef()
+ : m_pFragment(NULL), m_Offset(0) {
+}
+
+FragmentRef::FragmentRef(Fragment& pFrag,
+ FragmentRef::Offset pOffset)
+ : m_pFragment(&pFrag), m_Offset(pOffset) {
+}
+
+FragmentRef::~FragmentRef()
+{
+ m_pFragment = NULL;
+ m_Offset = 0;
+}
+
+FragmentRef& FragmentRef::assign(const FragmentRef& pCopy)
+{
+ m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment);
+ m_Offset = pCopy.m_Offset;
+ return *this;
+}
+
+FragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset)
+{
+ m_pFragment = &pFrag;
+ m_Offset = pOffset;
+ return *this;
+}
+
+void FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const
+{
+ // check if the offset is still in a legal range.
+ if (NULL == m_pFragment)
+ return;
+ unsigned int total_offset = m_Offset + pOffset;
+ switch(m_pFragment->getKind()) {
+ case Fragment::Region: {
+ RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment);
+ unsigned int total_length = region_frag->getRegion().size();
+ if (total_length < (total_offset+pNBytes))
+ pNBytes = total_length - total_offset;
+
+ std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes);
+ return;
+ }
+ case Fragment::Alignment:
+ case Fragment::Fillment:
+ default:
+ return;
+ }
+}
+
+FragmentRef::Address FragmentRef::deref()
+{
+ if (NULL == m_pFragment)
+ return NULL;
+ Address base = NULL;
+ switch(m_pFragment->getKind()) {
+ case Fragment::Region:
+ base = static_cast<RegionFragment*>(m_pFragment)->getRegion().getBuffer();
+ break;
+ case Fragment::Alignment:
+ case Fragment::Fillment:
+ default:
+ return NULL;
+ }
+ return base + m_Offset;
+}
+
+FragmentRef::ConstAddress FragmentRef::deref() const
+{
+ if (NULL == m_pFragment)
+ return NULL;
+ ConstAddress base = NULL;
+ switch(m_pFragment->getKind()) {
+ case Fragment::Region:
+ base = static_cast<const RegionFragment*>(m_pFragment)->getRegion().getBuffer();
+ break;
+ case Fragment::Alignment:
+ case Fragment::Fillment:
+ default:
+ return NULL;
+ }
+ return base + m_Offset;
+}
+
diff --git a/lib/LD/GNUArchiveReader.cpp b/lib/LD/GNUArchiveReader.cpp
index 0a64752..55c8c76 100644
--- a/lib/LD/GNUArchiveReader.cpp
+++ b/lib/LD/GNUArchiveReader.cpp
@@ -10,343 +10,384 @@
#include <mcld/MC/MCLDInput.h>
#include <mcld/MC/InputTree.h>
#include <mcld/LD/GNUArchiveReader.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/ELFObjectReader.h>
#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/FileHandle.h>
#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MemoryAreaFactory.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/Path.h>
#include <mcld/ADT/SizeTraits.h>
-#include <llvm/Support/system_error.h>
+#include <llvm/ADT/StringRef.h>
#include <llvm/Support/Host.h>
-#include <sstream>
-#include <string>
-#include <vector>
+#include <cstring>
#include <cstdlib>
using namespace mcld;
-typedef uint32_t elfWord;
-
-
-/// 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::SymbolTableEntry
+GNUArchiveReader::GNUArchiveReader(MCLDInfo& pLDInfo,
+ MemoryAreaFactory& pMemAreaFactory,
+ ELFObjectReader& pELFObjectReader)
+ : m_LDInfo(pLDInfo),
+ m_MemAreaFactory(pMemAreaFactory),
+ m_ELFObjectReader(pELFObjectReader)
{
- off_t fileOffset;
- std::string name;
-};
-
-
-
-/// convert string to size_t
-template<class Type>
-Type stringToType(const std::string &str)
-{
- Type n;
- std::stringstream ss(str);
- ss >> n;
- return n;
}
+GNUArchiveReader::~GNUArchiveReader()
+{
+}
-/// GNUArchiveReader Operations
-/// Public API
-bool GNUArchiveReader::isMyFormat(Input &pInput) const
+/// isMyFormat
+bool GNUArchiveReader::isMyFormat(Input& pInput) const
{
assert(pInput.hasMemArea());
+ MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
+ Archive::MAGIC_LEN);
+ const char* str = reinterpret_cast<const char*>(region->getBuffer());
- MemoryRegion *region = pInput.memArea()->request(0, ArchiveMagicSize);
- if (!region)
- llvm::report_fatal_error("can't request MemoryRegion for archive magic");
+ bool result = false;
+ assert(NULL != str);
+ if (isArchive(str) || isThinArchive(str))
+ result = true;
- const char *p_buffer = reinterpret_cast<char *> (region->getBuffer());
+ pInput.memArea()->release(region);
+ return result;
+}
- /// check archive format.
- if (memcmp(p_buffer, ArchiveMagic, ArchiveMagicSize) != 0
- && memcmp(p_buffer, ThinArchiveMagic, ArchiveMagicSize) != 0) {
- return false;
- }
+/// isArchive
+bool GNUArchiveReader::isArchive(const char* pStr) const
+{
+ return (0 == memcmp(pStr, Archive::MAGIC, Archive::MAGIC_LEN));
+}
+
+/// isThinArchive
+bool GNUArchiveReader::isThinArchive(const char* pStr) const
+{
+ return (0 == memcmp(pStr, Archive::THIN_MAGIC, Archive::MAGIC_LEN));
+}
+
+/// isThinArchive
+bool GNUArchiveReader::isThinArchive(Input& pInput) const
+{
+ assert(pInput.hasMemArea());
+ MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
+ Archive::MAGIC_LEN);
+ const char* str = reinterpret_cast<const char*>(region->getBuffer());
+
+ bool result = false;
+ assert(NULL != str);
+ if (isThinArchive(str))
+ result = true;
+
+ pInput.memArea()->release(region);
+ return result;
+}
+
+bool GNUArchiveReader::readArchive(Archive& pArchive)
+{
+ // read the symtab of the archive
+ readSymbolTable(pArchive);
+
+ // read the strtab of the archive
+ readStringTable(pArchive);
+
+ // add root archive to ArchiveMemberMap
+ pArchive.addArchiveMember(pArchive.getARFile().name(),
+ pArchive.inputs().root(),
+ &InputTree::Downward);
+
+ // include the needed members in the archive and build up the input tree
+ bool willSymResolved;
+ do {
+ willSymResolved = false;
+ for (size_t idx = 0; idx < pArchive.numOfSymbols(); ++idx) {
+ // bypass if we already decided to include this symbol or not
+ if (Archive::Symbol::Unknown != pArchive.getSymbolStatus(idx))
+ continue;
+
+ // bypass if another symbol with the same object file offset is included
+ if (pArchive.hasObjectMember(pArchive.getObjFileOffset(idx))) {
+ pArchive.setSymbolStatus(idx, Archive::Symbol::Include);
+ continue;
+ }
+
+ // check if we should include this defined symbol
+ Archive::Symbol::Status status =
+ shouldIncludeSymbol(pArchive.getSymbolName(idx));
+ if (Archive::Symbol::Unknown != status)
+ pArchive.setSymbolStatus(idx, status);
+
+ if (Archive::Symbol::Include == status) {
+ Input* cur_archive = &(pArchive.getARFile());
+ Input* member = cur_archive;
+ uint32_t file_offset = pArchive.getObjFileOffset(idx);
+ while ((member != NULL) && (Input::Object != member->type())) {
+ uint32_t nested_offset = 0;
+ // use the file offset in current archive to find out the member we
+ // want to include
+ member = readMemberHeader(pArchive,
+ *cur_archive,
+ file_offset,
+ nested_offset);
+ assert(member != NULL);
+ // bypass if we get an archive that is already in the map
+ if (Input::Archive == member->type()) {
+ cur_archive = member;
+ file_offset = nested_offset;
+ continue;
+ }
+
+ // insert a node into the subtree of current archive.
+ Archive::ArchiveMember* parent =
+ pArchive.getArchiveMember(cur_archive->name());
+
+ assert(NULL != parent);
+ pArchive.inputs().insert(parent->lastPos, *(parent->move), *member);
+
+ // move the iterator to new created node, and also adjust the
+ // direction to Afterward for next insertion in this subtree
+ parent->move->move(parent->lastPos);
+ parent->move = &InputTree::Afterward;
+
+ if (m_ELFObjectReader.isMyFormat(*member)) {
+ member->setType(Input::Object);
+ pArchive.addObjectMember(pArchive.getObjFileOffset(idx),
+ parent->lastPos);
+ m_ELFObjectReader.readObject(*member);
+ m_ELFObjectReader.readSections(*member);
+ m_ELFObjectReader.readSymbols(*member);
+ }
+ else if (isMyFormat(*member)) {
+ member->setType(Input::Archive);
+ // when adding a new archive node, set the iterator to archive
+ // itself, and set the direction to Downward
+ pArchive.addArchiveMember(member->name(),
+ parent->lastPos,
+ &InputTree::Downward);
+ cur_archive = member;
+ file_offset = nested_offset;
+ }
+ } // end of while
+ willSymResolved = true;
+ } // end of if
+ } // end of for
+ } while (willSymResolved);
+
return true;
}
-LDReader::Endian GNUArchiveReader::endian(Input& pFile) const
+/// readMemberHeader - read the header of a member in a archive file and then
+/// return the corresponding archive member (it may be an input object or
+/// another archive)
+/// @param pArchiveRoot - the archive root that holds the strtab (extended
+/// name table)
+/// @param pArchiveFile - the archive that contains the needed object
+/// @param pFileOffset - file offset of the member header in the archive
+/// @param pNestedOffset - used when we find a nested archive
+Input* GNUArchiveReader::readMemberHeader(Archive& pArchiveRoot,
+ Input& pArchiveFile,
+ uint32_t pFileOffset,
+ uint32_t& pNestedOffset)
{
- return LDReader::BigEndian;
-}
+ assert(pArchiveFile.hasMemArea());
-InputTree *GNUArchiveReader::readArchive(Input &pInput)
-{
- return setupNewArchive(pInput, 0);
-}
+ MemoryRegion* header_region =
+ pArchiveFile.memArea()->request((pArchiveFile.fileOffset() + pFileOffset),
+ sizeof(Archive::MemberHeader));
+ const Archive::MemberHeader* header =
+ reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
-/// Read Input as archive. First create a null InputTree.
-/// Then Construct Input object for corresponding member of this archive
-/// and insert the Input object into the InputTree.
-/// Finally, return the InputTree.
-InputTree *GNUArchiveReader::setupNewArchive(Input &pInput,
- size_t off)
-{
- assert(pInput.hasMemArea());
- MemoryRegion *region = pInput.memArea()->request(off, ArchiveMagicSize);
+ assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
- if (!region)
- llvm::report_fatal_error("can't request MemoryRegion for archive magic");
+ // int size = atoi(header->size);
- 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;
-
- off += ArchiveMagicSize ;
- size_t symbolTableSize = readMemberHeader(*pInput.memArea(), off, &archiveMemberName,
- NULL, extendedName);
- /// read archive symbol table
- if(archiveMemberName.empty())
- {
- readSymbolTable(*pInput.memArea(), symbolTable,
- off+sizeof(ArchiveMemberHeader), symbolTableSize);
- off = off + sizeof(ArchiveMemberHeader) + symbolTableSize;
+ // parse the member name and nested offset if any
+ std::string member_name;
+ llvm::StringRef name_field(header->name, 16);
+ if ('/' != header->name[0]) {
+ // this is an object file in an archive
+ size_t pos = name_field.find_first_of('/');
+ member_name.assign(name_field.substr(0, pos).str());
}
- else
- {
- llvm::report_fatal_error("fatal error : need symbol table\n");
- return NULL;
+ else {
+ // this is an object/archive file in a thin archive
+ size_t begin = 1;
+ size_t end = name_field.find_first_of(" :");
+ uint32_t name_offset = 0;
+ // parse the name offset
+ name_field.substr(begin, end - begin).getAsInteger(10, name_offset);
+
+ if (':' == name_field[end]) {
+ // there is a nested offset
+ begin = end + 1;
+ end = name_field.find_first_of(' ', begin);
+ name_field.substr(begin, end - begin).getAsInteger(10, pNestedOffset);
+ }
+
+ // get the member name from the extended name table
+ begin = name_offset;
+ end = pArchiveRoot.getStrTable().find_first_of('\n', begin);
+ member_name.assign(pArchiveRoot.getStrTable().substr(begin, end - begin -1));
}
- if((off&1) != 0)
- ++off;
-
- size_t extendedSize = readMemberHeader(*pInput.memArea(), off, &archiveMemberName,
- NULL, extendedName);
- /// read long Name table if exist
- if(archiveMemberName == "/")
- {
- off += sizeof(ArchiveMemberHeader);
- MemoryRegion *extended_name_region = pInput.memArea()->request(off, extendedSize);
- pFile = reinterpret_cast<char *>(extended_name_region->getBuffer());
- extendedName.assign(pFile, extendedSize);
-
+ Input* member = NULL;
+ if (!isThinArchive(pArchiveFile)) {
+ // this is an object file in an archive
+ member =
+ m_LDInfo.inputFactory().produce(member_name,
+ pArchiveFile.path(),
+ Input::Unknown,
+ (pFileOffset +
+ sizeof(Archive::MemberHeader)));
+ assert(member != NULL);
+ member->setMemArea(pArchiveFile.memArea());
+ LDContext *input_context = m_LDInfo.contextFactory().produce();
+ member->setContext(input_context);
}
+ else {
+ // this is a member in a thin archive
+ // try to find if this is a archive already in the map first
+ Archive::ArchiveMember* ar_member =
+ pArchiveRoot.getArchiveMember(member_name);
+ if (NULL != ar_member) {
+ return ar_member->file;
+ }
- /// traverse all the archive members
- InputTree::iterator node = resultTree->root();
- std::set<std::string> haveSeen;
- for(unsigned i=0 ; i<symbolTable.size() ; ++i)
- {
- /// We shall get each member at this archive.
- /// Construct a corresponding mcld::Input, and insert it into
- /// the original InputTree, resultTree.
- off_t nestedOff = 0;
-
- readMemberHeader(*pInput.memArea(), symbolTable[i].fileOffset, &archiveMemberName,
- &nestedOff, extendedName);
-
- if(haveSeen.find(archiveMemberName)==haveSeen.end())
- haveSeen.insert(archiveMemberName);
+ // get nested file path, the nested file's member name is the relative
+ // path to the archive containing it.
+ sys::fs::Path input_path(pArchiveFile.path().parent_path());
+ if (!input_path.empty())
+ input_path.append(member_name);
else
- continue;
+ input_path.assign(member_name);
+ member =
+ m_LDInfo.inputFactory().produce(member_name, input_path, Input::Unknown);
- if(!isThinArchive)
- {
- /// New a Input object and assign fileOffset in MCLDFile.
- /// Insert the object to resultTree and move ahead.
- off_t fileOffset = symbolTable[i].fileOffset + sizeof(ArchiveMemberHeader);
- Input *insertObjectFile = m_pLDInfo.inputFactory().produce(archiveMemberName,
- pInput.path(),
- MCLDFile::Object,
- fileOffset);
- resultTree->insert<InputTree::Positional>(node, *insertObjectFile);
- if(i==0)
- node.move<InputTree::Inclusive>();
- else
- node.move<InputTree::Positional>();
-
- continue;
+ assert(member != NULL);
+ MemoryArea* input_memory =
+ m_MemAreaFactory.produce(member->path(), FileHandle::ReadOnly);
+ if (input_memory->handler()->isGood()) {
+ member->setMemArea(input_memory);
}
-
- /// 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)
- {
- /// This is a member of a nested archive.
- /// Create an Input for this archive ,and recursive call setupNewArchive
- /// Finally, merge the new InputTree with the old one
- Input *newArchive = m_pLDInfo.inputFactory().produce(archiveMemberName,
- realPath,
- MCLDFile::Archive,
- 0);
-
- resultTree->insert<InputTree::Positional>(node, *newArchive);
- if(i==0)
- node.move<InputTree::Inclusive>();
- else
- node.move<InputTree::Positional>();
- InputTree *newArchiveTree = setupNewArchive(*newArchive, 0);
- resultTree->merge<InputTree::Inclusive>(node, *newArchiveTree);
- continue;
+ else {
+ error(diag::err_cannot_open_input) << member->name() << member->path();
+ return NULL;
}
- /// External member , open it as normal object file
- /// add new Input to InputTree
- Input *insertObjectFile = m_pLDInfo.inputFactory().produce(archiveMemberName,
- realPath,
- MCLDFile::Object,
- 0);
- resultTree->insert<InputTree::Positional>(node, *insertObjectFile);
- if(i==0)
- node.move<InputTree::Inclusive>();
- else
- node.move<InputTree::Positional>();
+ LDContext *input_context = m_LDInfo.contextFactory().produce(input_path);
+ member->setContext(input_context);
}
- return resultTree;
+
+ pArchiveFile.memArea()->release(header_region);
+ return member;
}
-
-/// Parse the member header and return the size of member
-/// Archive member names in System 5 style :
-///
-/// "/ " - symbol table, must be the first member
-/// "// " - long name table
-/// "filename.o/ " - regular file with short name
-/// "/5566 " - name at offset 5566 at long name table
-
-size_t GNUArchiveReader::readMemberHeader(MemoryArea &pArea,
- off_t off,
- std::string *p_Name,
- off_t *p_NestedOff,
- std::string &p_ExtendedName)
+/// readSymbolTable - read the archive symbol map (armap)
+bool GNUArchiveReader::readSymbolTable(Archive& pArchive)
{
- MemoryRegion *region = pArea.request(off, sizeof(ArchiveMemberHeader));
- const char *pFile = reinterpret_cast<char *>(region->getBuffer());
- const ArchiveMemberHeader *header = reinterpret_cast<const ArchiveMemberHeader *>(pFile);
+ assert(pArchive.getARFile().hasMemArea());
- /// check magic number of member header
- if(memcmp(header->finalMagic, HeaderFinalMagic, sizeof HeaderFinalMagic))
- {
- llvm::report_fatal_error("archive member header magic number false");
- return 0;
- }
+ MemoryRegion* header_region =
+ pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
+ Archive::MAGIC_LEN),
+ sizeof(Archive::MemberHeader));
+ const Archive::MemberHeader* header =
+ reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
+ assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
- /// evaluate member size
- std::string sizeString(header->size, sizeof(header->size)+1);
- size_t memberSize = stringToType<size_t>(sizeString);
- if(memberSize == 0)
- {
- llvm::report_fatal_error("member Size Error");
- return 0;
- }
+ int symtab_size = atoi(header->size);
+ pArchive.setSymTabSize(symtab_size);
- if(header->name[0] != '/')
- {
- /// This is a regular file with short name
- const char* nameEnd = strchr(header->name, '/');
- size_t nameLen = ((nameEnd == NULL) ? 0 : (nameEnd - header->name));
- if((nameLen <= 0) || (nameLen >= sizeof(header->name)))
- {
- llvm::report_fatal_error("header name format error\n");
- return 0;
- }
- p_Name->assign(header->name, nameLen);
+ MemoryRegion* symtab_region =
+ pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
+ Archive::MAGIC_LEN +
+ sizeof(Archive::MemberHeader)),
+ symtab_size);
+ const uint32_t* data =
+ reinterpret_cast<const uint32_t*>(symtab_region->getBuffer());
- if(!p_NestedOff)
- p_NestedOff = 0;
- }
- else if(header->name[1] == ' ')
- {
- /// This is symbol table
- if(!p_Name->empty())
- p_Name->clear();
- }
- else if(header->name[1] == '/')
- {
- /// This is long name table
- p_Name->assign(1,'/');
- }
+ // read the number of symbols
+ uint32_t number = 0;
+ if (llvm::sys::isLittleEndianHost())
+ number = bswap32(*data);
else
- {
- /// This is regular file with long name
- char *end;
- long extendedNameOff = strtol(header->name+1, &end, 10);
- long nestedOff = 0;
- if(*end == ':')
- nestedOff = strtol(end+1, &end, 10);
+ number = *data;
- if(*end != ' '
- || extendedNameOff < 0
- || static_cast<size_t>(extendedNameOff) >= p_ExtendedName.size())
- {
- llvm::report_fatal_error("extended name");
- return 0;
- }
+ // set up the pointers for file offset and name offset
+ ++data;
+ const char* name = reinterpret_cast<const char*>(data + number);
- const char *name = p_ExtendedName.data() + extendedNameOff;
- const char *nameEnd = strchr(name, '\n');
- if(nameEnd[-1] != '/'
- || static_cast<size_t>(nameEnd-name) > p_ExtendedName.size())
- {
- llvm::report_fatal_error("p_ExtendedName substring is not end with / \n");
- return 0;
- }
- p_Name->assign(name, nameEnd-name-1);
- if(p_NestedOff)
- *p_NestedOff = nestedOff;
+ // add the archive symbols
+ for (uint32_t i = 0; i < number; ++i) {
+ if (llvm::sys::isLittleEndianHost())
+ pArchive.addSymbol(name, bswap32(*data));
+ else
+ pArchive.addSymbol(name, *data);
+ name += strlen(name) + 1;
+ ++data;
}
- return memberSize;
+ pArchive.getARFile().memArea()->release(header_region);
+ pArchive.getARFile().memArea()->release(symtab_region);
+ return true;
}
-void GNUArchiveReader::readSymbolTable(MemoryArea &pArea,
- std::vector<SymbolTableEntry> &pSymbolTable,
- off_t start,
- size_t size)
+/// readStringTable - read the strtab for long file name of the archive
+bool GNUArchiveReader::readStringTable(Archive& pArchive)
{
- 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;
+ size_t offset = Archive::MAGIC_LEN +
+ sizeof(Archive::MemberHeader) +
+ pArchive.getSymTabSize();
- /// 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(llvm::sys::isLittleEndianHost())
- symbolNum = bswap32(symbolNum);
- ++p_Word;
+ if (0x0 != (offset & 1))
+ ++offset;
- const char *p_Name = reinterpret_cast<const char *>(p_Word + symbolNum);
+ assert(pArchive.getARFile().hasMemArea());
- for(unsigned int i=0 ; i<symbolNum ; ++i)
- {
- SymbolTableEntry entry;
- /// member offset
- unsigned int memberOffset = *p_Word;
- if(llvm::sys::isLittleEndianHost())
- memberOffset = bswap32(memberOffset);
- entry.fileOffset = static_cast<off_t>(memberOffset);
- ++p_Word;
- /// member name
- off_t nameEnd = strlen(p_Name) + 1;
- 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);
- }
+ MemoryRegion* header_region =
+ pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
+ offset),
+ sizeof(Archive::MemberHeader));
+ const Archive::MemberHeader* header =
+ reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
+
+ assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
+
+ int strtab_size = atoi(header->size);
+
+ MemoryRegion* strtab_region =
+ pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
+ offset +
+ sizeof(Archive::MemberHeader)),
+ strtab_size);
+ const char* strtab =
+ reinterpret_cast<const char*>(strtab_region->getBuffer());
+
+ pArchive.getStrTable().assign(strtab, strtab_size);
+
+ pArchive.getARFile().memArea()->release(header_region);
+ pArchive.getARFile().memArea()->release(strtab_region);
+ return true;
}
+
+/// shouldIncludeStatus - given a sym name from armap and check if including
+/// the corresponding archive member, and then return the decision
+enum Archive::Symbol::Status
+GNUArchiveReader::shouldIncludeSymbol(const llvm::StringRef& pSymName) const
+{
+ // TODO: handle symbol version issue and user defined symbols
+ ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pSymName);
+ if (NULL != info) {
+ if (!info->isUndef())
+ return Archive::Symbol::Exclude;
+ if (info->isWeak())
+ return Archive::Symbol::Unknown;
+ return Archive::Symbol::Include;
+ }
+ return Archive::Symbol::Unknown;
+}
+
diff --git a/lib/LD/LDSection.cpp b/lib/LD/LDSection.cpp
index 1ec9c13..2aad917 100644
--- a/lib/LD/LDSection.cpp
+++ b/lib/LD/LDSection.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/LDSection.h>
-#include <llvm/MC/SectionKind.h>
using namespace mcld;
@@ -18,8 +17,7 @@
uint64_t pSize,
uint64_t pOffset,
uint64_t pAddr)
- : llvm::MCSection(llvm::MCSection::SV_LDContext, llvm::SectionKind::getMetadata()),
- m_Name(pName),
+ : m_Name(pName),
m_Kind(pKind),
m_Type(pType),
m_Flag(pFlag),
diff --git a/lib/LD/LDSymbol.cpp b/lib/LD/LDSymbol.cpp
index f26e052..f088b5c 100644
--- a/lib/LD/LDSymbol.cpp
+++ b/lib/LD/LDSymbol.cpp
@@ -6,7 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/LD/LDSymbol.h"
+
+#include <mcld/LD/LDSymbol.h>
+
#include <cstring>
using namespace mcld;
@@ -33,7 +35,7 @@
return (*this);
}
-void LDSymbol::setFragmentRef(MCFragmentRef* pFragmentRef)
+void LDSymbol::setFragmentRef(FragmentRef* pFragmentRef)
{
m_pFragRef = pFragmentRef;
}
diff --git a/lib/LD/Layout.cpp b/lib/LD/Layout.cpp
index bc91cee..1650556 100644
--- a/lib/LD/Layout.cpp
+++ b/lib/LD/Layout.cpp
@@ -7,22 +7,29 @@
//
//===----------------------------------------------------------------------===//
-#include <llvm/ADT/Twine.h>
-#include <mcld/ADT/SizeTraits.h>
#include <mcld/LD/Layout.h>
+
+#include <cassert>
+
+#include <llvm/ADT/Twine.h>
+
+#include <mcld/ADT/SizeTraits.h>
#include <mcld/LD/LDContext.h>
#include <mcld/LD/LDFileFormat.h>
#include <mcld/LD/LDSection.h>
+#include <mcld/LD/Fragment.h>
+#include <mcld/LD/FillFragment.h>
+#include <mcld/LD/AlignFragment.h>
#include <mcld/MC/MCLinker.h>
#include <mcld/MC/MCLDInfo.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Target/TargetLDBackend.h>
-#include <cassert>
using namespace mcld;
//===----------------------------------------------------------------------===//
// Range
+//===----------------------------------------------------------------------===//
Layout::Range::Range()
: header(NULL),
prevRear(NULL) {
@@ -39,6 +46,7 @@
//===----------------------------------------------------------------------===//
// Layout
+//===----------------------------------------------------------------------===//
Layout::Layout()
: m_FragRefFactory(32) /** magic number **/ {
}
@@ -47,23 +55,25 @@
{
}
-void Layout::setFragmentLayoutOrder(llvm::MCFragment* pFrag)
+void Layout::setFragmentLayoutOrder(Fragment* pFrag)
{
if (NULL == pFrag)
return;
- // compute the most-recent fragment whose order was set.
- llvm::MCFragment* first = pFrag;
+ /// find the most-recent fragment whose order was set.
+ Fragment* first = pFrag;
while (!hasLayoutOrder(*first)) {
if (NULL == first->getPrevNode())
break;
first = first->getPrevNode();
}
- // set all layout order
- unsigned int layout_order = 0;
- llvm::MCFragment* frag_not_set = NULL;
+ /// set all layout order
+ // find the first fragment who has no order.
+ // find the last order of the fragment
+ unsigned int layout_order = 0;
+ Fragment* frag_not_set = NULL;
if (NULL == first->getPrevNode()) {
layout_order = 0;
frag_not_set = first;
@@ -73,7 +83,7 @@
frag_not_set = first->getNextNode();
}
- // set up all layout order
+ // for all fragments that has no order, set up its order
while(NULL != frag_not_set) {
frag_not_set->setLayoutOrder(layout_order);
++layout_order;
@@ -84,12 +94,13 @@
/// setFragmentLayoutOffset - set the fragment's layout offset. This function
/// also set up the layout offsets of all the fragments in the same range.
/// If the offset of the fragment was set before, return immediately.
-void Layout::setFragmentLayoutOffset(llvm::MCFragment* pFrag)
+void Layout::setFragmentLayoutOffset(Fragment* pFrag)
{
if (NULL == pFrag)
return;
- // compute the most-recent fragment whose offset was set.
- llvm::MCFragment* first = pFrag;
+
+ // find the most-recent fragment whose offset was set.
+ Fragment* first = pFrag;
while (!hasLayoutOffset(*first)) {
if (NULL == first->getPrevNode())
@@ -99,19 +110,19 @@
// set all layout order
uint64_t offset = 0;
- llvm::MCFragment* frag_not_set = NULL;
+ Fragment* frag_not_set = NULL;
if (NULL == first->getPrevNode()) {
offset = 0;
frag_not_set = first;
}
else {
- offset = first->Offset;
+ offset = first->getOffset();
offset += computeFragmentSize(*this, *first);
frag_not_set = first->getNextNode();
}
while(NULL != frag_not_set) {
- frag_not_set->Offset = offset;
+ frag_not_set->setOffset(offset);
offset += computeFragmentSize(*this, *frag_not_set);
frag_not_set = frag_not_set->getNextNode();
}
@@ -120,7 +131,8 @@
/// addInputRange
/// 1. add a new range <pInputHdr, previous rear fragment>
/// 2. compute the layout order of all previous ranges.
-void Layout::addInputRange(const llvm::MCSectionData& pSD,
+/// 2. compute the layout offset of all previous ranges.
+void Layout::addInputRange(const SectionData& pSD,
const LDSection& pInputHdr)
{
RangeList* range_list = NULL;
@@ -141,12 +153,12 @@
// set up previous rear of the range.
// FIXME: in current design, we can not add a range before finishing adding
// fragments in the previous range. If the limitation keeps, we can set
- // prevRear to the last fragment in the MCSectionData simply.
+ // prevRear to the last fragment in the SectionData simply.
//
// if the pSD's fragment list is empty, the range.prevRear keeps NULL.
if (!pSD.getFragmentList().empty()) {
range->prevRear =
- const_cast<llvm::MCFragment*>(&pSD.getFragmentList().back());
+ const_cast<Fragment*>(&pSD.getFragmentList().back());
}
// compute the layout order of the previous range.
@@ -156,24 +168,24 @@
}
}
-/// appendFragment - append the given MCFragment to the given MCSectionData,
+/// appendFragment - append the given Fragment to the given SectionData,
/// and insert a MCAlignFragment to preserve the required align constraint if
/// needed
-uint64_t Layout::appendFragment(llvm::MCFragment& pFrag,
- llvm::MCSectionData& pSD,
+uint64_t Layout::appendFragment(Fragment& pFrag,
+ SectionData& pSD,
uint32_t pAlignConstraint)
{
- // insert MCAlignFragment into MCSectionData first if needed
- llvm::MCAlignFragment* align_frag = NULL;
+ // insert MCAlignFragment into SectionData first if needed
+ AlignFragment* align_frag = NULL;
if (pAlignConstraint > 1) {
- align_frag = new llvm::MCAlignFragment(pAlignConstraint, // alignment
- 0x0, // the filled value
- 1u, // the size of filled value
- pAlignConstraint - 1, // max bytes to emit
- &pSD);
+ align_frag = new AlignFragment(pAlignConstraint, // alignment
+ 0x0, // the filled value
+ 1u, // the size of filled value
+ pAlignConstraint - 1, // max bytes to emit
+ &pSD);
}
- // append the fragment to the MCSectionData
+ // append the fragment to the SectionData
pFrag.setParent(&pSD);
pSD.getFragmentList().push_back(&pFrag);
@@ -188,30 +200,30 @@
setFragmentLayoutOffset(&pFrag);
if (NULL != align_frag)
- return pFrag.Offset - align_frag->Offset + computeFragmentSize(*this, pFrag);
+ return pFrag.getOffset() - align_frag->getOffset() + computeFragmentSize(*this, pFrag);
else
return computeFragmentSize(*this, pFrag);
}
-/// getInputLDSection - give a MCFragment, return the corresponding input
+/// getInputLDSection - give a Fragment, return the corresponding input
/// LDSection*
LDSection*
-Layout::getInputLDSection(const llvm::MCFragment& pFrag)
+Layout::getInputLDSection(const Fragment& pFrag)
{
- const llvm::MCSectionData* sect_data = pFrag.getParent();
- // check the MCSectionData
+ const SectionData* sect_data = pFrag.getParent();
+ // check the SectionData
if (NULL == sect_data) {
llvm::report_fatal_error(llvm::Twine("the fragment does not belong to") +
- llvm::Twine(" any MCSectionData.\n"));
+ llvm::Twine(" any SectionData.\n"));
}
- // check the MCSectionData's range list
+ // check the SectionData's range list
if (0 == m_SDRangeMap.count(sect_data)) {
llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
- llvm::Twine("the input's MCSectionData is not ") +
+ llvm::Twine("the input's SectionData is not ") +
llvm::Twine("registered in the Layout.\nPlease ") +
llvm::Twine("use MCLinker::getOrCreateSectData() ") +
- llvm::Twine("to get input's MCSectionData.\n"));
+ llvm::Twine("to get input's SectionData.\n"));
}
RangeList* range_list = m_SDRangeMap[sect_data];
@@ -237,25 +249,25 @@
}
}
-/// getInputLDSection - give a MCFragment, return the corresponding input
+/// getInputLDSection - give a Fragment, return the corresponding input
/// LDSection*
const LDSection*
-Layout::getInputLDSection(const llvm::MCFragment& pFrag) const
+Layout::getInputLDSection(const Fragment& pFrag) const
{
- const llvm::MCSectionData* sect_data = pFrag.getParent();
- // check the MCSectionData
+ const SectionData* sect_data = pFrag.getParent();
+ // check the SectionData
if (NULL == sect_data) {
llvm::report_fatal_error(llvm::Twine("the fragment does not belong to") +
- llvm::Twine(" any MCSectionData.\n"));
+ llvm::Twine(" any SectionData.\n"));
}
- // check the MCSectionData's range list
+ // check the SectionData's range list
if (0 == m_SDRangeMap.count(sect_data)) {
llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
- llvm::Twine("the input's MCSectionData is not ") +
+ llvm::Twine("the input's SectionData is not ") +
llvm::Twine("registered in the Layout.\nPlease ") +
llvm::Twine("use MCLinker::getOrCreateSectData() ") +
- llvm::Twine("to get input's MCSectionData.\n"));
+ llvm::Twine("to get input's SectionData.\n"));
}
SDRangeMap::const_iterator range_list_iter = m_SDRangeMap.find(sect_data);
@@ -283,37 +295,36 @@
}
/// getOutputLDSection
-LDSection* Layout::getOutputLDSection(const llvm::MCFragment& pFrag)
+LDSection* Layout::getOutputLDSection(const Fragment& pFrag)
{
- llvm::MCSectionData* sect_data = pFrag.getParent();
+ SectionData* sect_data = pFrag.getParent();
if (NULL == sect_data)
return NULL;
- return const_cast<LDSection*>(llvm::cast<LDSection>(§_data->getSection()));
+ return const_cast<LDSection*>(§_data->getSection());
}
/// getOutputLDSection
-const LDSection* Layout::getOutputLDSection(const llvm::MCFragment& pFrag) const
+const LDSection* Layout::getOutputLDSection(const Fragment& pFrag) const
{
- const llvm::MCSectionData* sect_data = pFrag.getParent();
+ const SectionData* sect_data = pFrag.getParent();
if (NULL == sect_data)
return NULL;
- return llvm::cast<LDSection>(§_data->getSection());
+ return §_data->getSection();
}
/// getFragmentRef - assume the ragne exist, find the fragment reference
-MCFragmentRef*
-Layout::getFragmentRef(Layout::Range& pRange, uint64_t pOffset)
+FragmentRef* Layout::getFragmentRef(Layout::Range& pRange, uint64_t pOffset)
{
if (isEmptyRange(pRange))
return NULL;
- llvm::MCFragment* front = getFront(pRange);
+ Fragment* front = getFront(pRange);
if (NULL == front)
return NULL;
- llvm::MCFragment* rear = getRear(pRange);
+ Fragment* rear = getRear(pRange);
if (NULL == rear)
return NULL;
@@ -323,13 +334,11 @@
// @param pFront is the first fragment in the range.
// @param pRear is the last fragment in the range.
// @pOffset is the offset started from pFront.
-MCFragmentRef*
-Layout::getFragmentRef(llvm::MCFragment& pFront,
- llvm::MCFragment& pRear,
- uint64_t pOffset)
+FragmentRef*
+Layout::getFragmentRef(Fragment& pFront, Fragment& pRear, uint64_t pOffset)
{
- llvm::MCFragment* front = &pFront;
- llvm::MCFragment* rear = &pRear;
+ Fragment* front = &pFront;
+ Fragment* rear = &pRear;
if (!hasLayoutOffset(*rear)) {
// compute layout order, offset
@@ -338,12 +347,12 @@
}
// compute the offset from overall start fragment.
- uint64_t target_offset = pFront.Offset + pOffset;
+ uint64_t target_offset = pFront.getOffset() + pOffset;
// from front to rear, find the offset which is as large as possible
// but smaller than the target_offset.
while (front != rear) {
- if (llvm::MCFragment::FT_Align == front->getKind()) {
+ if (Fragment::Alignment == front->getKind()) {
// alignment fragments were not counted in target_offset.
// Count in the size of alignment fragmen in target_offset here.
uint64_t align_size = 0x0;
@@ -355,33 +364,33 @@
else {
// If the alignment fragment is not the last fragment, the alignment
// fragment's size is the distance between the two fragment.
- align_size = front->getNextNode()->Offset - front->Offset;
+ align_size = front->getNextNode()->getOffset() - front->getOffset();
}
target_offset += align_size;
front = front->getNextNode();
continue;
}
- if (target_offset >= front->getNextNode()->Offset) {
+ if (target_offset >= front->getNextNode()->getOffset()) {
front = front->getNextNode();
}
else {
// found
- MCFragmentRef* result = m_FragRefFactory.allocate();
- new (result) MCFragmentRef(*front, target_offset - front->Offset);
+ FragmentRef* result = m_FragRefFactory.allocate();
+ new (result) FragmentRef(*front, target_offset - front->getOffset());
return result;
}
}
if (front == rear) {
- if (llvm::MCFragment::FT_Align == front->getKind())
+ if (Fragment::Alignment == front->getKind())
return NULL;
if (!isValidOffset(*front, target_offset))
return NULL;
- MCFragmentRef* result = m_FragRefFactory.allocate();
- new (result) MCFragmentRef(*front, target_offset - front->Offset);
+ FragmentRef* result = m_FragRefFactory.allocate();
+ new (result) FragmentRef(*front, target_offset - front->getOffset());
return result;
}
return NULL;
@@ -389,11 +398,11 @@
/// getFragmentRef - give a LDSection in input file and an offset, return
/// the fragment reference.
-MCFragmentRef*
+FragmentRef*
Layout::getFragmentRef(const LDSection& pInputSection, uint64_t pOffset)
{
// find out which SectionData covers the range of input section header
- const llvm::MCSectionData* sect_data = pInputSection.getSectionData();
+ const SectionData* sect_data = pInputSection.getSectionData();
// check range list
if (0 == m_SDRangeMap.count(sect_data))
@@ -428,21 +437,21 @@
/// @param pBigOffset - the offset, can be larger than the fragment, but can
/// not larger than this input section.
/// @return if found, return the fragment. Otherwise, return NULL.
-MCFragmentRef*
-Layout::getFragmentRef(const llvm::MCFragment& pFrag, uint64_t pBigOffset)
+FragmentRef*
+Layout::getFragmentRef(const Fragment& pFrag, uint64_t pBigOffset)
{
if (!hasLayoutOffset(pFrag)) {
// compute layout order, offset
- setFragmentLayoutOrder(const_cast<llvm::MCFragment*>(&pFrag));
- setFragmentLayoutOffset(const_cast<llvm::MCFragment*>(&pFrag));
+ setFragmentLayoutOrder(const_cast<Fragment*>(&pFrag));
+ setFragmentLayoutOffset(const_cast<Fragment*>(&pFrag));
}
// find out which SectionData covers the range of input section header
- const llvm::MCSectionData* sect_data = pFrag.getParent();
+ const SectionData* sect_data = pFrag.getParent();
// check range list
if (0 == m_SDRangeMap.count(sect_data)) {
- llvm::report_fatal_error(llvm::Twine("MCSectionData has no") +
+ llvm::report_fatal_error(llvm::Twine("SectionData has no") +
llvm::Twine(" correponding range list.\n"));
}
@@ -452,13 +461,13 @@
RangeList* range_list = m_SDRangeMap[sect_data];
// find out the specific part in SectionData range
- uint64_t target_offset = pBigOffset + pFrag.Offset;
+ uint64_t target_offset = pBigOffset + pFrag.getOffset();
RangeList::iterator range, rangeEnd = range_list->end();
for (range = range_list->begin(); range != rangeEnd; ++range) {
if (isEmptyRange(*range))
continue;
- if (getRear(*range)->Offset >= target_offset) {
+ if (getRear(*range)->getOffset() >= target_offset) {
break;
}
}
@@ -472,17 +481,17 @@
return getFragmentRef(*range, pBigOffset);
}
-uint64_t Layout::getOutputOffset(const llvm::MCFragment& pFrag)
+uint64_t Layout::getOutputOffset(const Fragment& pFrag)
{
if (!hasLayoutOffset(pFrag)) {
// compute layout order, offset
- setFragmentLayoutOrder(const_cast<llvm::MCFragment*>(&pFrag));
- setFragmentLayoutOffset(const_cast<llvm::MCFragment*>(&pFrag));
+ setFragmentLayoutOrder(const_cast<Fragment*>(&pFrag));
+ setFragmentLayoutOffset(const_cast<Fragment*>(&pFrag));
}
- return pFrag.Offset;
+ return pFrag.getOffset();
}
-uint64_t Layout::getOutputOffset(const llvm::MCFragment& pFrag) const
+uint64_t Layout::getOutputOffset(const Fragment& pFrag) const
{
if (!hasLayoutOffset(pFrag)) {
llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
@@ -490,15 +499,15 @@
llvm::Twine(__func__) +
llvm::Twine(" can not be used before layout().\n"));
}
- return pFrag.Offset;
+ return pFrag.getOffset();
}
-uint64_t Layout::getOutputOffset(const MCFragmentRef& pFragRef)
+uint64_t Layout::getOutputOffset(const FragmentRef& pFragRef)
{
return getOutputOffset(*(pFragRef.frag())) + pFragRef.offset();
}
-uint64_t Layout::getOutputOffset(const MCFragmentRef& pFragRef) const
+uint64_t Layout::getOutputOffset(const FragmentRef& pFragRef) const
{
return getOutputOffset(*(pFragRef.frag())) + pFragRef.offset();
}
@@ -534,6 +543,10 @@
}
}
+/// layout - layout the sections
+/// 1. finalize fragment offset
+/// 2. compute section order
+/// 3. finalize section offset
bool Layout::layout(Output& pOutput,
const TargetLDBackend& pBackend,
const MCLDInfo& pInfo)
@@ -544,6 +557,7 @@
LDContext& output_context = *pOutput.context();
LDContext::sect_iterator it, itEnd = output_context.sectEnd();
for (it = output_context.sectBegin(); it != itEnd; ++it) {
+ // calculate 1. all fragment offset, and 2. the section order
LDSection* sect = *it;
switch (sect->kind()) {
@@ -559,8 +573,7 @@
if (NULL != sect->getSectionData() &&
!sect->getSectionData()->getFragmentList().empty()) {
// make sure that all fragments are valid
- llvm::MCFragment& frag =
- sect->getSectionData()->getFragmentList().back();
+ Fragment& frag = sect->getSectionData()->getFragmentList().back();
setFragmentLayoutOrder(&frag);
setFragmentLayoutOffset(&frag);
}
@@ -604,15 +617,17 @@
// Backend defines the section start offset for section 1.
uint64_t offset = pBackend.sectionStartOffset();
- // compute the section offset and handle alignment also. And ignore section 0
- // (NULL in ELF/COFF), and MachO starts from section 1.
+
for (size_t index = 1; index < m_SectionOrder.size(); ++index) {
- // we should not preserve file space for the BSS section.
- if (LDFileFormat::BSS != m_SectionOrder[index - 1]->kind())
+ // compute the section offset and handle alignment also. And ignore section 0
+ // (NULL in ELF/COFF), and MachO starts from section 1.
+
+ if (LDFileFormat::BSS != m_SectionOrder[index - 1]->kind()) {
+ // we should not preserve file space for the BSS section.
offset += m_SectionOrder[index - 1]->size();
+ }
alignAddress(offset, m_SectionOrder[index]->align());
-
m_SectionOrder[index]->setOffset(offset);
}
@@ -627,15 +642,15 @@
return true;
}
-bool Layout::isValidOffset(const llvm::MCFragment& pFrag, uint64_t pTargetOffset) const
+bool Layout::isValidOffset(const Fragment& pFrag, uint64_t pTargetOffset) const
{
uint64_t size = computeFragmentSize(*this, pFrag);
if (0x0 == size)
- return (pTargetOffset == pFrag.Offset);
+ return (pTargetOffset == pFrag.getOffset());
if (NULL != pFrag.getNextNode())
- return (pTargetOffset >= pFrag.Offset && pTargetOffset < pFrag.getNextNode()->Offset);
+ return (pTargetOffset >= pFrag.getOffset() && pTargetOffset < pFrag.getNextNode()->getOffset());
- return (pTargetOffset >= pFrag.Offset && pTargetOffset < (pFrag.Offset + size));
+ return (pTargetOffset >= pFrag.getOffset() && pTargetOffset < (pFrag.getOffset() + size));
}
diff --git a/lib/LD/RegionFragment.cpp b/lib/LD/RegionFragment.cpp
new file mode 100644
index 0000000..7508ed5
--- /dev/null
+++ b/lib/LD/RegionFragment.cpp
@@ -0,0 +1,24 @@
+//===- RegionFragment.cpp -------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/LD/RegionFragment.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// RegionFragment
+//===----------------------------------------------------------------------===//
+RegionFragment::RegionFragment(MemoryRegion& pRegion, SectionData* pSD)
+ : Fragment(Fragment::Region, pSD), m_Region(pRegion) {
+}
+
+RegionFragment::~RegionFragment()
+{
+}
+
diff --git a/lib/LD/Relocation.cpp b/lib/LD/Relocation.cpp
index 4a901ba..0c95e06 100644
--- a/lib/LD/Relocation.cpp
+++ b/lib/LD/Relocation.cpp
@@ -6,7 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <llvm/MC/MCAssembler.h>
+
#include <mcld/LD/Relocation.h>
#include <mcld/LD/RelocationFactory.h>
#include <mcld/LD/Layout.h>
@@ -15,10 +15,10 @@
using namespace mcld;
Relocation::Relocation(Relocation::Type pType,
- MCFragmentRef* pTargetRef,
+ FragmentRef* pTargetRef,
Relocation::Address pAddend,
Relocation::DWord pTargetData)
- : MCFragment(llvm::MCFragment::FT_Reloc),
+ : Fragment(Fragment::Relocation),
m_Type(pType),
m_TargetData(pTargetData),
m_pSymInfo(NULL),
@@ -42,8 +42,7 @@
{
if (m_pSymInfo->type() == ResolveInfo::Section &&
m_pSymInfo->outSymbol()->hasFragRef()) {
- return llvm::cast<LDSection>(
- m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection()).addr();
+ return m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection().addr();
}
return m_pSymInfo->outSymbol()->value();
}
diff --git a/lib/LD/RelocationFactory.cpp b/lib/LD/RelocationFactory.cpp
index 2bcfeb3..828acb2 100644
--- a/lib/LD/RelocationFactory.cpp
+++ b/lib/LD/RelocationFactory.cpp
@@ -6,17 +6,22 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
#include <mcld/LD/RelocationFactory.h>
-#include <mcld/Target/GOT.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <llvm/Support/Host.h>
+
#include <cstring>
#include <cassert>
+#include <llvm/Support/Host.h>
+
+#include <mcld/Target/GOT.h>
+#include <mcld/Target/TargetLDBackend.h>
+
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// RelocationFactory
+//===----------------------------------------------------------------------===//
RelocationFactory::RelocationFactory(size_t pNum)
: GCFactory<Relocation, 0>(pNum),
m_pLayout(NULL) {
@@ -27,7 +32,7 @@
}
Relocation* RelocationFactory::produce(RelocationFactory::Type pType,
- MCFragmentRef& pFragRef,
+ FragmentRef& pFragRef,
Address pAddend)
{
// target_data is the place where the relocation applys to.
diff --git a/lib/LD/SectionData.cpp b/lib/LD/SectionData.cpp
new file mode 100644
index 0000000..d1858ba
--- /dev/null
+++ b/lib/LD/SectionData.cpp
@@ -0,0 +1,19 @@
+//===- SectionData.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/LDSection.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// SectionData
+//===----------------------------------------------------------------------===//
+SectionData::SectionData(const LDSection &pSection)
+ : m_pSection(&pSection), m_Alignment(1) {
+}
diff --git a/lib/LD/SectionMap.cpp b/lib/LD/SectionMap.cpp
index 9d32391..7bcd809 100644
--- a/lib/LD/SectionMap.cpp
+++ b/lib/LD/SectionMap.cpp
@@ -47,7 +47,7 @@
// TODO: handle the cases such as overriding the exist mapping and drawing
// exception from the given SECTIONS command
iterator it;
- for (it = begin(); it != end(); ++it) {
+ for (it = m_SectMap.begin(); it != m_SectMap.end(); ++it) {
if (pInput == (*it).inputSubStr)
return false;
}
@@ -131,8 +131,8 @@
bool SectionMap::initStdSectionMap()
{
for (int i = 0; i < m_StdSectionMapSize; ++i) {
- if (!push_back(m_StdSectionMap[i].from, m_StdSectionMap[i].to))
- return false;
+ struct Mapping mapping = { m_StdSectionMap[i].from, m_StdSectionMap[i].to};
+ m_SectMap.push_back(mapping);
}
return true;
}
diff --git a/lib/LD/SectionMerger.cpp b/lib/LD/SectionMerger.cpp
index f3a5b65..1817e0b 100644
--- a/lib/LD/SectionMerger.cpp
+++ b/lib/LD/SectionMerger.cpp
@@ -60,7 +60,7 @@
return section;
}
-llvm::MCSectionData* SectionMerger::getOutputSectData(const std::string& pName)
+SectionData* SectionMerger::getOutputSectData(const std::string& pName)
{
return getOutputSectHdr(pName)->getSectionData();
}
diff --git a/lib/LD/StaticResolver.cpp b/lib/LD/StaticResolver.cpp
index 09cbc11..6401262 100644
--- a/lib/LD/StaticResolver.cpp
+++ b/lib/LD/StaticResolver.cpp
@@ -103,7 +103,6 @@
}
case DUND:
case DUNDW: {
- old->override(pNew);
old->overrideVisibility(pNew);
old->setDynamic();
pOverride = false;
diff --git a/lib/MC/Android.mk b/lib/MC/Android.mk
index b184116..30ca202 100644
--- a/lib/MC/Android.mk
+++ b/lib/MC/Android.mk
@@ -5,8 +5,6 @@
ContextFactory.cpp \
InputFactory.cpp \
InputTree.cpp \
- MCBitcodeInterceptor.cpp \
- MCFragmentRef.cpp \
MCLDAttribute.cpp \
MCLDDirectory.cpp \
MCLDDriver.cpp \
@@ -16,7 +14,6 @@
MCLDOptions.cpp \
MCLDOutput.cpp \
MCLinker.cpp \
- MCRegionFragment.cpp \
SearchDirs.cpp \
SymbolCategory.cpp \
ZOption.cpp
diff --git a/lib/MC/MCBitcodeInterceptor.cpp b/lib/MC/MCBitcodeInterceptor.cpp
deleted file mode 100644
index a79c904..0000000
--- a/lib/MC/MCBitcodeInterceptor.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-//===- MCBitcodeInterceptor.cpp -------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/LD/Relocation.h>
-#include <mcld/MC/MCBitcodeInterceptor.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <llvm/MC/MCAssembler.h>
-#include <llvm/MC/MCExpr.h>
-#include <llvm/MC/MCValue.h>
-#include <llvm/MC/MCFixup.h>
-#include <llvm/MC/MCFixupKindInfo.h>
-#include <llvm/MC/MCSymbol.h>
-#include <llvm/MC/MCAsmLayout.h>
-#include <llvm/MC/MCAsmBackend.h>
-#include <llvm/MC/MCAssembler.h>
-#include <llvm/Support/raw_ostream.h>
-#include <llvm/MC/MCObjectStreamer.h>
-#include <llvm/Support/Casting.h>
-#include <llvm/Support/ELF.h>
-
-using namespace llvm;
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// non-member functions
-
-//===----------------------------------------------------------------------===//
-// MCBitcodeInterceptor
-MCBitcodeInterceptor::MCBitcodeInterceptor(MCObjectStreamer &pStreamer,
- TargetLDBackend& pBackend,
- MCLDInfo& pLDInfo)
- : MCObjectWriter(llvm::nulls(),
- pStreamer.getAssembler().getWriter().isLittleEndian()),
- m_Backend(pBackend),
- m_LDInfo(pLDInfo) {
- pStreamer.getAssembler().setWriter(*this);
-}
-
-MCBitcodeInterceptor::~MCBitcodeInterceptor()
-{
-}
-
-void MCBitcodeInterceptor::ExecutePostLayoutBinding(MCAssembler &Asm,
- const MCAsmLayout &Layout)
-{
-}
-
-
-void MCBitcodeInterceptor::RecordRelocation(const MCAssembler &Asm,
- const MCAsmLayout &Layout,
- const MCFragment *Fragment,
- const MCFixup &Fixup,
- MCValue Target,
- uint64_t &FixedValue)
-{
-}
-
-/// WriteObject - not really write out a object. Instead, load data to LDContext
-void MCBitcodeInterceptor::WriteObject(MCAssembler &Asm,
- const MCAsmLayout &Layout)
-{
-}
-
-
diff --git a/lib/MC/MCFragmentRef.cpp b/lib/MC/MCFragmentRef.cpp
deleted file mode 100644
index 69a865e..0000000
--- a/lib/MC/MCFragmentRef.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-//===- MCFragmentRef.cpp --------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <llvm/Support/MathExtras.h>
-#include <mcld/MC/MCFragmentRef.h>
-#include <mcld/MC/MCRegionFragment.h>
-#include <mcld/MC/MCTargetFragment.h>
-#include <mcld/LD/Layout.h>
-#include <cstring>
-#include <cassert>
-
-using namespace mcld;
-
-/// compunteFragmentSize - compute the specific MCFragment size
-uint64_t mcld::computeFragmentSize(const Layout& pLayout,
- const llvm::MCFragment& pFrag)
-{
- switch (pFrag.getKind()) {
- case llvm::MCFragment::FT_Data:
- return static_cast<const llvm::MCDataFragment&>(pFrag).getContents().size();
- case llvm::MCFragment::FT_Fill:
- return static_cast<const llvm::MCFillFragment&>(pFrag).getSize();
- case llvm::MCFragment::FT_Inst:
- return static_cast<const llvm::MCInstFragment&>(pFrag).getInstSize();
-
- case llvm::MCFragment::FT_LEB:
- return static_cast<const llvm::MCLEBFragment&>(pFrag).getContents().size();
-
- case llvm::MCFragment::FT_Align: {
- uint64_t offset = pLayout.getOutputOffset(pFrag);
- const llvm::MCAlignFragment& align_frag = static_cast<const llvm::MCAlignFragment&>(pFrag);
- uint64_t size = llvm::OffsetToAlignment(offset, align_frag.getAlignment());
- if (size > align_frag.getMaxBytesToEmit())
- return 0;
- return size;
- }
-
- case llvm::MCFragment::FT_Org: {
- // TODO
- assert(0 && "FT_Org: Not implemented yet");
- return 0;
- }
-
- case llvm::MCFragment::FT_Dwarf:
- return static_cast<const llvm::MCDwarfLineAddrFragment&>(pFrag).getContents().size();
- case llvm::MCFragment::FT_DwarfFrame:
- return static_cast<const llvm::MCDwarfCallFrameFragment&>(pFrag).getContents().size();
-
- case llvm::MCFragment::FT_Region:
- return static_cast<const MCRegionFragment&>(pFrag).getRegion().size();
-
- case llvm::MCFragment::FT_Target:
- return static_cast<const MCTargetFragment&>(pFrag).getSize();
-
- case llvm::MCFragment::FT_Reloc:
- assert(0 && "the size of FT_Reloc fragment is handled by backend");
- return 0;
-
- default:
- assert(0 && "invalid fragment kind");
- return 0;
- }
-}
-
-//==========================
-// MCFragmentRef
-MCFragmentRef::MCFragmentRef()
- : m_pFragment(NULL), m_Offset(0) {
-}
-
-MCFragmentRef::MCFragmentRef(llvm::MCFragment& pFrag,
- MCFragmentRef::Offset pOffset)
- : m_pFragment(&pFrag), m_Offset(pOffset) {
-}
-
-MCFragmentRef::~MCFragmentRef()
-{
- m_pFragment = NULL;
- m_Offset = 0;
-}
-
-MCFragmentRef& MCFragmentRef::assign(const MCFragmentRef& pCopy)
-{
- m_pFragment = const_cast<llvm::MCFragment*>(pCopy.m_pFragment);
- m_Offset = pCopy.m_Offset;
- return *this;
-}
-
-MCFragmentRef& MCFragmentRef::assign(llvm::MCFragment& pFrag, MCFragmentRef::Offset pOffset)
-{
- m_pFragment = &pFrag;
- m_Offset = pOffset;
- return *this;
-}
-
-void MCFragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const
-{
- // check if the offset is still in a legal range.
- if (NULL == m_pFragment)
- return;
- unsigned int total_offset = m_Offset + pOffset;
- switch(m_pFragment->getKind()) {
- case llvm::MCFragment::FT_Inst: {
- llvm::MCInstFragment* inst_frag = static_cast<llvm::MCInstFragment*>(m_pFragment);
- unsigned int total_length = inst_frag->getCode().size();
- if (total_length < (total_offset+pNBytes))
- pNBytes = total_length - total_offset;
-
- std::memcpy(pDest, (inst_frag->getCode().data()+total_offset), pNBytes);
- return;
- }
- case llvm::MCFragment::FT_Data: {
- llvm::MCDataFragment* data_frag = static_cast<llvm::MCDataFragment*>(m_pFragment);
- unsigned int total_length = data_frag->getContents().size();
- if (total_length < (total_offset+pNBytes))
- pNBytes = total_length - total_offset;
-
- std::memcpy(pDest, (data_frag->getContents().data()+total_offset), pNBytes);
- return;
- }
- case llvm::MCFragment::FT_Region: {
- MCRegionFragment* region_frag = static_cast<mcld::MCRegionFragment*>(m_pFragment);
- unsigned int total_length = region_frag->getRegion().size();
- if (total_length < (total_offset+pNBytes))
- pNBytes = total_length - total_offset;
-
- std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes);
- return;
- }
- case llvm::MCFragment::FT_Align:
- case llvm::MCFragment::FT_Fill:
- case llvm::MCFragment::FT_Org:
- case llvm::MCFragment::FT_Dwarf:
- case llvm::MCFragment::FT_DwarfFrame:
- case llvm::MCFragment::FT_LEB:
- default:
- return;
- }
-}
-
-MCFragmentRef::Address MCFragmentRef::deref()
-{
- if (NULL == m_pFragment)
- return NULL;
- Address base = NULL;
- switch(m_pFragment->getKind()) {
- case llvm::MCFragment::FT_Inst:
- base = (Address)static_cast<llvm::MCInstFragment*>(m_pFragment)->getCode().data();
- break;
- case llvm::MCFragment::FT_Data:
- base = (Address)static_cast<llvm::MCDataFragment*>(m_pFragment)->getContents().data();
- break;
- case llvm::MCFragment::FT_Region:
- base = static_cast<mcld::MCRegionFragment*>(m_pFragment)->getRegion().getBuffer();
- break;
- case llvm::MCFragment::FT_Align:
- case llvm::MCFragment::FT_Fill:
- case llvm::MCFragment::FT_Org:
- case llvm::MCFragment::FT_Dwarf:
- case llvm::MCFragment::FT_DwarfFrame:
- case llvm::MCFragment::FT_LEB:
- default:
- return NULL;
- }
- return base + m_Offset;
-}
-
-MCFragmentRef::ConstAddress MCFragmentRef::deref() const
-{
- if (NULL == m_pFragment)
- return NULL;
- ConstAddress base = NULL;
- switch(m_pFragment->getKind()) {
- case llvm::MCFragment::FT_Inst:
- base = (ConstAddress)static_cast<const llvm::MCInstFragment*>(m_pFragment)->getCode().data();
- break;
- case llvm::MCFragment::FT_Data:
- base = (ConstAddress)static_cast<const llvm::MCDataFragment*>(m_pFragment)->getContents().data();
- break;
- case llvm::MCFragment::FT_Region:
- base = static_cast<const mcld::MCRegionFragment*>(m_pFragment)->getRegion().getBuffer();
- break;
- case llvm::MCFragment::FT_Align:
- case llvm::MCFragment::FT_Fill:
- case llvm::MCFragment::FT_Org:
- case llvm::MCFragment::FT_Dwarf:
- case llvm::MCFragment::FT_DwarfFrame:
- case llvm::MCFragment::FT_LEB:
- default:
- return NULL;
- }
- return base + m_Offset;
-}
-
diff --git a/lib/MC/MCLDDriver.cpp b/lib/MC/MCLDDriver.cpp
index a86983d..a1af124 100644
--- a/lib/MC/MCLDDriver.cpp
+++ b/lib/MC/MCLDDriver.cpp
@@ -21,14 +21,18 @@
#include <mcld/Support/MemoryAreaFactory.h>
#include <mcld/Target/TargetLDBackend.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/LD/Archive.h>
using namespace llvm;
using namespace mcld;
-MCLDDriver::MCLDDriver(MCLDInfo& pLDInfo, TargetLDBackend& pLDBackend)
+MCLDDriver::MCLDDriver(MCLDInfo& pLDInfo,
+ TargetLDBackend& pLDBackend,
+ MemoryAreaFactory& pAreaFactory)
: m_LDInfo(pLDInfo),
m_LDBackend(pLDBackend),
- m_pLinker(NULL) {
+ m_pLinker(NULL),
+ m_AreaFactory(pAreaFactory) {
}
@@ -36,82 +40,6 @@
{
if (NULL != m_pLinker)
delete m_pLinker;
-
-}
-
-void MCLDDriver::normalize()
-{
- // ----- set up inputs ----- //
- InputTree::dfs_iterator input, inEnd = m_LDInfo.inputs().dfs_end();
- for (input = m_LDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
- // already got type - for example, bitcode or external OIR (object
- // intermediate representation)
- if ((*input)->type() == Input::Script ||
- (*input)->type() == Input::Object ||
- (*input)->type() == Input::DynObj ||
- (*input)->type() == Input::Archive ||
- (*input)->type() == Input::External)
- continue;
-
- // is a relocatable object file
- if (m_LDBackend.getObjectReader()->isMyFormat(**input)) {
- (*input)->setType(Input::Object);
- m_LDBackend.getObjectReader()->readObject(**input);
- }
- // is a shared object file
- else if (m_LDBackend.getDynObjReader()->isMyFormat(**input)) {
- (*input)->setType(Input::DynObj);
- m_LDBackend.getDynObjReader()->readDSO(**input);
- }
- // is an archive
- else if (m_LDBackend.getArchiveReader()->isMyFormat(*(*input))) {
- (*input)->setType(Input::Archive);
- mcld::InputTree* archive_member =
- m_LDBackend.getArchiveReader()->readArchive(**input);
- if(NULL == archive_member) {
- error(diag::err_empty_input) << (*input)->name() << (*input)->path();
- return;
- }
-
- m_LDInfo.inputs().merge<InputTree::Inclusive>(input, *archive_member);
- }
- else {
- fatal(diag::err_unrecognized_input_file) << (*input)->path()
- << m_LDInfo.triple().str();
- }
- } // end of for
-}
-
-bool MCLDDriver::linkable() const
-{
- // check we have input and output files
- if (m_LDInfo.inputs().empty()) {
- error(diag::err_no_inputs);
- return false;
- }
-
- // check all attributes are legal
- mcld::AttributeFactory::const_iterator attr, attrEnd = m_LDInfo.attrFactory().end();
- for (attr=m_LDInfo.attrFactory().begin(); attr!=attrEnd; ++attr) {
- if (!m_LDInfo.attrFactory().constraint().isLegal((**attr))) {
- return false;
- }
- }
-
- // can not mix -static with shared objects
- mcld::InputTree::const_bfs_iterator input, inEnd = m_LDInfo.inputs().bfs_end();
- for (input=m_LDInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
- if ((*input)->type() == mcld::Input::DynObj) {
- if((*input)->attribute()->isStatic()) {
- error(diag::err_mixed_shared_static_objects)
- << (*input)->name() << (*input)->path();
- return false;
- }
- }
- }
-
- // can not mix -r with shared objects
- return true;
}
/// initMCLinker - initialize MCLinker
@@ -126,7 +54,8 @@
// initialize the readers and writers
// Because constructor can not be failed, we initalize all readers and
// writers outside the MCLinker constructors.
- if (!m_LDBackend.initArchiveReader(*m_pLinker, m_LDInfo) ||
+ if (!m_LDBackend.initObjectReader(*m_pLinker) ||
+ !m_LDBackend.initArchiveReader(*m_pLinker, m_LDInfo, m_AreaFactory) ||
!m_LDBackend.initObjectReader(*m_pLinker) ||
!m_LDBackend.initDynObjReader(*m_pLinker) ||
!m_LDBackend.initObjectWriter(*m_pLinker) ||
@@ -189,18 +118,78 @@
return true;
}
-/// readSections - read all input section headers
-bool MCLDDriver::readSections()
+void MCLDDriver::normalize()
{
- // Bitcode is read by the other path. This function reads sections in object
- // files.
- mcld::InputTree::bfs_iterator input, inEnd = m_LDInfo.inputs().bfs_end();
- for (input=m_LDInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
- if ((*input)->type() == Input::Object) {
- if (!m_LDBackend.getObjectReader()->readSections(**input))
- return false;
+ // ----- set up inputs ----- //
+ InputTree::iterator input, inEnd = m_LDInfo.inputs().end();
+ for (input = m_LDInfo.inputs().begin(); input!=inEnd; ++input) {
+ // already got type - for example, bitcode or external OIR (object
+ // intermediate representation)
+ if ((*input)->type() == Input::Script ||
+ (*input)->type() == Input::Object ||
+ (*input)->type() == Input::DynObj ||
+ (*input)->type() == Input::Archive ||
+ (*input)->type() == Input::External)
+ continue;
+
+ // is a relocatable object file
+ if (m_LDBackend.getObjectReader()->isMyFormat(**input)) {
+ (*input)->setType(Input::Object);
+ m_LDBackend.getObjectReader()->readObject(**input);
+ m_LDBackend.getObjectReader()->readSections(**input);
+ m_LDBackend.getObjectReader()->readSymbols(**input);
+ }
+ // is a shared object file
+ else if (m_LDBackend.getDynObjReader()->isMyFormat(**input)) {
+ (*input)->setType(Input::DynObj);
+ m_LDBackend.getDynObjReader()->readDSO(**input);
+ m_LDBackend.getDynObjReader()->readSymbols(**input);
+ }
+ // is an archive
+ else if (m_LDBackend.getArchiveReader()->isMyFormat(**input)) {
+ (*input)->setType(Input::Archive);
+ Archive archive(**input, m_LDInfo.inputFactory());
+ m_LDBackend.getArchiveReader()->readArchive(archive);
+ if(archive.numOfObjectMember() > 0) {
+ m_LDInfo.inputs().merge<InputTree::Inclusive>(input, archive.inputs());
+ }
+ }
+ else {
+ fatal(diag::err_unrecognized_input_file) << (*input)->path()
+ << m_LDInfo.triple().str();
+ }
+ } // end of for
+}
+
+bool MCLDDriver::linkable() const
+{
+ // check we have input and output files
+ if (m_LDInfo.inputs().empty()) {
+ error(diag::err_no_inputs);
+ return false;
+ }
+
+ // check all attributes are legal
+ mcld::AttributeFactory::const_iterator attr, attrEnd = m_LDInfo.attrFactory().end();
+ for (attr=m_LDInfo.attrFactory().begin(); attr!=attrEnd; ++attr) {
+ if (!m_LDInfo.attrFactory().constraint().isLegal((**attr))) {
+ return false;
}
}
+
+ // can not mix -static with shared objects
+ mcld::InputTree::const_bfs_iterator input, inEnd = m_LDInfo.inputs().bfs_end();
+ for (input=m_LDInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
+ if ((*input)->type() == mcld::Input::DynObj) {
+ if((*input)->attribute()->isStatic()) {
+ error(diag::err_mixed_shared_static_objects)
+ << (*input)->name() << (*input)->path();
+ return false;
+ }
+ }
+ }
+
+ // can not mix -r with shared objects
return true;
}
@@ -212,26 +201,6 @@
return true;
}
-/// readSymbolTables - read symbol tables from the input files.
-/// for each input file, loads its symbol table from file.
-bool MCLDDriver::readSymbolTables()
-{
- mcld::InputTree::dfs_iterator input, inEnd = m_LDInfo.inputs().dfs_end();
- for (input=m_LDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
- switch((*input)->type()) {
- case Input::DynObj:
- if (!m_LDBackend.getDynObjReader()->readSymbols(**input))
- return false;
- break;
- case Input::Object:
- if (!m_LDBackend.getObjectReader()->readSymbols(**input))
- return false;
- break;
- }
- }
- return true;
-}
-
/// addStandardSymbols - shared object and executable files need some
/// standard symbols
/// @return if there are some input symbols with the same name to the
diff --git a/lib/MC/MCLinker.cpp b/lib/MC/MCLinker.cpp
index 7321e49..e9fb327 100644
--- a/lib/MC/MCLinker.cpp
+++ b/lib/MC/MCLinker.cpp
@@ -1,4 +1,4 @@
-//===- MCLinker.cpp -----------------------------------------------------===//
+//===- MCLinker.cpp -------------------------------------------------------===//
//
// The MCLinker Project
//
@@ -11,6 +11,10 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/MC/MCLinker.h>
+
+#include <llvm/Support/Host.h>
+#include <llvm/Support/raw_ostream.h>
+
#include <mcld/MC/MCLDInput.h>
#include <mcld/MC/MCLDInfo.h>
#include <mcld/LD/Resolver.h>
@@ -19,13 +23,13 @@
#include <mcld/LD/LDSectionFactory.h>
#include <mcld/LD/SectionMap.h>
#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/FillFragment.h>
+#include <mcld/LD/RegionFragment.h>
#include <mcld/LD/EhFrame.h>
#include <mcld/LD/EhFrameHdr.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Target/TargetLDBackend.h>
-#include <llvm/Support/Host.h>
-#include <llvm/Support/raw_ostream.h>
using namespace mcld;
@@ -50,6 +54,9 @@
delete m_pSectionMerger;
}
+//===----------------------------------------------------------------------===//
+// Symbol Operations
+//===----------------------------------------------------------------------===//
/// addSymbolFromObject - add a symbol from object file and resolve it
/// immediately
LDSymbol* MCLinker::addSymbolFromObject(const llvm::StringRef& pName,
@@ -58,7 +65,7 @@
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
- MCFragmentRef* pFragmentRef,
+ FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility)
{
@@ -165,7 +172,7 @@
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
- MCFragmentRef* pFragmentRef,
+ FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility)
{
// We merge sections when reading them. So we do not need symbols with
@@ -236,7 +243,7 @@
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
- MCFragmentRef* pFragmentRef,
+ FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility)
{
ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
@@ -306,13 +313,13 @@
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
- MCFragmentRef* pFragmentRef,
+ FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility)
{
ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
- if (NULL == info || !info->isUndef()) {
- // only undefined symbol can make a reference.
+ if (NULL == info || !(info->isUndef() || info->isDyn())) {
+ // only undefined symbol and dynamic symbol can make a reference.
return NULL;
}
@@ -357,7 +364,7 @@
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
- MCFragmentRef* pFragmentRef,
+ FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility)
{
// Result is <info, existent, override>
@@ -403,13 +410,13 @@
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
LDSymbol::ValueType pValue,
- MCFragmentRef* pFragmentRef,
+ FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility)
{
ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
- if (NULL == info || !info->isUndef()) {
- // only undefined symbol can make a reference
+ if (NULL == info || !(info->isUndef() || info->isDyn())) {
+ // only undefined symbol and dynamic symbol can make a reference.
return NULL;
}
@@ -424,6 +431,54 @@
pVisibility);
}
+bool MCLinker::finalizeSymbols()
+{
+ SymbolCategory::iterator symbol, symEnd = m_OutputSymbols.end();
+ for (symbol = m_OutputSymbols.begin(); symbol != symEnd; ++symbol) {
+
+ if ((*symbol)->resolveInfo()->isAbsolute() ||
+ (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
+ // absolute symbols or symbols with function type should have
+ // zero value
+ (*symbol)->setValue(0x0);
+ continue;
+ }
+
+ if ((*symbol)->hasFragRef()) {
+ // set the virtual address of the symbol. If the output file is
+ // relocatable object file, the section's virtual address becomes zero.
+ // And the symbol's value become section relative offset.
+ uint64_t value = getLayout().getOutputOffset(*(*symbol)->fragRef());
+ assert(NULL != (*symbol)->fragRef()->frag());
+ uint64_t addr = getLayout().getOutputLDSection(*(*symbol)->fragRef()->frag())->addr();
+ (*symbol)->setValue(value + addr);
+ continue;
+ }
+ }
+
+ // finialize target-dependent symbols
+ return m_Backend.finalizeSymbols(*this, m_LDInfo.output());
+}
+
+bool MCLinker::shouldForceLocal(const ResolveInfo& pInfo) const
+{
+ // forced local symbol matches all rules:
+ // 1. We are not doing incremental linking.
+ // 2. The symbol is with Hidden or Internal visibility.
+ // 3. The symbol should be global or weak. Otherwise, local symbol is local.
+ // 4. The symbol is defined or common
+ if (m_LDInfo.output().type() != Output::Object &&
+ (pInfo.visibility() == ResolveInfo::Hidden ||
+ pInfo.visibility() == ResolveInfo::Internal) &&
+ (pInfo.isGlobal() || pInfo.isWeak()) &&
+ (pInfo.isDefine() || pInfo.isCommon()))
+ return true;
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Section Operations
+//===----------------------------------------------------------------------===//
/// createSectHdr - create the input section header
LDSection& MCLinker::createSectHdr(const std::string& pName,
LDFileFormat::Kind pKind,
@@ -475,12 +530,12 @@
return *output_sect;
}
-/// getOrCreateSectData - get or create MCSectionData
+/// getOrCreateSectData - get or create SectionData
/// pSection is input LDSection
-llvm::MCSectionData& MCLinker::getOrCreateSectData(LDSection& pSection)
+SectionData& MCLinker::getOrCreateSectData(LDSection& pSection)
{
// if there is already a section data pointed by section, return it.
- llvm::MCSectionData* sect_data = pSection.getSectionData();
+ SectionData* sect_data = pSection.getSectionData();
if (NULL != sect_data) {
m_Layout.addInputRange(*sect_data, pSection);
return *sect_data;
@@ -500,22 +555,37 @@
return *sect_data;
}
- // if the output LDSection also has no MCSectionData, then create one.
+ // if the output LDSection also has no SectionData, then create one.
sect_data = m_LDSectDataFactory.allocate();
- new (sect_data) llvm::MCSectionData(*output_sect);
+ new (sect_data) SectionData(*output_sect);
pSection.setSectionData(sect_data);
output_sect->setSectionData(sect_data);
m_Layout.addInputRange(*sect_data, pSection);
return *sect_data;
}
+void MCLinker::initSectionMap()
+{
+ assert(m_LDInfo.output().hasContext());
+ if (NULL == m_pSectionMerger)
+ m_pSectionMerger = new SectionMerger(m_SectionMap, *m_LDInfo.output().context());
+}
+
+bool MCLinker::layout()
+{
+ return m_Layout.layout(m_LDInfo.output(), m_Backend, m_LDInfo);
+}
+
+//===----------------------------------------------------------------------===//
+// Relocation Operations
+//===----------------------------------------------------------------------===//
/// addRelocation - add a relocation entry in MCLinker (only for object file)
///
/// All symbols should be read and resolved before calling this function.
Relocation* MCLinker::addRelocation(Relocation::Type pType,
const LDSymbol& pSym,
ResolveInfo& pResolveInfo,
- MCFragmentRef& pFragmentRef,
+ FragmentRef& pFragmentRef,
const LDSection& pSection,
Relocation::Address pAddend)
{
@@ -548,7 +618,7 @@
RelocationListType::iterator relocIter, relocEnd = m_RelocationList.end();
for (relocIter = m_RelocationList.begin(); relocIter != relocEnd; ++relocIter) {
- llvm::MCFragment* frag = (llvm::MCFragment*)relocIter;
+ Fragment* frag = (Fragment*)relocIter;
static_cast<Relocation*>(frag)->apply(*m_Backend.getRelocFactory(), m_LDInfo);
}
return true;
@@ -565,7 +635,7 @@
RelocationListType::iterator relocIter, relocEnd = m_RelocationList.end();
for (relocIter = m_RelocationList.begin(); relocIter != relocEnd; ++relocIter) {
- llvm::MCFragment* frag = (llvm::MCFragment*)relocIter;
+ Fragment* frag = (Fragment*)relocIter;
Relocation* reloc = static_cast<Relocation*>(frag);
// get output file offset
@@ -600,63 +670,9 @@
m_LDInfo.output().memArea()->clear();
}
-void MCLinker::initSectionMap()
-{
- assert(m_LDInfo.output().hasContext());
- if (NULL == m_pSectionMerger)
- m_pSectionMerger = new SectionMerger(m_SectionMap, *m_LDInfo.output().context());
-}
-
-bool MCLinker::layout()
-{
- return m_Layout.layout(m_LDInfo.output(), m_Backend, m_LDInfo);
-}
-
-bool MCLinker::finalizeSymbols()
-{
- SymbolCategory::iterator symbol, symEnd = m_OutputSymbols.end();
- for (symbol = m_OutputSymbols.begin(); symbol != symEnd; ++symbol) {
-
- if ((*symbol)->resolveInfo()->isAbsolute() ||
- (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
- // absolute symbols or symbols with function type should have
- // zero value
- (*symbol)->setValue(0x0);
- continue;
- }
-
- if ((*symbol)->hasFragRef()) {
- // set the virtual address of the symbol. If the output file is
- // relocatable object file, the section's virtual address becomes zero.
- // And the symbol's value become section relative offset.
- uint64_t value = getLayout().getOutputOffset(*(*symbol)->fragRef());
- assert(NULL != (*symbol)->fragRef()->frag());
- uint64_t addr = getLayout().getOutputLDSection(*(*symbol)->fragRef()->frag())->addr();
- (*symbol)->setValue(value + addr);
- continue;
- }
- }
-
- // finialize target-dependent symbols
- return m_Backend.finalizeSymbols(*this, m_LDInfo.output());
-}
-
-bool MCLinker::shouldForceLocal(const ResolveInfo& pInfo) const
-{
- // forced local symbol matches all rules:
- // 1. We are not doing incremental linking.
- // 2. The symbol is with Hidden or Internal visibility.
- // 3. The symbol should be global or weak. Otherwise, local symbol is local.
- // 4. The symbol is defined or common
- if (m_LDInfo.output().type() != Output::Object &&
- (pInfo.visibility() == ResolveInfo::Hidden ||
- pInfo.visibility() == ResolveInfo::Internal) &&
- (pInfo.isGlobal() || pInfo.isWeak()) &&
- (pInfo.isDefine() || pInfo.isCommon()))
- return true;
- return false;
-}
-
+//===----------------------------------------------------------------------===//
+// Exception Handling Operations
+//===----------------------------------------------------------------------===//
/// addEhFrame - add an exception handling section
/// @param pSection - the input section
/// @param pArea - the memory area which pSection is within.
@@ -667,7 +683,7 @@
uint64_t size = 0;
// get the SectionData of this eh_frame
- llvm::MCSectionData& sect_data = getOrCreateSectData(pSection);
+ SectionData& sect_data = getOrCreateSectData(pSection);
// parse the eh_frame if the option --eh-frame-hdr is given
if (m_LDInfo.options().hasEhFrameHdr()) {
@@ -687,14 +703,14 @@
MemoryRegion* region = pArea.request(pInput.fileOffset() + pSection.offset(),
pSection.size());
- llvm::MCFragment* frag = NULL;
+ Fragment* frag = NULL;
if (NULL == region) {
// If the input section's size is zero, we got a NULL region.
// use a virtual fill fragment
- frag = new llvm::MCFillFragment(0x0, 0, 0);
+ frag = new FillFragment(0x0, 0, 0);
}
else
- frag = new MCRegionFragment(*region);
+ frag = new RegionFragment(*region);
size = m_Layout.appendFragment(*frag, sect_data, pSection.align());
return size;
diff --git a/lib/MC/MCRegionFragment.cpp b/lib/MC/MCRegionFragment.cpp
deleted file mode 100644
index 59b109a..0000000
--- a/lib/MC/MCRegionFragment.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- MCRegionFragment.cpp - MCRegionFragment implementation -------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mcld/MC/MCRegionFragment.h"
-
-using namespace mcld;
-using namespace llvm;
-
-//==========================
-// MCRegionFragment
-MCRegionFragment::MCRegionFragment(MemoryRegion& pRegion, MCSectionData* pSD)
- : MCFragment((llvm::MCFragment::FragmentType)FT_Region, pSD), m_Region(pRegion) {
-}
-
-MCRegionFragment::~MCRegionFragment()
-{
-}
-
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index cc15e37..891b2bb 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -16,9 +16,9 @@
using namespace mcld;
-//--------------------------------------------------
+//===----------------------------------------------------------------------===//
// parser<mcld::sys::fs::Path>
-//
+//===----------------------------------------------------------------------===//
bool parser<mcld::sys::fs::Path>::parse(llvm::cl::Option &O,
llvm::StringRef ArgName,
llvm::StringRef Arg,
@@ -52,9 +52,9 @@
// do nothing
}
-//--------------------------------------------------
+//===----------------------------------------------------------------------===//
// parser<mcld::MCLDDirectory>
-//
+//===----------------------------------------------------------------------===//
bool parser<mcld::MCLDDirectory>::parse(llvm::cl::Option &O,
llvm::StringRef ArgName,
llvm::StringRef Arg,
@@ -86,9 +86,9 @@
// do nothing
}
-//--------------------------------------------------
+//===----------------------------------------------------------------------===//
// parser<mcld::ZOption>
-//
+//===----------------------------------------------------------------------===//
bool parser<mcld::ZOption>::parse(llvm::cl::Option &O,
llvm::StringRef ArgName,
llvm::StringRef Arg,
diff --git a/lib/Support/FileHandle.cpp b/lib/Support/FileHandle.cpp
index f6b898c..6d43a4c 100644
--- a/lib/Support/FileHandle.cpp
+++ b/lib/Support/FileHandle.cpp
@@ -219,9 +219,6 @@
return true;
}
-#include <iostream>
-using namespace std;
-
bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength)
{
if (!isOpened()) {
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index e35132f..7f516f6 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -140,6 +140,14 @@
m_PathName.erase(begin+1,pSepPos-begin-1);
}
+Path Path::parent_path() const
+{
+ size_t end_pos = m_PathName.find_last_of(separator);
+ if (end_pos != StringType::npos)
+ return Path(m_PathName.substr(0, end_pos));
+ return Path();
+}
+
Path Path::stem() const
{
size_t begin_pos = m_PathName.find_last_of(separator)+1;
diff --git a/lib/Support/Unix/System.inc b/lib/Support/Unix/System.inc
index 716aaa2..a7ec15f 100644
--- a/lib/Support/Unix/System.inc
+++ b/lib/Support/Unix/System.inc
@@ -6,7 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <string>
+#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -16,7 +16,7 @@
char *strerror(int errnum)
{
- return ::strerror(errnum);
+ return std::strerror(errnum);
}
} // namespace of sys
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
index af37768..200bcb5 100644
--- a/lib/Target/ARM/ARMGOT.cpp
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -7,10 +7,14 @@
//
//===----------------------------------------------------------------------===//
#include "ARMGOT.h"
+
+#include <new>
+
+#include <llvm/Support/Casting.h>
+
#include <mcld/LD/LDFileFormat.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
-#include <new>
namespace {
const size_t ARMGOTEntrySize = 4;
@@ -20,7 +24,7 @@
//===----------------------------------------------------------------------===//
// ARMGOT
-ARMGOT::ARMGOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+ARMGOT::ARMGOT(LDSection& pSection, SectionData& pSectionData)
: GOT(pSection, pSectionData, ARMGOTEntrySize),
m_NormalGOTIterator(), m_GOTPLTIterator(),
m_GOTPLTBegin(), m_GOTPLTEnd()
@@ -33,7 +37,7 @@
&m_SectionData);
if (!Entry)
- fatal(diag::fail_allocate_memory) << "GOT0";
+ fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
}
@@ -66,7 +70,7 @@
&m_SectionData);
if (!Entry)
- fatal(diag::fail_allocate_memory) << "GOTEntry";
+ fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
}
@@ -79,7 +83,7 @@
got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
if (!got_entry)
- fatal(diag::fail_allocate_memory) << "GOTEntry";
+ fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + getEntrySize());
diff --git a/lib/Target/ARM/ARMGOT.h b/lib/Target/ARM/ARMGOT.h
index 90f0f53..13d3424 100644
--- a/lib/Target/ARM/ARMGOT.h
+++ b/lib/Target/ARM/ARMGOT.h
@@ -12,7 +12,10 @@
#include <gtest.h>
#endif
+#include <llvm/ADT/DenseMap.h>
+
#include <mcld/Target/GOT.h>
+#include <mcld/LD/SectionData.h>
namespace mcld
{
@@ -27,15 +30,15 @@
typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
public:
- typedef llvm::MCSectionData::iterator iterator;
- typedef llvm::MCSectionData::const_iterator const_iterator;
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
enum {
ARMGOT0Num = 3
};
public:
- ARMGOT(LDSection &pSection, llvm::MCSectionData& pSectionData);
+ ARMGOT(LDSection &pSection, SectionData& pSectionData);
~ARMGOT();
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index 81915c9..a44f1da 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -6,28 +6,34 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <llvm/ADT/Triple.h>
-#include <llvm/ADT/Twine.h>
-#include <llvm/Support/ELF.h>
-
-#include <mcld/LD/SectionMap.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCRegionFragment.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/TargetRegistry.h>
-
-#include <cstring>
-
#include "ARM.h"
#include "ARMELFDynamic.h"
#include "ARMLDBackend.h"
#include "ARMRelocationFactory.h"
+#include <cstring>
+
+#include <llvm/ADT/Triple.h>
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/Casting.h>
+
+#include <mcld/LD/SectionMap.h>
+#include <mcld/LD/FillFragment.h>
+#include <mcld/LD/AlignFragment.h>
+#include <mcld/LD/RegionFragment.h>
+#include <mcld/MC/MCLDInfo.h>
+#include <mcld/MC/MCLDOutput.h>
+#include <mcld/MC/MCLinker.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/TargetRegistry.h>
+
using namespace mcld;
+//===----------------------------------------------------------------------===//
+// ARMGNULDBackend
+//===----------------------------------------------------------------------===//
ARMGNULDBackend::ARMGNULDBackend()
: m_pRelocFactory(NULL),
m_pGOT(NULL),
@@ -176,7 +182,7 @@
void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput)
{
- // get .got LDSection and create MCSectionData
+ // get .got LDSection and create SectionData
ELFFileFormat* file_format = getOutputFormat(pOutput);
LDSection& got = file_format->getGOT();
@@ -218,11 +224,11 @@
// get .plt and .rel.plt LDSection
LDSection& plt = file_format->getPLT();
LDSection& relplt = file_format->getRelPlt();
- // create MCSectionData and ARMPLT
+ // create SectionData and ARMPLT
m_pPLT = new ARMPLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT);
// set info of .rel.plt to .plt
relplt.setLink(&plt);
- // create MCSectionData and ARMRelDynSection
+ // create SectionData and ARMRelDynSection
m_pRelPLT = new OutputRelocSection(relplt,
pLinker.getOrCreateSectData(relplt),
8);
@@ -233,9 +239,9 @@
{
ELFFileFormat* file_format = getOutputFormat(pOutput);
- // get .rel.dyn LDSection and create MCSectionData
+ // get .rel.dyn LDSection and create SectionData
LDSection& reldyn = file_format->getRelDyn();
- // create MCSectionData and ARMRelDynSection
+ // create SectionData and ARMRelDynSection
m_pRelDyn = new OutputRelocSection(reldyn,
pLinker.getOrCreateSectData(reldyn),
8);
@@ -274,9 +280,9 @@
llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
}
- // get or create corresponding BSS MCSectionData
+ // get or create corresponding BSS SectionData
assert(NULL != bss_sect_hdr);
- llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(
+ SectionData& bss_section = pLinker.getOrCreateSectData(
*bss_sect_hdr);
// Determine the alignment by the symbol value
@@ -284,7 +290,7 @@
uint32_t addralign = bitclass() / 8;
// allocate space in BSS for the copy symbol
- llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, pSym.size());
+ Fragment* frag = new FillFragment(0x0, 1, pSym.size());
uint64_t size = pLinker.getLayout().appendFragment(*frag,
bss_section,
addralign);
@@ -763,22 +769,21 @@
&pSection == m_pEXTAB) {
// FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
// directly from the input file.
- const llvm::MCSectionData* sect_data = pSection.getSectionData();
- llvm::MCSectionData::const_iterator frag_iter, frag_end = sect_data->end();
+ const SectionData* sect_data = pSection.getSectionData();
+ SectionData::const_iterator frag_iter, frag_end = sect_data->end();
uint8_t* out_offset = pRegion.start();
for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
size_t size = computeFragmentSize(pLayout, *frag_iter);
switch(frag_iter->getKind()) {
- case llvm::MCFragment::FT_Region: {
- const MCRegionFragment& region_frag =
- llvm::cast<MCRegionFragment>(*frag_iter);
+ case Fragment::Region: {
+ const RegionFragment& region_frag =
+ llvm::cast<RegionFragment>(*frag_iter);
const uint8_t* start = region_frag.getRegion().start();
memcpy(out_offset, start, size);
break;
}
- case llvm::MCFragment::FT_Align: {
- llvm::MCAlignFragment& align_frag =
- llvm::cast<llvm::MCAlignFragment>(*frag_iter);
+ case Fragment::Alignment: {
+ AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
uint64_t count = size / align_frag.getValueSize();
switch (align_frag.getValueSize()) {
case 1u:
@@ -844,16 +849,16 @@
MemoryRegion* region = pInput.memArea()->request(
pInput.fileOffset() + pInputSectHdr.offset(), pInputSectHdr.size());
- llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
+ SectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
- llvm::MCFragment* frag = NULL;
+ Fragment* frag = NULL;
if (NULL == region) {
// If the input section's size is zero, we got a NULL region.
// use a virtual fill fragment
- frag = new llvm::MCFillFragment(0x0, 0, 0);
+ frag = new FillFragment(0x0, 0, 0);
}
else
- frag = new MCRegionFragment(*region);
+ frag = new RegionFragment(*region);
uint64_t size = pLinker.getLayout().appendFragment(*frag,
sect_data,
diff --git a/lib/Target/ARM/ARMLDBackend.h b/lib/Target/ARM/ARMLDBackend.h
index 3e46cd7..981228e 100644
--- a/lib/Target/ARM/ARMLDBackend.h
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -155,7 +155,7 @@
/// call back target backend to emit the data.
///
/// Backends handle the target-special tables (plt, gp,...) by themselves.
- /// Backend can put the data of the tables in MCSectionData directly
+ /// Backend can put the data of the tables in SectionData directly
/// - LDSection.getSectionData can get the section data.
/// Or, backend can put the data into special data structure
/// - backend can maintain its own map<LDSection, table> to get the table
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
index 015d767..c9bc333 100644
--- a/lib/Target/ARM/ARMPLT.cpp
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -8,10 +8,13 @@
//===----------------------------------------------------------------------===//
#include "ARMGOT.h"
#include "ARMPLT.h"
-#include <llvm/Support/raw_ostream.h>
+
+#include <new>
+
+#include <llvm/Support/Casting.h>
+
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
-#include <new>
namespace {
@@ -33,17 +36,17 @@
using namespace mcld;
-ARMPLT0::ARMPLT0(llvm::MCSectionData* pParent)
+ARMPLT0::ARMPLT0(SectionData* pParent)
: PLTEntry(sizeof(arm_plt0), pParent) {}
-ARMPLT1::ARMPLT1(llvm::MCSectionData* pParent)
+ARMPLT1::ARMPLT1(SectionData* pParent)
: PLTEntry(sizeof(arm_plt1), pParent) {}
//===----------------------------------------------------------------------===//
// ARMPLT
ARMPLT::ARMPLT(LDSection& pSection,
- llvm::MCSectionData& pSectionData,
+ SectionData& pSectionData,
ARMGOT &pGOTPLT)
: PLT(pSection, pSectionData), m_GOT(pGOTPLT), m_PLTEntryIterator() {
ARMPLT0* plt0_entry = new ARMPLT0(&m_SectionData);
@@ -65,7 +68,7 @@
plt1_entry = new (std::nothrow) ARMPLT1(&m_SectionData);
if (!plt1_entry)
- fatal(diag::fail_allocate_memory) << "ARMPLT1";
+ fatal(diag::fail_allocate_memory_plt);
m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
@@ -166,7 +169,7 @@
data = static_cast<uint32_t*>(malloc(plt0->getEntrySize()));
if (!data)
- fatal(diag::fail_allocate_memory) << "plt0";
+ fatal(diag::fail_allocate_memory_plt);
memcpy(data, arm_plt0, plt0->getEntrySize());
data[4] = offset;
@@ -203,7 +206,7 @@
Out = static_cast<uint32_t*>(malloc(plt1->getEntrySize()));
if (!Out)
- fatal(diag::fail_allocate_memory) << "plt1";
+ fatal(diag::fail_allocate_memory_plt);
// Offset is the distance between the last PLT entry and the associated
// GOT entry.
diff --git a/lib/Target/ARM/ARMPLT.h b/lib/Target/ARM/ARMPLT.h
index f55aaa3..db36563 100644
--- a/lib/Target/ARM/ARMPLT.h
+++ b/lib/Target/ARM/ARMPLT.h
@@ -9,6 +9,7 @@
#ifndef MCLD_ARM_PLT_H
#define MCLD_ARM_PLT_H
+#include <mcld/LD/SectionData.h>
#include <mcld/Target/PLT.h>
namespace mcld {
@@ -19,12 +20,12 @@
class ARMPLT0 : public PLTEntry {
public:
- ARMPLT0(llvm::MCSectionData* pParent);
+ ARMPLT0(SectionData* pParent);
};
class ARMPLT1 : public PLTEntry {
public:
- ARMPLT1(llvm::MCSectionData* pParent);
+ ARMPLT1(SectionData* pParent);
};
/** \class ARMPLT
@@ -35,13 +36,11 @@
typedef llvm::DenseMap<const ResolveInfo*, ARMPLT1*> SymbolIndexType;
public:
- typedef llvm::MCSectionData::iterator iterator;
- typedef llvm::MCSectionData::const_iterator const_iterator;
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
public:
- ARMPLT(LDSection& pSection,
- llvm::MCSectionData& pSectionData,
- ARMGOT& pGOTPLT);
+ ARMPLT(LDSection& pSection, SectionData& pSectionData, ARMGOT& pGOTPLT);
~ARMPLT();
// Override virtual function.
diff --git a/lib/Target/ARM/ARMRelocationFactory.cpp b/lib/Target/ARM/ARMRelocationFactory.cpp
index 3d4b0dc..cc561db 100644
--- a/lib/Target/ARM/ARMRelocationFactory.cpp
+++ b/lib/Target/ARM/ARMRelocationFactory.cpp
@@ -169,7 +169,7 @@
rel_entry.targetRef().assign(got_entry);
}
else {
- fatal(diag::reserve_entry_number_mismatch) << "GOT";
+ fatal(diag::reserve_entry_number_mismatch_got);
}
}
return got_entry;
@@ -216,7 +216,7 @@
rel_entry.setSymInfo(rsym);
}
else {
- fatal(diag::reserve_entry_number_mismatch) << "PLT";
+ fatal(diag::reserve_entry_number_mismatch_plt);
}
}
return plt_entry;
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
index 69d0927..f81133f 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -6,27 +6,34 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <llvm/Support/ELF.h>
-#include <mcld/ADT/SizeTraits.h>
+
#include <mcld/Target/GNULDBackend.h>
+
+#include <string>
+#include <cstring>
+#include <cassert>
+
+#include <llvm/Support/ELF.h>
+
+#include <mcld/ADT/SizeTraits.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/Layout.h>
+#include <mcld/LD/FillFragment.h>
#include <mcld/MC/MCLDInfo.h>
#include <mcld/MC/MCLDOutput.h>
#include <mcld/MC/InputTree.h>
#include <mcld/MC/SymbolCategory.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/MC/MCLinker.h>
#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
-#include <mcld/MC/MCLinker.h>
-#include <string>
-#include <cstring>
-#include <cassert>
+#include <mcld/Support/MemoryAreaFactory.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
// GNULDBackend
+//===----------------------------------------------------------------------===//
GNULDBackend::GNULDBackend()
: m_pArchiveReader(NULL),
m_pObjectReader(NULL),
@@ -97,10 +104,16 @@
return defaultTextSegmentAddr();
}
-bool GNULDBackend::initArchiveReader(MCLinker&, MCLDInfo &pInfo)
+bool GNULDBackend::initArchiveReader(MCLinker& pLinker,
+ MCLDInfo& pInfo,
+ MemoryAreaFactory& pMemAreaFactory)
{
- if (NULL == m_pArchiveReader)
- m_pArchiveReader = new GNUArchiveReader(pInfo);
+ if (NULL == m_pArchiveReader) {
+ assert(NULL != m_pObjectReader);
+ m_pArchiveReader = new GNUArchiveReader(pInfo,
+ pMemAreaFactory,
+ *m_pObjectReader);
+ }
return true;
}
@@ -164,7 +177,7 @@
// ----- section symbols ----- //
// .preinit_array
- MCFragmentRef* preinit_array = NULL;
+ FragmentRef* preinit_array = NULL;
if (file_format->hasPreInitArray()) {
preinit_array = pLinker.getLayout().getFragmentRef(
*(file_format->getPreInitArray().getSectionData()->begin()),
@@ -194,7 +207,7 @@
ResolveInfo::Hidden);
// .init_array
- MCFragmentRef* init_array = NULL;
+ FragmentRef* init_array = NULL;
if (file_format->hasInitArray()) {
init_array = pLinker.getLayout().getFragmentRef(
*(file_format->getInitArray().getSectionData()->begin()),
@@ -225,7 +238,7 @@
ResolveInfo::Hidden);
// .fini_array
- MCFragmentRef* fini_array = NULL;
+ FragmentRef* fini_array = NULL;
if (file_format->hasFiniArray()) {
fini_array = pLinker.getLayout().getFragmentRef(
*(file_format->getFiniArray().getSectionData()->begin()),
@@ -256,7 +269,7 @@
ResolveInfo::Hidden);
// .stack
- MCFragmentRef* stack = NULL;
+ FragmentRef* stack = NULL;
if (file_format->hasStack()) {
stack = pLinker.getLayout().getFragmentRef(
*(file_format->getStack().getSectionData()->begin()),
@@ -1283,9 +1296,9 @@
assert(NULL != bss_sect && NULL !=tbss_sect);
- // get or create corresponding BSS MCSectionData
- llvm::MCSectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
- llvm::MCSectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
+ // get or create corresponding BSS SectionData
+ SectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
+ SectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
// remember original BSS size
uint64_t bss_offset = bss_sect->size();
@@ -1302,8 +1315,8 @@
// when emitting the regular name pools. We must change the symbols'
// description here.
(*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
- llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
- (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+ Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
+ (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
// allocate TLS common symbol in tbss section
@@ -1328,8 +1341,8 @@
// when emitting the regular name pools. We must change the symbols'
// description here.
(*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
- llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
- (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+ Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
+ (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
// allocate TLS common symbol in tbss section
@@ -1366,33 +1379,38 @@
interp_seg->addSection(&file_format->getInterp());
}
+ // FIXME: Should we consider -z relro here?
if (pInfo.options().hasRelro()) {
// if -z relro is given, we need to adjust sections' offset again, and let
// PT_GNU_RELRO end on a common page boundary
LDContext::SectionTable& sect_table = pOutput.context()->getSectionTable();
- size_t idx = 0;
- while (idx < pOutput.context()->numOfSections()) {
- // find the first non-relro section, and align its offset to a page
- // boundary
+
+ size_t idx;
+ for (idx = 0; idx < pOutput.context()->numOfSections(); ++idx) {
+ // find the first non-relro section
if (getSectionOrder(pOutput, *sect_table[idx], pInfo) > SHO_RELRO_LAST) {
- uint64_t offset = sect_table[idx]->offset();
- alignAddress(offset, commonPageSize(pInfo));
- sect_table[idx]->setOffset(offset);
- ++idx;
break;
}
- ++idx;
}
- while (idx < pOutput.context()->numOfSections()) {
- // adjust the remaining sections' offset
- uint64_t offset = sect_table[idx - 1]->offset();
- if (LDFileFormat::BSS != sect_table[idx - 1]->kind())
- offset += sect_table[idx - 1]->size();
+
+ // align the first non-relro section to page boundary
+ uint64_t offset = sect_table[idx]->offset();
+ alignAddress(offset, commonPageSize(pInfo));
+ sect_table[idx]->setOffset(offset);
+
+ // set up remaining section's offset
+ for (++idx; idx < pOutput.context()->numOfSections(); ++idx) {
+ uint64_t offset;
+ size_t prev_idx = idx - 1;
+ if (LDFileFormat::BSS == sect_table[prev_idx]->kind())
+ offset = sect_table[prev_idx]->offset();
+ else
+ offset = sect_table[prev_idx]->offset() + sect_table[prev_idx]->size();
+
alignAddress(offset, sect_table[idx]->align());
sect_table[idx]->setOffset(offset);
- ++idx;
}
- }
+ } // relro
uint32_t cur_seg_flag, prev_seg_flag = getSegmentFlag(0);
uint64_t padding = 0;
@@ -1411,7 +1429,7 @@
LDFileFormat::Null == (*sect)->kind()) {
// create new PT_LOAD segment
load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD);
- load_seg->setAlign(commonPageSize(pInfo));
+ load_seg->setAlign(abiPageSize(pInfo));
// check if this segment needs padding
padding = 0;
@@ -1585,7 +1603,7 @@
}
}
-/// postLayout -Backend can do any needed modification after layout
+/// postLayout - Backend can do any needed modification after layout
void GNULDBackend::postLayout(const Output& pOutput,
const MCLDInfo& pInfo,
MCLinker& pLinker)
diff --git a/lib/Target/GOT.cpp b/lib/Target/GOT.cpp
index a05b574..f9e7b91 100644
--- a/lib/Target/GOT.cpp
+++ b/lib/Target/GOT.cpp
@@ -6,7 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
#include <mcld/Target/GOT.h>
+
#include <cstring>
#include <cstdlib>
@@ -14,9 +16,9 @@
//===----------------------------------------------------------------------===//
// GOTEntry
-GOTEntry::GOTEntry(uint64_t pContent, size_t pEntrySize,
- llvm::MCSectionData* pParent)
- : MCTargetFragment(llvm::MCFragment::FT_Target, pParent),
+//===----------------------------------------------------------------------===//
+GOTEntry::GOTEntry(uint64_t pContent, size_t pEntrySize, SectionData* pParent)
+ : TargetFragment(Fragment::Target, pParent),
f_Content(pContent), m_EntrySize(pEntrySize) {
}
@@ -26,8 +28,9 @@
//===----------------------------------------------------------------------===//
// GOT
+//===----------------------------------------------------------------------===//
GOT::GOT(LDSection& pSection,
- llvm::MCSectionData& pSectionData,
+ SectionData& pSectionData,
size_t pEntrySize)
: m_Section(pSection),
m_SectionData(pSectionData),
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
index 57e5c70..42ef972 100644
--- a/lib/Target/Mips/MipsGOT.cpp
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -7,10 +7,13 @@
//
//===----------------------------------------------------------------------===//
+#include "MipsGOT.h"
+
+#include <llvm/Support/Casting.h>
+
#include <mcld/LD/ResolveInfo.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
-#include "MipsGOT.h"
namespace {
const size_t MipsGOTEntrySize = 4;
@@ -21,7 +24,7 @@
//===----------------------------------------------------------------------===//
// MipsGOT
-MipsGOT::MipsGOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+MipsGOT::MipsGOT(LDSection& pSection, SectionData& pSectionData)
: GOT(pSection, pSectionData, MipsGOTEntrySize),
m_pLocalNum(0)
{
@@ -31,7 +34,7 @@
new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
if (NULL == entry)
- fatal(diag::fail_allocate_memory) << "GOT0";
+ fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
}
@@ -94,7 +97,7 @@
new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
if (NULL == entry)
- fatal(diag::fail_allocate_memory) << "GOTEntry";
+ fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
}
diff --git a/lib/Target/Mips/MipsGOT.h b/lib/Target/Mips/MipsGOT.h
index 2f04ef4..23a3ded 100644
--- a/lib/Target/Mips/MipsGOT.h
+++ b/lib/Target/Mips/MipsGOT.h
@@ -12,7 +12,10 @@
#include <gtest.h>
#endif
+#include <llvm/ADT/DenseMap.h>
+
#include <mcld/Target/GOT.h>
+#include <mcld/LD/SectionData.h>
namespace mcld
{
@@ -29,11 +32,11 @@
typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolTypeMapType;
public:
- typedef llvm::MCSectionData::iterator iterator;
- typedef llvm::MCSectionData::const_iterator const_iterator;
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
public:
- MipsGOT(LDSection& pSection, llvm::MCSectionData& pSectionData);
+ MipsGOT(LDSection& pSection, SectionData& pSectionData);
iterator begin();
iterator end();
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
index 87e43b8..e8b68ea 100644
--- a/lib/Target/Mips/MipsLDBackend.cpp
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -7,9 +7,15 @@
//
//===----------------------------------------------------------------------===//
+#include "Mips.h"
+#include "MipsELFDynamic.h"
+#include "MipsLDBackend.h"
+#include "MipsRelocationFactory.h"
+
#include <llvm/ADT/Triple.h>
#include <llvm/Support/ELF.h>
+#include <mcld/LD/FillFragment.h>
#include <mcld/LD/SectionMap.h>
#include <mcld/MC/MCLDInfo.h>
#include <mcld/MC/MCLinker.h>
@@ -18,11 +24,6 @@
#include <mcld/Support/TargetRegistry.h>
#include <mcld/Target/OutputRelocSection.h>
-#include "Mips.h"
-#include "MipsELFDynamic.h"
-#include "MipsLDBackend.h"
-#include "MipsRelocationFactory.h"
-
enum {
// The original o32 abi.
E_MIPS_ABI_O32 = 0x00001000,
@@ -67,21 +68,6 @@
void MipsGNULDBackend::initTargetSections(MCLinker& pLinker)
{
- // Set up .dynamic
- ELFFileFormat* file_format = NULL;
- switch(pLinker.getLDInfo().output().type()) {
- case Output::DynObj:
- file_format = getDynObjFileFormat();
- break;
- case Output::Exec:
- file_format = getExecFileFormat();
- break;
- case Output::Object:
- default:
- // TODO: not support yet
- return;
- }
- file_format->getDynamic().setFlag(llvm::ELF::SHF_ALLOC);
}
void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
@@ -213,6 +199,14 @@
return 0x80000;
}
+uint64_t MipsGNULDBackend::abiPageSize(const MCLDInfo& pInfo) const
+{
+ if (pInfo.options().maxPageSize() > 0)
+ return pInfo.options().maxPageSize();
+ else
+ return static_cast<uint64_t>(0x10000);
+}
+
void MipsGNULDBackend::doPreLayout(const Output& pOutput,
const MCLDInfo& pInfo,
MCLinker& pLinker)
@@ -498,7 +492,8 @@
/// finalizeSymbol - finalize the symbol value
bool MipsGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
{
- m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
+ if (NULL != m_pGpDispSymbol)
+ m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
return true;
}
@@ -550,9 +545,9 @@
assert(NULL != bss_sect && NULL != tbss_sect);
- // get or create corresponding BSS MCSectionData
- llvm::MCSectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
- llvm::MCSectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
+ // get or create corresponding BSS SectionData
+ SectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
+ SectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
// remember original BSS size
uint64_t bss_offset = bss_sect->size();
@@ -569,8 +564,8 @@
// when emitting the regular name pools. We must change the symbols'
// description here.
(*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
- llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
- (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+ Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
+ (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
// allocate TLS common symbol in tbss section
@@ -596,8 +591,8 @@
// when emitting the regular name pools. We must change the symbols'
// description here.
(*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
- llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
- (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
+ Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
+ (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
// allocate TLS common symbol in tbss section
@@ -879,9 +874,9 @@
{
ELFFileFormat* file_format = getOutputFormat(pOutput);
- // get .rel.dyn LDSection and create MCSectionData
+ // get .rel.dyn LDSection and create SectionData
LDSection& reldyn = file_format->getRelDyn();
- // create MCSectionData and ARMRelDynSection
+ // create SectionData and ARMRelDynSection
m_pRelDyn = new OutputRelocSection(reldyn,
pLinker.getOrCreateSectData(reldyn),
8);
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
index f9742ed..84f2277 100644
--- a/lib/Target/Mips/MipsLDBackend.h
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -78,6 +78,9 @@
uint64_t defaultTextSegmentAddr() const;
+ /// abiPageSize - the abi page size of the target machine
+ uint64_t abiPageSize(const MCLDInfo& pInfo) const;
+
/// preLayout - Backend can do any needed modification before layout
void doPreLayout(const Output& pOutput,
const MCLDInfo& pInfo,
@@ -101,7 +104,7 @@
/// call back target backend to emit the data.
///
/// Backends handle the target-special tables (plt, gp,...) by themselves.
- /// Backend can put the data of the tables in MCSectionData directly
+ /// Backend can put the data of the tables in SectionData directly
/// - LDSection.getSectionData can get the section data.
/// Or, backend can put the data into special data structure
/// - backend can maintain its own map<LDSection, table> to get the table
diff --git a/lib/Target/Mips/MipsRelocationFactory.cpp b/lib/Target/Mips/MipsRelocationFactory.cpp
index e9d26f8..a9a34b2 100644
--- a/lib/Target/Mips/MipsRelocationFactory.cpp
+++ b/lib/Target/Mips/MipsRelocationFactory.cpp
@@ -131,7 +131,7 @@
got_entry.setContent(pReloc.symValue());
}
else {
- fatal(diag::reserve_entry_number_mismatch) << "GOT";
+ fatal(diag::reserve_entry_number_mismatch_got);
}
}
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
index dbb8194..c5bb9a8 100644
--- a/lib/Target/OutputRelocSection.cpp
+++ b/lib/Target/OutputRelocSection.cpp
@@ -6,18 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/LDSection.h>
+
#include <mcld/Target/OutputRelocSection.h>
+
+#include <llvm/Support/Casting.h>
+
+#include <mcld/LD/LDSection.h>
#include <mcld/Support/MsgHandling.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// OutputRelocSection
-
-
+//===----------------------------------------------------------------------===//
OutputRelocSection::OutputRelocSection(LDSection& pSection,
- llvm::MCSectionData& pSectionData,
+ SectionData& pSectionData,
unsigned int pEntrySize)
: m_pSection(&pSection),
m_pSectionData(&pSectionData),
diff --git a/lib/Target/PLT.cpp b/lib/Target/PLT.cpp
index a29dfd8..782d974 100644
--- a/lib/Target/PLT.cpp
+++ b/lib/Target/PLT.cpp
@@ -6,16 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
#include <mcld/Target/PLT.h>
using namespace mcld;
class GOT;
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// PLTEntry
-PLTEntry::PLTEntry(size_t pSize, llvm::MCSectionData* pParent)
- : MCTargetFragment(llvm::MCFragment::FT_Target, pParent),
+//===----------------------------------------------------------------------===//
+PLTEntry::PLTEntry(size_t pSize, SectionData* pParent)
+ : TargetFragment(Fragment::Target, pParent),
m_EntrySize(pSize), m_pContent(NULL)
{
}
@@ -28,9 +30,10 @@
}
}
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// PLT
-PLT::PLT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+//===----------------------------------------------------------------------===//
+PLT::PLT(LDSection& pSection, SectionData& pSectionData)
:m_Section(pSection),
m_SectionData(pSectionData)
{
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
index 91c7d65..518cc36 100644
--- a/lib/Target/X86/X86GOT.cpp
+++ b/lib/Target/X86/X86GOT.cpp
@@ -7,10 +7,15 @@
//
//===----------------------------------------------------------------------===//
#include "X86GOT.h"
-#include <mcld/LD/LDFileFormat.h>
-#include <mcld/Support/MsgHandling.h>
+
#include <new>
+#include <llvm/Support/Casting.h>
+
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Support/MsgHandling.h>
+
namespace {
const size_t X86GOTEntrySize = 4;
}
@@ -19,7 +24,8 @@
//===----------------------------------------------------------------------===//
// X86GOT
-X86GOT::X86GOT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+//===----------------------------------------------------------------------===//
+X86GOT::X86GOT(LDSection& pSection, SectionData& pSectionData)
: GOT(pSection, pSectionData, X86GOTEntrySize),
m_GOTIterator(), m_fIsVisit(false)
{
@@ -38,7 +44,7 @@
&m_SectionData);
if (!Entry)
- fatal(diag::fail_allocate_memory) << "GOTEntry";
+ fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + X86GOTEntrySize);
}
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
index d758de0..91cc3e8 100644
--- a/lib/Target/X86/X86GOT.h
+++ b/lib/Target/X86/X86GOT.h
@@ -6,14 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_X86_GOT_H
-#define MCLD_X86_GOT_H
+#ifndef MCLD_TARGET_X86_GOT_H
+#define MCLD_TARGET_X86_GOT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include "X86PLT.h"
+
#include <mcld/Target/GOT.h>
+#include <mcld/LD/SectionData.h>
namespace mcld
{
@@ -28,11 +30,11 @@
typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
public:
- typedef llvm::MCSectionData::iterator iterator;
- typedef llvm::MCSectionData::const_iterator const_iterator;
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
public:
- X86GOT(LDSection& pSection, llvm::MCSectionData& pSectionData);
+ X86GOT(LDSection& pSection, SectionData& pSectionData);
~X86GOT();
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index 2ba5669..49f3449 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -6,10 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
#include "X86GOTPLT.h"
+
+#include <new>
+
+#include <llvm/Support/Casting.h>
+
#include <mcld/LD/LDFileFormat.h>
#include <mcld/Support/MsgHandling.h>
-#include <new>
namespace {
const uint64_t X86GOTPLTEntrySize = 4;
@@ -19,7 +24,8 @@
//===----------------------------------------------------------------------===//
// X86GOTPLT
-X86GOTPLT::X86GOTPLT(LDSection& pSection, llvm::MCSectionData& pSectionData)
+//===----------------------------------------------------------------------===//
+X86GOTPLT::X86GOTPLT(LDSection& pSection, SectionData& pSectionData)
: GOT(pSection, pSectionData, X86GOTPLTEntrySize), m_GOTPLTIterator()
{
GOTEntry* Entry = 0;
@@ -30,7 +36,7 @@
&m_SectionData);
if (!Entry)
- fatal(diag::fail_allocate_memory) << "GOT0";
+ fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + X86GOTPLTEntrySize);
}
@@ -84,7 +90,7 @@
for (size_t i = 0; i < pNum; ++i) {
got_entry = new GOTEntry(0, getEntrySize(),&(getSectionData()));
if (!got_entry)
- fatal(diag::fail_allocate_memory) << "GOT";
+ fatal(diag::fail_allocate_memory_got);
m_Section.setSize(m_Section.size() + getEntrySize());
}
diff --git a/lib/Target/X86/X86GOTPLT.h b/lib/Target/X86/X86GOTPLT.h
index ae9f0f7..7ca695b 100644
--- a/lib/Target/X86/X86GOTPLT.h
+++ b/lib/Target/X86/X86GOTPLT.h
@@ -12,28 +12,30 @@
#include <gtest.h>
#endif
+#include <llvm/ADT/DenseMap.h>
+
#include <mcld/Target/GOT.h>
+#include <mcld/LD/SectionData.h>
namespace mcld
{
class LDSection;
+const unsigned int X86GOTPLT0Num = 3;
+
/** \class X86GOTPLT
* \brief X86 .got.plt section.
*/
-
-const unsigned int X86GOTPLT0Num = 3;
-
class X86GOTPLT : public GOT
{
typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
public:
- typedef llvm::MCSectionData::iterator iterator;
- typedef llvm::MCSectionData::const_iterator const_iterator;
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
public:
- X86GOTPLT(LDSection &pSection, llvm::MCSectionData& pSectionData);
+ X86GOTPLT(LDSection &pSection, SectionData& pSectionData);
~X86GOTPLT();
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index 2355afc..d02e621 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -13,11 +13,14 @@
#include "X86RelocationFactory.h"
#include <llvm/ADT/Triple.h>
+#include <llvm/Support/Casting.h>
+
#include <mcld/LD/SectionMap.h>
+#include <mcld/LD/FillFragment.h>
+#include <mcld/LD/RegionFragment.h>
#include <mcld/MC/MCLDInfo.h>
#include <mcld/MC/MCLDOutput.h>
#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCRegionFragment.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/TargetRegistry.h>
@@ -106,7 +109,7 @@
void X86GNULDBackend::createX86GOT(MCLinker& pLinker, const Output& pOutput)
{
- // get .got LDSection and create MCSectionData
+ // get .got LDSection and create SectionData
ELFFileFormat* file_format = getOutputFormat(pOutput);
LDSection& got = file_format->getGOT();
@@ -115,7 +118,7 @@
void X86GNULDBackend::createX86GOTPLT(MCLinker& pLinker, const Output& pOutput)
{
- // get .got.plt LDSection and create MCSectionData
+ // get .got.plt LDSection and create SectionData
ELFFileFormat* file_format = getOutputFormat(pOutput);
LDSection& gotplt = file_format->getGOTPLT();
@@ -158,12 +161,12 @@
LDSection& plt = file_format->getPLT();
LDSection& relplt = file_format->getRelPlt();
assert(m_pGOTPLT != NULL);
- // create MCSectionData and X86PLT
+ // create SectionData and X86PLT
m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOTPLT, pOutput);
// set info of .rel.plt to .plt
relplt.setLink(&plt);
- // create MCSectionData and X86RelDynSection
+ // create SectionData and X86RelDynSection
m_pRelPLT = new OutputRelocSection(relplt,
pLinker.getOrCreateSectData(relplt),
8);
@@ -172,11 +175,11 @@
void X86GNULDBackend::createX86RelDyn(MCLinker& pLinker,
const Output& pOutput)
{
- // get .rel.dyn LDSection and create MCSectionData
+ // get .rel.dyn LDSection and create SectionData
ELFFileFormat* file_format = getOutputFormat(pOutput);
LDSection& reldyn = file_format->getRelDyn();
- // create MCSectionData and X86RelDynSection
+ // create SectionData and X86RelDynSection
m_pRelDyn = new OutputRelocSection(reldyn,
pLinker.getOrCreateSectData(reldyn),
8);
@@ -215,9 +218,9 @@
llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
}
- // get or create corresponding BSS MCSectionData
+ // get or create corresponding BSS SectionData
assert(NULL != bss_sect_hdr);
- llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(
+ SectionData& bss_section = pLinker.getOrCreateSectData(
*bss_sect_hdr);
// Determine the alignment by the symbol value
@@ -225,7 +228,7 @@
uint32_t addralign = bitclass() / 8;
// allocate space in BSS for the copy symbol
- llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, pSym.size());
+ Fragment* frag = new FillFragment(0x0, 1, pSym.size());
uint64_t size = pLinker.getLayout().appendFragment(*frag,
bss_section,
addralign);
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index 2396a21..cbdb568 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -1,4 +1,4 @@
-//===- X86PLT.cpp -----------------------------------------------------------===//
+//===- X86PLT.cpp ---------------------------------------------------------===//
//
// The MCLinker Project
//
@@ -8,12 +8,18 @@
//===----------------------------------------------------------------------===//
#include "X86GOTPLT.h"
#include "X86PLT.h"
-#include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/ELF.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/Support/MsgHandling.h>
+
#include <new>
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/Casting.h>
+
+#include <mcld/MC/MCLDOutput.h>
+#include <mcld/Support/MsgHandling.h>
+
+//===----------------------------------------------------------------------===//
+// PLT entry data
+//===----------------------------------------------------------------------===//
namespace {
const uint8_t x86_dyn_plt0[] = {
@@ -44,17 +50,17 @@
namespace mcld {
-X86PLT0::X86PLT0(llvm::MCSectionData* pParent, unsigned int pSize)
+X86PLT0::X86PLT0(SectionData* pParent, unsigned int pSize)
: PLTEntry(pSize, pParent) { }
-X86PLT1::X86PLT1(llvm::MCSectionData* pParent, unsigned int pSize)
+X86PLT1::X86PLT1(SectionData* pParent, unsigned int pSize)
: PLTEntry(pSize, pParent) { }
//===----------------------------------------------------------------------===//
// X86PLT
-
+//===----------------------------------------------------------------------===//
X86PLT::X86PLT(LDSection& pSection,
- llvm::MCSectionData& pSectionData,
+ SectionData& pSectionData,
X86GOTPLT &pGOTPLT,
const Output& pOutput)
: PLT(pSection, pSectionData),
@@ -94,7 +100,7 @@
plt1_entry = new (std::nothrow) X86PLT1(&m_SectionData, m_PLT1Size);
if (!plt1_entry)
- fatal(diag::fail_allocate_memory) << "X86PLT1";
+ fatal(diag::fail_allocate_memory_plt);
m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
@@ -152,7 +158,7 @@
data = static_cast<unsigned char*>(malloc(plt0->getEntrySize()));
if (!data)
- fatal(diag::fail_allocate_memory) << "plt0";
+ fatal(diag::fail_allocate_memory_plt);
memcpy(data, m_PLT0, plt0->getEntrySize());
@@ -200,7 +206,7 @@
data = static_cast<unsigned char*>(malloc(plt1->getEntrySize()));
if (!data)
- fatal(diag::fail_allocate_memory) << "plt1";
+ fatal(diag::fail_allocate_memory_plt);
memcpy(data, m_PLT1, plt1->getEntrySize());
diff --git a/lib/Target/X86/X86PLT.h b/lib/Target/X86/X86PLT.h
index 6c7002a..1669a49 100644
--- a/lib/Target/X86/X86PLT.h
+++ b/lib/Target/X86/X86PLT.h
@@ -1,4 +1,4 @@
-//===- X86PLT.h -----------------------------------------------------===//
+//===- X86PLT.h -----------------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,10 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef X86_PLT_H
-#define X86_PLT_H
+#ifndef MCLD_TARGET_X86_PLT_H
+#define MCLD_TARGET_X86_PLT_H
+
+#include <llvm/ADT/DenseMap.h>
#include <mcld/Target/PLT.h>
+#include <mcld/LD/SectionData.h>
namespace mcld {
@@ -17,14 +20,16 @@
class GOTEntry;
class Output;
-class X86PLT0 : public PLTEntry {
+class X86PLT0 : public PLTEntry
+{
public:
- X86PLT0(llvm::MCSectionData* pParent, unsigned int pSize);
+ X86PLT0(SectionData* pParent, unsigned int pSize);
};
-class X86PLT1 : public PLTEntry {
+class X86PLT1 : public PLTEntry
+{
public:
- X86PLT1(llvm::MCSectionData* pParent, unsigned int pSize);
+ X86PLT1(SectionData* pParent, unsigned int pSize);
};
/** \class X86PLT
@@ -35,12 +40,12 @@
typedef llvm::DenseMap<const ResolveInfo*, X86PLT1*> SymbolIndexType;
public:
- typedef llvm::MCSectionData::iterator iterator;
- typedef llvm::MCSectionData::const_iterator const_iterator;
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
public:
X86PLT(LDSection& pSection,
- llvm::MCSectionData& pSectionData,
+ SectionData& pSectionData,
X86GOTPLT& pGOTPLT,
const Output& pOutput);
~X86PLT();
diff --git a/lib/Target/X86/X86RelocationFactory.cpp b/lib/Target/X86/X86RelocationFactory.cpp
index 71fa344..f603b6e 100644
--- a/lib/Target/X86/X86RelocationFactory.cpp
+++ b/lib/Target/X86/X86RelocationFactory.cpp
@@ -132,7 +132,7 @@
rel_entry.targetRef().assign(got_entry);
}
else {
- fatal(diag::reserve_entry_number_mismatch) << "GOT";
+ fatal(diag::reserve_entry_number_mismatch_got);
}
}
return got_entry;
@@ -182,7 +182,7 @@
rel_entry.setSymInfo(rsym);
}
else {
- fatal(diag::reserve_entry_number_mismatch) << "PLT";
+ fatal(diag::reserve_entry_number_mismatch_plt);
}
}
return plt_entry;
diff --git a/lib/Target/X86/X86SectLinker.cpp b/lib/Target/X86/X86SectLinker.cpp
index a888f47..2954d1f 100644
--- a/lib/Target/X86/X86SectLinker.cpp
+++ b/lib/Target/X86/X86SectLinker.cpp
@@ -47,3 +47,4 @@
// Register the linker frontend
mcld::TargetRegistry::RegisterSectLinker(TheX86Target, createX86SectLinker);
}
+