1*9880d681SAndroid Build Coastguard Worker //===----- RuntimeDyldMachOARM.h ---- MachO/ARM 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_RUNTIMEDYLDMACHOARM_H 11*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H 12*9880d681SAndroid Build Coastguard Worker 13*9880d681SAndroid Build Coastguard Worker #include "../RuntimeDyldMachO.h" 14*9880d681SAndroid Build Coastguard Worker #include <string> 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 RuntimeDyldMachOARM 21*9880d681SAndroid Build Coastguard Worker : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> { 22*9880d681SAndroid Build Coastguard Worker private: 23*9880d681SAndroid Build Coastguard Worker typedef RuntimeDyldMachOCRTPBase<RuntimeDyldMachOARM> ParentT; 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard Worker public: 26*9880d681SAndroid Build Coastguard Worker 27*9880d681SAndroid Build Coastguard Worker typedef uint32_t TargetPtrT; 28*9880d681SAndroid Build Coastguard Worker RuntimeDyldMachOARM(RuntimeDyld::MemoryManager & MM,RuntimeDyld::SymbolResolver & Resolver)29*9880d681SAndroid Build Coastguard Worker RuntimeDyldMachOARM(RuntimeDyld::MemoryManager &MM, 30*9880d681SAndroid Build Coastguard Worker RuntimeDyld::SymbolResolver &Resolver) 31*9880d681SAndroid Build Coastguard Worker : RuntimeDyldMachOCRTPBase(MM, Resolver) {} 32*9880d681SAndroid Build Coastguard Worker getMaxStubSize()33*9880d681SAndroid Build Coastguard Worker unsigned getMaxStubSize() override { return 8; } 34*9880d681SAndroid Build Coastguard Worker getStubAlignment()35*9880d681SAndroid Build Coastguard Worker unsigned getStubAlignment() override { return 4; } 36*9880d681SAndroid Build Coastguard Worker decodeAddend(const RelocationEntry & RE)37*9880d681SAndroid Build Coastguard Worker int64_t decodeAddend(const RelocationEntry &RE) const { 38*9880d681SAndroid Build Coastguard Worker const SectionEntry &Section = Sections[RE.SectionID]; 39*9880d681SAndroid Build Coastguard Worker uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 40*9880d681SAndroid Build Coastguard Worker 41*9880d681SAndroid Build Coastguard Worker switch (RE.RelType) { 42*9880d681SAndroid Build Coastguard Worker default: 43*9880d681SAndroid Build Coastguard Worker return memcpyAddend(RE); 44*9880d681SAndroid Build Coastguard Worker case MachO::ARM_RELOC_BR24: { 45*9880d681SAndroid Build Coastguard Worker uint32_t Temp = readBytesUnaligned(LocalAddress, 4); 46*9880d681SAndroid Build Coastguard Worker Temp &= 0x00ffffff; // Mask out the opcode. 47*9880d681SAndroid Build Coastguard Worker // Now we've got the shifted immediate, shift by 2, sign extend and ret. 48*9880d681SAndroid Build Coastguard Worker return SignExtend32<26>(Temp << 2); 49*9880d681SAndroid Build Coastguard Worker } 50*9880d681SAndroid Build Coastguard Worker } 51*9880d681SAndroid Build Coastguard Worker } 52*9880d681SAndroid Build Coastguard Worker 53*9880d681SAndroid Build Coastguard Worker Expected<relocation_iterator> processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)54*9880d681SAndroid Build Coastguard Worker processRelocationRef(unsigned SectionID, relocation_iterator RelI, 55*9880d681SAndroid Build Coastguard Worker const ObjectFile &BaseObjT, 56*9880d681SAndroid Build Coastguard Worker ObjSectionToIDMap &ObjSectionToID, 57*9880d681SAndroid Build Coastguard Worker StubMap &Stubs) override { 58*9880d681SAndroid Build Coastguard Worker const MachOObjectFile &Obj = 59*9880d681SAndroid Build Coastguard Worker static_cast<const MachOObjectFile &>(BaseObjT); 60*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info RelInfo = 61*9880d681SAndroid Build Coastguard Worker Obj.getRelocation(RelI->getRawDataRefImpl()); 62*9880d681SAndroid Build Coastguard Worker uint32_t RelType = Obj.getAnyRelocationType(RelInfo); 63*9880d681SAndroid Build Coastguard Worker 64*9880d681SAndroid Build Coastguard Worker if (Obj.isRelocationScattered(RelInfo)) { 65*9880d681SAndroid Build Coastguard Worker if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF) 66*9880d681SAndroid Build Coastguard Worker return processHALFSECTDIFFRelocation(SectionID, RelI, Obj, 67*9880d681SAndroid Build Coastguard Worker ObjSectionToID); 68*9880d681SAndroid Build Coastguard Worker else if (RelType == MachO::GENERIC_RELOC_VANILLA) 69*9880d681SAndroid Build Coastguard Worker return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); 70*9880d681SAndroid Build Coastguard Worker else 71*9880d681SAndroid Build Coastguard Worker return ++RelI; 72*9880d681SAndroid Build Coastguard Worker } 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker // Sanity check relocation type. 75*9880d681SAndroid Build Coastguard Worker switch (RelType) { 76*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PAIR); 77*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_SECTDIFF); 78*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_LOCAL_SECTDIFF); 79*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_PB_LA_PTR); 80*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_RELOC_BR22); 81*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::ARM_THUMB_32BIT_BRANCH); 82*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::ARM_RELOC_HALF); 83*9880d681SAndroid Build Coastguard Worker default: 84*9880d681SAndroid Build Coastguard Worker if (RelType > MachO::ARM_RELOC_HALF_SECTDIFF) 85*9880d681SAndroid Build Coastguard Worker return make_error<RuntimeDyldError>(("MachO ARM relocation type " + 86*9880d681SAndroid Build Coastguard Worker Twine(RelType) + 87*9880d681SAndroid Build Coastguard Worker " is out of range").str()); 88*9880d681SAndroid Build Coastguard Worker break; 89*9880d681SAndroid Build Coastguard Worker } 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 92*9880d681SAndroid Build Coastguard Worker RE.Addend = decodeAddend(RE); 93*9880d681SAndroid Build Coastguard Worker RelocationValueRef Value; 94*9880d681SAndroid Build Coastguard Worker if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) 95*9880d681SAndroid Build Coastguard Worker Value = *ValueOrErr; 96*9880d681SAndroid Build Coastguard Worker else 97*9880d681SAndroid Build Coastguard Worker return ValueOrErr.takeError(); 98*9880d681SAndroid Build Coastguard Worker 99*9880d681SAndroid Build Coastguard Worker if (RE.IsPCRel) 100*9880d681SAndroid Build Coastguard Worker makeValueAddendPCRel(Value, RelI, 8); 101*9880d681SAndroid Build Coastguard Worker 102*9880d681SAndroid Build Coastguard Worker if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) 103*9880d681SAndroid Build Coastguard Worker processBranchRelocation(RE, Value, Stubs); 104*9880d681SAndroid Build Coastguard Worker else { 105*9880d681SAndroid Build Coastguard Worker RE.Addend = Value.Offset; 106*9880d681SAndroid Build Coastguard Worker if (Value.SymbolName) 107*9880d681SAndroid Build Coastguard Worker addRelocationForSymbol(RE, Value.SymbolName); 108*9880d681SAndroid Build Coastguard Worker else 109*9880d681SAndroid Build Coastguard Worker addRelocationForSection(RE, Value.SectionID); 110*9880d681SAndroid Build Coastguard Worker } 111*9880d681SAndroid Build Coastguard Worker 112*9880d681SAndroid Build Coastguard Worker return ++RelI; 113*9880d681SAndroid Build Coastguard Worker } 114*9880d681SAndroid Build Coastguard Worker resolveRelocation(const RelocationEntry & RE,uint64_t Value)115*9880d681SAndroid Build Coastguard Worker void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 116*9880d681SAndroid Build Coastguard Worker DEBUG(dumpRelocationToResolve(RE, Value)); 117*9880d681SAndroid Build Coastguard Worker const SectionEntry &Section = Sections[RE.SectionID]; 118*9880d681SAndroid Build Coastguard Worker uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Worker // If the relocation is PC-relative, the value to be encoded is the 121*9880d681SAndroid Build Coastguard Worker // pointer difference. 122*9880d681SAndroid Build Coastguard Worker if (RE.IsPCRel) { 123*9880d681SAndroid Build Coastguard Worker uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 124*9880d681SAndroid Build Coastguard Worker Value -= FinalAddress; 125*9880d681SAndroid Build Coastguard Worker // ARM PCRel relocations have an effective-PC offset of two instructions 126*9880d681SAndroid Build Coastguard Worker // (four bytes in Thumb mode, 8 bytes in ARM mode). 127*9880d681SAndroid Build Coastguard Worker // FIXME: For now, assume ARM mode. 128*9880d681SAndroid Build Coastguard Worker Value -= 8; 129*9880d681SAndroid Build Coastguard Worker } 130*9880d681SAndroid Build Coastguard Worker 131*9880d681SAndroid Build Coastguard Worker switch (RE.RelType) { 132*9880d681SAndroid Build Coastguard Worker case MachO::ARM_RELOC_VANILLA: 133*9880d681SAndroid Build Coastguard Worker writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 134*9880d681SAndroid Build Coastguard Worker break; 135*9880d681SAndroid Build Coastguard Worker case MachO::ARM_RELOC_BR24: { 136*9880d681SAndroid Build Coastguard Worker // Mask the value into the target address. We know instructions are 137*9880d681SAndroid Build Coastguard Worker // 32-bit aligned, so we can do it all at once. 138*9880d681SAndroid Build Coastguard Worker Value += RE.Addend; 139*9880d681SAndroid Build Coastguard Worker // The low two bits of the value are not encoded. 140*9880d681SAndroid Build Coastguard Worker Value >>= 2; 141*9880d681SAndroid Build Coastguard Worker // Mask the value to 24 bits. 142*9880d681SAndroid Build Coastguard Worker uint64_t FinalValue = Value & 0xffffff; 143*9880d681SAndroid Build Coastguard Worker // FIXME: If the destination is a Thumb function (and the instruction 144*9880d681SAndroid Build Coastguard Worker // is a non-predicated BL instruction), we need to change it to a BLX 145*9880d681SAndroid Build Coastguard Worker // instruction instead. 146*9880d681SAndroid Build Coastguard Worker 147*9880d681SAndroid Build Coastguard Worker // Insert the value into the instruction. 148*9880d681SAndroid Build Coastguard Worker uint32_t Temp = readBytesUnaligned(LocalAddress, 4); 149*9880d681SAndroid Build Coastguard Worker writeBytesUnaligned((Temp & ~0xffffff) | FinalValue, LocalAddress, 4); 150*9880d681SAndroid Build Coastguard Worker 151*9880d681SAndroid Build Coastguard Worker break; 152*9880d681SAndroid Build Coastguard Worker } 153*9880d681SAndroid Build Coastguard Worker case MachO::ARM_RELOC_HALF_SECTDIFF: { 154*9880d681SAndroid Build Coastguard Worker uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress(); 155*9880d681SAndroid Build Coastguard Worker uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress(); 156*9880d681SAndroid Build Coastguard Worker assert((Value == SectionABase || Value == SectionBBase) && 157*9880d681SAndroid Build Coastguard Worker "Unexpected HALFSECTDIFF relocation value."); 158*9880d681SAndroid Build Coastguard Worker Value = SectionABase - SectionBBase + RE.Addend; 159*9880d681SAndroid Build Coastguard Worker if (RE.Size & 0x1) // :upper16: 160*9880d681SAndroid Build Coastguard Worker Value = (Value >> 16); 161*9880d681SAndroid Build Coastguard Worker Value &= 0xffff; 162*9880d681SAndroid Build Coastguard Worker 163*9880d681SAndroid Build Coastguard Worker uint32_t Insn = readBytesUnaligned(LocalAddress, 4); 164*9880d681SAndroid Build Coastguard Worker Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff); 165*9880d681SAndroid Build Coastguard Worker writeBytesUnaligned(Insn, LocalAddress, 4); 166*9880d681SAndroid Build Coastguard Worker break; 167*9880d681SAndroid Build Coastguard Worker } 168*9880d681SAndroid Build Coastguard Worker 169*9880d681SAndroid Build Coastguard Worker default: 170*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid relocation type"); 171*9880d681SAndroid Build Coastguard Worker } 172*9880d681SAndroid Build Coastguard Worker } 173*9880d681SAndroid Build Coastguard Worker finalizeSection(const ObjectFile & Obj,unsigned SectionID,const SectionRef & Section)174*9880d681SAndroid Build Coastguard Worker Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, 175*9880d681SAndroid Build Coastguard Worker const SectionRef &Section) { 176*9880d681SAndroid Build Coastguard Worker StringRef Name; 177*9880d681SAndroid Build Coastguard Worker Section.getName(Name); 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker if (Name == "__nl_symbol_ptr") 180*9880d681SAndroid Build Coastguard Worker return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), 181*9880d681SAndroid Build Coastguard Worker Section, SectionID); 182*9880d681SAndroid Build Coastguard Worker return Error::success(); 183*9880d681SAndroid Build Coastguard Worker } 184*9880d681SAndroid Build Coastguard Worker 185*9880d681SAndroid Build Coastguard Worker private: 186*9880d681SAndroid Build Coastguard Worker processBranchRelocation(const RelocationEntry & RE,const RelocationValueRef & Value,StubMap & Stubs)187*9880d681SAndroid Build Coastguard Worker void processBranchRelocation(const RelocationEntry &RE, 188*9880d681SAndroid Build Coastguard Worker const RelocationValueRef &Value, 189*9880d681SAndroid Build Coastguard Worker StubMap &Stubs) { 190*9880d681SAndroid Build Coastguard Worker // This is an ARM branch relocation, need to use a stub function. 191*9880d681SAndroid Build Coastguard Worker // Look up for existing stub. 192*9880d681SAndroid Build Coastguard Worker SectionEntry &Section = Sections[RE.SectionID]; 193*9880d681SAndroid Build Coastguard Worker RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value); 194*9880d681SAndroid Build Coastguard Worker uint8_t *Addr; 195*9880d681SAndroid Build Coastguard Worker if (i != Stubs.end()) { 196*9880d681SAndroid Build Coastguard Worker Addr = Section.getAddressWithOffset(i->second); 197*9880d681SAndroid Build Coastguard Worker } else { 198*9880d681SAndroid Build Coastguard Worker // Create a new stub function. 199*9880d681SAndroid Build Coastguard Worker Stubs[Value] = Section.getStubOffset(); 200*9880d681SAndroid Build Coastguard Worker uint8_t *StubTargetAddr = createStubFunction( 201*9880d681SAndroid Build Coastguard Worker Section.getAddressWithOffset(Section.getStubOffset())); 202*9880d681SAndroid Build Coastguard Worker RelocationEntry StubRE( 203*9880d681SAndroid Build Coastguard Worker RE.SectionID, StubTargetAddr - Section.getAddress(), 204*9880d681SAndroid Build Coastguard Worker MachO::GENERIC_RELOC_VANILLA, Value.Offset, false, 2); 205*9880d681SAndroid Build Coastguard Worker if (Value.SymbolName) 206*9880d681SAndroid Build Coastguard Worker addRelocationForSymbol(StubRE, Value.SymbolName); 207*9880d681SAndroid Build Coastguard Worker else 208*9880d681SAndroid Build Coastguard Worker addRelocationForSection(StubRE, Value.SectionID); 209*9880d681SAndroid Build Coastguard Worker Addr = Section.getAddressWithOffset(Section.getStubOffset()); 210*9880d681SAndroid Build Coastguard Worker Section.advanceStubOffset(getMaxStubSize()); 211*9880d681SAndroid Build Coastguard Worker } 212*9880d681SAndroid Build Coastguard Worker RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0, 213*9880d681SAndroid Build Coastguard Worker RE.IsPCRel, RE.Size); 214*9880d681SAndroid Build Coastguard Worker resolveRelocation(TargetRE, (uint64_t)Addr); 215*9880d681SAndroid Build Coastguard Worker } 216*9880d681SAndroid Build Coastguard Worker 217*9880d681SAndroid Build Coastguard Worker Expected<relocation_iterator> processHALFSECTDIFFRelocation(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseTObj,ObjSectionToIDMap & ObjSectionToID)218*9880d681SAndroid Build Coastguard Worker processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 219*9880d681SAndroid Build Coastguard Worker const ObjectFile &BaseTObj, 220*9880d681SAndroid Build Coastguard Worker ObjSectionToIDMap &ObjSectionToID) { 221*9880d681SAndroid Build Coastguard Worker const MachOObjectFile &MachO = 222*9880d681SAndroid Build Coastguard Worker static_cast<const MachOObjectFile&>(BaseTObj); 223*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info RE = 224*9880d681SAndroid Build Coastguard Worker MachO.getRelocation(RelI->getRawDataRefImpl()); 225*9880d681SAndroid Build Coastguard Worker 226*9880d681SAndroid Build Coastguard Worker 227*9880d681SAndroid Build Coastguard Worker // For a half-diff relocation the length bits actually record whether this 228*9880d681SAndroid Build Coastguard Worker // is a movw/movt, and whether this is arm or thumb. 229*9880d681SAndroid Build Coastguard Worker // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1). 230*9880d681SAndroid Build Coastguard Worker // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1). 231*9880d681SAndroid Build Coastguard Worker unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE); 232*9880d681SAndroid Build Coastguard Worker if (HalfDiffKindBits & 0x2) 233*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Thumb not yet supported."); 234*9880d681SAndroid Build Coastguard Worker 235*9880d681SAndroid Build Coastguard Worker SectionEntry &Section = Sections[SectionID]; 236*9880d681SAndroid Build Coastguard Worker uint32_t RelocType = MachO.getAnyRelocationType(RE); 237*9880d681SAndroid Build Coastguard Worker bool IsPCRel = MachO.getAnyRelocationPCRel(RE); 238*9880d681SAndroid Build Coastguard Worker uint64_t Offset = RelI->getOffset(); 239*9880d681SAndroid Build Coastguard Worker uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 240*9880d681SAndroid Build Coastguard Worker int64_t Immediate = readBytesUnaligned(LocalAddress, 4); // Copy the whole instruction out. 241*9880d681SAndroid Build Coastguard Worker Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff); 242*9880d681SAndroid Build Coastguard Worker 243*9880d681SAndroid Build Coastguard Worker ++RelI; 244*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info RE2 = 245*9880d681SAndroid Build Coastguard Worker MachO.getRelocation(RelI->getRawDataRefImpl()); 246*9880d681SAndroid Build Coastguard Worker uint32_t AddrA = MachO.getScatteredRelocationValue(RE); 247*9880d681SAndroid Build Coastguard Worker section_iterator SAI = getSectionByAddress(MachO, AddrA); 248*9880d681SAndroid Build Coastguard Worker assert(SAI != MachO.section_end() && "Can't find section for address A"); 249*9880d681SAndroid Build Coastguard Worker uint64_t SectionABase = SAI->getAddress(); 250*9880d681SAndroid Build Coastguard Worker uint64_t SectionAOffset = AddrA - SectionABase; 251*9880d681SAndroid Build Coastguard Worker SectionRef SectionA = *SAI; 252*9880d681SAndroid Build Coastguard Worker bool IsCode = SectionA.isText(); 253*9880d681SAndroid Build Coastguard Worker uint32_t SectionAID = ~0U; 254*9880d681SAndroid Build Coastguard Worker if (auto SectionAIDOrErr = 255*9880d681SAndroid Build Coastguard Worker findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID)) 256*9880d681SAndroid Build Coastguard Worker SectionAID = *SectionAIDOrErr; 257*9880d681SAndroid Build Coastguard Worker else 258*9880d681SAndroid Build Coastguard Worker return SectionAIDOrErr.takeError(); 259*9880d681SAndroid Build Coastguard Worker 260*9880d681SAndroid Build Coastguard Worker uint32_t AddrB = MachO.getScatteredRelocationValue(RE2); 261*9880d681SAndroid Build Coastguard Worker section_iterator SBI = getSectionByAddress(MachO, AddrB); 262*9880d681SAndroid Build Coastguard Worker assert(SBI != MachO.section_end() && "Can't find section for address B"); 263*9880d681SAndroid Build Coastguard Worker uint64_t SectionBBase = SBI->getAddress(); 264*9880d681SAndroid Build Coastguard Worker uint64_t SectionBOffset = AddrB - SectionBBase; 265*9880d681SAndroid Build Coastguard Worker SectionRef SectionB = *SBI; 266*9880d681SAndroid Build Coastguard Worker uint32_t SectionBID = ~0U; 267*9880d681SAndroid Build Coastguard Worker if (auto SectionBIDOrErr = 268*9880d681SAndroid Build Coastguard Worker findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID)) 269*9880d681SAndroid Build Coastguard Worker SectionBID = *SectionBIDOrErr; 270*9880d681SAndroid Build Coastguard Worker else 271*9880d681SAndroid Build Coastguard Worker return SectionBIDOrErr.takeError(); 272*9880d681SAndroid Build Coastguard Worker 273*9880d681SAndroid Build Coastguard Worker uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff; 274*9880d681SAndroid Build Coastguard Worker unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0; 275*9880d681SAndroid Build Coastguard Worker uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift)); 276*9880d681SAndroid Build Coastguard Worker int64_t Addend = FullImmVal - (AddrA - AddrB); 277*9880d681SAndroid Build Coastguard Worker 278*9880d681SAndroid Build Coastguard Worker // addend = Encoded - Expected 279*9880d681SAndroid Build Coastguard Worker // = Encoded - (AddrA - AddrB) 280*9880d681SAndroid Build Coastguard Worker 281*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB 282*9880d681SAndroid Build Coastguard Worker << ", Addend: " << Addend << ", SectionA ID: " << SectionAID 283*9880d681SAndroid Build Coastguard Worker << ", SectionAOffset: " << SectionAOffset 284*9880d681SAndroid Build Coastguard Worker << ", SectionB ID: " << SectionBID 285*9880d681SAndroid Build Coastguard Worker << ", SectionBOffset: " << SectionBOffset << "\n"); 286*9880d681SAndroid Build Coastguard Worker RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, 287*9880d681SAndroid Build Coastguard Worker SectionAOffset, SectionBID, SectionBOffset, IsPCRel, 288*9880d681SAndroid Build Coastguard Worker HalfDiffKindBits); 289*9880d681SAndroid Build Coastguard Worker 290*9880d681SAndroid Build Coastguard Worker addRelocationForSection(R, SectionAID); 291*9880d681SAndroid Build Coastguard Worker addRelocationForSection(R, SectionBID); 292*9880d681SAndroid Build Coastguard Worker 293*9880d681SAndroid Build Coastguard Worker return ++RelI; 294*9880d681SAndroid Build Coastguard Worker } 295*9880d681SAndroid Build Coastguard Worker 296*9880d681SAndroid Build Coastguard Worker }; 297*9880d681SAndroid Build Coastguard Worker } 298*9880d681SAndroid Build Coastguard Worker 299*9880d681SAndroid Build Coastguard Worker #undef DEBUG_TYPE 300*9880d681SAndroid Build Coastguard Worker 301*9880d681SAndroid Build Coastguard Worker #endif 302