1 //===- MipsGOT.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 TARGET_MIPS_MIPSGOT_H_ 10 #define TARGET_MIPS_MIPSGOT_H_ 11 #include "mcld/ADT/SizeTraits.h" 12 #include "mcld/Fragment/Relocation.h" 13 #include "mcld/Support/MemoryRegion.h" 14 #include "mcld/Target/GOT.h" 15 16 #include <llvm/ADT/DenseMap.h> 17 #include <llvm/ADT/DenseSet.h> 18 19 #include <map> 20 #include <set> 21 #include <vector> 22 23 namespace mcld { 24 25 class Input; 26 class LDSection; 27 class LDSymbol; 28 class OutputRelocSection; 29 30 /** \class MipsGOT 31 * \brief Mips Global Offset Table. 32 */ 33 class MipsGOT : public GOT { 34 public: 35 explicit MipsGOT(LDSection& pSection); 36 37 /// Assign value to the GOT entry. 38 virtual void setEntryValue(Fragment* entry, uint64_t pValue) = 0; 39 40 /// Emit the global offset table. 41 virtual uint64_t emit(MemoryRegion& pRegion) = 0; 42 43 /// Address of _gp_disp symbol. 44 uint64_t getGPDispAddress() const; 45 46 void initializeScan(const Input& pInput); 47 void finalizeScan(const Input& pInput); 48 49 bool reserveLocalEntry(ResolveInfo& pInfo, 50 int reloc, 51 Relocation::DWord pAddend); 52 bool reserveGlobalEntry(ResolveInfo& pInfo); 53 54 size_t getLocalNum() const; ///< number of local symbols in primary GOT 55 size_t getGlobalNum() const; ///< total number of global symbols 56 57 bool isPrimaryGOTConsumed(); 58 59 Fragment* consumeLocal(); 60 Fragment* consumeGlobal(); 61 62 uint64_t getGPAddr(const Input& pInput) const; 63 uint64_t getGPRelOffset(const Input& pInput, const Fragment& pEntry) const; 64 65 void recordGlobalEntry(const ResolveInfo* pInfo, Fragment* pEntry); 66 Fragment* lookupGlobalEntry(const ResolveInfo* pInfo); 67 68 void recordLocalEntry(const ResolveInfo* pInfo, 69 Relocation::DWord pAddend, 70 Fragment* pEntry); 71 Fragment* lookupLocalEntry(const ResolveInfo* pInfo, 72 Relocation::DWord pAddend); 73 74 /// hasGOT1 - return if this got section has any GOT1 entry 75 bool hasGOT1() const; 76 77 bool hasMultipleGOT() const; 78 79 /// Create GOT entries and reserve dynrel entries. 80 void finalizeScanning(OutputRelocSection& pRelDyn); 81 82 /// Compare two symbols to define order in the .dynsym. 83 bool dynSymOrderCompare(const LDSymbol* pX, const LDSymbol* pY) const; 84 85 protected: 86 /// Create GOT entry. 87 virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent) = 0; 88 89 /// Size of GOT entry. 90 virtual size_t getEntrySize() const = 0; 91 92 /// Reserve GOT header entries. 93 virtual void reserveHeader() = 0; 94 95 private: 96 /** \class GOTMultipart 97 * \brief GOTMultipart counts local and global entries in the GOT. 98 */ 99 struct GOTMultipart { 100 explicit GOTMultipart(size_t local = 0, size_t global = 0); 101 102 typedef llvm::DenseSet<const Input*> InputSetType; 103 104 size_t m_LocalNum; ///< number of reserved local entries 105 size_t m_GlobalNum; ///< number of reserved global entries 106 107 size_t m_ConsumedLocal; ///< consumed local entries 108 size_t m_ConsumedGlobal; ///< consumed global entries 109 110 Fragment* m_pLastLocal; ///< the last consumed local entry 111 Fragment* m_pLastGlobal; ///< the last consumed global entry 112 113 InputSetType m_Inputs; 114 115 bool isConsumed() const; 116 117 void consumeLocal(); 118 void consumeGlobal(); 119 }; 120 121 /** \class LocalEntry 122 * \brief LocalEntry local GOT entry descriptor. 123 */ 124 struct LocalEntry { 125 const ResolveInfo* m_pInfo; 126 Relocation::DWord m_Addend; 127 bool m_IsGot16; 128 129 LocalEntry(const ResolveInfo* pInfo, 130 Relocation::DWord addend, 131 bool isGot16); 132 133 bool operator<(const LocalEntry& O) const; 134 }; 135 136 typedef std::vector<GOTMultipart> MultipartListType; 137 138 // Set of global symbols. 139 typedef llvm::DenseSet<const ResolveInfo*> SymbolSetType; 140 // Map of symbols. If value is true, the symbol is referenced 141 // in the current input only. If value is false, the symbol 142 // is referenced in the other modules merged to the current GOT. 143 typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolUniqueMapType; 144 145 // Set of local symbols. 146 typedef std::set<LocalEntry> LocalSymbolSetType; 147 148 MultipartListType m_MultipartList; ///< list of GOT's descriptors 149 const Input* m_pInput; ///< current input 150 151 // Global symbols merged to the current GOT 152 // except symbols from the current input. 153 SymbolSetType m_MergedGlobalSymbols; 154 // Global symbols from the current input. 155 SymbolUniqueMapType m_InputGlobalSymbols; 156 // Local symbols merged to the current GOT 157 // except symbols from the current input. 158 LocalSymbolSetType m_MergedLocalSymbols; 159 // Local symbols from the current input. 160 LocalSymbolSetType m_InputLocalSymbols; 161 162 size_t m_CurrentGOTPart; 163 164 typedef llvm::DenseMap<const LDSymbol*, unsigned> SymbolOrderMapType; 165 SymbolOrderMapType m_SymbolOrderMap; 166 167 void initGOTList(); 168 169 void changeInput(); 170 bool isGOTFull() const; 171 void split(); 172 void reserve(size_t pNum); 173 174 private: 175 struct GotEntryKey { 176 size_t m_GOTPage; 177 const ResolveInfo* m_pInfo; 178 Relocation::DWord m_Addend; 179 180 bool operator<(const GotEntryKey& key) const { 181 if (m_GOTPage != key.m_GOTPage) 182 return m_GOTPage < key.m_GOTPage; 183 184 if (m_pInfo != key.m_pInfo) 185 return m_pInfo < key.m_pInfo; 186 187 return m_Addend < key.m_Addend; 188 } 189 }; 190 191 typedef std::map<GotEntryKey, Fragment*> GotEntryMapType; 192 GotEntryMapType m_GotLocalEntriesMap; 193 GotEntryMapType m_GotGlobalEntriesMap; 194 }; 195 196 /** \class Mips32GOT 197 * \brief Mips 32-bit Global Offset Table. 198 */ 199 class Mips32GOT : public MipsGOT { 200 public: 201 explicit Mips32GOT(LDSection& pSection); 202 203 private: 204 typedef GOT::Entry<4> Mips32GOTEntry; 205 206 // MipsGOT 207 virtual void setEntryValue(Fragment* entry, uint64_t pValue); 208 virtual uint64_t emit(MemoryRegion& pRegion); 209 virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent); 210 virtual size_t getEntrySize() const; 211 virtual void reserveHeader(); 212 }; 213 214 /** \class Mips64GOT 215 * \brief Mips 64-bit Global Offset Table. 216 */ 217 class Mips64GOT : public MipsGOT { 218 public: 219 explicit Mips64GOT(LDSection& pSection); 220 221 private: 222 typedef GOT::Entry<8> Mips64GOTEntry; 223 224 // MipsGOT 225 virtual void setEntryValue(Fragment* entry, uint64_t pValue); 226 virtual uint64_t emit(MemoryRegion& pRegion); 227 virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent); 228 virtual size_t getEntrySize() const; 229 virtual void reserveHeader(); 230 }; 231 232 } // namespace mcld 233 234 #endif // TARGET_MIPS_MIPSGOT_H_ 235