//===- ELFDynamic.h -------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef MCLD_TARGET_ELFDYNAMIC_H #define MCLD_TARGET_ELFDYNAMIC_H #include <mcld/LD/LDSection.h> #include <mcld/Support/FileOutputBuffer.h> #include <llvm/Support/ELF.h> #include <vector> #include <cstring> namespace mcld { class ELFFileFormat; class GNULDBackend; class LinkerConfig; namespace elf_dynamic { /** \class EntryIF * \brief EntryIF provides a common interface for one entry in the dynamic * section */ class EntryIF { protected: EntryIF(); public: virtual ~EntryIF(); virtual EntryIF* clone() const = 0; virtual size_t size() const = 0; virtual size_t symbolSize() const = 0; virtual size_t relSize() const = 0; virtual size_t relaSize() const = 0; virtual size_t emit(uint8_t* pAddress) const = 0; virtual void setValue(uint64_t pTag, uint64_t pValue) = 0; }; template<size_t BITNUMBER, bool LITTLEENDIAN> class Entry { }; template<> class Entry<32, true> : public EntryIF { public: typedef llvm::ELF::Elf32_Dyn Pair; typedef llvm::ELF::Elf32_Sym Symbol; typedef llvm::ELF::Elf32_Rel Rel; typedef llvm::ELF::Elf32_Rela Rela; public: inline Entry(); inline ~Entry(); Entry* clone() const { return new Entry(); } size_t size() const { return sizeof(Pair); } size_t symbolSize() const { return sizeof(Symbol); } size_t relSize() const { return sizeof(Rel); } size_t relaSize() const { return sizeof(Rela); } inline void setValue(uint64_t pTag, uint64_t pValue); inline size_t emit(uint8_t* pAddress) const; private: Pair m_Pair; }; template<> class Entry<64, true> : public EntryIF { public: typedef llvm::ELF::Elf64_Dyn Pair; typedef llvm::ELF::Elf64_Sym Symbol; typedef llvm::ELF::Elf64_Rel Rel; typedef llvm::ELF::Elf64_Rela Rela; public: inline Entry(); inline ~Entry(); Entry* clone() const { return new Entry(); } size_t size() const { return sizeof(Pair); } size_t symbolSize() const { return sizeof(Symbol); } size_t relSize() const { return sizeof(Rel); } size_t relaSize() const { return sizeof(Rela); } inline void setValue(uint64_t pTag, uint64_t pValue); inline size_t emit(uint8_t* pAddress) const; private: Pair m_Pair; }; #include "ELFDynamic.tcc" } // namespace of elf_dynamic /** \class ELFDynamic * \brief ELFDynamic is the .dynamic section in ELF shared and executable * files. */ class ELFDynamic { public: typedef std::vector<elf_dynamic::EntryIF*> EntryListType; typedef EntryListType::iterator iterator; typedef EntryListType::const_iterator const_iterator; public: ELFDynamic(const GNULDBackend& pBackend, const LinkerConfig& pConfig); virtual ~ELFDynamic(); size_t size() const; size_t entrySize() const; size_t numOfBytes() const; /// reserveEntries - reserve entries void reserveEntries(const ELFFileFormat& pFormat); /// reserveNeedEntry - reserve on DT_NEED entry. void reserveNeedEntry(); /// applyEntries - apply entries void applyEntries(const ELFFileFormat& pFormat); void applySoname(uint64_t pStrTabIdx); const_iterator needBegin() const { return m_NeedList.begin(); } iterator needBegin() { return m_NeedList.begin(); } const_iterator needEnd() const { return m_NeedList.end(); } iterator needEnd() { return m_NeedList.end(); } /// emit void emit(const LDSection& pSection, MemoryRegion& pRegion) const; protected: /// reserveTargetEntries - reserve target dependent entries virtual void reserveTargetEntries(const ELFFileFormat& pFormat) = 0; /// applyTargetEntries - apply target-dependant virtual void applyTargetEntries(const ELFFileFormat& pFormat) = 0; protected: void reserveOne(uint64_t pTag); void applyOne(uint64_t pTag, uint64_t pValue); size_t symbolSize() const; const LinkerConfig& config() const { return m_Config; } private: EntryListType m_EntryList; 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 // by the counter. m_Idx is the counter indicating to the entry being applied. size_t m_Idx; }; } // namespace of mcld #endif