ARMLDBackend.h revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
1//===- ARMLDBackend.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 MCLD_ARM_LDBACKEND_H 10#define MCLD_ARM_LDBACKEND_H 11 12#include "ARMELFDynamic.h" 13#include "ARMGOT.h" 14#include "ARMPLT.h" 15#include <mcld/LD/LDSection.h> 16#include <mcld/Target/GNULDBackend.h> 17#include <mcld/Target/OutputRelocSection.h> 18 19namespace mcld { 20 21class LinkerConfig; 22class GNUInfo; 23class SectionMap; 24 25//===----------------------------------------------------------------------===// 26/// ARMGNULDBackend - linker backend of ARM target of GNU ELF format 27/// 28class ARMGNULDBackend : public GNULDBackend 29{ 30public: 31 // max branch offsets for ARM, THUMB, and THUMB2 32 // @ref gold/arm.cc:99 33 static const int32_t ARM_MAX_FWD_BRANCH_OFFSET = ((((1 << 23) - 1) << 2) + 8); 34 static const int32_t ARM_MAX_BWD_BRANCH_OFFSET = ((-((1 << 23) << 2)) + 8); 35 static const int32_t THM_MAX_FWD_BRANCH_OFFSET = ((1 << 22) -2 + 4); 36 static const int32_t THM_MAX_BWD_BRANCH_OFFSET = (-(1 << 22) + 4); 37 static const int32_t THM2_MAX_FWD_BRANCH_OFFSET = (((1 << 24) - 2) + 4); 38 static const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4); 39 40public: 41 ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo); 42 ~ARMGNULDBackend(); 43 44public: 45 typedef std::vector<llvm::ELF::Elf32_Dyn*> ELF32DynList; 46 47 /** \enum ReservedEntryType 48 * \brief The reserved entry type of reserved space in ResolveInfo. 49 * 50 * This is used for sacnRelocation to record what kinds of entries are 51 * reserved for this resolved symbol 52 * 53 * In ARM, there are three kinds of entries, GOT, PLT, and dynamic reloction. 54 * GOT may needs a corresponding relocation to relocate itself, so we 55 * separate GOT to two situations: GOT and GOTRel. Besides, for the same 56 * symbol, there might be two kinds of entries reserved for different location. 57 * For example, reference to the same symbol, one may use GOT and the other may 58 * use dynamic relocation. 59 * 60 * bit: 3 2 1 0 61 * | PLT | GOTRel | GOT | Rel | 62 * 63 * value Name - Description 64 * 65 * 0000 None - no reserved entry 66 * 0001 ReserveRel - reserve an dynamic relocation entry 67 * 0010 ReserveGOT - reserve an GOT entry 68 * 0011 GOTandRel - For different relocation, we've reserved GOT and 69 * Rel for different location. 70 * 0100 GOTRel - reserve an GOT entry and the corresponding Dyncamic 71 * relocation entry which relocate this GOT entry 72 * 0101 GOTRelandRel - For different relocation, we've reserved GOTRel 73 * and relocation entry for different location. 74 * 1000 ReservePLT - reserve an PLT entry and the corresponding GOT, 75 * Dynamic relocation entries 76 * 1001 PLTandRel - For different relocation, we've reserved PLT and 77 * Rel for different location. 78 */ 79 enum ReservedEntryType { 80 None = 0, 81 ReserveRel = 1, 82 ReserveGOT = 2, 83 GOTandRel = 3, 84 GOTRel = 4, 85 GOTRelandRel = 5, 86 ReservePLT = 8, 87 PLTandRel = 9 88 }; 89 90public: 91 /// initTargetSections - initialize target dependent sections in output. 92 void initTargetSections(Module& pModule, ObjectBuilder& pBuilder); 93 94 /// initTargetSymbols - initialize target dependent symbols in output. 95 void initTargetSymbols(IRBuilder& pBuilder, Module& pModule); 96 97 /// initRelocator - create and initialize Relocator. 98 bool initRelocator(); 99 100 /// getRelocator - return relocator. 101 Relocator* getRelocator(); 102 103 /// scanRelocation - determine the empty entries are needed or not and create 104 /// the empty entries if needed. 105 /// For ARM, following entries are check to create: 106 /// - GOT entry (for .got section) 107 /// - PLT entry (for .plt section) 108 /// - dynamin relocation entries (for .rel.plt and .rel.dyn sections) 109 void scanRelocation(Relocation& pReloc, 110 IRBuilder& pBuilder, 111 Module& pModule, 112 LDSection& pSection); 113 114 /// doPreLayout - Backend can do any needed modification before layout 115 void doPreLayout(IRBuilder& pBuilder); 116 117 /// doPostLayout -Backend can do any needed modification after layout 118 void doPostLayout(Module& pModule, IRBuilder& pBuilder); 119 120 /// dynamic - the dynamic section of the target machine. 121 /// Use co-variant return type to return its own dynamic section. 122 ARMELFDynamic& dynamic(); 123 124 /// dynamic - the dynamic section of the target machine. 125 /// Use co-variant return type to return its own dynamic section. 126 const ARMELFDynamic& dynamic() const; 127 128 129 /// emitSectionData - write out the section data into the memory region. 130 /// When writers get a LDSection whose kind is LDFileFormat::Target, writers 131 /// call back target backend to emit the data. 132 /// 133 /// Backends handle the target-special tables (plt, gp,...) by themselves. 134 /// Backend can put the data of the tables in SectionData directly 135 /// - LDSection.getSectionData can get the section data. 136 /// Or, backend can put the data into special data structure 137 /// - backend can maintain its own map<LDSection, table> to get the table 138 /// from given LDSection. 139 /// 140 /// @param pSection - the given LDSection 141 /// @param pConfig - all options in the command line. 142 /// @param pRegion - the region to write out data 143 /// @return the size of the table in the file. 144 uint64_t emitSectionData(const LDSection& pSection, 145 MemoryRegion& pRegion) const; 146 147 ARMGOT& getGOT(); 148 149 const ARMGOT& getGOT() const; 150 151 ARMPLT& getPLT(); 152 153 const ARMPLT& getPLT() const; 154 155 OutputRelocSection& getRelDyn(); 156 157 const OutputRelocSection& getRelDyn() const; 158 159 OutputRelocSection& getRelPLT(); 160 161 const OutputRelocSection& getRelPLT() const; 162 163 /// getTargetSectionOrder - compute the layout order of ARM target sections 164 unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const; 165 166 /// finalizeTargetSymbols - finalize the symbol value 167 bool finalizeTargetSymbols(); 168 169 /// mergeSection - merge target dependent sections 170 bool mergeSection(Module& pModule, LDSection& pSection); 171 172 /// readSection - read target dependent sections 173 bool readSection(Input& pInput, SectionData& pSD); 174 175private: 176 void scanLocalReloc(Relocation& pReloc, const LDSection& pSection); 177 178 void scanGlobalReloc(Relocation& pReloc, 179 IRBuilder& pBuilder, 180 const LDSection& pSection); 181 182 void checkValidReloc(Relocation& pReloc) const; 183 184 /// addCopyReloc - add a copy relocation into .rel.dyn for pSym 185 /// @param pSym - A resolved copy symbol that defined in BSS section 186 void addCopyReloc(ResolveInfo& pSym); 187 188 /// defineSymbolforCopyReloc - allocate a space in BSS section and 189 /// and force define the copy of pSym to BSS section 190 /// @return the output LDSymbol of the copy symbol 191 LDSymbol& defineSymbolforCopyReloc(IRBuilder& pLinker, 192 const ResolveInfo& pSym); 193 194 void defineGOTSymbol(IRBuilder& pBuilder); 195 196 /// maxBranchOffset 197 /// FIXME: if we can handle arm attributes, we may refine this! 198 uint64_t maxBranchOffset() { return THM_MAX_FWD_BRANCH_OFFSET; } 199 200 /// mayRelax - Backends should override this function if they need relaxation 201 bool mayRelax() { return true; } 202 203 /// doRelax - Backend can orevride this function to add its relaxation 204 /// implementation. Return true if the output (e.g., .text) is "relaxed" 205 /// (i.e. layout is changed), and set pFinished to true if everything is fit, 206 /// otherwise set it to false. 207 bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished); 208 209 /// initTargetStubs 210 bool initTargetStubs(); 211 212 /// getRelEntrySize - the size in BYTE of rel type relocation 213 size_t getRelEntrySize() 214 { return 8; } 215 216 /// getRelEntrySize - the size in BYTE of rela type relocation 217 size_t getRelaEntrySize() 218 { assert(0 && "ARM backend with Rela type relocation\n"); return 12; } 219 220 /// doCreateProgramHdrs - backend can implement this function to create the 221 /// target-dependent segments 222 virtual void doCreateProgramHdrs(Module& pModule); 223 224private: 225 Relocator* m_pRelocator; 226 227 ARMGOT* m_pGOT; 228 ARMPLT* m_pPLT; 229 /// m_RelDyn - dynamic relocation table of .rel.dyn 230 OutputRelocSection* m_pRelDyn; 231 /// m_RelPLT - dynamic relocation table of .rel.plt 232 OutputRelocSection* m_pRelPLT; 233 234 ARMELFDynamic* m_pDynamic; 235 LDSymbol* m_pGOTSymbol; 236 LDSymbol* m_pEXIDXStart; 237 LDSymbol* m_pEXIDXEnd; 238 239 // variable name : ELF 240 LDSection* m_pEXIDX; // .ARM.exidx 241 LDSection* m_pEXTAB; // .ARM.extab 242 LDSection* m_pAttributes; // .ARM.attributes 243// LDSection* m_pPreemptMap; // .ARM.preemptmap 244// LDSection* m_pDebugOverlay; // .ARM.debug_overlay 245// LDSection* m_pOverlayTable; // .ARM.overlay_table 246}; 247} // namespace of mcld 248 249#endif 250 251