1*9880d681SAndroid Build Coastguard Worker //===-- RuntimeDyldMachOAArch64.h -- MachO/AArch64 specific code. -*- C++ -*-=// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker 10*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H 11*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H 12*9880d681SAndroid Build Coastguard Worker 13*9880d681SAndroid Build Coastguard Worker #include "../RuntimeDyldMachO.h" 14*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Endian.h" 15*9880d681SAndroid Build Coastguard Worker 16*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "dyld" 17*9880d681SAndroid Build Coastguard Worker 18*9880d681SAndroid Build Coastguard Worker namespace llvm { 19*9880d681SAndroid Build Coastguard Worker 20*9880d681SAndroid Build Coastguard Worker class RuntimeDyldMachOAArch64 21*9880d681SAndroid Build Coastguard Worker : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOAArch64> { 22*9880d681SAndroid Build Coastguard Worker public: 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard Worker typedef uint64_t TargetPtrT; 25*9880d681SAndroid Build Coastguard Worker RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager & MM,RuntimeDyld::SymbolResolver & Resolver)26*9880d681SAndroid Build Coastguard Worker RuntimeDyldMachOAArch64(RuntimeDyld::MemoryManager &MM, 27*9880d681SAndroid Build Coastguard Worker RuntimeDyld::SymbolResolver &Resolver) 28*9880d681SAndroid Build Coastguard Worker : RuntimeDyldMachOCRTPBase(MM, Resolver) {} 29*9880d681SAndroid Build Coastguard Worker getMaxStubSize()30*9880d681SAndroid Build Coastguard Worker unsigned getMaxStubSize() override { return 8; } 31*9880d681SAndroid Build Coastguard Worker getStubAlignment()32*9880d681SAndroid Build Coastguard Worker unsigned getStubAlignment() override { return 8; } 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard Worker /// Extract the addend encoded in the instruction / memory location. decodeAddend(const RelocationEntry & RE)35*9880d681SAndroid Build Coastguard Worker int64_t decodeAddend(const RelocationEntry &RE) const { 36*9880d681SAndroid Build Coastguard Worker const SectionEntry &Section = Sections[RE.SectionID]; 37*9880d681SAndroid Build Coastguard Worker uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 38*9880d681SAndroid Build Coastguard Worker unsigned NumBytes = 1 << RE.Size; 39*9880d681SAndroid Build Coastguard Worker int64_t Addend = 0; 40*9880d681SAndroid Build Coastguard Worker // Verify that the relocation has the correct size and alignment. 41*9880d681SAndroid Build Coastguard Worker switch (RE.RelType) { 42*9880d681SAndroid Build Coastguard Worker default: 43*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unsupported relocation type!"); 44*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_UNSIGNED: 45*9880d681SAndroid Build Coastguard Worker assert((NumBytes == 4 || NumBytes == 8) && "Invalid relocation size."); 46*9880d681SAndroid Build Coastguard Worker break; 47*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_BRANCH26: 48*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGE21: 49*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGEOFF12: 50*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 51*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 52*9880d681SAndroid Build Coastguard Worker assert(NumBytes == 4 && "Invalid relocation size."); 53*9880d681SAndroid Build Coastguard Worker assert((((uintptr_t)LocalAddress & 0x3) == 0) && 54*9880d681SAndroid Build Coastguard Worker "Instruction address is not aligned to 4 bytes."); 55*9880d681SAndroid Build Coastguard Worker break; 56*9880d681SAndroid Build Coastguard Worker } 57*9880d681SAndroid Build Coastguard Worker 58*9880d681SAndroid Build Coastguard Worker switch (RE.RelType) { 59*9880d681SAndroid Build Coastguard Worker default: 60*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unsupported relocation type!"); 61*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_UNSIGNED: 62*9880d681SAndroid Build Coastguard Worker // This could be an unaligned memory location. 63*9880d681SAndroid Build Coastguard Worker if (NumBytes == 4) 64*9880d681SAndroid Build Coastguard Worker Addend = *reinterpret_cast<support::ulittle32_t *>(LocalAddress); 65*9880d681SAndroid Build Coastguard Worker else 66*9880d681SAndroid Build Coastguard Worker Addend = *reinterpret_cast<support::ulittle64_t *>(LocalAddress); 67*9880d681SAndroid Build Coastguard Worker break; 68*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_BRANCH26: { 69*9880d681SAndroid Build Coastguard Worker // Verify that the relocation points to the expected branch instruction. 70*9880d681SAndroid Build Coastguard Worker auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress); 71*9880d681SAndroid Build Coastguard Worker assert((*p & 0xFC000000) == 0x14000000 && "Expected branch instruction."); 72*9880d681SAndroid Build Coastguard Worker 73*9880d681SAndroid Build Coastguard Worker // Get the 26 bit addend encoded in the branch instruction and sign-extend 74*9880d681SAndroid Build Coastguard Worker // to 64 bit. The lower 2 bits are always zeros and are therefore implicit 75*9880d681SAndroid Build Coastguard Worker // (<< 2). 76*9880d681SAndroid Build Coastguard Worker Addend = (*p & 0x03FFFFFF) << 2; 77*9880d681SAndroid Build Coastguard Worker Addend = SignExtend64(Addend, 28); 78*9880d681SAndroid Build Coastguard Worker break; 79*9880d681SAndroid Build Coastguard Worker } 80*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 81*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGE21: { 82*9880d681SAndroid Build Coastguard Worker // Verify that the relocation points to the expected adrp instruction. 83*9880d681SAndroid Build Coastguard Worker auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress); 84*9880d681SAndroid Build Coastguard Worker assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction."); 85*9880d681SAndroid Build Coastguard Worker 86*9880d681SAndroid Build Coastguard Worker // Get the 21 bit addend encoded in the adrp instruction and sign-extend 87*9880d681SAndroid Build Coastguard Worker // to 64 bit. The lower 12 bits (4096 byte page) are always zeros and are 88*9880d681SAndroid Build Coastguard Worker // therefore implicit (<< 12). 89*9880d681SAndroid Build Coastguard Worker Addend = ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3) << 12; 90*9880d681SAndroid Build Coastguard Worker Addend = SignExtend64(Addend, 33); 91*9880d681SAndroid Build Coastguard Worker break; 92*9880d681SAndroid Build Coastguard Worker } 93*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: { 94*9880d681SAndroid Build Coastguard Worker // Verify that the relocation points to one of the expected load / store 95*9880d681SAndroid Build Coastguard Worker // instructions. 96*9880d681SAndroid Build Coastguard Worker auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress); 97*9880d681SAndroid Build Coastguard Worker (void)p; 98*9880d681SAndroid Build Coastguard Worker assert((*p & 0x3B000000) == 0x39000000 && 99*9880d681SAndroid Build Coastguard Worker "Only expected load / store instructions."); 100*9880d681SAndroid Build Coastguard Worker } // fall-through 101*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGEOFF12: { 102*9880d681SAndroid Build Coastguard Worker // Verify that the relocation points to one of the expected load / store 103*9880d681SAndroid Build Coastguard Worker // or add / sub instructions. 104*9880d681SAndroid Build Coastguard Worker auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress); 105*9880d681SAndroid Build Coastguard Worker assert((((*p & 0x3B000000) == 0x39000000) || 106*9880d681SAndroid Build Coastguard Worker ((*p & 0x11C00000) == 0x11000000) ) && 107*9880d681SAndroid Build Coastguard Worker "Expected load / store or add/sub instruction."); 108*9880d681SAndroid Build Coastguard Worker 109*9880d681SAndroid Build Coastguard Worker // Get the 12 bit addend encoded in the instruction. 110*9880d681SAndroid Build Coastguard Worker Addend = (*p & 0x003FFC00) >> 10; 111*9880d681SAndroid Build Coastguard Worker 112*9880d681SAndroid Build Coastguard Worker // Check which instruction we are decoding to obtain the implicit shift 113*9880d681SAndroid Build Coastguard Worker // factor of the instruction. 114*9880d681SAndroid Build Coastguard Worker int ImplicitShift = 0; 115*9880d681SAndroid Build Coastguard Worker if ((*p & 0x3B000000) == 0x39000000) { // << load / store 116*9880d681SAndroid Build Coastguard Worker // For load / store instructions the size is encoded in bits 31:30. 117*9880d681SAndroid Build Coastguard Worker ImplicitShift = ((*p >> 30) & 0x3); 118*9880d681SAndroid Build Coastguard Worker if (ImplicitShift == 0) { 119*9880d681SAndroid Build Coastguard Worker // Check if this a vector op to get the correct shift value. 120*9880d681SAndroid Build Coastguard Worker if ((*p & 0x04800000) == 0x04800000) 121*9880d681SAndroid Build Coastguard Worker ImplicitShift = 4; 122*9880d681SAndroid Build Coastguard Worker } 123*9880d681SAndroid Build Coastguard Worker } 124*9880d681SAndroid Build Coastguard Worker // Compensate for implicit shift. 125*9880d681SAndroid Build Coastguard Worker Addend <<= ImplicitShift; 126*9880d681SAndroid Build Coastguard Worker break; 127*9880d681SAndroid Build Coastguard Worker } 128*9880d681SAndroid Build Coastguard Worker } 129*9880d681SAndroid Build Coastguard Worker return Addend; 130*9880d681SAndroid Build Coastguard Worker } 131*9880d681SAndroid Build Coastguard Worker 132*9880d681SAndroid Build Coastguard Worker /// Extract the addend encoded in the instruction. encodeAddend(uint8_t * LocalAddress,unsigned NumBytes,MachO::RelocationInfoType RelType,int64_t Addend)133*9880d681SAndroid Build Coastguard Worker void encodeAddend(uint8_t *LocalAddress, unsigned NumBytes, 134*9880d681SAndroid Build Coastguard Worker MachO::RelocationInfoType RelType, int64_t Addend) const { 135*9880d681SAndroid Build Coastguard Worker // Verify that the relocation has the correct alignment. 136*9880d681SAndroid Build Coastguard Worker switch (RelType) { 137*9880d681SAndroid Build Coastguard Worker default: 138*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unsupported relocation type!"); 139*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_UNSIGNED: 140*9880d681SAndroid Build Coastguard Worker assert((NumBytes == 4 || NumBytes == 8) && "Invalid relocation size."); 141*9880d681SAndroid Build Coastguard Worker break; 142*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_BRANCH26: 143*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGE21: 144*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGEOFF12: 145*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 146*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 147*9880d681SAndroid Build Coastguard Worker assert(NumBytes == 4 && "Invalid relocation size."); 148*9880d681SAndroid Build Coastguard Worker assert((((uintptr_t)LocalAddress & 0x3) == 0) && 149*9880d681SAndroid Build Coastguard Worker "Instruction address is not aligned to 4 bytes."); 150*9880d681SAndroid Build Coastguard Worker break; 151*9880d681SAndroid Build Coastguard Worker } 152*9880d681SAndroid Build Coastguard Worker 153*9880d681SAndroid Build Coastguard Worker switch (RelType) { 154*9880d681SAndroid Build Coastguard Worker default: 155*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unsupported relocation type!"); 156*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_UNSIGNED: 157*9880d681SAndroid Build Coastguard Worker // This could be an unaligned memory location. 158*9880d681SAndroid Build Coastguard Worker if (NumBytes == 4) 159*9880d681SAndroid Build Coastguard Worker *reinterpret_cast<support::ulittle32_t *>(LocalAddress) = Addend; 160*9880d681SAndroid Build Coastguard Worker else 161*9880d681SAndroid Build Coastguard Worker *reinterpret_cast<support::ulittle64_t *>(LocalAddress) = Addend; 162*9880d681SAndroid Build Coastguard Worker break; 163*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_BRANCH26: { 164*9880d681SAndroid Build Coastguard Worker auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress); 165*9880d681SAndroid Build Coastguard Worker // Verify that the relocation points to the expected branch instruction. 166*9880d681SAndroid Build Coastguard Worker assert((*p & 0xFC000000) == 0x14000000 && "Expected branch instruction."); 167*9880d681SAndroid Build Coastguard Worker 168*9880d681SAndroid Build Coastguard Worker // Verify addend value. 169*9880d681SAndroid Build Coastguard Worker assert((Addend & 0x3) == 0 && "Branch target is not aligned"); 170*9880d681SAndroid Build Coastguard Worker assert(isInt<28>(Addend) && "Branch target is out of range."); 171*9880d681SAndroid Build Coastguard Worker 172*9880d681SAndroid Build Coastguard Worker // Encode the addend as 26 bit immediate in the branch instruction. 173*9880d681SAndroid Build Coastguard Worker *p = (*p & 0xFC000000) | ((uint32_t)(Addend >> 2) & 0x03FFFFFF); 174*9880d681SAndroid Build Coastguard Worker break; 175*9880d681SAndroid Build Coastguard Worker } 176*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 177*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGE21: { 178*9880d681SAndroid Build Coastguard Worker // Verify that the relocation points to the expected adrp instruction. 179*9880d681SAndroid Build Coastguard Worker auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress); 180*9880d681SAndroid Build Coastguard Worker assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction."); 181*9880d681SAndroid Build Coastguard Worker 182*9880d681SAndroid Build Coastguard Worker // Check that the addend fits into 21 bits (+ 12 lower bits). 183*9880d681SAndroid Build Coastguard Worker assert((Addend & 0xFFF) == 0 && "ADRP target is not page aligned."); 184*9880d681SAndroid Build Coastguard Worker assert(isInt<33>(Addend) && "Invalid page reloc value."); 185*9880d681SAndroid Build Coastguard Worker 186*9880d681SAndroid Build Coastguard Worker // Encode the addend into the instruction. 187*9880d681SAndroid Build Coastguard Worker uint32_t ImmLoValue = ((uint64_t)Addend << 17) & 0x60000000; 188*9880d681SAndroid Build Coastguard Worker uint32_t ImmHiValue = ((uint64_t)Addend >> 9) & 0x00FFFFE0; 189*9880d681SAndroid Build Coastguard Worker *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue; 190*9880d681SAndroid Build Coastguard Worker break; 191*9880d681SAndroid Build Coastguard Worker } 192*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: { 193*9880d681SAndroid Build Coastguard Worker // Verify that the relocation points to one of the expected load / store 194*9880d681SAndroid Build Coastguard Worker // instructions. 195*9880d681SAndroid Build Coastguard Worker auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress); 196*9880d681SAndroid Build Coastguard Worker assert((*p & 0x3B000000) == 0x39000000 && 197*9880d681SAndroid Build Coastguard Worker "Only expected load / store instructions."); 198*9880d681SAndroid Build Coastguard Worker (void)p; 199*9880d681SAndroid Build Coastguard Worker } // fall-through 200*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGEOFF12: { 201*9880d681SAndroid Build Coastguard Worker // Verify that the relocation points to one of the expected load / store 202*9880d681SAndroid Build Coastguard Worker // or add / sub instructions. 203*9880d681SAndroid Build Coastguard Worker auto *p = reinterpret_cast<support::aligned_ulittle32_t *>(LocalAddress); 204*9880d681SAndroid Build Coastguard Worker assert((((*p & 0x3B000000) == 0x39000000) || 205*9880d681SAndroid Build Coastguard Worker ((*p & 0x11C00000) == 0x11000000) ) && 206*9880d681SAndroid Build Coastguard Worker "Expected load / store or add/sub instruction."); 207*9880d681SAndroid Build Coastguard Worker 208*9880d681SAndroid Build Coastguard Worker // Check which instruction we are decoding to obtain the implicit shift 209*9880d681SAndroid Build Coastguard Worker // factor of the instruction and verify alignment. 210*9880d681SAndroid Build Coastguard Worker int ImplicitShift = 0; 211*9880d681SAndroid Build Coastguard Worker if ((*p & 0x3B000000) == 0x39000000) { // << load / store 212*9880d681SAndroid Build Coastguard Worker // For load / store instructions the size is encoded in bits 31:30. 213*9880d681SAndroid Build Coastguard Worker ImplicitShift = ((*p >> 30) & 0x3); 214*9880d681SAndroid Build Coastguard Worker switch (ImplicitShift) { 215*9880d681SAndroid Build Coastguard Worker case 0: 216*9880d681SAndroid Build Coastguard Worker // Check if this a vector op to get the correct shift value. 217*9880d681SAndroid Build Coastguard Worker if ((*p & 0x04800000) == 0x04800000) { 218*9880d681SAndroid Build Coastguard Worker ImplicitShift = 4; 219*9880d681SAndroid Build Coastguard Worker assert(((Addend & 0xF) == 0) && 220*9880d681SAndroid Build Coastguard Worker "128-bit LDR/STR not 16-byte aligned."); 221*9880d681SAndroid Build Coastguard Worker } 222*9880d681SAndroid Build Coastguard Worker break; 223*9880d681SAndroid Build Coastguard Worker case 1: 224*9880d681SAndroid Build Coastguard Worker assert(((Addend & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned."); 225*9880d681SAndroid Build Coastguard Worker break; 226*9880d681SAndroid Build Coastguard Worker case 2: 227*9880d681SAndroid Build Coastguard Worker assert(((Addend & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned."); 228*9880d681SAndroid Build Coastguard Worker break; 229*9880d681SAndroid Build Coastguard Worker case 3: 230*9880d681SAndroid Build Coastguard Worker assert(((Addend & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned."); 231*9880d681SAndroid Build Coastguard Worker break; 232*9880d681SAndroid Build Coastguard Worker } 233*9880d681SAndroid Build Coastguard Worker } 234*9880d681SAndroid Build Coastguard Worker // Compensate for implicit shift. 235*9880d681SAndroid Build Coastguard Worker Addend >>= ImplicitShift; 236*9880d681SAndroid Build Coastguard Worker assert(isUInt<12>(Addend) && "Addend cannot be encoded."); 237*9880d681SAndroid Build Coastguard Worker 238*9880d681SAndroid Build Coastguard Worker // Encode the addend into the instruction. 239*9880d681SAndroid Build Coastguard Worker *p = (*p & 0xFFC003FF) | ((uint32_t)(Addend << 10) & 0x003FFC00); 240*9880d681SAndroid Build Coastguard Worker break; 241*9880d681SAndroid Build Coastguard Worker } 242*9880d681SAndroid Build Coastguard Worker } 243*9880d681SAndroid Build Coastguard Worker } 244*9880d681SAndroid Build Coastguard Worker 245*9880d681SAndroid Build Coastguard Worker Expected<relocation_iterator> processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)246*9880d681SAndroid Build Coastguard Worker processRelocationRef(unsigned SectionID, relocation_iterator RelI, 247*9880d681SAndroid Build Coastguard Worker const ObjectFile &BaseObjT, 248*9880d681SAndroid Build Coastguard Worker ObjSectionToIDMap &ObjSectionToID, 249*9880d681SAndroid Build Coastguard Worker StubMap &Stubs) override { 250*9880d681SAndroid Build Coastguard Worker const MachOObjectFile &Obj = 251*9880d681SAndroid Build Coastguard Worker static_cast<const MachOObjectFile &>(BaseObjT); 252*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info RelInfo = 253*9880d681SAndroid Build Coastguard Worker Obj.getRelocation(RelI->getRawDataRefImpl()); 254*9880d681SAndroid Build Coastguard Worker 255*9880d681SAndroid Build Coastguard Worker if (Obj.isRelocationScattered(RelInfo)) 256*9880d681SAndroid Build Coastguard Worker return make_error<RuntimeDyldError>("Scattered relocations not supported " 257*9880d681SAndroid Build Coastguard Worker "for MachO AArch64"); 258*9880d681SAndroid Build Coastguard Worker 259*9880d681SAndroid Build Coastguard Worker // ARM64 has an ARM64_RELOC_ADDEND relocation type that carries an explicit 260*9880d681SAndroid Build Coastguard Worker // addend for the following relocation. If found: (1) store the associated 261*9880d681SAndroid Build Coastguard Worker // addend, (2) consume the next relocation, and (3) use the stored addend to 262*9880d681SAndroid Build Coastguard Worker // override the addend. 263*9880d681SAndroid Build Coastguard Worker int64_t ExplicitAddend = 0; 264*9880d681SAndroid Build Coastguard Worker if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_ADDEND) { 265*9880d681SAndroid Build Coastguard Worker assert(!Obj.getPlainRelocationExternal(RelInfo)); 266*9880d681SAndroid Build Coastguard Worker assert(!Obj.getAnyRelocationPCRel(RelInfo)); 267*9880d681SAndroid Build Coastguard Worker assert(Obj.getAnyRelocationLength(RelInfo) == 2); 268*9880d681SAndroid Build Coastguard Worker int64_t RawAddend = Obj.getPlainRelocationSymbolNum(RelInfo); 269*9880d681SAndroid Build Coastguard Worker // Sign-extend the 24-bit to 64-bit. 270*9880d681SAndroid Build Coastguard Worker ExplicitAddend = SignExtend64(RawAddend, 24); 271*9880d681SAndroid Build Coastguard Worker ++RelI; 272*9880d681SAndroid Build Coastguard Worker RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); 273*9880d681SAndroid Build Coastguard Worker } 274*9880d681SAndroid Build Coastguard Worker 275*9880d681SAndroid Build Coastguard Worker if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_SUBTRACTOR) 276*9880d681SAndroid Build Coastguard Worker return processSubtractRelocation(SectionID, RelI, Obj, ObjSectionToID); 277*9880d681SAndroid Build Coastguard Worker 278*9880d681SAndroid Build Coastguard Worker RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 279*9880d681SAndroid Build Coastguard Worker RE.Addend = decodeAddend(RE); 280*9880d681SAndroid Build Coastguard Worker 281*9880d681SAndroid Build Coastguard Worker assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\ 282*9880d681SAndroid Build Coastguard Worker "ARM64_RELOC_ADDEND and embedded addend in the instruction."); 283*9880d681SAndroid Build Coastguard Worker if (ExplicitAddend) 284*9880d681SAndroid Build Coastguard Worker RE.Addend = ExplicitAddend; 285*9880d681SAndroid Build Coastguard Worker 286*9880d681SAndroid Build Coastguard Worker RelocationValueRef Value; 287*9880d681SAndroid Build Coastguard Worker if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) 288*9880d681SAndroid Build Coastguard Worker Value = *ValueOrErr; 289*9880d681SAndroid Build Coastguard Worker else 290*9880d681SAndroid Build Coastguard Worker return ValueOrErr.takeError(); 291*9880d681SAndroid Build Coastguard Worker 292*9880d681SAndroid Build Coastguard Worker bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 293*9880d681SAndroid Build Coastguard Worker if (!IsExtern && RE.IsPCRel) 294*9880d681SAndroid Build Coastguard Worker makeValueAddendPCRel(Value, RelI, 1 << RE.Size); 295*9880d681SAndroid Build Coastguard Worker 296*9880d681SAndroid Build Coastguard Worker RE.Addend = Value.Offset; 297*9880d681SAndroid Build Coastguard Worker 298*9880d681SAndroid Build Coastguard Worker if (RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGE21 || 299*9880d681SAndroid Build Coastguard Worker RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12) 300*9880d681SAndroid Build Coastguard Worker processGOTRelocation(RE, Value, Stubs); 301*9880d681SAndroid Build Coastguard Worker else { 302*9880d681SAndroid Build Coastguard Worker if (Value.SymbolName) 303*9880d681SAndroid Build Coastguard Worker addRelocationForSymbol(RE, Value.SymbolName); 304*9880d681SAndroid Build Coastguard Worker else 305*9880d681SAndroid Build Coastguard Worker addRelocationForSection(RE, Value.SectionID); 306*9880d681SAndroid Build Coastguard Worker } 307*9880d681SAndroid Build Coastguard Worker 308*9880d681SAndroid Build Coastguard Worker return ++RelI; 309*9880d681SAndroid Build Coastguard Worker } 310*9880d681SAndroid Build Coastguard Worker resolveRelocation(const RelocationEntry & RE,uint64_t Value)311*9880d681SAndroid Build Coastguard Worker void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 312*9880d681SAndroid Build Coastguard Worker DEBUG(dumpRelocationToResolve(RE, Value)); 313*9880d681SAndroid Build Coastguard Worker 314*9880d681SAndroid Build Coastguard Worker const SectionEntry &Section = Sections[RE.SectionID]; 315*9880d681SAndroid Build Coastguard Worker uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 316*9880d681SAndroid Build Coastguard Worker MachO::RelocationInfoType RelType = 317*9880d681SAndroid Build Coastguard Worker static_cast<MachO::RelocationInfoType>(RE.RelType); 318*9880d681SAndroid Build Coastguard Worker 319*9880d681SAndroid Build Coastguard Worker switch (RelType) { 320*9880d681SAndroid Build Coastguard Worker default: 321*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid relocation type!"); 322*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_UNSIGNED: { 323*9880d681SAndroid Build Coastguard Worker assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_UNSIGNED not supported"); 324*9880d681SAndroid Build Coastguard Worker // Mask in the target value a byte at a time (we don't have an alignment 325*9880d681SAndroid Build Coastguard Worker // guarantee for the target address, so this is safest). 326*9880d681SAndroid Build Coastguard Worker if (RE.Size < 2) 327*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid size for ARM64_RELOC_UNSIGNED"); 328*9880d681SAndroid Build Coastguard Worker 329*9880d681SAndroid Build Coastguard Worker encodeAddend(LocalAddress, 1 << RE.Size, RelType, Value + RE.Addend); 330*9880d681SAndroid Build Coastguard Worker break; 331*9880d681SAndroid Build Coastguard Worker } 332*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_BRANCH26: { 333*9880d681SAndroid Build Coastguard Worker assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_BRANCH26 not supported"); 334*9880d681SAndroid Build Coastguard Worker // Check if branch is in range. 335*9880d681SAndroid Build Coastguard Worker uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 336*9880d681SAndroid Build Coastguard Worker int64_t PCRelVal = Value - FinalAddress + RE.Addend; 337*9880d681SAndroid Build Coastguard Worker encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal); 338*9880d681SAndroid Build Coastguard Worker break; 339*9880d681SAndroid Build Coastguard Worker } 340*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 341*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGE21: { 342*9880d681SAndroid Build Coastguard Worker assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_PAGE21 not supported"); 343*9880d681SAndroid Build Coastguard Worker // Adjust for PC-relative relocation and offset. 344*9880d681SAndroid Build Coastguard Worker uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 345*9880d681SAndroid Build Coastguard Worker int64_t PCRelVal = 346*9880d681SAndroid Build Coastguard Worker ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096)); 347*9880d681SAndroid Build Coastguard Worker encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal); 348*9880d681SAndroid Build Coastguard Worker break; 349*9880d681SAndroid Build Coastguard Worker } 350*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 351*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_PAGEOFF12: { 352*9880d681SAndroid Build Coastguard Worker assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_PAGEOFF21 not supported"); 353*9880d681SAndroid Build Coastguard Worker // Add the offset from the symbol. 354*9880d681SAndroid Build Coastguard Worker Value += RE.Addend; 355*9880d681SAndroid Build Coastguard Worker // Mask out the page address and only use the lower 12 bits. 356*9880d681SAndroid Build Coastguard Worker Value &= 0xFFF; 357*9880d681SAndroid Build Coastguard Worker encodeAddend(LocalAddress, /*Size=*/4, RelType, Value); 358*9880d681SAndroid Build Coastguard Worker break; 359*9880d681SAndroid Build Coastguard Worker } 360*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_SUBTRACTOR: { 361*9880d681SAndroid Build Coastguard Worker uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress(); 362*9880d681SAndroid Build Coastguard Worker uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress(); 363*9880d681SAndroid Build Coastguard Worker assert((Value == SectionABase || Value == SectionBBase) && 364*9880d681SAndroid Build Coastguard Worker "Unexpected SUBTRACTOR relocation value."); 365*9880d681SAndroid Build Coastguard Worker Value = SectionABase - SectionBBase + RE.Addend; 366*9880d681SAndroid Build Coastguard Worker writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); 367*9880d681SAndroid Build Coastguard Worker break; 368*9880d681SAndroid Build Coastguard Worker } 369*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_POINTER_TO_GOT: 370*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 371*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 372*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Relocation type not yet implemented!"); 373*9880d681SAndroid Build Coastguard Worker case MachO::ARM64_RELOC_ADDEND: 374*9880d681SAndroid Build Coastguard Worker llvm_unreachable("ARM64_RELOC_ADDEND should have been handeled by " 375*9880d681SAndroid Build Coastguard Worker "processRelocationRef!"); 376*9880d681SAndroid Build Coastguard Worker } 377*9880d681SAndroid Build Coastguard Worker } 378*9880d681SAndroid Build Coastguard Worker finalizeSection(const ObjectFile & Obj,unsigned SectionID,const SectionRef & Section)379*9880d681SAndroid Build Coastguard Worker Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, 380*9880d681SAndroid Build Coastguard Worker const SectionRef &Section) { 381*9880d681SAndroid Build Coastguard Worker return Error::success(); 382*9880d681SAndroid Build Coastguard Worker } 383*9880d681SAndroid Build Coastguard Worker 384*9880d681SAndroid Build Coastguard Worker private: processGOTRelocation(const RelocationEntry & RE,RelocationValueRef & Value,StubMap & Stubs)385*9880d681SAndroid Build Coastguard Worker void processGOTRelocation(const RelocationEntry &RE, 386*9880d681SAndroid Build Coastguard Worker RelocationValueRef &Value, StubMap &Stubs) { 387*9880d681SAndroid Build Coastguard Worker assert(RE.Size == 2); 388*9880d681SAndroid Build Coastguard Worker SectionEntry &Section = Sections[RE.SectionID]; 389*9880d681SAndroid Build Coastguard Worker StubMap::const_iterator i = Stubs.find(Value); 390*9880d681SAndroid Build Coastguard Worker int64_t Offset; 391*9880d681SAndroid Build Coastguard Worker if (i != Stubs.end()) 392*9880d681SAndroid Build Coastguard Worker Offset = static_cast<int64_t>(i->second); 393*9880d681SAndroid Build Coastguard Worker else { 394*9880d681SAndroid Build Coastguard Worker // FIXME: There must be a better way to do this then to check and fix the 395*9880d681SAndroid Build Coastguard Worker // alignment every time!!! 396*9880d681SAndroid Build Coastguard Worker uintptr_t BaseAddress = uintptr_t(Section.getAddress()); 397*9880d681SAndroid Build Coastguard Worker uintptr_t StubAlignment = getStubAlignment(); 398*9880d681SAndroid Build Coastguard Worker uintptr_t StubAddress = 399*9880d681SAndroid Build Coastguard Worker (BaseAddress + Section.getStubOffset() + StubAlignment - 1) & 400*9880d681SAndroid Build Coastguard Worker -StubAlignment; 401*9880d681SAndroid Build Coastguard Worker unsigned StubOffset = StubAddress - BaseAddress; 402*9880d681SAndroid Build Coastguard Worker Stubs[Value] = StubOffset; 403*9880d681SAndroid Build Coastguard Worker assert(((StubAddress % getStubAlignment()) == 0) && 404*9880d681SAndroid Build Coastguard Worker "GOT entry not aligned"); 405*9880d681SAndroid Build Coastguard Worker RelocationEntry GOTRE(RE.SectionID, StubOffset, 406*9880d681SAndroid Build Coastguard Worker MachO::ARM64_RELOC_UNSIGNED, Value.Offset, 407*9880d681SAndroid Build Coastguard Worker /*IsPCRel=*/false, /*Size=*/3); 408*9880d681SAndroid Build Coastguard Worker if (Value.SymbolName) 409*9880d681SAndroid Build Coastguard Worker addRelocationForSymbol(GOTRE, Value.SymbolName); 410*9880d681SAndroid Build Coastguard Worker else 411*9880d681SAndroid Build Coastguard Worker addRelocationForSection(GOTRE, Value.SectionID); 412*9880d681SAndroid Build Coastguard Worker Section.advanceStubOffset(getMaxStubSize()); 413*9880d681SAndroid Build Coastguard Worker Offset = static_cast<int64_t>(StubOffset); 414*9880d681SAndroid Build Coastguard Worker } 415*9880d681SAndroid Build Coastguard Worker RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, Offset, 416*9880d681SAndroid Build Coastguard Worker RE.IsPCRel, RE.Size); 417*9880d681SAndroid Build Coastguard Worker addRelocationForSection(TargetRE, RE.SectionID); 418*9880d681SAndroid Build Coastguard Worker } 419*9880d681SAndroid Build Coastguard Worker 420*9880d681SAndroid Build Coastguard Worker Expected<relocation_iterator> processSubtractRelocation(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID)421*9880d681SAndroid Build Coastguard Worker processSubtractRelocation(unsigned SectionID, relocation_iterator RelI, 422*9880d681SAndroid Build Coastguard Worker const ObjectFile &BaseObjT, 423*9880d681SAndroid Build Coastguard Worker ObjSectionToIDMap &ObjSectionToID) { 424*9880d681SAndroid Build Coastguard Worker const MachOObjectFile &Obj = 425*9880d681SAndroid Build Coastguard Worker static_cast<const MachOObjectFile&>(BaseObjT); 426*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info RE = 427*9880d681SAndroid Build Coastguard Worker Obj.getRelocation(RelI->getRawDataRefImpl()); 428*9880d681SAndroid Build Coastguard Worker 429*9880d681SAndroid Build Coastguard Worker unsigned Size = Obj.getAnyRelocationLength(RE); 430*9880d681SAndroid Build Coastguard Worker uint64_t Offset = RelI->getOffset(); 431*9880d681SAndroid Build Coastguard Worker uint8_t *LocalAddress = Sections[SectionID].getAddressWithOffset(Offset); 432*9880d681SAndroid Build Coastguard Worker unsigned NumBytes = 1 << Size; 433*9880d681SAndroid Build Coastguard Worker 434*9880d681SAndroid Build Coastguard Worker Expected<StringRef> SubtrahendNameOrErr = RelI->getSymbol()->getName(); 435*9880d681SAndroid Build Coastguard Worker if (!SubtrahendNameOrErr) 436*9880d681SAndroid Build Coastguard Worker return SubtrahendNameOrErr.takeError(); 437*9880d681SAndroid Build Coastguard Worker auto SubtrahendI = GlobalSymbolTable.find(*SubtrahendNameOrErr); 438*9880d681SAndroid Build Coastguard Worker unsigned SectionBID = SubtrahendI->second.getSectionID(); 439*9880d681SAndroid Build Coastguard Worker uint64_t SectionBOffset = SubtrahendI->second.getOffset(); 440*9880d681SAndroid Build Coastguard Worker int64_t Addend = 441*9880d681SAndroid Build Coastguard Worker SignExtend64(readBytesUnaligned(LocalAddress, NumBytes), NumBytes * 8); 442*9880d681SAndroid Build Coastguard Worker 443*9880d681SAndroid Build Coastguard Worker ++RelI; 444*9880d681SAndroid Build Coastguard Worker Expected<StringRef> MinuendNameOrErr = RelI->getSymbol()->getName(); 445*9880d681SAndroid Build Coastguard Worker if (!MinuendNameOrErr) 446*9880d681SAndroid Build Coastguard Worker return MinuendNameOrErr.takeError(); 447*9880d681SAndroid Build Coastguard Worker auto MinuendI = GlobalSymbolTable.find(*MinuendNameOrErr); 448*9880d681SAndroid Build Coastguard Worker unsigned SectionAID = MinuendI->second.getSectionID(); 449*9880d681SAndroid Build Coastguard Worker uint64_t SectionAOffset = MinuendI->second.getOffset(); 450*9880d681SAndroid Build Coastguard Worker 451*9880d681SAndroid Build Coastguard Worker RelocationEntry R(SectionID, Offset, MachO::ARM64_RELOC_SUBTRACTOR, (uint64_t)Addend, 452*9880d681SAndroid Build Coastguard Worker SectionAID, SectionAOffset, SectionBID, SectionBOffset, 453*9880d681SAndroid Build Coastguard Worker false, Size); 454*9880d681SAndroid Build Coastguard Worker 455*9880d681SAndroid Build Coastguard Worker addRelocationForSection(R, SectionAID); 456*9880d681SAndroid Build Coastguard Worker 457*9880d681SAndroid Build Coastguard Worker return ++RelI; 458*9880d681SAndroid Build Coastguard Worker } 459*9880d681SAndroid Build Coastguard Worker 460*9880d681SAndroid Build Coastguard Worker }; 461*9880d681SAndroid Build Coastguard Worker } 462*9880d681SAndroid Build Coastguard Worker 463*9880d681SAndroid Build Coastguard Worker #undef DEBUG_TYPE 464*9880d681SAndroid Build Coastguard Worker 465*9880d681SAndroid Build Coastguard Worker #endif 466