1 //===- X86Relocator.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 X86_RELOCATION_FACTORY_H 10 #define X86_RELOCATION_FACTORY_H 11 #ifdef ENABLE_UNITTEST 12 #include <gtest.h> 13 #endif 14 15 #include <mcld/LD/Relocator.h> 16 #include <mcld/Target/GOT.h> 17 #include <mcld/Target/PLT.h> 18 #include <mcld/Target/SymbolEntryMap.h> 19 #include "X86LDBackend.h" 20 21 namespace mcld { 22 23 class ResolveInfo; 24 class LinkerConfig; 25 26 /** \class X86Relocator 27 * \brief X86Relocator creates and destroys the X86 relocations. 28 * 29 */ 30 class X86Relocator : public Relocator 31 { 32 public: 33 typedef SymbolEntryMap<PLTEntryBase> SymPLTMap; 34 35 /** \enum ReservedEntryType 36 * \brief The reserved entry type of reserved space in ResolveInfo. 37 * 38 * This is used for sacnRelocation to record what kinds of entries are 39 * reserved for this resolved symbol 40 * 41 * In X86, there are three kinds of entries, GOT, PLT, and dynamic reloction. 42 * GOT may needs a corresponding relocation to relocate itself, so we 43 * separate GOT to two situations: GOT and GOTRel. Besides, for the same 44 * symbol, there might be two kinds of entries reserved for different location. 45 * For example, reference to the same symbol, one may use GOT and the other may 46 * use dynamic relocation. 47 * 48 * bit: 3 2 1 0 49 * | PLT | GOTRel | GOT | Rel | 50 * 51 * value Name - Description 52 * 53 * 0000 None - no reserved entry 54 * 0001 ReserveRel - reserve an dynamic relocation entry 55 * 0010 ReserveGOT - reserve an GOT entry 56 * 0011 GOTandRel - For different relocation, we've reserved GOT and 57 * Rel for different location. 58 * 0100 GOTRel - reserve an GOT entry and the corresponding Dyncamic 59 * relocation entry which relocate this GOT entry 60 * 0101 GOTRelandRel - For different relocation, we've reserved GOTRel 61 * and relocation entry for different location. 62 * 1000 ReservePLT - reserve an PLT entry and the corresponding GOT, 63 * Dynamic relocation entries 64 * 1001 PLTandRel - For different relocation, we've reserved PLT and 65 * Rel for different location. 66 */ 67 enum ReservedEntryType { 68 None = 0, 69 ReserveRel = 1, 70 ReserveGOT = 2, 71 GOTandRel = 3, 72 GOTRel = 4, 73 GOTRelandRel = 5, 74 ReservePLT = 8, 75 PLTandRel = 9 76 }; 77 78 public: 79 X86Relocator(const LinkerConfig& pConfig); 80 ~X86Relocator(); 81 82 virtual Result applyRelocation(Relocation& pRelocation) = 0; 83 84 virtual const char* getName(Relocation::Type pType) const = 0; 85 86 const SymPLTMap& getSymPLTMap() const { return m_SymPLTMap; } 87 SymPLTMap& getSymPLTMap() { return m_SymPLTMap; } 88 89 /// scanRelocation - determine the empty entries are needed or not and create 90 /// the empty entries if needed. 91 /// For X86, following entries are check to create: 92 /// - GOT entry (for .got and .got.plt sections) 93 /// - PLT entry (for .plt section) 94 /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections) 95 void scanRelocation(Relocation& pReloc, 96 IRBuilder& pBuilder, 97 Module& pModule, 98 LDSection& pSection); 99 100 protected: 101 /// addCopyReloc - add a copy relocation into .rel.dyn for pSym 102 /// @param pSym - A resolved copy symbol that defined in BSS section 103 void addCopyReloc(ResolveInfo& pSym, X86GNULDBackend& pTarget); 104 105 /// defineSymbolforCopyReloc - allocate a space in BSS section and 106 /// and force define the copy of pSym to BSS section 107 /// @return the output LDSymbol of the copy symbol 108 LDSymbol& defineSymbolforCopyReloc(IRBuilder& pLinker, 109 const ResolveInfo& pSym, 110 X86GNULDBackend& pTarget); 111 112 private: 113 virtual void scanLocalReloc(Relocation& pReloc, 114 IRBuilder& pBuilder, 115 Module& pModule, 116 LDSection& pSection) = 0; 117 118 virtual void scanGlobalReloc(Relocation& pReloc, 119 IRBuilder& pBuilder, 120 Module& pModule, 121 LDSection& pSection) = 0; 122 123 private: 124 SymPLTMap m_SymPLTMap; 125 }; 126 127 /** \class X86_32Relocator 128 * \brief X86_32Relocator creates and destroys the X86-32 relocations. 129 * 130 */ 131 class X86_32Relocator : public X86Relocator 132 { 133 public: 134 typedef SymbolEntryMap<X86_32GOTEntry> SymGOTMap; 135 typedef SymbolEntryMap<X86_32GOTEntry> SymGOTPLTMap; 136 137 enum { 138 R_386_TLS_OPT = 44 // mcld internal relocation type 139 }; 140 141 public: 142 X86_32Relocator(X86_32GNULDBackend& pParent, const LinkerConfig& pConfig); 143 144 Result applyRelocation(Relocation& pRelocation); 145 146 X86_32GNULDBackend& getTarget() 147 { return m_Target; } 148 149 const X86_32GNULDBackend& getTarget() const 150 { return m_Target; } 151 152 const char* getName(Relocation::Type pType) const; 153 154 Size getSize(Relocation::Type pType) const; 155 156 const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; } 157 SymGOTMap& getSymGOTMap() { return m_SymGOTMap; } 158 159 const SymGOTPLTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; } 160 SymGOTPLTMap& getSymGOTPLTMap() { return m_SymGOTPLTMap; } 161 162 X86_32GOTEntry& getTLSModuleID(); 163 164 private: 165 void scanLocalReloc(Relocation& pReloc, 166 IRBuilder& pBuilder, 167 Module& pModule, 168 LDSection& pSection); 169 170 void scanGlobalReloc(Relocation& pReloc, 171 IRBuilder& pBuilder, 172 Module& pModule, 173 LDSection& pSection); 174 175 /// ----- tls optimization ----- /// 176 /// convert R_386_TLS_IE to R_386_TLS_LE 177 void convertTLSIEtoLE(Relocation& pReloc, LDSection& pSection); 178 179 private: 180 X86_32GNULDBackend& m_Target; 181 SymGOTMap m_SymGOTMap; 182 SymGOTPLTMap m_SymGOTPLTMap; 183 }; 184 185 /** \class X86_64Relocator 186 * \brief X86_64Relocator creates and destroys the X86-64 relocations. 187 * 188 */ 189 class X86_64Relocator : public X86Relocator 190 { 191 public: 192 typedef SymbolEntryMap<X86_64GOTEntry> SymGOTMap; 193 typedef SymbolEntryMap<X86_64GOTEntry> SymGOTPLTMap; 194 195 public: 196 X86_64Relocator(X86_64GNULDBackend& pParent, const LinkerConfig& pConfig); 197 198 Result applyRelocation(Relocation& pRelocation); 199 200 X86_64GNULDBackend& getTarget() 201 { return m_Target; } 202 203 const X86_64GNULDBackend& getTarget() const 204 { return m_Target; } 205 206 const char* getName(Relocation::Type pType) const; 207 208 Size getSize(Relocation::Type pType) const; 209 210 const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; } 211 SymGOTMap& getSymGOTMap() { return m_SymGOTMap; } 212 213 const SymGOTPLTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; } 214 SymGOTPLTMap& getSymGOTPLTMap() { return m_SymGOTPLTMap; } 215 216 private: 217 void scanLocalReloc(Relocation& pReloc, 218 IRBuilder& pBuilder, 219 Module& pModule, 220 LDSection& pSection); 221 222 void scanGlobalReloc(Relocation& pReloc, 223 IRBuilder& pBuilder, 224 Module& pModule, 225 LDSection& pSection); 226 227 private: 228 X86_64GNULDBackend& m_Target; 229 SymGOTMap m_SymGOTMap; 230 SymGOTPLTMap m_SymGOTPLTMap; 231 }; 232 233 } // namespace of mcld 234 235 #endif 236 237