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 bool reserveTLSGdEntry(ResolveInfo& pInfo); 54 bool reserveTLSGotEntry(ResolveInfo& pInfo); 55 bool reserveTLSLdmEntry(); 56 57 size_t getLocalNum() const; ///< number of local symbols in primary GOT 58 size_t getGlobalNum() const; ///< total number of global symbols 59 60 bool isPrimaryGOTConsumed(); 61 62 Fragment* consumeLocal(); 63 Fragment* consumeGlobal(); 64 Fragment* consumeTLS(Relocation::Type pType); 65 66 uint64_t getGPAddr(const Input& pInput) const; 67 uint64_t getGPRelOffset(const Input& pInput, const Fragment& pEntry) const; 68 69 void recordGlobalEntry(const ResolveInfo* pInfo, Fragment* pEntry); 70 Fragment* lookupGlobalEntry(const ResolveInfo* pInfo); 71 72 void recordTLSEntry(const ResolveInfo* pInfo, Fragment* pEntry, 73 Relocation::Type pType); 74 Fragment* lookupTLSEntry(const ResolveInfo* pInfo, Relocation::Type pType); 75 76 void recordLocalEntry(const ResolveInfo* pInfo, 77 Relocation::DWord pAddend, 78 Fragment* pEntry); 79 Fragment* lookupLocalEntry(const ResolveInfo* pInfo, 80 Relocation::DWord pAddend); 81 82 /// hasGOT1 - return if this got section has any GOT1 entry 83 bool hasGOT1() const; 84 85 bool hasMultipleGOT() const; 86 87 /// Create GOT entries and reserve dynrel entries. 88 void finalizeScanning(OutputRelocSection& pRelDyn); 89 90 /// Compare two symbols to define order in the .dynsym. 91 bool dynSymOrderCompare(const LDSymbol* pX, const LDSymbol* pY) const; 92 93 protected: 94 /// Create GOT entry. 95 virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent) = 0; 96 97 /// Size of GOT entry. 98 virtual size_t getEntrySize() const = 0; 99 100 /// Reserve GOT header entries. 101 virtual void reserveHeader() = 0; 102 103 private: 104 /** \class GOTMultipart 105 * \brief GOTMultipart counts local and global entries in the GOT. 106 */ 107 struct GOTMultipart { 108 explicit GOTMultipart(size_t local = 0, size_t global = 0); 109 110 typedef llvm::DenseSet<const Input*> InputSetType; 111 112 size_t m_LocalNum; ///< number of reserved local entries 113 size_t m_GlobalNum; ///< number of reserved global entries 114 size_t m_TLSNum; ///< number of reserved TLS entries 115 size_t m_TLSDynNum; ///< number of reserved TLS related dynamic relocations 116 117 size_t m_ConsumedLocal; ///< consumed local entries 118 size_t m_ConsumedGlobal; ///< consumed global entries 119 size_t m_ConsumedTLS; ///< consumed TLS entries 120 121 Fragment* m_pLastLocal; ///< the last consumed local entry 122 Fragment* m_pLastGlobal; ///< the last consumed global entry 123 Fragment* m_pLastTLS; ///< the last consumed TLS entry 124 125 InputSetType m_Inputs; 126 127 bool isConsumed() const; 128 129 void consumeLocal(); 130 void consumeGlobal(); 131 void consumeTLS(Relocation::Type pType); 132 }; 133 134 /** \class LocalEntry 135 * \brief LocalEntry local GOT entry descriptor. 136 */ 137 struct LocalEntry { 138 const ResolveInfo* m_pInfo; 139 Relocation::DWord m_Addend; 140 bool m_IsGot16; 141 142 LocalEntry(const ResolveInfo* pInfo, 143 Relocation::DWord addend, 144 bool isGot16); 145 146 bool operator<(const LocalEntry& O) const; 147 }; 148 149 typedef std::vector<GOTMultipart> MultipartListType; 150 151 // Set of global symbols. 152 typedef llvm::DenseSet<const ResolveInfo*> SymbolSetType; 153 // Map of symbols. If value is true, the symbol is referenced 154 // in the current input only. If value is false, the symbol 155 // is referenced in the other modules merged to the current GOT. 156 typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolUniqueMapType; 157 158 // Set of local symbols. 159 typedef std::set<LocalEntry> LocalSymbolSetType; 160 161 MultipartListType m_MultipartList; ///< list of GOT's descriptors 162 const Input* m_pInput; ///< current input 163 164 // Global symbols merged to the current GOT 165 // except symbols from the current input. 166 SymbolSetType m_MergedGlobalSymbols; 167 // Global symbols from the current input. 168 SymbolUniqueMapType m_InputGlobalSymbols; 169 // Set of symbols referenced by TLS GD relocations. 170 SymbolSetType m_InputTLSGdSymbols; 171 // Set of symbols referenced by TLS GOTTPREL relocation. 172 SymbolSetType m_InputTLSGotSymbols; 173 // There is a symbol referenced by TLS LDM relocations. 174 bool m_HasTLSLdmSymbol; 175 // Local symbols merged to the current GOT 176 // except symbols from the current input. 177 LocalSymbolSetType m_MergedLocalSymbols; 178 // Local symbols from the current input. 179 LocalSymbolSetType m_InputLocalSymbols; 180 181 size_t m_CurrentGOTPart; 182 183 typedef llvm::DenseMap<const LDSymbol*, unsigned> SymbolOrderMapType; 184 SymbolOrderMapType m_SymbolOrderMap; 185 186 void initGOTList(); 187 188 void changeInput(); 189 bool isGOTFull() const; 190 void split(); 191 void reserve(size_t pNum); 192 193 private: 194 struct GotEntryKey { 195 size_t m_GOTPage; 196 const ResolveInfo* m_pInfo; 197 Relocation::DWord m_Addend; 198 199 bool operator<(const GotEntryKey& key) const { 200 if (m_GOTPage != key.m_GOTPage) 201 return m_GOTPage < key.m_GOTPage; 202 203 if (m_pInfo != key.m_pInfo) 204 return m_pInfo < key.m_pInfo; 205 206 return m_Addend < key.m_Addend; 207 } 208 }; 209 210 typedef std::map<GotEntryKey, Fragment*> GotEntryMapType; 211 GotEntryMapType m_GotLocalEntriesMap; 212 GotEntryMapType m_GotGlobalEntriesMap; 213 GotEntryMapType m_GotTLSGdEntriesMap; 214 GotEntryMapType m_GotTLSGotEntriesMap; 215 Fragment* m_GotTLSLdmEntry; 216 }; 217 218 /** \class Mips32GOT 219 * \brief Mips 32-bit Global Offset Table. 220 */ 221 class Mips32GOT : public MipsGOT { 222 public: 223 explicit Mips32GOT(LDSection& pSection); 224 225 private: 226 typedef GOT::Entry<4> Mips32GOTEntry; 227 228 // MipsGOT 229 virtual void setEntryValue(Fragment* entry, uint64_t pValue); 230 virtual uint64_t emit(MemoryRegion& pRegion); 231 virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent); 232 virtual size_t getEntrySize() const; 233 virtual void reserveHeader(); 234 }; 235 236 /** \class Mips64GOT 237 * \brief Mips 64-bit Global Offset Table. 238 */ 239 class Mips64GOT : public MipsGOT { 240 public: 241 explicit Mips64GOT(LDSection& pSection); 242 243 private: 244 typedef GOT::Entry<8> Mips64GOTEntry; 245 246 // MipsGOT 247 virtual void setEntryValue(Fragment* entry, uint64_t pValue); 248 virtual uint64_t emit(MemoryRegion& pRegion); 249 virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent); 250 virtual size_t getEntrySize() const; 251 virtual void reserveHeader(); 252 }; 253 254 } // namespace mcld 255 256 #endif // TARGET_MIPS_MIPSGOT_H_ 257