1//===- ELFDynamic.h -------------------------------------------------------===// 2// 3// The MCLinker Project 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#ifndef MCLD_TARGET_ELFDYNAMIC_H 10#define MCLD_TARGET_ELFDYNAMIC_H 11 12#include <mcld/LD/LDSection.h> 13#include <mcld/Support/FileOutputBuffer.h> 14#include <llvm/Support/ELF.h> 15#include <vector> 16#include <cstring> 17 18namespace mcld { 19 20class ELFFileFormat; 21class GNULDBackend; 22class LinkerConfig; 23 24namespace elf_dynamic { 25 26/** \class EntryIF 27* \brief EntryIF provides a common interface for one entry in the dynamic 28* section 29*/ 30class EntryIF 31{ 32protected: 33 EntryIF(); 34 35public: 36 virtual ~EntryIF(); 37 38 virtual EntryIF* clone() const = 0; 39 virtual size_t size() const = 0; 40 virtual size_t symbolSize() const = 0; 41 virtual size_t relSize() const = 0; 42 virtual size_t relaSize() const = 0; 43 virtual size_t emit(uint8_t* pAddress) const = 0; 44 virtual void setValue(uint64_t pTag, uint64_t pValue) = 0; 45}; 46 47template<size_t BITNUMBER, bool LITTLEENDIAN> 48class Entry 49{ }; 50 51template<> 52class Entry<32, true> : public EntryIF 53{ 54public: 55 typedef llvm::ELF::Elf32_Dyn Pair; 56 typedef llvm::ELF::Elf32_Sym Symbol; 57 typedef llvm::ELF::Elf32_Rel Rel; 58 typedef llvm::ELF::Elf32_Rela Rela; 59 60public: 61 inline Entry(); 62 63 inline ~Entry(); 64 65 Entry* clone() const 66 { return new Entry(); } 67 68 size_t size() const 69 { return sizeof(Pair); } 70 71 size_t symbolSize() const 72 { return sizeof(Symbol); } 73 74 size_t relSize() const 75 { return sizeof(Rel); } 76 77 size_t relaSize() const 78 { return sizeof(Rela); } 79 80 inline void setValue(uint64_t pTag, uint64_t pValue); 81 82 inline size_t emit(uint8_t* pAddress) const; 83 84private: 85 Pair m_Pair; 86}; 87 88template<> 89class Entry<64, true> : public EntryIF 90{ 91public: 92 typedef llvm::ELF::Elf64_Dyn Pair; 93 typedef llvm::ELF::Elf64_Sym Symbol; 94 typedef llvm::ELF::Elf64_Rel Rel; 95 typedef llvm::ELF::Elf64_Rela Rela; 96 97public: 98 inline Entry(); 99 100 inline ~Entry(); 101 102 Entry* clone() const 103 { return new Entry(); } 104 105 size_t size() const 106 { return sizeof(Pair); } 107 108 size_t symbolSize() const 109 { return sizeof(Symbol); } 110 111 size_t relSize() const 112 { return sizeof(Rel); } 113 114 size_t relaSize() const 115 { return sizeof(Rela); } 116 117 inline void setValue(uint64_t pTag, uint64_t pValue); 118 119 inline size_t emit(uint8_t* pAddress) const; 120 121private: 122 Pair m_Pair; 123}; 124 125#include "ELFDynamic.tcc" 126 127} // namespace of elf_dynamic 128 129/** \class ELFDynamic 130 * \brief ELFDynamic is the .dynamic section in ELF shared and executable 131 * files. 132 */ 133class ELFDynamic 134{ 135public: 136 typedef std::vector<elf_dynamic::EntryIF*> EntryListType; 137 typedef EntryListType::iterator iterator; 138 typedef EntryListType::const_iterator const_iterator; 139 140public: 141 ELFDynamic(const GNULDBackend& pBackend, const LinkerConfig& pConfig); 142 143 virtual ~ELFDynamic(); 144 145 size_t size() const; 146 147 size_t entrySize() const; 148 149 size_t numOfBytes() const; 150 151 /// reserveEntries - reserve entries 152 void reserveEntries(const ELFFileFormat& pFormat); 153 154 /// reserveNeedEntry - reserve on DT_NEED entry. 155 void reserveNeedEntry(); 156 157 /// applyEntries - apply entries 158 void applyEntries(const ELFFileFormat& pFormat); 159 160 void applySoname(uint64_t pStrTabIdx); 161 162 const_iterator needBegin() const { return m_NeedList.begin(); } 163 iterator needBegin() { return m_NeedList.begin(); } 164 165 const_iterator needEnd() const { return m_NeedList.end(); } 166 iterator needEnd() { return m_NeedList.end(); } 167 168 /// emit 169 void emit(const LDSection& pSection, MemoryRegion& pRegion) const; 170 171protected: 172 /// reserveTargetEntries - reserve target dependent entries 173 virtual void reserveTargetEntries(const ELFFileFormat& pFormat) = 0; 174 175 /// applyTargetEntries - apply target-dependant 176 virtual void applyTargetEntries(const ELFFileFormat& pFormat) = 0; 177 178protected: 179 void reserveOne(uint64_t pTag); 180 181 void applyOne(uint64_t pTag, uint64_t pValue); 182 183 size_t symbolSize() const; 184 185 const LinkerConfig& config() const { return m_Config; } 186 187private: 188 EntryListType m_EntryList; 189 EntryListType m_NeedList; 190 elf_dynamic::EntryIF* m_pEntryFactory; 191 const GNULDBackend& m_Backend; 192 const LinkerConfig& m_Config; 193 194 // The entry reserved and the entry being applied are not must matched. 195 // For better performance, we use a simple counter and apply entry one-by-one 196 // by the counter. m_Idx is the counter indicating to the entry being applied. 197 size_t m_Idx; 198}; 199 200} // namespace of mcld 201 202#endif 203 204