1 //===- X86LDBackend.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_LDBACKEND_H 10 #define X86_LDBACKEND_H 11 12 #include "X86ELFDynamic.h" 13 #include "X86GOT.h" 14 #include "X86GOTPLT.h" 15 #include "X86PLT.h" 16 #include <mcld/LD/LDSection.h> 17 #include <mcld/Target/GNULDBackend.h> 18 #include <mcld/Target/OutputRelocSection.h> 19 20 namespace mcld { 21 22 class LinkerConfig; 23 class GNUInfo; 24 25 //===----------------------------------------------------------------------===// 26 /// X86GNULDBackend - linker backend of X86 target of GNU ELF format 27 /// 28 class X86GNULDBackend : public GNULDBackend 29 { 30 public: 31 /** \enum ReservedEntryType 32 * \brief The reserved entry type of reserved space in ResolveInfo. 33 * 34 * This is used for sacnRelocation to record what kinds of entries are 35 * reserved for this resolved symbol 36 * 37 * In X86, there are three kinds of entries, GOT, PLT, and dynamic reloction. 38 * GOT may needs a corresponding relocation to relocate itself, so we 39 * separate GOT to two situations: GOT and GOTRel. Besides, for the same 40 * symbol, there might be two kinds of entries reserved for different location. 41 * For example, reference to the same symbol, one may use GOT and the other may 42 * use dynamic relocation. 43 * 44 * bit: 3 2 1 0 45 * | PLT | GOTRel | GOT | Rel | 46 * 47 * value Name - Description 48 * 49 * 0000 None - no reserved entry 50 * 0001 ReserveRel - reserve an dynamic relocation entry 51 * 0010 ReserveGOT - reserve an GOT entry 52 * 0011 GOTandRel - For different relocation, we've reserved GOT and 53 * Rel for different location. 54 * 0100 GOTRel - reserve an GOT entry and the corresponding Dyncamic 55 * relocation entry which relocate this GOT entry 56 * 0101 GOTRelandRel - For different relocation, we've reserved GOTRel 57 * and relocation entry for different location. 58 * 1000 ReservePLT - reserve an PLT entry and the corresponding GOT, 59 * Dynamic relocation entries 60 * 1001 PLTandRel - For different relocation, we've reserved PLT and 61 * Rel for different location. 62 */ 63 enum ReservedEntryType { 64 None = 0, 65 ReserveRel = 1, 66 ReserveGOT = 2, 67 GOTandRel = 3, 68 GOTRel = 4, 69 GOTRelandRel = 5, 70 ReservePLT = 8, 71 PLTandRel = 9 72 }; 73 74 public: 75 X86GNULDBackend(const LinkerConfig& pConfig, 76 GNUInfo* pInfo, 77 Relocation::Type pCopyRel); 78 79 ~X86GNULDBackend(); 80 81 uint32_t machine() const; 82 83 X86PLT& getPLT(); 84 85 const X86PLT& getPLT() const; 86 87 /// preLayout - Backend can do any needed modification before layout 88 void doPreLayout(IRBuilder& pBuilder); 89 90 /// postLayout -Backend can do any needed modification after layout 91 void doPostLayout(Module& pModule, IRBuilder& pBuilder); 92 93 /// dynamic - the dynamic section of the target machine. 94 /// Use co-variant return type to return its own dynamic section. 95 X86ELFDynamic& dynamic(); 96 97 /// dynamic - the dynamic section of the target machine. 98 /// Use co-variant return type to return its own dynamic section. 99 const X86ELFDynamic& dynamic() const; 100 101 /// emitSectionData - write out the section data into the memory region. 102 /// When writers get a LDSection whose kind is LDFileFormat::Target, writers 103 /// call back target backend to emit the data. 104 /// 105 /// Backends handle the target-special tables (plt, gp,...) by themselves. 106 /// Backend can put the data of the tables in MCSectionData directly 107 /// - LDSection.getSectionData can get the section data. 108 /// Or, backend can put the data into special data structure 109 /// - backend can maintain its own map<LDSection, table> to get the table 110 /// from given LDSection. 111 /// 112 /// @param pSection - the given LDSection 113 /// @param pLayout - for comouting the size of fragment 114 /// @param pRegion - the region to write out data 115 /// @return the size of the table in the file. 116 uint64_t emitSectionData(const LDSection& pSection, 117 MemoryRegion& pRegion) const; 118 119 /// initRelocator - create and initialize Relocator. 120 virtual bool initRelocator() = 0; 121 122 /// getRelocator - return relocator. 123 Relocator* getRelocator(); 124 125 virtual void initTargetSections(Module& pModule, ObjectBuilder& pBuilder) = 0; 126 127 void initTargetSymbols(IRBuilder& pBuilder, Module& pModule); 128 129 /// scanRelocation - determine the empty entries are needed or not and create 130 /// the empty entries if needed. 131 /// For X86, following entries are check to create: 132 /// - GOT entry (for .got and .got.plt sections) 133 /// - PLT entry (for .plt section) 134 /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections) 135 void scanRelocation(Relocation& pReloc, 136 IRBuilder& pBuilder, 137 Module& pModule, 138 LDSection& pSection); 139 140 OutputRelocSection& getRelDyn(); 141 142 const OutputRelocSection& getRelDyn() const; 143 144 OutputRelocSection& getRelPLT(); 145 146 const OutputRelocSection& getRelPLT() const; 147 148 /// getTargetSectionOrder - compute the layout order of X86 target sections 149 unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const; 150 151 /// finalizeTargetSymbols - finalize the symbol value 152 bool finalizeTargetSymbols(); 153 154 /// getPointerRel - get pointer relocation type. getPointerRel()155 Relocation::Type getPointerRel() 156 { return m_PointerRel; } 157 158 private: 159 virtual void scanLocalReloc(Relocation& pReloc, 160 IRBuilder& pBuilder, 161 Module& pModule, 162 LDSection& pSection) = 0; 163 164 virtual void scanGlobalReloc(Relocation& pReloc, 165 IRBuilder& pBuilder, 166 Module& pModule, 167 LDSection& pSection) = 0; 168 169 protected: 170 /// addCopyReloc - add a copy relocation into .rel.dyn for pSym 171 /// @param pSym - A resolved copy symbol that defined in BSS section 172 void addCopyReloc(ResolveInfo& pSym); 173 174 /// defineSymbolforCopyReloc - allocate a space in BSS section and 175 /// and force define the copy of pSym to BSS section 176 /// @return the output LDSymbol of the copy symbol 177 LDSymbol& defineSymbolforCopyReloc(IRBuilder& pLinker, 178 const ResolveInfo& pSym); 179 180 void defineGOTSymbol(IRBuilder& pBuilder, Fragment&); 181 182 protected: 183 /// getRelEntrySize - the size in BYTE of rel type relocation getRelEntrySize()184 size_t getRelEntrySize() 185 { return m_RelEntrySize; } 186 187 /// getRelEntrySize - the size in BYTE of rela type relocation getRelaEntrySize()188 size_t getRelaEntrySize() 189 { return m_RelaEntrySize; } 190 191 private: 192 /// doCreateProgramHdrs - backend can implement this function to create the 193 /// target-dependent segments 194 void doCreateProgramHdrs(Module& pModule); 195 196 virtual void setGOTSectionSize(IRBuilder& pBuilder) = 0; 197 198 virtual uint64_t emitGOTSectionData(MemoryRegion& pRegion) const = 0; 199 200 virtual uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion, 201 const ELFFileFormat* FileFormat) const = 0; 202 203 virtual void setRelDynSize() = 0; 204 virtual void setRelPLTSize() = 0; 205 206 protected: 207 Relocator* m_pRelocator; 208 X86PLT* m_pPLT; 209 /// m_RelDyn - dynamic relocation table of .rel.dyn 210 OutputRelocSection* m_pRelDyn; 211 /// m_RelPLT - dynamic relocation table of .rel.plt 212 OutputRelocSection* m_pRelPLT; 213 214 X86ELFDynamic* m_pDynamic; 215 LDSymbol* m_pGOTSymbol; 216 217 size_t m_RelEntrySize; 218 size_t m_RelaEntrySize; 219 220 Relocation::Type m_CopyRel; 221 Relocation::Type m_PointerRel; 222 }; 223 224 // 225 //===----------------------------------------------------------------------===// 226 /// X86_32GNULDBackend - linker backend of X86-32 target of GNU ELF format 227 /// 228 class X86_32GNULDBackend : public X86GNULDBackend 229 { 230 public: 231 X86_32GNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo); 232 233 ~X86_32GNULDBackend(); 234 235 void initTargetSections(Module& pModule, ObjectBuilder& pBuilder); 236 237 X86_32GOT& getGOT(); 238 239 const X86_32GOT& getGOT() const; 240 241 X86_32GOTPLT& getGOTPLT(); 242 243 const X86_32GOTPLT& getGOTPLT() const; 244 245 X86_32GOTEntry& getTLSModuleID(); 246 247 private: 248 void scanLocalReloc(Relocation& pReloc, 249 IRBuilder& pBuilder, 250 Module& pModule, 251 LDSection& pSection); 252 253 void scanGlobalReloc(Relocation& pReloc, 254 IRBuilder& pBuilder, 255 Module& pModule, 256 LDSection& pSection); 257 258 /// initRelocator - create and initialize Relocator. 259 bool initRelocator(); 260 261 /// ----- tls optimization ----- /// 262 /// convert R_386_TLS_IE to R_386_TLS_LE 263 void convertTLSIEtoLE(Relocation& pReloc, LDSection& pSection); 264 265 void setGOTSectionSize(IRBuilder& pBuilder); 266 267 uint64_t emitGOTSectionData(MemoryRegion& pRegion) const; 268 269 uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion, 270 const ELFFileFormat* FileFormat) const; 271 272 void setRelDynSize(); 273 void setRelPLTSize(); 274 275 private: 276 X86_32GOT* m_pGOT; 277 X86_32GOTPLT* m_pGOTPLT; 278 }; 279 280 // 281 //===----------------------------------------------------------------------===// 282 /// X86_64GNULDBackend - linker backend of X86-64 target of GNU ELF format 283 /// 284 class X86_64GNULDBackend : public X86GNULDBackend 285 { 286 public: 287 X86_64GNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo); 288 289 ~X86_64GNULDBackend(); 290 291 void initTargetSections(Module& pModule, ObjectBuilder& pBuilder); 292 293 X86_64GOT& getGOT(); 294 295 const X86_64GOT& getGOT() const; 296 297 X86_64GOTPLT& getGOTPLT(); 298 299 const X86_64GOTPLT& getGOTPLT() const; 300 301 private: 302 void scanLocalReloc(Relocation& pReloc, 303 IRBuilder& pBuilder, 304 Module& pModule, 305 LDSection& pSection); 306 307 void scanGlobalReloc(Relocation& pReloc, 308 IRBuilder& pBuilder, 309 Module& pModule, 310 LDSection& pSection); 311 312 /// initRelocator - create and initialize Relocator. 313 bool initRelocator(); 314 315 void setGOTSectionSize(IRBuilder& pBuilder); 316 317 uint64_t emitGOTSectionData(MemoryRegion& pRegion) const; 318 319 uint64_t emitGOTPLTSectionData(MemoryRegion& pRegion, 320 const ELFFileFormat* FileFormat) const; 321 322 void setRelDynSize(); 323 void setRelPLTSize(); 324 325 private: 326 X86_64GOT* m_pGOT; 327 X86_64GOTPLT* m_pGOTPLT; 328 }; 329 } // namespace of mcld 330 331 #endif 332 333