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 TARGET_ARM_ARMLDBACKEND_H_ 10 #define TARGET_ARM_ARMLDBACKEND_H_ 11 12 #include "ARMELFDynamic.h" 13 #include "ARMException.h" 14 #include "ARMGOT.h" 15 #include "ARMPLT.h" 16 #include "mcld/LD/LDSection.h" 17 #include "mcld/Target/GNULDBackend.h" 18 #include "mcld/Target/OutputRelocSection.h" 19 20 #include <memory> 21 22 namespace mcld { 23 24 class ARMELFAttributeData; 25 class GNUInfo; 26 class LinkerConfig; 27 28 //===----------------------------------------------------------------------===// 29 /// ARMGNULDBackend - linker backend of ARM target of GNU ELF format 30 /// 31 class ARMGNULDBackend : public GNULDBackend { 32 public: 33 // max branch offsets for ARM, THUMB, and THUMB2 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 41 public: 42 ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo); 43 ~ARMGNULDBackend(); 44 45 public: 46 typedef std::vector<llvm::ELF::Elf32_Dyn*> ELF32DynList; 47 48 public: 49 /// initTargetSections - initialize target dependent sections in output. 50 void initTargetSections(Module& pModule, ObjectBuilder& pBuilder); 51 52 /// initTargetSymbols - initialize target dependent symbols in output. 53 void initTargetSymbols(IRBuilder& pBuilder, Module& pModule); 54 55 /// initRelocator - create and initialize Relocator. 56 bool initRelocator(); 57 58 /// getRelocator - return relocator. 59 const Relocator* getRelocator() const; 60 Relocator* getRelocator(); 61 62 /// doPreLayout - Backend can do any needed modification before layout 63 void doPreLayout(IRBuilder& pBuilder); 64 65 /// doPostLayout -Backend can do any needed modification after layout 66 void doPostLayout(Module& pModule, IRBuilder& pBuilder); 67 68 /// dynamic - the dynamic section of the target machine. 69 /// Use co-variant return type to return its own dynamic section. 70 ARMELFDynamic& dynamic(); 71 72 /// dynamic - the dynamic section of the target machine. 73 /// Use co-variant return type to return its own dynamic section. 74 const ARMELFDynamic& dynamic() const; 75 76 /// emitSectionData - write out the section data into the memory region. 77 /// When writers get a LDSection whose kind is LDFileFormat::Target, writers 78 /// call back target backend to emit the data. 79 /// 80 /// Backends handle the target-special tables (plt, gp,...) by themselves. 81 /// Backend can put the data of the tables in SectionData directly 82 /// - LDSection.getSectionData can get the section data. 83 /// Or, backend can put the data into special data structure 84 /// - backend can maintain its own map<LDSection, table> to get the table 85 /// from given LDSection. 86 /// 87 /// @param pSection - the given LDSection 88 /// @param pConfig - all options in the command line. 89 /// @param pRegion - the region to write out data 90 /// @return the size of the table in the file. 91 uint64_t emitSectionData(const LDSection& pSection, 92 MemoryRegion& pRegion) const; 93 94 ARMGOT& getGOT(); 95 const ARMGOT& getGOT() const; 96 97 ARMPLT& getPLT(); 98 const ARMPLT& getPLT() const; 99 100 OutputRelocSection& getRelDyn(); 101 const OutputRelocSection& getRelDyn() const; 102 103 OutputRelocSection& getRelPLT(); 104 const OutputRelocSection& getRelPLT() const; 105 106 ARMELFAttributeData& getAttributeData(); 107 const ARMELFAttributeData& getAttributeData() const; 108 getGOTSymbol()109 LDSymbol* getGOTSymbol() { return m_pGOTSymbol; } getGOTSymbol()110 const LDSymbol* getGOTSymbol() const { return m_pGOTSymbol; } 111 112 /// getTargetSectionOrder - compute the layout order of ARM target sections 113 unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const; 114 115 /// finalizeTargetSymbols - finalize the symbol value 116 bool finalizeTargetSymbols(); 117 118 /// preMergeSections - hooks to be executed before merging sections 119 virtual void preMergeSections(Module& pModule); 120 121 /// postMergeSections - hooks to be executed after merging sections 122 virtual void postMergeSections(Module& pModule); 123 124 /// mergeSection - merge target dependent sections 125 bool mergeSection(Module& pModule, const Input& pInput, LDSection& pSection); 126 127 /// setUpReachedSectionsForGC - set the reference from section XXX to 128 /// .ARM.exidx.XXX to make sure GC correctly handle section exidx 129 void setUpReachedSectionsForGC( 130 const Module& pModule, 131 GarbageCollection::SectionReachedListMap& pSectReachedListMap) const; 132 133 /// readSection - read target dependent sections 134 bool readSection(Input& pInput, SectionData& pSD); 135 136 /// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe 137 /// function pointer access 138 bool mayHaveUnsafeFunctionPointerAccess(const LDSection& pSection) const; 139 140 private: 141 void defineGOTSymbol(IRBuilder& pBuilder); 142 143 /// maxFwdBranchOffset 144 int64_t maxFwdBranchOffset() const; 145 /// maxBwdBranchOffset 146 int64_t maxBwdBranchOffset() const; 147 148 /// mayRelax - Backends should override this function if they need relaxation mayRelax()149 bool mayRelax() { return true; } 150 151 /// relax - the relaxation pass 152 virtual bool relax(Module& pModule, IRBuilder& pBuilder); 153 154 /// doRelax - Backend can orevride this function to add its relaxation 155 /// implementation. Return true if the output (e.g., .text) is "relaxed" 156 /// (i.e. layout is changed), and set pFinished to true if everything is fit, 157 /// otherwise set it to false. 158 bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished); 159 160 /// initTargetStubs 161 bool initTargetStubs(); 162 163 /// getRelEntrySize - the size in BYTE of rel type relocation getRelEntrySize()164 size_t getRelEntrySize() { return 8; } 165 166 /// getRelEntrySize - the size in BYTE of rela type relocation getRelaEntrySize()167 size_t getRelaEntrySize() { 168 assert(0 && "ARM backend with Rela type relocation\n"); 169 return 12; 170 } 171 172 /// doCreateProgramHdrs - backend can implement this function to create the 173 /// target-dependent segments 174 virtual void doCreateProgramHdrs(Module& pModule); 175 176 /// rewriteExceptionSection - rewrite the output .ARM.exidx section. 177 void rewriteARMExIdxSection(Module& pModule); 178 179 private: 180 Relocator* m_pRelocator; 181 182 ARMGOT* m_pGOT; 183 ARMPLT* m_pPLT; 184 /// m_RelDyn - dynamic relocation table of .rel.dyn 185 OutputRelocSection* m_pRelDyn; 186 /// m_RelPLT - dynamic relocation table of .rel.plt 187 OutputRelocSection* m_pRelPLT; 188 189 /// m_pAttrData - attribute data in public ("aeabi") attribute subsection 190 ARMELFAttributeData* m_pAttrData; 191 192 ARMELFDynamic* m_pDynamic; 193 LDSymbol* m_pGOTSymbol; 194 LDSymbol* m_pEXIDXStart; 195 LDSymbol* m_pEXIDXEnd; 196 197 // variable name : ELF 198 LDSection* m_pEXIDX; // .ARM.exidx 199 LDSection* m_pEXTAB; // .ARM.extab 200 LDSection* m_pAttributes; // .ARM.attributes 201 // LDSection* m_pPreemptMap; // .ARM.preemptmap 202 // LDSection* m_pDebugOverlay; // .ARM.debug_overlay 203 // LDSection* m_pOverlayTable; // .ARM.overlay_table 204 205 // m_pExData - exception handling section data structures 206 std::unique_ptr<ARMExData> m_pExData; 207 }; 208 209 } // namespace mcld 210 211 #endif // TARGET_ARM_ARMLDBACKEND_H_ 212