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 <map> 12 #include <vector> 13 14 15 #include <mcld/ADT/SizeTraits.h> 16 #include <mcld/Target/GOT.h> 17 #include <mcld/Fragment/Relocation.h> 18 #include <mcld/Support/MemoryRegion.h> 19 #include <llvm/ADT/DenseMap.h> 20 #include <llvm/ADT/DenseSet.h> 21 #include <set> 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 { 35 public: 36 MipsGOT(LDSection& pSection); 37 38 /// Assign value to the GOT entry. 39 virtual void setEntryValue(Fragment* entry, uint64_t pValue) = 0; 40 41 /// Emit the global offset table. 42 virtual uint64_t emit(MemoryRegion& pRegion) = 0; 43 44 /// Address of _gp_disp symbol. 45 uint64_t getGPDispAddress() const; 46 47 void initializeScan(const Input& pInput); 48 void finalizeScan(const Input& pInput); 49 50 bool reserveLocalEntry(ResolveInfo& pInfo, 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 { 101 GOTMultipart(size_t local = 0, size_t global = 0); 102 103 typedef llvm::DenseSet<const Input*> InputSetType; 104 105 size_t m_LocalNum; ///< number of reserved local entries 106 size_t m_GlobalNum; ///< number of reserved global entries 107 108 size_t m_ConsumedLocal; ///< consumed local entries 109 size_t m_ConsumedGlobal; ///< consumed global entries 110 111 Fragment* m_pLastLocal; ///< the last consumed local entry 112 Fragment* m_pLastGlobal; ///< the last consumed global entry 113 114 InputSetType m_Inputs; 115 116 bool isConsumed() const; 117 118 void consumeLocal(); 119 void consumeGlobal(); 120 }; 121 122 /** \class LocalEntry 123 * \brief LocalEntry local GOT entry descriptor. 124 */ 125 struct LocalEntry 126 { 127 const ResolveInfo* m_pInfo; 128 Relocation::DWord m_Addend; 129 bool m_IsGot16; 130 131 LocalEntry(const ResolveInfo* pInfo, 132 Relocation::DWord addend, bool isGot16); 133 134 bool operator<(const LocalEntry &O) const; 135 }; 136 137 typedef std::vector<GOTMultipart> MultipartListType; 138 139 // Set of global symbols. 140 typedef llvm::DenseSet<const ResolveInfo*> SymbolSetType; 141 // Map of symbols. If value is true, the symbol is referenced 142 // in the current input only. If value is false, the symbol 143 // is referenced in the other modules merged to the current GOT. 144 typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolUniqueMapType; 145 146 // Set of local symbols. 147 typedef std::set<LocalEntry> LocalSymbolSetType; 148 149 MultipartListType m_MultipartList; ///< list of GOT's descriptors 150 const Input* m_pInput; ///< current input 151 152 // Global symbols merged to the current GOT 153 // except symbols from the current input. 154 SymbolSetType m_MergedGlobalSymbols; 155 // Global symbols from the current input. 156 SymbolUniqueMapType m_InputGlobalSymbols; 157 // Local symbols merged to the current GOT 158 // except symbols from the current input. 159 LocalSymbolSetType m_MergedLocalSymbols; 160 // Local symbols from the current input. 161 LocalSymbolSetType m_InputLocalSymbols; 162 163 size_t m_CurrentGOTPart; 164 165 typedef llvm::DenseMap<const LDSymbol*, unsigned> SymbolOrderMapType; 166 SymbolOrderMapType m_SymbolOrderMap; 167 168 void initGOTList(); 169 170 void changeInput(); 171 bool isGOTFull() const; 172 void split(); 173 void reserve(size_t pNum); 174 175 private: 176 struct GotEntryKey 177 { 178 size_t m_GOTPage; 179 const ResolveInfo* m_pInfo; 180 Relocation::DWord m_Addend; 181 182 bool operator<(const GotEntryKey& key) const 183 { 184 if (m_GOTPage != key.m_GOTPage) 185 return m_GOTPage < key.m_GOTPage; 186 187 if (m_pInfo != key.m_pInfo) 188 return m_pInfo < key.m_pInfo; 189 190 return m_Addend < key.m_Addend; 191 } 192 }; 193 194 typedef std::map<GotEntryKey, Fragment*> GotEntryMapType; 195 GotEntryMapType m_GotLocalEntriesMap; 196 GotEntryMapType m_GotGlobalEntriesMap; 197 }; 198 199 /** \class Mips32GOT 200 * \brief Mips 32-bit Global Offset Table. 201 */ 202 class Mips32GOT : public MipsGOT 203 { 204 public: 205 Mips32GOT(LDSection& pSection); 206 207 private: 208 typedef GOT::Entry<4> Mips32GOTEntry; 209 210 // MipsGOT 211 virtual void setEntryValue(Fragment* entry, uint64_t pValue); 212 virtual uint64_t emit(MemoryRegion& pRegion); 213 virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent); 214 virtual size_t getEntrySize() const; 215 virtual void reserveHeader(); 216 }; 217 218 /** \class Mips64GOT 219 * \brief Mips 64-bit Global Offset Table. 220 */ 221 class Mips64GOT : public MipsGOT 222 { 223 public: 224 Mips64GOT(LDSection& pSection); 225 226 private: 227 typedef GOT::Entry<8> Mips64GOTEntry; 228 229 // MipsGOT 230 virtual void setEntryValue(Fragment* entry, uint64_t pValue); 231 virtual uint64_t emit(MemoryRegion& pRegion); 232 virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent); 233 virtual size_t getEntrySize() const; 234 virtual void reserveHeader(); 235 }; 236 237 } // namespace of mcld 238 239 #endif 240 241