ARMLDBackend.h revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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 FragmentLinker; 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); 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(FragmentLinker& pLinker); 96 97 /// initRelocFactory - create and initialize RelocationFactory 98 bool initRelocFactory(const FragmentLinker& pLinker); 99 100 /// getRelocFactory 101 RelocationFactory* getRelocFactory(); 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 FragmentLinker& pLinker, 111 Module& pModule, 112 const LDSection& pSection); 113 114 uint32_t machine() const 115 { return llvm::ELF::EM_ARM; } 116 117 /// OSABI - the value of e_ident[EI_OSABI] 118 virtual uint8_t OSABI() const 119 { return llvm::ELF::ELFOSABI_NONE; } 120 121 /// ABIVersion - the value of e_ident[EI_ABIVRESION] 122 virtual uint8_t ABIVersion() const 123 { return 0x0; } 124 125 /// flags - the value of ElfXX_Ehdr::e_flags 126 virtual uint64_t flags() const 127 { return (llvm::ELF::EF_ARM_EABIMASK & 0x05000000); } 128 129 bool isLittleEndian() const 130 { return true; } 131 132 unsigned int bitclass() const 133 { return 32; } 134 135 uint64_t defaultTextSegmentAddr() const 136 { return 0x8000; } 137 138 /// doPreLayout - Backend can do any needed modification before layout 139 void doPreLayout(FragmentLinker& pLinker); 140 141 /// doPostLayout -Backend can do any needed modification after layout 142 void doPostLayout(Module& pModule, FragmentLinker& pLinker); 143 144 /// dynamic - the dynamic section of the target machine. 145 /// Use co-variant return type to return its own dynamic section. 146 ARMELFDynamic& dynamic(); 147 148 /// dynamic - the dynamic section of the target machine. 149 /// Use co-variant return type to return its own dynamic section. 150 const ARMELFDynamic& dynamic() const; 151 152 153 /// emitSectionData - write out the section data into the memory region. 154 /// When writers get a LDSection whose kind is LDFileFormat::Target, writers 155 /// call back target backend to emit the data. 156 /// 157 /// Backends handle the target-special tables (plt, gp,...) by themselves. 158 /// Backend can put the data of the tables in SectionData directly 159 /// - LDSection.getSectionData can get the section data. 160 /// Or, backend can put the data into special data structure 161 /// - backend can maintain its own map<LDSection, table> to get the table 162 /// from given LDSection. 163 /// 164 /// @param pSection - the given LDSection 165 /// @param pConfig - all options in the command line. 166 /// @param pRegion - the region to write out data 167 /// @return the size of the table in the file. 168 uint64_t emitSectionData(const LDSection& pSection, 169 MemoryRegion& pRegion) const; 170 171 ARMGOT& getGOT(); 172 173 const ARMGOT& getGOT() const; 174 175 ARMPLT& getPLT(); 176 177 const ARMPLT& getPLT() const; 178 179 OutputRelocSection& getRelDyn(); 180 181 const OutputRelocSection& getRelDyn() const; 182 183 OutputRelocSection& getRelPLT(); 184 185 const OutputRelocSection& getRelPLT() const; 186 187 /// getTargetSectionOrder - compute the layout order of ARM target sections 188 unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const; 189 190 /// finalizeTargetSymbols - finalize the symbol value 191 bool finalizeTargetSymbols(FragmentLinker& pLinker); 192 193 /// mergeSection - merge target dependent sections 194 bool mergeSection(Module& pModule, LDSection& pSection); 195 196 /// readSection - read target dependent sections 197 bool readSection(Input& pInput, SectionData& pSD); 198 199private: 200 void scanLocalReloc(Relocation& pReloc, FragmentLinker& pLinker); 201 202 void scanGlobalReloc(Relocation& pReloc, FragmentLinker& pLinker); 203 204 void checkValidReloc(Relocation& pReloc, 205 const FragmentLinker& pLinker) const; 206 207 /// addCopyReloc - add a copy relocation into .rel.dyn for pSym 208 /// @param pSym - A resolved copy symbol that defined in BSS section 209 void addCopyReloc(ResolveInfo& pSym); 210 211 /// defineSymbolforCopyReloc - allocate a space in BSS section and 212 /// and force define the copy of pSym to BSS section 213 /// @return the output LDSymbol of the copy symbol 214 LDSymbol& defineSymbolforCopyReloc(FragmentLinker& pLinker, 215 const ResolveInfo& pSym); 216 217 void defineGOTSymbol(FragmentLinker& pLinker); 218 219 /// maxBranchOffset 220 /// FIXME: if we can handle arm attributes, we may refine this! 221 uint64_t maxBranchOffset() { return THM_MAX_FWD_BRANCH_OFFSET; } 222 223 /// mayRelax - Backends should override this function if they need relaxation 224 bool mayRelax() { return true; } 225 226 /// doRelax - Backend can orevride this function to add its relaxation 227 /// implementation. Return true if the output (e.g., .text) is "relaxed" 228 /// (i.e. layout is changed), and set pFinished to true if everything is fit, 229 /// otherwise set it to false. 230 bool doRelax(Module& pModule, FragmentLinker& pLinker, bool& pFinished); 231 232 /// initTargetStubs 233 bool initTargetStubs(FragmentLinker& pLinker); 234 235 /// getRelEntrySize - the size in BYTE of rel type relocation 236 size_t getRelEntrySize() 237 { return 8; } 238 239 /// getRelEntrySize - the size in BYTE of rela type relocation 240 size_t getRelaEntrySize() 241 { assert(0 && "ARM backend with Rela type relocation\n"); return 12; } 242 243 /// doCreateProgramHdrs - backend can implement this function to create the 244 /// target-dependent segments 245 virtual void doCreateProgramHdrs(Module& pModule, 246 const FragmentLinker& pLinker); 247 248private: 249 RelocationFactory* m_pRelocFactory; 250 ARMGOT* m_pGOT; 251 ARMPLT* m_pPLT; 252 /// m_RelDyn - dynamic relocation table of .rel.dyn 253 OutputRelocSection* m_pRelDyn; 254 /// m_RelPLT - dynamic relocation table of .rel.plt 255 OutputRelocSection* m_pRelPLT; 256 257 ARMELFDynamic* m_pDynamic; 258 LDSymbol* m_pGOTSymbol; 259 LDSymbol* m_pEXIDXStart; 260 LDSymbol* m_pEXIDXEnd; 261 262 // variable name : ELF 263 LDSection* m_pEXIDX; // .ARM.exidx 264 LDSection* m_pEXTAB; // .ARM.extab 265 LDSection* m_pAttributes; // .ARM.attributes 266// LDSection* m_pPreemptMap; // .ARM.preemptmap 267// LDSection* m_pDebugOverlay; // .ARM.debug_overlay 268// LDSection* m_pOverlayTable; // .ARM.overlay_table 269}; 270 271//===----------------------------------------------------------------------===// 272/// ARMMachOLDBackend - linker backend of ARM target of MachO format 273/// 274/** 275class ARMMachOLDBackend : public DarwinARMLDBackend 276{ 277public: 278 ARMMachOLDBackend(); 279 ~ARMMachOLDBackend(); 280 281private: 282 MCMachOTargetArchiveReader *createTargetArchiveReader() const; 283 MCMachOTargetObjectReader *createTargetObjectReader() const; 284 MCMachOTargetObjectWriter *createTargetObjectWriter() const; 285 286}; 287**/ 288} // namespace of mcld 289 290#endif 291 292