MCLinker upstream commit c27f2593f4e3.
Change-Id: I41325b6622594ebecd0a494a8d6d298c1c474ac1
diff --git a/include/mcld/ADT/SizeTraits.h b/include/mcld/ADT/SizeTraits.h
index 666d8c0..c8822cf 100644
--- a/include/mcld/ADT/SizeTraits.h
+++ b/include/mcld/ADT/SizeTraits.h
@@ -66,6 +66,16 @@
return (pAddress + 0x3F) & (~0x3F);
}
+#ifdef bswap16
+#undef bswap16
+#endif
+#ifdef bswap32
+#undef bswap32
+#endif
+#ifdef bswap64
+#undef bswap64
+#endif
+
/// bswap16 - byte swap 16-bit version
/// @ref binary utilities - elfcpp_swap
inline uint16_t bswap16(uint16_t pData)
diff --git a/include/mcld/Config/Config.h b/include/mcld/Config/Config.h
index f604109..8cadee1 100644
--- a/include/mcld/Config/Config.h
+++ b/include/mcld/Config/Config.h
@@ -29,6 +29,7 @@
#define MCLD_NUM_OF_INPUTS 32
#define MCLD_SECTIONS_PER_INPUT 16
#define MCLD_SYMBOLS_PER_INPUT 128
+#define MCLD_RELOCATIONS_PER_INPUT 1024
#endif
diff --git a/include/mcld/Config/Config.h.in b/include/mcld/Config/Config.h.in
index f025393..7b55240 100644
--- a/include/mcld/Config/Config.h.in
+++ b/include/mcld/Config/Config.h.in
@@ -15,6 +15,7 @@
#define MCLD_NUM_OF_INPUTS 32
#define MCLD_SECTIONS_PER_INPUT 16
#define MCLD_SYMBOLS_PER_INPUT 128
+#define MCLD_RELOCATIONS_PER_INPUT 1024
#endif
diff --git a/include/mcld/Fragment/Fragment.h b/include/mcld/Fragment/Fragment.h
index b3d072d..3501341 100644
--- a/include/mcld/Fragment/Fragment.h
+++ b/include/mcld/Fragment/Fragment.h
@@ -33,7 +33,6 @@
Alignment,
Fillment,
Region,
- Relocation,
Target,
Stub,
Null
@@ -48,7 +47,8 @@
Type getKind() const { return m_Kind; }
- SectionData *getParent() const { return m_pParent; }
+ const SectionData* getParent() const { return m_pParent; }
+ SectionData* getParent() { return m_pParent; }
void setParent(SectionData *pValue) { m_pParent = pValue; }
diff --git a/include/mcld/Fragment/FragmentLinker.h b/include/mcld/Fragment/FragmentLinker.h
index 9fd70d0..17e80bd 100644
--- a/include/mcld/Fragment/FragmentLinker.h
+++ b/include/mcld/Fragment/FragmentLinker.h
@@ -65,17 +65,6 @@
~FragmentLinker();
// ----- about symbols ----- //
- /// addDynSymbol - add a symbol and resolve it immediately
- template<Input::Type FROM>
- LDSymbol* addSymbol(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
-
/// defineSymbol - add a symbol
/// defineSymbol define a output symbol
///
@@ -108,20 +97,6 @@
bool finalizeSymbols();
- // ----- relocations ----- //
- /// addRelocation - add a relocation entry in FragmentLinker (only for object file)
- /// @param pType - the type of the relocation
- /// @param pSym - the symbol should be the symbol in the input file. FragmentLinker
- /// computes the real applied address by the output symbol.
- /// @param pSection - the input relocation section
- /// @param pOffset - the offset of target section.
- /// @param pAddend - the addend value for applying relocation
- Relocation* addRelocation(Relocation::Type pType,
- LDSymbol& pSym,
- LDSection& pSection,
- uint32_t pOffset,
- Relocation::Address pAddend = 0);
-
/// applyRelocations - apply all relocation enties.
bool applyRelocations();
@@ -182,24 +157,6 @@
bool shouldForceLocal(const ResolveInfo& pInfo) const;
- LDSymbol* addSymbolFromDynObj(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility);
-
- LDSymbol* addSymbolFromObject(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility);
-
/// checkIsOutputPIC - return whether the output is position-independent,
/// called by isOutputPIC()
bool checkIsOutputPIC() const;
diff --git a/include/mcld/Fragment/FragmentLinker.tcc b/include/mcld/Fragment/FragmentLinker.tcc
index 884a597..cc3fad6 100644
--- a/include/mcld/Fragment/FragmentLinker.tcc
+++ b/include/mcld/Fragment/FragmentLinker.tcc
@@ -6,53 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
-/// addSymbol - add a symbol and resolve it immediately
-template<Input::Type FROM>
-LDSymbol* FragmentLinker::addSymbol(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
- llvm::StringRef symbol_name = pName;
- if (!getLDInfo().scripts().renameMap().empty() &&
- ResolveInfo::Undefined == pDesc) {
- // If the renameMap is not empty, some symbols should be renamed.
- // --wrap and --portable defines the symbol rename map.
- ScriptOptions::SymbolRenameMap::const_iterator renameSym
- = getLDInfo().scripts().renameMap().find(pName);
- if (renameSym != getLDInfo().scripts().renameMap().end())
- symbol_name = renameSym.getEntry()->value();
- }
-
- if (FROM == Input::DynObj)
- return addSymbolFromDynObj(symbol_name,
- pType,
- pDesc,
- pBinding,
- pSize,
- pValue,
- pFragmentRef,
- pVisibility);
-
- if (FROM == Input::Object)
- return addSymbolFromObject(symbol_name,
- pType,
- pDesc,
- pBinding,
- pSize,
- pValue,
- pFragmentRef,
- pVisibility);
-
- llvm::report_fatal_error("add a symbol from unknown file type.\n");
- return NULL;
-}
-
// defineSymbol - define a new symbol
template<FragmentLinker::DefinePolicy POLICY,
FragmentLinker::ResolvePolicy RESOLVE>
diff --git a/include/mcld/Fragment/Relocation.h b/include/mcld/Fragment/Relocation.h
index c6584c4..37b32f6 100644
--- a/include/mcld/Fragment/Relocation.h
+++ b/include/mcld/Fragment/Relocation.h
@@ -11,20 +11,24 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/Support/DataTypes.h>
-
-#include <mcld/Fragment/Fragment.h>
+#include <mcld/Config/Config.h>
#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/Support/GCFactoryListTraits.h>
+
+#include <llvm/ADT/ilist_node.h>
+#include <llvm/Support/DataTypes.h>
namespace mcld {
class ResolveInfo;
-class RelocationFactory;
+class Relocator;
class LinkerConfig;
-class Relocation : public Fragment
+class Relocation : public llvm::ilist_node<Relocation>
{
friend class RelocationFactory;
+friend class GCFactoryListTraits<Relocation>;
+friend class Chunk<Relocation, MCLD_RELOCATIONS_PER_INPUT>;
public:
typedef uint64_t Address; // FIXME: use SizeTrait<T>::Address instead
@@ -33,14 +37,35 @@
typedef uint8_t Type;
private:
+ Relocation();
+
Relocation(Type pType,
FragmentRef* pTargetRef,
Address pAddend,
DWord pTargetData);
-public:
~Relocation();
+public:
+ /// Initialize - set up the relocation factory
+ static void SetUp(const LinkerConfig& pConfig);
+
+ /// Clear - Clean up the relocation factory
+ static void Clear();
+
+ /// Create - produce an empty relocation entry
+ static Relocation* Create();
+
+ /// Create - produce a relocation entry
+ /// @param pType [in] the type of the relocation entry
+ /// @param pFragRef [in] the place to apply the relocation
+ /// @param pAddend [in] the addend of the relocation entry
+ static Relocation* Create(Type pType, FragmentRef& pFragRef,
+ Address pAddend = 0);
+
+ /// Destroy - destroy a relocation entry
+ static void Destroy(Relocation*& pRelocation);
+
/// type - relocation type
Type type() const
{ return m_Type; }
@@ -67,8 +92,7 @@
const FragmentRef& targetRef() const { return m_TargetAddress; }
FragmentRef& targetRef() { return m_TargetAddress; }
-
- void apply(RelocationFactory& pRelocFactory);
+ void apply(Relocator& pRelocator);
/// updateAddend - A relocation with a section symbol must update addend
/// before reading its value.
@@ -81,13 +105,6 @@
void setSymInfo(ResolveInfo* pSym);
- // Relocation is a kind of Fragment with type of FT_Reloc
- static bool classof(const Fragment *F)
- { return F->getKind() == Fragment::Relocation; }
-
- static bool classof(const Relocation *)
- { return true; }
-
size_t size() const;
private:
diff --git a/include/mcld/GeneralOptions.h b/include/mcld/GeneralOptions.h
index 0b5c7a9..1468704 100644
--- a/include/mcld/GeneralOptions.h
+++ b/include/mcld/GeneralOptions.h
@@ -199,38 +199,56 @@
// -n, --nmagic
void setNMagic(bool pMagic = true)
- { m_NMagic = pMagic; }
+ { m_bNMagic = pMagic; }
bool nnagic() const
- { return m_NMagic; }
+ { return m_bNMagic; }
// -N, --omagic
void setOMagic(bool pMagic = true)
- { m_OMagic = pMagic; }
+ { m_bOMagic = pMagic; }
bool omagic() const
- { return m_OMagic; }
+ { return m_bOMagic; }
// -S, --strip-debug
void setStripDebug(bool pStripDebug = true)
- { m_StripDebug = pStripDebug; }
+ { m_bStripDebug = pStripDebug; }
bool stripDebug() const
- { return m_StripDebug; }
+ { return m_bStripDebug; }
// -E, --export-dynamic
void setExportDynamic(bool pExportDynamic = true)
- { m_ExportDynamic = pExportDynamic; }
+ { m_bExportDynamic = pExportDynamic; }
bool exportDynamic() const
- { return m_ExportDynamic; }
+ { return m_bExportDynamic; }
// --warn-shared-textrel
void setWarnSharedTextrel(bool pWarnSharedTextrel = true)
- { m_WarnSharedTextrel = pWarnSharedTextrel; }
+ { m_bWarnSharedTextrel = pWarnSharedTextrel; }
bool warnSharedTextrel() const
- { return m_WarnSharedTextrel; }
+ { return m_bWarnSharedTextrel; }
+
+ void setBinaryInput(bool pBinaryInput = true)
+ { m_bBinaryInput = pBinaryInput; }
+
+ bool isBinaryInput() const
+ { return m_bBinaryInput; }
+
+ void setDefineCommon(bool pEnable = true)
+ { m_bDefineCommon = pEnable; }
+
+ bool isDefineCommon() const
+ { return m_bDefineCommon; }
+
+ void setFatalWarnings(bool pEnable = true)
+ { m_bFatalWarnings = pEnable; }
+
+ bool isFatalWarnings() const
+ { return m_bFatalWarnings; }
private:
enum status {
@@ -273,11 +291,14 @@
bool m_bColor : 1; // --color[=true,false,auto]
bool m_bAllowShlibUndefined : 1; // --[no-]allow-shlib-undefined and
bool m_bCreateEhFrameHdr : 1; // --eh-frame-hdr
- bool m_NMagic; // -n, --nmagic
- bool m_OMagic; // -N, --omagic
- bool m_StripDebug; // -S, --strip-debug
- bool m_ExportDynamic; //-E, --export-dynamic
- bool m_WarnSharedTextrel; // --warn-shared-textrel
+ bool m_bNMagic : 1; // -n, --nmagic
+ bool m_bOMagic : 1; // -N, --omagic
+ bool m_bStripDebug : 1; // -S, --strip-debug
+ bool m_bExportDynamic :1; //-E, --export-dynamic
+ bool m_bWarnSharedTextrel : 1; // --warn-shared-textrel
+ bool m_bBinaryInput : 1; // -b [input-format], --format=[input-format]
+ bool m_bDefineCommon : 1; // -d, -dc, -dp
+ bool m_bFatalWarnings : 1; // --fatal-warnings
};
} // namespace of mcld
diff --git a/include/mcld/IRBuilder.h b/include/mcld/IRBuilder.h
index 1ebd153..3de292f 100644
--- a/include/mcld/IRBuilder.h
+++ b/include/mcld/IRBuilder.h
@@ -19,6 +19,7 @@
#include <mcld/LD/LDSection.h>
#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/LDSymbol.h>
#include <mcld/Fragment/Fragment.h>
#include <mcld/Fragment/Relocation.h>
@@ -360,6 +361,68 @@
/// @return Total size of the inserted fragments.
static uint64_t AppendEhFrame(EhFrame::CIE& pCIE, EhFrame& pEhFrame);
+ /// AddSymbol - To add a symbol to the input file and module. The symbol is
+ /// resolved immediately.
+ ///
+ /// This is a general method for all kinds of symbol.
+ ///
+ /// @param [in, out] pInput The input file. Either a relocatable or dynamic
+ /// object
+ /// @param [in] pName The name of the symbol
+ /// @param [in] pType What the symbol refers to
+ /// @param [in] pDesc { Undefined, Define, Common, Indirect }
+ /// @param [in] pBind { Global, Weak, Local, Absolute }
+ /// @param [in] pSize The size of the symbol. Bigger common symbols
+ /// overrides the smaller common symbols.
+ /// @param [in] pValue Common symbols' value are alignment constraints
+ /// Undefined symbols don't have value.
+ /// The rest symbols' value are relative section
+ /// offset.
+ /// @param [in] pSection Absolute, undefined, common symbols do not have
+ /// pSection. Keep their pSection be NULL.
+ /// @oaram [in] pVis The visibility of the symbol
+ LDSymbol* AddSymbol(Input& pInput,
+ const std::string& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBind,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue = 0x0,
+ LDSection* pSection = NULL,
+ ResolveInfo::Visibility pVis = ResolveInfo::Default);
+
+ /// AddRelocation - To add a relocation entry
+ ///
+ /// @param [in] pSection The relocation section. pSection's link should point to
+ /// the target section.
+ /// @param [in] pType The type of the relocation (target dependent)
+ /// @param [in] pSym The symbol should be the symbol in the input file.
+ /// @param [in] pOffset The offset of target section.
+ /// @param [in] pAddend Tthe addend value for applying relocation
+ static Relocation* AddRelocation(LDSection& pSection,
+ Relocation::Type pType,
+ LDSymbol& pSym,
+ uint32_t pOffset,
+ Relocation::Address pAddend = 0);
+
+private:
+ LDSymbol* addSymbolFromObject(const std::string& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility);
+
+ LDSymbol* addSymbolFromDynObj(const std::string& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ ResolveInfo::Visibility pVisibility);
+
private:
Module& m_Module;
const LinkerConfig& m_Config;
diff --git a/include/mcld/LD/BinaryReader.h b/include/mcld/LD/BinaryReader.h
new file mode 100644
index 0000000..e9c47db
--- /dev/null
+++ b/include/mcld/LD/BinaryReader.h
@@ -0,0 +1,45 @@
+//===- BinaryReader.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_Binary_READER_H
+#define MCLD_Binary_READER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include "mcld/LD/LDReader.h"
+#include <llvm/Support/system_error.h>
+
+namespace mcld {
+
+class Module;
+class Input;
+
+/** \class BinaryReader
+ * \brief BinaryReader provides an common interface for different Binary
+ * formats.
+ */
+class BinaryReader : public LDReader
+{
+protected:
+ BinaryReader()
+ { }
+
+public:
+ virtual ~BinaryReader()
+ { }
+
+ virtual bool isMyFormat(Input& pInput) const
+ { return true; }
+
+ virtual bool readBinary(Input& pFile) = 0;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/BinaryWriter.h b/include/mcld/LD/BinaryWriter.h
new file mode 100644
index 0000000..d8133c4
--- /dev/null
+++ b/include/mcld/LD/BinaryWriter.h
@@ -0,0 +1,39 @@
+//===- BinaryWriter.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_BINARY_WRITER_INTERFACE_H
+#define MCLD_BINARY_WRITER_INTERFACE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/Support/system_error.h>
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+class GNULDBackend;
+
+/** \class BinaryWriter
+ * \brief BinaryWriter provides a common interface for Binary file writers.
+ */
+class BinaryWriter
+{
+protected:
+ BinaryWriter(GNULDBackend& pBackend);
+
+public:
+ virtual ~BinaryWriter();
+
+ virtual llvm::error_code writeBinary(Module& pModule, MemoryArea& pOutput) = 0;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/DiagRelocations.inc b/include/mcld/LD/DiagRelocations.inc
index 5d52dd8..7ada05f 100644
--- a/include/mcld/LD/DiagRelocations.inc
+++ b/include/mcld/LD/DiagRelocations.inc
@@ -1,3 +1,5 @@
+DIAG(reloc_factory_has_not_config, DiagnosticEngine::Fatal, "Please call mcld::Linker::config before creating relocations", "Please call mcld::Linker::config before creating relocations")
+DIAG(unsupported_bitclass, DiagnosticEngine::Fatal, "Only supports 32 and 64 bits targets. (Target: %0, bitclass:%1)", "Only supports 32 and 64 bits targets. (Target: %0, bitclass:%1)")
DIAG(undefined_reference, DiagnosticEngine::Fatal, "undefined reference to `%0'", "In %1:%2, variable %0 must be defined")
DIAG(non_pic_relocation, DiagnosticEngine::Error, "attempt to generate unsupported relocation type `%0' for symbol `%1', recompile with -fPIC", "attempt to generate unsupported relocation type `%0' for symbol `%1, recompile with -fPIC")
DIAG(base_relocation, DiagnosticEngine::Fatal, "relocation type `%0' is not supported for symbol `%1'\nPlease report to %2", "relocation type `%0' is not supported for symbol `%1'\nPlease report to %2")
diff --git a/include/mcld/LD/ELFBinaryReader.h b/include/mcld/LD/ELFBinaryReader.h
new file mode 100644
index 0000000..fc3a067
--- /dev/null
+++ b/include/mcld/LD/ELFBinaryReader.h
@@ -0,0 +1,48 @@
+//===- ELFBinaryReader.h --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELF_Binary_READER_H
+#define MCLD_ELF_Binary_READER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/LD/BinaryReader.h>
+
+namespace mcld {
+
+class Module;
+class Input;
+class IRBuilder;
+class GNULDBackend;
+class LinkerConfig;
+
+/** \lclass ELFBinaryReader
+ * \brief ELFBinaryReader reads target-independent parts of Binary file
+ */
+class ELFBinaryReader : public BinaryReader
+{
+public:
+ ELFBinaryReader(GNULDBackend& pBackend,
+ IRBuilder& pBuilder,
+ const LinkerConfig& pConfig);
+
+ ~ELFBinaryReader();
+
+ virtual bool readBinary(Input& pInput);
+
+private:
+ GNULDBackend& m_Backend;
+ IRBuilder& m_Builder;
+ const LinkerConfig& m_Config;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ELFBinaryWriter.h b/include/mcld/LD/ELFBinaryWriter.h
new file mode 100644
index 0000000..593b54b
--- /dev/null
+++ b/include/mcld/LD/ELFBinaryWriter.h
@@ -0,0 +1,46 @@
+//===- ELFBinaryWriter.h --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELF_BINARY_WRITER_H
+#define MCLD_ELF_BINARY_WRITER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/Support/system_error.h>
+#include <mcld/LD/BinaryWriter.h>
+#include <mcld/LD/ELFWriter.h>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+class MemoryArea;
+class GNULDBackend;
+
+/** \class ELFBinaryWriter
+ * \brief ELFBinaryWriter writes the target-independent parts of Binary files.
+ * ELFBinaryWriter reads a MCLDFile and writes into raw_ostream
+ *
+ */
+class ELFBinaryWriter : public BinaryWriter, protected ELFWriter
+{
+public:
+ ELFBinaryWriter(GNULDBackend& pBackend, const LinkerConfig& pConfig);
+
+ ~ELFBinaryWriter();
+
+ llvm::error_code writeBinary(Module& pModule, MemoryArea& pOutput);
+
+private:
+ const LinkerConfig& m_Config;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ELFDynObjReader.h b/include/mcld/LD/ELFDynObjReader.h
index b5d59a3..f6d2067 100644
--- a/include/mcld/LD/ELFDynObjReader.h
+++ b/include/mcld/LD/ELFDynObjReader.h
@@ -14,11 +14,11 @@
#include <mcld/LD/DynObjReader.h>
#include <llvm/Support/system_error.h>
-namespace mcld
-{
+namespace mcld {
class Input;
-class FragmentLinker;
+class LinkerConfig;
+class IRBuilder;
class GNULDBackend;
class ELFReaderIF;
@@ -29,7 +29,9 @@
class ELFDynObjReader : public DynObjReader
{
public:
- ELFDynObjReader(GNULDBackend& pBackend, FragmentLinker& pLinker);
+ ELFDynObjReader(GNULDBackend& pBackend,
+ IRBuilder& pBuilder,
+ const LinkerConfig& pConfig);
~ELFDynObjReader();
// ----- observers ----- //
@@ -42,7 +44,7 @@
private:
ELFReaderIF *m_pELFReader;
- FragmentLinker& m_Linker;
+ IRBuilder& m_Builder;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFDynObjWriter.h b/include/mcld/LD/ELFDynObjWriter.h
index b5dd390..774943e 100644
--- a/include/mcld/LD/ELFDynObjWriter.h
+++ b/include/mcld/LD/ELFDynObjWriter.h
@@ -17,9 +17,9 @@
namespace mcld {
class Module;
+class LinkerConfig;
class MemoryArea;
class GNULDBackend;
-class FragmentLinker;
/** \class ELFDynObjWriter
* \brief ELFDynObjWriter writes the dynamic sections.
@@ -30,13 +30,15 @@
typedef ELFWriter::FileOffset FileOffset;
public:
- ELFDynObjWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
+ ELFDynObjWriter(GNULDBackend& pBackend,
+ const LinkerConfig& pConfig);
+
~ELFDynObjWriter();
llvm::error_code writeDynObj(Module& pModule, MemoryArea& pOutput);
private:
- FragmentLinker& m_Linker;
+ const LinkerConfig& m_Config;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFExecWriter.h b/include/mcld/LD/ELFExecWriter.h
index dc731b9..ca69235 100644
--- a/include/mcld/LD/ELFExecWriter.h
+++ b/include/mcld/LD/ELFExecWriter.h
@@ -17,9 +17,9 @@
namespace mcld {
class Module;
+class LinkerConfig;
class MemoryArea;
class GNULDBackend;
-class FragmentLinker;
/** \class ELFDynObjWriter
* \brief ELFDynObjWriter writes the dynamic sections.
@@ -30,13 +30,15 @@
typedef ELFWriter::FileOffset FileOffset;
public:
- ELFExecWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
+ ELFExecWriter(GNULDBackend& pBackend,
+ const LinkerConfig& pConfig);
+
~ELFExecWriter();
llvm::error_code writeExecutable(Module& pModule, MemoryArea& pOutput);
private:
- FragmentLinker& m_Linker;
+ const LinkerConfig& m_Config;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFObjectReader.h b/include/mcld/LD/ELFObjectReader.h
index c1463fa..27e4489 100644
--- a/include/mcld/LD/ELFObjectReader.h
+++ b/include/mcld/LD/ELFObjectReader.h
@@ -19,10 +19,11 @@
class Module;
class Input;
-class FragmentLinker;
+class IRBuilder;
class GNULDBackend;
class ELFReaderIF;
class EhFrameReader;
+class LinkerConfig;
/** \lclass ELFObjectReader
* \brief ELFObjectReader reads target-independent parts of ELF object file
@@ -38,7 +39,9 @@
typedef Flags<ReadFlagType> ReadFlag;
public:
- ELFObjectReader(GNULDBackend& pBackend, FragmentLinker& pLinker);
+ ELFObjectReader(GNULDBackend& pBackend,
+ IRBuilder& pBuilder,
+ const LinkerConfig& pConfig);
~ELFObjectReader();
@@ -60,9 +63,10 @@
private:
ELFReaderIF* m_pELFReader;
EhFrameReader* m_pEhFrameReader;
- FragmentLinker& m_Linker;
+ IRBuilder& m_Builder;
ReadFlag m_ReadFlag;
GNULDBackend& m_Backend;
+ const LinkerConfig& m_Config;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFObjectWriter.h b/include/mcld/LD/ELFObjectWriter.h
index 31f7b12..28bbba8 100644
--- a/include/mcld/LD/ELFObjectWriter.h
+++ b/include/mcld/LD/ELFObjectWriter.h
@@ -11,15 +11,16 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/Support/system_error.h>
#include <mcld/LD/ObjectWriter.h>
#include <mcld/LD/ELFWriter.h>
+#include <llvm/Support/system_error.h>
+
namespace mcld {
class Module;
+class LinkerConfig;
class MemoryArea;
-class FragmentLinker;
class GNULDBackend;
/** \class ELFObjectWriter
@@ -30,14 +31,15 @@
class ELFObjectWriter : public ObjectWriter, protected ELFWriter
{
public:
- ELFObjectWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
+ ELFObjectWriter(GNULDBackend& pBackend,
+ const LinkerConfig& pConfig);
~ELFObjectWriter();
llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput);
private:
- FragmentLinker& m_Linker;
+ const LinkerConfig& m_Config;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFReader.h b/include/mcld/LD/ELFReader.h
index 941c8cd..146a00a 100644
--- a/include/mcld/LD/ELFReader.h
+++ b/include/mcld/LD/ELFReader.h
@@ -29,8 +29,8 @@
namespace mcld {
class Module;
+class IRBuilder;
class FragmentRef;
-class FragmentLinker;
class SectionData;
class LDSection;
@@ -74,7 +74,7 @@
/// readSymbols - read ELF symbols and create LDSymbol
virtual bool readSymbols(Input& pInput,
- FragmentLinker& pLinker,
+ IRBuilder& pBuilder,
const MemoryRegion& pRegion,
const char* StrTab) const = 0;
@@ -86,13 +86,11 @@
/// readRela - read ELF rela and create Relocation
virtual bool readRela(Input& pInput,
- FragmentLinker& pLinker,
LDSection& pSection,
const MemoryRegion& pRegion) const = 0;
/// readRel - read ELF rel and create Relocation
virtual bool readRel(Input& pInput,
- FragmentLinker& pLinker,
LDSection& pSection,
const MemoryRegion& pRegion) const = 0;
@@ -181,9 +179,9 @@
/// readSymbols - read ELF symbols and create LDSymbol
bool readSymbols(Input& pInput,
- FragmentLinker& pLinker,
- const MemoryRegion& pRegion,
- const char* StrTab) const;
+ IRBuilder& pBuilder,
+ const MemoryRegion& pRegion,
+ const char* StrTab) const;
/// readSignature - read a symbol from the given Input and index in symtab
/// This is used to get the signature of a group section.
@@ -193,13 +191,11 @@
/// readRela - read ELF rela and create Relocation
bool readRela(Input& pInput,
- FragmentLinker& pLinker,
LDSection& pSection,
const MemoryRegion& pRegion) const;
/// readRel - read ELF rel and create Relocation
bool readRel(Input& pInput,
- FragmentLinker& pLinker,
LDSection& pSection,
const MemoryRegion& pRegion) const;
diff --git a/include/mcld/LD/Layout.h b/include/mcld/LD/Layout.h
deleted file mode 100644
index 7380b20..0000000
--- a/include/mcld/LD/Layout.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//===- Layout.h -----------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_LAYOUT_H
-#define MCLD_LD_LAYOUT_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <vector>
-#include <map>
-
-#include <llvm/ADT/ilist.h>
-#include <llvm/ADT/ilist_node.h>
-#include <llvm/ADT/DenseMap.h>
-
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/SectionData.h>
-#include <mcld/LinkerConfig.h>
-#include <mcld/Support/GCFactory.h>
-
-namespace mcld {
-
-class Module;
-class FragmentRef;
-class FragmentLinker;
-class TargetLDBackend;
-
-/** \class Layout
- * \brief Layout maintains the mapping between sections and fragments.
- *
- * FragmentLinker is a fragment-based linker. But readers and target backends
- * still need section information. Layout is used to maintain the mapping
- * between sections and fragments. Layout helps readers and target backends
- * get the input or output section information from a fragment.
- */
-class Layout
-{
-public:
- // ----- modifiers ----- //
- bool layout(Module& pModule,
- const TargetLDBackend& pBackend,
- const LinkerConfig& pConfig);
-
-private:
- /// sortSectionOrder - perform sorting on m_SectionOrder to get final layout
- /// ordering
- void sortSectionOrder(const TargetLDBackend& pBackend,
- const LinkerConfig& pConfig);
-
-private:
- typedef std::vector<LDSection*> SectionOrder;
-
-private:
- /// a vector to describe the order of sections
- SectionOrder m_SectionOrder;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/RelocData.h b/include/mcld/LD/RelocData.h
index 6061544..b53151a 100644
--- a/include/mcld/LD/RelocData.h
+++ b/include/mcld/LD/RelocData.h
@@ -12,81 +12,85 @@
#include <gtest.h>
#endif
-#include <llvm/ADT/ilist.h>
-#include <llvm/ADT/ilist_node.h>
-#include <llvm/Support/DataTypes.h>
-
#include <mcld/Config/Config.h>
-#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/Relocation.h>
#include <mcld/Support/Allocators.h>
#include <mcld/Support/GCFactoryListTraits.h>
+#include <llvm/ADT/ilist.h>
+#include <llvm/ADT/ilist_node.h>
+#include <llvm/Support/DataTypes.h>
namespace mcld {
class LDSection;
/** \class RelocData
- * \brief RelocData is the special SectionData to store Relocation fragments.
+ * \brief RelocData stores Relocation.
+ *
* Since Relocations are created by GCFactory, we use GCFactoryListTraits for the
- * FragmentList here to avoid iplist to delete Relocations.
+ * RelocationList here to avoid iplist to delete Relocations.
*/
class RelocData
{
private:
+ friend class Chunk<RelocData, MCLD_SECTIONS_PER_INPUT>;
+
RelocData();
- explicit RelocData(const LDSection &pSection);
+ explicit RelocData(LDSection &pSection);
RelocData(const RelocData &); // DO NOT IMPLEMENT
RelocData& operator=(const RelocData &); // DO NOT IMPLEMENT
public:
- typedef llvm::iplist<Fragment,
- GCFactoryListTraits<Fragment> > FragmentListType;
+ typedef llvm::iplist<Relocation,
+ GCFactoryListTraits<Relocation> > RelocationListType;
- typedef FragmentListType::reference reference;
- typedef FragmentListType::const_reference const_reference;
+ typedef RelocationListType::reference reference;
+ typedef RelocationListType::const_reference const_reference;
- typedef FragmentListType::iterator iterator;
- typedef FragmentListType::const_iterator const_iterator;
+ typedef RelocationListType::iterator iterator;
+ typedef RelocationListType::const_iterator const_iterator;
- typedef FragmentListType::reverse_iterator reverse_iterator;
- typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
+ typedef RelocationListType::reverse_iterator reverse_iterator;
+ typedef RelocationListType::const_reverse_iterator const_reverse_iterator;
public:
- static RelocData* Create(const LDSection& pSection);
-
- static RelocData* Create();
+ static RelocData* Create(LDSection& pSection);
static void Destroy(RelocData*& pSection);
- const LDSection &getSection() const
- { assert(NULL != m_pSection ); return *m_pSection; }
+ static void Clear();
- FragmentListType &getFragmentList() { return m_Fragments; }
- const FragmentListType &getFragmentList() const { return m_Fragments; }
+ const LDSection& getSection() const { return *m_pSection; }
+ LDSection& getSection() { return *m_pSection; }
- size_t size() const { return m_Fragments.size(); }
+ const RelocationListType& getRelocationList() const { return m_Relocations; }
+ RelocationListType& getRelocationList() { return m_Relocations; }
- bool empty() const { return m_Fragments.empty(); }
+ size_t size() const { return m_Relocations.size(); }
- reference front () { return m_Fragments.front(); }
- const_reference front () const { return m_Fragments.front(); }
- reference back () { return m_Fragments.back(); }
- const_reference back () const { return m_Fragments.back(); }
+ bool empty() const { return m_Relocations.empty(); }
- const_iterator begin () const { return m_Fragments.begin(); }
- iterator begin () { return m_Fragments.begin(); }
- const_iterator end () const { return m_Fragments.end(); }
- iterator end () { return m_Fragments.end(); }
- const_reverse_iterator rbegin() const { return m_Fragments.rbegin(); }
- reverse_iterator rbegin() { return m_Fragments.rbegin(); }
- const_reverse_iterator rend () const { return m_Fragments.rend(); }
- reverse_iterator rend () { return m_Fragments.rend(); }
+ RelocData& append(Relocation& pRelocation);
+
+ reference front () { return m_Relocations.front(); }
+ const_reference front () const { return m_Relocations.front(); }
+ reference back () { return m_Relocations.back(); }
+ const_reference back () const { return m_Relocations.back(); }
+
+ const_iterator begin () const { return m_Relocations.begin(); }
+ iterator begin () { return m_Relocations.begin(); }
+ const_iterator end () const { return m_Relocations.end(); }
+ iterator end () { return m_Relocations.end(); }
+ const_reverse_iterator rbegin() const { return m_Relocations.rbegin(); }
+ reverse_iterator rbegin() { return m_Relocations.rbegin(); }
+ const_reverse_iterator rend () const { return m_Relocations.rend(); }
+ reverse_iterator rend () { return m_Relocations.rend(); }
private:
- FragmentListType m_Fragments;
- const LDSection* m_pSection;
+ RelocationListType m_Relocations;
+ LDSection* m_pSection;
};
diff --git a/include/mcld/LD/RelocationFactory.h b/include/mcld/LD/RelocationFactory.h
index c9f0d64..bd590a5 100644
--- a/include/mcld/LD/RelocationFactory.h
+++ b/include/mcld/LD/RelocationFactory.h
@@ -11,18 +11,13 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
+#include <mcld/Config/Config.h>
#include <mcld/Support/GCFactory.h>
#include <mcld/Fragment/Relocation.h>
namespace mcld {
-class LDSymbol;
-class ResolveInfo;
class FragmentRef;
-class FragmentLinker;
-class Layout;
-class GOT;
-class TargetLDBackend;
class LinkerConfig;
/** \class RelocationFactory
@@ -30,7 +25,7 @@
* relocation
*
*/
-class RelocationFactory : public GCFactory<Relocation, 0>
+class RelocationFactory : public GCFactory<Relocation, MCLD_RELOCATIONS_PER_INPUT>
{
public:
typedef Relocation::Type Type;
@@ -38,21 +33,10 @@
typedef Relocation::DWord DWord;
typedef Relocation::SWord SWord;
- enum Result {
- OK,
- BadReloc,
- Overflow,
- Unsupport,
- Unknown
- };
-
public:
- explicit RelocationFactory(size_t pNum);
+ explicit RelocationFactory();
- virtual ~RelocationFactory();
-
- /// apply - general apply function
- virtual Result applyRelocation(Relocation& pRelocation) = 0;
+ void setConfig(const LinkerConfig& pConfig);
// ----- production ----- //
/// produce - produce a relocation entry
@@ -69,22 +53,8 @@
void destroy(Relocation* pRelocation);
- void setFragmentLinker(const FragmentLinker& pLinker);
-
- // ------ observers -----//
- const FragmentLinker& getFragmentLinker() const;
-
- bool hasFragmentLinker() const;
-
- virtual TargetLDBackend& getTarget() = 0;
-
- virtual const TargetLDBackend& getTarget() const = 0;
-
- virtual const char* getName(Type pType) const = 0;
-
private:
- const FragmentLinker* m_pLinker;
-
+ const LinkerConfig* m_pConfig;
};
} // namespace of mcld
diff --git a/include/mcld/LD/Relocator.h b/include/mcld/LD/Relocator.h
new file mode 100644
index 0000000..6fd431e
--- /dev/null
+++ b/include/mcld/LD/Relocator.h
@@ -0,0 +1,76 @@
+//===- Relocator.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_RELOCATOR_H
+#define MCLD_RELOCATOR_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Fragment/Relocation.h>
+
+namespace mcld
+{
+
+class FragmentLinker;
+class TargetLDBackend;
+
+/** \class Relocator
+ * \brief Relocator provides the interface of performing relocations
+ */
+class Relocator
+{
+public:
+ typedef Relocation::Type Type;
+ typedef Relocation::Address Address;
+ typedef Relocation::DWord DWord;
+ typedef Relocation::SWord SWord;
+
+public:
+ enum Result {
+ OK,
+ BadReloc,
+ Overflow,
+ Unsupport,
+ Unknown
+ };
+
+public:
+ virtual ~Relocator() {}
+
+ /// apply - general apply function
+ virtual Result applyRelocation(Relocation& pRelocation) = 0;
+
+ void setFragmentLinker(const FragmentLinker& pLinker)
+ { m_pLinker = &pLinker; }
+
+ // ------ observers -----//
+ const FragmentLinker& getFragmentLinker() const
+ {
+ assert(NULL != m_pLinker);
+ return *m_pLinker;
+ }
+
+ bool hasFragmentLinker() const
+ { return (NULL != m_pLinker); }
+
+ virtual TargetLDBackend& getTarget() = 0;
+
+ virtual const TargetLDBackend& getTarget() const = 0;
+
+ virtual const char* getName(Type pType) const = 0;
+
+private:
+ const FragmentLinker* m_pLinker;
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ResolveInfo.h b/include/mcld/LD/ResolveInfo.h
index 2cff57e..aaf74e1 100644
--- a/include/mcld/LD/ResolveInfo.h
+++ b/include/mcld/LD/ResolveInfo.h
@@ -26,7 +26,7 @@
* - Desc - Defined, Reference, Common or Indirect
* - Binding - Global, Local, Weak
* - IsDyn - appear in dynamic objects or regular objects
- * - Type - what the symbol points to
+ * - Type - what the symbol refers to
* - Size - the size of the symbol point to
* - Value - the pointer to another LDSymbol
* In order to save the memory and speed up the performance, FragmentLinker uses
@@ -37,6 +37,7 @@
class ResolveInfo
{
friend class FragmentLinker;
+friend class IRBuilder;
public:
typedef uint64_t SizeType;
diff --git a/include/mcld/LD/SectionData.h b/include/mcld/LD/SectionData.h
index 316d92f..4f58afa 100644
--- a/include/mcld/LD/SectionData.h
+++ b/include/mcld/LD/SectionData.h
@@ -55,6 +55,8 @@
static void Destroy(SectionData*& pSection);
+ static void Clear();
+
const LDSection& getSection() const { return *m_pSection; }
LDSection& getSection() { return *m_pSection; }
diff --git a/include/mcld/LD/StubFactory.h b/include/mcld/LD/StubFactory.h
index 00a65ec..b38a96f 100644
--- a/include/mcld/LD/StubFactory.h
+++ b/include/mcld/LD/StubFactory.h
@@ -6,7 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#ifndef MCLD_LD_STUB_FACTORY_H
#define MCLD_LD_STUB_FACTORY_H
#ifdef ENABLE_UNITTEST
@@ -16,12 +15,10 @@
#include <llvm/Support/DataTypes.h>
#include <vector>
-namespace mcld
-{
+namespace mcld {
class Stub;
class Relocation;
-class RelocationFactory;
class BranchIslandFactory;
class FragmentLinker;
@@ -32,8 +29,6 @@
class StubFactory
{
public:
- StubFactory();
-
~StubFactory();
/// addPrototype - register a stub prototype
@@ -43,7 +38,6 @@
Stub* create(Relocation& pReloc,
uint64_t pTargetSymValue,
FragmentLinker& pLinker,
- RelocationFactory& pRelocFactory,
BranchIslandFactory& pBRIslandFactory);
private:
diff --git a/include/mcld/LinkerConfig.h b/include/mcld/LinkerConfig.h
index 7d52819..9e70ecf 100644
--- a/include/mcld/LinkerConfig.h
+++ b/include/mcld/LinkerConfig.h
@@ -16,6 +16,7 @@
#include <mcld/GeneralOptions.h>
#include <mcld/ScriptOptions.h>
+#include <mcld/TargetOptions.h>
#include <mcld/BitcodeOption.h>
#include <mcld/AttributeOption.h>
#include <mcld/Support/Path.h>
@@ -39,7 +40,8 @@
Object,
DynObj,
Exec,
- External
+ External,
+ Binary
};
public:
@@ -55,6 +57,9 @@
const ScriptOptions& scripts() const { return m_Scripts; }
ScriptOptions& scripts() { return m_Scripts; }
+ const TargetOptions& targets() const { return m_Targets; }
+ TargetOptions& targets() { return m_Targets; }
+
const BitcodeOption& bitcode() const { return m_Bitcode; }
BitcodeOption& bitcode() { return m_Bitcode; }
@@ -65,22 +70,16 @@
void setCodeGenType(CodeGenType pType) { m_CodeGenType = pType; }
- const llvm::Triple& triple() const { return m_Triple; }
-
- void setTriple(const std::string& pTriple);
-
- void setTriple(const llvm::Triple& pTriple);
-
static const char* version();
private:
// ----- General Options ----- //
GeneralOptions m_Options;
ScriptOptions m_Scripts;
+ TargetOptions m_Targets;
BitcodeOption m_Bitcode;
AttributeOption m_Attribute;
- llvm::Triple m_Triple;
CodeGenType m_CodeGenType;
};
diff --git a/include/mcld/Object/ObjectLinker.h b/include/mcld/Object/ObjectLinker.h
index 4d9f642..515bc58 100644
--- a/include/mcld/Object/ObjectLinker.h
+++ b/include/mcld/Object/ObjectLinker.h
@@ -22,7 +22,7 @@
class Module;
class LinkerConfig;
-class InputBuilder;
+class IRBuilder;
class FragmentLinker;
class TargetLDBackend;
class MemoryArea;
@@ -31,9 +31,11 @@
class DynObjReader;
class ArchiveReader;
class GroupReader;
+class BinaryReader;
class ObjectWriter;
class DynObjWriter;
class ExecWriter;
+class BinaryWriter;
/** \class ObjectLinker
* \brief ObjectLinker prepares parameters for FragmentLinker.
@@ -43,7 +45,7 @@
public:
ObjectLinker(const LinkerConfig& pConfig,
Module& pModule,
- InputBuilder& pInputBuilder,
+ IRBuilder& pBuilder,
TargetLDBackend& pLDBackend);
~ObjectLinker();
@@ -132,8 +134,11 @@
const ArchiveReader* getArchiveReader() const { return m_pArchiveReader; }
ArchiveReader* getArchiveReader() { return m_pArchiveReader; }
- const GroupReader* getGroupReader() const { return m_pGroupReader; }
- GroupReader* getGroupReader() { return m_pGroupReader; }
+ const GroupReader* getGroupReader () const { return m_pGroupReader; }
+ GroupReader* getGroupReader () { return m_pGroupReader; }
+
+ const BinaryReader* getBinaryReader () const { return m_pBinaryReader; }
+ BinaryReader* getBinaryReader () { return m_pBinaryReader; }
const ObjectWriter* getObjectWriter () const { return m_pObjectWriter; }
ObjectWriter* getObjectWriter () { return m_pObjectWriter; }
@@ -144,24 +149,28 @@
const ExecWriter* getExecWriter () const { return m_pExecWriter; }
ExecWriter* getExecWriter () { return m_pExecWriter; }
+ const BinaryWriter* getBinaryWriter () const { return m_pBinaryWriter; }
+ BinaryWriter* getBinaryWriter () { return m_pBinaryWriter; }
+
private:
const LinkerConfig& m_Config;
Module& m_Module;
- // we pass in InputBuilder for Archive and GroupReader.
- InputBuilder& m_InputBuilder;
+ IRBuilder& m_Builder;
FragmentLinker* m_pLinker;
TargetLDBackend &m_LDBackend;
// ----- readers and writers ----- //
- ObjectReader* m_pObjectReader;
- DynObjReader* m_pDynObjReader;
+ ObjectReader* m_pObjectReader;
+ DynObjReader* m_pDynObjReader;
ArchiveReader* m_pArchiveReader;
- ObjectWriter* m_pObjectWriter;
- DynObjWriter* m_pDynObjWriter;
- ExecWriter* m_pExecWriter;
- GroupReader* m_pGroupReader;
+ GroupReader* m_pGroupReader;
+ BinaryReader* m_pBinaryReader;
+ ObjectWriter* m_pObjectWriter;
+ DynObjWriter* m_pDynObjWriter;
+ ExecWriter* m_pExecWriter;
+ BinaryWriter* m_pBinaryWriter;
};
} // end namespace mcld
diff --git a/include/mcld/Support/CommandLine.h b/include/mcld/Support/CommandLine.h
index 6a90309..2bb9904 100644
--- a/include/mcld/Support/CommandLine.h
+++ b/include/mcld/Support/CommandLine.h
@@ -11,18 +11,42 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/ADT/StringRef.h>
-#include <llvm/Support/CommandLine.h>
#include <mcld/Support/FileSystem.h>
-#include <mcld/MC/MCLDDirectory.h>
#include <mcld/MC/ZOption.h>
-//--------------------------------------------------
-// parser<mcld::sys::fs::Path>
-//
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/CommandLine.h>
+
+#include <string>
+
namespace llvm {
namespace cl {
+//===----------------------------------------------------------------------===//
+// SearchDirParser
+//===----------------------------------------------------------------------===//
+class SearchDirParser : public llvm::cl::basic_parser<std::string>
+{
+public:
+ // parse - Return true on error.
+ bool parse(Option &pOption,
+ StringRef pArgName,
+ StringRef pArg,
+ std::string &pValue);
+
+ const char *getValueName() const { return "searchdir"; }
+
+ void printOptionDiff(const Option &pOption,
+ StringRef pValue,
+ OptVal pDefault,
+ size_t pGlobalWidth) const;
+
+ void anchor();
+};
+
+//===----------------------------------------------------------------------===//
+// parser<mcld::sys::fs::Path>
+//===----------------------------------------------------------------------===//
template<>
class parser<mcld::sys::fs::Path> : public basic_parser<mcld::sys::fs::Path>
{
@@ -40,26 +64,9 @@
virtual void anchor();
};
-//--------------------------------------------------
-// parser<mcld::MCLDDirectory>
-//
-template<>
-class parser<mcld::MCLDDirectory> : public llvm::cl::basic_parser<mcld::MCLDDirectory>
-{
-public:
- bool parse(Option &O, StringRef ArgName, StringRef Arg, mcld::MCLDDirectory &Val);
-
- virtual const char *getValueName() const { return "directory"; }
- void printOptionDiff(const Option &O,
- const mcld::MCLDDirectory &V,
- OptVal Default,
- size_t GlobalWidth) const;
- virtual void anchor();
-};
-
-//--------------------------------------------------
+//===----------------------------------------------------------------------===//
// parser<mcld::ZOption>
-//
+//===----------------------------------------------------------------------===//
template<>
class parser<mcld::ZOption> : public llvm::cl::basic_parser<mcld::ZOption>
{
diff --git a/include/mcld/Support/GCFactoryListTraits.h b/include/mcld/Support/GCFactoryListTraits.h
index 8a768c8..986f6f6 100644
--- a/include/mcld/Support/GCFactoryListTraits.h
+++ b/include/mcld/Support/GCFactoryListTraits.h
@@ -17,8 +17,7 @@
#include <assert.h>
-namespace mcld
-{
+namespace mcld {
/** \class GCFactoryListTraits
* \brief GCFactoryListTraits provides trait class for llvm::iplist when
diff --git a/include/mcld/Target/ELFDynamic.h b/include/mcld/Target/ELFDynamic.h
index 2298bfd..7102226 100644
--- a/include/mcld/Target/ELFDynamic.h
+++ b/include/mcld/Target/ELFDynamic.h
@@ -17,11 +17,10 @@
#include <vector>
#include <cstring>
-namespace mcld
-{
+namespace mcld {
-class GNULDBackend;
class ELFFileFormat;
+class GNULDBackend;
class LinkerConfig;
class MemoryRegion;
@@ -105,7 +104,7 @@
typedef EntryListType::const_iterator const_iterator;
public:
- ELFDynamic(const GNULDBackend& pParent);
+ ELFDynamic(const GNULDBackend& pBackend, const LinkerConfig& pConfig);
virtual ~ELFDynamic();
@@ -116,29 +115,21 @@
size_t numOfBytes() const;
/// reserveEntries - reserve entries
- void reserveEntries(const LinkerConfig& pConfig,
- const ELFFileFormat& pFormat);
+ void reserveEntries(const ELFFileFormat& pFormat);
/// reserveNeedEntry - reserve on DT_NEED entry.
void reserveNeedEntry();
/// applyEntries - apply entries
- void applyEntries(const LinkerConfig& pConfig,
- const ELFFileFormat& pFormat);
+ void applyEntries(const ELFFileFormat& pFormat);
void applySoname(uint64_t pStrTabIdx);
- iterator needBegin()
- { return m_NeedList.begin(); }
+ const_iterator needBegin() const { return m_NeedList.begin(); }
+ iterator needBegin() { return m_NeedList.begin(); }
- iterator needEnd()
- { return m_NeedList.end(); }
-
- const_iterator needBegin() const
- { return m_NeedList.begin(); }
-
- const_iterator needEnd() const
- { return m_NeedList.end(); }
+ const_iterator needEnd() const { return m_NeedList.end(); }
+ iterator needEnd() { return m_NeedList.end(); }
/// emit
void emit(const LDSection& pSection, MemoryRegion& pRegion) const;
@@ -162,6 +153,7 @@
EntryListType m_NeedList;
elf_dynamic::EntryIF* m_pEntryFactory;
const GNULDBackend& m_Backend;
+ const LinkerConfig& m_Config;
// The entry reserved and the entry being applied are not must matched.
// For better performance, we use a simple counter and apply entry one-by-one
diff --git a/include/mcld/Target/GNUInfo.h b/include/mcld/Target/GNUInfo.h
new file mode 100644
index 0000000..f918431
--- /dev/null
+++ b/include/mcld/Target/GNUInfo.h
@@ -0,0 +1,48 @@
+//===- GNUInfo.h ----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_GNU_INFO_H
+#define MCLD_TARGET_GNU_INFO_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/ADT/Triple.h>
+#include <llvm/Support/ELF.h>
+
+namespace mcld {
+
+/** \class GNUInfo
+ * \brief GNUInfo records ELF-dependent and target-dependnet data fields
+ */
+class GNUInfo
+{
+public:
+ GNUInfo(const llvm::Triple& pTriple);
+
+ virtual ~GNUInfo() { }
+
+ /// ELFVersion - the value of e_ident[EI_VERSION]
+ virtual uint8_t ELFVersion() const { return llvm::ELF::EV_CURRENT; }
+
+ /// The return value of machine() it the same as e_machine in the ELF header
+ virtual uint32_t machine() const = 0;
+
+ /// OSABI - the value of e_ident[EI_OSABI]
+ uint8_t OSABI() const;
+
+ /// ABIVersion - the value of e_ident[EI_ABIVRESION]
+ uint8_t ABIVersion() const { return 0x0; }
+
+private:
+ const llvm::Triple& m_Triple;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Target/GNULDBackend.h b/include/mcld/Target/GNULDBackend.h
index 4623e33..d20b8ac 100644
--- a/include/mcld/Target/GNULDBackend.h
+++ b/include/mcld/Target/GNULDBackend.h
@@ -22,12 +22,15 @@
#include <mcld/LD/GNUArchiveReader.h>
#include <mcld/LD/ELFObjectReader.h>
#include <mcld/LD/ELFDynObjReader.h>
+#include <mcld/LD/ELFBinaryReader.h>
#include <mcld/LD/ELFDynObjWriter.h>
#include <mcld/LD/ELFExecWriter.h>
#include <mcld/LD/ELFObjectWriter.h>
+#include <mcld/LD/ELFBinaryWriter.h>
#include <mcld/LD/ELFSegment.h>
#include <mcld/LD/ELFSegmentFactory.h>
#include <mcld/Target/ELFDynamic.h>
+#include <mcld/Target/GNUInfo.h>
#include <mcld/Support/GCFactory.h>
#include <mcld/Module.h>
@@ -36,11 +39,13 @@
class Module;
class LinkerConfig;
+class IRBuilder;
class Layout;
class EhFrame;
class EhFrameHdr;
class BranchIslandFactory;
class StubFactory;
+class GNUInfo;
/** \class GNULDBackend
* \brief GNULDBackend provides a common interface for all GNU Unix-OS
@@ -49,18 +54,20 @@
class GNULDBackend : public TargetLDBackend
{
protected:
- GNULDBackend(const LinkerConfig& pConfig);
+ GNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
public:
virtual ~GNULDBackend();
// ----- readers/writers ----- //
GNUArchiveReader* createArchiveReader(Module& pModule);
- ELFObjectReader* createObjectReader(FragmentLinker& pLinker);
- ELFDynObjReader* createDynObjReader(FragmentLinker& pLinker);
- ELFObjectWriter* createObjectWriter(FragmentLinker& pLinker);
- ELFDynObjWriter* createDynObjWriter(FragmentLinker& pLinker);
- ELFExecWriter* createExecWriter(FragmentLinker& pLinker);
+ ELFObjectReader* createObjectReader(IRBuilder& pBuilder);
+ ELFDynObjReader* createDynObjReader(IRBuilder& pBuilder);
+ ELFBinaryReader* createBinaryReader(IRBuilder& pBuilder);
+ ELFObjectWriter* createObjectWriter();
+ ELFDynObjWriter* createDynObjWriter();
+ ELFExecWriter* createExecWriter();
+ ELFBinaryWriter* createBinaryWriter();
// ----- output sections ----- //
/// initStdSections - initialize standard sections of the output file.
@@ -100,18 +107,8 @@
size_t sectionStartOffset() const;
- /// The return value of machine() it the same as e_machine in the ELF header*/
- virtual uint32_t machine() const = 0;
-
- /// ELFVersion - the value of e_ident[EI_VERSION]
- virtual uint8_t ELFVersion() const
- { return llvm::ELF::EV_CURRENT; }
-
- /// OSABI - the value of e_ident[EI_OSABI]
- virtual uint8_t OSABI() const = 0;
-
- /// ABIVersion - the value of e_ident[EI_ABIVRESION]
- virtual uint8_t ABIVersion() const = 0;
+ const GNUInfo& getInfo() const { return *m_pInfo; }
+ GNUInfo& getInfo() { return *m_pInfo; }
/// flags - the value of ElfXX_Ehdr::e_flags
virtual uint64_t flags() const = 0;
@@ -364,6 +361,9 @@
Module::iterator pSectBegin,
Module::iterator pSectEnd);
+ /// layout - layout method
+ void layout(Module& pModule, FragmentLinker& pLinker);
+
/// preLayout - Backend can do any needed modification before layout
void preLayout(Module& pModule, FragmentLinker& pLinker);
@@ -436,6 +436,14 @@
SHO_STRTAB // .strtab
};
+ typedef std::pair<LDSection*, unsigned int> SHOEntry;
+
+ struct SHOCompare
+ {
+ bool operator()(const SHOEntry& X, const SHOEntry& Y) const
+ { return X.second < Y.second; }
+ };
+
struct SymCompare
{
bool operator()(const LDSymbol* X, const LDSymbol* Y) const
@@ -465,6 +473,9 @@
ELFExecFileFormat* m_pExecFileFormat;
ELFObjectFileFormat* m_pObjectFileFormat;
+ // GNUInfo
+ GNUInfo* m_pInfo;
+
// ELF segment factory
ELFSegmentFactory m_ELFSegmentTable;
diff --git a/include/mcld/Target/GOT.h b/include/mcld/Target/GOT.h
index 6dfa9b1..732e98f 100644
--- a/include/mcld/Target/GOT.h
+++ b/include/mcld/Target/GOT.h
@@ -28,41 +28,44 @@
class GOT
{
protected:
- GOT(LDSection& pSection, size_t pEntrySize);
+ GOT(LDSection& pSection);
public:
typedef SectionData::iterator iterator;
typedef SectionData::const_iterator const_iterator;
+ template<size_t SIZE>
class Entry : public TargetFragment
{
public:
- Entry(uint64_t pContent, size_t pEntrySize, SectionData* pParent);
+ enum { EntrySize = SIZE };
- virtual ~Entry();
+ public:
+ Entry(uint64_t pValue, SectionData* pParent)
+ : TargetFragment(Fragment::Target, pParent),
+ f_Value(pValue) {
+ }
- uint64_t getContent() const
- { return f_Content; }
+ virtual ~Entry() {}
- void setContent(uint64_t pValue)
- { f_Content = pValue; }
+ uint64_t getValue() const
+ { return f_Value; }
+
+ void setValue(uint64_t pValue)
+ { f_Value = pValue; }
// Override pure virtual function
size_t size() const
- { return m_EntrySize; }
+ { return EntrySize; }
protected:
- uint64_t f_Content;
- size_t m_EntrySize;
+ uint64_t f_Value;
};
public:
virtual ~GOT();
// ----- observers -----//
- /// entrySize - the number of bytes per entry
- size_t getEntrySize() const;
-
uint64_t addr() const { return m_Section.addr(); }
const_iterator begin() const { return m_SectionData->begin(); }
@@ -81,17 +84,11 @@
/// needed. If an entry is needed, the empty entry is reserved for layout
/// to adjust the fragment offset. After that, we fill up the entries when
/// applying relocations.
- virtual void reserve(size_t pNum = 1);
-
- /// consume - consume and return an empty entry
- virtual Entry* consume();
+ virtual void reserve(size_t pNum = 1) = 0;
protected:
LDSection& m_Section;
SectionData* m_SectionData;
- size_t f_EntrySize;
-
- Entry* m_pLast; ///< the last consumed entry
};
} // namespace of mcld
diff --git a/include/mcld/Target/OutputRelocSection.h b/include/mcld/Target/OutputRelocSection.h
index ace0c71..b0f8f2d 100644
--- a/include/mcld/Target/OutputRelocSection.h
+++ b/include/mcld/Target/OutputRelocSection.h
@@ -28,18 +28,14 @@
class OutputRelocSection
{
public:
- OutputRelocSection(Module& pModule,
- LDSection& pSection,
- unsigned int pEntrySize);
+ OutputRelocSection(Module& pModule, LDSection& pSection);
~OutputRelocSection();
- void reserveEntry(RelocationFactory& pRelFactory, size_t pNum=1);
+ void reserveEntry(size_t pNum=1);
Relocation* consumeEntry();
- void finalizeSectionSize();
-
/// addSymbolToDynSym - add local symbol to TLS category so that it'll be
/// emitted into .dynsym
bool addSymbolToDynSym(LDSymbol& pSymbol);
@@ -48,27 +44,23 @@
bool empty()
{ return m_pRelocData->empty(); }
+ size_t numOfRelocs();
+
private:
- typedef RelocData::iterator FragmentIterator;
+ typedef RelocData::iterator RelocIterator;
private:
Module& m_Module;
- /// m_pSection - LDSection of this Section
- LDSection* m_pSection;
-
/// m_RelocData - the output RelocData which contains the dynamic
/// relocations
RelocData* m_pRelocData;
- /// m_EntryBytes - size of a relocation entry
- unsigned int m_EntryBytes;
-
/// m_isVisit - First time visit the function getEntry() or not
bool m_isVisit;
/// m_ValidEntryIterator - point to the first valid entry
- FragmentIterator m_ValidEntryIterator;
+ RelocIterator m_ValidEntryIterator;
};
} // namespace of mcld
diff --git a/include/mcld/Target/PLT.h b/include/mcld/Target/PLT.h
index bd5936a..5d91446 100644
--- a/include/mcld/Target/PLT.h
+++ b/include/mcld/Target/PLT.h
@@ -21,6 +21,35 @@
class LDSection;
class ResolveInfo;
+/** \class PLTEntryDefaultBase
+ * \brief PLTEntryDefaultBase provides the default interface for PLE Entry
+ */
+class PLTEntryBase : public TargetFragment
+{
+public:
+ PLTEntryBase(SectionData& pParent)
+ : TargetFragment(Fragment::Target, &pParent), m_pValue(NULL)
+ {}
+
+ virtual ~PLTEntryBase()
+ {
+ delete m_pValue;
+ }
+
+ void setValue(unsigned char* pValue)
+ { m_pValue = pValue; }
+
+ const unsigned char* getValue() const
+ { return m_pValue; }
+
+ //Used by llvm::cast<>.
+ static bool classof(const Fragment *O)
+ { return true; }
+
+protected:
+ unsigned char* m_pValue;
+};
+
/** \class PLT
* \brief Procedure linkage table
*/
@@ -30,31 +59,21 @@
typedef SectionData::iterator iterator;
typedef SectionData::const_iterator const_iterator;
- class Entry : public TargetFragment
+ template<size_t SIZE, typename EntryBase = PLTEntryBase>
+ class Entry : public EntryBase
{
public:
- Entry(size_t pSize, SectionData& pParent);
- virtual ~Entry();
+ enum { EntrySize = SIZE };
- size_t getEntrySize() const
- { return m_EntrySize; }
+ public:
+ Entry(SectionData& pParent)
+ : EntryBase(pParent)
+ {}
- void setContent(unsigned char* pContent)
- { m_pContent = pContent; }
-
- const unsigned char* getContent() const
- { return m_pContent; }
-
- //Used by llvm::cast<>.
- static bool classof(const Fragment *O)
- { return true; }
+ virtual ~Entry() {}
size_t size() const
- { return m_EntrySize; }
-
- protected:
- size_t m_EntrySize;
- unsigned char* m_pContent;
+ { return EntrySize; }
};
public:
diff --git a/include/mcld/Target/TargetLDBackend.h b/include/mcld/Target/TargetLDBackend.h
index c18bc79..10cf280 100644
--- a/include/mcld/Target/TargetLDBackend.h
+++ b/include/mcld/Target/TargetLDBackend.h
@@ -15,16 +15,20 @@
class Module;
class LinkerConfig;
+class IRBuilder;
class FragmentLinker;
class Relocation;
class RelocationFactory;
+class Relocator;
class Layout;
class ArchiveReader;
class ObjectReader;
class DynObjReader;
+class BinaryReader;
class ObjectWriter;
class DynObjWriter;
class ExecWriter;
+class BinaryWriter;
class LDFileFormat;
class LDSymbol;
class LDSection;
@@ -57,9 +61,10 @@
virtual void initTargetSymbols(FragmentLinker& pLinker) { }
virtual void initTargetRelocation(FragmentLinker& pLinker) { }
virtual bool initStandardSymbols(FragmentLinker& pLinker, Module& pModule) = 0;
- virtual bool initRelocFactory(const FragmentLinker& pLinker) = 0;
- virtual RelocationFactory* getRelocFactory() = 0;
+ virtual bool initRelocator(const FragmentLinker& pLinker) = 0;
+
+ virtual Relocator* getRelocator() = 0;
/// scanRelocation - When read in relocations, backend can do any modification
/// to relocation and generate empty entries, such as GOT, dynamic relocation
@@ -86,14 +91,19 @@
// ----- format dependent ----- //
virtual ArchiveReader* createArchiveReader(Module&) = 0;
- virtual ObjectReader* createObjectReader(FragmentLinker&) = 0;
- virtual DynObjReader* createDynObjReader(FragmentLinker&) = 0;
- virtual ObjectWriter* createObjectWriter(FragmentLinker&) = 0;
- virtual DynObjWriter* createDynObjWriter(FragmentLinker&) = 0;
- virtual ExecWriter* createExecWriter(FragmentLinker&) = 0;
+ virtual ObjectReader* createObjectReader(IRBuilder&) = 0;
+ virtual DynObjReader* createDynObjReader(IRBuilder&) = 0;
+ virtual BinaryReader* createBinaryReader(IRBuilder&) = 0;
+ virtual ObjectWriter* createObjectWriter() = 0;
+ virtual DynObjWriter* createDynObjWriter() = 0;
+ virtual ExecWriter* createExecWriter() = 0;
+ virtual BinaryWriter* createBinaryWriter() = 0;
virtual bool initStdSections(ObjectBuilder& pBuilder) = 0;
+ /// layout - layout method
+ virtual void layout(Module& pModule, FragmentLinker& pLinker) = 0;
+
/// preLayout - Backend can do any needed modification before layout
virtual void preLayout(Module& pModule, FragmentLinker& pLinker) = 0;
@@ -104,12 +114,6 @@
virtual void postProcessing(FragmentLinker& pLinker,
MemoryArea& pOutput) = 0;
- /// Is the target machine little endian? **/
- virtual bool isLittleEndian() const = 0;
-
- /// bit class. the bit length of the target machine, 32 or 64 **/
- virtual unsigned int bitclass() const = 0;
-
/// the common page size of the target machine
virtual uint64_t commonPageSize() const = 0;
diff --git a/include/mcld/Target/TargetMachine.h b/include/mcld/Target/TargetMachine.h
index 1b167ab..1c2ad99 100644
--- a/include/mcld/Target/TargetMachine.h
+++ b/include/mcld/Target/TargetMachine.h
@@ -39,6 +39,7 @@
CGFT_DSOFile,
CGFT_EXEFile,
CGFT_PARTIAL,
+ CGFT_BINARY,
CGFT_NULLFile
};
diff --git a/include/mcld/TargetOptions.h b/include/mcld/TargetOptions.h
new file mode 100644
index 0000000..21f65cf
--- /dev/null
+++ b/include/mcld/TargetOptions.h
@@ -0,0 +1,71 @@
+//===- TargetOptions.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_OPTIONS_H
+#define MCLD_TARGET_OPTIONS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/ADT/Triple.h>
+
+#include <string>
+
+namespace mcld {
+
+/** \class TargetOptions
+ * \brief TargetOptions collects the options that dependent on a target
+ * backend.
+ */
+class TargetOptions
+{
+public:
+ enum Endian {
+ Little,
+ Big,
+ Unknown
+ };
+
+public:
+ TargetOptions();
+
+ TargetOptions(const std::string& pTriple);
+
+ ~TargetOptions();
+
+ const llvm::Triple& triple() const { return m_Triple; }
+
+ void setTriple(const std::string& pTriple);
+
+ void setTriple(const llvm::Triple& pTriple);
+
+ Endian endian() const { return m_Endian; }
+
+ void setEndian(Endian pEndian) { m_Endian = pEndian; }
+
+ bool isLittleEndian() const { return (Little == m_Endian); }
+ bool isBigEndian () const { return (Big == m_Endian); }
+
+ unsigned int bitclass() const { return m_BitClass; }
+
+ void setBitClass(unsigned int pBitClass) { m_BitClass = pBitClass; }
+
+ bool is32Bits() const { return (32 == m_BitClass); }
+ bool is64Bits() const { return (64 == m_BitClass); }
+
+private:
+ llvm::Triple m_Triple;
+ Endian m_Endian;
+ unsigned int m_BitClass;
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/CodeGen/MCLDTargetMachine.cpp b/lib/CodeGen/MCLDTargetMachine.cpp
index e0eeb63..1a2cfff 100644
--- a/lib/CodeGen/MCLDTargetMachine.cpp
+++ b/lib/CodeGen/MCLDTargetMachine.cpp
@@ -241,6 +241,16 @@
return true;
break;
}
+ case CGFT_BINARY: {
+ pConfig.setCodeGenType(LinkerConfig::Binary);
+ if (addLinkerPasses(pPM,
+ pConfig,
+ pModule,
+ pOutput.memory(),
+ Context))
+ return true;
+ break;
+ }
case CGFT_DSOFile: {
pConfig.setCodeGenType(LinkerConfig::DynObj);
if (addLinkerPasses(pPM,
diff --git a/lib/Core/Android.mk b/lib/Core/Android.mk
index c30d80c..2fd5781 100644
--- a/lib/Core/Android.mk
+++ b/lib/Core/Android.mk
@@ -10,7 +10,8 @@
LinkerConfig.cpp \
Linker.cpp \
Module.cpp \
- ScriptOptions.cpp
+ ScriptOptions.cpp \
+ TargetOptions.cpp
# For the host
# =====================================================
diff --git a/lib/Core/Environment.cpp b/lib/Core/Environment.cpp
index 5755fe7..0aa7536 100644
--- a/lib/Core/Environment.cpp
+++ b/lib/Core/Environment.cpp
@@ -9,6 +9,8 @@
#include <mcld/Environment.h>
#include <mcld/Support/TargetSelect.h>
+#include <llvm/Support/TargetSelect.h>
+
void mcld::Initialize()
{
static bool is_initialized = false;
@@ -16,6 +18,7 @@
if (is_initialized)
return;
+ llvm::InitializeAllTargets();
mcld::InitializeAllTargets();
mcld::InitializeAllEmulations();
mcld::InitializeAllDiagnostics();
diff --git a/lib/Core/GeneralOptions.cpp b/lib/Core/GeneralOptions.cpp
index 902f753..d762237 100644
--- a/lib/Core/GeneralOptions.cpp
+++ b/lib/Core/GeneralOptions.cpp
@@ -43,11 +43,14 @@
m_bColor(true),
m_bAllowShlibUndefined(true),
m_bCreateEhFrameHdr(false),
- m_NMagic(false),
- m_OMagic(false),
- m_StripDebug(false),
- m_ExportDynamic(false),
- m_WarnSharedTextrel(false)
+ m_bNMagic(false),
+ m_bOMagic(false),
+ m_bStripDebug(false),
+ m_bExportDynamic(false),
+ m_bWarnSharedTextrel(false),
+ m_bBinaryInput(false),
+ m_bDefineCommon(false),
+ m_bFatalWarnings(false)
{
}
diff --git a/lib/Core/IRBuilder.cpp b/lib/Core/IRBuilder.cpp
index 58c1360..5472db0 100644
--- a/lib/Core/IRBuilder.cpp
+++ b/lib/Core/IRBuilder.cpp
@@ -13,6 +13,7 @@
#include <mcld/LD/EhFrame.h>
#include <mcld/LD/RelocData.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/Fragment/FragmentRef.h>
using namespace mcld;
@@ -82,6 +83,22 @@
return LDFileFormat::MetaData;
}
+bool shouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig)
+{
+ // 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 (LinkerConfig::Object != pConfig.codeGenType() &&
+ (pInfo.visibility() == ResolveInfo::Hidden ||
+ pInfo.visibility() == ResolveInfo::Internal) &&
+ (pInfo.isGlobal() || pInfo.isWeak()) &&
+ (pInfo.isDefine() || pInfo.isCommon()))
+ return true;
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// IRBuilder
//===----------------------------------------------------------------------===//
@@ -382,7 +399,7 @@
/// AppendRelocation - To append an relocation to the given RelocData pRD.
void IRBuilder::AppendRelocation(Relocation& pRelocation, RelocData& pRD)
{
- pRD.getFragmentList().push_back(&pRelocation);
+ pRD.append(pRelocation);
}
/// AppendEhFrame - To append a fragment to EhFrame.
@@ -411,3 +428,249 @@
return pCIE.size();
}
+/// AddSymbol - To add a symbol in the input file and resolve the symbol
+/// immediately
+LDSymbol* IRBuilder::AddSymbol(Input& pInput,
+ const std::string& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBind,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ LDSection* pSection,
+ ResolveInfo::Visibility pVis)
+{
+ // rename symbols
+ std::string name = pName;
+ if (!m_Config.scripts().renameMap().empty() &&
+ ResolveInfo::Undefined == pDesc) {
+ // If the renameMap is not empty, some symbols should be renamed.
+ // --wrap and --portable defines the symbol rename map.
+ ScriptOptions::SymbolRenameMap::const_iterator renameSym =
+ m_Config.scripts().renameMap().find(pName);
+ if (renameSym != m_Config.scripts().renameMap().end())
+ name = renameSym.getEntry()->value();
+ }
+
+ switch (pInput.type()) {
+ case Input::Object: {
+
+ FragmentRef* frag = NULL;
+ if (NULL == pSection ||
+ ResolveInfo::Undefined == pDesc ||
+ ResolveInfo::Common == pDesc ||
+ ResolveInfo::Absolute == pBind ||
+ LDFileFormat::Ignore == pSection->kind() ||
+ LDFileFormat::Group == pSection->kind())
+ frag = FragmentRef::Null();
+ else
+ frag = FragmentRef::Create(*pSection, pValue);
+
+ LDSymbol* input_sym = addSymbolFromObject(name, pType, pDesc, pBind, pSize, pValue, frag, pVis);
+ pInput.context()->addSymbol(input_sym);
+ return input_sym;
+ }
+ case Input::DynObj: {
+ return addSymbolFromDynObj(name, pType, pDesc, pBind, pSize, pValue, pVis);
+ }
+ default: {
+ return NULL;
+ break;
+ }
+ }
+}
+
+LDSymbol* IRBuilder::addSymbolFromObject(const std::string& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
+{
+ // Step 1. calculate a Resolver::Result
+ // resolved_result is a triple <resolved_info, existent, override>
+ Resolver::Result resolved_result;
+ ResolveInfo old_info; // used for arrange output symbols
+
+ if (pBinding == ResolveInfo::Local) {
+ // if the symbol is a local symbol, create a LDSymbol for input, but do not
+ // resolve them.
+ resolved_result.info = m_Module.getNamePool().createSymbol(pName,
+ false,
+ pType,
+ pDesc,
+ pBinding,
+ pSize,
+ pVisibility);
+
+ // No matter if there is a symbol with the same name, insert the symbol
+ // into output symbol table. So, we let the existent false.
+ resolved_result.existent = false;
+ resolved_result.overriden = true;
+ }
+ else {
+ // if the symbol is not local, insert and resolve it immediately
+ m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
+ pSize, pVisibility,
+ &old_info, resolved_result);
+ }
+
+ // the return ResolveInfo should not NULL
+ assert(NULL != resolved_result.info);
+
+ /// Step 2. create an input LDSymbol.
+ // create a LDSymbol for the input file.
+ LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
+ input_sym->setFragmentRef(pFragmentRef);
+ input_sym->setValue(pValue);
+
+ // Step 3. Set up corresponding output LDSymbol
+ LDSymbol* output_sym = resolved_result.info->outSymbol();
+ bool has_output_sym = (NULL != output_sym);
+ if (!resolved_result.existent || !has_output_sym) {
+ // it is a new symbol, the output_sym should be NULL.
+ assert(NULL == output_sym);
+
+ if (pType == ResolveInfo::Section) {
+ // if it is a section symbol, its output LDSymbol is the input LDSymbol.
+ output_sym = input_sym;
+ }
+ else {
+ // if it is a new symbol, create a LDSymbol for the output
+ output_sym = LDSymbol::Create(*resolved_result.info);
+ }
+ resolved_result.info->setSymPtr(output_sym);
+ }
+
+ if (resolved_result.overriden || !has_output_sym) {
+ // symbol can be overriden only if it exists.
+ assert(output_sym != NULL);
+
+ // should override output LDSymbol
+ output_sym->setFragmentRef(pFragmentRef);
+ output_sym->setValue(pValue);
+ }
+
+ // Step 4. Adjust the position of output LDSymbol.
+ // After symbol resolution, visibility is changed to the most restrict one.
+ // we need to arrange its position in the output symbol. We arrange the
+ // positions by sorting symbols in SymbolCategory.
+ if (pType != ResolveInfo::Section) {
+ if (!has_output_sym) {
+ // We merge sections when reading them. So we do not need to output symbols
+ // with section type
+
+ // No matter the symbol is already in the output or not, add it if it
+ // should be forcefully set local.
+ if (shouldForceLocal(*resolved_result.info, m_Config))
+ m_Module.getSymbolTable().forceLocal(*output_sym);
+ else {
+ // the symbol should not be forcefully local.
+ m_Module.getSymbolTable().add(*output_sym);
+ }
+ }
+ else if (resolved_result.overriden) {
+ if (!shouldForceLocal(old_info, m_Config) ||
+ !shouldForceLocal(*resolved_result.info, m_Config)) {
+ // If the old info and the new info are both forcefully local, then
+ // we should keep the output_sym in forcefully local category. Else,
+ // we should re-sort the output_sym
+ m_Module.getSymbolTable().arrange(*output_sym, old_info);
+ }
+ }
+ }
+
+ return input_sym;
+}
+
+LDSymbol* IRBuilder::addSymbolFromDynObj(const std::string& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ ResolveInfo::Visibility pVisibility)
+{
+ // We don't need sections of dynamic objects. So we ignore section symbols.
+ if (pType == ResolveInfo::Section)
+ return NULL;
+
+ // ignore symbols with local binding or that have internal or hidden
+ // visibility
+ if (pBinding == ResolveInfo::Local ||
+ pVisibility == ResolveInfo::Internal ||
+ pVisibility == ResolveInfo::Hidden)
+ return NULL;
+
+ // A protected symbol in a shared library must be treated as a
+ // normal symbol when viewed from outside the shared library.
+ if (pVisibility == ResolveInfo::Protected)
+ pVisibility = ResolveInfo::Default;
+
+ // insert symbol and resolve it immediately
+ // resolved_result is a triple <resolved_info, existent, override>
+ Resolver::Result resolved_result;
+ m_Module.getNamePool().insertSymbol(pName, true, pType, pDesc,
+ pBinding, pSize, pVisibility,
+ NULL, resolved_result);
+
+ // the return ResolveInfo should not NULL
+ assert(NULL != resolved_result.info);
+
+ // create a LDSymbol for the input file.
+ LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
+ input_sym->setFragmentRef(FragmentRef::Null());
+ input_sym->setValue(pValue);
+
+ LDSymbol* output_sym = NULL;
+ if (!resolved_result.existent) {
+ // we get a new symbol, leave it as NULL
+ resolved_result.info->setSymPtr(NULL);
+ }
+ else {
+ // we saw the symbol before, but the output_sym still may be NULL.
+ output_sym = resolved_result.info->outSymbol();
+ }
+
+ if (output_sym != NULL) {
+ // After symbol resolution, visibility is changed to the most restrict one.
+ // If we are not doing incremental linking, then any symbol with hidden
+ // or internal visibility is forcefully set as a local symbol.
+ if (shouldForceLocal(*resolved_result.info, m_Config)) {
+ m_Module.getSymbolTable().forceLocal(*output_sym);
+ }
+ }
+
+ return input_sym;
+}
+
+/// AddRelocation - add a relocation entry
+///
+/// All symbols should be read and resolved before calling this function.
+Relocation* IRBuilder::AddRelocation(LDSection& pSection,
+ Relocation::Type pType,
+ LDSymbol& pSym,
+ uint32_t pOffset,
+ Relocation::Address pAddend)
+{
+ // FIXME: we should dicard sections and symbols first instead
+ // if the symbol is in the discarded input section, then we also need to
+ // discard this relocation.
+ ResolveInfo* resolve_info = pSym.resolveInfo();
+ if (!pSym.hasFragRef() &&
+ ResolveInfo::Section == resolve_info->type() &&
+ ResolveInfo::Undefined == resolve_info->desc())
+ return NULL;
+
+ FragmentRef* frag_ref = FragmentRef::Create(*pSection.getLink(), pOffset);
+
+ Relocation* relocation = Relocation::Create(pType, *frag_ref, pAddend);
+
+ relocation->setSymInfo(resolve_info);
+ pSection.getRelocData()->append(*relocation);
+
+ return relocation;
+}
+
diff --git a/lib/Core/Linker.cpp b/lib/Core/Linker.cpp
index 7262537..9f6449e 100644
--- a/lib/Core/Linker.cpp
+++ b/lib/Core/Linker.cpp
@@ -22,6 +22,9 @@
#include <mcld/Target/TargetLDBackend.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/Fragment/Relocation.h>
#include <mcld/Fragment/FragmentRef.h>
#include <cassert>
@@ -64,7 +67,7 @@
m_pIRBuilder = &pBuilder;
m_pObjLinker = new ObjectLinker(*m_pConfig,
pModule,
- m_pIRBuilder->getInputBuilder(),
+ *m_pIRBuilder,
*m_pBackend);
// 2. - initialize FragmentLinker
@@ -203,6 +206,11 @@
m_pIRBuilder = NULL;
m_pTarget = NULL;
+ // Because llvm::iplist will touch the removed node, we must clear
+ // RelocData before deleting target backend.
+ RelocData::Clear();
+ SectionData::Clear();
+
delete m_pBackend;
m_pBackend = NULL;
@@ -212,6 +220,7 @@
LDSection::Clear();
LDSymbol::Clear();
FragmentRef::Clear();
+ Relocation::Clear();
return true;
}
@@ -220,9 +229,9 @@
assert(NULL != m_pConfig);
std::string error;
- m_pTarget = TargetRegistry::lookupTarget(m_pConfig->triple().str(), error);
+ m_pTarget = mcld::TargetRegistry::lookupTarget(m_pConfig->targets().triple().str(), error);
if (NULL == m_pTarget) {
- fatal(diag::fatal_cannot_init_target) << m_pConfig->triple().str() << error;
+ fatal(diag::fatal_cannot_init_target) << m_pConfig->targets().triple().str() << error;
return false;
}
return true;
@@ -233,7 +242,7 @@
assert(NULL != m_pTarget);
m_pBackend = m_pTarget->createLDBackend(*m_pConfig);
if (NULL == m_pBackend) {
- fatal(diag::fatal_cannot_init_backend) << m_pConfig->triple().str();
+ fatal(diag::fatal_cannot_init_backend) << m_pConfig->targets().triple().str();
return false;
}
return true;
@@ -242,7 +251,12 @@
bool Linker::initEmulator()
{
assert(NULL != m_pTarget && NULL != m_pConfig);
- return m_pTarget->emulate(m_pConfig->triple().str(), *m_pConfig);
+ bool result = m_pTarget->emulate(m_pConfig->targets().triple().str(),
+ *m_pConfig);
+
+ // Relocation should be set up after emulation.
+ Relocation::SetUp(*m_pConfig);
+ return result;
}
bool Linker::initOStream()
diff --git a/lib/Core/LinkerConfig.cpp b/lib/Core/LinkerConfig.cpp
index d94bbe2..cbdb7a7 100644
--- a/lib/Core/LinkerConfig.cpp
+++ b/lib/Core/LinkerConfig.cpp
@@ -19,9 +19,9 @@
LinkerConfig::LinkerConfig()
: m_Options(),
m_Scripts(),
+ m_Targets(),
m_Bitcode(),
m_Attribute(),
- m_Triple(),
m_CodeGenType(Unknown)
{
// FIXME: is here the right place to hold this?
@@ -31,9 +31,9 @@
LinkerConfig::LinkerConfig(const std::string& pTripleString)
: m_Options(),
m_Scripts(),
+ m_Targets(pTripleString),
m_Bitcode(),
m_Attribute(),
- m_Triple(pTripleString),
m_CodeGenType(Unknown)
{
// FIXME: is here the right place to hold this?
@@ -46,16 +46,6 @@
FinalizeDiagnosticEngine();
}
-void LinkerConfig::setTriple(const llvm::Triple& pTriple)
-{
- m_Triple = pTriple;
-}
-
-void LinkerConfig::setTriple(const std::string& pTriple)
-{
- m_Triple.setTriple(pTriple);
-}
-
const char* LinkerConfig::version()
{
return MCLD_VERSION;
diff --git a/lib/Core/TargetOptions.cpp b/lib/Core/TargetOptions.cpp
new file mode 100644
index 0000000..db723b6
--- /dev/null
+++ b/lib/Core/TargetOptions.cpp
@@ -0,0 +1,40 @@
+//===- TargetOptions.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/TargetOptions.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// TargetOptions
+//===----------------------------------------------------------------------===//
+TargetOptions::TargetOptions()
+ : m_Endian(Unknown),
+ m_BitClass(0) {
+}
+
+TargetOptions::TargetOptions(const std::string& pTriple)
+ : m_Triple(pTriple),
+ m_Endian(Unknown),
+ m_BitClass(0) {
+}
+
+TargetOptions::~TargetOptions()
+{
+}
+
+void TargetOptions::setTriple(const llvm::Triple& pTriple)
+{
+ m_Triple = pTriple;
+}
+
+void TargetOptions::setTriple(const std::string& pTriple)
+{
+ m_Triple.setTriple(pTriple);
+}
+
diff --git a/lib/Fragment/FragmentLinker.cpp b/lib/Fragment/FragmentLinker.cpp
index 4ad3d90..0398834 100644
--- a/lib/Fragment/FragmentLinker.cpp
+++ b/lib/Fragment/FragmentLinker.cpp
@@ -20,7 +20,6 @@
#include <mcld/Module.h>
#include <mcld/MC/MCLDInput.h>
#include <mcld/LD/BranchIslandFactory.h>
-#include <mcld/LD/Layout.h>
#include <mcld/LD/Resolver.h>
#include <mcld/LD/LDContext.h>
#include <mcld/LD/RelocationFactory.h>
@@ -31,9 +30,13 @@
#include <mcld/Support/FileHandle.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/Fragment/Relocation.h>
using namespace mcld;
+//===----------------------------------------------------------------------===//
+// FragmentLinker
+//===----------------------------------------------------------------------===//
/// Constructor
FragmentLinker::FragmentLinker(const LinkerConfig& pConfig,
Module& pModule,
@@ -52,178 +55,6 @@
//===----------------------------------------------------------------------===//
// Symbol Operations
//===----------------------------------------------------------------------===//
-/// addSymbolFromObject - add a symbol from object file and resolve it
-/// immediately
-LDSymbol* FragmentLinker::addSymbolFromObject(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
-
- // Step 1. calculate a Resolver::Result
- // resolved_result is a triple <resolved_info, existent, override>
- Resolver::Result resolved_result;
- ResolveInfo old_info; // used for arrange output symbols
-
- if (pBinding == ResolveInfo::Local) {
- // if the symbol is a local symbol, create a LDSymbol for input, but do not
- // resolve them.
- resolved_result.info = m_Module.getNamePool().createSymbol(pName,
- false,
- pType,
- pDesc,
- pBinding,
- pSize,
- pVisibility);
-
- // No matter if there is a symbol with the same name, insert the symbol
- // into output symbol table. So, we let the existent false.
- resolved_result.existent = false;
- resolved_result.overriden = true;
- }
- else {
- // if the symbol is not local, insert and resolve it immediately
- m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
- pSize, pVisibility,
- &old_info, resolved_result);
- }
-
- // the return ResolveInfo should not NULL
- assert(NULL != resolved_result.info);
-
- /// Step 2. create an input LDSymbol.
- // create a LDSymbol for the input file.
- LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
- input_sym->setFragmentRef(pFragmentRef);
- input_sym->setValue(pValue);
-
- // Step 3. Set up corresponding output LDSymbol
- LDSymbol* output_sym = resolved_result.info->outSymbol();
- bool has_output_sym = (NULL != output_sym);
- if (!resolved_result.existent || !has_output_sym) {
- // it is a new symbol, the output_sym should be NULL.
- assert(NULL == output_sym);
-
- if (pType == ResolveInfo::Section) {
- // if it is a section symbol, its output LDSymbol is the input LDSymbol.
- output_sym = input_sym;
- }
- else {
- // if it is a new symbol, create a LDSymbol for the output
- output_sym = LDSymbol::Create(*resolved_result.info);
- }
- resolved_result.info->setSymPtr(output_sym);
- }
-
- if (resolved_result.overriden || !has_output_sym) {
- // symbol can be overriden only if it exists.
- assert(output_sym != NULL);
-
- // should override output LDSymbol
- output_sym->setFragmentRef(pFragmentRef);
- output_sym->setValue(pValue);
- }
-
- // Step 4. Adjust the position of output LDSymbol.
- // After symbol resolution, visibility is changed to the most restrict one.
- // we need to arrange its position in the output symbol. We arrange the
- // positions by sorting symbols in SymbolCategory.
- if (pType != ResolveInfo::Section) {
- if (!has_output_sym) {
- // We merge sections when reading them. So we do not need to output symbols
- // with section type
-
- // No matter the symbol is already in the output or not, add it if it
- // should be forcefully set local.
- if (shouldForceLocal(*resolved_result.info))
- m_Module.getSymbolTable().forceLocal(*output_sym);
- else {
- // the symbol should not be forcefully local.
- m_Module.getSymbolTable().add(*output_sym);
- }
- }
- else if (resolved_result.overriden) {
- if (!shouldForceLocal(old_info) ||
- !shouldForceLocal(*resolved_result.info)) {
- // If the old info and the new info are both forcefully local, then
- // we should keep the output_sym in forcefully local category. Else,
- // we should re-sort the output_sym
- m_Module.getSymbolTable().arrange(*output_sym, old_info);
- }
- }
- }
-
- return input_sym;
-}
-
-/// addSymbolFromDynObj - add a symbol from object file and resolve it
-/// immediately
-LDSymbol* FragmentLinker::addSymbolFromDynObj(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
- // We don't need sections of dynamic objects. So we ignore section symbols.
- if (pType == ResolveInfo::Section)
- return NULL;
-
- // ignore symbols with local binding or that have internal or hidden
- // visibility
- if (pBinding == ResolveInfo::Local ||
- pVisibility == ResolveInfo::Internal ||
- pVisibility == ResolveInfo::Hidden)
- return NULL;
-
- // A protected symbol in a shared library must be treated as a
- // normal symbol when viewed from outside the shared library.
- if (pVisibility == ResolveInfo::Protected)
- pVisibility = ResolveInfo::Default;
-
- // insert symbol and resolve it immediately
- // resolved_result is a triple <resolved_info, existent, override>
- Resolver::Result resolved_result;
- m_Module.getNamePool().insertSymbol(pName, true, pType, pDesc,
- pBinding, pSize, pVisibility,
- NULL, resolved_result);
-
- // the return ResolveInfo should not NULL
- assert(NULL != resolved_result.info);
-
- // create a LDSymbol for the input file.
- LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
- input_sym->setFragmentRef(pFragmentRef);
- input_sym->setValue(pValue);
-
- LDSymbol* output_sym = NULL;
- if (!resolved_result.existent) {
- // we get a new symbol, leave it as NULL
- resolved_result.info->setSymPtr(NULL);
- }
- else {
- // we saw the symbol before, but the output_sym still may be NULL.
- output_sym = resolved_result.info->outSymbol();
- }
-
- if (output_sym != NULL) {
- // After symbol resolution, visibility is changed to the most restrict one.
- // If we are not doing incremental linking, then any symbol with hidden
- // or internal visibility is forcefully set as a local symbol.
- if (shouldForceLocal(*resolved_result.info)) {
- m_Module.getSymbolTable().forceLocal(*output_sym);
- }
- }
-
- return input_sym;
-}
-
/// defineSymbolForcefully - define an output symbol and override it immediately
LDSymbol* FragmentLinker::defineSymbolForcefully(const llvm::StringRef& pName,
bool pIsDyn,
@@ -462,36 +293,6 @@
//===----------------------------------------------------------------------===//
// Relocation Operations
//===----------------------------------------------------------------------===//
-/// addRelocation - add a relocation entry in FragmentLinker (only for object file)
-///
-/// All symbols should be read and resolved before calling this function.
-Relocation* FragmentLinker::addRelocation(Relocation::Type pType,
- LDSymbol& pSym,
- LDSection& pSection,
- uint32_t pOffset,
- Relocation::Address pAddend)
-{
- // FIXME: we should dicard sections and symbols first instead
- // if the symbol is in the discarded input section, then we also need to
- // discard this relocation.
- ResolveInfo* resolve_info = pSym.resolveInfo();
- if (!pSym.hasFragRef() &&
- resolve_info->type() == ResolveInfo::Section &&
- resolve_info->desc() == ResolveInfo::Undefined)
- return NULL;
-
- FragmentRef* frag_ref = FragmentRef::Create(*pSection.getLink(), pOffset);
-
- Relocation* relocation = m_Backend.getRelocFactory()->produce(pType,
- *frag_ref,
- pAddend);
-
- relocation->setSymInfo(resolve_info);
- pSection.getRelocData()->getFragmentList().push_back(relocation);
-
- return relocation;
-}
-
bool FragmentLinker::applyRelocations()
{
// when producing relocatables, no need to apply relocation
@@ -513,7 +314,7 @@
RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
Relocation* relocation = llvm::cast<Relocation>(reloc);
- relocation->apply(*m_Backend.getRelocFactory());
+ relocation->apply(*m_Backend.getRelocator());
} // for all relocations
} // for all relocation section
} // for all inputs
@@ -525,7 +326,7 @@
BranchIsland& island = *facIter;
BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
for (iter = island.reloc_begin(); iter != iterEnd; ++iter)
- (*iter)->apply(*m_Backend.getRelocFactory());
+ (*iter)->apply(*m_Backend.getRelocator());
}
return true;
}
@@ -630,17 +431,17 @@
uint8_t* target_addr = pOutput + out_offset;
// byte swapping if target and host has different endian, and then write back
- if(llvm::sys::isLittleEndianHost() != m_Backend.isLittleEndian()) {
+ if(llvm::sys::isLittleEndianHost() != m_Config.targets().isLittleEndian()) {
uint64_t tmp_data = 0;
- switch(m_Backend.bitclass()) {
+ switch(m_Config.targets().bitclass()) {
case 32u:
- tmp_data = bswap32(pReloc.target());
+ tmp_data = mcld::bswap32(pReloc.target());
std::memcpy(target_addr, &tmp_data, 4);
break;
case 64u:
- tmp_data = bswap64(pReloc.target());
+ tmp_data = mcld::bswap64(pReloc.target());
std::memcpy(target_addr, &tmp_data, 8);
break;
@@ -649,7 +450,7 @@
}
}
else
- std::memcpy(target_addr, &pReloc.target(), m_Backend.bitclass()/8);
+ std::memcpy(target_addr, &pReloc.target(), m_Config.targets().bitclass()/8);
}
/// isOutputPIC - return whether the output is position-independent
diff --git a/lib/Fragment/Relocation.cpp b/lib/Fragment/Relocation.cpp
index bae49af..293b1c9 100644
--- a/lib/Fragment/Relocation.cpp
+++ b/lib/Fragment/Relocation.cpp
@@ -7,21 +7,69 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/Fragment/Relocation.h>
-#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/Relocator.h>
#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/SectionData.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/LD/RelocationFactory.h>
+
+#include <llvm/Support/ManagedStatic.h>
using namespace mcld;
+static llvm::ManagedStatic<RelocationFactory> g_RelocationFactory;
+
+//===----------------------------------------------------------------------===//
+// Relocation Factory Methods
+//===----------------------------------------------------------------------===//
+/// Initialize - set up the relocation factory
+void Relocation::SetUp(const LinkerConfig& pConfig)
+{
+ g_RelocationFactory->setConfig(pConfig);
+}
+
+/// Clear - Clean up the relocation factory
+void Relocation::Clear()
+{
+ g_RelocationFactory->clear();
+}
+
+/// Create - produce an empty relocation entry
+Relocation* Relocation::Create()
+{
+ return g_RelocationFactory->produceEmptyEntry();
+}
+
+/// Create - produce a relocation entry
+/// @param pType [in] the type of the relocation entry
+/// @param pFragRef [in] the place to apply the relocation
+/// @param pAddend [in] the addend of the relocation entry
+Relocation* Relocation::Create(Type pType, FragmentRef& pFragRef, Address pAddend)
+{
+ return g_RelocationFactory->produce(pType, pFragRef, pAddend);
+}
+
+/// Destroy - destroy a relocation entry
+void Relocation::Destroy(Relocation*& pRelocation)
+{
+ g_RelocationFactory->destroy(pRelocation);
+ pRelocation = NULL;
+}
+
+//===----------------------------------------------------------------------===//
+// Relocation
+//===----------------------------------------------------------------------===//
+Relocation::Relocation()
+ : m_Type(0x0), m_TargetData(0x0), m_pSymInfo(NULL), m_Addend(0x0) {
+}
+
Relocation::Relocation(Relocation::Type pType,
FragmentRef* pTargetRef,
Relocation::Address pAddend,
Relocation::DWord pTargetData)
- : Fragment(Fragment::Relocation),
- m_Type(pType),
+ : m_Type(pType),
m_TargetData(pTargetData),
m_pSymInfo(NULL),
m_Addend(pAddend)
@@ -49,31 +97,31 @@
return m_pSymInfo->outSymbol()->value();
}
-void Relocation::apply(RelocationFactory& pRelocFactory)
+void Relocation::apply(Relocator& pRelocator)
{
- RelocationFactory::Result result = pRelocFactory.applyRelocation(*this);
+ Relocator::Result result = pRelocator.applyRelocation(*this);
switch (result) {
- case RelocationFactory::OK: {
+ case Relocator::OK: {
// do nothing
return;
}
- case RelocationFactory::Overflow: {
- error(diag::result_overflow) << pRelocFactory.getName(type())
+ case Relocator::Overflow: {
+ error(diag::result_overflow) << pRelocator.getName(type())
<< symInfo()->name();
return;
}
- case RelocationFactory::BadReloc: {
- error(diag::result_badreloc) << pRelocFactory.getName(type())
+ case Relocator::BadReloc: {
+ error(diag::result_badreloc) << pRelocator.getName(type())
<< symInfo()->name();
return;
}
- case RelocationFactory::Unsupport: {
+ case Relocator::Unsupport: {
fatal(diag::unsupported_relocation) << type()
<< "[email protected]";
return;
}
- case RelocationFactory::Unknown: {
+ case Relocator::Unknown: {
fatal(diag::unknown_relocation) << type() << symInfo()->name();
return;
}
diff --git a/lib/LD/Android.mk b/lib/LD/Android.mk
index 21e452e..53c1f10 100644
--- a/lib/LD/Android.mk
+++ b/lib/LD/Android.mk
@@ -7,6 +7,7 @@
mcld_ld_SRC_FILES := \
Archive.cpp \
ArchiveReader.cpp \
+ BinaryWriter.cpp \
BranchIsland.cpp \
BranchIslandFactory.cpp \
DWARFLineInfo.cpp \
@@ -17,6 +18,8 @@
DiagnosticPrinter.cpp \
DynObjReader.cpp \
DynObjWriter.cpp \
+ ELFBinaryReader.cpp \
+ ELFBinaryWriter.cpp \
ELFSegment.cpp \
ELFSegmentFactory.cpp \
EhFrame.cpp \
@@ -24,7 +27,6 @@
EhFrameReader.cpp \
ExecWriter.cpp \
GroupReader.cpp \
- Layout.cpp \
LDContext.cpp \
LDFileFormat.cpp \
LDReader.cpp \
diff --git a/lib/LD/BinaryWriter.cpp b/lib/LD/BinaryWriter.cpp
new file mode 100644
index 0000000..00dd169
--- /dev/null
+++ b/lib/LD/BinaryWriter.cpp
@@ -0,0 +1,24 @@
+//===- BinaryWriter.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/BinaryWriter.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Target/GNULDBackend.h>
+
+using namespace mcld;
+
+//==========================
+// BinaryWriter
+BinaryWriter::BinaryWriter(GNULDBackend& pBackend)
+{
+}
+
+BinaryWriter::~BinaryWriter()
+{
+}
+
diff --git a/lib/LD/DiagnosticInfos.cpp b/lib/LD/DiagnosticInfos.cpp
index 6639d0a..130fd9a 100644
--- a/lib/LD/DiagnosticInfos.cpp
+++ b/lib/LD/DiagnosticInfos.cpp
@@ -146,6 +146,14 @@
break;
} // end of switch
+ // If --fatal-warnings is turned on, then switch warnings and errors to fatal
+ if (m_Config.options().isFatalWarnings()) {
+ if (severity == DiagnosticEngine::Warning ||
+ severity == DiagnosticEngine::Error) {
+ severity = DiagnosticEngine::Fatal;
+ }
+ }
+
// finally, report it.
pEngine.getPrinter()->handleDiagnostic(severity, info);
return true;
diff --git a/lib/LD/DiagnosticPrinter.cpp b/lib/LD/DiagnosticPrinter.cpp
index 245555f..6eee86a 100644
--- a/lib/LD/DiagnosticPrinter.cpp
+++ b/lib/LD/DiagnosticPrinter.cpp
@@ -10,8 +10,9 @@
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// DiagnosticPrinter
+//===----------------------------------------------------------------------===//
DiagnosticPrinter::DiagnosticPrinter()
: m_NumErrors(0), m_NumWarnings(0) {
}
diff --git a/lib/LD/ELFBinaryReader.cpp b/lib/LD/ELFBinaryReader.cpp
new file mode 100644
index 0000000..c291544
--- /dev/null
+++ b/lib/LD/ELFBinaryReader.cpp
@@ -0,0 +1,124 @@
+//===- ELFBinaryReader.cpp ------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFBinaryReader.h>
+
+#include <mcld/IRBuilder.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Target/GNULDBackend.h>
+
+#include <llvm/Support/ELF.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ELFBinaryReader
+//===----------------------------------------------------------------------===//
+/// constructor
+ELFBinaryReader::ELFBinaryReader(GNULDBackend& pBackend,
+ IRBuilder& pBuilder,
+ const LinkerConfig& pConfig)
+ : BinaryReader(),
+ m_Backend(pBackend),
+ m_Builder(pBuilder),
+ m_Config(pConfig) {
+}
+
+/// destructor
+ELFBinaryReader::~ELFBinaryReader()
+{
+}
+
+bool ELFBinaryReader::readBinary(Input& pInput)
+{
+ // section: NULL
+ m_Builder.CreateELFHeader(pInput,
+ "",
+ LDFileFormat::Null,
+ llvm::ELF::SHT_NULL,
+ 0x0);
+
+ // section: .data
+ LDSection* data_sect =
+ m_Builder.CreateELFHeader(pInput,
+ ".data",
+ LDFileFormat::Regular,
+ llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC,
+ 0x1);
+
+
+ SectionData* data = m_Builder.CreateSectionData(*data_sect);
+ size_t data_size = pInput.memArea()->handler()->size();
+ Fragment* frag = m_Builder.CreateRegion(pInput, 0x0, data_size);
+ m_Builder.AppendFragment(*frag, *data);
+
+ // section: .shstrtab
+ m_Builder.CreateELFHeader(pInput,
+ ".shstrtab",
+ LDFileFormat::NamePool,
+ llvm::ELF::SHT_STRTAB,
+ 0x1);
+
+ // section: .symtab
+ m_Builder.CreateELFHeader(pInput,
+ ".symtab",
+ LDFileFormat::NamePool,
+ llvm::ELF::SHT_SYMTAB,
+ m_Config.targets().bitclass() / 8);
+
+ // symbol: .data
+ m_Builder.AddSymbol(pInput,
+ ".data",
+ ResolveInfo::Section,
+ ResolveInfo::Define,
+ ResolveInfo::Local,
+ 0x0,
+ 0x0,
+ data_sect);
+
+ // symbol: _start
+ m_Builder.AddSymbol(pInput,
+ "_binary_" + pInput.path().filename().string() + "_start",
+ ResolveInfo::NoType,
+ ResolveInfo::Define,
+ ResolveInfo::Global,
+ 0x0,
+ 0x0,
+ data_sect);
+
+ // symbol: _end
+ m_Builder.AddSymbol(pInput,
+ "_binary_" + pInput.path().filename().string() + "_end",
+ ResolveInfo::NoType,
+ ResolveInfo::Define,
+ ResolveInfo::Global,
+ 0x0,
+ data_size,
+ data_sect);
+
+ // symbol: _size
+ m_Builder.AddSymbol(pInput,
+ "_binary_" + pInput.path().filename().string() + "_size",
+ ResolveInfo::NoType,
+ ResolveInfo::Define,
+ ResolveInfo::Global,
+ 0x0,
+ data_size,
+ data_sect);
+
+ // section: .strtab
+ m_Builder.CreateELFHeader(pInput,
+ ".strtab",
+ LDFileFormat::NamePool,
+ llvm::ELF::SHT_STRTAB,
+ 0x1);
+
+ return true;
+}
diff --git a/lib/LD/ELFBinaryWriter.cpp b/lib/LD/ELFBinaryWriter.cpp
new file mode 100644
index 0000000..28ef553
--- /dev/null
+++ b/lib/LD/ELFBinaryWriter.cpp
@@ -0,0 +1,110 @@
+//===- ELFBinaryWriter.cpp ------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFBinaryWriter.h>
+
+#include <mcld/Module.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/ELFSegment.h>
+
+#include <llvm/Support/system_error.h>
+using namespace llvm;
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ELFBinaryWriter
+//===----------------------------------------------------------------------===//
+ELFBinaryWriter::ELFBinaryWriter(GNULDBackend& pBackend,
+ const LinkerConfig& pConfig)
+ : BinaryWriter(pBackend), ELFWriter(pBackend), m_Config(pConfig) {
+}
+
+ELFBinaryWriter::~ELFBinaryWriter()
+{
+}
+
+llvm::error_code ELFBinaryWriter::writeBinary(Module& pModule,
+ MemoryArea& pOutput)
+{
+ // Write out regular ELF sections
+ for (ELFSegmentFactory::iterator seg = target().elfSegmentTable().begin(),
+ segEnd = target().elfSegmentTable().end(); seg != segEnd; ++seg) {
+ if (llvm::ELF::PT_LOAD != (*seg).type())
+ continue;
+
+ for (ELFSegment::sect_iterator sect = (*seg).begin(),
+ sectEnd = (*seg).end(); sect != sectEnd; ++sect) {
+ MemoryRegion* region = NULL;
+ // request output region
+ switch((*sect)->kind()) {
+ case LDFileFormat::Note:
+ if ((*sect)->getSectionData() == NULL)
+ continue;
+ // Fall through
+ case LDFileFormat::Regular:
+ case LDFileFormat::Relocation:
+ case LDFileFormat::Target:
+ case LDFileFormat::Debug:
+ case LDFileFormat::GCCExceptTable:
+ case LDFileFormat::EhFrame: {
+ region = pOutput.request((*sect)->offset(), (*sect)->size());
+ if (NULL == region) {
+ llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
+ llvm::Twine((*sect)->name()) +
+ llvm::Twine("'.\n"));
+ }
+ break;
+ }
+ case LDFileFormat::Null:
+ case LDFileFormat::NamePool:
+ case LDFileFormat::BSS:
+ case LDFileFormat::MetaData:
+ case LDFileFormat::Version:
+ case LDFileFormat::EhFrameHdr:
+ case LDFileFormat::StackNote:
+ // ignore these sections
+ continue;
+ default: {
+ llvm::errs() << "WARNING: unsupported section kind: "
+ << (*sect)->kind()
+ << " of section "
+ << (*sect)->name()
+ << ".\n";
+ continue;
+ }
+ }
+
+ // write out sections with data
+ switch((*sect)->kind()) {
+ case LDFileFormat::Regular:
+ case LDFileFormat::Debug:
+ case LDFileFormat::GCCExceptTable:
+ case LDFileFormat::Note:
+ case LDFileFormat::EhFrame: {
+ // FIXME: if optimization of exception handling sections is enabled,
+ // then we should emit these sections by the other way.
+ emitSectionData(**sect, *region);
+ break;
+ }
+ case LDFileFormat::Relocation:
+ emitRelocation(m_Config, **sect, *region);
+ break;
+ case LDFileFormat::Target:
+ target().emitSectionData(**sect, *region);
+ break;
+ default:
+ continue;
+ }
+ } // end of section for loop
+ } // end of segment for loop
+ return llvm::make_error_code(llvm::errc::success);
+}
+
diff --git a/lib/LD/ELFDynObjReader.cpp b/lib/LD/ELFDynObjReader.cpp
index 740577c..e52e863 100644
--- a/lib/LD/ELFDynObjReader.cpp
+++ b/lib/LD/ELFDynObjReader.cpp
@@ -6,17 +6,19 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFDynObjReader.h>
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/LD/ELFReader.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Target/GNULDBackend.h>
+
#include <llvm/ADT/Twine.h>
#include <llvm/ADT/OwningPtr.h>
#include <llvm/Support/ErrorHandling.h>
-#include <mcld/LD/ELFDynObjReader.h>
-#include <mcld/LD/ELFReader.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryRegion.h>
-
#include <string>
using namespace mcld;
@@ -24,11 +26,13 @@
//===----------------------------------------------------------------------===//
// ELFDynObjReader
//===----------------------------------------------------------------------===//
-ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend, FragmentLinker& pLinker)
+ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend,
+ IRBuilder& pBuilder,
+ const LinkerConfig& pConfig)
: DynObjReader(),
m_pELFReader(0),
- m_Linker(pLinker) {
- if (32 == pBackend.bitclass() && pBackend.isLittleEndian())
+ m_Builder(pBuilder) {
+ if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian())
m_pELFReader = new ELFReader<32, true>(pBackend);
}
@@ -108,8 +112,8 @@
MemoryRegion* strtab_region = pInput.memArea()->request(
pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
char* strtab = reinterpret_cast<char*>(strtab_region->start());
- bool result = m_pELFReader->readSymbols(pInput, m_Linker, *symtab_region,
- strtab);
+ bool result = m_pELFReader->readSymbols(pInput, m_Builder,
+ *symtab_region, strtab);
pInput.memArea()->release(symtab_region);
pInput.memArea()->release(strtab_region);
diff --git a/lib/LD/ELFDynObjWriter.cpp b/lib/LD/ELFDynObjWriter.cpp
index 48ce0a3..2e903ce 100644
--- a/lib/LD/ELFDynObjWriter.cpp
+++ b/lib/LD/ELFDynObjWriter.cpp
@@ -13,7 +13,6 @@
#include <mcld/LD/LDSymbol.h>
#include <mcld/Target/GNULDBackend.h>
#include <mcld/MC/MCLDInput.h>
-#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MemoryArea.h>
#include <llvm/Support/ELF.h>
@@ -26,10 +25,10 @@
//===----------------------------------------------------------------------===//
// ELFDynObjWriter
//===----------------------------------------------------------------------===//
-ELFDynObjWriter::ELFDynObjWriter(GNULDBackend& pBackend, FragmentLinker& pLinker)
- : DynObjWriter(pBackend),
- ELFWriter(pBackend),
- m_Linker(pLinker) {
+ELFDynObjWriter::ELFDynObjWriter(GNULDBackend& pBackend,
+ const LinkerConfig& pConfig)
+ : DynObjWriter(pBackend), ELFWriter(pBackend),
+ m_Config(pConfig) {
}
@@ -54,6 +53,10 @@
MemoryRegion* region = NULL;
// request output region
switch((*sect)->kind()) {
+ case LDFileFormat::Note:
+ if ((*sect)->getSectionData() == NULL)
+ continue;
+ // Fall through
case LDFileFormat::Regular:
case LDFileFormat::Relocation:
case LDFileFormat::Target:
@@ -71,7 +74,6 @@
case LDFileFormat::Null:
case LDFileFormat::NamePool:
case LDFileFormat::BSS:
- case LDFileFormat::Note:
case LDFileFormat::MetaData:
case LDFileFormat::Version:
case LDFileFormat::EhFrameHdr:
@@ -93,6 +95,7 @@
case LDFileFormat::Regular:
case LDFileFormat::Debug:
case LDFileFormat::GCCExceptTable:
+ case LDFileFormat::Note:
case LDFileFormat::EhFrame: {
// FIXME: if optimization of exception handling sections is enabled,
// then we should emit these sections by the other way.
@@ -100,7 +103,7 @@
break;
}
case LDFileFormat::Relocation:
- emitRelocation(m_Linker.getLDInfo(), **sect, *region);
+ emitRelocation(m_Config, **sect, *region);
break;
case LDFileFormat::Target:
target().emitSectionData(**sect, *region);
@@ -115,27 +118,23 @@
pModule,
pOutput);
- if (32 == target().bitclass()) {
+ if (m_Config.targets().is32Bits()) {
// Write out ELF header
// Write out section header table
- writeELF32Header(m_Linker.getLDInfo(),
- pModule,
- pOutput);
+ writeELF32Header(m_Config, pModule, pOutput);
emitELF32ProgramHeader(pOutput);
- emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+ emitELF32SectionHeader(pModule, m_Config, pOutput);
}
- else if (64 == target().bitclass()) {
+ else if (m_Config.targets().is64Bits()) {
// Write out ELF header
// Write out section header table
- writeELF64Header(m_Linker.getLDInfo(),
- pModule,
- pOutput);
+ writeELF64Header(m_Config, pModule, pOutput);
emitELF64ProgramHeader(pOutput);
- emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+ emitELF64SectionHeader(pModule, m_Config, pOutput);
}
else
return make_error_code(errc::not_supported);
diff --git a/lib/LD/ELFExecWriter.cpp b/lib/LD/ELFExecWriter.cpp
index dec5e26..a9af584 100644
--- a/lib/LD/ELFExecWriter.cpp
+++ b/lib/LD/ELFExecWriter.cpp
@@ -12,7 +12,6 @@
#include <mcld/LinkerConfig.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MemoryArea.h>
#include <llvm/Support/ELF.h>
@@ -25,10 +24,10 @@
//===----------------------------------------------------------------------===//
// ELFExecWriter
//===----------------------------------------------------------------------===//
-ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, FragmentLinker& pLinker)
- : ExecWriter(pBackend),
- ELFWriter(pBackend),
- m_Linker(pLinker) {
+ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend,
+ const LinkerConfig& pConfig)
+ : ExecWriter(pBackend), ELFWriter(pBackend),
+ m_Config(pConfig) {
}
@@ -54,6 +53,10 @@
MemoryRegion* region = NULL;
// request output region
switch((*sect)->kind()) {
+ case LDFileFormat::Note:
+ if ((*sect)->getSectionData() == NULL)
+ continue;
+ // Fall through
case LDFileFormat::Regular:
case LDFileFormat::Relocation:
case LDFileFormat::Target:
@@ -71,7 +74,6 @@
case LDFileFormat::Null:
case LDFileFormat::NamePool:
case LDFileFormat::BSS:
- case LDFileFormat::Note:
case LDFileFormat::MetaData:
case LDFileFormat::Version:
case LDFileFormat::EhFrameHdr:
@@ -93,6 +95,7 @@
case LDFileFormat::Regular:
case LDFileFormat::Debug:
case LDFileFormat::GCCExceptTable:
+ case LDFileFormat::Note:
case LDFileFormat::EhFrame: {
// FIXME: if optimization of exception handling sections is enabled,
// then we should emit these sections by the other way.
@@ -100,7 +103,7 @@
break;
}
case LDFileFormat::Relocation:
- emitRelocation(m_Linker.getLDInfo(), **sect, *region);
+ emitRelocation(m_Config, **sect, *region);
break;
case LDFileFormat::Target:
target().emitSectionData(**sect, *region);
@@ -114,27 +117,23 @@
pModule,
pOutput);
- if (32 == target().bitclass()) {
+ if (m_Config.targets().is32Bits()) {
// Write out ELF header
// Write out section header table
- writeELF32Header(m_Linker.getLDInfo(),
- pModule,
- pOutput);
+ writeELF32Header(m_Config, pModule, pOutput);
emitELF32ProgramHeader(pOutput);
- emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+ emitELF32SectionHeader(pModule, m_Config, pOutput);
}
- else if (64 == target().bitclass()) {
+ else if (m_Config.targets().is64Bits()) {
// Write out ELF header
// Write out section header table
- writeELF64Header(m_Linker.getLDInfo(),
- pModule,
- pOutput);
+ writeELF64Header(m_Config, pModule, pOutput);
emitELF64ProgramHeader(pOutput);
- emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+ emitELF64SectionHeader(pModule, m_Config, pOutput);
}
else
return make_error_code(errc::not_supported);
diff --git a/lib/LD/ELFFileFormat.cpp b/lib/LD/ELFFileFormat.cpp
index 7512e38..b4792b5 100644
--- a/lib/LD/ELFFileFormat.cpp
+++ b/lib/LD/ELFFileFormat.cpp
@@ -155,6 +155,7 @@
llvm::ELF::SHT_SYMTAB,
0x0,
pBitClass / 8);
+
f_pStrTab = pBuilder.CreateSection(".strtab",
LDFileFormat::NamePool,
llvm::ELF::SHT_STRTAB,
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index 4124098..a87b5b8 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -16,7 +16,6 @@
#include <mcld/IRBuilder.h>
#include <mcld/MC/MCLDInput.h>
-#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/LD/ELFReader.h>
#include <mcld/LD/EhFrameReader.h>
#include <mcld/LD/EhFrame.h>
@@ -30,14 +29,17 @@
// ELFObjectReader
//===----------------------------------------------------------------------===//
/// constructor
-ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend, FragmentLinker& pLinker)
+ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend,
+ IRBuilder& pBuilder,
+ const LinkerConfig& pConfig)
: ObjectReader(),
m_pELFReader(NULL),
m_pEhFrameReader(NULL),
- m_Linker(pLinker),
+ m_Builder(pBuilder),
m_ReadFlag(ParseEhFrame),
- m_Backend(pBackend) {
- if (32 == pBackend.bitclass() && pBackend.isLittleEndian()) {
+ m_Backend(pBackend),
+ m_Config(pConfig) {
+ if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian()) {
m_pELFReader = new ELFReader<32, true>(pBackend);
}
@@ -166,7 +168,7 @@
break;
}
case LDFileFormat::Debug: {
- if (m_Linker.getLDInfo().options().stripDebug()) {
+ if (m_Config.options().stripDebug()) {
(*section)->setKind(LDFileFormat::Ignore);
}
else {
@@ -180,7 +182,7 @@
case LDFileFormat::EhFrame: {
EhFrame* eh_frame = IRBuilder::CreateEhFrame(**section);
- if (m_Linker.getLDInfo().options().hasEhFrameHdr() &&
+ if (m_Config.options().hasEhFrameHdr() &&
(m_ReadFlag & ParseEhFrame)) {
// if --eh-frame-hdr option is given, parse .eh_frame.
@@ -231,7 +233,7 @@
return true;
}
-/// readSymbols - read symbols into FragmentLinker from the input relocatable object.
+/// readSymbols - read symbols from the input relocatable object.
bool ELFObjectReader::readSymbols(Input& pInput)
{
assert(pInput.hasMemArea());
@@ -258,7 +260,7 @@
pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
char* strtab = reinterpret_cast<char*>(strtab_region->start());
bool result = m_pELFReader->readSymbols(pInput,
- m_Linker,
+ m_Builder,
*symtab_region,
strtab);
pInput.memArea()->release(symtab_region);
@@ -282,14 +284,14 @@
IRBuilder::CreateRelocData(**rs); ///< create relocation data for the header
switch ((*rs)->type()) {
case llvm::ELF::SHT_RELA: {
- if (!m_pELFReader->readRela(pInput, m_Linker, **rs, *region)) {
+ if (!m_pELFReader->readRela(pInput, **rs, *region)) {
mem->release(region);
return false;
}
break;
}
case llvm::ELF::SHT_REL: {
- if (!m_pELFReader->readRel(pInput, m_Linker, **rs, *region)) {
+ if (!m_pELFReader->readRel(pInput, **rs, *region)) {
mem->release(region);
return false;
}
diff --git a/lib/LD/ELFObjectWriter.cpp b/lib/LD/ELFObjectWriter.cpp
index ee9a7ac..e9b7b99 100644
--- a/lib/LD/ELFObjectWriter.cpp
+++ b/lib/LD/ELFObjectWriter.cpp
@@ -9,11 +9,12 @@
#include <mcld/LD/ELFObjectWriter.h>
#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MemoryArea.h>
#include <llvm/Support/system_error.h>
+
using namespace llvm;
using namespace mcld;
@@ -21,8 +22,9 @@
// ELFObjectWriter
//===----------------------------------------------------------------------===//
ELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend,
- FragmentLinker& pLinker)
- : ObjectWriter(pBackend), ELFWriter(pBackend), m_Linker(pLinker) {
+ const LinkerConfig& pConfig)
+ : ObjectWriter(pBackend), ELFWriter(pBackend),
+ m_Config(pConfig) {
}
ELFObjectWriter::~ELFObjectWriter()
@@ -41,6 +43,10 @@
MemoryRegion* region = NULL;
// request output region
switch((*sect)->kind()) {
+ case LDFileFormat::Note:
+ if ((*sect)->getSectionData() == NULL)
+ continue;
+ // Fall through
case LDFileFormat::Regular:
case LDFileFormat::Relocation:
case LDFileFormat::Target:
@@ -58,7 +64,6 @@
case LDFileFormat::Null:
case LDFileFormat::NamePool:
case LDFileFormat::BSS:
- case LDFileFormat::Note:
case LDFileFormat::MetaData:
case LDFileFormat::Version:
case LDFileFormat::EhFrameHdr:
@@ -80,6 +85,7 @@
case LDFileFormat::Regular:
case LDFileFormat::Debug:
case LDFileFormat::GCCExceptTable:
+ case LDFileFormat::Note:
case LDFileFormat::EhFrame: {
// FIXME: if optimization of exception handling sections is enabled,
// then we should emit these sections by the other way.
@@ -87,7 +93,7 @@
break;
}
case LDFileFormat::Relocation:
- emitRelocation(m_Linker.getLDInfo(), **sect, *region);
+ emitRelocation(m_Config, **sect, *region);
break;
case LDFileFormat::Target:
target().emitSectionData(**sect, *region);
@@ -101,23 +107,23 @@
pModule,
pOutput);
- if (32 == target().bitclass()) {
+ if (m_Config.targets().is32Bits()) {
// Write out ELF header
// Write out section header table
- writeELF32Header(m_Linker.getLDInfo(),
+ writeELF32Header(m_Config,
pModule,
pOutput);
- emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+ emitELF32SectionHeader(pModule, m_Config, pOutput);
}
- else if (64 == target().bitclass()) {
+ else if (m_Config.targets().is64Bits()) {
// Write out ELF header
// Write out section header table
- writeELF64Header(m_Linker.getLDInfo(),
+ writeELF64Header(m_Config,
pModule,
pOutput);
- emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+ emitELF64SectionHeader(pModule, m_Config, pOutput);
}
else
return make_error_code(errc::not_supported);
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index 7f105b3..84ad17b 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -9,7 +9,6 @@
#include <mcld/LD/ELFReader.h>
#include <mcld/IRBuilder.h>
-#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Fragment/FillFragment.h>
#include <mcld/LD/EhFrame.h>
#include <mcld/LD/SectionData.h>
@@ -105,7 +104,10 @@
if (Input::DynObj == pInput.type())
return FragmentRef::Null();
- if (pShndx == llvm::ELF::SHN_UNDEF || pShndx >= llvm::ELF::SHN_LORESERVE)
+ if (pShndx == llvm::ELF::SHN_UNDEF)
+ return FragmentRef::Null();
+
+ if (pShndx >= llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
return FragmentRef::Null();
LDSection* sect_hdr = pInput.context()->getSection(pShndx);
@@ -193,7 +195,7 @@
/// readSymbols - read ELF symbols and create LDSymbol
bool ELFReader<32, true>::readSymbols(Input& pInput,
- FragmentLinker& pLinker,
+ IRBuilder& pBuilder,
const MemoryRegion& pRegion,
const char* pStrTab) const
{
@@ -223,10 +225,10 @@
st_shndx = symtab[idx].st_shndx;
}
else {
- st_name = bswap32(symtab[idx].st_name);
- st_value = bswap32(symtab[idx].st_value);
- st_size = bswap32(symtab[idx].st_size);
- st_shndx = bswap16(symtab[idx].st_shndx);
+ st_name = mcld::bswap32(symtab[idx].st_name);
+ st_value = mcld::bswap32(symtab[idx].st_value);
+ st_size = mcld::bswap32(symtab[idx].st_size);
+ st_shndx = mcld::bswap16(symtab[idx].st_shndx);
}
// If the section should not be included, set the st_shndx SHN_UNDEF
@@ -250,55 +252,33 @@
// get ld_value - ld_value must be section relative.
uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
- // get the input fragment
- FragmentRef* ld_frag_ref = getSymFragmentRef(pInput,
- st_shndx,
- ld_value);
-
// get ld_vis
ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
+ // get section
+ LDSection* section = NULL;
+ if (st_shndx < llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
+ section = pInput.context()->getSection(st_shndx);
+
// get ld_name
- llvm::StringRef ld_name;
+ std::string ld_name;
if (ResolveInfo::Section == ld_type) {
// Section symbol's st_name is the section index.
- LDSection* section = pInput.context()->getSection(st_shndx);
assert(NULL != section && "get a invalid section");
- ld_name = llvm::StringRef(section->name());
+ ld_name = section->name();
}
else {
- ld_name = llvm::StringRef(pStrTab + st_name);
+ ld_name = std::string(pStrTab + st_name);
}
-
- // push into FragmentLinker
- LDSymbol* input_sym = NULL;
-
- if (pInput.type() == Input::Object) {
- input_sym = pLinker.addSymbol<Input::Object>(ld_name,
- ld_type,
- ld_desc,
- ld_binding,
- st_size,
- ld_value,
- ld_frag_ref,
- ld_vis);
- // push into the input file
- pInput.context()->addSymbol(input_sym);
- continue;
- }
- else if (pInput.type() == Input::DynObj) {
- input_sym = pLinker.addSymbol<Input::DynObj>(ld_name,
- ld_type,
- ld_desc,
- ld_binding,
- st_size,
- ld_value,
- ld_frag_ref,
- ld_vis);
- continue;
- }
-
+ pBuilder.AddSymbol(pInput,
+ ld_name,
+ ld_type,
+ ld_desc,
+ ld_binding,
+ st_size,
+ ld_value,
+ section, ld_vis);
} // end of for loop
return true;
}
@@ -308,7 +288,6 @@
//===----------------------------------------------------------------------===//
/// ELFReader::readRela - read ELF rela and create Relocation
bool ELFReader<32, true>::readRela(Input& pInput,
- FragmentLinker& pLinker,
LDSection& pSection,
const MemoryRegion& pRegion) const
{
@@ -327,9 +306,9 @@
r_addend = relaTab[idx].r_addend;
}
else {
- r_offset = bswap32(relaTab[idx].r_offset);
- r_info = bswap32(relaTab[idx].r_info);
- r_addend = bswap32(relaTab[idx].r_addend);
+ r_offset = mcld::bswap32(relaTab[idx].r_offset);
+ r_info = mcld::bswap32(relaTab[idx].r_info);
+ r_addend = mcld::bswap32(relaTab[idx].r_addend);
}
uint8_t r_type = static_cast<unsigned char>(r_info);
@@ -339,14 +318,13 @@
fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
}
- pLinker.addRelocation(r_type, *symbol, pSection, r_offset, r_addend);
+ IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
} // end of for
return true;
}
/// readRel - read ELF rel and create Relocation
bool ELFReader<32, true>::readRel(Input& pInput,
- FragmentLinker& pLinker,
LDSection& pSection,
const MemoryRegion& pRegion) const
{
@@ -363,8 +341,8 @@
r_info = relTab[idx].r_info;
}
else {
- r_offset = bswap32(relTab[idx].r_offset);
- r_info = bswap32(relTab[idx].r_info);
+ r_offset = mcld::bswap32(relTab[idx].r_offset);
+ r_info = mcld::bswap32(relTab[idx].r_info);
}
uint8_t r_type = static_cast<unsigned char>(r_info);
@@ -375,7 +353,7 @@
fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
}
- pLinker.addRelocation(r_type, *symbol, pSection, r_offset);
+ IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
} // end of for
return true;
}
@@ -396,8 +374,8 @@
reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
if (llvm::sys::isLittleEndianHost())
- return (hdr->e_machine == target().machine());
- return (bswap16(hdr->e_machine) == target().machine());
+ return (hdr->e_machine == target().getInfo().machine());
+ return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
}
/// fileType - return the file type
@@ -409,7 +387,7 @@
if (llvm::sys::isLittleEndianHost())
type = hdr->e_type;
else
- type = bswap16(hdr->e_type);
+ type = mcld::bswap16(hdr->e_type);
switch(type) {
case llvm::ELF::ET_REL:
@@ -445,10 +423,10 @@
shstrtab = ehdr->e_shstrndx;
}
else {
- shoff = bswap32(ehdr->e_shoff);
- shentsize = bswap16(ehdr->e_shentsize);
- shnum = bswap16(ehdr->e_shnum);
- shstrtab = bswap16(ehdr->e_shstrndx);
+ shoff = mcld::bswap32(ehdr->e_shoff);
+ shentsize = mcld::bswap16(ehdr->e_shentsize);
+ shnum = mcld::bswap16(ehdr->e_shnum);
+ shstrtab = mcld::bswap16(ehdr->e_shstrndx);
}
// If the file has no section header table, e_shoff holds zero.
@@ -476,8 +454,8 @@
sh_size = shdr->sh_size;
}
else {
- sh_offset = bswap32(shdr->sh_offset);
- sh_size = bswap32(shdr->sh_size);
+ sh_offset = mcld::bswap32(shdr->sh_offset);
+ sh_size = mcld::bswap32(shdr->sh_size);
}
MemoryRegion* sect_name_region = pInput.memArea()->request(
@@ -500,14 +478,14 @@
sh_addralign = shdrTab[idx].sh_addralign;
}
else {
- sh_name = bswap32(shdrTab[idx].sh_name);
- sh_type = bswap32(shdrTab[idx].sh_type);
- sh_flags = bswap32(shdrTab[idx].sh_flags);
- sh_offset = bswap32(shdrTab[idx].sh_offset);
- sh_size = bswap32(shdrTab[idx].sh_size);
- sh_link = bswap32(shdrTab[idx].sh_link);
- sh_info = bswap32(shdrTab[idx].sh_info);
- sh_addralign = bswap32(shdrTab[idx].sh_addralign);
+ sh_name = mcld::bswap32(shdrTab[idx].sh_name);
+ sh_type = mcld::bswap32(shdrTab[idx].sh_type);
+ sh_flags = mcld::bswap32(shdrTab[idx].sh_flags);
+ sh_offset = mcld::bswap32(shdrTab[idx].sh_offset);
+ sh_size = mcld::bswap32(shdrTab[idx].sh_size);
+ sh_link = mcld::bswap32(shdrTab[idx].sh_link);
+ sh_info = mcld::bswap32(shdrTab[idx].sh_info);
+ sh_addralign = mcld::bswap32(shdrTab[idx].sh_addralign);
}
LDSection* section = IRBuilder::CreateELFHeader(pInput,
@@ -574,8 +552,8 @@
st_shndx = entry->st_shndx;
}
else {
- st_name = bswap32(entry->st_name);
- st_shndx = bswap16(entry->st_shndx);
+ st_name = mcld::bswap32(entry->st_name);
+ st_shndx = mcld::bswap16(entry->st_shndx);
}
MemoryRegion* strtab_region = pInput.memArea()->request(
@@ -635,8 +613,8 @@
d_tag = dynamic[idx].d_tag;
d_val = dynamic[idx].d_un.d_val;
} else {
- d_tag = bswap32(dynamic[idx].d_tag);
- d_val = bswap32(dynamic[idx].d_un.d_val);
+ d_tag = mcld::bswap32(dynamic[idx].d_tag);
+ d_val = mcld::bswap32(dynamic[idx].d_un.d_val);
}
switch (d_tag) {
diff --git a/lib/LD/ELFWriter.cpp b/lib/LD/ELFWriter.cpp
index 93fc4b9..a37e654 100644
--- a/lib/LD/ELFWriter.cpp
+++ b/lib/LD/ELFWriter.cpp
@@ -49,11 +49,11 @@
memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
header->e_ident[EI_CLASS] = ELFCLASS32;
- header->e_ident[EI_DATA] = target().isLittleEndian()?
+ header->e_ident[EI_DATA] = pConfig.targets().isLittleEndian()?
ELFDATA2LSB : ELFDATA2MSB;
- header->e_ident[EI_VERSION] = target().ELFVersion();
- header->e_ident[EI_OSABI] = target().OSABI();
- header->e_ident[EI_ABIVERSION] = target().ABIVersion();
+ header->e_ident[EI_VERSION] = target().getInfo().ELFVersion();
+ header->e_ident[EI_OSABI] = target().getInfo().OSABI();
+ header->e_ident[EI_ABIVERSION] = target().getInfo().ABIVersion();
// FIXME: add processor-specific and core file types.
switch(pConfig.codeGenType()) {
@@ -70,7 +70,7 @@
llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
header->e_type = ET_NONE;
}
- header->e_machine = target().machine();
+ header->e_machine = target().getInfo().machine();
header->e_version = header->e_ident[EI_VERSION];
header->e_entry = getEntryPoint(pConfig, pModule);
@@ -101,11 +101,11 @@
memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
header->e_ident[EI_CLASS] = ELFCLASS64;
- header->e_ident[EI_DATA] = target().isLittleEndian()?
+ header->e_ident[EI_DATA] = pConfig.targets().isLittleEndian()?
ELFDATA2LSB : ELFDATA2MSB;
- header->e_ident[EI_VERSION] = target().ELFVersion();
- header->e_ident[EI_OSABI] = target().OSABI();
- header->e_ident[EI_ABIVERSION] = target().ABIVersion();
+ header->e_ident[EI_VERSION] = target().getInfo().ELFVersion();
+ header->e_ident[EI_OSABI] = target().getInfo().OSABI();
+ header->e_ident[EI_ABIVERSION] = target().getInfo().ABIVersion();
// FIXME: add processor-specific and core file types.
switch(pConfig.codeGenType()) {
@@ -122,7 +122,7 @@
llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
header->e_type = ET_NONE;
}
- header->e_machine = target().machine();
+ header->e_machine = target().getInfo().machine();
header->e_version = header->e_ident[EI_VERSION];
header->e_entry = getEntryPoint(pConfig, pModule);
@@ -500,10 +500,18 @@
/// getSectInfo - compute ElfXX_Shdr::sh_info
uint64_t ELFWriter::getSectInfo(const LDSection& pSection) const
{
- const LDSection* info_link = pSection.getLink();
- if (NULL == info_link)
- return 0x0;
- return info_link->index();
+ if (llvm::ELF::SHT_SYMTAB == pSection.type() ||
+ llvm::ELF::SHT_DYNSYM == pSection.type())
+ return pSection.getInfo();
+
+ if (llvm::ELF::SHT_REL == pSection.type() ||
+ llvm::ELF::SHT_RELA == pSection.type()) {
+ const LDSection* info_link = pSection.getLink();
+ if (NULL != info_link)
+ return info_link->index();
+ }
+
+ return 0x0;
}
/// getELF32LastStartOffset
@@ -579,9 +587,6 @@
assert(0x0 == size);
break;
}
- case Fragment::Relocation:
- llvm::report_fatal_error("relocation fragment should not be in a regular section.\n");
- break;
case Fragment::Target:
llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
break;
diff --git a/lib/LD/GNUArchiveReader.cpp b/lib/LD/GNUArchiveReader.cpp
index 9aeaa6b..82e4fec 100644
--- a/lib/LD/GNUArchiveReader.cpp
+++ b/lib/LD/GNUArchiveReader.cpp
@@ -262,7 +262,7 @@
// read the number of symbols
uint32_t number = 0;
if (llvm::sys::isLittleEndianHost())
- number = bswap32(*data);
+ number = mcld::bswap32(*data);
else
number = *data;
@@ -273,7 +273,7 @@
// add the archive symbols
for (uint32_t i = 0; i < number; ++i) {
if (llvm::sys::isLittleEndianHost())
- pArchive.addSymbol(name, bswap32(*data));
+ pArchive.addSymbol(name, mcld::bswap32(*data));
else
pArchive.addSymbol(name, *data);
name += strlen(name) + 1;
diff --git a/lib/LD/GroupReader.cpp b/lib/LD/GroupReader.cpp
index 91e79c0..a407c3d 100644
--- a/lib/LD/GroupReader.cpp
+++ b/lib/LD/GroupReader.cpp
@@ -94,7 +94,7 @@
}
else {
fatal(diag::err_unrecognized_input_file) << (*input)->path()
- << pConfig.triple().str();
+ << pConfig.targets().triple().str();
}
++input;
}
diff --git a/lib/LD/Layout.cpp b/lib/LD/Layout.cpp
deleted file mode 100644
index a2a1028..0000000
--- a/lib/LD/Layout.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-//===- Layout.cpp ---------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/LD/Layout.h>
-
-#include <mcld/Module.h>
-#include <mcld/LinkerConfig.h>
-#include <mcld/ADT/SizeTraits.h>
-#include <mcld/LD/LDFileFormat.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Target/TargetLDBackend.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// Layout
-//===----------------------------------------------------------------------===//
-void Layout::sortSectionOrder(const TargetLDBackend& pBackend,
- const LinkerConfig& pConfig)
-{
- typedef std::pair<LDSection*, unsigned int> SectOrder;
- typedef std::vector<SectOrder > SectListTy;
- SectListTy sect_list;
- // get section order from backend
- for (size_t index = 0; index < m_SectionOrder.size(); ++index) {
- sect_list.push_back(
- std::make_pair(
- m_SectionOrder[index],
- pBackend.getSectionOrder(*m_SectionOrder[index])
- ));
- }
-
- // simple insertion sort should be fine for general cases such as so and exec
- for (unsigned int i = 1; i < sect_list.size(); ++i) {
- SectOrder order = sect_list[i];
- int j = i - 1;
- while (j >= 0 && sect_list[j].second > order.second) {
- sect_list[j + 1] = sect_list[j];
- --j;
- }
- sect_list[j + 1] = order;
- }
-
- // update the sorted ordering to m_SectionOrder
- m_SectionOrder.clear();
- for (size_t index = 0; index < sect_list.size(); ++index) {
- m_SectionOrder.push_back(sect_list[index].first);
- }
-}
-
-/// layout - layout the sections
-/// 1. finalize fragment offset
-/// 2. compute section order
-/// 3. finalize section offset
-bool Layout::layout(Module& pModule,
- const TargetLDBackend& pBackend,
- const LinkerConfig& pConfig)
-{
- // determine what sections in output context will go into final output, and
- // push the needed sections into m_SectionOrder for later processing
- Module::iterator it, itEnd = pModule.end();
- for (it = pModule.begin(); it != itEnd; ++it) {
- // calculate 1. all fragment offset, and 2. the section order
- LDSection* sect = *it;
-
- switch (sect->kind()) {
- // take NULL and StackNote directly
- case LDFileFormat::Null:
- case LDFileFormat::StackNote:
- m_SectionOrder.push_back(sect);
- break;
- // ignore if section size is 0
- case LDFileFormat::Regular:
- case LDFileFormat::Target:
- case LDFileFormat::MetaData:
- case LDFileFormat::BSS:
- case LDFileFormat::Debug:
- case LDFileFormat::EhFrame:
- case LDFileFormat::GCCExceptTable:
- case LDFileFormat::NamePool:
- case LDFileFormat::Relocation:
- case LDFileFormat::Note:
- case LDFileFormat::EhFrameHdr:
- if (0 != sect->size()) {
- m_SectionOrder.push_back(sect);
- }
- break;
- case LDFileFormat::Group:
- if (LinkerConfig::Object == pConfig.codeGenType()) {
- //TODO: support incremental linking
- ;
- }
- break;
- case LDFileFormat::Version:
- if (0 != sect->size()) {
- m_SectionOrder.push_back(sect);
- warning(diag::warn_unsupported_symbolic_versioning) << sect->name();
- }
- break;
- default:
- if (0 != sect->size()) {
- error(diag::err_unsupported_section) << sect->name() << sect->kind();
- }
- break;
- }
- } // end of for
-
- // perform sorting on m_SectionOrder to get a ordering for final layout
- sortSectionOrder(pBackend, pConfig);
-
- // 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.
- // always set NULL section's offset to 0
- m_SectionOrder[0]->setOffset(0);
- for (size_t index = 1; index < m_SectionOrder.size(); ++index) {
-
- 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);
- }
-
- // FIXME: Currently Writer bases on the section table in output context to
- // write out sections, so we have to update its content..
- pModule.getSectionTable().clear();
- for (size_t index = 0; index < m_SectionOrder.size(); ++index) {
- pModule.getSectionTable().push_back(m_SectionOrder[index]);
- // after sorting, update the correct output section indices
- m_SectionOrder[index]->setIndex(index);
- }
- return true;
-}
-
diff --git a/lib/LD/NamePool.cpp b/lib/LD/NamePool.cpp
index 9e4755d..6af1f7d 100644
--- a/lib/LD/NamePool.cpp
+++ b/lib/LD/NamePool.cpp
@@ -93,7 +93,7 @@
pOldInfo->override(*old_symbol);
}
- // exit and is a symbol
+ // exist and is a symbol
// symbol resolution
bool override = false;
unsigned int action = Resolver::LastAction;
diff --git a/lib/LD/RelocData.cpp b/lib/LD/RelocData.cpp
index 92192e6..1c9411d 100644
--- a/lib/LD/RelocData.cpp
+++ b/lib/LD/RelocData.cpp
@@ -7,9 +7,16 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/RelocData.h>
+#include <mcld/Support/GCFactory.h>
+
+#include <llvm/Support/ManagedStatic.h>
using namespace mcld;
+typedef GCFactory<RelocData, MCLD_SECTIONS_PER_INPUT> RelocDataFactory;
+
+static llvm::ManagedStatic<RelocDataFactory> g_RelocDataFactory;
+
//===----------------------------------------------------------------------===//
// RelocData
//===----------------------------------------------------------------------===//
@@ -17,23 +24,32 @@
: m_pSection(NULL) {
}
-RelocData::RelocData(const LDSection &pSection)
+RelocData::RelocData(LDSection &pSection)
: m_pSection(&pSection) {
}
-RelocData* RelocData::Create(const LDSection& pSection)
+RelocData* RelocData::Create(LDSection& pSection)
{
- return new RelocData(pSection);
-}
-
-RelocData* RelocData::Create()
-{
- return new RelocData();
+ RelocData* result = g_RelocDataFactory->allocate();
+ new (result) RelocData(pSection);
+ return result;
}
void RelocData::Destroy(RelocData*& pSection)
{
- delete pSection;
+ pSection->~RelocData();
+ g_RelocDataFactory->deallocate(pSection);
pSection = NULL;
}
+void RelocData::Clear()
+{
+ g_RelocDataFactory->clear();
+}
+
+RelocData& RelocData::append(Relocation& pRelocation)
+{
+ m_Relocations.push_back(&pRelocation);
+ return *this;
+}
+
diff --git a/lib/LD/RelocationFactory.cpp b/lib/LD/RelocationFactory.cpp
index 6fb6cb2..52bf45c 100644
--- a/lib/LD/RelocationFactory.cpp
+++ b/lib/LD/RelocationFactory.cpp
@@ -6,62 +6,69 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include <mcld/LD/RelocationFactory.h>
-
-#include <cstring>
-#include <cassert>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/Support/MsgHandling.h>
#include <llvm/Support/Host.h>
-#include <mcld/Target/GOT.h>
-#include <mcld/Target/TargetLDBackend.h>
+#include <cstring>
+#include <cassert>
using namespace mcld;
//===----------------------------------------------------------------------===//
// RelocationFactory
//===----------------------------------------------------------------------===//
-RelocationFactory::RelocationFactory(size_t pNum)
- : GCFactory<Relocation, 0>(pNum),
- m_pLinker(NULL) {
+RelocationFactory::RelocationFactory()
+ : GCFactory<Relocation, MCLD_RELOCATIONS_PER_INPUT>(), m_pConfig(NULL) {
}
-RelocationFactory::~RelocationFactory()
+void RelocationFactory::setConfig(const LinkerConfig& pConfig)
{
+ m_pConfig = &pConfig;
}
Relocation* RelocationFactory::produce(RelocationFactory::Type pType,
FragmentRef& pFragRef,
Address pAddend)
{
+ if (NULL == m_pConfig) {
+ fatal(diag::reloc_factory_has_not_config);
+ return NULL;
+ }
+
// target_data is the place where the relocation applys to.
// Use TargetDataFactory to generate temporary data, and copy the
// content of the fragment into this data.
DWord target_data = 0;
// byte swapping if the host and target have different endian
- if(llvm::sys::isLittleEndianHost() != getTarget().isLittleEndian()) {
+ if(llvm::sys::isLittleEndianHost() != m_pConfig->targets().isLittleEndian()) {
uint32_t tmp_data;
- switch(getTarget().bitclass()) {
- case 32u:
- pFragRef.memcpy(&tmp_data, 4);
- tmp_data = bswap32(tmp_data);
- target_data = tmp_data;
- break;
-
- case 64u:
- pFragRef.memcpy(&target_data, 8);
- target_data = bswap64(target_data);
- break;
-
- default:
- break;
- }
+ switch (m_pConfig->targets().bitclass()) {
+ case 32: {
+ pFragRef.memcpy(&tmp_data, 4);
+ tmp_data = mcld::bswap32(tmp_data);
+ target_data = tmp_data;
+ break;
+ }
+ case 64: {
+ pFragRef.memcpy(&target_data, 8);
+ target_data = mcld::bswap64(target_data);
+ break;
+ }
+ default: {
+ fatal(diag::unsupported_bitclass) << m_pConfig->targets().triple().str()
+ << m_pConfig->targets().bitclass();
+ return NULL;
+ }
+ } // end of switch
}
else {
- pFragRef.memcpy(&target_data, (getTarget().bitclass()/8));
+ pFragRef.memcpy(&target_data, (m_pConfig->targets().bitclass()/8));
}
Relocation *result = allocate();
@@ -83,19 +90,3 @@
/** GCFactory will recycle the relocation **/
}
-void RelocationFactory::setFragmentLinker(const FragmentLinker& pLinker)
-{
- m_pLinker = &pLinker;
-}
-
-const FragmentLinker& RelocationFactory::getFragmentLinker() const
-{
- assert(NULL != m_pLinker);
- return *m_pLinker;
-}
-
-bool RelocationFactory::hasFragmentLinker() const
-{
- return (NULL != m_pLinker);
-}
-
diff --git a/lib/LD/SectionData.cpp b/lib/LD/SectionData.cpp
index 43800ff..bb73724 100644
--- a/lib/LD/SectionData.cpp
+++ b/lib/LD/SectionData.cpp
@@ -44,3 +44,8 @@
pSection = NULL;
}
+void SectionData::Clear()
+{
+ g_SectDataFactory->clear();
+}
+
diff --git a/lib/LD/SectionSymbolSet.cpp b/lib/LD/SectionSymbolSet.cpp
index 79f4d78..e369412 100644
--- a/lib/LD/SectionSymbolSet.cpp
+++ b/lib/LD/SectionSymbolSet.cpp
@@ -64,13 +64,16 @@
bool SectionSymbolSet::finalize(LDSection& pOutSect,
SymbolTable& pSymTab)
{
+ if (0x0 == pOutSect.size())
+ return true;
+
LDSymbol* sym = get(pOutSect);
assert(NULL != sym);
FragmentRef* frag_ref = NULL;
switch (pOutSect.kind()) {
case LDFileFormat::Relocation:
- frag_ref = FragmentRef::Create(pOutSect.getRelocData()->front(), 0x0);
- break;
+ // Relocation section should not have section symbol.
+ return true;
case LDFileFormat::EhFrame:
frag_ref = FragmentRef::Create(
diff --git a/lib/LD/StubFactory.cpp b/lib/LD/StubFactory.cpp
index 1fc43dd..cbe14b2 100644
--- a/lib/LD/StubFactory.cpp
+++ b/lib/LD/StubFactory.cpp
@@ -6,25 +6,23 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include <mcld/LD/StubFactory.h>
#include <mcld/LD/BranchIslandFactory.h>
#include <mcld/LD/BranchIsland.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/RelocationFactory.h>
#include <mcld/Fragment/Stub.h>
#include <mcld/Fragment/Relocation.h>
#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Fragment/FragmentRef.h>
#include <string>
+
using namespace mcld;
-StubFactory::StubFactory()
-{
-}
-
+//===----------------------------------------------------------------------===//
+// StubFactory
+//===----------------------------------------------------------------------===//
StubFactory::~StubFactory()
{
for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
@@ -42,7 +40,6 @@
Stub* StubFactory::create(Relocation& pReloc,
uint64_t pTargetSymValue,
FragmentLinker& pLinker,
- RelocationFactory& pRelocFactory,
BranchIslandFactory& pBRIslandFactory)
{
// find if there is a prototype stub for the input relocation
@@ -93,8 +90,7 @@
for (Stub::fixup_iterator it = stub->fixup_begin(),
ie = stub->fixup_end(); it != ie; ++it) {
- Relocation* reloc = pRelocFactory.produce(
- (*it)->type(),
+ Relocation* reloc = Relocation::Create((*it)->type(),
*(FragmentRef::Create(*stub, (*it)->offset())),
(*it)->addend());
reloc->setSymInfo(pReloc.symInfo());
diff --git a/lib/Object/ObjectLinker.cpp b/lib/Object/ObjectLinker.cpp
index 93fdb20..1e2ccb4 100644
--- a/lib/Object/ObjectLinker.cpp
+++ b/lib/Object/ObjectLinker.cpp
@@ -11,7 +11,7 @@
#include <mcld/LinkerConfig.h>
#include <mcld/Module.h>
#include <mcld/InputTree.h>
-#include <mcld/MC/InputBuilder.h>
+#include <mcld/IRBuilder.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDContext.h>
#include <mcld/LD/Archive.h>
@@ -19,11 +19,12 @@
#include <mcld/LD/ObjectReader.h>
#include <mcld/LD/DynObjReader.h>
#include <mcld/LD/GroupReader.h>
+#include <mcld/LD/BinaryReader.h>
#include <mcld/LD/ObjectWriter.h>
#include <mcld/LD/DynObjWriter.h>
#include <mcld/LD/ExecWriter.h>
+#include <mcld/LD/BinaryWriter.h>
#include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/Layout.h>
#include <mcld/LD/RelocData.h>
#include <mcld/Support/RealPath.h>
#include <mcld/Support/MemoryArea.h>
@@ -39,20 +40,22 @@
ObjectLinker::ObjectLinker(const LinkerConfig& pConfig,
Module& pModule,
- InputBuilder& pInputBuilder,
+ IRBuilder& pBuilder,
TargetLDBackend& pLDBackend)
: m_Config(pConfig),
m_Module(pModule),
- m_InputBuilder(pInputBuilder),
+ m_Builder(pBuilder),
m_pLinker(NULL),
m_LDBackend(pLDBackend),
m_pObjectReader(NULL),
m_pDynObjReader(NULL),
m_pArchiveReader(NULL),
+ m_pGroupReader(NULL),
+ m_pBinaryReader(NULL),
m_pObjectWriter(NULL),
m_pDynObjWriter(NULL),
m_pExecWriter(NULL),
- m_pGroupReader(NULL)
+ m_pBinaryWriter(NULL)
{
// set up soname
if (!m_Config.options().soname().empty()) {
@@ -66,10 +69,12 @@
delete m_pObjectReader;
delete m_pDynObjReader;
delete m_pArchiveReader;
+ delete m_pGroupReader;
+ delete m_pBinaryReader;
delete m_pObjectWriter;
delete m_pDynObjWriter;
delete m_pExecWriter;
- delete m_pGroupReader;
+ delete m_pBinaryWriter;
}
/// initFragmentLinker - initialize FragmentLinker
@@ -85,17 +90,19 @@
// initialize the readers and writers
// Because constructor can not be failed, we initalize all readers and
// writers outside the FragmentLinker constructors.
- m_pObjectReader = m_LDBackend.createObjectReader(*m_pLinker);
+ m_pObjectReader = m_LDBackend.createObjectReader(m_Builder);
m_pArchiveReader = m_LDBackend.createArchiveReader(m_Module);
- m_pDynObjReader = m_LDBackend.createDynObjReader(*m_pLinker);
- m_pObjectWriter = m_LDBackend.createObjectWriter(*m_pLinker);
- m_pDynObjWriter = m_LDBackend.createDynObjWriter(*m_pLinker);
- m_pExecWriter = m_LDBackend.createExecWriter(*m_pLinker);
+ m_pDynObjReader = m_LDBackend.createDynObjReader(m_Builder);
m_pGroupReader = new GroupReader(m_Module, *m_pObjectReader,
*m_pDynObjReader, *m_pArchiveReader);
+ m_pBinaryReader = m_LDBackend.createBinaryReader(m_Builder);
+ m_pObjectWriter = m_LDBackend.createObjectWriter();
+ m_pDynObjWriter = m_LDBackend.createDynObjWriter();
+ m_pExecWriter = m_LDBackend.createExecWriter();
+ m_pBinaryWriter = m_LDBackend.createBinaryWriter();
- // initialize RelocationFactory
- m_LDBackend.initRelocFactory(*m_pLinker);
+ // initialize Relocator
+ m_LDBackend.initRelocator(*m_pLinker);
// initialize BranchIslandFactory
m_LDBackend.initBRIslandFactory();
@@ -130,7 +137,7 @@
for (input = m_Module.input_begin(); input!=inEnd; ++input) {
// is a group node
if (isGroup(input)) {
- getGroupReader()->readGroup(input, m_InputBuilder, m_Config);
+ getGroupReader()->readGroup(input, m_Builder.getInputBuilder(), m_Config);
continue;
}
@@ -151,8 +158,14 @@
continue;
}
+ // read input as a binary file
+ if (m_Config.options().isBinaryInput()) {
+ (*input)->setType(Input::Object);
+ getBinaryReader()->readBinary(**input);
+ m_Module.getObjectList().push_back(*input);
+ }
// is a relocatable object file
- if (getObjectReader()->isMyFormat(**input)) {
+ else if (getObjectReader()->isMyFormat(**input)) {
(*input)->setType(Input::Object);
getObjectReader()->readHeader(**input);
getObjectReader()->readSections(**input);
@@ -169,7 +182,7 @@
// is an archive
else if (getArchiveReader()->isMyFormat(**input)) {
(*input)->setType(Input::Archive);
- Archive archive(**input, m_InputBuilder);
+ Archive archive(**input, m_Builder.getInputBuilder());
getArchiveReader()->readArchive(archive);
if(archive.numOfObjectMember() > 0) {
m_Module.getInputTree().merge<InputTree::Inclusive>(input,
@@ -178,7 +191,7 @@
}
else {
fatal(diag::err_unrecognized_input_file) << (*input)->path()
- << m_Config.triple().str();
+ << m_Config.targets().triple().str();
}
} // end of for
}
@@ -342,18 +355,16 @@
{
// finalize the section symbols, set their fragment reference and push them
// into output symbol table
- Module::iterator iter, iterEnd = m_Module.end();
- for (iter = m_Module.begin(); iter != iterEnd; ++iter) {
- LDSection* section = *iter;
- if (0x0 == section->size() || LDFileFormat::Relocation == section->kind())
- continue;
- m_Module.getSectionSymbolSet().finalize(
- *section, m_Module.getSymbolTable());
+ Module::iterator sect, sEnd = m_Module.end();
+ for (sect = m_Module.begin(); sect != sEnd; ++sect) {
+ m_Module.getSectionSymbolSet().finalize(**sect, m_Module.getSymbolTable());
}
m_LDBackend.preLayout(m_Module, *m_pLinker);
- m_LDBackend.allocateCommonSymbols(m_Module);
+ if (LinkerConfig::Object != m_Config.codeGenType() ||
+ m_Config.options().isDefineCommon())
+ m_LDBackend.allocateCommonSymbols(m_Module);
/// check program interpreter - computer the name size of the runtime dyld
if (!m_pLinker->isStaticLink() &&
@@ -380,8 +391,8 @@
/// directly
bool ObjectLinker::layout()
{
- Layout layout;
- return layout.layout(m_Module, m_LDBackend, m_Config);
+ m_LDBackend.layout(m_Module, *m_pLinker);
+ return true;
}
/// prelayout - help backend to do some modification after layout
@@ -422,6 +433,9 @@
case LinkerConfig::Exec:
getExecWriter()->writeExecutable(m_Module, pOutput);
return true;
+ case LinkerConfig::Binary:
+ getBinaryWriter()->writeBinary(m_Module, pOutput);
+ return true;
default:
fatal(diag::unrecognized_output_file) << m_Config.codeGenType();
}
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 891b2bb..15cd816 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -16,6 +16,45 @@
using namespace mcld;
+static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff
+
+//===----------------------------------------------------------------------===//
+// SearchDirParser
+//===----------------------------------------------------------------------===//
+// parse - Return true on error.
+bool SearchDirParser::parse(Option &pOption,
+ StringRef pArgName,
+ StringRef pArg,
+ std::string &pValue)
+{
+ char separator = *(pArgName.data() + 1);
+ if ('=' == separator)
+ pValue = '=';
+ pValue += pArg.str();
+ return false;
+}
+
+void SearchDirParser::printOptionDiff(const Option &pOption,
+ StringRef pValue,
+ OptVal pDefault,
+ size_t pGlobalWidth) const
+{
+ printOptionName(pOption, pGlobalWidth);
+ outs() << "= " << pValue;
+ size_t NumSpaces = MaxOptWidth > pValue.size()?MaxOptWidth - pValue.size():0;
+ outs().indent(NumSpaces) << " (default: ";
+ if (pDefault.hasValue())
+ outs() << pDefault.getValue();
+ else
+ outs() << "*no default*";
+ outs() << ")\n";
+}
+
+void SearchDirParser::anchor()
+{
+ // do nothing
+}
+
//===----------------------------------------------------------------------===//
// parser<mcld::sys::fs::Path>
//===----------------------------------------------------------------------===//
@@ -28,8 +67,6 @@
return false;
}
-static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff
-
void parser<mcld::sys::fs::Path>::printOptionDiff(const llvm::cl::Option &O,
const mcld::sys::fs::Path &V,
parser<mcld::sys::fs::Path>::OptVal Default,
@@ -53,40 +90,6 @@
}
//===----------------------------------------------------------------------===//
-// parser<mcld::MCLDDirectory>
-//===----------------------------------------------------------------------===//
-bool parser<mcld::MCLDDirectory>::parse(llvm::cl::Option &O,
- llvm::StringRef ArgName,
- llvm::StringRef Arg,
- mcld::MCLDDirectory &Val)
-{
- Val.assign(Arg);
- return false;
-}
-
-void parser<mcld::MCLDDirectory>::printOptionDiff(const llvm::cl::Option &O,
- const mcld::MCLDDirectory &V,
- parser<mcld::MCLDDirectory>::OptVal Default,
- size_t GlobalWidth) const
-{
- printOptionName(O, GlobalWidth);
- outs() << "= " << V.name();
- size_t VSize = V.name().size();
- size_t NumSpaces = MaxOptWidth > VSize ? MaxOptWidth - VSize : 0;
- outs().indent(NumSpaces) << " (default: ";
- if (Default.hasValue())
- outs() << Default.getValue().name();
- else
- outs() << "*no default*";
- outs() << ")\n";
-}
-
-void parser<mcld::MCLDDirectory>::anchor()
-{
- // do nothing
-}
-
-//===----------------------------------------------------------------------===//
// parser<mcld::ZOption>
//===----------------------------------------------------------------------===//
bool parser<mcld::ZOption>::parse(llvm::cl::Option &O,
diff --git a/lib/Support/RegionFactory.cpp b/lib/Support/RegionFactory.cpp
index 7ed87f1..a52921b 100644
--- a/lib/Support/RegionFactory.cpp
+++ b/lib/Support/RegionFactory.cpp
@@ -9,6 +9,8 @@
#include <mcld/Support/RegionFactory.h>
#include <mcld/Support/Space.h>
+#include <new>
+
using namespace mcld;
//===----------------------------------------------------------------------===//
diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index 8bfa235..38074d5 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/lib/Support/TargetRegistry.cpp
@@ -16,7 +16,8 @@
s_TargetList.push_back(&T);
}
-const mcld::Target* mcld::TargetRegistry::lookupTarget(const llvm::Target &pTarget)
+const mcld::Target*
+mcld::TargetRegistry::lookupTarget(const llvm::Target &pTarget)
{
mcld::Target *result = 0;
TargetListTy::const_iterator TIter, TEnd = s_TargetList.end();
@@ -29,12 +30,14 @@
return result;
}
-const mcld::Target *mcld::TargetRegistry::lookupTarget(const std::string &pTriple,
- std::string &pError)
+const mcld::Target*
+mcld::TargetRegistry::lookupTarget(const std::string &pTriple,
+ std::string &pError)
{
const llvm::Target* target = llvm::TargetRegistry::lookupTarget(pTriple, pError);
if (!target)
- return 0;
+ return NULL;
+
return lookupTarget( *target );
}
diff --git a/lib/Target/ARM/ARMELFDynamic.cpp b/lib/Target/ARM/ARMELFDynamic.cpp
index c81a6f3..cbec6e8 100644
--- a/lib/Target/ARM/ARMELFDynamic.cpp
+++ b/lib/Target/ARM/ARMELFDynamic.cpp
@@ -6,14 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include "ARMELFDynamic.h"
#include <mcld/LD/ELFFileFormat.h>
-#include "ARMELFDynamic.h"
using namespace mcld;
-ARMELFDynamic::ARMELFDynamic(const GNULDBackend& pParent)
- : ELFDynamic(pParent)
+ARMELFDynamic::ARMELFDynamic(const GNULDBackend& pParent,
+ const LinkerConfig& pConfig)
+ : ELFDynamic(pParent, pConfig)
{
}
diff --git a/lib/Target/ARM/ARMELFDynamic.h b/lib/Target/ARM/ARMELFDynamic.h
index 914dcc4..826070b 100644
--- a/lib/Target/ARM/ARMELFDynamic.h
+++ b/lib/Target/ARM/ARMELFDynamic.h
@@ -18,7 +18,7 @@
class ARMELFDynamic : public ELFDynamic {
public:
- ARMELFDynamic(const GNULDBackend& pParent);
+ ARMELFDynamic(const GNULDBackend& pParent, const LinkerConfig& pConfig);
~ARMELFDynamic();
private:
diff --git a/lib/Target/ARM/ARMEmulation.cpp b/lib/Target/ARM/ARMEmulation.cpp
index 875d229..3995618 100644
--- a/lib/Target/ARM/ARMEmulation.cpp
+++ b/lib/Target/ARM/ARMEmulation.cpp
@@ -18,6 +18,10 @@
if (!MCLDEmulateELF(pConfig))
return false;
+ // set up bitclass and endian
+ pConfig.targets().setEndian(TargetOptions::Little);
+ pConfig.targets().setBitClass(32);
+
// set up target-dependent constraints of attributes
pConfig.attribute().constraint().enableWholeArchive();
pConfig.attribute().constraint().enableAsNeeded();
diff --git a/lib/Target/ARM/ARMGNUInfo.h b/lib/Target/ARM/ARMGNUInfo.h
new file mode 100644
index 0000000..9091dce
--- /dev/null
+++ b/lib/Target/ARM/ARMGNUInfo.h
@@ -0,0 +1,29 @@
+//===- ARMGNUInfo.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_ARM_GNU_INFO_H
+#define MCLD_TARGET_ARM_GNU_INFO_H
+#include <mcld/Target/GNUInfo.h>
+
+#include <llvm/Support/ELF.h>
+
+namespace mcld {
+
+class ARMGNUInfo : public GNUInfo
+{
+public:
+ ARMGNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
+
+ uint32_t machine() const { return llvm::ELF::EM_ARM; }
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
index 3d2d07a..1796635 100644
--- a/lib/Target/ARM/ARMGOT.cpp
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -8,8 +8,6 @@
//===----------------------------------------------------------------------===//
#include "ARMGOT.h"
-#include <new>
-
#include <llvm/Support/Casting.h>
#include <mcld/LD/LDSection.h>
@@ -18,7 +16,6 @@
#include <mcld/Support/MsgHandling.h>
namespace {
- const size_t ARMGOTEntrySize = 4;
const unsigned int ARMGOT0Num = 3;
} // end of anonymous namespace
@@ -27,7 +24,7 @@
//===----------------------------------------------------------------------===//
// ARMGOT
ARMGOT::ARMGOT(LDSection& pSection)
- : GOT(pSection, ARMGOTEntrySize)
+ : GOT(pSection), m_pLast(NULL)
{
// Create GOT0 entries.
reserve(ARMGOT0Num);
@@ -47,9 +44,28 @@
return (m_SectionData->size() > ARMGOT0Num);
}
+void ARMGOT::reserve(size_t pNum)
+{
+ for (size_t i = 0; i < pNum; i++) {
+ new ARMGOTEntry(0, m_SectionData);
+ }
+}
+
+ARMGOTEntry* ARMGOT::consume()
+{
+ if (NULL == m_pLast) {
+ assert(!empty() && "Consume empty GOT entry!");
+ m_pLast = llvm::cast<ARMGOTEntry>(&m_SectionData->front());
+ return m_pLast;
+ }
+
+ m_pLast = llvm::cast<ARMGOTEntry>(m_pLast->getNextNode());
+ return m_pLast;
+}
+
void ARMGOT::reserveGOTPLT()
{
- Entry* entry = new Entry(0, getEntrySize(), m_SectionData);
+ ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData);
if (NULL == m_GOTPLT.front) {
// GOTPLT is empty
if (NULL == m_GOT.front) {
@@ -60,26 +76,26 @@
else {
// GOTn is not empty. Shift GOTn backward by one entry.
m_GOTPLT.front = m_GOT.front;
- m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode());
+ m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode());
}
}
else {
// GOTPLT is not empty
if (NULL != m_GOT.front)
- m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode());
+ m_GOT.front = llvm::cast<ARMGOTEntry>(m_GOT.front->getNextNode());
}
}
void ARMGOT::reserveGOT()
{
- Entry* entry = new Entry(0, getEntrySize(), m_SectionData);
+ ARMGOTEntry* entry = new ARMGOTEntry(0, m_SectionData);
if (NULL == m_GOT.front) {
// Entry must be the last entry. We can directly assign it to GOT part.
m_GOT.front = entry;
}
}
-GOT::Entry* ARMGOT::consumeGOTPLT()
+ARMGOTEntry* ARMGOT::consumeGOTPLT()
{
assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!");
@@ -87,13 +103,13 @@
m_GOTPLT.last_used = m_GOTPLT.front;
}
else {
- m_GOTPLT.last_used = llvm::cast<GOT::Entry>(m_GOTPLT.last_used->getNextNode());
+ m_GOTPLT.last_used = llvm::cast<ARMGOTEntry>(m_GOTPLT.last_used->getNextNode());
assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!");
}
return m_GOTPLT.last_used;
}
-GOT::Entry* ARMGOT::consumeGOT()
+ARMGOTEntry* ARMGOT::consumeGOT()
{
assert(NULL != m_GOT.front && "Consuming empty GOT section!");
@@ -101,7 +117,7 @@
m_GOT.last_used = m_GOT.front;
}
else {
- m_GOT.last_used = llvm::cast<GOT::Entry>(m_GOT.last_used->getNextNode());
+ m_GOT.last_used = llvm::cast<ARMGOTEntry>(m_GOT.last_used->getNextNode());
assert(m_GOT.last_used != NULL && "No GOTn entry to consume!");
}
return m_GOT.last_used;
@@ -109,8 +125,8 @@
void ARMGOT::applyGOT0(uint64_t pAddress)
{
- llvm::cast<Entry>
- (*(m_SectionData->getFragmentList().begin())).setContent(pAddress);
+ llvm::cast<ARMGOTEntry>
+ (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
}
void ARMGOT::applyGOTPLT(uint64_t pPLTBase)
@@ -126,7 +142,7 @@
e_end = SectionData::iterator(m_GOT.front);
while (entry != e_end) {
- llvm::cast<GOT::Entry>(entry)->setContent(pPLTBase);
+ llvm::cast<ARMGOTEntry>(entry)->setValue(pPLTBase);
++entry;
}
}
@@ -135,13 +151,12 @@
{
uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
- Entry* got = 0;
- unsigned int entry_size = getEntrySize();
+ ARMGOTEntry* got = NULL;
uint64_t result = 0x0;
for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
- got = &(llvm::cast<Entry>((*it)));
- *buffer = static_cast<uint32_t>(got->getContent());
- result += entry_size;
+ got = &(llvm::cast<ARMGOTEntry>((*it)));
+ *buffer = static_cast<uint32_t>(got->getValue());
+ result += ARMGOTEntry::EntrySize;
}
return result;
}
diff --git a/lib/Target/ARM/ARMGOT.h b/lib/Target/ARM/ARMGOT.h
index 1e8f383..be22c67 100644
--- a/lib/Target/ARM/ARMGOT.h
+++ b/lib/Target/ARM/ARMGOT.h
@@ -21,6 +21,17 @@
class LDSection;
class MemoryRegion;
+/** \class ARMGOTEntry
+ * \brief GOT Entry with size of 4 bytes
+ */
+class ARMGOTEntry : public GOT::Entry<4>
+{
+public:
+ ARMGOTEntry(uint64_t pContent, SectionData* pParent)
+ : GOT::Entry<4>(pContent, pParent)
+ {}
+};
+
/** \class ARMGOT
* \brief ARM Global Offset Table.
*
@@ -45,13 +56,17 @@
~ARMGOT();
+ void reserve(size_t pNum = 1);
+
void reserveGOTPLT();
void reserveGOT();
- GOT::Entry* consumeGOT();
+ ARMGOTEntry* consume();
- GOT::Entry* consumeGOTPLT();
+ ARMGOTEntry* consumeGOT();
+
+ ARMGOTEntry* consumeGOTPLT();
uint64_t emit(MemoryRegion& pRegion);
@@ -67,14 +82,15 @@
Part() : front(NULL), last_used(NULL) { }
public:
- GOT::Entry* front;
- GOT::Entry* last_used;
+ ARMGOTEntry* front;
+ ARMGOTEntry* last_used;
};
private:
Part m_GOTPLT;
Part m_GOT;
+ ARMGOTEntry* m_pLast; ///< the last consumed entry
};
} // namespace of mcld
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index a90ae63..2fd7e64 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -7,9 +7,10 @@
//
//===----------------------------------------------------------------------===//
#include "ARM.h"
+#include "ARMGNUInfo.h"
#include "ARMELFDynamic.h"
#include "ARMLDBackend.h"
-#include "ARMRelocationFactory.h"
+#include "ARMRelocator.h"
#include "ARMToARMStub.h"
#include "ARMToTHMStub.h"
#include "THMToTHMStub.h"
@@ -38,15 +39,16 @@
#include <mcld/Object/ObjectBuilder.h>
#include <mcld/Fragment/NullFragment.h>
#include <mcld/LD/LDContext.h>
+#include <mcld/Target/GNUInfo.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
// ARMGNULDBackend
//===----------------------------------------------------------------------===//
-ARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig)
- : GNULDBackend(pConfig),
- m_pRelocFactory(NULL),
+ARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo)
+ : GNULDBackend(pConfig, pInfo),
+ m_pRelocator(NULL),
m_pGOT(NULL),
m_pPLT(NULL),
m_pRelDyn(NULL),
@@ -62,7 +64,7 @@
ARMGNULDBackend::~ARMGNULDBackend()
{
- delete m_pRelocFactory;
+ delete m_pRelocator;
delete m_pGOT;
delete m_pPLT;
delete m_pRelDyn;
@@ -70,21 +72,6 @@
delete m_pDynamic;
}
-bool ARMGNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
-{
- if (NULL == m_pRelocFactory) {
- m_pRelocFactory = new ARMRelocationFactory(1024, *this);
- m_pRelocFactory->setFragmentLinker(pLinker);
- }
- return true;
-}
-
-RelocationFactory* ARMGNULDBackend::getRelocFactory()
-{
- assert(NULL != m_pRelocFactory);
- return m_pRelocFactory;
-}
-
void ARMGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
{
// FIXME: Currently we set exidx and extab to "Exception" and directly emit
@@ -93,7 +80,7 @@
LDFileFormat::Target,
llvm::ELF::SHT_ARM_EXIDX,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
- bitclass() / 8);
+ config().targets().bitclass() / 8);
m_pEXTAB = pBuilder.CreateSection(".ARM.extab",
LDFileFormat::Target,
llvm::ELF::SHT_PROGBITS,
@@ -120,15 +107,11 @@
LDSection& relplt = file_format->getRelPlt();
relplt.setLink(&plt);
// create SectionData and ARMRelDynSection
- m_pRelPLT = new OutputRelocSection(pModule,
- relplt,
- getRelEntrySize());
+ m_pRelPLT = new OutputRelocSection(pModule, relplt);
// initialize .rel.dyn
LDSection& reldyn = file_format->getRelDyn();
- m_pRelDyn = new OutputRelocSection(pModule,
- reldyn,
- getRelEntrySize());
+ m_pRelDyn = new OutputRelocSection(pModule, reldyn);
}
}
@@ -184,6 +167,21 @@
ResolveInfo::Hidden);
}
+bool ARMGNULDBackend::initRelocator(const FragmentLinker& pLinker)
+{
+ if (NULL == m_pRelocator) {
+ m_pRelocator = new ARMRelocator(*this);
+ m_pRelocator->setFragmentLinker(pLinker);
+ }
+ return true;
+}
+
+Relocator* ARMGNULDBackend::getRelocator()
+{
+ assert(NULL != m_pRelocator);
+ return m_pRelocator;
+}
+
void ARMGNULDBackend::doPreLayout(FragmentLinker& pLinker)
{
// set .got size
@@ -200,13 +198,16 @@
if (m_pPLT->hasPLT1())
m_pPLT->finalizeSectionSize();
+ ELFFileFormat* file_format = getOutputFormat();
// set .rel.dyn size
if (!m_pRelDyn->empty())
- m_pRelDyn->finalizeSectionSize();
+ file_format->getRelDyn().setSize(
+ m_pRelDyn->numOfRelocs() * getRelEntrySize());
// set .rel.plt size
if (!m_pRelPLT->empty())
- m_pRelPLT->finalizeSectionSize();
+ file_format->getRelPlt().setSize(
+ m_pRelPLT->numOfRelocs() * getRelEntrySize());
}
}
@@ -242,7 +243,7 @@
ARMELFDynamic& ARMGNULDBackend::dynamic()
{
if (NULL == m_pDynamic)
- m_pDynamic = new ARMELFDynamic(*this);
+ m_pDynamic = new ARMELFDynamic(*this, config());
return *m_pDynamic;
}
@@ -320,7 +321,7 @@
// Determine the alignment by the symbol value
// FIXME: here we use the largest alignment
- uint32_t addralign = bitclass() / 8;
+ uint32_t addralign = config().targets().bitclass() / 8;
// allocate space in BSS for the copy symbol
Fragment* frag = new FillFragment(0x0, 1, pSym.size());
@@ -398,7 +399,7 @@
// a dynamic relocations with RELATIVE type to this location is needed.
// Reserve an entry in .rel.dyn
if (pLinker.isOutputPIC()) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set Rel bit
rsym->setReserved(rsym->reserved() | ReserveRel);
}
@@ -444,7 +445,7 @@
// Reserve an entry in .rel.dyn
if (pLinker.isOutputPIC()) {
// create .rel.dyn section if not exist
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | 0x4u);
return;
@@ -512,7 +513,7 @@
// in .got and .rel.plt. (GOT entry will be reserved simultaneously
// when calling ARMPLT->reserveEntry())
m_pPLT->reserveEntry();
- m_pRelPLT->reserveEntry(*m_pRelocFactory);
+ m_pRelPLT->reserveEntry();
// set PLT bit
rsym->setReserved(rsym->reserved() | ReservePLT);
}
@@ -521,7 +522,7 @@
if (symbolNeedsDynRel(
pLinker, *rsym, (rsym->reserved() & ReservePLT), true)) {
// symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
addCopyReloc(*cpy_sym.resolveInfo());
@@ -596,7 +597,7 @@
if (symbolNeedsDynRel(
pLinker, *rsym, (rsym->reserved() & ReservePLT), false)) {
// symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
addCopyReloc(*cpy_sym.resolveInfo());
@@ -644,7 +645,7 @@
// in .got and .rel.plt. (GOT entry will be reserved simultaneously
// when calling ARMPLT->reserveEntry())
m_pPLT->reserveEntry();
- m_pRelPLT->reserveEntry(*m_pRelocFactory);
+ m_pRelPLT->reserveEntry();
// set PLT bit
rsym->setReserved(rsym->reserved() | ReservePLT);
return;
@@ -666,7 +667,7 @@
// if the symbol cannot be fully resolved at link time, then we need a
// dynamic relocation
if (!symbolFinalValueIsKnown(pLinker, *rsym)) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
return;
@@ -718,7 +719,7 @@
// check if we shoule issue undefined reference for the relocation target
// symbol
- if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+ if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
fatal(diag::undefined_reference) << rsym->name();
if ((rsym->reserved() & ReserveRel) != 0x0) {
@@ -984,14 +985,13 @@
Stub* stub = getStubFactory()->create(*relocation, // relocation
sym_value, // symbol value
pLinker,
- *getRelocFactory(),
*getBRIslandFactory());
if (NULL != stub) {
assert(NULL != stub->symInfo());
// increase the size of .symtab and .strtab
LDSection& symtab = file_format->getSymTab();
LDSection& strtab = file_format->getStrTab();
- if (32 == bitclass())
+ if (config().targets().is32Bits())
symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
else
symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym));
@@ -1079,7 +1079,7 @@
TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget,
const LinkerConfig& pConfig)
{
- if (pConfig.triple().isOSDarwin()) {
+ if (pConfig.targets().triple().isOSDarwin()) {
assert(0 && "MachO linker is not supported yet");
/**
return new ARMMachOLDBackend(createARMMachOArchiveReader,
@@ -1087,7 +1087,7 @@
createARMMachOObjectWriter);
**/
}
- if (pConfig.triple().isOSWindows()) {
+ if (pConfig.targets().triple().isOSWindows()) {
assert(0 && "COFF linker is not supported yet");
/**
return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
@@ -1095,7 +1095,7 @@
createARMCOFFObjectWriter);
**/
}
- return new ARMGNULDBackend(pConfig);
+ return new ARMGNULDBackend(pConfig, new ARMGNUInfo(pConfig.targets().triple()));
}
} // namespace of mcld
diff --git a/lib/Target/ARM/ARMLDBackend.h b/lib/Target/ARM/ARMLDBackend.h
index 6cf531b..6110b1c 100644
--- a/lib/Target/ARM/ARMLDBackend.h
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -19,6 +19,7 @@
namespace mcld {
class LinkerConfig;
+class GNUInfo;
class FragmentLinker;
class SectionMap;
@@ -38,7 +39,7 @@
static const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4);
public:
- ARMGNULDBackend(const LinkerConfig& pConfig);
+ ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo);
~ARMGNULDBackend();
public:
@@ -94,11 +95,11 @@
/// initTargetSymbols - initialize target dependent symbols in output.
void initTargetSymbols(FragmentLinker& pLinker);
- /// initRelocFactory - create and initialize RelocationFactory
- bool initRelocFactory(const FragmentLinker& pLinker);
+ /// initRelocator - create and initialize Relocator.
+ bool initRelocator(const FragmentLinker& pLinker);
- /// getRelocFactory
- RelocationFactory* getRelocFactory();
+ /// getRelocator - return relocator.
+ Relocator* getRelocator();
/// scanRelocation - determine the empty entries are needed or not and create
/// the empty entries if needed.
@@ -111,27 +112,10 @@
Module& pModule,
const LDSection& pSection);
- uint32_t machine() const
- { return llvm::ELF::EM_ARM; }
-
- /// OSABI - the value of e_ident[EI_OSABI]
- virtual uint8_t OSABI() const
- { return llvm::ELF::ELFOSABI_NONE; }
-
- /// ABIVersion - the value of e_ident[EI_ABIVRESION]
- virtual uint8_t ABIVersion() const
- { return 0x0; }
-
/// flags - the value of ElfXX_Ehdr::e_flags
virtual uint64_t flags() const
{ return (llvm::ELF::EF_ARM_EABIMASK & 0x05000000); }
- bool isLittleEndian() const
- { return true; }
-
- unsigned int bitclass() const
- { return 32; }
-
uint64_t defaultTextSegmentAddr() const
{ return 0x8000; }
@@ -246,7 +230,8 @@
const FragmentLinker& pLinker);
private:
- RelocationFactory* m_pRelocFactory;
+ Relocator* m_pRelocator;
+
ARMGOT* m_pGOT;
ARMPLT* m_pPLT;
/// m_RelDyn - dynamic relocation table of .rel.dyn
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
index a5f4733..d7342ab 100644
--- a/lib/Target/ARM/ARMPLT.cpp
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -17,31 +17,13 @@
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
-namespace {
-
-const uint32_t arm_plt0[] = {
- 0xe52de004, // str lr, [sp, #-4]!
- 0xe59fe004, // ldr lr, [pc, #4]
- 0xe08fe00e, // add lr, pc, lr
- 0xe5bef008, // ldr pc, [lr, #8]!
- 0x00000000, // &GOT[0] - .
-};
-
-const uint32_t arm_plt1[] = {
- 0xe28fc600, // add ip, pc, #0xNN00000
- 0xe28cca00, // add ip, ip, #0xNN000
- 0xe5bcf000, // ldr pc, [ip, #0xNNN]!
-};
-
-} // anonymous namespace
-
using namespace mcld;
ARMPLT0::ARMPLT0(SectionData& pParent)
- : PLT::Entry(sizeof(arm_plt0), pParent) {}
+ : PLT::Entry<sizeof(arm_plt0)>(pParent) {}
ARMPLT1::ARMPLT1(SectionData& pParent)
- : PLT::Entry(sizeof(arm_plt1), pParent) {}
+ : PLT::Entry<sizeof(arm_plt1)>(pParent) {}
//===----------------------------------------------------------------------===//
// ARMPLT
@@ -134,15 +116,15 @@
ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
uint32_t* data = 0;
- data = static_cast<uint32_t*>(malloc(plt0->getEntrySize()));
+ data = static_cast<uint32_t*>(malloc(ARMPLT0::EntrySize));
if (!data)
fatal(diag::fail_allocate_memory_plt);
- memcpy(data, arm_plt0, plt0->getEntrySize());
+ memcpy(data, arm_plt0, ARMPLT0::EntrySize);
data[4] = offset;
- plt0->setContent(reinterpret_cast<unsigned char*>(data));
+ plt0->setValue(reinterpret_cast<unsigned char*>(data));
}
void ARMPLT::applyPLT1() {
@@ -157,21 +139,21 @@
ARMPLT::iterator ie = m_SectionData->end();
assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
- uint32_t GOTEntrySize = m_GOT.getEntrySize();
+ uint32_t GOTEntrySize = ARMGOTEntry::EntrySize;
uint32_t GOTEntryAddress =
got_base + GOTEntrySize * 3;
uint64_t PLTEntryAddress =
- plt_base + llvm::cast<ARMPLT0>((*it)).getEntrySize(); //Offset of PLT0
+ plt_base + ARMPLT0::EntrySize; //Offset of PLT0
++it; //skip PLT0
- uint64_t PLT1EntrySize = llvm::cast<ARMPLT1>((*it)).getEntrySize();
+ uint64_t PLT1EntrySize = ARMPLT1::EntrySize;
ARMPLT1* plt1 = NULL;
uint32_t* Out = NULL;
while (it != ie) {
plt1 = &(llvm::cast<ARMPLT1>(*it));
- Out = static_cast<uint32_t*>(malloc(plt1->getEntrySize()));
+ Out = static_cast<uint32_t*>(malloc(ARMPLT1::EntrySize));
if (!Out)
fatal(diag::fail_allocate_memory_plt);
@@ -184,7 +166,7 @@
Out[1] = arm_plt1[1] | ((Offset >> 12) & 0xFF);
Out[2] = arm_plt1[2] | (Offset & 0xFFF);
- plt1->setContent(reinterpret_cast<unsigned char*>(Out));
+ plt1->setValue(reinterpret_cast<unsigned char*>(Out));
++it;
GOTEntryAddress += GOTEntrySize;
@@ -198,21 +180,18 @@
{
uint64_t result = 0x0;
iterator it = begin();
- unsigned int plt0_size = llvm::cast<ARMPLT0>((*it)).getEntrySize();
unsigned char* buffer = pRegion.getBuffer();
- memcpy(buffer, llvm::cast<ARMPLT0>((*it)).getContent(), plt0_size);
- result += plt0_size;
+ memcpy(buffer, llvm::cast<ARMPLT0>((*it)).getValue(), ARMPLT0::EntrySize);
+ result += ARMPLT0::EntrySize;
++it;
ARMPLT1* plt1 = 0;
ARMPLT::iterator ie = end();
- unsigned int entry_size = 0;
while (it != ie) {
plt1 = &(llvm::cast<ARMPLT1>(*it));
- entry_size = plt1->getEntrySize();
- memcpy(buffer + result, plt1->getContent(), entry_size);
- result += entry_size;
+ memcpy(buffer + result, plt1->getValue(), ARMPLT1::EntrySize);
+ result += ARMPLT1::EntrySize;
++it;
}
return result;
diff --git a/lib/Target/ARM/ARMPLT.h b/lib/Target/ARM/ARMPLT.h
index 67b6f4e..9554f0c 100644
--- a/lib/Target/ARM/ARMPLT.h
+++ b/lib/Target/ARM/ARMPLT.h
@@ -12,17 +12,37 @@
#include <mcld/Target/GOT.h>
#include <mcld/Target/PLT.h>
+namespace {
+
+const uint32_t arm_plt0[] = {
+ 0xe52de004, // str lr, [sp, #-4]!
+ 0xe59fe004, // ldr lr, [pc, #4]
+ 0xe08fe00e, // add lr, pc, lr
+ 0xe5bef008, // ldr pc, [lr, #8]!
+ 0x00000000, // &GOT[0] - .
+};
+
+const uint32_t arm_plt1[] = {
+ 0xe28fc600, // add ip, pc, #0xNN00000
+ 0xe28cca00, // add ip, ip, #0xNN000
+ 0xe5bcf000, // ldr pc, [ip, #0xNNN]!
+};
+
+} // anonymous namespace
+
namespace mcld {
class ARMGOT;
class MemoryRegion;
-class ARMPLT0 : public PLT::Entry {
+class ARMPLT0 : public PLT::Entry<sizeof(arm_plt0)>
+{
public:
ARMPLT0(SectionData& pParent);
};
-class ARMPLT1 : public PLT::Entry {
+class ARMPLT1 : public PLT::Entry<sizeof(arm_plt1)>
+{
public:
ARMPLT1(SectionData& pParent);
};
diff --git a/lib/Target/ARM/ARMRelocationFunctions.h b/lib/Target/ARM/ARMRelocationFunctions.h
index 3f8b90e..cd25e2c 100644
--- a/lib/Target/ARM/ARMRelocationFunctions.h
+++ b/lib/Target/ARM/ARMRelocationFunctions.h
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#define DECL_ARM_APPLY_RELOC_FUNC(Name) \
-static ARMRelocationFactory::Result Name (Relocation& pEntry, \
- ARMRelocationFactory& pParent);
+static ARMRelocator::Result Name (Relocation& pEntry, \
+ ARMRelocator& pParent);
#define DECL_ARM_APPLY_RELOC_FUNCS \
DECL_ARM_APPLY_RELOC_FUNC(none) \
diff --git a/lib/Target/ARM/ARMRelocationFactory.cpp b/lib/Target/ARM/ARMRelocator.cpp
similarity index 63%
rename from lib/Target/ARM/ARMRelocationFactory.cpp
rename to lib/Target/ARM/ARMRelocator.cpp
index d668fc5..d613d66 100644
--- a/lib/Target/ARM/ARMRelocationFactory.cpp
+++ b/lib/Target/ARM/ARMRelocator.cpp
@@ -1,4 +1,4 @@
-//===- ARMRelocationFactory.cpp ----------------------------------------===//
+//===- ARMRelocator.cpp ----------------------------------------===//
//
// The MCLinker Project
//
@@ -12,9 +12,8 @@
#include <llvm/Support/ELF.h>
#include <llvm/Support/Host.h>
#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/LinkerConfig.h>
#include <mcld/Support/MsgHandling.h>
-#include "ARMRelocationFactory.h"
+#include "ARMRelocator.h"
#include "ARMRelocationFunctions.h"
using namespace mcld;
@@ -25,9 +24,8 @@
DECL_ARM_APPLY_RELOC_FUNCS
/// the prototype of applying function
-typedef RelocationFactory::Result (*ApplyFunctionType)(
- Relocation& pReloc,
- ARMRelocationFactory& pParent);
+typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
+ ARMRelocator& pParent);
// the table entry of applying functions
struct ApplyFunctionTriple
@@ -43,41 +41,40 @@
};
//===--------------------------------------------------------------------===//
-// ARMRelocationFactory
+// ARMRelocator
//===--------------------------------------------------------------------===//
-ARMRelocationFactory::ARMRelocationFactory(size_t pNum,
- ARMGNULDBackend& pParent)
- : RelocationFactory(pNum),
+ARMRelocator::ARMRelocator(ARMGNULDBackend& pParent)
+ : Relocator(),
m_Target(pParent) {
}
-ARMRelocationFactory::~ARMRelocationFactory()
+ARMRelocator::~ARMRelocator()
{
}
-RelocationFactory::Result
-ARMRelocationFactory::applyRelocation(Relocation& pRelocation)
+Relocator::Result
+ARMRelocator::applyRelocation(Relocation& pRelocation)
{
Relocation::Type type = pRelocation.type();
if (type > 130) { // 131-255 doesn't noted in ARM spec
- return RelocationFactory::Unknown;
+ return Relocator::Unknown;
}
return ApplyFunctions[type].func(pRelocation, *this);
}
-const char* ARMRelocationFactory::getName(RelocationFactory::Type pType) const
+const char* ARMRelocator::getName(Relocator::Type pType) const
{
return ApplyFunctions[pType].name;
}
//===--------------------------------------------------------------------===//
// non-member functions
-static RelocationFactory::DWord getThumbBit(const Relocation& pReloc)
+static Relocator::DWord getThumbBit(const Relocation& pReloc)
{
// Set thumb bit if
// - symbol has type of STT_FUNC, is defined and with bit 0 of its value set
- RelocationFactory::DWord thumbBit =
+ Relocator::DWord thumbBit =
((!pReloc.symInfo()->isUndef() || pReloc.symInfo()->isDyn()) &&
(pReloc.symInfo()->type() == ResolveInfo::Function) &&
((pReloc.symValue() & 0x1) != 0))?
@@ -112,7 +109,7 @@
// Check if symbol can use relocation R_ARM_RELATIVE
static bool
helper_use_relative_reloc(const ResolveInfo& pSym,
- const ARMRelocationFactory& pFactory)
+ const ARMRelocator& pFactory)
{
// if symbol is dynamic or undefine or preemptible
if (pSym.isDyn() ||
@@ -123,21 +120,21 @@
}
static
-GOT::Entry& helper_get_GOT_and_init(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMGOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
+ ARMRelocator& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
ARMGNULDBackend& ld_backend = pParent.getTarget();
- GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ ARMGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
if (NULL == got_entry) {
got_entry = ld_backend.getGOT().consumeGOT();
pParent.getSymGOTMap().record(*rsym, *got_entry);
// If we first get this GOT entry, we should initialize it.
if (rsym->reserved() & ARMGNULDBackend::ReserveGOT) {
// No corresponding dynamic relocation, initialize to the symbol value.
- got_entry->setContent(pReloc.symValue());
+ got_entry->setValue(pReloc.symValue());
}
else if (rsym->reserved() & ARMGNULDBackend::GOTRel) {
@@ -146,13 +143,13 @@
if ( rsym->isLocal() ||
helper_use_relative_reloc(*rsym, pParent)) {
// Initialize got entry to target symbol address
- got_entry->setContent(pReloc.symValue());
+ got_entry->setValue(pReloc.symValue());
rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
rel_entry.setSymInfo(0);
}
else {
// Initialize got entry to 0 for corresponding dynamic relocation.
- got_entry->setContent(0);
+ got_entry->setValue(0);
rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
rel_entry.setSymInfo(rsym);
}
@@ -166,30 +163,28 @@
}
static
-ARMRelocationFactory::Address helper_GOT_ORG(ARMRelocationFactory& pParent)
+ARMRelocator::Address helper_GOT_ORG(ARMRelocator& pParent)
{
return pParent.getTarget().getGOT().addr();
}
static
-ARMRelocationFactory::Address helper_GOT(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Address helper_GOT(Relocation& pReloc, ARMRelocator& pParent)
{
- GOT::Entry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
+ ARMGOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
return helper_GOT_ORG(pParent) + got_entry.getOffset();
}
static
-PLT::Entry& helper_get_PLT_and_init(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMPLT1& helper_get_PLT_and_init(Relocation& pReloc, ARMRelocator& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
ARMGNULDBackend& ld_backend = pParent.getTarget();
- PLT::Entry* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
+ ARMPLT1* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
if (NULL != plt_entry)
return *plt_entry;
@@ -198,7 +193,7 @@
// If we first get this PLT entry, we should initialize it.
if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
- GOT::Entry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
+ ARMGOTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
gotplt_entry = ld_backend.getGOT().consumeGOTPLT();
pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
@@ -217,26 +212,26 @@
}
static
-ARMRelocationFactory::Address helper_PLT_ORG(ARMRelocationFactory& pParent)
+ARMRelocator::Address helper_PLT_ORG(ARMRelocator& pParent)
{
return pParent.getTarget().getPLT().addr();
}
static
-ARMRelocationFactory::Address helper_PLT(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Address helper_PLT(Relocation& pReloc, ARMRelocator& pParent)
{
- PLT::Entry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
+ ARMPLT1& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
return helper_PLT_ORG(pParent) + plt_entry.getOffset();
}
// Get an relocation entry in .rel.dyn and set its type to pType,
-// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo()
+// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to
+// pReloc->symInfo()
static
void helper_DynRel(Relocation& pReloc,
- ARMRelocationFactory::Type pType,
- ARMRelocationFactory& pParent)
+ ARMRelocator::Type pType,
+ ARMRelocator& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
@@ -252,17 +247,17 @@
rel_entry.setSymInfo(rsym);
}
-static ARMRelocationFactory::DWord
-helper_extract_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
+static ARMRelocator::DWord
+helper_extract_movw_movt_addend(ARMRelocator::DWord pTarget)
{
// imm16: [19-16][11-0]
return helper_sign_extend((((pTarget >> 4)) & 0xf000U) | (pTarget & 0xfffU),
16);
}
-static ARMRelocationFactory::DWord
-helper_insert_val_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
- ARMRelocationFactory::DWord pImm)
+static ARMRelocator::DWord
+helper_insert_val_movw_movt_inst(ARMRelocator::DWord pTarget,
+ ARMRelocator::DWord pImm)
{
// imm16: [19-16][11-0]
pTarget &= 0xfff0f000U;
@@ -271,8 +266,8 @@
return pTarget;
}
-static ARMRelocationFactory::DWord
-helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pValue)
+static ARMRelocator::DWord
+helper_extract_thumb_movw_movt_addend(ARMRelocator::DWord pValue)
{
// imm16: [19-16][26][14-12][7-0]
return helper_sign_extend((((pValue >> 4) & 0xf000U) |
@@ -282,9 +277,9 @@
16);
}
-static ARMRelocationFactory::DWord
-helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pValue,
- ARMRelocationFactory::DWord pImm)
+static ARMRelocator::DWord
+helper_insert_val_thumb_movw_movt_inst(ARMRelocator::DWord pValue,
+ ARMRelocator::DWord pImm)
{
// imm16: [19-16][26][14-12][7-0]
pValue &= 0xfbf08f00U;
@@ -295,16 +290,16 @@
return pValue;
}
-static ARMRelocationFactory::DWord
-helper_thumb32_branch_offset(ARMRelocationFactory::DWord pUpper16,
- ARMRelocationFactory::DWord pLower16)
+static ARMRelocator::DWord
+helper_thumb32_branch_offset(ARMRelocator::DWord pUpper16,
+ ARMRelocator::DWord pLower16)
{
- ARMRelocationFactory::DWord s = (pUpper16 & (1U << 10)) >> 10, // 26 bit
- u = pUpper16 & 0x3ffU, // 25-16
- l = pLower16 & 0x7ffU, // 10-0
- j1 = (pLower16 & (1U << 13)) >> 13, // 13
- j2 = (pLower16 & (1U << 11)) >> 11; // 11
- ARMRelocationFactory::DWord i1 = j1 ^ s? 0: 1,
+ ARMRelocator::DWord s = (pUpper16 & (1U << 10)) >> 10, // 26 bit
+ u = pUpper16 & 0x3ffU, // 25-16
+ l = pLower16 & 0x7ffU, // 10-0
+ j1 = (pLower16 & (1U << 13)) >> 13, // 13
+ j2 = (pLower16 & (1U << 11)) >> 11; // 11
+ ARMRelocator::DWord i1 = j1 ^ s? 0: 1,
i2 = j2 ^ s? 0: 1;
// [31-25][24][23][22][21-12][11-1][0]
@@ -314,17 +309,17 @@
25);
}
-static ARMRelocationFactory::DWord
-helper_thumb32_branch_upper(ARMRelocationFactory::DWord pUpper16,
- ARMRelocationFactory::DWord pOffset)
+static ARMRelocator::DWord
+helper_thumb32_branch_upper(ARMRelocator::DWord pUpper16,
+ ARMRelocator::DWord pOffset)
{
uint32_t sign = ((pOffset & 0x80000000U) >> 31);
return (pUpper16 & ~0x7ffU) | ((pOffset >> 12) & 0x3ffU) | (sign << 10);
}
-static ARMRelocationFactory::DWord
-helper_thumb32_branch_lower(ARMRelocationFactory::DWord pLower16,
- ARMRelocationFactory::DWord pOffset)
+static ARMRelocator::DWord
+helper_thumb32_branch_lower(ARMRelocator::DWord pLower16,
+ ARMRelocator::DWord pOffset)
{
uint32_t sign = ((pOffset & 0x80000000U) >> 31);
return ((pLower16 & ~0x2fffU) |
@@ -335,7 +330,7 @@
// Return true if overflow
static bool
-helper_check_signed_overflow(ARMRelocationFactory::DWord pValue,
+helper_check_signed_overflow(ARMRelocator::DWord pValue,
unsigned bits)
{
int32_t signed_val = static_cast<int32_t>(pValue);
@@ -354,20 +349,18 @@
//=========================================//
// R_ARM_NONE
-ARMRelocationFactory::Result none(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result none(Relocation& pReloc, ARMRelocator& pParent)
{
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_ABS32: (S + A) | T
-ARMRelocationFactory::Result abs32(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result abs32(Relocation& pReloc, ARMRelocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- ARMRelocationFactory::DWord S = pReloc.symValue();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
+ ARMRelocator::DWord S = pReloc.symValue();
LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
@@ -375,14 +368,14 @@
// but perform static relocation. (e.g., applying .debug section)
if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
pReloc.target() = (S + A) | T;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// A local symbol may need REL Type dynamic relocation
if (rsym->isLocal() && (rsym->reserved() & ARMGNULDBackend::ReserveRel)) {
helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
pReloc.target() = (S + A) | T ;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// An external symbol may need PLT and dynamic relocation
@@ -400,7 +393,7 @@
}
else {
helper_DynRel(pReloc, pReloc.type(), pParent);
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
}
}
@@ -408,17 +401,16 @@
// perform static relocation
pReloc.target() = (S + A) | T;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_REL32: ((S + A) | T) - P
-ARMRelocationFactory::Result rel32(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result rel32(Relocation& pReloc, ARMRelocator& pParent)
{
// perform static relocation
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
// An external symbol may need PLT (this reloc is from stub)
if (!pReloc.symInfo()->isLocal()) {
@@ -431,70 +423,65 @@
// perform relocation
pReloc.target() = ((S + A) | T) - pReloc.place();
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_BASE_PREL: B(S) + A - P
-ARMRelocationFactory::Result base_prel(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result base_prel(Relocation& pReloc, ARMRelocator& pParent)
{
// perform static relocation
- ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
pReloc.target() = pReloc.symValue() + A - pReloc.place();
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG
-ARMRelocationFactory::Result gotoff32(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result gotoff32(Relocation& pReloc, ARMRelocator& pParent)
{
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
- ARMRelocationFactory::Address S = pReloc.symValue();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
+ ARMRelocator::Address GOT_ORG = helper_GOT_ORG(pParent);
+ ARMRelocator::Address S = pReloc.symValue();
pReloc.target() = ((S + A) | T) - GOT_ORG;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
-ARMRelocationFactory::Result got_brel(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result got_brel(Relocation& pReloc, ARMRelocator& pParent)
{
if (!(pReloc.symInfo()->reserved() &
(ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
- return ARMRelocationFactory::BadReloc;
+ return ARMRelocator::BadReloc;
}
- ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pParent);
- ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
+ ARMRelocator::Address GOT_S = helper_GOT(pReloc, pParent);
+ ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
+ ARMRelocator::Address GOT_ORG = helper_GOT_ORG(pParent);
// Apply relocation.
pReloc.target() = GOT_S + A - GOT_ORG;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_GOT_PREL: GOT(S) + A - P
-ARMRelocationFactory::Result got_prel(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result got_prel(Relocation& pReloc, ARMRelocator& pParent)
{
if (!(pReloc.symInfo()->reserved() &
(ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
- return ARMRelocationFactory::BadReloc;
+ return ARMRelocator::BadReloc;
}
- ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pParent);
- ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- ARMRelocationFactory::Address P = pReloc.place();
+ ARMRelocator::Address GOT_S = helper_GOT(pReloc, pParent);
+ ARMRelocator::DWord A = pReloc.target() + pReloc.addend();
+ ARMRelocator::Address P = pReloc.place();
// Apply relocation.
pReloc.target() = GOT_S + A - P;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_PLT32: ((S + A) | T) - P
// R_ARM_JUMP24: ((S + A) | T) - P
// R_ARM_CALL: ((S + A) | T) - P
-ARMRelocationFactory::Result call(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result call(Relocation& pReloc, ARMRelocator& pParent)
{
// If target is undefined weak symbol, we only need to jump to the
// next instruction unless it has PLT entry. Rewrite instruction
@@ -505,15 +492,15 @@
!(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
// change target to NOP : mov r0, r0
pReloc.target() = (pReloc.target() & 0xf0000000U) | 0x01a00000;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
- ARMRelocationFactory::Address S; // S depends on PLT exists or not.
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A =
+ ARMRelocator::Address S; // S depends on PLT exists or not.
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord A =
helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26)
+ pReloc.addend();
- ARMRelocationFactory::Address P = pReloc.place();
+ ARMRelocator::Address P = pReloc.place();
S = pReloc.symValue();
if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
@@ -528,26 +515,25 @@
if (T != 0) {
// cannot rewrite to blx for R_ARM_JUMP24
if (pReloc.type() == llvm::ELF::R_ARM_JUMP24)
- return ARMRelocationFactory::BadReloc;
+ return ARMRelocator::BadReloc;
pReloc.target() = (pReloc.target() & 0xffffff) |
0xfa000000 |
(((S + A - P) & 2) << 23);
}
- ARMRelocationFactory::DWord X = ((S + A) | T) - P;
+ ARMRelocator::DWord X = ((S + A) | T) - P;
// Check X is 24bit sign int. If not, we should use stub or PLT before apply.
if (helper_check_signed_overflow(X, 26))
- return ARMRelocationFactory::Overflow;
+ return ARMRelocator::Overflow;
// Make sure the Imm is 0. Result Mask.
pReloc.target() = (pReloc.target() & 0xFF000000u) | ((X & 0x03FFFFFEu) >> 2);
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_THM_CALL: ((S + A) | T) - P
// R_ARM_THM_JUMP24: (((S + A) | T) - P)
-ARMRelocationFactory::Result thm_call(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result thm_call(Relocation& pReloc, ARMRelocator& pParent)
{
// If target is undefined weak symbol, we only need to jump to the
// next instruction unless it has PLT entry. Rewrite instruction
@@ -557,18 +543,18 @@
!pReloc.symInfo()->isDyn() &&
!(pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT)) {
pReloc.target() = (0xe000U << 16) | 0xbf00U;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// get lower and upper 16 bit instructions from relocation targetData
uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper_inst,
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord A = helper_thumb32_branch_offset(upper_inst,
lower_inst);
- ARMRelocationFactory::Address P = pReloc.place();
- ARMRelocationFactory::Address S;
+ ARMRelocator::Address P = pReloc.place();
+ ARMRelocator::Address S;
// if symbol has plt
if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
@@ -588,7 +574,7 @@
if (T == 0) {
// cannot rewrite to blx for R_ARM_THM_JUMP24
if (pReloc.type() == llvm::ELF::R_ARM_THM_JUMP24)
- return ARMRelocationFactory::BadReloc;
+ return ARMRelocator::BadReloc;
// for BLX, select bit 1 from relocation base address to jump target
// address
@@ -601,11 +587,11 @@
lower_inst |= 0x1000U;
}
- ARMRelocationFactory::DWord X = (S | T) - P;
+ ARMRelocator::DWord X = (S | T) - P;
// FIXME: Check bit size is 24(thumb2) or 22?
if (helper_check_signed_overflow(X, 25)) {
- return ARMRelocationFactory::Overflow;
+ return ARMRelocator::Overflow;
}
upper_inst = helper_thumb32_branch_upper(upper_inst, X);
@@ -614,19 +600,18 @@
*(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
*(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_MOVW_ABS_NC: (S + A) | T
-ARMRelocationFactory::Result movw_abs_nc(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A =
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord A =
helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
@@ -644,39 +629,37 @@
X = (S + A) | T;
pReloc.target() = helper_insert_val_movw_movt_inst(
pReloc.target() + pReloc.addend(), X);
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
-ARMRelocationFactory::Result movw_prel_nc(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent)
{
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord P = pReloc.place();
- ARMRelocationFactory::DWord A =
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord P = pReloc.place();
+ ARMRelocator::DWord A =
helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
X = ((S + A) | T) - P;
if (helper_check_signed_overflow(X, 16)) {
- return ARMRelocationFactory::Overflow;
+ return ARMRelocator::Overflow;
} else {
pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
}
// R_ARM_MOVT_ABS: S + A
-ARMRelocationFactory::Result movt_abs(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result movt_abs(Relocation& pReloc, ARMRelocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord A =
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord A =
helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
@@ -693,41 +676,39 @@
X >>= 16;
// perform static relocation
pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_MOVT_PREL: S + A - P
-ARMRelocationFactory::Result movt_prel(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result movt_prel(Relocation& pReloc, ARMRelocator& pParent)
{
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord P = pReloc.place();
- ARMRelocationFactory::DWord A =
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord P = pReloc.place();
+ ARMRelocator::DWord A =
helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
X = S + A - P;
X >>= 16;
pReloc.target() = helper_insert_val_movw_movt_inst(pReloc.target(), X);
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_THM_MOVW_ABS_NC: (S + A) | T
-ARMRelocationFactory::Result thm_movw_abs_nc(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result thm_movw_abs_nc(Relocation& pReloc, ARMRelocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
// get lower and upper 16 bit instructions from relocation targetData
uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
- ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
- ARMRelocationFactory::DWord A =
+ ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
+ ARMRelocator::DWord A =
helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
@@ -745,24 +726,23 @@
*(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
*(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
-ARMRelocationFactory::Result thm_movw_prel_nc(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result thm_movw_prel_nc(Relocation& pReloc, ARMRelocator& pParent)
{
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord P = pReloc.place();
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord P = pReloc.place();
// get lower and upper 16 bit instructions from relocation targetData
uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
- ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
- ARMRelocationFactory::DWord A =
+ ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
+ ARMRelocator::DWord A =
helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
X = ((S + A) | T) - P;
@@ -770,25 +750,24 @@
*(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
*(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
-ARMRelocationFactory::Result thm_movw_brel(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result thm_movw_brel(Relocation& pReloc, ARMRelocator& pParent)
{
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord P = pReloc.place();
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord P = pReloc.place();
// get lower and upper 16 bit instructions from relocation targetData
uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
- ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
- ARMRelocationFactory::DWord A =
+ ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
+ ARMRelocator::DWord A =
helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
X = ((S + A) | T) - P;
@@ -796,23 +775,22 @@
*(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
*(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_THM_MOVT_ABS: S + A
-ARMRelocationFactory::Result thm_movt_abs(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result thm_movt_abs(Relocation& pReloc, ARMRelocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- ARMRelocationFactory::Address S = pReloc.symValue();
+ ARMRelocator::Address S = pReloc.symValue();
// get lower and upper 16 bit instructions from relocation targetData
uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
- ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
- ARMRelocationFactory::DWord A =
+ ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
+ ARMRelocator::DWord A =
helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
@@ -829,30 +807,29 @@
// check 16-bit overflow
if (helper_check_signed_overflow(X, 16)) {
- return ARMRelocationFactory::Overflow;
+ return ARMRelocator::Overflow;
} else {
val = helper_insert_val_thumb_movw_movt_inst(val, X);
*(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
*(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
}
// R_ARM_THM_MOVT_PREL: S + A - P
// R_ARM_THM_MOVT_BREL: S + A - B(S)
-ARMRelocationFactory::Result thm_movt_prel(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result thm_movt_prel(Relocation& pReloc, ARMRelocator& pParent)
{
- ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord P = pReloc.place();
+ ARMRelocator::Address S = pReloc.symValue();
+ ARMRelocator::DWord P = pReloc.place();
// get lower and upper 16 bit instructions from relocation targetData
uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
- ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
- ARMRelocationFactory::DWord A =
+ ARMRelocator::DWord val = ((upper_inst) << 16) | (lower_inst);
+ ARMRelocator::DWord A =
helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
- ARMRelocationFactory::DWord X;
+ ARMRelocator::DWord X;
X = S + A - P;
X >>= 16;
@@ -861,19 +838,18 @@
*(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
*(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::OK;
}
// R_ARM_PREL31: ((S + A) | T) - P
-ARMRelocationFactory::Result prel31(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result prel31(Relocation& pReloc, ARMRelocator& pParent)
{
- ARMRelocationFactory::DWord target = pReloc.target();
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A = helper_sign_extend(target, 31) +
+ ARMRelocator::DWord target = pReloc.target();
+ ARMRelocator::DWord T = getThumbBit(pReloc);
+ ARMRelocator::DWord A = helper_sign_extend(target, 31) +
pReloc.addend();
- ARMRelocationFactory::DWord P = pReloc.place();
- ARMRelocationFactory::Address S;
+ ARMRelocator::DWord P = pReloc.place();
+ ARMRelocator::Address S;
S = pReloc.symValue();
// if symbol has plt
@@ -882,24 +858,22 @@
T = 0; // PLT is not thumb.
}
- ARMRelocationFactory::DWord X = ((S + A) | T) - P;
+ ARMRelocator::DWord X = ((S + A) | T) - P;
pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
if (helper_check_signed_overflow(X, 31))
- return ARMRelocationFactory::Overflow;
- return ARMRelocationFactory::OK;
+ return ARMRelocator::Overflow;
+ return ARMRelocator::OK;
}
// R_ARM_TLS_GD32: GOT(S) + A - P
// R_ARM_TLS_IE32: GOT(S) + A - P
// R_ARM_TLS_LE32: S + A - tp
-ARMRelocationFactory::Result tls(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result tls(Relocation& pReloc, ARMRelocator& pParent)
{
- return ARMRelocationFactory::Unsupport;
+ return ARMRelocator::Unsupport;
}
-ARMRelocationFactory::Result unsupport(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+ARMRelocator::Result unsupport(Relocation& pReloc, ARMRelocator& pParent)
{
- return ARMRelocationFactory::Unsupport;
+ return ARMRelocator::Unsupport;
}
diff --git a/lib/Target/ARM/ARMRelocationFactory.h b/lib/Target/ARM/ARMRelocator.h
similarity index 74%
rename from lib/Target/ARM/ARMRelocationFactory.h
rename to lib/Target/ARM/ARMRelocator.h
index 25135ed..0bf3653 100644
--- a/lib/Target/ARM/ARMRelocationFactory.h
+++ b/lib/Target/ARM/ARMRelocator.h
@@ -1,4 +1,4 @@
-//===- ARMRelocationFactory.h --------------------------------------------===//
+//===- ARMRelocator.h ----------------------------------------------------===//
//
// The MCLinker Project
//
@@ -12,26 +12,26 @@
#include <gtest.h>
#endif
-#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/Relocator.h>
#include <mcld/Target/GOT.h>
#include <mcld/Target/SymbolEntryMap.h>
#include "ARMLDBackend.h"
namespace mcld {
-/** \class ARMRelocationFactory
- * \brief ARMRelocationFactory creates and destroys the ARM relocations.
+/** \class ARMRelocator
+ * \brief ARMRelocator creates and destroys the ARM relocations.
*
*/
-class ARMRelocationFactory : public RelocationFactory
+class ARMRelocator : public Relocator
{
public:
- typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
- typedef SymbolEntryMap<PLT::Entry> SymPLTMap;
+ typedef SymbolEntryMap<ARMGOTEntry> SymGOTMap;
+ typedef SymbolEntryMap<ARMPLT1> SymPLTMap;
public:
- ARMRelocationFactory(size_t pNum, ARMGNULDBackend& pParent);
- ~ARMRelocationFactory();
+ ARMRelocator(ARMGNULDBackend& pParent);
+ ~ARMRelocator();
Result applyRelocation(Relocation& pRelocation);
diff --git a/lib/Target/ARM/Android.mk b/lib/Target/ARM/Android.mk
index f9cb356..525ac4e 100644
--- a/lib/Target/ARM/Android.mk
+++ b/lib/Target/ARM/Android.mk
@@ -9,7 +9,7 @@
ARMLDBackend.cpp \
ARMMCLinker.cpp \
ARMPLT.cpp \
- ARMRelocationFactory.cpp \
+ ARMRelocator.cpp \
ARMTargetMachine.cpp \
ARMToARMStub.cpp \
ARMToTHMStub.cpp \
diff --git a/lib/Target/ARM/README b/lib/Target/ARM/README
deleted file mode 100644
index ea88bfe..0000000
--- a/lib/Target/ARM/README
+++ /dev/null
@@ -1,2 +0,0 @@
-ARMLDBackend stands like ARMAsmBackend. It's a backend of linker,
-and all target-dependent behavior and data are here.
diff --git a/lib/Target/Android.mk b/lib/Target/Android.mk
index e70b467..77ab932 100644
--- a/lib/Target/Android.mk
+++ b/lib/Target/Android.mk
@@ -4,6 +4,7 @@
ELFDynamic.cpp \
ELFEmulation.cpp \
ELFMCLinker.cpp \
+ GNUInfo.cpp \
GNULDBackend.cpp \
GOT.cpp \
OutputRelocSection.cpp \
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
index 25b21f0..89917cc 100644
--- a/lib/Target/ELFDynamic.cpp
+++ b/lib/Target/ELFDynamic.cpp
@@ -20,6 +20,7 @@
//===----------------------------------------------------------------------===//
// elf_dynamic::EntryIF
+//===----------------------------------------------------------------------===//
EntryIF::EntryIF()
{
}
@@ -30,9 +31,11 @@
//===----------------------------------------------------------------------===//
// ELFDynamic
-ELFDynamic::ELFDynamic(const GNULDBackend& pParent)
- : m_pEntryFactory(NULL), m_Backend(pParent), m_Idx(0) {
- if (32 == pParent.bitclass() && pParent.isLittleEndian()) {
+//===----------------------------------------------------------------------===//
+ELFDynamic::ELFDynamic(const GNULDBackend& pParent,
+ const LinkerConfig& pConfig)
+ : m_pEntryFactory(NULL), m_Backend(pParent), m_Config(pConfig), m_Idx(0) {
+ if (m_Config.targets().is32Bits() && m_Config.targets().isLittleEndian()) {
m_pEntryFactory = new Entry<32, true>();
}
// FIXME: support big-endian and 64-bit machine.
@@ -86,13 +89,12 @@
}
/// reserveEntries - reserve entries
-void ELFDynamic::reserveEntries(const LinkerConfig& pConfig,
- const ELFFileFormat& pFormat)
+void ELFDynamic::reserveEntries(const ELFFileFormat& pFormat)
{
- if (LinkerConfig::DynObj == pConfig.codeGenType()) {
+ if (LinkerConfig::DynObj == m_Config.codeGenType()) {
reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
- if (pConfig.options().Bsymbolic())
+ if (m_Config.options().Bsymbolic())
reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
}
@@ -147,29 +149,29 @@
reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
}
- if (pConfig.options().hasOrigin() ||
- pConfig.options().Bsymbolic() ||
- pConfig.options().hasNow() ||
+ if (m_Config.options().hasOrigin() ||
+ m_Config.options().Bsymbolic() ||
+ m_Config.options().hasNow() ||
m_Backend.hasTextRel() ||
(m_Backend.hasStaticTLS() &&
- (LinkerConfig::DynObj == pConfig.codeGenType()))) {
+ (LinkerConfig::DynObj == m_Config.codeGenType()))) {
reserveOne(llvm::ELF::DT_FLAGS); // DT_FLAGS
}
if (m_Backend.hasTextRel())
reserveOne(llvm::ELF::DT_TEXTREL); // DT_TEXTREL
- if (pConfig.options().hasNow() ||
- pConfig.options().hasLoadFltr() ||
- pConfig.options().hasOrigin() ||
- pConfig.options().hasInterPose() ||
- pConfig.options().hasNoDefaultLib() ||
- pConfig.options().hasNoDump() ||
- pConfig.options().Bgroup() ||
- ((LinkerConfig::DynObj == pConfig.codeGenType()) &&
- (pConfig.options().hasNoDelete() ||
- pConfig.options().hasInitFirst() ||
- pConfig.options().hasNoDLOpen()))) {
+ if (m_Config.options().hasNow() ||
+ m_Config.options().hasLoadFltr() ||
+ m_Config.options().hasOrigin() ||
+ m_Config.options().hasInterPose() ||
+ m_Config.options().hasNoDefaultLib() ||
+ m_Config.options().hasNoDump() ||
+ m_Config.options().Bgroup() ||
+ ((LinkerConfig::DynObj == m_Config.codeGenType()) &&
+ (m_Config.options().hasNoDelete() ||
+ m_Config.options().hasInitFirst() ||
+ m_Config.options().hasNoDLOpen()))) {
reserveOne(llvm::ELF::DT_FLAGS_1); // DT_FLAGS_1
}
@@ -177,11 +179,10 @@
}
/// applyEntries - apply entries
-void ELFDynamic::applyEntries(const LinkerConfig& pConfig,
- const ELFFileFormat& pFormat)
+void ELFDynamic::applyEntries(const ELFFileFormat& pFormat)
{
- if (LinkerConfig::DynObj == pConfig.codeGenType() &&
- pConfig.options().Bsymbolic()) {
+ if (LinkerConfig::DynObj == m_Config.codeGenType() &&
+ m_Config.options().Bsymbolic()) {
applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
}
@@ -247,48 +248,48 @@
if (m_Backend.hasTextRel()) {
applyOne(llvm::ELF::DT_TEXTREL, 0x0); // DT_TEXTREL
- if (pConfig.options().warnSharedTextrel() &&
- LinkerConfig::DynObj == pConfig.codeGenType())
+ if (m_Config.options().warnSharedTextrel() &&
+ LinkerConfig::DynObj == m_Config.codeGenType())
mcld::warning(mcld::diag::warn_shared_textrel);
}
uint64_t dt_flags = 0x0;
- if (pConfig.options().hasOrigin())
+ if (m_Config.options().hasOrigin())
dt_flags |= llvm::ELF::DF_ORIGIN;
- if (pConfig.options().Bsymbolic())
+ if (m_Config.options().Bsymbolic())
dt_flags |= llvm::ELF::DF_SYMBOLIC;
- if (pConfig.options().hasNow())
+ if (m_Config.options().hasNow())
dt_flags |= llvm::ELF::DF_BIND_NOW;
if (m_Backend.hasTextRel())
dt_flags |= llvm::ELF::DF_TEXTREL;
if (m_Backend.hasStaticTLS() &&
- (LinkerConfig::DynObj == pConfig.codeGenType()))
+ (LinkerConfig::DynObj == m_Config.codeGenType()))
dt_flags |= llvm::ELF::DF_STATIC_TLS;
if (0x0 != dt_flags) {
applyOne(llvm::ELF::DT_FLAGS, dt_flags); // DT_FLAGS
}
uint64_t dt_flags_1 = 0x0;
- if (pConfig.options().hasNow())
+ if (m_Config.options().hasNow())
dt_flags_1 |= llvm::ELF::DF_1_NOW;
- if (pConfig.options().hasLoadFltr())
+ if (m_Config.options().hasLoadFltr())
dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
- if (pConfig.options().hasOrigin())
+ if (m_Config.options().hasOrigin())
dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
- if (pConfig.options().hasInterPose())
+ if (m_Config.options().hasInterPose())
dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
- if (pConfig.options().hasNoDefaultLib())
+ if (m_Config.options().hasNoDefaultLib())
dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
- if (pConfig.options().hasNoDump())
+ if (m_Config.options().hasNoDump())
dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
- if (pConfig.options().Bgroup())
+ if (m_Config.options().Bgroup())
dt_flags_1 |= llvm::ELF::DF_1_GROUP;
- if (LinkerConfig::DynObj == pConfig.codeGenType()) {
- if (pConfig.options().hasNoDelete())
+ if (LinkerConfig::DynObj == m_Config.codeGenType()) {
+ if (m_Config.options().hasNoDelete())
dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
- if (pConfig.options().hasInitFirst())
+ if (m_Config.options().hasInitFirst())
dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
- if (pConfig.options().hasNoDLOpen())
+ if (m_Config.options().hasNoDLOpen())
dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
}
if (0x0 != dt_flags_1)
diff --git a/lib/Target/GNUInfo.cpp b/lib/Target/GNUInfo.cpp
new file mode 100644
index 0000000..75234b0
--- /dev/null
+++ b/lib/Target/GNUInfo.cpp
@@ -0,0 +1,31 @@
+//===- GNUInfo.cpp --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Target/GNUInfo.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// GNUInfo
+//===----------------------------------------------------------------------===//
+GNUInfo::GNUInfo(const llvm::Triple& pTriple)
+ : m_Triple(pTriple) {
+}
+
+uint8_t GNUInfo::OSABI() const
+{
+ switch (m_Triple.getOS()) {
+ case llvm::Triple::FreeBSD:
+ return llvm::ELF::ELFOSABI_FREEBSD;
+ case llvm::Triple::Linux:
+ return llvm::ELF::ELFOSABI_LINUX;
+ default:
+ return llvm::ELF::ELFOSABI_NONE;
+ }
+}
+
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
index 950ac43..590c14f 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -11,11 +11,14 @@
#include <string>
#include <cstring>
#include <cassert>
+#include <vector>
+#include <algorithm>
#include <mcld/Module.h>
#include <mcld/LinkerConfig.h>
#include <mcld/IRBuilder.h>
#include <mcld/InputTree.h>
+#include <mcld/Config/Config.h>
#include <mcld/ADT/SizeTraits.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/LD/LDContext.h>
@@ -23,6 +26,7 @@
#include <mcld/LD/EhFrame.h>
#include <mcld/LD/EhFrameHdr.h>
#include <mcld/LD/RelocData.h>
+#include <mcld/LD/RelocationFactory.h>
#include <mcld/MC/Attribute.h>
#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MemoryArea.h>
@@ -52,12 +56,13 @@
//===----------------------------------------------------------------------===//
// GNULDBackend
//===----------------------------------------------------------------------===//
-GNULDBackend::GNULDBackend(const LinkerConfig& pConfig)
+GNULDBackend::GNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo)
: TargetLDBackend(pConfig),
m_pObjectReader(NULL),
m_pDynObjFileFormat(NULL),
m_pExecFileFormat(NULL),
m_pObjectFileFormat(NULL),
+ m_pInfo(pInfo),
m_ELFSegmentTable(9), // magic number
m_pBRIslandFactory(NULL),
m_pStubFactory(NULL),
@@ -89,6 +94,7 @@
GNULDBackend::~GNULDBackend()
{
+ delete m_pInfo;
delete m_pDynObjFileFormat;
delete m_pExecFileFormat;
delete m_pSymIndexMap;
@@ -103,8 +109,21 @@
size_t GNULDBackend::sectionStartOffset() const
{
- // FIXME: use fixed offset, we need 10 segments by default
- return sizeof(llvm::ELF::Elf64_Ehdr)+10*sizeof(llvm::ELF::Elf64_Phdr);
+ if (LinkerConfig::Binary == config().codeGenType())
+ return 0x0;
+
+ switch (config().targets().bitclass()) {
+ case 32u:
+ return sizeof(llvm::ELF::Elf32_Ehdr) +
+ numOfSegments() * sizeof(llvm::ELF::Elf32_Phdr);
+ case 64u:
+ return sizeof(llvm::ELF::Elf64_Ehdr) +
+ numOfSegments() * sizeof(llvm::ELF::Elf64_Phdr);
+ default:
+ fatal(diag::unsupported_bitclass) << config().targets().triple().str()
+ << config().targets().bitclass();
+ return 0;
+ }
}
uint64_t GNULDBackend::segmentStartAddr(const FragmentLinker& pLinker) const
@@ -126,30 +145,40 @@
return new GNUArchiveReader(pModule, *m_pObjectReader);
}
-ELFObjectReader* GNULDBackend::createObjectReader(FragmentLinker& pLinker)
+ELFObjectReader* GNULDBackend::createObjectReader(IRBuilder& pBuilder)
{
- m_pObjectReader = new ELFObjectReader(*this, pLinker);
+ m_pObjectReader = new ELFObjectReader(*this, pBuilder, config());
return m_pObjectReader;
}
-ELFDynObjReader* GNULDBackend::createDynObjReader(FragmentLinker& pLinker)
+ELFDynObjReader* GNULDBackend::createDynObjReader(IRBuilder& pBuilder)
{
- return new ELFDynObjReader(*this, pLinker);
+ return new ELFDynObjReader(*this, pBuilder, config());
}
-ELFObjectWriter* GNULDBackend::createObjectWriter(FragmentLinker& pLinker)
+ELFBinaryReader* GNULDBackend::createBinaryReader(IRBuilder& pBuilder)
{
- return new ELFObjectWriter(*this, pLinker);
+ return new ELFBinaryReader(*this, pBuilder, config());
}
-ELFDynObjWriter* GNULDBackend::createDynObjWriter(FragmentLinker& pLinker)
+ELFObjectWriter* GNULDBackend::createObjectWriter()
{
- return new ELFDynObjWriter(*this, pLinker);
+ return new ELFObjectWriter(*this, config());
}
-ELFExecWriter* GNULDBackend::createExecWriter(FragmentLinker& pLinker)
+ELFDynObjWriter* GNULDBackend::createDynObjWriter()
{
- return new ELFExecWriter(*this, pLinker);
+ return new ELFDynObjWriter(*this, config());
+}
+
+ELFExecWriter* GNULDBackend::createExecWriter()
+{
+ return new ELFExecWriter(*this, config());
+}
+
+ELFBinaryWriter* GNULDBackend::createBinaryWriter()
+{
+ return new ELFBinaryWriter(*this, config());
}
bool GNULDBackend::initStdSections(ObjectBuilder& pBuilder)
@@ -158,19 +187,23 @@
case LinkerConfig::DynObj: {
if (NULL == m_pDynObjFileFormat)
m_pDynObjFileFormat = new ELFDynObjFileFormat();
- m_pDynObjFileFormat->initStdSections(pBuilder, bitclass());
+ m_pDynObjFileFormat->initStdSections(pBuilder,
+ config().targets().bitclass());
return true;
}
- case LinkerConfig::Exec: {
+ case LinkerConfig::Exec:
+ case LinkerConfig::Binary: {
if (NULL == m_pExecFileFormat)
m_pExecFileFormat = new ELFExecFileFormat();
- m_pExecFileFormat->initStdSections(pBuilder, bitclass());
+ m_pExecFileFormat->initStdSections(pBuilder,
+ config().targets().bitclass());
return true;
}
case LinkerConfig::Object: {
if (NULL == m_pObjectFileFormat)
m_pObjectFileFormat = new ELFObjectFileFormat();
- m_pObjectFileFormat->initStdSections(pBuilder, bitclass());
+ m_pObjectFileFormat->initStdSections(pBuilder,
+ config().targets().bitclass());
return true;
}
default:
@@ -687,6 +720,7 @@
assert(NULL != m_pDynObjFileFormat);
return m_pDynObjFileFormat;
case LinkerConfig::Exec:
+ case LinkerConfig::Binary:
assert(NULL != m_pExecFileFormat);
return m_pExecFileFormat;
case LinkerConfig::Object:
@@ -705,6 +739,7 @@
assert(NULL != m_pDynObjFileFormat);
return m_pDynObjFileFormat;
case LinkerConfig::Exec:
+ case LinkerConfig::Binary:
assert(NULL != m_pExecFileFormat);
return m_pExecFileFormat;
case LinkerConfig::Object:
@@ -758,6 +793,9 @@
size_t shstrtab = 1;
size_t hash = 0;
+ // number of local symbol in the .dynsym
+ size_t dynsym_local_cnt = 0;
+
/// compute the size of .symtab, .dynsym and .strtab
/// @{
Module::const_sym_iterator symbol;
@@ -789,6 +827,7 @@
if (ResolveInfo::Section != (*symbol)->type())
strtab += str_size;
}
+ dynsym_local_cnt = dynsym;
// compute the size of the reset of symbols
symEnd = pModule.sym_end();
for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
@@ -813,7 +852,8 @@
dynstr += pModule.name().size() + 1;
}
/** fall through **/
- case LinkerConfig::Exec: {
+ case LinkerConfig::Exec:
+ case LinkerConfig::Binary: {
// add DT_NEED strings into .dynstr and .dynamic
// Rules:
// 1. ignore --no-add-needed
@@ -844,21 +884,28 @@
}
// set size
- if (32 == bitclass())
+ if (config().targets().is32Bits())
file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf32_Sym));
else
file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf64_Sym));
file_format->getDynStrTab().setSize(dynstr);
file_format->getHashTab().setSize(hash);
+ // set .dynsym sh_info to one greater than the symbol table
+ // index of the last local symbol
+ file_format->getDynSymTab().setInfo(dynsym_local_cnt);
}
/* fall through */
case LinkerConfig::Object: {
- if (32 == bitclass())
+ if (config().targets().is32Bits())
file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf32_Sym));
else
file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf64_Sym));
file_format->getStrTab().setSize(strtab);
+
+ // set .symtab sh_info to one greater than the symbol table
+ // index of the last local symbol
+ file_format->getSymTab().setInfo(symbols.numOfLocals() + 1);
break;
}
default:
@@ -870,12 +917,13 @@
/// reserve fixed entries in the .dynamic section.
/// @{
if (LinkerConfig::DynObj == config().codeGenType() ||
- LinkerConfig::Exec == config().codeGenType()) {
+ LinkerConfig::Exec == config().codeGenType() ||
+ LinkerConfig::Binary == config().codeGenType()) {
// Because some entries in .dynamic section need information of .dynsym,
// .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
// entries until we get the size of the sections mentioned above
if (!pIsStaticLink)
- dynamic().reserveEntries(config(), *file_format);
+ dynamic().reserveEntries(*file_format);
file_format->getDynamic().setSize(dynamic().numOfBytes());
}
/// @}
@@ -956,20 +1004,21 @@
// set up symtab_region
llvm::ELF::Elf32_Sym* symtab32 = NULL;
llvm::ELF::Elf64_Sym* symtab64 = NULL;
- if (32 == bitclass())
+ if (config().targets().is32Bits())
symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
- else if (64 == bitclass())
+ else if (config().targets().is64Bits())
symtab64 = (llvm::ELF::Elf64_Sym*)symtab_region->start();
- else
- llvm::report_fatal_error(llvm::Twine("unsupported bitclass ") +
- llvm::Twine(bitclass()) +
- llvm::Twine(".\n"));
+ else {
+ fatal(diag::unsupported_bitclass) << config().targets().triple().str()
+ << config().targets().bitclass();
+ }
+
// set up strtab_region
char* strtab = (char*)strtab_region->start();
strtab[0] = '\0';
// initialize the first ELF symbol
- if (32 == bitclass()) {
+ if (config().targets().is32Bits()) {
symtab32[0].st_name = 0;
symtab32[0].st_value = 0;
symtab32[0].st_size = 0;
@@ -1005,7 +1054,7 @@
entry->setValue(symtabIdx);
}
- if (32 == bitclass())
+ if (config().targets().is32Bits())
emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
symtabIdx);
else
@@ -1052,17 +1101,17 @@
// set up symtab_region
llvm::ELF::Elf32_Sym* symtab32 = NULL;
llvm::ELF::Elf64_Sym* symtab64 = NULL;
- if (32 == bitclass())
+ if (config().targets().is32Bits())
symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
- else if (64 == bitclass())
+ else if (config().targets().is64Bits())
symtab64 = (llvm::ELF::Elf64_Sym*)symtab_region->start();
- else
- llvm::report_fatal_error(llvm::Twine("unsupported bitclass ") +
- llvm::Twine(bitclass()) +
- llvm::Twine(".\n"));
+ else {
+ fatal(diag::unsupported_bitclass) << config().targets().triple().str()
+ << config().targets().bitclass();
+ }
// initialize the first ELF symbol
- if (32 == bitclass()) {
+ if (config().targets().is32Bits()) {
symtab32[0].st_name = 0;
symtab32[0].st_value = 0;
symtab32[0].st_size = 0;
@@ -1098,7 +1147,7 @@
if (!isDynamicSymbol(**symbol))
continue;
- if (32 == bitclass())
+ if (config().targets().is32Bits())
emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
symtabIdx);
else
@@ -1117,7 +1166,7 @@
// emit symbols in TLS category, all symbols in TLS category shold be emitited
symEnd = symbols.tlsEnd();
for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
- if (32 == bitclass())
+ if (config().targets().is32Bits())
emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
symtabIdx);
else
@@ -1139,7 +1188,7 @@
if (!isDynamicSymbol(**symbol))
continue;
- if (32 == bitclass())
+ if (config().targets().is32Bits())
emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
symtabIdx);
else
@@ -1188,7 +1237,7 @@
// set pointer to SONAME entry in dynamic string table.
dynamic().applySoname(strtabsize);
}
- dynamic().applyEntries(config(), *file_format);
+ dynamic().applyEntries(*file_format);
dynamic().emit(dyn_sect, *dyn_region);
// emit soname
@@ -1217,7 +1266,7 @@
StringHash<ELF> hash_func;
- if (32 == bitclass()) {
+ if (config().targets().is32Bits()) {
for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) {
llvm::StringRef name(strtab + symtab32[sym_idx].st_name);
size_t bucket_pos = hash_func(name) % nbucket;
@@ -1225,7 +1274,7 @@
bucket[bucket_pos] = sym_idx;
}
}
- else if (64 == bitclass()) {
+ else if (config().targets().is64Bits()) {
for (size_t sym_idx=0; sym_idx < symtabIdx; ++sym_idx) {
llvm::StringRef name(strtab + symtab64[sym_idx].st_name);
size_t bucket_pos = hash_func(name) % nbucket;
@@ -1301,9 +1350,9 @@
&pSectHdr == &file_format->getCtors() ||
&pSectHdr == &file_format->getDtors() ||
&pSectHdr == &file_format->getJCR() ||
- 0 == pSectHdr.name().compare(".data.rel.ro"))
+ &pSectHdr == &file_format->getDataRelRo())
return SHO_RELRO;
- if (0 == pSectHdr.name().compare(".data.rel.ro.local"))
+ if (&pSectHdr == &file_format->getDataRelRoLocal())
return SHO_RELRO_LOCAL;
}
if ((pSectHdr.flag() & llvm::ELF::SHF_TLS) != 0x0) {
@@ -1374,8 +1423,9 @@
bind = llvm::ELF::STB_GLOBAL;
}
- if (pSymbol.visibility() == llvm::ELF::STV_INTERNAL ||
- pSymbol.visibility() == llvm::ELF::STV_HIDDEN)
+ if (config().codeGenType() != LinkerConfig::Object &&
+ (pSymbol.visibility() == llvm::ELF::STV_INTERNAL ||
+ pSymbol.visibility() == llvm::ELF::STV_HIDDEN))
bind = llvm::ELF::STB_LOCAL;
uint32_t type = pSymbol.resolveInfo()->type();
@@ -1660,7 +1710,7 @@
// update PT_PHDR
if (llvm::ELF::PT_PHDR == segment.type()) {
uint64_t offset, phdr_size;
- if (32 == bitclass()) {
+ if (config().targets().is32Bits()) {
offset = sizeof(llvm::ELF::Elf32_Ehdr);
phdr_size = sizeof(llvm::ELF::Elf32_Phdr);
}
@@ -1673,7 +1723,7 @@
segment.setPaddr(segment.vaddr());
segment.setFilesz(numOfSegments() * phdr_size);
segment.setMemsz(numOfSegments() * phdr_size);
- segment.setAlign(bitclass() / 8);
+ segment.setAlign(config().targets().bitclass() / 8);
continue;
}
@@ -1859,16 +1909,18 @@
if (mapping != config().scripts().addressMap().end()) {
// check address mapping
start_addr = mapping.getEntry()->value();
- const uint64_t remainder = start_addr % abiPageSize();
- if (remainder != (*seg).front()->offset() % abiPageSize()) {
- uint64_t padding = abiPageSize() + remainder -
- (*seg).front()->offset() % abiPageSize();
- setOutputSectionOffset(pModule,
- pModule.begin() + (*seg).front()->index(),
- pModule.end(),
- (*seg).front()->offset() + padding);
- if (config().options().hasRelro())
- setupRelro(pModule);
+ if ((*seg).front()->kind() != LDFileFormat::Null) {
+ const uint64_t remainder = start_addr % abiPageSize();
+ if (remainder != (*seg).front()->offset() % abiPageSize()) {
+ uint64_t padding = abiPageSize() + remainder -
+ (*seg).front()->offset() % abiPageSize();
+ setOutputSectionOffset(pModule,
+ pModule.begin() + (*seg).front()->index(),
+ pModule.end(),
+ (*seg).front()->offset() + padding);
+ if (config().options().hasRelro())
+ setupRelro(pModule);
+ }
}
}
else {
@@ -1910,6 +1962,75 @@
}
}
+/// layout - layout method
+void GNULDBackend::layout(Module& pModule, FragmentLinker& pLinker)
+{
+ std::vector<SHOEntry> output_list;
+ // 1. determine what sections will go into final output, and push the needed
+ // sections into output_list for later processing
+ for (Module::iterator it = pModule.begin(), ie = pModule.end(); it != ie;
+ ++it) {
+ switch ((*it)->kind()) {
+ // take NULL and StackNote directly
+ case LDFileFormat::Null:
+ case LDFileFormat::StackNote:
+ output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+ break;
+ // ignore if section size is 0
+ case LDFileFormat::Regular:
+ case LDFileFormat::Target:
+ case LDFileFormat::MetaData:
+ case LDFileFormat::BSS:
+ case LDFileFormat::Debug:
+ case LDFileFormat::EhFrame:
+ case LDFileFormat::GCCExceptTable:
+ case LDFileFormat::NamePool:
+ case LDFileFormat::Relocation:
+ case LDFileFormat::Note:
+ case LDFileFormat::EhFrameHdr:
+ if (0 != (*it)->size()) {
+ output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+ }
+ break;
+ case LDFileFormat::Group:
+ if (LinkerConfig::Object == config().codeGenType()) {
+ //TODO: support incremental linking
+ ;
+ }
+ break;
+ case LDFileFormat::Version:
+ if (0 != (*it)->size()) {
+ output_list.push_back(std::make_pair(*it, getSectionOrder(**it)));
+ warning(diag::warn_unsupported_symbolic_versioning) << (*it)->name();
+ }
+ break;
+ default:
+ if (0 != (*it)->size()) {
+ error(diag::err_unsupported_section) << (*it)->name() << (*it)->kind();
+ }
+ break;
+ }
+ } // end of for
+
+ // 2. sort output section orders
+ std::stable_sort(output_list.begin(), output_list.end(), SHOCompare());
+
+ // 3. update output sections in Module
+ pModule.getSectionTable().clear();
+ for(size_t index = 0; index < output_list.size(); ++index) {
+ (output_list[index].first)->setIndex(index);
+ pModule.getSectionTable().push_back(output_list[index].first);
+ }
+
+ // 4. create program headers
+ if (LinkerConfig::Object != config().codeGenType()) {
+ createProgramHdrs(pModule, pLinker);
+ }
+
+ // 5. set output section offset
+ setOutputSectionOffset(pModule, pModule.begin(), pModule.end(), 0x0);
+}
+
/// preLayout - Backend can do any needed modification before layout
void GNULDBackend::preLayout(Module& pModule, FragmentLinker& pLinker)
{
@@ -1970,10 +2091,10 @@
RelocData* out_reloc_data = output_sect->getRelocData();
// move relocations from input's to output's RelcoationData
- RelocData::FragmentListType& out_list =
- out_reloc_data->getFragmentList();
- RelocData::FragmentListType& in_list =
- (*rs)->getRelocData()->getFragmentList();
+ RelocData::RelocationListType& out_list =
+ out_reloc_data->getRelocationList();
+ RelocData::RelocationListType& in_list =
+ (*rs)->getRelocData()->getRelocationList();
out_list.splice(out_list.end(), in_list);
// size output
@@ -1997,25 +2118,20 @@
void GNULDBackend::postLayout(Module& pModule,
FragmentLinker& pLinker)
{
- // 1. emit program headers
- if (LinkerConfig::Object != config().codeGenType()) {
- // 1.1 create program headers
- createProgramHdrs(pModule, pLinker);
- }
-
+ // 1. set up section address and segment attributes
if (LinkerConfig::Object != config().codeGenType()) {
if (config().options().hasRelro()) {
- // 1.2 set up the offset constraint of PT_RELRO
+ // 1.1 set up the offset constraint of PT_RELRO
setupRelro(pModule);
}
- // 1.3 set up the output sections' address
+ // 1.2 set up the output sections' address
setOutputSectionAddress(pLinker, pModule, pModule.begin(), pModule.end());
- // 1.4 do relaxation
+ // 1.3 do relaxation
relax(pModule, pLinker);
- // 1.5 set up the attributes of program headers
+ // 1.4 set up the attributes of program headers
setupProgramHdrs(pLinker);
}
@@ -2027,7 +2143,7 @@
{
if (config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
// emit eh_frame_hdr
- if (bitclass() == 32)
+ if (config().targets().is32Bits())
m_pEhFrameHdr->emitOutput<32>(pOutput);
}
}
@@ -2070,9 +2186,11 @@
// If we are building shared object, and the visibility is external, we
// need to add it.
if (LinkerConfig::DynObj == config().codeGenType() ||
- LinkerConfig::Exec == config().codeGenType()) {
+ LinkerConfig::Exec == config().codeGenType() ||
+ LinkerConfig::Binary == config().codeGenType()) {
if (pSymbol.resolveInfo()->visibility() == ResolveInfo::Default ||
- pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected) {
+ pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected ||
+ pSymbol.resolveInfo()->type() == ResolveInfo::ThreadLocal) {
return true;
}
}
@@ -2091,9 +2209,11 @@
// If we are building shared object, and the visibility is external, we
// need to add it.
if (LinkerConfig::DynObj == config().codeGenType() ||
- LinkerConfig::Exec == config().codeGenType()) {
+ LinkerConfig::Exec == config().codeGenType() ||
+ LinkerConfig::Binary == config().codeGenType()) {
if (pResolveInfo.visibility() == ResolveInfo::Default ||
- pResolveInfo.visibility() == ResolveInfo::Protected) {
+ pResolveInfo.visibility() == ResolveInfo::Protected ||
+ pResolveInfo.type() == ResolveInfo::ThreadLocal) {
return true;
}
}
@@ -2160,7 +2280,8 @@
// resolved to 0 and no need a dynamic relocation
if (pSym.isUndef() &&
!pSym.isDyn() &&
- LinkerConfig::Exec == config().codeGenType())
+ (LinkerConfig::Exec == config().codeGenType() ||
+ LinkerConfig::Binary == config().codeGenType()))
return false;
if (pSym.isAbsolute())
@@ -2214,7 +2335,9 @@
{
// if the output is pic code or if not executables, symbols' value may change
// at runtime
- if (pLinker.isOutputPIC() || LinkerConfig::Exec != config().codeGenType())
+ if (pLinker.isOutputPIC() ||
+ (LinkerConfig::Exec != config().codeGenType() &&
+ LinkerConfig::Binary != config().codeGenType()))
return false;
// if the symbol is from dynamic object, then its value is unknown
diff --git a/lib/Target/GOT.cpp b/lib/Target/GOT.cpp
index 32afdff..a441775 100644
--- a/lib/Target/GOT.cpp
+++ b/lib/Target/GOT.cpp
@@ -19,25 +19,10 @@
using namespace mcld;
//===----------------------------------------------------------------------===//
-// GOT::Entry
-//===----------------------------------------------------------------------===//
-GOT::Entry::Entry(uint64_t pContent, size_t pEntrySize, SectionData* pParent)
- : TargetFragment(Fragment::Target, pParent),
- f_Content(pContent),
- m_EntrySize(pEntrySize) {
-}
-
-GOT::Entry::~Entry()
-{
-}
-
-//===----------------------------------------------------------------------===//
// GOT
//===----------------------------------------------------------------------===//
-GOT::GOT(LDSection& pSection, size_t pEntrySize)
- : m_Section(pSection),
- f_EntrySize(pEntrySize),
- m_pLast(NULL) {
+GOT::GOT(LDSection& pSection)
+ : m_Section(pSection) {
m_SectionData = IRBuilder::CreateSectionData(pSection);
}
@@ -45,39 +30,15 @@
{
}
-size_t GOT::getEntrySize() const
-{
- return f_EntrySize;
-}
-
-void GOT::reserve(size_t pNum)
-{
- for (size_t i = 0; i < pNum; i++) {
- new Entry(0, f_EntrySize, m_SectionData);
- }
-}
-
-GOT::Entry* GOT::consume()
-{
- if (NULL == m_pLast) {
- assert(!empty() && "Consume empty GOT entry!");
- m_pLast = llvm::cast<Entry>(&m_SectionData->front());
- return m_pLast;
- }
-
- m_pLast = llvm::cast<Entry>(m_pLast->getNextNode());
- return m_pLast;
-}
-
void GOT::finalizeSectionSize()
{
- m_Section.setSize(m_SectionData->size() * f_EntrySize);
-
uint32_t offset = 0;
SectionData::iterator frag, fragEnd = m_SectionData->end();
for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
frag->setOffset(offset);
offset += frag->size();
}
+
+ m_Section.setSize(offset);
}
diff --git a/lib/Target/Mips/Android.mk b/lib/Target/Mips/Android.mk
index dd3905d..2410f6f 100644
--- a/lib/Target/Mips/Android.mk
+++ b/lib/Target/Mips/Android.mk
@@ -8,7 +8,7 @@
MipsGOT.cpp \
MipsLDBackend.cpp \
MipsMCLinker.cpp \
- MipsRelocationFactory.cpp \
+ MipsRelocator.cpp \
MipsTargetMachine.cpp
# For the host
diff --git a/lib/Target/Mips/MipsELFDynamic.cpp b/lib/Target/Mips/MipsELFDynamic.cpp
index fd779f3..58ed7a5 100644
--- a/lib/Target/Mips/MipsELFDynamic.cpp
+++ b/lib/Target/Mips/MipsELFDynamic.cpp
@@ -6,11 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include "MipsELFDynamic.h"
+#include "MipsLDBackend.h"
#include <mcld/LD/ELFFileFormat.h>
#include <mcld/Target/GNULDBackend.h>
-#include "MipsELFDynamic.h"
-#include "MipsLDBackend.h"
using namespace mcld;
@@ -24,8 +24,9 @@
MIPS_GOTSYM = 0x70000013
};
-MipsELFDynamic::MipsELFDynamic(const MipsGNULDBackend& pParent)
- : ELFDynamic(pParent),
+MipsELFDynamic::MipsELFDynamic(const MipsGNULDBackend& pParent,
+ const LinkerConfig& pConfig)
+ : ELFDynamic(pParent, pConfig),
m_pParent(pParent)
{
}
diff --git a/lib/Target/Mips/MipsELFDynamic.h b/lib/Target/Mips/MipsELFDynamic.h
index 118e4f9..6efbf71 100644
--- a/lib/Target/Mips/MipsELFDynamic.h
+++ b/lib/Target/Mips/MipsELFDynamic.h
@@ -21,7 +21,7 @@
class MipsELFDynamic : public ELFDynamic
{
public:
- MipsELFDynamic(const MipsGNULDBackend& pParent);
+ MipsELFDynamic(const MipsGNULDBackend& pParent, const LinkerConfig& pConfig);
~MipsELFDynamic();
private:
diff --git a/lib/Target/Mips/MipsEmulation.cpp b/lib/Target/Mips/MipsEmulation.cpp
index 74f2637..845e1a5 100644
--- a/lib/Target/Mips/MipsEmulation.cpp
+++ b/lib/Target/Mips/MipsEmulation.cpp
@@ -18,6 +18,10 @@
if (!MCLDEmulateELF(pConfig))
return false;
+ // set up bitclass and endian
+ pConfig.targets().setEndian(TargetOptions::Little);
+ pConfig.targets().setBitClass(32);
+
// set up target-dependent constraints of attributes
pConfig.attribute().constraint().enableWholeArchive();
pConfig.attribute().constraint().enableAsNeeded();
diff --git a/lib/Target/Mips/MipsGNUInfo.h b/lib/Target/Mips/MipsGNUInfo.h
new file mode 100644
index 0000000..9bbc548
--- /dev/null
+++ b/lib/Target/Mips/MipsGNUInfo.h
@@ -0,0 +1,29 @@
+//===- MipsGNUInfo.h ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_MIPS_GNU_INFO_H
+#define MCLD_TARGET_MIPS_GNU_INFO_H
+#include <mcld/Target/GNUInfo.h>
+
+#include <llvm/Support/ELF.h>
+
+namespace mcld {
+
+class MipsGNUInfo : public GNUInfo
+{
+public:
+ MipsGNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
+
+ uint32_t machine() const { return llvm::ELF::EM_MIPS; }
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
index b4eb1cd..d18eebf 100644
--- a/lib/Target/Mips/MipsGOT.cpp
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -16,7 +16,6 @@
#include <mcld/Support/MsgHandling.h>
namespace {
- const size_t MipsGOTEntrySize = 4;
const size_t MipsGOT0Num = 1;
}
@@ -26,8 +25,9 @@
// MipsGOT
//===----------------------------------------------------------------------===//
MipsGOT::MipsGOT(LDSection& pSection)
- : GOT(pSection, MipsGOTEntrySize),
- m_pLocalNum(0)
+ : GOT(pSection),
+ m_pLocalNum(0),
+ m_pLast(NULL)
{
// Create GOT0 entries.
reserve(MipsGOT0Num);
@@ -47,6 +47,25 @@
m_pLocalNum = MipsGOT0Num;
}
+void MipsGOT::reserve(size_t pNum)
+{
+ for (size_t i = 0; i < pNum; i++) {
+ new MipsGOTEntry(0, m_SectionData);
+ }
+}
+
+MipsGOTEntry* MipsGOT::consume()
+{
+ if (NULL == m_pLast) {
+ assert(!empty() && "Consume empty GOT entry!");
+ m_pLast = llvm::cast<MipsGOTEntry>(&m_SectionData->front());
+ return m_pLast;
+ }
+
+ m_pLast = llvm::cast<MipsGOTEntry>(m_pLast->getNextNode());
+ return m_pLast;
+}
+
bool MipsGOT::hasGOT1() const
{
return (m_SectionData->size() > MipsGOT0Num);
@@ -56,14 +75,12 @@
{
uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
- size_t entry_size = getEntrySize();
-
uint64_t result = 0;
for (iterator it = begin(), ie = end();
it != ie; ++it, ++buffer) {
- GOT::Entry* got = &(llvm::cast<GOT::Entry>((*it)));
- *buffer = static_cast<uint32_t>(got->getContent());
- result += entry_size;
+ MipsGOTEntry* got = &(llvm::cast<MipsGOTEntry>((*it)));
+ *buffer = static_cast<uint32_t>(got->getValue());
+ result += got->size();
}
return result;
}
@@ -83,22 +100,22 @@
reserve(1);
}
-GOT::Entry* MipsGOT::consumeLocal()
+MipsGOTEntry* MipsGOT::consumeLocal()
{
iterator& it = m_LocalGOTIterator;
++it;
assert(it != m_SectionData->getFragmentList().end() &&
"The number of GOT Entries and ResolveInfo doesn't match");
- return llvm::cast<GOT::Entry>(&(*it));
+ return llvm::cast<MipsGOTEntry>(&(*it));
}
-GOT::Entry* MipsGOT::consumeGlobal()
+MipsGOTEntry* MipsGOT::consumeGlobal()
{
iterator& it = m_GlobalGOTIterator;
++it;
assert(it != m_SectionData->getFragmentList().end() &&
"The number of GOT Entries and ResolveInfo doesn't match");
- return llvm::cast<GOT::Entry>(&(*it));
+ return llvm::cast<MipsGOTEntry>(&(*it));
}
size_t MipsGOT::getTotalNum() const
diff --git a/lib/Target/Mips/MipsGOT.h b/lib/Target/Mips/MipsGOT.h
index 6ec4926..fa46e91 100644
--- a/lib/Target/Mips/MipsGOT.h
+++ b/lib/Target/Mips/MipsGOT.h
@@ -21,6 +21,17 @@
class LDSection;
class MemoryRegion;
+/** \class MipsGOTEntry
+ * \brief GOT Entry with size of 4 bytes
+ */
+class MipsGOTEntry : public GOT::Entry<4>
+{
+public:
+ MipsGOTEntry(uint64_t pContent, SectionData* pParent)
+ : GOT::Entry<4>(pContent, pParent)
+ {}
+};
+
/** \class MipsGOT
* \brief Mips Global Offset Table.
*/
@@ -31,14 +42,16 @@
uint64_t emit(MemoryRegion& pRegion);
+ void reserve(size_t pNum = 1);
void reserveLocalEntry();
void reserveGlobalEntry();
size_t getTotalNum() const;
size_t getLocalNum() const;
- GOT::Entry* consumeLocal();
- GOT::Entry* consumeGlobal();
+ MipsGOTEntry* consume();
+ MipsGOTEntry* consumeLocal();
+ MipsGOTEntry* consumeGlobal();
void setLocal(const ResolveInfo* pInfo) {
m_GOTTypeMap[pInfo] = false;
@@ -68,6 +81,8 @@
iterator m_LocalGOTIterator; // last local GOT entries
iterator m_GlobalGOTIterator; // last global GOT entries
size_t m_pLocalNum;
+
+ MipsGOTEntry* m_pLast; ///< the last consumed entry
};
} // namespace of mcld
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
index da2399e..59b8d18 100644
--- a/lib/Target/Mips/MipsLDBackend.cpp
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -7,9 +7,10 @@
//
//===----------------------------------------------------------------------===//
#include "Mips.h"
+#include "MipsGNUInfo.h"
#include "MipsELFDynamic.h"
#include "MipsLDBackend.h"
-#include "MipsRelocationFactory.h"
+#include "MipsRelocator.h"
#include <llvm/ADT/Triple.h>
#include <llvm/Support/ELF.h>
@@ -43,9 +44,10 @@
//===----------------------------------------------------------------------===//
// MipsGNULDBackend
//===----------------------------------------------------------------------===//
-MipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig)
- : GNULDBackend(pConfig),
- m_pRelocFactory(NULL),
+MipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig,
+ MipsGNUInfo* pInfo)
+ : GNULDBackend(pConfig, pInfo),
+ m_pRelocator(NULL),
m_pGOT(NULL),
m_pRelDyn(NULL),
m_pDynamic(NULL),
@@ -56,7 +58,7 @@
MipsGNULDBackend::~MipsGNULDBackend()
{
- delete m_pRelocFactory;
+ delete m_pRelocator;
delete m_pGOT;
delete m_pRelDyn;
delete m_pDynamic;
@@ -73,9 +75,7 @@
// initialize .rel.dyn
LDSection& reldyn = file_format->getRelDyn();
- m_pRelDyn = new OutputRelocSection(pModule,
- reldyn,
- getRelEntrySize());
+ m_pRelDyn = new OutputRelocSection(pModule, reldyn);
}
}
@@ -110,19 +110,19 @@
}
}
-bool MipsGNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
+bool MipsGNULDBackend::initRelocator(const FragmentLinker& pLinker)
{
- if (NULL == m_pRelocFactory) {
- m_pRelocFactory = new MipsRelocationFactory(1024, *this);
- m_pRelocFactory->setFragmentLinker(pLinker);
+ if (NULL == m_pRelocator) {
+ m_pRelocator = new MipsRelocator(*this);
+ m_pRelocator->setFragmentLinker(pLinker);
}
return true;
}
-RelocationFactory* MipsGNULDBackend::getRelocFactory()
+Relocator* MipsGNULDBackend::getRelocator()
{
- assert(NULL != m_pRelocFactory);
- return m_pRelocFactory;
+ assert(NULL != m_pRelocator);
+ return m_pRelocator;
}
void MipsGNULDBackend::scanRelocation(Relocation& pReloc,
@@ -156,7 +156,7 @@
// check if we shoule issue undefined reference for the relocation target
// symbol
- if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+ if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
fatal(diag::undefined_reference) << rsym->name();
if ((rsym->reserved() & ReserveRel) != 0x0) {
@@ -165,21 +165,6 @@
}
}
-uint32_t MipsGNULDBackend::machine() const
-{
- return llvm::ELF::EM_MIPS;
-}
-
-uint8_t MipsGNULDBackend::OSABI() const
-{
- return llvm::ELF::ELFOSABI_NONE;
-}
-
-uint8_t MipsGNULDBackend::ABIVersion() const
-{
- return 0;
-}
-
uint64_t MipsGNULDBackend::flags() const
{
// TODO: (simon) The correct flag's set depend on command line
@@ -191,17 +176,6 @@
E_MIPS_ABI_O32;
}
-bool MipsGNULDBackend::isLittleEndian() const
-{
- // Now we support little endian (mipsel) target only.
- return true;
-}
-
-unsigned int MipsGNULDBackend::bitclass() const
-{
- return 32;
-}
-
uint64_t MipsGNULDBackend::defaultTextSegmentAddr() const
{
return 0x80000;
@@ -227,9 +201,11 @@
defineGOTSymbol(pLinker);
}
+ ELFFileFormat* file_format = getOutputFormat();
// set .rel.dyn size
if (!m_pRelDyn->empty())
- m_pRelDyn->finalizeSectionSize();
+ file_format->getRelDyn().setSize(
+ m_pRelDyn->numOfRelocs() * getRelEntrySize());
}
}
void MipsGNULDBackend::doPostLayout(Module& pModule,
@@ -242,7 +218,7 @@
MipsELFDynamic& MipsGNULDBackend::dynamic()
{
if (NULL == m_pDynamic)
- m_pDynamic = new MipsELFDynamic(*this);
+ m_pDynamic = new MipsELFDynamic(*this, config());
return *m_pDynamic;
}
@@ -298,6 +274,9 @@
size_t shstrtab = 1;
size_t hash = 0;
+ // number of local symbol in the .dynsym
+ size_t dynsym_local_cnt = 0;
+
/// compute the size of .symtab, .dynsym and .strtab
/// @{
Module::const_sym_iterator symbol;
@@ -329,6 +308,7 @@
if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
strtab += str_size;
}
+ dynsym_local_cnt = dynsym;
// compute the size of the reset of symbols
symEnd = pModule.sym_end();
for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
@@ -384,21 +364,28 @@
}
// set size
- if (32 == bitclass())
+ if (config().targets().is32Bits())
file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf32_Sym));
else
file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf64_Sym));
file_format->getDynStrTab().setSize(dynstr);
file_format->getHashTab().setSize(hash);
+ // set .dynsym sh_info to one greater than the symbol table
+ // index of the last local symbol
+ file_format->getDynSymTab().setInfo(dynsym_local_cnt);
}
/* fall through */
case LinkerConfig::Object: {
- if (32 == bitclass())
+ if (config().targets().is32Bits())
file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf32_Sym));
else
file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf64_Sym));
file_format->getStrTab().setSize(strtab);
+
+ // set .symtab sh_info to one greater than the symbol table
+ // index of the last local symbol
+ file_format->getSymTab().setInfo(symbols.numOfLocals() + 1);
break;
}
default: {
@@ -415,7 +402,7 @@
// Because some entries in .dynamic section need information of .dynsym,
// .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
// entries until we get the size of the sections mentioned above
- dynamic().reserveEntries(config(), *file_format);
+ dynamic().reserveEntries(*file_format);
file_format->getDynamic().setSize(dynamic().numOfBytes());
}
/// @}
@@ -630,7 +617,7 @@
// initialize value of ELF .dynamic section
if (LinkerConfig::DynObj == config().codeGenType())
dynamic().applySoname(strtabsize);
- dynamic().applyEntries(config(), *file_format);
+ dynamic().applyEntries(*file_format);
dynamic().emit(dyn_sect, *dyn_region);
strcpy((strtab + strtabsize), pModule.name().c_str());
@@ -823,7 +810,7 @@
// section if the symbol section flags contains SHF_EXECINSTR.
// 1. Find the reason of this condition.
// 2. Check this condition here.
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
rsym->setReserved(rsym->reserved() | ReserveRel);
// Remeber this rsym is a local GOT entry (as if it needs an entry).
@@ -927,7 +914,7 @@
case llvm::ELF::R_MIPS_HI16:
case llvm::ELF::R_MIPS_LO16:
if (symbolNeedsDynRel(pLinker, *rsym, false, true)) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
rsym->setReserved(rsym->reserved() | ReserveRel);
// Remeber this rsym is a global GOT entry (as if it needs an entry).
@@ -1038,13 +1025,13 @@
static TargetLDBackend* createMipsLDBackend(const llvm::Target& pTarget,
const LinkerConfig& pConfig)
{
- if (pConfig.triple().isOSDarwin()) {
+ if (pConfig.targets().triple().isOSDarwin()) {
assert(0 && "MachO linker is not supported yet");
}
- if (pConfig.triple().isOSWindows()) {
+ if (pConfig.targets().triple().isOSWindows()) {
assert(0 && "COFF linker is not supported yet");
}
- return new MipsGNULDBackend(pConfig);
+ return new MipsGNULDBackend(pConfig, new MipsGNUInfo(pConfig.targets().triple()));
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
index b6adb93..b9db410 100644
--- a/lib/Target/Mips/MipsLDBackend.h
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -19,6 +19,7 @@
class OutputRelocSection;
class SectionMap;
class MemoryArea;
+class MipsGNUInfo;
//===----------------------------------------------------------------------===//
/// MipsGNULDBackend - linker backend of Mips target of GNU ELF format
@@ -34,7 +35,7 @@
};
public:
- MipsGNULDBackend(const LinkerConfig& pConfig);
+ MipsGNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo);
~MipsGNULDBackend();
public:
@@ -44,11 +45,11 @@
/// initTargetSymbols - initialize target dependent symbols in output.
void initTargetSymbols(FragmentLinker& pLinker);
- /// initRelocFactory - create and initialize RelocationFactory.
- bool initRelocFactory(const FragmentLinker& pLinker);
+ /// initRelocator - create and initialize Relocator.
+ bool initRelocator(const FragmentLinker& pLinker);
- /// getRelocFactory - return relocation factory.
- RelocationFactory* getRelocFactory();
+ /// getRelocator - return relocator.
+ Relocator* getRelocator();
/// scanRelocation - determine the empty entries are needed or not and
/// create the empty entries if needed.
@@ -58,21 +59,9 @@
Module& pModule,
const LDSection& pSection);
- uint32_t machine() const;
-
- /// OSABI - the value of e_ident[EI_OSABI]
- uint8_t OSABI() const;
-
- /// ABIVersion - the value of e_ident[EI_ABIVRESION]
- uint8_t ABIVersion() const;
-
/// flags - the value of ElfXX_Ehdr::e_flags
uint64_t flags() const;
- bool isLittleEndian() const;
-
- unsigned int bitclass() const;
-
uint64_t defaultTextSegmentAddr() const;
/// abiPageSize - the abi page size of the target machine
@@ -159,7 +148,7 @@
const FragmentLinker& pLinker);
private:
- RelocationFactory* m_pRelocFactory;
+ Relocator* m_pRelocator;
MipsGOT* m_pGOT; // .got
OutputRelocSection* m_pRelDyn; // .rel.dyn
diff --git a/lib/Target/Mips/MipsRelocationFunctions.h b/lib/Target/Mips/MipsRelocationFunctions.h
index adff43f..aad708e 100644
--- a/lib/Target/Mips/MipsRelocationFunctions.h
+++ b/lib/Target/Mips/MipsRelocationFunctions.h
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#define DECL_MIPS_APPLY_RELOC_FUNC(Name) \
-static MipsRelocationFactory::Result Name(Relocation& pEntry, \
- MipsRelocationFactory& pParent);
+static MipsRelocator::Result Name(Relocation& pEntry, \
+ MipsRelocator& pParent);
#define DECL_MIPS_APPLY_RELOC_FUNCS \
DECL_MIPS_APPLY_RELOC_FUNC(none) \
@@ -18,7 +18,9 @@
DECL_MIPS_APPLY_RELOC_FUNC(lo16) \
DECL_MIPS_APPLY_RELOC_FUNC(got16) \
DECL_MIPS_APPLY_RELOC_FUNC(call16) \
-DECL_MIPS_APPLY_RELOC_FUNC(gprel32)
+DECL_MIPS_APPLY_RELOC_FUNC(gprel32) \
+DECL_MIPS_APPLY_RELOC_FUNC(gothi16) \
+DECL_MIPS_APPLY_RELOC_FUNC(gotlo16)
#define DECL_MIPS_APPLY_RELOC_FUNC_PTRS \
{ &none, 0, "R_MIPS_NONE" }, \
@@ -43,16 +45,16 @@
{ &none, 19, "R_MIPS_GOT_DISP" }, \
{ &none, 20, "R_MIPS_GOT_PAGE" }, \
{ &none, 21, "R_MIPS_GOT_OFST" }, \
- { &none, 22, "R_MIPS_GOT_HI16" }, \
- { &none, 23, "R_MIPS_GOT_LO16" }, \
+ { &gothi16, 22, "R_MIPS_GOT_HI16" }, \
+ { &gotlo16, 23, "R_MIPS_GOT_LO16" }, \
{ &none, 24, "R_MIPS_SUB" }, \
{ &none, 25, "R_MIPS_INSERT_A" }, \
{ &none, 26, "R_MIPS_INSERT_B" }, \
{ &none, 27, "R_MIPS_DELETE" }, \
{ &none, 28, "R_MIPS_HIGHER" }, \
{ &none, 29, "R_MIPS_HIGHEST" }, \
- { &none, 30, "R_MIPS_CALL_HI16" }, \
- { &none, 31, "R_MIPS_CALL_LO16" }, \
+ { &gothi16, 30, "R_MIPS_CALL_HI16" }, \
+ { &gotlo16, 31, "R_MIPS_CALL_LO16" }, \
{ &none, 32, "R_MIPS_SCN_DISP" }, \
{ &none, 33, "R_MIPS_REL16" }, \
{ &none, 34, "R_MIPS_ADD_IMMEDIATE" }, \
diff --git a/lib/Target/Mips/MipsRelocationFactory.cpp b/lib/Target/Mips/MipsRelocator.cpp
similarity index 72%
rename from lib/Target/Mips/MipsRelocationFactory.cpp
rename to lib/Target/Mips/MipsRelocator.cpp
index 09041be..ad5de22 100644
--- a/lib/Target/Mips/MipsRelocationFactory.cpp
+++ b/lib/Target/Mips/MipsRelocator.cpp
@@ -1,4 +1,4 @@
-//===- MipsRelocationFactory.cpp -----------------------------------------===//
+//===- MipsRelocator.cpp -----------------------------------------===//
//
// The MCLinker Project
//
@@ -13,7 +13,7 @@
#include <mcld/Support/MsgHandling.h>
#include <mcld/Target/OutputRelocSection.h>
-#include "MipsRelocationFactory.h"
+#include "MipsRelocator.h"
#include "MipsRelocationFunctions.h"
using namespace mcld;
@@ -24,8 +24,7 @@
DECL_MIPS_APPLY_RELOC_FUNCS
/// the prototype of applying function
-typedef RelocationFactory::Result (*ApplyFunctionType)(Relocation&,
- MipsRelocationFactory&);
+typedef Relocator::Result (*ApplyFunctionType)(Relocation&, MipsRelocator&);
// the table entry of applying functions
struct ApplyFunctionTriple
@@ -41,18 +40,17 @@
};
//===----------------------------------------------------------------------===//
-// MipsRelocationFactory
+// MipsRelocator
//===----------------------------------------------------------------------===//
-MipsRelocationFactory::MipsRelocationFactory(size_t pNum,
- MipsGNULDBackend& pParent)
- : RelocationFactory(pNum),
+MipsRelocator::MipsRelocator(MipsGNULDBackend& pParent)
+ : Relocator(),
m_Target(pParent),
m_AHL(0)
{
}
-RelocationFactory::Result
-MipsRelocationFactory::applyRelocation(Relocation& pRelocation)
+Relocator::Result
+MipsRelocator::applyRelocation(Relocation& pRelocation)
{
Relocation::Type type = pRelocation.type();
@@ -65,7 +63,7 @@
return ApplyFunctions[type].func(pRelocation, *this);
}
-const char* MipsRelocationFactory::getName(Relocation::Type pType) const
+const char* MipsRelocator::getName(Relocation::Type pType) const
{
return ApplyFunctions[pType].name;
}
@@ -101,15 +99,15 @@
}
static
-RelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent)
+Relocator::Address helper_GetGP(MipsRelocator& pParent)
{
return pParent.getTarget().getGOT().addr() + 0x7FF0;
}
static
-GOT::Entry& helper_GetGOTEntry(Relocation& pReloc,
- MipsRelocationFactory& pParent,
- bool& pExist, int32_t value)
+MipsGOTEntry& helper_GetGOTEntry(Relocation& pReloc,
+ MipsRelocator& pParent,
+ bool& pExist, int32_t value)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
@@ -121,7 +119,7 @@
return *got.consumeLocal();
}
- GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ MipsGOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
if (NULL != got_entry) {
// found a mapping, then return the mapped entry immediately
return *got_entry;
@@ -137,7 +135,7 @@
// If we first get this GOT entry, we should initialize it.
if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
- got_entry->setContent(pReloc.symValue());
+ got_entry->setValue(pReloc.symValue());
}
else {
fatal(diag::reserve_entry_number_mismatch_got);
@@ -147,11 +145,11 @@
}
static
-RelocationFactory::Address helper_GetGOTOffset(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+Relocator::Address helper_GetGOTOffset(Relocation& pReloc,
+ MipsRelocator& pParent)
{
bool exist;
- GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
+ MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
return got_entry.getOffset() - 0x7FF0;
}
@@ -174,8 +172,7 @@
}
static
-void helper_DynRel(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+void helper_DynRel(Relocation& pReloc, MipsRelocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
MipsGNULDBackend& ld_backend = pParent.getTarget();
@@ -186,8 +183,8 @@
rel_entry.setType(llvm::ELF::R_MIPS_REL32);
rel_entry.targetRef() = pReloc.targetRef();
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- RelocationFactory::DWord S = pReloc.symValue();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ Relocator::DWord S = pReloc.symValue();
if (got.isLocal(rsym)) {
rel_entry.setSymInfo(NULL);
@@ -206,47 +203,44 @@
// R_MIPS_NONE and those unsupported/deprecated relocation type
static
-MipsRelocationFactory::Result none(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+MipsRelocator::Result none(Relocation& pReloc, MipsRelocator& pParent)
{
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
}
// R_MIPS_32: S + A
static
-MipsRelocationFactory::Result abs32(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+MipsRelocator::Result abs32(Relocation& pReloc, MipsRelocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- RelocationFactory::DWord S = pReloc.symValue();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ Relocator::DWord S = pReloc.symValue();
LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
pReloc.target() = S + A;
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
}
if (rsym->reserved() & MipsGNULDBackend::ReserveRel) {
helper_DynRel(pReloc, pParent);
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
}
pReloc.target() = (S + A);
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
}
// R_MIPS_HI16:
// local/external: ((AHL + S) - (short)(AHL + S)) >> 16
// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
static
-MipsRelocationFactory::Result hi16(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+MipsRelocator::Result hi16(Relocation& pReloc, MipsRelocator& pParent)
{
Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
assert(NULL != lo_reloc && "There is no paired R_MIPS_LO16 for R_MIPS_HI16");
@@ -269,15 +263,14 @@
pReloc.target() &= 0xFFFF0000;
pReloc.target() |= (res & 0xFFFF);
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
}
// R_MIPS_LO16:
// local/external: AHL + S
// _gp_disp : AHL + GP - P + 4
static
-MipsRelocationFactory::Result lo16(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+MipsRelocator::Result lo16(Relocation& pReloc, MipsRelocator& pParent)
{
int32_t res = 0;
@@ -299,18 +292,17 @@
pReloc.target() &= 0xFFFF0000;
pReloc.target() |= (res & 0xFFFF);
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
}
// R_MIPS_GOT16:
// local : G (calculate AHL and put high 16 bit to GOT)
// external: G
static
-MipsRelocationFactory::Result got16(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+MipsRelocator::Result got16(Relocation& pReloc, MipsRelocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- RelocationFactory::Address G = 0;
+ Relocator::Address G = 0;
if (rsym->isLocal()) {
Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
@@ -323,9 +315,9 @@
int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
bool exist;
- GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
+ MipsGOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
- got_entry.setContent(res);
+ got_entry.setValue(res);
G = got_entry.getOffset() - 0x7FF0;
}
else {
@@ -335,26 +327,55 @@
pReloc.target() &= 0xFFFF0000;
pReloc.target() |= (G & 0xFFFF);
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
}
-// R_MIPS_CALL16: G
+// R_MIPS_GOTHI16:
+// external: (G - (short)G) >> 16 + A
static
-MipsRelocationFactory::Result call16(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+MipsRelocator::Result gothi16(Relocation& pReloc, MipsRelocator& pParent)
{
- RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
+ int32_t res = 0;
+
+ Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
+ int32_t A = pReloc.target() + pReloc.addend();
+
+ res = (G - (int16_t)G) >> (16 + A);
+
+ pReloc.target() &= 0xFFFF0000;
+ pReloc.target() |= (res & 0xFFFF);
+
+ return MipsRelocator::OK;
+}
+
+// R_MIPS_GOTLO16:
+// external: G & 0xffff
+static
+MipsRelocator::Result gotlo16(Relocation& pReloc, MipsRelocator& pParent)
+{
+ Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
pReloc.target() &= 0xFFFF0000;
pReloc.target() |= (G & 0xFFFF);
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
+}
+
+// R_MIPS_CALL16: G
+static
+MipsRelocator::Result call16(Relocation& pReloc, MipsRelocator& pParent)
+{
+ Relocator::Address G = helper_GetGOTOffset(pReloc, pParent);
+
+ pReloc.target() &= 0xFFFF0000;
+ pReloc.target() |= (G & 0xFFFF);
+
+ return MipsRelocator::OK;
}
// R_MIPS_GPREL32: A + S + GP0 - GP
static
-MipsRelocationFactory::Result gprel32(Relocation& pReloc,
- MipsRelocationFactory& pParent)
+MipsRelocator::Result gprel32(Relocation& pReloc, MipsRelocator& pParent)
{
// Remember to add the section offset to A.
int32_t A = pReloc.target() + pReloc.addend();
@@ -365,5 +386,6 @@
// Assume that GP0 is zero.
pReloc.target() = (A + S - GP) & 0xFFFFFFFF;
- return MipsRelocationFactory::OK;
+ return MipsRelocator::OK;
}
+
diff --git a/lib/Target/Mips/MipsRelocationFactory.h b/lib/Target/Mips/MipsRelocator.h
similarity index 73%
rename from lib/Target/Mips/MipsRelocationFactory.h
rename to lib/Target/Mips/MipsRelocator.h
index 6076416..836b7d2 100644
--- a/lib/Target/Mips/MipsRelocationFactory.h
+++ b/lib/Target/Mips/MipsRelocator.h
@@ -1,4 +1,4 @@
-//===- MipsRelocationFactory.h --------------------------------------------===//
+//===- MipsRelocator.h --------------------------------------------===//
//
// The MCLinker Project
//
@@ -12,23 +12,23 @@
#include <gtest.h>
#endif
-#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/Relocator.h>
#include <mcld/Support/GCFactory.h>
#include <mcld/Target/SymbolEntryMap.h>
#include "MipsLDBackend.h"
namespace mcld {
-/** \class MipsRelocationFactory
- * \brief MipsRelocationFactory creates and destroys the Mips relocations.
+/** \class MipsRelocator
+ * \brief MipsRelocator creates and destroys the Mips relocations.
*/
-class MipsRelocationFactory : public RelocationFactory
+class MipsRelocator : public Relocator
{
public:
- typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
+ typedef SymbolEntryMap<MipsGOTEntry> SymGOTMap;
public:
- MipsRelocationFactory(size_t pNum, MipsGNULDBackend& pParent);
+ MipsRelocator(MipsGNULDBackend& pParent);
Result applyRelocation(Relocation& pRelocation);
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
index 593bdb9..3c1a0ce 100644
--- a/lib/Target/OutputRelocSection.cpp
+++ b/lib/Target/OutputRelocSection.cpp
@@ -6,28 +6,24 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
-#include <llvm/Support/Casting.h>
+#include <mcld/Target/OutputRelocSection.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/RelocationFactory.h>
#include <mcld/Module.h>
#include <mcld/Support/MsgHandling.h>
-#include <mcld/Target/OutputRelocSection.h>
#include <mcld/IRBuilder.h>
+#include <llvm/Support/Casting.h>
+
using namespace mcld;
//===----------------------------------------------------------------------===//
// OutputRelocSection
//===----------------------------------------------------------------------===//
-OutputRelocSection::OutputRelocSection(Module& pModule,
- LDSection& pSection,
- unsigned int pEntrySize)
+OutputRelocSection::OutputRelocSection(Module& pModule, LDSection& pSection)
: m_Module(pModule),
- m_pSection(&pSection),
m_pRelocData(NULL),
- m_EntryBytes(pEntrySize),
m_isVisit(false),
m_ValidEntryIterator(){
assert(!pSection.hasRelocData() && "Given section is not a relocation section");
@@ -38,15 +34,10 @@
{
}
-void OutputRelocSection::reserveEntry(RelocationFactory& pRelFactory,
- size_t pNum)
+void OutputRelocSection::reserveEntry(size_t pNum)
{
- for(size_t i=0; i<pNum; i++) {
- m_pRelocData->getFragmentList().push_back(
- pRelFactory.produceEmptyEntry());
- // update section size
- m_pSection->setSize(m_pSection->size() + m_EntryBytes);
- }
+ for(size_t i=0; i<pNum; i++)
+ m_pRelocData->append(*Relocation::Create());
}
Relocation* OutputRelocSection::consumeEntry()
@@ -54,9 +45,9 @@
// first time visit this function, set m_ValidEntryIterator to
// Fragments.begin()
if(!m_isVisit) {
- assert(!m_pRelocData->getFragmentList().empty() &&
+ assert(!m_pRelocData->getRelocationList().empty() &&
"DynRelSection contains no entries.");
- m_ValidEntryIterator = m_pRelocData->getFragmentList().begin();
+ m_ValidEntryIterator = m_pRelocData->begin();
m_isVisit = true;
}
else {
@@ -70,13 +61,12 @@
assert(m_ValidEntryIterator != m_pRelocData->end() &&
"No empty relocation entry for the incoming symbol.");
- Relocation* result = &llvm::cast<Relocation>(*m_ValidEntryIterator);
- return result;
+ return &(*m_ValidEntryIterator);
}
-void OutputRelocSection::finalizeSectionSize()
+size_t OutputRelocSection::numOfRelocs()
{
- m_pSection->setSize(m_pRelocData->size() * m_EntryBytes);
+ return m_pRelocData->size();
}
bool OutputRelocSection::addSymbolToDynSym(LDSymbol& pSymbol)
@@ -84,3 +74,4 @@
m_Module.getSymbolTable().changeLocalToTLS(pSymbol);
return true;
}
+
diff --git a/lib/Target/PLT.cpp b/lib/Target/PLT.cpp
index a8b515c..60e219e 100644
--- a/lib/Target/PLT.cpp
+++ b/lib/Target/PLT.cpp
@@ -15,23 +15,6 @@
class GOT;
//===----------------------------------------------------------------------===//
-// PLT::Entry
-//===----------------------------------------------------------------------===//
-PLT::Entry::Entry(size_t pSize, SectionData& pParent)
- : TargetFragment(Fragment::Target, &pParent),
- m_EntrySize(pSize), m_pContent(NULL)
-{
-}
-
-PLT::Entry::~Entry()
-{
- if (m_pContent) {
- free(m_pContent);
- m_pContent = NULL;
- }
-}
-
-//===----------------------------------------------------------------------===//
// PLT
//===----------------------------------------------------------------------===//
PLT::PLT(LDSection& pSection)
diff --git a/lib/Target/X86/Android.mk b/lib/Target/X86/Android.mk
index cf7ea17..94b2f0f 100644
--- a/lib/Target/X86/Android.mk
+++ b/lib/Target/X86/Android.mk
@@ -10,7 +10,7 @@
X86LDBackend.cpp \
X86MCLinker.cpp \
X86PLT.cpp \
- X86RelocationFactory.cpp \
+ X86Relocator.cpp \
X86TargetMachine.cpp
# For the host
diff --git a/lib/Target/X86/X86ELFDynamic.cpp b/lib/Target/X86/X86ELFDynamic.cpp
index af86b2c..c74cc13 100644
--- a/lib/Target/X86/X86ELFDynamic.cpp
+++ b/lib/Target/X86/X86ELFDynamic.cpp
@@ -6,14 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include "X86ELFDynamic.h"
#include <mcld/LD/ELFFileFormat.h>
-#include "X86ELFDynamic.h"
using namespace mcld;
-X86ELFDynamic::X86ELFDynamic(const GNULDBackend& pParent)
- : ELFDynamic(pParent)
+X86ELFDynamic::X86ELFDynamic(const GNULDBackend& pParent,
+ const LinkerConfig& pConfig)
+ : ELFDynamic(pParent, pConfig)
{
}
diff --git a/lib/Target/X86/X86ELFDynamic.h b/lib/Target/X86/X86ELFDynamic.h
index 7053a0b..e3d5338 100644
--- a/lib/Target/X86/X86ELFDynamic.h
+++ b/lib/Target/X86/X86ELFDynamic.h
@@ -19,7 +19,7 @@
class X86ELFDynamic : public ELFDynamic
{
public:
- X86ELFDynamic(const GNULDBackend& pParent);
+ X86ELFDynamic(const GNULDBackend& pParent, const LinkerConfig& pConfig);
~X86ELFDynamic();
private:
diff --git a/lib/Target/X86/X86Emulation.cpp b/lib/Target/X86/X86Emulation.cpp
index 74b7e47..9343583 100644
--- a/lib/Target/X86/X86Emulation.cpp
+++ b/lib/Target/X86/X86Emulation.cpp
@@ -18,6 +18,10 @@
if (!MCLDEmulateELF(pConfig))
return false;
+ // set up bitclass and endian
+ pConfig.targets().setEndian(TargetOptions::Little);
+ pConfig.targets().setBitClass(32);
+
// set up target-dependent constraints of attributes
pConfig.attribute().constraint().enableWholeArchive();
pConfig.attribute().constraint().enableAsNeeded();
diff --git a/lib/Target/X86/X86GNUInfo.h b/lib/Target/X86/X86GNUInfo.h
new file mode 100644
index 0000000..af548f0
--- /dev/null
+++ b/lib/Target/X86/X86GNUInfo.h
@@ -0,0 +1,29 @@
+//===- X86GNUInfo.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_X86_GNU_INFO_H
+#define MCLD_TARGET_X86_GNU_INFO_H
+#include <mcld/Target/GNUInfo.h>
+
+#include <llvm/Support/ELF.h>
+
+namespace mcld {
+
+class X86GNUInfo : public GNUInfo
+{
+public:
+ X86GNUInfo(const llvm::Triple& pTriple) : GNUInfo(pTriple) { }
+
+ uint32_t machine() const { return llvm::ELF::EM_386; }
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
index ae28ea7..e734bb3 100644
--- a/lib/Target/X86/X86GOT.cpp
+++ b/lib/Target/X86/X86GOT.cpp
@@ -11,9 +11,7 @@
#include <mcld/LD/LDFileFormat.h>
#include <mcld/LD/SectionData.h>
-namespace {
- const size_t X86GOTEntrySize = 4;
-}
+#include <llvm/Support/Casting.h>
using namespace mcld;
@@ -21,7 +19,7 @@
// X86GOT
//===----------------------------------------------------------------------===//
X86GOT::X86GOT(LDSection& pSection)
- : GOT(pSection, X86GOTEntrySize)
+ : GOT(pSection), m_pLast(NULL)
{
}
@@ -29,3 +27,22 @@
{
}
+void X86GOT::reserve(size_t pNum)
+{
+ for (size_t i = 0; i < pNum; i++) {
+ new X86GOTEntry(0, m_SectionData);
+ }
+}
+
+X86GOTEntry* X86GOT::consume()
+{
+ if (NULL == m_pLast) {
+ assert(!empty() && "Consume empty GOT entry!");
+ m_pLast = llvm::cast<X86GOTEntry>(&m_SectionData->front());
+ return m_pLast;
+ }
+
+ m_pLast = llvm::cast<X86GOTEntry>(m_pLast->getNextNode());
+ return m_pLast;
+}
+
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
index a027dc7..66967e1 100644
--- a/lib/Target/X86/X86GOT.h
+++ b/lib/Target/X86/X86GOT.h
@@ -19,6 +19,17 @@
class LDSection;
class SectionData;
+/** \class X86GOTEntry
+ * \brief GOT Entry with size of 4 bytes
+ */
+class X86GOTEntry : public GOT::Entry<4>
+{
+public:
+ X86GOTEntry(uint64_t pContent, SectionData* pParent)
+ : GOT::Entry<4>(pContent, pParent)
+ {}
+};
+
/** \class X86GOT
* \brief X86 Global Offset Table.
*/
@@ -29,6 +40,13 @@
X86GOT(LDSection& pSection);
~X86GOT();
+
+ void reserve(size_t pNum = 1);
+
+ X86GOTEntry* consume();
+
+private:
+ X86GOTEntry* m_pLast; ///< the last consumed entry
};
} // namespace of mcld
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index b4e0ffe..b72487e 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -9,25 +9,19 @@
#include "X86GOTPLT.h"
#include "X86PLT.h"
-#include <new>
-
#include <llvm/Support/Casting.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDFileFormat.h>
#include <mcld/Support/MsgHandling.h>
-namespace {
- const uint64_t X86GOTPLTEntrySize = 4;
-}
-
namespace mcld {
//===----------------------------------------------------------------------===//
// X86GOTPLT
//===----------------------------------------------------------------------===//
X86GOTPLT::X86GOTPLT(LDSection& pSection)
- : GOT(pSection, X86GOTPLTEntrySize)
+ : GOT(pSection), m_pLast(NULL)
{
// Create GOT0 entries
reserve(X86GOTPLT0Num);
@@ -42,6 +36,25 @@
{
}
+void X86GOTPLT::reserve(size_t pNum)
+{
+ for (size_t i = 0; i < pNum; i++) {
+ new X86GOTPLTEntry(0, m_SectionData);
+ }
+}
+
+X86GOTPLTEntry* X86GOTPLT::consume()
+{
+ if (NULL == m_pLast) {
+ assert(!empty() && "Consume empty GOT entry!");
+ m_pLast = llvm::cast<X86GOTPLTEntry>(&m_SectionData->front());
+ return m_pLast;
+ }
+
+ m_pLast = llvm::cast<X86GOTPLTEntry>(m_pLast->getNextNode());
+ return m_pLast;
+}
+
bool X86GOTPLT::hasGOT1() const
{
return (m_SectionData->size() > X86GOTPLT0Num);
@@ -49,8 +62,8 @@
void X86GOTPLT::applyGOT0(uint64_t pAddress)
{
- llvm::cast<Entry>
- (*(m_SectionData->getFragmentList().begin())).setContent(pAddress);
+ llvm::cast<X86GOTPLTEntry>
+ (*(m_SectionData->getFragmentList().begin())).setValue(pAddress);
}
void X86GOTPLT::applyAllGOTPLT(const X86PLT& pPLT)
@@ -62,7 +75,7 @@
// address of corresponding plt entry
uint64_t plt_addr = pPLT.addr() + pPLT.getPLT0Size();
for (; it != end() ; ++it) {
- llvm::cast<Entry>(*it).setContent(plt_addr + 6);
+ llvm::cast<X86GOTPLTEntry>(*it).setValue(plt_addr + 6);
plt_addr += pPLT.getPLT1Size();
}
}
diff --git a/lib/Target/X86/X86GOTPLT.h b/lib/Target/X86/X86GOTPLT.h
index b2fa65a..f288fa4 100644
--- a/lib/Target/X86/X86GOTPLT.h
+++ b/lib/Target/X86/X86GOTPLT.h
@@ -23,6 +23,14 @@
const unsigned int X86GOTPLT0Num = 3;
+class X86GOTPLTEntry : public GOT::Entry<4>
+{
+public:
+ X86GOTPLTEntry(uint64_t pContent, SectionData* pParent)
+ : GOT::Entry<4>(pContent, pParent)
+ {}
+};
+
/** \class X86GOTPLT
* \brief X86 .got.plt section.
*/
@@ -33,12 +41,19 @@
~X86GOTPLT();
+ void reserve(size_t pNum = 1);
+
+ X86GOTPLTEntry* consume();
+
// hasGOT1 - return if this section has any GOT1 entry
bool hasGOT1() const;
void applyGOT0(uint64_t pAddress);
void applyAllGOTPLT(const X86PLT& pPLT);
+
+private:
+ X86GOTPLTEntry* m_pLast; ///< the last consumed entry
};
} // namespace of mcld
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index 987daec..a18fedb 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -9,7 +9,8 @@
#include "X86.h"
#include "X86ELFDynamic.h"
#include "X86LDBackend.h"
-#include "X86RelocationFactory.h"
+#include "X86Relocator.h"
+#include "X86GNUInfo.h"
#include <llvm/ADT/Triple.h>
#include <llvm/Support/Casting.h>
@@ -31,9 +32,9 @@
//===----------------------------------------------------------------------===//
// X86GNULDBackend
//===----------------------------------------------------------------------===//
-X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig)
- : GNULDBackend(pConfig),
- m_pRelocFactory(NULL),
+X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig, X86GNUInfo* pInfo)
+ : GNULDBackend(pConfig, pInfo),
+ m_pRelocator(NULL),
m_pGOT(NULL),
m_pPLT(NULL),
m_pGOTPLT(NULL),
@@ -45,7 +46,7 @@
X86GNULDBackend::~X86GNULDBackend()
{
- delete m_pRelocFactory;
+ delete m_pRelocator;
delete m_pGOT;
delete m_pPLT;
delete m_pGOTPLT;
@@ -54,21 +55,21 @@
delete m_pDynamic;
}
-RelocationFactory* X86GNULDBackend::getRelocFactory()
+bool X86GNULDBackend::initRelocator(const FragmentLinker& pLinker)
{
- assert(NULL != m_pRelocFactory);
- return m_pRelocFactory;
-}
-
-bool X86GNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
-{
- if (NULL == m_pRelocFactory) {
- m_pRelocFactory = new X86RelocationFactory(1024, *this);
- m_pRelocFactory->setFragmentLinker(pLinker);
+ if (NULL == m_pRelocator) {
+ m_pRelocator = new X86Relocator(*this);
+ m_pRelocator->setFragmentLinker(pLinker);
}
return true;
}
+Relocator* X86GNULDBackend::getRelocator()
+{
+ assert(NULL != m_pRelocator);
+ return m_pRelocator;
+}
+
void X86GNULDBackend::doPreLayout(FragmentLinker& pLinker)
{
// set .got.plt size
@@ -89,13 +90,16 @@
if (m_pPLT->hasPLT1())
m_pPLT->finalizeSectionSize();
+ ELFFileFormat* file_format = getOutputFormat();
// set .rel.dyn size
if (!m_pRelDyn->empty())
- m_pRelDyn->finalizeSectionSize();
+ file_format->getRelDyn().setSize(
+ m_pRelDyn->numOfRelocs() * getRelEntrySize());
// set .rel.plt size
if (!m_pRelPLT->empty())
- m_pRelPLT->finalizeSectionSize();
+ file_format->getRelPlt().setSize(
+ m_pRelPLT->numOfRelocs() * getRelEntrySize());
}
}
@@ -109,7 +113,7 @@
X86ELFDynamic& X86GNULDBackend::dynamic()
{
if (NULL == m_pDynamic)
- m_pDynamic = new X86ELFDynamic(*this);
+ m_pDynamic = new X86ELFDynamic(*this, config());
return *m_pDynamic;
}
@@ -186,7 +190,7 @@
// Determine the alignment by the symbol value
// FIXME: here we use the largest alignment
- uint32_t addralign = bitclass() / 8;
+ uint32_t addralign = config().targets().bitclass() / 8;
// allocate space in BSS for the copy symbol
Fragment* frag = new FillFragment(0x0, 1, pSym.size());
@@ -233,7 +237,7 @@
// a dynamic relocations with RELATIVE type to this location is needed.
// Reserve an entry in .rel.dyn
if (pLinker.isOutputPIC()) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set Rel bit
rsym->setReserved(rsym->reserved() | ReserveRel);
}
@@ -256,7 +260,7 @@
// entry in .rel.dyn
if (LinkerConfig::DynObj ==
config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
return;
@@ -276,7 +280,7 @@
return;
m_pGOT->reserve(2);
// reserve an rel entry
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
// define the section symbol for .tdata or .tbss
@@ -310,14 +314,14 @@
setHasStaticTLS();
// if buildint shared object, a RELATIVE dynamic relocation is needed
if (LinkerConfig::DynObj == config().codeGenType()) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
rsym->setReserved(rsym->reserved() | ReserveRel);
}
if (rsym->reserved() & GOTRel)
return;
// reserve got and dyn relocation entries for tp-relative offset
m_pGOT->reserve();
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
@@ -329,7 +333,7 @@
return;
// reserve got and dyn relocation entries for tp-relative offset
m_pGOT->reserve();
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
@@ -340,7 +344,7 @@
setHasStaticTLS();
// if buildint shared object, a dynamic relocation is needed
if (LinkerConfig::DynObj == config().codeGenType()) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
rsym->setReserved(rsym->reserved() | ReserveRel);
// the target symbol of the dynamic relocation is rsym, so we need to
// emit it into .dynsym
@@ -379,7 +383,7 @@
// when calling X86PLT->reserveEntry())
m_pPLT->reserveEntry();
m_pGOTPLT->reserve();
- m_pRelPLT->reserveEntry(*m_pRelocFactory);
+ m_pRelPLT->reserveEntry();
// set PLT bit
rsym->setReserved(rsym->reserved() | ReservePLT);
}
@@ -388,7 +392,7 @@
if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
true)) {
// symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
addCopyReloc(*cpy_sym.resolveInfo());
@@ -430,7 +434,7 @@
// when calling X86PLT->reserveEntry())
m_pPLT->reserveEntry();
m_pGOTPLT->reserve();
- m_pRelPLT->reserveEntry(*m_pRelocFactory);
+ m_pRelPLT->reserveEntry();
// set PLT bit
rsym->setReserved(rsym->reserved() | ReservePLT);
return;
@@ -446,7 +450,7 @@
// entry in .rel.dyn
if (LinkerConfig::DynObj ==
config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
return;
@@ -469,7 +473,7 @@
// when calling X86PLT->reserveEntry())
m_pPLT->reserveEntry();
m_pGOTPLT->reserve();
- m_pRelPLT->reserveEntry(*m_pRelocFactory);
+ m_pRelPLT->reserveEntry();
// set PLT bit
rsym->setReserved(rsym->reserved() | ReservePLT);
}
@@ -478,7 +482,7 @@
if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
false)) {
// symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
addCopyReloc(*cpy_sym.resolveInfo());
@@ -496,7 +500,7 @@
return;
// reserve two pairs of got entry and dynamic relocation
m_pGOT->reserve(2);
- m_pRelDyn->reserveEntry(*m_pRelocFactory, 2);
+ m_pRelDyn->reserveEntry(2);
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
return;
@@ -513,14 +517,14 @@
setHasStaticTLS();
// if buildint shared object, a RELATIVE dynamic relocation is needed
if (LinkerConfig::DynObj == config().codeGenType()) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
rsym->setReserved(rsym->reserved() | ReserveRel);
}
if (rsym->reserved() & GOTRel)
return;
// reserve got and dyn relocation entries for tp-relative offset
m_pGOT->reserve();
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
return;
@@ -531,7 +535,7 @@
return;
// reserve got and dyn relocation entries for tp-relative offset
m_pGOT->reserve();
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
return;
@@ -541,7 +545,7 @@
setHasStaticTLS();
// if buildint shared object, a dynamic relocation is needed
if (LinkerConfig::DynObj == config().codeGenType()) {
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
rsym->setReserved(rsym->reserved() | ReserveRel);
}
return;
@@ -579,7 +583,7 @@
// check if we shoule issue undefined reference for the relocation target
// symbol
- if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+ if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull())
fatal(diag::undefined_reference) << rsym->name();
if ((rsym->reserved() & ReserveRel) != 0x0) {
@@ -608,18 +612,18 @@
m_pPLT->applyPLT0();
m_pPLT->applyPLT1();
X86PLT::iterator it = m_pPLT->begin();
- unsigned int plt0_size = llvm::cast<X86PLT0>((*it)).getEntrySize();
+ unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size();
- memcpy(buffer, llvm::cast<X86PLT0>((*it)).getContent(), plt0_size);
+ memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size);
RegionSize += plt0_size;
++it;
- X86PLT1* plt1 = 0;
+ PLTEntryBase* plt1 = 0;
X86PLT::iterator ie = m_pPLT->end();
while (it != ie) {
- plt1 = &(llvm::cast<X86PLT1>(*it));
- EntrySize = plt1->getEntrySize();
- memcpy(buffer + RegionSize, plt1->getContent(), EntrySize);
+ plt1 = &(llvm::cast<PLTEntryBase>(*it));
+ EntrySize = plt1->size();
+ memcpy(buffer + RegionSize, plt1->getValue(), EntrySize);
RegionSize += EntrySize;
++it;
}
@@ -630,13 +634,13 @@
uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
- GOT::Entry* got = 0;
- EntrySize = m_pGOT->getEntrySize();
+ X86GOTEntry* got = 0;
+ EntrySize = X86GOTEntry::EntrySize;
for (X86GOT::iterator it = m_pGOT->begin(),
ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
- got = &(llvm::cast<GOT::Entry>((*it)));
- *buffer = static_cast<uint32_t>(got->getContent());
+ got = &(llvm::cast<X86GOTEntry>((*it)));
+ *buffer = static_cast<uint32_t>(got->getValue());
RegionSize += EntrySize;
}
}
@@ -648,13 +652,13 @@
uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
- GOT::Entry* got = 0;
- EntrySize = m_pGOTPLT->getEntrySize();
+ X86GOTEntry* got = 0;
+ EntrySize = X86GOTPLTEntry::EntrySize;
for (X86GOTPLT::iterator it = m_pGOTPLT->begin(),
ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
- got = &(llvm::cast<GOT::Entry>((*it)));
- *buffer = static_cast<uint32_t>(got->getContent());
+ got = &(llvm::cast<X86GOTEntry>((*it)));
+ *buffer = static_cast<uint32_t>(got->getValue());
RegionSize += EntrySize;
}
}
@@ -667,11 +671,6 @@
return RegionSize;
}
-uint32_t X86GNULDBackend::machine() const
-{
- return llvm::ELF::EM_386;
-}
-
X86GOT& X86GNULDBackend::getGOT()
{
assert(NULL != m_pGOT);
@@ -721,18 +720,18 @@
}
// Create a GOT entry for the TLS module index
-GOT::Entry& X86GNULDBackend::getTLSModuleID()
+X86GOTEntry& X86GNULDBackend::getTLSModuleID()
{
- static GOT::Entry* got_entry = NULL;
+ static X86GOTEntry* got_entry = NULL;
if (NULL != got_entry)
return *got_entry;
// Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
m_pGOT->reserve(2);
got_entry = m_pGOT->consume();
- m_pGOT->consume()->setContent(0x0);
+ m_pGOT->consume()->setValue(0x0);
- m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ m_pRelDyn->reserveEntry();
Relocation* rel_entry = m_pRelDyn->consumeEntry();
rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32);
rel_entry->targetRef().assign(*got_entry, 0x0);
@@ -776,11 +775,6 @@
return SHO_UNDEFINED;
}
-unsigned int X86GNULDBackend::bitclass() const
-{
- return 32;
-}
-
void X86GNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
{
if (LinkerConfig::Object != config().codeGenType()) {
@@ -802,14 +796,12 @@
// initialize .rel.plt
LDSection& relplt = file_format->getRelPlt();
relplt.setLink(&plt);
- m_pRelPLT = new OutputRelocSection(pModule,
- relplt,
- getRelEntrySize());
+ m_pRelPLT = new OutputRelocSection(pModule, relplt);
+
// initialize .rel.dyn
LDSection& reldyn = file_format->getRelDyn();
- m_pRelDyn = new OutputRelocSection(pModule,
- reldyn,
- getRelEntrySize());
+ m_pRelDyn = new OutputRelocSection(pModule, reldyn);
+
}
}
@@ -854,7 +846,7 @@
TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget,
const LinkerConfig& pConfig)
{
- if (pConfig.triple().isOSDarwin()) {
+ if (pConfig.targets().triple().isOSDarwin()) {
assert(0 && "MachO linker is not supported yet");
/**
return new X86MachOLDBackend(createX86MachOArchiveReader,
@@ -862,7 +854,7 @@
createX86MachOObjectWriter);
**/
}
- if (pConfig.triple().isOSWindows()) {
+ if (pConfig.targets().triple().isOSWindows()) {
assert(0 && "COFF linker is not supported yet");
/**
return new X86COFFLDBackend(createX86COFFArchiveReader,
@@ -870,7 +862,7 @@
createX86COFFObjectWriter);
**/
}
- return new X86GNULDBackend(pConfig);
+ return new X86GNULDBackend(pConfig, new X86GNUInfo(pConfig.targets().triple()));
}
} // namespace of mcld
diff --git a/lib/Target/X86/X86LDBackend.h b/lib/Target/X86/X86LDBackend.h
index fb3aa6b..3f8a626 100644
--- a/lib/Target/X86/X86LDBackend.h
+++ b/lib/Target/X86/X86LDBackend.h
@@ -20,6 +20,7 @@
namespace mcld {
class LinkerConfig;
+class X86GNUInfo;
//===----------------------------------------------------------------------===//
/// X86GNULDBackend - linker backend of X86 target of GNU ELF format
@@ -71,17 +72,12 @@
};
public:
- X86GNULDBackend(const LinkerConfig& pConfig);
+ X86GNULDBackend(const LinkerConfig& pConfig, X86GNUInfo* pInfo);
~X86GNULDBackend();
- RelocationFactory* getRelocFactory();
-
uint32_t machine() const;
- bool isLittleEndian() const
- { return true; }
-
X86GOT& getGOT();
const X86GOT& getGOT() const;
@@ -94,9 +90,7 @@
const X86PLT& getPLT() const;
- GOT::Entry& getTLSModuleID();
-
- unsigned int bitclass() const;
+ X86GOTEntry& getTLSModuleID();
/// preLayout - Backend can do any needed modification before layout
void doPreLayout(FragmentLinker& pLinker);
@@ -130,16 +124,6 @@
uint64_t emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const;
- /// OSABI - the value of e_ident[EI_OSABI]
- /// FIXME
- uint8_t OSABI() const
- { return llvm::ELF::ELFOSABI_NONE; }
-
- /// ABIVersion - the value of e_ident[EI_ABIVRESION]
- /// FIXME
- uint8_t ABIVersion() const
- { return 0x0; }
-
/// flags - the value of ElfXX_Ehdr::e_flags
/// FIXME
uint64_t flags() const
@@ -148,8 +132,11 @@
uint64_t defaultTextSegmentAddr() const
{ return 0x08048000; }
- // initRelocFactory - create and initialize RelocationFactory
- bool initRelocFactory(const FragmentLinker& pLinker);
+ /// initRelocator - create and initialize Relocator.
+ bool initRelocator(const FragmentLinker& pLinker);
+
+ /// getRelocator - return relocator.
+ Relocator* getRelocator();
void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
@@ -217,7 +204,7 @@
const FragmentLinker& pLinker);
private:
- RelocationFactory* m_pRelocFactory;
+ Relocator* m_pRelocator;
X86GOT* m_pGOT;
X86PLT* m_pPLT;
X86GOTPLT* m_pGOTPLT;
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index 5b5ac58..25eaab9 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -16,44 +16,30 @@
#include <mcld/LinkerConfig.h>
#include <mcld/Support/MsgHandling.h>
+using namespace mcld;
+
//===----------------------------------------------------------------------===//
// PLT entry data
//===----------------------------------------------------------------------===//
-namespace {
-
-const uint8_t x86_dyn_plt0[] = {
- 0xff, 0xb3, 0x04, 0, 0, 0, // pushl 0x4(%ebx)
- 0xff, 0xa3, 0x08, 0, 0, 0, // jmp *0x8(%ebx)
- 0x0f, 0x1f, 0x4, 0 // nopl 0(%eax)
-};
-
-const uint8_t x86_dyn_plt1[] = {
- 0xff, 0xa3, 0, 0, 0, 0, // jmp *sym@GOT(%ebx)
- 0x68, 0, 0, 0, 0, // pushl $offset
- 0xe9, 0, 0, 0, 0 // jmp plt0
-};
-
-const uint8_t x86_exec_plt0[] = {
- 0xff, 0x35, 0, 0, 0, 0, // pushl .got + 4
- 0xff, 0x25, 0, 0, 0, 0, // jmp *(.got + 8)
- 0x0f, 0x1f, 0x4, 0 // nopl 0(%eax)
-};
-
-const uint8_t x86_exec_plt1[] = {
- 0xff, 0x25, 0, 0, 0, 0, // jmp *(sym in .got)
- 0x68, 0, 0, 0, 0, // pushl $offset
- 0xe9, 0, 0, 0, 0 // jmp plt0
-};
-
+X86DynPLT0::X86DynPLT0(SectionData& pParent)
+ : PLT::Entry<sizeof(x86_dyn_plt0)>(pParent)
+{
}
-namespace mcld {
+X86DynPLT1::X86DynPLT1(SectionData& pParent)
+ : PLT::Entry<sizeof(x86_dyn_plt1)>(pParent)
+{
+}
-X86PLT0::X86PLT0(SectionData& pParent, unsigned int pSize)
- : PLT::Entry(pSize, pParent) { }
+X86ExecPLT0::X86ExecPLT0(SectionData& pParent)
+ : PLT::Entry<sizeof(x86_exec_plt0)>(pParent)
+{
+}
-X86PLT1::X86PLT1(SectionData& pParent, unsigned int pSize)
- : PLT::Entry(pSize, pParent) { }
+X86ExecPLT1::X86ExecPLT1(SectionData& pParent)
+ : PLT::Entry<sizeof(x86_exec_plt1)>(pParent)
+{
+}
//===----------------------------------------------------------------------===//
// X86PLT
@@ -66,22 +52,25 @@
m_Config(pConfig)
{
assert(LinkerConfig::DynObj == m_Config.codeGenType() ||
- LinkerConfig::Exec == m_Config.codeGenType());
+ LinkerConfig::Exec == m_Config.codeGenType() ||
+ LinkerConfig::Binary == m_Config.codeGenType());
if (LinkerConfig::DynObj == m_Config.codeGenType()) {
- m_PLT0 = x86_dyn_plt0;
- m_PLT1 = x86_dyn_plt1;
- m_PLT0Size = sizeof (x86_dyn_plt0);
- m_PLT1Size = sizeof (x86_dyn_plt1);
+ m_PLT0 = x86_dyn_plt0;
+ m_PLT1 = x86_dyn_plt1;
+ m_PLT0Size = sizeof (x86_dyn_plt0);
+ m_PLT1Size = sizeof (x86_dyn_plt1);
+ // create PLT0
+ new X86DynPLT0(*m_SectionData);
}
else {
- m_PLT0 = x86_exec_plt0;
- m_PLT1 = x86_exec_plt1;
- m_PLT0Size = sizeof (x86_exec_plt0);
- m_PLT1Size = sizeof (x86_exec_plt1);
+ m_PLT0 = x86_exec_plt0;
+ m_PLT1 = x86_exec_plt1;
+ m_PLT0Size = sizeof (x86_exec_plt0);
+ m_PLT1Size = sizeof (x86_exec_plt1);
+ // create PLT0
+ new X86ExecPLT0(*m_SectionData);
}
- new X86PLT0(*m_SectionData, m_PLT0Size);
-
m_Last = m_SectionData->begin();
}
@@ -93,15 +82,15 @@
{
uint64_t size = 0;
// plt0 size
- size = getPLT0()->getEntrySize();
+ size = getPLT0()->size();
// get first plt1 entry
X86PLT::iterator it = begin();
++it;
if (end() != it) {
// plt1 size
- X86PLT1* plt1 = &(llvm::cast<X86PLT1>(*it));
- size += (m_SectionData->size() - 1) * plt1->getEntrySize();
+ PLTEntryBase* plt1 = &(llvm::cast<PLTEntryBase>(*it));
+ size += (m_SectionData->size() - 1) * plt1->size();
}
m_Section.setSize(size);
@@ -120,34 +109,37 @@
void X86PLT::reserveEntry(size_t pNum)
{
- X86PLT1* plt1_entry = 0;
+ PLTEntryBase* plt1_entry = NULL;
for (size_t i = 0; i < pNum; ++i) {
- plt1_entry = new (std::nothrow) X86PLT1(*m_SectionData, m_PLT1Size);
- if (!plt1_entry)
+ if (LinkerConfig::DynObj == m_Config.codeGenType())
+ plt1_entry = new X86DynPLT1(*m_SectionData);
+ else
+ plt1_entry = new X86ExecPLT1(*m_SectionData);
+
+ if (NULL == plt1_entry)
fatal(diag::fail_allocate_memory_plt);
}
}
-PLT::Entry* X86PLT::consume()
+PLTEntryBase* X86PLT::consume()
{
// This will skip PLT0.
++m_Last;
assert(m_Last != m_SectionData->end() &&
"The number of PLT Entries and ResolveInfo doesn't match");
- return llvm::cast<X86PLT1>(&(*m_Last));
+ return llvm::cast<PLTEntryBase>(&(*m_Last));
}
-X86PLT0* X86PLT::getPLT0() const
+PLTEntryBase* X86PLT::getPLT0() const
{
-
iterator first = m_SectionData->getFragmentList().begin();
assert(first != m_SectionData->getFragmentList().end() &&
"FragmentList is empty, getPLT0 failed!");
- X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
+ PLTEntryBase* plt0 = &(llvm::cast<PLTEntryBase>(*first));
return plt0;
}
@@ -155,15 +147,15 @@
// FIXME: It only works on little endian machine.
void X86PLT::applyPLT0()
{
- X86PLT0* plt0 = getPLT0();
+ PLTEntryBase* plt0 = getPLT0();
unsigned char* data = 0;
- data = static_cast<unsigned char*>(malloc(plt0->getEntrySize()));
+ data = static_cast<unsigned char*>(malloc(plt0->size()));
if (!data)
fatal(diag::fail_allocate_memory_plt);
- memcpy(data, m_PLT0, plt0->getEntrySize());
+ memcpy(data, m_PLT0, plt0->size());
if (m_PLT0 == x86_exec_plt0) {
uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
@@ -172,7 +164,7 @@
*offset = m_GOTPLT.addr() + 8;
}
- plt0->setContent(data);
+ plt0->setValue(data);
}
// FIXME: It only works on little endian machine.
@@ -184,7 +176,7 @@
X86PLT::iterator ie = m_SectionData->end();
assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
- uint64_t GOTEntrySize = m_GOTPLT.getEntrySize();
+ uint64_t GOTEntrySize = X86GOTPLTEntry::EntrySize;
// Skip GOT0
uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
@@ -195,19 +187,19 @@
uint64_t PLTEntryOffset = m_PLT0Size;
++it;
- X86PLT1* plt1 = 0;
+ PLTEntryBase* plt1 = 0;
uint64_t PLTRelOffset = 0;
while (it != ie) {
- plt1 = &(llvm::cast<X86PLT1>(*it));
+ plt1 = &(llvm::cast<PLTEntryBase>(*it));
unsigned char *data;
- data = static_cast<unsigned char*>(malloc(plt1->getEntrySize()));
+ data = static_cast<unsigned char*>(malloc(plt1->size()));
if (!data)
fatal(diag::fail_allocate_memory_plt);
- memcpy(data, m_PLT1, plt1->getEntrySize());
+ memcpy(data, m_PLT1, plt1->size());
uint32_t* offset;
@@ -223,10 +215,8 @@
*offset = -(PLTEntryOffset + 12 + 4);
PLTEntryOffset += m_PLT1Size;
- plt1->setContent(data);
+ plt1->setValue(data);
++it;
}
}
-} // end namespace mcld
-
diff --git a/lib/Target/X86/X86PLT.h b/lib/Target/X86/X86PLT.h
index 5e8b45f..75a72e6 100644
--- a/lib/Target/X86/X86PLT.h
+++ b/lib/Target/X86/X86PLT.h
@@ -11,24 +11,70 @@
#include <mcld/Target/PLT.h>
+namespace {
+
+const uint8_t x86_dyn_plt0[] = {
+ 0xff, 0xb3, 0x04, 0, 0, 0, // pushl 0x4(%ebx)
+ 0xff, 0xa3, 0x08, 0, 0, 0, // jmp *0x8(%ebx)
+ 0x0f, 0x1f, 0x4, 0 // nopl 0(%eax)
+};
+
+const uint8_t x86_dyn_plt1[] = {
+ 0xff, 0xa3, 0, 0, 0, 0, // jmp *sym@GOT(%ebx)
+ 0x68, 0, 0, 0, 0, // pushl $offset
+ 0xe9, 0, 0, 0, 0 // jmp plt0
+};
+
+const uint8_t x86_exec_plt0[] = {
+ 0xff, 0x35, 0, 0, 0, 0, // pushl .got + 4
+ 0xff, 0x25, 0, 0, 0, 0, // jmp *(.got + 8)
+ 0x0f, 0x1f, 0x4, 0 // nopl 0(%eax)
+};
+
+const uint8_t x86_exec_plt1[] = {
+ 0xff, 0x25, 0, 0, 0, 0, // jmp *(sym in .got)
+ 0x68, 0, 0, 0, 0, // pushl $offset
+ 0xe9, 0, 0, 0, 0 // jmp plt0
+};
+
+} // anonymous namespace
+
namespace mcld {
class X86GOTPLT;
class GOTEntry;
class LinkerConfig;
-class X86PLT0 : public PLT::Entry
+//===----------------------------------------------------------------------===//
+// X86PLT Entry
+//===----------------------------------------------------------------------===//
+class X86DynPLT0 : public PLT::Entry<sizeof(x86_dyn_plt0)>
{
public:
- X86PLT0(SectionData& pParent, unsigned int pSize);
+ X86DynPLT0(SectionData& pParent);
};
-class X86PLT1 : public PLT::Entry
+class X86DynPLT1 : public PLT::Entry<sizeof(x86_dyn_plt1)>
{
public:
- X86PLT1(SectionData& pParent, unsigned int pSize);
+ X86DynPLT1(SectionData& pParent);
};
+class X86ExecPLT0 : public PLT::Entry<sizeof(x86_exec_plt0)>
+{
+public:
+ X86ExecPLT0(SectionData& pParent);
+};
+
+class X86ExecPLT1 : public PLT::Entry<sizeof(x86_exec_plt1)>
+{
+public:
+ X86ExecPLT1(SectionData& pParent);
+};
+
+//===----------------------------------------------------------------------===//
+// X86PLT
+//===----------------------------------------------------------------------===//
/** \class X86PLT
* \brief X86 Procedure Linkage Table
*/
@@ -48,7 +94,7 @@
void reserveEntry(size_t pNum = 1) ;
- PLT::Entry* consume();
+ PLTEntryBase* consume();
void applyPLT0();
@@ -58,7 +104,7 @@
unsigned int getPLT1Size() const { return m_PLT1Size; }
private:
- X86PLT0* getPLT0() const;
+ PLTEntryBase* getPLT0() const;
private:
X86GOTPLT& m_GOTPLT;
@@ -77,3 +123,4 @@
} // namespace of mcld
#endif
+
diff --git a/lib/Target/X86/X86RelocationFunctions.h b/lib/Target/X86/X86RelocationFunctions.h
index 9b82739..df2e70c 100644
--- a/lib/Target/X86/X86RelocationFunctions.h
+++ b/lib/Target/X86/X86RelocationFunctions.h
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#define DECL_X86_APPLY_RELOC_FUNC(Name) \
-static X86RelocationFactory::Result Name (Relocation& pEntry, \
- X86RelocationFactory& pParent);
+static X86Relocator::Result Name (Relocation& pEntry, \
+ X86Relocator& pParent);
#define DECL_X86_APPLY_RELOC_FUNCS \
DECL_X86_APPLY_RELOC_FUNC(none) \
diff --git a/lib/Target/X86/X86RelocationFactory.cpp b/lib/Target/X86/X86Relocator.cpp
similarity index 67%
rename from lib/Target/X86/X86RelocationFactory.cpp
rename to lib/Target/X86/X86Relocator.cpp
index d7cfe09..3b4d389 100644
--- a/lib/Target/X86/X86RelocationFactory.cpp
+++ b/lib/Target/X86/X86Relocator.cpp
@@ -1,4 +1,4 @@
-//===- X86RelocationFactory.cpp -------------------------------------------===//
+//===- X86Relocator.cpp -------------------------------------------===//
//
// The MCLinker Project
//
@@ -11,10 +11,9 @@
#include <llvm/Support/DataTypes.h>
#include <llvm/Support/ELF.h>
#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/LinkerConfig.h>
#include <mcld/Support/MsgHandling.h>
-#include "X86RelocationFactory.h"
+#include "X86Relocator.h"
#include "X86RelocationFunctions.h"
using namespace mcld;
@@ -25,9 +24,8 @@
DECL_X86_APPLY_RELOC_FUNCS
/// the prototype of applying function
-typedef RelocationFactory::Result
- (*ApplyFunctionType)(Relocation& pReloc,
- X86RelocationFactory& pParent);
+typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
+ X86Relocator& pParent);
// the table entry of applying functions
struct ApplyFunctionTriple
@@ -43,20 +41,19 @@
};
//===--------------------------------------------------------------------===//
-// X86RelocationFactory
+// X86Relocator
//===--------------------------------------------------------------------===//
-X86RelocationFactory::X86RelocationFactory(size_t pNum,
- X86GNULDBackend& pParent)
- : RelocationFactory(pNum),
+X86Relocator::X86Relocator(X86GNULDBackend& pParent)
+ : Relocator(),
m_Target(pParent) {
}
-X86RelocationFactory::~X86RelocationFactory()
+X86Relocator::~X86Relocator()
{
}
-RelocationFactory::Result
-X86RelocationFactory::applyRelocation(Relocation& pRelocation)
+Relocator::Result
+X86Relocator::applyRelocation(Relocation& pRelocation)
{
Relocation::Type type = pRelocation.type();
@@ -68,7 +65,7 @@
return ApplyFunctions[type].func(pRelocation, *this);
}
-const char* X86RelocationFactory::getName(Relocation::Type pType) const
+const char* X86Relocator::getName(Relocation::Type pType) const
{
return ApplyFunctions[pType].name;
}
@@ -82,8 +79,8 @@
Relocation& helper_DynRel(ResolveInfo* pSym,
Fragment& pFrag,
uint64_t pOffset,
- X86RelocationFactory::Type pType,
- X86RelocationFactory& pParent)
+ X86Relocator::Type pType,
+ X86Relocator& pParent)
{
X86GNULDBackend& ld_backend = pParent.getTarget();
Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
@@ -102,7 +99,7 @@
/// R_386_RELATIVE
static bool
helper_use_relative_reloc(const ResolveInfo& pSym,
- const X86RelocationFactory& pFactory)
+ const X86Relocator& pFactory)
{
// if symbol is dynamic or undefine or preemptible
@@ -114,14 +111,14 @@
}
static
-GOT::Entry& helper_get_GOT_and_init(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
+ X86Relocator& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
X86GNULDBackend& ld_backend = pParent.getTarget();
- GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ X86GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
if (NULL != got_entry)
return *got_entry;
@@ -132,17 +129,17 @@
// If we first get this GOT entry, we should initialize it.
if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
// No corresponding dynamic relocation, initialize to the symbol value.
- got_entry->setContent(pReloc.symValue());
+ got_entry->setValue(pReloc.symValue());
}
else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
// Initialize got_entry content and the corresponding dynamic relocation.
if (helper_use_relative_reloc(*rsym, pParent)) {
helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent);
- got_entry->setContent(pReloc.symValue());
+ got_entry->setValue(pReloc.symValue());
}
else {
helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent);
- got_entry->setContent(0);
+ got_entry->setValue(0);
}
}
else {
@@ -153,31 +150,29 @@
static
-X86RelocationFactory::Address helper_GOT_ORG(X86RelocationFactory& pParent)
+X86Relocator::Address helper_GOT_ORG(X86Relocator& pParent)
{
return pParent.getTarget().getGOTPLT().addr();
}
static
-X86RelocationFactory::Address helper_GOT(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Address helper_GOT(Relocation& pReloc, X86Relocator& pParent)
{
- GOT::Entry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
- X86RelocationFactory::Address got_addr = pParent.getTarget().getGOT().addr();
+ X86GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
+ X86Relocator::Address got_addr = pParent.getTarget().getGOT().addr();
return got_addr + got_entry.getOffset();
}
static
-PLT::Entry& helper_get_PLT_and_init(Relocation& pReloc,
- X86RelocationFactory& pParent)
+PLTEntryBase& helper_get_PLT_and_init(Relocation& pReloc, X86Relocator& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
X86GNULDBackend& ld_backend = pParent.getTarget();
- PLT::Entry* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
+ PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
if (NULL != plt_entry)
return *plt_entry;
@@ -186,7 +181,7 @@
pParent.getSymPLTMap().record(*rsym, *plt_entry);
// If we first get this PLT entry, we should initialize it.
if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
- GOT::Entry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
+ X86GOTPLTEntry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
gotplt_entry = ld_backend.getGOTPLT().consume();
pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
@@ -205,17 +200,16 @@
static
-X86RelocationFactory::Address helper_PLT_ORG(X86RelocationFactory& pParent)
+X86Relocator::Address helper_PLT_ORG(X86Relocator& pParent)
{
return pParent.getTarget().getPLT().addr();
}
static
-X86RelocationFactory::Address helper_PLT(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Address helper_PLT(Relocation& pReloc, X86Relocator& pParent)
{
- PLT::Entry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
+ PLTEntryBase& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
return helper_PLT_ORG(pParent) + plt_entry.getOffset();
}
@@ -225,21 +219,19 @@
//=========================================//
// R_386_NONE
-X86RelocationFactory::Result none(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result none(Relocation& pReloc, X86Relocator& pParent)
{
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_32: S + A
// R_386_16
// R_386_8
-X86RelocationFactory::Result abs(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result abs(Relocation& pReloc, X86Relocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- RelocationFactory::DWord S = pReloc.symValue();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ Relocator::DWord S = pReloc.symValue();
bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
pParent.getFragmentLinker(),
*rsym,
@@ -251,7 +243,7 @@
// but perform static relocation. (e.g., applying .debug section)
if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
pReloc.target() = S + A;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// A local symbol may need REL Type dynamic relocation
@@ -267,7 +259,7 @@
pReloc.targetRef().offset(), pReloc.type(), pParent);
}
pReloc.target() = S + A;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// An external symbol may need PLT and dynamic relocation
@@ -287,33 +279,32 @@
else {
helper_DynRel(rsym, *pReloc.targetRef().frag(),
pReloc.targetRef().offset(), pReloc.type(), pParent);
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
}
}
// perform static relocation
pReloc.target() = S + A;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_PC32: S + A - P
// R_386_PC16
// R_386_PC8
-X86RelocationFactory::Result rel(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result rel(Relocation& pReloc, X86Relocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- RelocationFactory::DWord S = pReloc.symValue();
- RelocationFactory::DWord P = pReloc.place();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ Relocator::DWord S = pReloc.symValue();
+ Relocator::DWord P = pReloc.place();
LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
pReloc.target() = S + A - P;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// An external symbol may need PLT and dynamic relocation
@@ -334,80 +325,75 @@
else {
helper_DynRel(rsym, *pReloc.targetRef().frag(),
pReloc.targetRef().offset(), pReloc.type(), pParent);
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
}
}
// perform static relocation
pReloc.target() = S + A - P;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_GOTOFF: S + A - GOT_ORG
-X86RelocationFactory::Result gotoff32(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result gotoff32(Relocation& pReloc, X86Relocator& pParent)
{
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
- X86RelocationFactory::Address S = pReloc.symValue();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
+ X86Relocator::Address S = pReloc.symValue();
pReloc.target() = S + A - GOT_ORG;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_GOTPC: GOT_ORG + A - P
-X86RelocationFactory::Result gotpc32(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result gotpc32(Relocation& pReloc, X86Relocator& pParent)
{
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
// Apply relocation.
pReloc.target() = GOT_ORG + A - pReloc.place();
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_GOT32: GOT(S) + A - GOT_ORG
-X86RelocationFactory::Result got32(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result got32(Relocation& pReloc, X86Relocator& pParent)
{
if (!(pReloc.symInfo()->reserved()
& (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
- return X86RelocationFactory::BadReloc;
+ return X86Relocator::BadReloc;
}
- X86RelocationFactory::Address GOT_S = helper_GOT(pReloc, pParent);
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
+ X86Relocator::Address GOT_S = helper_GOT(pReloc, pParent);
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ X86Relocator::Address GOT_ORG = helper_GOT_ORG(pParent);
// Apply relocation.
pReloc.target() = GOT_S + A - GOT_ORG;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_PLT32: PLT(S) + A - P
-X86RelocationFactory::Result plt32(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result plt32(Relocation& pReloc, X86Relocator& pParent)
{
// PLT_S depends on if there is a PLT entry.
- X86RelocationFactory::Address PLT_S;
+ X86Relocator::Address PLT_S;
if ((pReloc.symInfo()->reserved() & X86GNULDBackend::ReservePLT))
PLT_S = helper_PLT(pReloc, pParent);
else
PLT_S = pReloc.symValue();
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- X86RelocationFactory::Address P = pReloc.place();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ X86Relocator::Address P = pReloc.place();
pReloc.target() = PLT_S + A - P;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_TLS_GD:
-X86RelocationFactory::Result tls_gd(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result tls_gd(Relocation& pReloc, X86Relocator& pParent)
{
// global-dynamic
ResolveInfo* rsym = pReloc.symInfo();
// must reserve two pairs of got and dynamic relocation
if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
- return X86RelocationFactory::BadReloc;
+ return X86Relocator::BadReloc;
}
X86GNULDBackend& ld_backend = pParent.getTarget();
@@ -416,21 +402,21 @@
// get first got entry, if there is already a got entry for rsym, then apply
// this relocation to the got entry directly. If not, setup the corresponding
// got and dyn relocation entries
- GOT::Entry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
+ X86GOTEntry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
if (NULL == got_entry1) {
// get and init two got entries if not exist
got_entry1 = ld_backend.getGOT().consume();
pParent.getSymGOTMap().record(*rsym, *got_entry1);
- GOT::Entry* got_entry2 = ld_backend.getGOT().consume();
- got_entry1->setContent(0x0);
- got_entry2->setContent(0x0);
+ X86GOTEntry* got_entry2 = ld_backend.getGOT().consume();
+ got_entry1->setValue(0x0);
+ got_entry2->setValue(0x0);
// setup dyn rel for get_entry1
Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0,
llvm::ELF::R_386_TLS_DTPMOD32, pParent);
if (rsym->isLocal()) {
// for local symbol, set got_entry2 to symbol value
- got_entry2->setContent(pReloc.symValue());
+ got_entry2->setValue(pReloc.symValue());
// for local tls symbol, add rel entry against the section symbol this
// symbol belong to (.tdata or .tbss)
@@ -452,52 +438,49 @@
}
// perform relocation to the first got entry
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
// GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the
// .got.plt section)
- X86RelocationFactory::Address GOT_OFF =
+ X86Relocator::Address GOT_OFF =
file_format->getGOT().addr() +
got_entry1->getOffset() -
file_format->getGOTPLT().addr();
pReloc.target() = GOT_OFF + A;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_TLS_LDM
-X86RelocationFactory::Result tls_ldm(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result tls_ldm(Relocation& pReloc, X86Relocator& pParent)
{
// FIXME: no linker optimization for TLS relocation
- const GOT::Entry& got_entry = pParent.getTarget().getTLSModuleID();
+ const X86GOTEntry& got_entry = pParent.getTarget().getTLSModuleID();
// All GOT offsets are relative to the end of the GOT.
- X86RelocationFactory::SWord GOT_S = got_entry.getOffset() -
+ X86Relocator::SWord GOT_S = got_entry.getOffset() -
(pParent.getTarget().getGOTPLT().addr() -
pParent.getTarget().getGOT().addr());
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
pReloc.target() = GOT_S + A;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_TLS_LDO_32
-X86RelocationFactory::Result tls_ldo_32(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result tls_ldo_32(Relocation& pReloc, X86Relocator& pParent)
{
// FIXME: no linker optimization for TLS relocation
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- X86RelocationFactory::Address S = pReloc.symValue();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ X86Relocator::Address S = pReloc.symValue();
pReloc.target() = S + A;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_X86_TLS_IE
-X86RelocationFactory::Result tls_ie(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result tls_ie(Relocation& pReloc, X86Relocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
- return X86RelocationFactory::BadReloc;
+ return X86Relocator::BadReloc;
}
if (rsym->reserved() & X86GNULDBackend::ReserveRel) {
@@ -507,13 +490,13 @@
}
// set up the got and dynamic relocation entries if not exist
- GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ X86GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
if (NULL == got_entry) {
// set got entry
X86GNULDBackend& ld_backend = pParent.getTarget();
got_entry = ld_backend.getGOT().consume();
pParent.getSymGOTMap().record(*rsym, *got_entry);
- got_entry->setContent(0x0);
+ got_entry->setValue(0x0);
// set relocation entry
Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
@@ -522,32 +505,31 @@
}
// perform relocation to the absolute address of got_entry
- X86RelocationFactory::Address GOT_S =
+ X86Relocator::Address GOT_S =
pParent.getTarget().getGOT().addr() + got_entry->getOffset();
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
pReloc.target() = GOT_S + A;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_386_TLS_GOTIE
-X86RelocationFactory::Result tls_gotie(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result tls_gotie(Relocation& pReloc, X86Relocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
- return X86RelocationFactory::BadReloc;
+ return X86Relocator::BadReloc;
}
// set up the got and dynamic relocation entries if not exist
- GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ X86GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
if (NULL == got_entry) {
// set got entry
X86GNULDBackend& ld_backend = pParent.getTarget();
got_entry = ld_backend.getGOT().consume();
pParent.getSymGOTMap().record(*rsym, *got_entry);
- got_entry->setContent(0x0);
+ got_entry->setValue(0x0);
// set relocation entry
Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
@@ -556,17 +538,16 @@
}
// All GOT offsets are relative to the end of the GOT.
- X86RelocationFactory::SWord GOT_S = got_entry->getOffset() -
+ X86Relocator::SWord GOT_S = got_entry->getOffset() -
(pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr());
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
pReloc.target() = GOT_S + A;
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// R_X86_TLS_LE
-X86RelocationFactory::Result tls_le(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result tls_le(Relocation& pReloc, X86Relocator& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
if (pReloc.symInfo()->reserved() & X86GNULDBackend::ReserveRel) {
@@ -575,22 +556,21 @@
pReloc.targetRef().offset(),
llvm::ELF::R_386_TLS_TPOFF,
pParent);
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
// perform static relocation
// get TLS segment
ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find(
llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- X86RelocationFactory::Address S = pReloc.symValue();
+ Relocator::DWord A = pReloc.target() + pReloc.addend();
+ X86Relocator::Address S = pReloc.symValue();
pReloc.target() = S + A - tls_seg->memsz();
- return X86RelocationFactory::OK;
+ return X86Relocator::OK;
}
-X86RelocationFactory::Result unsupport(Relocation& pReloc,
- X86RelocationFactory& pParent)
+X86Relocator::Result unsupport(Relocation& pReloc, X86Relocator& pParent)
{
- return X86RelocationFactory::Unsupport;
+ return X86Relocator::Unsupport;
}
diff --git a/lib/Target/X86/X86RelocationFactory.h b/lib/Target/X86/X86Relocator.h
similarity index 64%
rename from lib/Target/X86/X86RelocationFactory.h
rename to lib/Target/X86/X86Relocator.h
index 92119f1..7d3c289 100644
--- a/lib/Target/X86/X86RelocationFactory.h
+++ b/lib/Target/X86/X86Relocator.h
@@ -1,4 +1,4 @@
-//===- X86RelocationFactory.h --------------------------------------------===//
+//===- X86Relocator.h --------------------------------------------===//
//
// The MCLinker Project
//
@@ -12,7 +12,7 @@
#include <gtest.h>
#endif
-#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/Relocator.h>
#include <mcld/Target/GOT.h>
#include <mcld/Target/PLT.h>
#include <mcld/Target/SymbolEntryMap.h>
@@ -22,19 +22,20 @@
class ResolveInfo;
-/** \class X86RelocationFactory
- * \brief X86RelocationFactory creates and destroys the X86 relocations.
+/** \class X86Relocator
+ * \brief X86Relocator creates and destroys the X86 relocations.
*
*/
-class X86RelocationFactory : public RelocationFactory
+class X86Relocator : public Relocator
{
public:
- typedef SymbolEntryMap<PLT::Entry> SymPLTMap;
- typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
+ typedef SymbolEntryMap<PLTEntryBase> SymPLTMap;
+ typedef SymbolEntryMap<X86GOTEntry> SymGOTMap;
+ typedef SymbolEntryMap<X86GOTPLTEntry> SymGOTPLTMap;
public:
- X86RelocationFactory(size_t pNum, X86GNULDBackend& pParent);
- ~X86RelocationFactory();
+ X86Relocator(X86GNULDBackend& pParent);
+ ~X86Relocator();
Result applyRelocation(Relocation& pRelocation);
@@ -52,14 +53,14 @@
const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
SymGOTMap& getSymGOTMap() { return m_SymGOTMap; }
- const SymGOTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
- SymGOTMap& getSymGOTPLTMap() { return m_SymGOTPLTMap; }
+ const SymGOTPLTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
+ SymGOTPLTMap& getSymGOTPLTMap() { return m_SymGOTPLTMap; }
private:
X86GNULDBackend& m_Target;
SymPLTMap m_SymPLTMap;
SymGOTMap m_SymGOTMap;
- SymGOTMap m_SymGOTPLTMap;
+ SymGOTPLTMap m_SymGOTPLTMap;
};
} // namespace of mcld
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index 28a18c6..e7a48d0 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -283,7 +283,7 @@
cl::value_desc("directory"),
cl::ValueRequired);
-static cl::list<std::string>
+static cl::list<std::string, bool, llvm::cl::SearchDirParser>
ArgSearchDirList("L",
cl::ZeroOrMore,
cl::desc("Add path searchdir to the list of paths that ld will search for archive libraries and ld control scripts."),
@@ -597,6 +597,26 @@
cl::desc("alias for -u"),
cl::aliasopt(ArgForceUndefined));
+static cl::opt<std::string>
+ArgVersionScript("version-script",
+ cl::desc("Version script."),
+ cl::value_desc("Version script"));
+
+static cl::opt<bool>
+ArgNoStdLib("nostdlib",
+ cl::desc("Only search lib dirs explicitly specified on cmdline"),
+ cl::init(false));
+
+static cl::opt<bool>
+ArgWarnCommon("warn-common",
+ cl::desc("warn common symbol"),
+ cl::init(false));
+
+static cl::opt<bool>
+ArgFatalWarnings("fatal-warnings",
+ cl::desc("turn all warnings into errors"),
+ cl::init(false));
+
/// @{
/// @name FIXME: end of unsupported options
/// @}
@@ -606,6 +626,54 @@
cl::desc("Warn if adding DT_TEXTREL in a shared object."),
cl::init(false));
+namespace format {
+enum Format {
+ Binary,
+ Unknown // decided by triple
+};
+} // namespace of format
+
+static cl::opt<format::Format>
+ArgFormat("b",
+ cl::value_desc("Format"),
+ cl::desc("set input format"),
+ cl::init(format::Unknown),
+ cl::values(
+ clEnumValN(format::Binary, "binary",
+ "read in binary machine code."),
+ clEnumValEnd));
+
+static cl::alias
+ArgFormatAlias("format",
+ cl::desc("alias for -b"),
+ cl::aliasopt(ArgFormat));
+
+static cl::opt<format::Format>
+ArgOFormat("oformat",
+ cl::value_desc("Format"),
+ cl::desc("set output format"),
+ cl::init(format::Unknown),
+ cl::values(
+ clEnumValN(format::Binary, "binary",
+ "generate binary machine code."),
+ clEnumValEnd));
+
+static cl::opt<bool>
+ArgDefineCommon("d",
+ cl::ZeroOrMore,
+ cl::desc("Define common symbol"),
+ cl::init(false));
+
+static cl::alias
+ArgDefineCommonAlias1("dc",
+ cl::desc("alias for -d"),
+ cl::aliasopt(ArgDefineCommon));
+
+static cl::alias
+ArgDefineCommonAlias2("dp",
+ cl::desc("alias for -d"),
+ cl::aliasopt(ArgDefineCommon));
+
//===----------------------------------------------------------------------===//
// Scripting Options
//===----------------------------------------------------------------------===//
@@ -743,6 +811,7 @@
break;
case mcld::CGFT_DSOFile:
case mcld::CGFT_EXEFile:
+ case mcld::CGFT_BINARY:
case mcld::CGFT_NULLFile:
permission = 0755;
break;
@@ -759,6 +828,44 @@
return result_output;
}
+/// ParseProgName - Parse program name
+/// This function simplifies cross-compiling by reading triple from the program
+/// name. For example, if the program name is `arm-linux-eabi-ld.mcld', we can
+/// get the triple is arm-linux-eabi by the program name.
+static void ParseProgName(const char *progname)
+{
+ static const char *suffixes[] = {
+ "ld",
+ "ld.mcld",
+ };
+
+ std::string ProgName(mcld::sys::fs::Path(progname).stem().native());
+
+ for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
+ if (ProgName == suffixes[i])
+ return;
+ }
+
+ StringRef ProgNameRef(ProgName);
+ StringRef Prefix;
+
+ for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
+ if (!ProgNameRef.endswith(suffixes[i]))
+ continue;
+
+ StringRef::size_type LastComponent = ProgNameRef.rfind('-',
+ ProgNameRef.size() - strlen(suffixes[i]));
+ if (LastComponent == StringRef::npos)
+ continue;
+ StringRef Prefix = ProgNameRef.slice(0, LastComponent);
+ std::string IgnoredError;
+ if (!llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError))
+ continue;
+ TargetTriple = Prefix.str();
+ return;
+ }
+}
+
static bool ShouldColorize()
{
const char* term = getenv("TERM");
@@ -788,6 +895,9 @@
// set up soname
pConfig.options().setSOName(ArgSOName);
+ // --fatal-warnings
+ pConfig.options().setFatalWarnings(ArgFatalWarnings);
+
// -shared or -pie
if (true == ArgShared || true == ArgPIE) {
ArgFileType = mcld::CGFT_DSOFile;
@@ -795,6 +905,13 @@
else if (true == ArgRelocatable) {
ArgFileType = mcld::CGFT_PARTIAL;
}
+ else if (format::Binary == ArgOFormat) {
+ ArgFileType = mcld::CGFT_BINARY;
+ }
+
+ // -b [input-format], --format=[input-format]
+ if (format::Binary == ArgFormat)
+ pConfig.options().setBinaryInput();
// -V
if (ArgVersion) {
@@ -838,6 +955,7 @@
pConfig.options().setStripDebug(ArgStripDebug);
pConfig.options().setExportDynamic(ArgExportDynamic);
pConfig.options().setWarnSharedTextrel(ArgWarnSharedTextrel);
+ pConfig.options().setDefineCommon(ArgDefineCommon);
// set up rename map, for --wrap
cl::list<std::string>::iterator wname;
@@ -968,13 +1086,6 @@
{
LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
-
-#ifdef ENABLE_UNITTEST
- if (UnitTest) {
- return unit_test( argc, argv );
- }
-#endif
// Initialize targets first, so that --version shows registered targets.
InitializeAllTargets();
@@ -986,6 +1097,15 @@
mcld::InitializeAllEmulations();
mcld::InitializeAllDiagnostics();
+ ParseProgName(argv[0]);
+ cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
+
+#ifdef ENABLE_UNITTEST
+ if (UnitTest) {
+ return unit_test( argc, argv );
+ }
+#endif
+
// Load the module to be compiled...
std::auto_ptr<llvm::Module> M;
@@ -1003,7 +1123,8 @@
if (ArgBitcodeFilename.empty() &&
(mcld::CGFT_DSOFile != ArgFileType &&
mcld::CGFT_EXEFile != ArgFileType &&
- mcld::CGFT_PARTIAL != ArgFileType)) {
+ mcld::CGFT_PARTIAL != ArgFileType &&
+ mcld::CGFT_BINARY != ArgFileType)) {
// If the file is not given, forcefully read from stdin
if (ArgVerbose >= 0) {
errs() << "** The bitcode/llvm asm file is not given. Read from stdin.\n"
@@ -1087,7 +1208,7 @@
}
}
// Set up mcld::LinkerConfig
- LDConfig.setTriple(TheTriple);
+ LDConfig.targets().setTriple(TheTriple);
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
@@ -1199,6 +1320,9 @@
PM.run(mod);
}
+ if (mcld::getDiagnosticEngine().getPrinter()->getNumErrors())
+ return 1;
+
// Declare success.
Out->keep();
return 0;
diff --git a/tools/mcld/include/alone/Linker.h b/tools/mcld/include/alone/Linker.h
index b0bdc5e..987b36a 100644
--- a/tools/mcld/include/alone/Linker.h
+++ b/tools/mcld/include/alone/Linker.h
@@ -15,16 +15,11 @@
namespace mcld {
class Module;
-class TargetLDBackend;
-class ObjectLinker;
-class ContextFactory;
+class IRBuilder;
class LinkerConfig;
-class TreeIteratorBase;
+class Linker;
class Input;
-class InputFactory;
-class InputBuilder;
class MemoryArea;
-class MemoryAreaFactory;
namespace sys { namespace fs {
@@ -43,11 +38,10 @@
enum ErrorCode {
kSuccess,
kDoubleConfig,
- kCreateBackend,
kDelegateLDInfo,
kFindNameSpec,
- kOpenNameSpec,
kOpenObjectFile,
+ kOpenMemory,
kNotConfig,
kNotSetUpOutput,
kOpenOutput,
@@ -62,15 +56,11 @@
private:
const mcld::LinkerConfig *mLDConfig;
mcld::Module *mModule;
- mcld::TargetLDBackend *mBackend;
- mcld::ObjectLinker *mObjLinker;
- mcld::InputFactory *mInputFactory;
- mcld::MemoryAreaFactory *mMemAreaFactory;
- mcld::ContextFactory *mContextFactory;
- mcld::InputBuilder *mBuilder;
- mcld::TreeIteratorBase *mRoot;
+ mcld::Linker *mLinker;
+ mcld::IRBuilder *mBuilder;
std::string mSOName;
- mcld::MemoryArea* mOutput;
+ std::string mOutputPath;
+ int mOutputHandler;
public:
Linker();
@@ -97,12 +87,6 @@
private:
enum ErrorCode extractFiles(const LinkerConfig& pConfig);
-
- enum ErrorCode openFile(const mcld::sys::fs::Path& pPath,
- enum ErrorCode pCode,
- mcld::Input& pInput);
-
- void advanceRoot();
};
} // end namespace alone
diff --git a/tools/mcld/include/alone/Support/LinkerConfig.h b/tools/mcld/include/alone/Support/LinkerConfig.h
index 0aa3277..6eecdd5 100644
--- a/tools/mcld/include/alone/Support/LinkerConfig.h
+++ b/tools/mcld/include/alone/Support/LinkerConfig.h
@@ -86,6 +86,8 @@
void setBsymbolic(bool pEnable = true);
+ void setDefineCommon(bool pEnable = true);
+
void setSOName(const std::string &pSOName);
void setDyld(const std::string &pDyld);
diff --git a/tools/mcld/include/alone/Support/Log.h b/tools/mcld/include/alone/Support/Log.h
index bc91d44..e3c80d1 100644
--- a/tools/mcld/include/alone/Support/Log.h
+++ b/tools/mcld/include/alone/Support/Log.h
@@ -13,6 +13,6 @@
#include <cstdio>
#define ALOGE(fmt, args...) \
-printf("%s:%s:%d: "fmt, __FILE__, __FUNCTION__, __LINE__, args)
+printf("%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, args)
#endif // ALONE_SUPPORT_LOG_H
diff --git a/tools/mcld/lib/Core/Linker.cpp b/tools/mcld/lib/Core/Linker.cpp
index d3f1450..83de5a8 100644
--- a/tools/mcld/lib/Core/Linker.cpp
+++ b/tools/mcld/lib/Core/Linker.cpp
@@ -15,20 +15,11 @@
#include <mcld/Module.h>
#include <mcld/IRBuilder.h>
-#include <mcld/InputTree.h>
-#include <mcld/Object/ObjectLinker.h>
-#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/MC/InputFactory.h>
-#include <mcld/MC/ContextFactory.h>
-#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Linker.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDContext.h>
-#include <mcld/Target/TargetLDBackend.h>
#include <mcld/Support/Path.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Support/TargetRegistry.h>
using namespace alone;
@@ -38,14 +29,10 @@
"Successfully compiled.",
/* kDoubleConfig */
"Configure Linker twice.",
- /* kCreateBackend */
- "Cannot create backend.",
/* kDelegateLDInfo */
"Cannot get linker information",
/* kFindNameSpec */
"Cannot find -lnamespec",
- /* kOpenNameSpec */
- "Cannot open -lnamespec",
/* kOpenObjectFile */
"Cannot open object file",
/* kNotConfig */
@@ -75,15 +62,13 @@
// Linker
//===----------------------------------------------------------------------===//
Linker::Linker()
- : mLDConfig(NULL), mModule(NULL), mBackend(NULL), mObjLinker(NULL),
- mInputFactory(NULL), mMemAreaFactory(NULL), mContextFactory(NULL),
- mBuilder(NULL), mRoot(NULL), mOutput(NULL) {
+ : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
+ mOutputHandler(-1) {
}
Linker::Linker(const LinkerConfig& pConfig)
- : mLDConfig(NULL), mModule(NULL), mBackend(NULL), mObjLinker(NULL),
- mInputFactory(NULL), mMemAreaFactory(NULL), mContextFactory(NULL),
- mBuilder(NULL), mRoot(NULL), mOutput(NULL) {
+ : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
+ mOutputHandler(-1) {
const std::string &triple = pConfig.getTriple();
@@ -98,14 +83,8 @@
Linker::~Linker() {
delete mModule;
- delete mObjLinker;
- // FIXME: current implementation can not change the order of deleting
- // ObjectLinker and TargetLDBackend. Because the deletion of relocation list
- // in FragmentLinker (FragmentLinker is deleted by ObjectLinker) depends on
- // RelocationFactory in TargetLDBackend
- delete mBackend;
+ delete mLinker;
delete mBuilder;
- delete mRoot;
}
enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
@@ -123,229 +102,73 @@
extractFiles(pConfig);
- mBackend = pConfig.getTarget()->createLDBackend(*mLDConfig);
- if (mBackend == NULL) {
- return kCreateBackend;
- }
-
- mInputFactory = new mcld::InputFactory(32, *mLDConfig);
-
- mContextFactory = new mcld::ContextFactory(32);
- /* 32 is a magic number, the estimated number of input files **/
-
- mMemAreaFactory = new mcld::MemoryAreaFactory(32);
-
- mBuilder = new mcld::InputBuilder(*mLDConfig,
- *mInputFactory,
- *mContextFactory,
- *mMemAreaFactory,
- true); // delegated
-
mModule = new mcld::Module(mLDConfig->options().soname());
- mRoot = new mcld::InputTree::iterator(mModule->getInputTree().root());
+ mBuilder = new mcld::IRBuilder(*mModule, *mLDConfig);
- mObjLinker = new mcld::ObjectLinker(*mLDConfig, *mModule, *mBuilder, *mBackend);
+ mLinker = new mcld::Linker();
- mObjLinker->initFragmentLinker();
+ mLinker->config(const_cast<mcld::LinkerConfig&>(*mLDConfig));
return kSuccess;
}
-void Linker::advanceRoot() {
- if (mRoot->isRoot()) {
- mRoot->move<mcld::TreeIteratorBase::Leftward>();
- } else {
- mRoot->move<mcld::TreeIteratorBase::Rightward>();
- }
- return;
-}
-
-enum Linker::ErrorCode Linker::openFile(const mcld::sys::fs::Path& pPath,
- enum Linker::ErrorCode pCode,
- mcld::Input& pInput) {
- mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pPath,
- mcld::FileHandle::ReadOnly);
-
- if (input_memory->handler()->isGood()) {
- pInput.setMemArea(input_memory);
- } else {
- return pCode;
- }
-
- mBuilder->setContext(pInput);
- return kSuccess;
-}
-
enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
- const mcld::sys::fs::Path* path = NULL;
- // find out the real path of the namespec.
- if (mLDConfig->attribute().constraint().isSharedSystem()) {
- // In the system with shared object support, we can find both archive
- // and shared object.
-
- if (mInputFactory->attr().isStatic()) {
- // with --static, we must search an archive.
- path = mLDConfig->options().directories().find(pNameSpec,
- mcld::Input::Archive);
- }
- else {
- // otherwise, with --Bdynamic, we can find either an archive or a
- // shared object.
- path = mLDConfig->options().directories().find(pNameSpec,
- mcld::Input::DynObj);
- }
- }
- else {
- // In the system without shared object support, we only look for an
- // archive.
- path = mLDConfig->options().directories().find(pNameSpec,
- mcld::Input::Archive);
- }
-
- if (NULL == path)
+ mcld::Input* input = mBuilder->ReadInput(pNameSpec);
+ if (NULL == input)
return kFindNameSpec;
-
- mcld::Input* input = mInputFactory->produce(pNameSpec, *path,
- mcld::Input::Unknown);
- mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
-
- advanceRoot();
-
- return openFile(*path, kOpenNameSpec, *input);
+ return kSuccess;
}
/// addObject - Add a object file by the filename.
enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
- mcld::Input* input = mInputFactory->produce(pObjectPath,
- pObjectPath,
- mcld::Input::Unknown);
-
- mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
-
- advanceRoot();
-
- return openFile(pObjectPath, kOpenObjectFile, *input);
+ mcld::Input* input = mBuilder->ReadInput(pObjectPath, pObjectPath);
+ if (NULL == input)
+ return kOpenObjectFile;
+ return kSuccess;
}
/// addObject - Add a piece of memory. The memory is of ELF format.
enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
-
- mcld::Input* input = mInputFactory->produce("memory object", "NAN",
- mcld::Input::Unknown);
-
- mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
-
- advanceRoot();
-
- mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
- input->setMemArea(input_memory);
-
- mcld::LDContext *input_context = mContextFactory->produce();
- input->setContext(input_context);
-
+ mcld::Input* input = mBuilder->ReadInput("NAN", pMemory, pSize);
+ if (NULL == input)
+ return kOpenMemory;
return kSuccess;
}
enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
- mcld::Input* input = mInputFactory->produce("code object", "NAN",
- mcld::Input::External);
-
- mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
-
- advanceRoot();
-
- mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
- input->setMemArea(input_memory);
-
- mcld::LDContext *input_context = mContextFactory->produce();
- input->setContext(input_context);
-
- // FIXME: So far, FragmentLinker must set up output before add input files.
- // set up LDContext
- if (mObjLinker->hasInitLinker()) {
- return kNotConfig;
- }
-
- // create NULL section
- mcld::LDSection* null = mcld::IRBuilder::CreateELFHeader(*input, "",
- llvm::ELF::SHT_NULL, 0, 0);
- null->setSize(0);
- null->setOffset(0);
- null->setInfo(0);
-
- // create .text section
- mcld::LDSection* text = mcld::IRBuilder::CreateELFHeader(*input, ".text",
- llvm::ELF::SHT_PROGBITS,
- llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
- 1);
-
- text->setSize(pSize);
- text->setOffset(0x0);
- text->setInfo(0);
-
+ mcld::Input* input = mBuilder->CreateInput("NAN", "NAN", mcld::Input::Object);
+ mcld::LDSection* sect = mBuilder->CreateELFHeader(*input, ".text",
+ llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
+ 0x1);
+ mcld::SectionData* data = mBuilder->CreateSectionData(*sect);
+ mcld::Fragment* frag = mBuilder->CreateRegion(pMemory, pSize);
+ mBuilder->AppendFragment(*frag, *data);
return kSuccess;
}
enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
- // ----- initialize output file ----- //
- mcld::FileHandle::Permission perm = 0755;
-
- mOutput = mMemAreaFactory->produce(
- pPath,
- mcld::FileHandle::ReadWrite |
- mcld::FileHandle::Truncate |
- mcld::FileHandle::Create,
- perm);
-
- if (!mOutput->handler()->isGood()) {
- return kOpenOutput;
- }
-
+ mOutputPath = pPath;
return kSuccess;
}
enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
- mOutput = mMemAreaFactory->produce(pFileHandler, mcld::FileHandle::ReadWrite);
-
- if (!mOutput->handler()->isGood()) {
- return kOpenOutput;
- }
-
+ mOutputHandler = pFileHandler;
return kSuccess;
}
enum Linker::ErrorCode Linker::link() {
- if (NULL == mOutput)
- return kNotSetUpOutput;
-
- if (!mObjLinker->hasInitLinker()) {
- return kNotConfig;
+ mLinker->link(*mModule, *mBuilder);
+ if (!mOutputPath.empty()) {
+ mLinker->emit(mOutputPath);
+ return kSuccess;
}
- mObjLinker->initStdSections();
-
- mObjLinker->normalize();
-
- if (!mObjLinker->readRelocations())
- return kReadSections;
-
- if (!mObjLinker->mergeSections())
- return kReadSections;
-
- if (!mObjLinker->addStandardSymbols() || !mObjLinker->addTargetSymbols()) {
- return kAddAdditionalSymbols;
+ if (-1 != mOutputHandler) {
+ mLinker->emit(mOutputHandler);
+ return kSuccess;
}
-
- mObjLinker->scanRelocations();
- mObjLinker->prelayout();
- mObjLinker->layout();
- mObjLinker->postlayout();
- mObjLinker->finalizeSymbolValue();
- mObjLinker->relocation();
- mObjLinker->emitOutput(*mOutput);
- mObjLinker->postProcessing(*mOutput);
-
- return kSuccess;
+ return kNotSetUpOutput;
}
diff --git a/tools/mcld/lib/Support/LinkerConfig.cpp b/tools/mcld/lib/Support/LinkerConfig.cpp
index 3a53ae1..3715bf8 100644
--- a/tools/mcld/lib/Support/LinkerConfig.cpp
+++ b/tools/mcld/lib/Support/LinkerConfig.cpp
@@ -157,6 +157,11 @@
return;
}
+void LinkerConfig::setDefineCommon(bool pEnable) {
+ mLDConfig->options().setDefineCommon(pEnable);
+ return;
+}
+
void LinkerConfig::setSOName(const std::string &pSOName) {
mLDConfig->options().setSOName(pSOName);
return;
diff --git a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
index 0382c2a..1ce0237 100644
--- a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
+++ b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
@@ -10,7 +10,9 @@
#include "alone/Config/Config.h"
#include "alone/Support/TargetLinkerConfigs.h"
+#include <mcld/TargetOptions.h>
#include <mcld/MC/InputFactory.h>
+#include <mcld/Fragment/Relocation.h>
using namespace alone;
@@ -28,6 +30,10 @@
#if defined(PROVIDE_ARM_CODEGEN)
ARMLinkerConfig::ARMLinkerConfig() : LinkerConfig(DEFAULT_ARM_TRIPLE_STRING) {
+ // set up target-dependent options
+ getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
+ getLDConfig()->targets().setBitClass(32);
+
// set up target-dependent constraints of attributes
getLDConfig()->attribute().constraint().enableWholeArchive();
getLDConfig()->attribute().constraint().disableAsNeeded();
@@ -53,6 +59,9 @@
getLDConfig()->scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
getLDConfig()->scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
}
+
+ // set up relocation factory
+ mcld::Relocation::SetUp(*getLDConfig());
}
#endif // defined(PROVIDE_ARM_CODEGEN)
@@ -63,6 +72,10 @@
MipsLinkerConfig::MipsLinkerConfig()
: LinkerConfig(DEFAULT_MIPS_TRIPLE_STRING) {
+ // set up target-dependent options
+ getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
+ getLDConfig()->targets().setBitClass(32);
+
// set up target-dependent constraints of attibutes
getLDConfig()->attribute().constraint().enableWholeArchive();
getLDConfig()->attribute().constraint().disableAsNeeded();
@@ -80,6 +93,9 @@
if (!getLDConfig()->options().hasDyld()) {
getLDConfig()->options().setDyld(gDefaultDyld);
}
+
+ // set up relocation factory
+ mcld::Relocation::SetUp(*getLDConfig());
}
#endif // defined(PROVIDE_MIPS_CODEGEN)
@@ -89,6 +105,10 @@
#if defined(PROVIDE_X86_CODEGEN)
X86FamilyLinkerConfigBase::X86FamilyLinkerConfigBase(const std::string& pTriple)
: LinkerConfig(pTriple) {
+ // set up target-dependent options
+ getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
+ getLDConfig()->targets().setBitClass(32);
+
// set up target-dependent constraints of attibutes
getLDConfig()->attribute().constraint().enableWholeArchive();
getLDConfig()->attribute().constraint().disableAsNeeded();
@@ -106,6 +126,9 @@
if (!getLDConfig()->options().hasDyld()) {
getLDConfig()->options().setDyld(gDefaultDyld);
}
+
+ // set up relocation factory
+ mcld::Relocation::SetUp(*getLDConfig());
}
X86_32LinkerConfig::X86_32LinkerConfig()
@@ -123,6 +146,11 @@
//===----------------------------------------------------------------------===//
GeneralLinkerConfig::GeneralLinkerConfig(const std::string& pTriple)
: LinkerConfig(pTriple) {
+
+ // set up target-dependent options
+ getLDConfig()->targets().setEndian(mcld::TargetOptions::Little);
+ getLDConfig()->targets().setBitClass(32);
+
// set up target-dependent constraints of attributes
getLDConfig()->attribute().constraint().enableWholeArchive();
getLDConfig()->attribute().constraint().disableAsNeeded();
@@ -133,12 +161,15 @@
getLDConfig()->attribute().predefined().setDynamic();
// set up section map
- if (llvm::Triple::arm == getLDConfig()->triple().getArch() &&
+ if (llvm::Triple::arm == getLDConfig()->targets().triple().getArch() &&
getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
bool exist = false;
getLDConfig()->scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
getLDConfig()->scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
getLDConfig()->scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
}
+
+ // set up relocation factory
+ mcld::Relocation::SetUp(*getLDConfig());
}
#endif // defined(TARGET_BUILD)
diff --git a/tools/mcld/main.cpp b/tools/mcld/main.cpp
index a66fb7c..58a9bb0 100644
--- a/tools/mcld/main.cpp
+++ b/tools/mcld/main.cpp
@@ -97,6 +97,33 @@
llvm::cl::desc("Set the name of the dynamic linker."),
llvm::cl::value_desc("Program"));
+static llvm::cl::opt<bool>
+OptRelocatable("relocatable",
+ llvm::cl::desc("Generate relocatable output"),
+ llvm::cl::init(false));
+
+static llvm::cl::alias
+OptRelocatableAlias("r",
+ llvm::cl::desc("alias for --relocatable"),
+ llvm::cl::aliasopt(OptRelocatable));
+
+static llvm::cl::opt<bool>
+OptDefineCommon("d",
+ llvm::cl::ZeroOrMore,
+ llvm::cl::desc("Define common symbol"),
+ llvm::cl::init(false));
+
+static llvm::cl::alias
+OptDefineCommonAlias1("dc",
+ llvm::cl::desc("alias for -d"),
+ llvm::cl::aliasopt(OptDefineCommon));
+
+static llvm::cl::alias
+OptDefineCommonAlias2("dp",
+ llvm::cl::desc("alias for -d"),
+ llvm::cl::aliasopt(OptDefineCommon));
+
+
//===----------------------------------------------------------------------===//
// Inputs
//===----------------------------------------------------------------------===//
@@ -135,7 +162,7 @@
static void MCLDVersionPrinter() {
llvm::raw_ostream &os = llvm::outs();
os << "mcld (The MCLinker Project, http://mclinker.googlecode.com/):\n"
- << " version: "MCLD_VERSION"\n"
+ << " version: " MCLD_VERSION "\n"
<< " Default target: " << DEFAULT_TARGET_TRIPLE_STRING << "\n";
os << "\n";
@@ -236,6 +263,9 @@
// 8. Set up -Bsymbolic.
config->setBsymbolic(OptBsymbolic);
+ // 9. Set up -d (define common symbols)
+ config->setDefineCommon(OptDefineCommon);
+
Linker::ErrorCode result = pLinker.config(*config);
if (Linker::kSuccess != result) {
llvm::errs() << "Failed to configure the linker! (detail: "
diff --git a/unittests/FragmentTest.cpp b/unittests/FragmentTest.cpp
index 9713f48..43f51b6 100644
--- a/unittests/FragmentTest.cpp
+++ b/unittests/FragmentTest.cpp
@@ -47,9 +47,8 @@
new Fragment(Fragment::Alignment, s);
new Fragment(Fragment::Region, s);
new Fragment(Fragment::Fillment, s);
- new Fragment(Fragment::Relocation, s);
new Fragment(Fragment::Target, s);
- EXPECT_TRUE(6 == s->size());
+ EXPECT_TRUE(5 == s->size());
LDSection::Destroy(test);
// SectionData::Destroy(s);
diff --git a/unittests/Linker/TestLinker.cpp b/unittests/Linker/TestLinker.cpp
deleted file mode 100644
index d1ead28..0000000
--- a/unittests/Linker/TestLinker.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-//===- TestLinker.cpp -----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "TestLinker.h"
-
-#include <llvm/Support/TargetSelect.h>
-
-#include <mcld/Environment.h>
-#include <mcld/InputTree.h>
-#include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/MC/InputBuilder.h>
-#include <mcld/MC/InputFactory.h>
-#include <mcld/MC/MCLDDirectory.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Support/Space.h>
-#include <mcld/Support/TargetSelect.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/raw_ostream.h>
-#include <mcld/Support/SystemUtils.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/MC/ContextFactory.h>
-
-using namespace mcld;
-using namespace mcld::sys::fs;
-using namespace mcld::test;
-
-//===----------------------------------------------------------------------===//
-// TestLinker
-//===----------------------------------------------------------------------===//
-TestLinker::TestLinker()
- : m_pTarget(NULL), m_pObjLinker(NULL), m_pConfig(NULL), m_pDiagLineInfo(NULL),
- m_pDiagPrinter(NULL), m_pBackend(NULL), m_pBuilder(NULL), m_pOutput(NULL) {
-}
-
-TestLinker::~TestLinker()
-{
- std::list<mcld::FileHandle*>::iterator file, fEnd = m_FileHandleList.end();
- for (file = m_FileHandleList.begin(); file != fEnd; ++file)
- delete (*file);
-
- std::list<mcld::MemoryArea*>::iterator mem, mEnd = m_MemAreaList.end() ;
- for (mem = m_MemAreaList.begin(); mem != mEnd; ++mem)
- delete (*mem);
-
- delete m_pObjLinker;
- delete m_pConfig;
- delete m_pDiagLineInfo;
- delete m_pDiagPrinter;
- delete m_pBackend;
- delete m_pBuilder;
- delete m_pOutput;
-}
-
-bool TestLinker::initialize(const std::string &pTriple)
-{
- // initilaize all llvm::Target and mcld::Target
- llvm::InitializeAllTargets();
- llvm::InitializeAllAsmPrinters();
- llvm::InitializeAllAsmParsers();
- llvm::InitializeAllTargetMCs();
- mcld::Initialize();
-
- // create mcld::LinkerConfig
- m_pConfig = new LinkerConfig(pTriple);
-
- m_Root = m_Module.getInputTree().root();
-
- // specify mcld::Target
- std::string error;
- m_pTarget = mcld::TargetRegistry::lookupTarget(pTriple, error);
- if (NULL == m_pTarget) {
- fatal(diag::fatal_cannot_init_target) << pTriple << error;
- return false;
- }
-
- // create mcld::DiagnosticLineInfo
- m_pDiagLineInfo = m_pTarget->createDiagnosticLineInfo(*m_pTarget, pTriple);
- if (NULL == m_pDiagLineInfo) {
- fatal(diag::fatal_cannot_init_lineinfo) << pTriple;
- return false;
- }
- mcld::getDiagnosticEngine().setLineInfo(*m_pDiagLineInfo);
-
- // create mcld::TargetLDBackend
- m_pBackend = m_pTarget->createLDBackend(*m_pConfig);
- if (NULL == m_pBackend) {
- fatal(diag::fatal_cannot_init_backend) << pTriple;
- return false;
- }
-
- m_pInputFactory = new mcld::InputFactory(10, *m_pConfig);
- m_pContextFactory = new mcld::ContextFactory(10);
- m_pMemAreaFactory = new mcld::MemoryAreaFactory(10);
- m_pBuilder = new mcld::InputBuilder(*m_pConfig,
- *m_pInputFactory,
- *m_pContextFactory,
- *m_pMemAreaFactory,
- true);
-
- m_pObjLinker = new mcld::ObjectLinker(*m_pConfig, m_Module, *m_pBuilder, *m_pBackend);
- m_pObjLinker->initFragmentLinker();
-
- return true;
-}
-
-void TestLinker::addSearchDir(const std::string &pDirPath)
-{
- assert(NULL != m_pConfig && "initialize() must be called before addSearchDir");
- assert(!m_pConfig->options().sysroot().empty() &&
- "must setSysRoot before addSearchDir");
-
- if (!m_pConfig->options().directories().insert(pDirPath)) {
- mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
- }
-}
-
-void TestLinker::setSysRoot(const mcld::sys::fs::Path &pPath)
-{
- assert(NULL != m_pConfig && "initialize() must be called before setSysRoot");
- m_pConfig->options().setSysroot(pPath);
-}
-
-void TestLinker::addObject(const std::string &pPath)
-{
- mcld::Input* input = m_pInputFactory->produce(pPath, pPath,
- mcld::Input::Unknown);
-
- m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
-
- advanceRoot();
-
- mcld::FileHandle* handler = new mcld::FileHandle();
- m_FileHandleList.push_back(handler);
- if (!handler->open(pPath, mcld::FileHandle::ReadOnly)) {
- mcld::error(mcld::diag::err_cannot_open_file)
- << pPath
- << mcld::sys::strerror(handler->error());
- }
-
- mcld::MemoryArea* input_memory = new MemoryArea(*handler);
- input->setMemArea(input_memory);
- m_MemAreaList.push_back(input_memory);
-
- m_pBuilder->setContext(*input);
-}
-
-void TestLinker::addObject(void* pMemBuffer, size_t pSize)
-{
- mcld::Input* input = m_pInputFactory->produce("memory object", "NAN",
- mcld::Input::Unknown);
-
- m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
-
- advanceRoot();
-
- mcld::Space* space = Space::Create(pMemBuffer, pSize);
- mcld::MemoryArea* input_memory = new MemoryArea(*space);
- input->setMemArea(input_memory);
- m_MemAreaList.push_back(input_memory);
-
- mcld::LDContext* context = m_pContextFactory->produce();
- input->setContext(context);
-}
-
-void TestLinker::addObject(int pFileHandler)
-{
- mcld::Input* input = m_pInputFactory->produce("handler object", "NAN",
- mcld::Input::Unknown);
-
- m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
-
- advanceRoot();
-
- mcld::FileHandle* handler = new mcld::FileHandle();
- m_FileHandleList.push_back(handler);
- handler->delegate(pFileHandler);
-
- mcld::MemoryArea* input_memory = new MemoryArea(*handler);
- input->setMemArea(input_memory);
- m_MemAreaList.push_back(input_memory);
-
- mcld::LDContext* context = m_pContextFactory->produce();
- input->setContext(context);
-}
-
-void TestLinker::addNameSpec(const std::string &pNameSpec)
-{
- mcld::sys::fs::Path* path = NULL;
- // find out the real path of the namespec.
- if (m_pConfig->attribute().constraint().isSharedSystem()) {
- // In the system with shared object support, we can find both archive
- // and shared object.
-
- if (m_pInputFactory->attr().isStatic()) {
- // with --static, we must search an archive.
- path = m_pConfig->options().directories().find(pNameSpec,
- mcld::Input::Archive);
- }
- else {
- // otherwise, with --Bdynamic, we can find either an archive or a
- // shared object.
- path = m_pConfig->options().directories().find(pNameSpec,
- mcld::Input::DynObj);
- }
- }
- else {
- // In the system without shared object support, we only look for an
- // archive.
- path = m_pConfig->options().directories().find(pNameSpec,
- mcld::Input::Archive);
- }
-
- if (NULL == path) {
- mcld::fatal(diag::err_cannot_find_namespec) << pNameSpec;
- return;
- }
-
- mcld::Input* input = m_pInputFactory->produce(pNameSpec, *path,
- mcld::Input::Unknown);
-
- m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
-
- advanceRoot();
-
- mcld::FileHandle* handler = new mcld::FileHandle();
- m_FileHandleList.push_back(handler);
- if (!handler->open(*path, mcld::FileHandle::ReadOnly)) {
- mcld::error(mcld::diag::err_cannot_open_file)
- << *path
- << mcld::sys::strerror(handler->error());
- }
-
- mcld::MemoryArea* input_memory = new MemoryArea(*handler);
- input->setMemArea(input_memory);
- m_MemAreaList.push_back(input_memory);
-
- m_pBuilder->setContext(*input);
-}
-
-bool TestLinker::setOutput(const std::string &pPath)
-{
- mcld::FileHandle* handler = new mcld::FileHandle();
- m_FileHandleList.push_back(handler);
- bool open_res = handler->open(pPath, mcld::FileHandle::ReadWrite |
- mcld::FileHandle::Truncate |
- mcld::FileHandle::Create,
- mcld::FileHandle::Permission(0755));
- if (!open_res) {
- mcld::error(mcld::diag::err_cannot_open_file)
- << pPath
- << mcld::sys::strerror(handler->error());
- }
-
- m_pOutput = new MemoryArea(*handler);
-
- // FIXME: remove the initStdSections().
- m_pObjLinker->initStdSections();
- return true;
-}
-
-bool TestLinker::setOutput(const sys::fs::Path &pPath)
-{
- return setOutput(pPath.native());
-}
-
-bool TestLinker::setOutput(int pFileHandler)
-{
- mcld::FileHandle* handler = new mcld::FileHandle();
- handler->delegate(pFileHandler);
- m_FileHandleList.push_back(handler);
-
- m_pOutput = new MemoryArea(*handler);
-
- // FIXME: remove the initStdSections().
- m_pObjLinker->initStdSections();
- return true;
-}
-
-void TestLinker::advanceRoot()
-{
- if (m_Root.isRoot())
- --m_Root;
- else
- ++m_Root;
-}
diff --git a/unittests/Linker/TestLinker.h b/unittests/Linker/TestLinker.h
deleted file mode 100644
index 701a405..0000000
--- a/unittests/Linker/TestLinker.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//===- TestLinker.h -------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_TEST_LINKER_H
-#define MCLD_TEST_LINKER_H
-
-#include <gtest.h>
-
-#include <string>
-#include <list>
-
-#include <mcld/Module.h>
-#include <mcld/Object/ObjectLinker.h>
-#include <mcld/Fragment/FragmentLinker.h>
-#include <mcld/LD/DiagnosticPrinter.h>
-#include <mcld/LD/DiagnosticLineInfo.h>
-#include <mcld/Support/TargetRegistry.h>
-#include <mcld/Support/Path.h>
-
-namespace mcld {
-
-class FileHandle;
-class LinkerConfig;
-class TargetLDBackend;
-class RegionFactory;
-class InputFactory;
-class MemoryAreaFactory;
-class ContextFactory;
-class InputBuilder;
-
-namespace test {
-
-class TestLinker
-{
-public:
- TestLinker();
-
- ~TestLinker();
-
- bool initialize(const std::string &pTriple);
-
- LinkerConfig* config() {
- assert(NULL != m_pConfig);
- return m_pConfig;
- }
-
- const LinkerConfig* config() const {
- assert(NULL != m_pConfig);
- return m_pConfig;
- }
-
- const Module* module() const { return &m_Module; }
- Module* module() { return &m_Module; }
-
- // ----- search directories ----- //
- void addSearchDir(const std::string &pPath);
-
- void setSysRoot(const mcld::sys::fs::Path &pPath);
-
- // ----- input operators ----- //
- void addObject(const std::string &pPath);
-
- void addObject(const mcld::sys::fs::Path &pPath)
- { addObject(pPath.native()); }
-
- void addObject(void* pMemBuffer, size_t pSize);
-
- void addObject(int pFileHandler);
-
- void addNameSpec(const std::string &pNameSpec);
-
- bool setOutput(const std::string &pPath);
-
- bool setOutput(int pFileHandler);
-
- bool setOutput(const sys::fs::Path &pPath);
-
- const MemoryArea* getOutput() const { return m_pOutput; }
-
- MemoryArea* getOutput() { return m_pOutput; }
-
- /// getObjLinker
- ObjectLinker* getObjLinker() {
- assert(NULL != m_pObjLinker);
- return m_pObjLinker;
- }
-
- /// getObjLinker
- const ObjectLinker* getObjLinker() const {
- assert(NULL != m_pObjLinker);
- return m_pObjLinker;
- }
-
- /// getLinker
- FragmentLinker* getLinker() {
- assert(NULL != m_pObjLinker);
- return m_pObjLinker->getLinker();
- }
-
- /// getLinker
- const FragmentLinker* getLinker() const {
- assert(NULL != m_pObjLinker);
- return m_pObjLinker->getLinker();
- }
-
-private:
- void advanceRoot();
-
-private:
- const mcld::Target* m_pTarget;
- mcld::ObjectLinker *m_pObjLinker;
- mcld::LinkerConfig* m_pConfig;
- mcld::Module m_Module;
- mcld::DiagnosticLineInfo* m_pDiagLineInfo;
- mcld::DiagnosticPrinter* m_pDiagPrinter;
- mcld::TargetLDBackend* m_pBackend;
- mcld::InputTree::iterator m_Root;
- mcld::InputFactory* m_pInputFactory;
- mcld::MemoryAreaFactory* m_pMemAreaFactory;
- mcld::ContextFactory* m_pContextFactory;
-
- mcld::InputBuilder* m_pBuilder;
-
- std::list<mcld::FileHandle*> m_FileHandleList;
- std::list<mcld::MemoryArea*> m_MemAreaList;
-
- mcld::MemoryArea* m_pOutput;
-};
-
-} // namespace of test
-} // namespace of mcld
-
-#endif
-
diff --git a/unittests/LinkerTest.cpp b/unittests/LinkerTest.cpp
index 64da08d..00ba23b 100644
--- a/unittests/LinkerTest.cpp
+++ b/unittests/LinkerTest.cpp
@@ -352,6 +352,7 @@
gotplt_o.append("test/PLT/gotplt.o");
Input* input = builder.CreateInput("gotplt.o", gotplt_o, Input::Object);
+ /// Sections
/// [ 0] NULL 00000000 000000 000000 00 0 0 0
builder.CreateELFHeader(*input,
"",
@@ -374,25 +375,35 @@
Fragment* text_frag = builder.CreateRegion(text_content, 0x10);
builder.AppendFragment(*text_frag, *text_data);
- // [ 3] .data PROGBITS 00000000 000044 000000 00 WA 0 0 4
- builder.CreateELFHeader(*input,
+ /// [ 2] .rel.text REL 00000000 0002ac 000008 08 7 1 4
+ LDSection* rel_text = builder.CreateELFHeader(*input,
+ ".rel.text",
+ llvm::ELF::SHT_REL,
+ 0x0, 4);
+ rel_text->setLink(text);
+ builder.CreateRelocData(*rel_text);
+
+ /// [ 3] .data PROGBITS 00000000 000044 000000 00 WA 0 0 4
+ LDSection* data = builder.CreateELFHeader(*input,
".data",
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
4);
- // [ 4] .bss NOBITS 00000000 000044 000000 00 WA 0 0 4
- builder.CreateELFHeader(*input,
+ /// [ 4] .bss NOBITS 00000000 000044 000000 00 WA 0 0 4
+ LDSection* bss = builder.CreateELFHeader(*input,
".bss",
- llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHT_NOBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
4);
- // [ 5] .ARM.attributes ARM_ATTRIBUTES 00000000 000044 000020 00 0 0 1
+ builder.CreateBSS(*bss);
+
+ /// [ 5] .ARM.attributes ARM_ATTRIBUTES 00000000 000044 000020 00 0 0 1
LDSection* attr = builder.CreateELFHeader(*input,
".ARM.attributes",
llvm::ELF::SHT_ARM_ATTRIBUTES,
0x0,
- 4);
+ 1);
SectionData* attr_data = builder.CreateSectionData(*attr);
static uint8_t attr_content[] = {
@@ -407,6 +418,48 @@
Fragment* attr_frag = builder.CreateRegion(attr_content, 0x20);
builder.AppendFragment(*attr_frag, *attr_data);
+ /// Symbols
+ /// 1: 00000000 0 FILE LOCAL DEFAULT ABS Output/gotplt.bc
+ builder.AddSymbol(*input,
+ "Output/gotplt.bc", ResolveInfo::File,
+ ResolveInfo::Define, ResolveInfo::Local, 0);
+ /// 2: 00000000 0 SECTION LOCAL DEFAULT 1
+ builder.AddSymbol(*input,
+ ".text", ResolveInfo::Section,
+ ResolveInfo::Define, ResolveInfo::Local, 0, 0x0, text);
+ /// 3: 00000000 0 SECTION LOCAL DEFAULT 3
+ builder.AddSymbol(*input,
+ ".data", ResolveInfo::Section,
+ ResolveInfo::Define, ResolveInfo::Local, 0, 0x0, data);
+ /// 4: 00000000 0 SECTION LOCAL DEFAULT 4
+ builder.AddSymbol(*input,
+ ".bss", ResolveInfo::Section,
+ ResolveInfo::Define, ResolveInfo::Local, 0, 0x0, bss);
+ /// 5: 00000000 0 SECTION LOCAL DEFAULT 5
+ builder.AddSymbol(*input,
+ ".ARM.attributes", ResolveInfo::Section,
+ ResolveInfo::Define, ResolveInfo::Local, 0, 0x0, attr);
+ /// 6: 00000000 16 FUNC GLOBAL DEFAULT 1 _Z1fv
+ builder.AddSymbol(*input,
+ "_Z1fv", ResolveInfo::Function,
+ ResolveInfo::Define, ResolveInfo::Global,
+ 16,
+ 0x0,
+ text);
+
+ /// 7: 00000000 0 NOTYPE GLOBAL DEFAULT UND _Z1gv
+ LDSymbol* z1gv = builder.AddSymbol(*input,
+ "_Z1gv",
+ ResolveInfo::NoType,
+ ResolveInfo::Undefined,
+ ResolveInfo::Global,
+ 0);
+
+ /// Relocations
+ /// Offset Info Type Sym.Value Sym. Name
+ /// 00000004 0000071b R_ARM_PLT32 00000000 _Z1gv
+ builder.AddRelocation(*rel_text, llvm::ELF::R_ARM_PLT32, *z1gv, 0x4);
+
if (linker.link(module, builder)) {
linker.emit("libgotplt.so"); ///< -o libgotplt.so
}
diff --git a/unittests/ReadStageTest.cpp b/unittests/ReadStageTest.cpp
deleted file mode 100644
index b2aaf8d..0000000
--- a/unittests/ReadStageTest.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-//===- ReadStageTest.cpp --------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "ReadStageTest.h"
-
-#include <mcld/Module.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/SectionData.h>
-#include <mcld/Fragment/Fragment.h>
-#include <mcld/Fragment/FragmentRef.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/LD/ResolveInfo.h>
-#include <mcld/MC/InputFactory.h>
-#include <mcld/Support/FileHandle.h>
-
-#include <sstream>
-#include <iostream>
-
-using namespace std;
-
-using namespace mcld;
-using namespace mcld::test;
-
-
-// Constructor can do set-up work for all test here.
-ReadStageTest::ReadStageTest()
- : m_pLinker(NULL) {
-}
-
-// Destructor can do clean-up work that doesn't throw exceptions here.
-ReadStageTest::~ReadStageTest()
-{
-}
-
-// SetUp() will be called immediately before each test.
-void ReadStageTest::SetUp()
-{
- m_pLinker = new mcld::test::TestLinker();
- m_pLinker->initialize("arm-none-linux-gnueabi");
-
- // set up target-dependent constraints of attributes
- m_pLinker->config()->attribute().constraint().enableWholeArchive();
- m_pLinker->config()->attribute().constraint().disableAsNeeded();
- m_pLinker->config()->attribute().constraint().setSharedSystem();
-
- // set up the predefined attributes
- m_pLinker->config()->attribute().predefined().setWholeArchive();
- m_pLinker->config()->attribute().predefined().setDynamic();
-
- // set up target dependent options
- mcld::sys::fs::Path path = TOPDIR;
- path.append("test/libs/ARM/Android/android-14");
- m_pLinker->setSysRoot(path);
- m_pLinker->addSearchDir("=/");
-
- m_pLinker->config()->options().setDyld("/usr/lib/ld.so.1");
- m_pLinker->config()->options().setBsymbolic(true);
-}
-
-// TearDown() will be called immediately after each test.
-void ReadStageTest::TearDown()
-{
- delete m_pLinker;
-}
-
-void ReadStageTest::dumpInput(const mcld::Input &pInput, mcld::FileHandle &pFile, size_t pIdent)
-{
- stringstream sstream;
- for (size_t i=0; i < pIdent; ++i)
- sstream << " ";
- sstream << "<input name=\"" << pInput.name() << "\">\n";
-
- LDContext::const_sect_iterator sect, sectEnd = pInput.context()->sectEnd();
- for (sect = pInput.context()->sectBegin(); sect != sectEnd; ++sect) {
- for (size_t i=0; i < (pIdent+1); ++i)
- sstream << " ";
- sstream << "<section name=\"" << (*sect)->name() << "\"/>\n";
- }
- for (size_t i=0; i < pIdent; ++i)
- sstream << " ";
- sstream << "</input>\n";
-
- size_t org_size = pFile.size();
- pFile.truncate(sstream.str().size() + org_size);
- pFile.write(sstream.str().data(), org_size, sstream.str().size());
-}
-
-void ReadStageTest::dumpOutput(const mcld::Module& pModule, mcld::FileHandle &pFile, size_t pIdent)
-{
- stringstream sstream;
- for (size_t i=0; i < pIdent; ++i)
- sstream << " ";
- sstream << "<output name=\"" << m_pLinker->module()->name() << "\">\n";
-
- Module::const_iterator sect, sectEnd = pModule.end();
- for (sect = pModule.begin(); sect != sectEnd; ++sect) {
- for (size_t i=0; i < (pIdent+1); ++i)
- sstream << " ";
- sstream << "<section name=\"" << (*sect)->name() << "\"/>\n";
- }
- for (size_t i=0; i < pIdent; ++i)
- sstream << " ";
- sstream << "</output>\n";
-
- size_t org_size = pFile.size();
- pFile.truncate(sstream.str().size() + org_size);
- pFile.write(sstream.str().data(), org_size, sstream.str().size());
-}
-//===----------------------------------------------------------------------===//
-// Testcases
-//===----------------------------------------------------------------------===//
-TEST_F(ReadStageTest, quake) {
- mcld::sys::fs::Path top_level = TOPDIR;
-
- // set up output
- m_pLinker->config()->setCodeGenType(mcld::LinkerConfig::DynObj);
- m_pLinker->setOutput(top_level + "unittests/plasma.so");
-
-
- // set up input
- m_pLinker->addObject(top_level + "test/libs/ARM/Android/android-14/crtbegin_so.o");
- m_pLinker->addObject(top_level + "test/Android/Plasma/ARM/plasma.o");
- m_pLinker->addNameSpec("m");
- m_pLinker->addNameSpec("log");
- m_pLinker->addNameSpec("jnigraphics");
- m_pLinker->addNameSpec("c");
- m_pLinker->addObject(top_level + "test/libs/ARM/Android/android-14/crtend_so.o");
-
- // dump status
- m_pLinker->getObjLinker()->normalize();
-
- FileHandle file;
- file.open(top_level + "unittests/read_stage.xml",
- FileHandle::ReadWrite | FileHandle::Create | FileHandle::Truncate, 0644);
-
- Module::input_iterator input, inEnd = m_pLinker->module()->input_end();
- for (input = m_pLinker->module()->input_begin(); input != inEnd; ++input) {
- dumpInput(**input, file, 1);
- }
-
- dumpOutput(*m_pLinker->module(), file, 1);
- // dump status
- ASSERT_TRUE(m_pLinker->getObjLinker()->mergeSections());
-}
-
diff --git a/unittests/ReadStageTest.h b/unittests/ReadStageTest.h
deleted file mode 100644
index e799664..0000000
--- a/unittests/ReadStageTest.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- ReadStageTest.h ----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_UNITTEST_READSTAGE_TEST_H
-#define MCLD_UNITTEST_READSTAGE_TEST_H
-
-#include <gtest.h>
-#include "Linker/TestLinker.h"
-
-namespace mcld {
-namespace test {
-
-class ReadStageTest : public ::testing::Test
-{
-public:
- // Constructor can do set-up work for all test here.
- ReadStageTest();
-
- // Destructor can do clean-up work that doesn't throw exceptions here.
- virtual ~ReadStageTest();
-
- // SetUp() will be called immediately before each test.
- virtual void SetUp();
-
- // TearDown() will be called immediately after each test.
- virtual void TearDown();
-
- void dumpInput(const mcld::Input &pInput, mcld::FileHandle &pFile, size_t pIdent);
-
- void dumpOutput(const mcld::Module &pModule, mcld::FileHandle &pFile, size_t pIdent);
-protected:
- TestLinker* m_pLinker;
-};
-
-} // end of namespace test
-} // end of namespace mcld
-
-#endif
-
diff --git a/unittests/SectionDataTest.cpp b/unittests/SectionDataTest.cpp
index 5113068..dfabc15 100644
--- a/unittests/SectionDataTest.cpp
+++ b/unittests/SectionDataTest.cpp
@@ -60,9 +60,8 @@
new Fragment(Fragment::Alignment, s);
new Fragment(Fragment::Region, s);
new Fragment(Fragment::Fillment, s);
- new Fragment(Fragment::Relocation, s);
new Fragment(Fragment::Target, s);
- EXPECT_TRUE(6 == s->size());
+ EXPECT_TRUE(5 == s->size());
//iterator
llvm::iplist<Fragment>::iterator iter=s->begin();
@@ -74,8 +73,6 @@
++iter;
EXPECT_TRUE(Fragment::Fillment == iter->getKind());
++iter;
- EXPECT_TRUE(Fragment::Relocation == iter->getKind());
- ++iter;
EXPECT_TRUE(Fragment::Target == iter->getKind());
++iter;
EXPECT_TRUE(iter == s->end());
diff --git a/unittests/StaticResolverTest.cpp b/unittests/StaticResolverTest.cpp
index cb4c668..bd40cd5 100644
--- a/unittests/StaticResolverTest.cpp
+++ b/unittests/StaticResolverTest.cpp
@@ -26,8 +26,6 @@
// create testee. modify it if need
m_pResolver = new StaticResolver();
- mcld::InitializeAllDiagnostics();
-
m_pConfig = new LinkerConfig("arm-none-linux-gnueabi");
}
diff --git a/unittests/TestLinkerTest.cpp b/unittests/TestLinkerTest.cpp
deleted file mode 100644
index 0b1a141..0000000
--- a/unittests/TestLinkerTest.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-//===- TestLinkerTest.cpp -------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "Linker/TestLinker.h"
-#include "TestLinkerTest.h"
-
-#include <mcld/Support/Path.h>
-#include <mcld/MC/MCLDDirectory.h>
-#include <mcld/MC/InputFactory.h>
-
-using namespace mcld;
-using namespace mcld::test;
-using namespace mcld::sys::fs;
-using namespace mcldtest;
-
-
-// Constructor can do set-up work for all test here.
-TestLinkerTest::TestLinkerTest()
- : m_pLinker(NULL) {
-}
-
-// Destructor can do clean-up work that doesn't throw exceptions here.
-TestLinkerTest::~TestLinkerTest()
-{
-}
-
-// SetUp() will be called immediately before each test.
-void TestLinkerTest::SetUp()
-{
- m_pLinker = new mcld::test::TestLinker();
- m_pLinker->initialize("arm-none-linux-gnueabi");
-
- // set up target-dependent constraints of attributes
- m_pLinker->config()->attribute().constraint().enableWholeArchive();
- m_pLinker->config()->attribute().constraint().disableAsNeeded();
- m_pLinker->config()->attribute().constraint().setSharedSystem();
-
- // set up the predefined attributes
- m_pLinker->config()->attribute().predefined().setWholeArchive();
- m_pLinker->config()->attribute().predefined().setDynamic();
-
- // set up target dependent options
- mcld::sys::fs::Path path = TOPDIR;
- path.append("test/libs/ARM/Android/android-14");
- m_pLinker->setSysRoot(path);
- m_pLinker->addSearchDir("=/");
-
- m_pLinker->config()->options().setDyld("/usr/lib/ld.so.1");
- m_pLinker->config()->options().setBsymbolic(true);
-}
-
-// TearDown() will be called immediately after each test.
-void TestLinkerTest::TearDown()
-{
- delete m_pLinker;
-}
-
-//===----------------------------------------------------------------------===//
-// Testcases
-//===----------------------------------------------------------------------===//
-TEST_F( TestLinkerTest, test) {
- m_pLinker->config()->options().setVerbose(3);
- mcld::sys::fs::Path top_level = TOPDIR;
- m_pLinker->addObject(top_level + "test/libs/ARM/Android/android-14/crtbegin_so.o");
- m_pLinker->addObject(top_level + "test/Android/Plasma/ARM/plasma.o");
- m_pLinker->addNameSpec("m");
- m_pLinker->addNameSpec("log");
- m_pLinker->addNameSpec("jnigraphics");
- m_pLinker->addNameSpec("c");
- m_pLinker->addObject(top_level + "test/libs/ARM/Android/android-14/crtend_so.o");
-}
-
diff --git a/unittests/TestLinkerTest.h b/unittests/TestLinkerTest.h
deleted file mode 100644
index ba6efcf..0000000
--- a/unittests/TestLinkerTest.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- TestLinkerTest.h ---------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_TEST_LINKER_TEST_H
-#define MCLD_TEST_LINKER_TEST_H
-#include <gtest.h>
-
-#include "Linker/TestLinker.h"
-
-namespace mcldtest
-{
-
-class TestLinkerTest : public ::testing::Test
-{
-public:
- // Constructor can do set-up work for all test here.
- TestLinkerTest();
-
- // Destructor can do clean-up work that doesn't throw exceptions here.
- virtual ~TestLinkerTest();
-
- // SetUp() will be called immediately before each test.
- virtual void SetUp();
-
- // TearDown() will be called immediately after each test.
- virtual void TearDown();
-
-protected:
- mcld::test::TestLinker* m_pLinker;
-};
-
-} // namespace of mcldtest
-
-#endif
-
diff --git a/unittests/UniqueGCFactoryBaseTest.cpp b/unittests/UniqueGCFactoryBaseTest.cpp
index f8e098a..45a2aca 100644
--- a/unittests/UniqueGCFactoryBaseTest.cpp
+++ b/unittests/UniqueGCFactoryBaseTest.cpp
@@ -19,8 +19,6 @@
// Constructor can do set-up work for all test here.
UniqueGCFactoryBaseTest::UniqueGCFactoryBaseTest()
{
- InitializeAllDiagnostics();
-
m_pConfig = new LinkerConfig("arm-none-linux-gnueabi");
}