1 //===- MipsLDBackend.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_MIPSLDBACKEND_H_ 10 #define TARGET_MIPS_MIPSLDBACKEND_H_ 11 #include <llvm/Support/ELF.h> 12 #include "mcld/Target/GNULDBackend.h" 13 #include "MipsAbiFlags.h" 14 #include "MipsELFDynamic.h" 15 #include "MipsGOT.h" 16 #include "MipsGOTPLT.h" 17 #include "MipsPLT.h" 18 19 namespace mcld { 20 21 class LinkerConfig; 22 class MemoryArea; 23 class MipsGNUInfo; 24 class OutputRelocSection; 25 class SectionMap; 26 27 /** \class MipsGNULDBackend 28 * \brief Base linker backend of Mips target of GNU ELF format. 29 */ 30 class MipsGNULDBackend : public GNULDBackend { 31 public: 32 typedef std::vector<LDSymbol*> SymbolListType; 33 34 public: 35 MipsGNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo); 36 ~MipsGNULDBackend(); 37 38 bool needsLA25Stub(Relocation::Type pType, const mcld::ResolveInfo* pSym); 39 40 void addNonPICBranchSym(ResolveInfo* rsym); 41 bool hasNonPICBranch(const ResolveInfo* rsym) const; 42 43 public: 44 /// initTargetSections - initialize target dependent sections in output 45 void initTargetSections(Module& pModule, ObjectBuilder& pBuilder); 46 47 /// initTargetSymbols - initialize target dependent symbols in output. 48 void initTargetSymbols(IRBuilder& pBuilder, Module& pModule); 49 50 /// getRelocator - return relocator. 51 const Relocator* getRelocator() const; 52 Relocator* getRelocator(); 53 54 /// preLayout - Backend can do any needed modification before layout 55 void doPreLayout(IRBuilder& pBuilder); 56 57 /// postLayout - Backend can do any needed modification after layout 58 void doPostLayout(Module& pModule, IRBuilder& pBuilder); 59 60 /// dynamic - the dynamic section of the target machine. 61 /// Use co-variant return type to return its own dynamic section. 62 MipsELFDynamic& dynamic(); 63 64 /// dynamic - the dynamic section of the target machine. 65 /// Use co-variant return type to return its own dynamic section. 66 const MipsELFDynamic& dynamic() const; 67 68 /// emitSectionData - write out the section data into the memory region. 69 /// When writers get a LDSection whose kind is LDFileFormat::Target, writers 70 /// call back target backend to emit the data. 71 /// 72 /// Backends handle the target-special tables (plt, gp,...) by themselves. 73 /// Backend can put the data of the tables in SectionData directly 74 /// - LDSection.getSectionData can get the section data. 75 /// Or, backend can put the data into special data structure 76 /// - backend can maintain its own map<LDSection, table> to get the table 77 /// from given LDSection. 78 /// 79 /// @param pSection - the given LDSection 80 /// @param pRegion - the region to write out data 81 /// @return the size of the table in the file. 82 uint64_t emitSectionData(const LDSection& pSection, 83 MemoryRegion& pRegion) const; 84 85 /// hasEntryInStrTab - symbol has an entry in a .strtab 86 bool hasEntryInStrTab(const LDSymbol& pSym) const; 87 88 /// orderSymbolTable - order symbol table before emitting 89 void orderSymbolTable(Module& pModule); 90 91 /// readSection - read a target dependent section. 92 bool readSection(Input& pInput, SectionData& pSD); 93 94 MipsGOT& getGOT(); 95 const MipsGOT& getGOT() const; 96 97 MipsPLT& getPLT(); 98 const MipsPLT& getPLT() const; 99 100 MipsGOTPLT& getGOTPLT(); 101 const MipsGOTPLT& getGOTPLT() const; 102 103 OutputRelocSection& getRelPLT(); 104 const OutputRelocSection& getRelPLT() const; 105 106 OutputRelocSection& getRelDyn(); 107 const OutputRelocSection& getRelDyn() const; 108 getGOTSymbol()109 LDSymbol* getGOTSymbol() { return m_pGOTSymbol; } getGOTSymbol()110 const LDSymbol* getGOTSymbol() const { return m_pGOTSymbol; } 111 getGpDispSymbol()112 LDSymbol* getGpDispSymbol() { return m_pGpDispSymbol; } getGpDispSymbol()113 const LDSymbol* getGpDispSymbol() const { return m_pGpDispSymbol; } 114 getGlobalGOTSyms()115 SymbolListType& getGlobalGOTSyms() { return m_GlobalGOTSyms; } getGlobalGOTSyms()116 const SymbolListType& getGlobalGOTSyms() const { return m_GlobalGOTSyms; } 117 118 /// getTargetSectionOrder - compute the layout order of ARM target sections 119 unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const; 120 121 /// finalizeSymbol - finalize the symbol value 122 bool finalizeTargetSymbols(); 123 124 /// allocateCommonSymbols - allocate common symbols in the corresponding 125 /// sections. 126 bool allocateCommonSymbols(Module& pModule); 127 128 /// getTPOffset - return TP_OFFSET against the SHF_TLS 129 /// section in the specified input. 130 uint64_t getTPOffset(const Input& pInput) const; 131 132 /// getDTPOffset - return DTP_OFFSET against the SHF_TLS 133 /// section in the specified input. 134 uint64_t getDTPOffset(const Input& pInput) const; 135 136 /// getGP0 - the gp value used to create the relocatable objects 137 /// in the specified input. 138 uint64_t getGP0(const Input& pInput) const; 139 140 private: 141 void defineGOTSymbol(IRBuilder& pBuilder); 142 void defineGOTPLTSymbol(IRBuilder& pBuilder); 143 144 bool relaxRelocation(IRBuilder& pBuilder, Relocation& pRel); 145 146 /// emitSymbol32 - emit an ELF32 symbol, override parent's function 147 void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32, 148 LDSymbol& pSymbol, 149 char* pStrtab, 150 size_t pStrtabsize, 151 size_t pSymtabIdx); 152 153 /// doCreateProgramHdrs - backend can implement this function to create the 154 /// target-dependent segments 155 void doCreateProgramHdrs(Module& pModule); 156 157 /// mayRelax - Backends should override this function if they need relaxation mayRelax()158 bool mayRelax() { return true; } 159 160 /// doRelax - Backend can orevride this function to add its relaxation 161 /// implementation. Return true if the output (e.g., .text) is "relaxed" 162 /// (i.e. layout is changed), and set pFinished to true if everything is fit, 163 /// otherwise set it to false. 164 bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished); 165 166 /// initTargetStubs 167 bool initTargetStubs(); 168 169 /// readRelocation - read ELF32_Rel entry 170 bool readRelocation(const llvm::ELF::Elf32_Rel& pRel, 171 Relocation::Type& pType, 172 uint32_t& pSymIdx, 173 uint32_t& pOffset) const; 174 175 /// readRelocation - read ELF32_Rela entry 176 bool readRelocation(const llvm::ELF::Elf32_Rela& pRel, 177 Relocation::Type& pType, 178 uint32_t& pSymIdx, 179 uint32_t& pOffset, 180 int32_t& pAddend) const; 181 182 /// readRelocation - read ELF64_Rel entry 183 bool readRelocation(const llvm::ELF::Elf64_Rel& pRel, 184 Relocation::Type& pType, 185 uint32_t& pSymIdx, 186 uint64_t& pOffset) const; 187 188 /// readRel - read ELF64_Rela entry 189 bool readRelocation(const llvm::ELF::Elf64_Rela& pRel, 190 Relocation::Type& pType, 191 uint32_t& pSymIdx, 192 uint64_t& pOffset, 193 int64_t& pAddend) const; 194 195 /// emitRelocation - write data to the ELF32_Rel entry 196 void emitRelocation(llvm::ELF::Elf32_Rel& pRel, 197 Relocation::Type pType, 198 uint32_t pSymIdx, 199 uint32_t pOffset) const; 200 201 /// emitRelocation - write data to the ELF32_Rela entry 202 void emitRelocation(llvm::ELF::Elf32_Rela& pRel, 203 Relocation::Type pType, 204 uint32_t pSymIdx, 205 uint32_t pOffset, 206 int32_t pAddend) const; 207 208 /// emitRelocation - write data to the ELF64_Rel entry 209 void emitRelocation(llvm::ELF::Elf64_Rel& pRel, 210 Relocation::Type pType, 211 uint32_t pSymIdx, 212 uint64_t pOffset) const; 213 214 /// emitRelocation - write data to the ELF64_Rela entry 215 void emitRelocation(llvm::ELF::Elf64_Rela& pRel, 216 Relocation::Type pType, 217 uint32_t pSymIdx, 218 uint64_t pOffset, 219 int64_t pAddend) const; 220 221 /// preMergeSections - hooks to be executed before merging sections 222 void preMergeSections(Module& pModule); 223 224 /// mergeSection - merge target dependent sections 225 bool mergeSection(Module& pModule, const Input& pInput, LDSection& pSection); 226 227 protected: 228 virtual void mergeFlags(Input& pInput, const char* ELF_hdr); 229 230 private: 231 typedef llvm::DenseSet<const ResolveInfo*> ResolveInfoSetType; 232 typedef llvm::DenseMap<const Input*, llvm::ELF::Elf64_Addr> InputNumMapType; 233 typedef llvm::DenseMap<const Input*, uint64_t> ElfFlagsMapType; 234 235 protected: 236 Relocator* m_pRelocator; 237 MipsGOT* m_pGOT; // .got 238 MipsPLT* m_pPLT; // .plt 239 MipsGOTPLT* m_pGOTPLT; // .got.plt 240 241 private: 242 MipsGNUInfo& m_pInfo; 243 llvm::Optional<MipsAbiFlags> m_pAbiInfo; 244 245 OutputRelocSection* m_pRelPlt; // .rel.plt 246 OutputRelocSection* m_pRelDyn; // .rel.dyn 247 248 MipsELFDynamic* m_pDynamic; 249 LDSection* m_psdata; 250 LDSection* m_pAbiFlags; 251 LDSymbol* m_pGOTSymbol; 252 LDSymbol* m_pPLTSymbol; 253 LDSymbol* m_pGpDispSymbol; 254 255 SymbolListType m_GlobalGOTSyms; 256 ResolveInfoSetType m_HasNonPICBranchSyms; 257 InputNumMapType m_GP0Map; 258 InputNumMapType m_TpOffsetMap; 259 InputNumMapType m_DtpOffsetMap; 260 ElfFlagsMapType m_ElfFlagsMap; 261 262 void moveSectionData(SectionData& pFrom, SectionData& pTo); 263 void saveTPOffset(const Input& pInput); 264 }; 265 266 /** \class Mips32GNULDBackend 267 * \brief Base linker backend of Mips 32-bit target of GNU ELF format. 268 */ 269 class Mips32GNULDBackend : public MipsGNULDBackend { 270 public: 271 Mips32GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo); 272 273 private: 274 // MipsGNULDBackend 275 276 bool initRelocator(); 277 void initTargetSections(Module& pModule, ObjectBuilder& pBuilder); 278 size_t getRelEntrySize(); 279 size_t getRelaEntrySize(); 280 }; 281 282 /** \class Mips64GNULDBackend 283 * \brief Base linker backend of Mips 64-bit target of GNU ELF format. 284 */ 285 class Mips64GNULDBackend : public MipsGNULDBackend { 286 public: 287 Mips64GNULDBackend(const LinkerConfig& pConfig, MipsGNUInfo* pInfo); 288 289 private: 290 // MipsGNULDBackend 291 292 bool initRelocator(); 293 void initTargetSections(Module& pModule, ObjectBuilder& pBuilder); 294 size_t getRelEntrySize(); 295 size_t getRelaEntrySize(); 296 }; 297 298 } // namespace mcld 299 300 #endif // TARGET_MIPS_MIPSLDBACKEND_H_ 301