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