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