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