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