AArch64RelocationHelpers.h revision 551ae4ebd3e9d137ea668fb83ae4a55b8cfba451
1//===- AArch64RelocationHelpers.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_AARCH64_AARCH64RELOCATIONHELPERS_H 10#define TARGET_AARCH64_AARCH64RELOCATIONHELPERS_H 11 12#include "AArch64Relocator.h" 13#include <llvm/Support/Host.h> 14 15namespace mcld { 16//===----------------------------------------------------------------------===// 17// Relocation helper functions 18//===----------------------------------------------------------------------===// 19// Return true if overflow 20static inline bool 21helper_check_signed_overflow(Relocator::DWord pValue, unsigned bits) 22{ 23 if (bits >= sizeof(int64_t) * 8) 24 return false; 25 int64_t signed_val = static_cast<int64_t>(pValue); 26 int64_t max = (1 << (bits - 1)) - 1; 27 int64_t min = -(1 << (bits - 1)); 28 if (signed_val > max || signed_val < min) 29 return true; 30 return false; 31} 32 33static inline Relocator::Address 34helper_get_page_address(Relocator::Address pValue) 35{ 36 return (pValue & ~ (Relocator::Address) 0xFFF); 37} 38 39static inline Relocator::Address 40helper_get_page_offset(Relocator::Address pValue) 41{ 42 return (pValue & (Relocator::Address) 0xFFF); 43} 44 45static inline uint32_t get_mask(uint32_t pValue) 46{ 47 return ((1u << (pValue)) - 1); 48} 49 50static inline uint32_t 51helper_reencode_adr_imm(uint32_t pInst, uint32_t pImm) 52{ 53 return (pInst & ~((get_mask(2) << 29) | (get_mask(19) << 5))) 54 | ((pImm & get_mask(2)) << 29) | ((pImm & (get_mask(19) << 2)) << 3); 55} 56 57// Reencode the imm field of add immediate. 58static inline uint32_t helper_reencode_add_imm(uint32_t pInst, uint32_t pImm) 59{ 60 return (pInst & ~(get_mask(12) << 10)) | ((pImm & get_mask(12)) << 10); 61} 62 63// Encode the 26-bit offset of unconditional branch. 64static inline uint32_t 65helper_reencode_branch_offset_26(uint32_t pInst, uint32_t pOff) 66{ 67 return (pInst & ~get_mask(26)) | (pOff & get_mask(26)); 68} 69 70// Encode the 19-bit offset of conditional branch and compare & branch. 71static inline uint32_t 72helper_reencode_cond_branch_ofs_19(uint32_t pInst, uint32_t pOff) 73{ 74 return (pInst & ~(get_mask(19) << 5)) | ((pOff & get_mask(19)) << 5); 75} 76 77// Reencode the imm field of ld/st pos immediate. 78static inline uint32_t 79helper_reencode_ldst_pos_imm (uint32_t pInst, uint32_t pImm) 80{ 81 return (pInst & ~(get_mask(12) << 10)) | ((pImm & get_mask(12)) << 10); 82} 83 84static inline uint32_t helper_get_upper32(Relocator::DWord pData) 85{ 86 if (llvm::sys::IsLittleEndianHost) 87 return pData >> 32; 88 return pData & 0xFFFFFFFF; 89} 90 91static inline void helper_put_upper32(uint32_t pData, Relocator::DWord& pDes) 92{ 93 *(reinterpret_cast<uint32_t*>(&pDes)) = pData; 94} 95 96static inline Relocator::Address 97helper_get_PLT_address(ResolveInfo& pSym, AArch64Relocator& pParent) 98{ 99 PLTEntryBase* plt_entry = pParent.getSymPLTMap().lookUp(pSym); 100 assert(NULL != plt_entry); 101 return pParent.getTarget().getPLT().addr() + plt_entry->getOffset(); 102} 103 104static inline AArch64PLT1& 105helper_PLT_init(Relocation& pReloc, AArch64Relocator& pParent) 106{ 107 // rsym - The relocation target symbol 108 ResolveInfo* rsym = pReloc.symInfo(); 109 AArch64GNULDBackend& ld_backend = pParent.getTarget(); 110 assert(NULL == pParent.getSymPLTMap().lookUp(*rsym)); 111 112 AArch64PLT1* plt_entry = ld_backend.getPLT().create(); 113 pParent.getSymPLTMap().record(*rsym, *plt_entry); 114 115 // initialize plt and the corresponding gotplt and dyn rel entry. 116 assert(NULL == pParent.getSymGOTPLTMap().lookUp(*rsym) && 117 "PLT entry not exist, but DynRel entry exist!"); 118 AArch64GOTEntry* gotplt_entry = ld_backend.getGOTPLT().createGOTPLT(); 119 pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry); 120 121 // init the corresponding rel entry in .rela.plt 122 Relocation& rel_entry = *ld_backend.getRelaPLT().create(); 123 rel_entry.setType(R_AARCH64_JUMP_SLOT); 124 rel_entry.targetRef().assign(*gotplt_entry); 125 rel_entry.setSymInfo(rsym); 126 return *plt_entry; 127} 128 129/// helper_DynRel - Get an relocation entry in .rela.dyn 130static inline Relocation& 131helper_DynRela_init(ResolveInfo* pSym, 132 Fragment& pFrag, 133 uint64_t pOffset, 134 Relocator::Type pType, 135 AArch64Relocator& pParent) 136{ 137 AArch64GNULDBackend& ld_backend = pParent.getTarget(); 138 Relocation& rel_entry = *ld_backend.getRelaDyn().create(); 139 rel_entry.setType(pType); 140 rel_entry.targetRef().assign(pFrag, pOffset); 141 if (pType == R_AARCH64_RELATIVE || NULL == pSym) 142 rel_entry.setSymInfo(NULL); 143 else 144 rel_entry.setSymInfo(pSym); 145 146 return rel_entry; 147} 148 149/// helper_use_relative_reloc - Check if symbol can use relocation 150/// R_AARCH64_RELATIVE 151static inline bool 152helper_use_relative_reloc(const ResolveInfo& pSym, 153 const AArch64Relocator& pParent) 154 155{ 156 // if symbol is dynamic or undefine or preemptible 157 if (pSym.isDyn() || 158 pSym.isUndef() || 159 pParent.getTarget().isSymbolPreemptible(pSym)) 160 return false; 161 return true; 162} 163 164static inline Relocator::Address 165helper_get_GOT_address(ResolveInfo& pSym, AArch64Relocator& pParent) 166{ 167 AArch64GOTEntry* got_entry = pParent.getSymGOTMap().lookUp(pSym); 168 assert(NULL != got_entry); 169 return pParent.getTarget().getGOT().addr() + got_entry->getOffset(); 170} 171 172static inline Relocator::Address 173helper_GOT_ORG(AArch64Relocator& pParent) 174{ 175 return pParent.getTarget().getGOT().addr(); 176} 177 178static inline AArch64GOTEntry& 179helper_GOT_init(Relocation& pReloc, bool pHasRel, AArch64Relocator& pParent) 180{ 181 // rsym - The relocation target symbol 182 ResolveInfo* rsym = pReloc.symInfo(); 183 AArch64GNULDBackend& ld_backend = pParent.getTarget(); 184 assert(NULL == pParent.getSymGOTMap().lookUp(*rsym)); 185 186 AArch64GOTEntry* got_entry = ld_backend.getGOT().createGOT(); 187 pParent.getSymGOTMap().record(*rsym, *got_entry); 188 189 // If we first get this GOT entry, we should initialize it. 190 if (!pHasRel) { 191 // No corresponding dynamic relocation, initialize to the symbol value. 192 got_entry->setValue(AArch64Relocator::SymVal); 193 } 194 else { 195 // Initialize got_entry content and the corresponding dynamic relocation. 196 if (helper_use_relative_reloc(*rsym, pParent)) { 197 got_entry->setValue(AArch64Relocator::SymVal); 198 Relocation& rel_entry = helper_DynRela_init(rsym, *got_entry, 0x0, 199 R_AARCH64_RELATIVE, pParent); 200 rel_entry.setAddend(AArch64Relocator::SymVal); 201 pParent.getRelRelMap().record(pReloc, rel_entry); 202 } 203 else { 204 helper_DynRela_init(rsym, *got_entry, 0x0, R_AARCH64_GLOB_DAT, pParent); 205 got_entry->setValue(0); 206 } 207 } 208 return *got_entry; 209} 210 211} 212#endif 213