1*9880d681SAndroid Build Coastguard Worker //===---- RuntimeDyldMachOI386.h ---- MachO/I386 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_RUNTIMEDYLDMACHOI386_H 11*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_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 RuntimeDyldMachOI386 21*9880d681SAndroid Build Coastguard Worker : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { 22*9880d681SAndroid Build Coastguard Worker public: 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard Worker typedef uint32_t TargetPtrT; 25*9880d681SAndroid Build Coastguard Worker RuntimeDyldMachOI386(RuntimeDyld::MemoryManager & MM,RuntimeDyld::SymbolResolver & Resolver)26*9880d681SAndroid Build Coastguard Worker RuntimeDyldMachOI386(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 0; } 31*9880d681SAndroid Build Coastguard Worker getStubAlignment()32*9880d681SAndroid Build Coastguard Worker unsigned getStubAlignment() override { return 1; } 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard Worker Expected<relocation_iterator> processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)35*9880d681SAndroid Build Coastguard Worker processRelocationRef(unsigned SectionID, relocation_iterator RelI, 36*9880d681SAndroid Build Coastguard Worker const ObjectFile &BaseObjT, 37*9880d681SAndroid Build Coastguard Worker ObjSectionToIDMap &ObjSectionToID, 38*9880d681SAndroid Build Coastguard Worker StubMap &Stubs) override { 39*9880d681SAndroid Build Coastguard Worker const MachOObjectFile &Obj = 40*9880d681SAndroid Build Coastguard Worker static_cast<const MachOObjectFile &>(BaseObjT); 41*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info RelInfo = 42*9880d681SAndroid Build Coastguard Worker Obj.getRelocation(RelI->getRawDataRefImpl()); 43*9880d681SAndroid Build Coastguard Worker uint32_t RelType = Obj.getAnyRelocationType(RelInfo); 44*9880d681SAndroid Build Coastguard Worker 45*9880d681SAndroid Build Coastguard Worker if (Obj.isRelocationScattered(RelInfo)) { 46*9880d681SAndroid Build Coastguard Worker if (RelType == MachO::GENERIC_RELOC_SECTDIFF || 47*9880d681SAndroid Build Coastguard Worker RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) 48*9880d681SAndroid Build Coastguard Worker return processSECTDIFFRelocation(SectionID, RelI, Obj, 49*9880d681SAndroid Build Coastguard Worker ObjSectionToID); 50*9880d681SAndroid Build Coastguard Worker else if (RelType == MachO::GENERIC_RELOC_VANILLA) 51*9880d681SAndroid Build Coastguard Worker return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); 52*9880d681SAndroid Build Coastguard Worker return make_error<RuntimeDyldError>(("Unhandled I386 scattered relocation " 53*9880d681SAndroid Build Coastguard Worker "type: " + Twine(RelType)).str()); 54*9880d681SAndroid Build Coastguard Worker } 55*9880d681SAndroid Build Coastguard Worker 56*9880d681SAndroid Build Coastguard Worker switch (RelType) { 57*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR); 58*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR); 59*9880d681SAndroid Build Coastguard Worker UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV); 60*9880d681SAndroid Build Coastguard Worker default: 61*9880d681SAndroid Build Coastguard Worker if (RelType > MachO::GENERIC_RELOC_TLV) 62*9880d681SAndroid Build Coastguard Worker return make_error<RuntimeDyldError>(("MachO I386 relocation type " + 63*9880d681SAndroid Build Coastguard Worker Twine(RelType) + 64*9880d681SAndroid Build Coastguard Worker " is out of range").str()); 65*9880d681SAndroid Build Coastguard Worker break; 66*9880d681SAndroid Build Coastguard Worker } 67*9880d681SAndroid Build Coastguard Worker 68*9880d681SAndroid Build Coastguard Worker RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 69*9880d681SAndroid Build Coastguard Worker RE.Addend = memcpyAddend(RE); 70*9880d681SAndroid Build Coastguard Worker RelocationValueRef Value; 71*9880d681SAndroid Build Coastguard Worker if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) 72*9880d681SAndroid Build Coastguard Worker Value = *ValueOrErr; 73*9880d681SAndroid Build Coastguard Worker else 74*9880d681SAndroid Build Coastguard Worker return ValueOrErr.takeError(); 75*9880d681SAndroid Build Coastguard Worker 76*9880d681SAndroid Build Coastguard Worker // Addends for external, PC-rel relocations on i386 point back to the zero 77*9880d681SAndroid Build Coastguard Worker // offset. Calculate the final offset from the relocation target instead. 78*9880d681SAndroid Build Coastguard Worker // This allows us to use the same logic for both external and internal 79*9880d681SAndroid Build Coastguard Worker // relocations in resolveI386RelocationRef. 80*9880d681SAndroid Build Coastguard Worker // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 81*9880d681SAndroid Build Coastguard Worker // if (IsExtern && RE.IsPCRel) { 82*9880d681SAndroid Build Coastguard Worker // uint64_t RelocAddr = 0; 83*9880d681SAndroid Build Coastguard Worker // RelI->getAddress(RelocAddr); 84*9880d681SAndroid Build Coastguard Worker // Value.Addend += RelocAddr + 4; 85*9880d681SAndroid Build Coastguard Worker // } 86*9880d681SAndroid Build Coastguard Worker if (RE.IsPCRel) 87*9880d681SAndroid Build Coastguard Worker makeValueAddendPCRel(Value, RelI, 1 << RE.Size); 88*9880d681SAndroid Build Coastguard Worker 89*9880d681SAndroid Build Coastguard Worker RE.Addend = Value.Offset; 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker if (Value.SymbolName) 92*9880d681SAndroid Build Coastguard Worker addRelocationForSymbol(RE, Value.SymbolName); 93*9880d681SAndroid Build Coastguard Worker else 94*9880d681SAndroid Build Coastguard Worker addRelocationForSection(RE, Value.SectionID); 95*9880d681SAndroid Build Coastguard Worker 96*9880d681SAndroid Build Coastguard Worker return ++RelI; 97*9880d681SAndroid Build Coastguard Worker } 98*9880d681SAndroid Build Coastguard Worker resolveRelocation(const RelocationEntry & RE,uint64_t Value)99*9880d681SAndroid Build Coastguard Worker void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 100*9880d681SAndroid Build Coastguard Worker DEBUG(dumpRelocationToResolve(RE, Value)); 101*9880d681SAndroid Build Coastguard Worker 102*9880d681SAndroid Build Coastguard Worker const SectionEntry &Section = Sections[RE.SectionID]; 103*9880d681SAndroid Build Coastguard Worker uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 104*9880d681SAndroid Build Coastguard Worker 105*9880d681SAndroid Build Coastguard Worker if (RE.IsPCRel) { 106*9880d681SAndroid Build Coastguard Worker uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 107*9880d681SAndroid Build Coastguard Worker Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 108*9880d681SAndroid Build Coastguard Worker } 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker switch (RE.RelType) { 111*9880d681SAndroid Build Coastguard Worker case MachO::GENERIC_RELOC_VANILLA: 112*9880d681SAndroid Build Coastguard Worker writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 113*9880d681SAndroid Build Coastguard Worker break; 114*9880d681SAndroid Build Coastguard Worker case MachO::GENERIC_RELOC_SECTDIFF: 115*9880d681SAndroid Build Coastguard Worker case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 116*9880d681SAndroid Build Coastguard Worker uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress(); 117*9880d681SAndroid Build Coastguard Worker uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress(); 118*9880d681SAndroid Build Coastguard Worker assert((Value == SectionABase || Value == SectionBBase) && 119*9880d681SAndroid Build Coastguard Worker "Unexpected SECTDIFF relocation value."); 120*9880d681SAndroid Build Coastguard Worker Value = SectionABase - SectionBBase + RE.Addend; 121*9880d681SAndroid Build Coastguard Worker writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); 122*9880d681SAndroid Build Coastguard Worker break; 123*9880d681SAndroid Build Coastguard Worker } 124*9880d681SAndroid Build Coastguard Worker default: 125*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid relocation type!"); 126*9880d681SAndroid Build Coastguard Worker } 127*9880d681SAndroid Build Coastguard Worker } 128*9880d681SAndroid Build Coastguard Worker finalizeSection(const ObjectFile & Obj,unsigned SectionID,const SectionRef & Section)129*9880d681SAndroid Build Coastguard Worker Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, 130*9880d681SAndroid Build Coastguard Worker const SectionRef &Section) { 131*9880d681SAndroid Build Coastguard Worker StringRef Name; 132*9880d681SAndroid Build Coastguard Worker Section.getName(Name); 133*9880d681SAndroid Build Coastguard Worker 134*9880d681SAndroid Build Coastguard Worker if (Name == "__jump_table") 135*9880d681SAndroid Build Coastguard Worker return populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID); 136*9880d681SAndroid Build Coastguard Worker else if (Name == "__pointers") 137*9880d681SAndroid Build Coastguard Worker return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), 138*9880d681SAndroid Build Coastguard Worker Section, SectionID); 139*9880d681SAndroid Build Coastguard Worker return Error::success(); 140*9880d681SAndroid Build Coastguard Worker } 141*9880d681SAndroid Build Coastguard Worker 142*9880d681SAndroid Build Coastguard Worker private: 143*9880d681SAndroid Build Coastguard Worker Expected<relocation_iterator> processSECTDIFFRelocation(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID)144*9880d681SAndroid Build Coastguard Worker processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 145*9880d681SAndroid Build Coastguard Worker const ObjectFile &BaseObjT, 146*9880d681SAndroid Build Coastguard Worker ObjSectionToIDMap &ObjSectionToID) { 147*9880d681SAndroid Build Coastguard Worker const MachOObjectFile &Obj = 148*9880d681SAndroid Build Coastguard Worker static_cast<const MachOObjectFile&>(BaseObjT); 149*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info RE = 150*9880d681SAndroid Build Coastguard Worker Obj.getRelocation(RelI->getRawDataRefImpl()); 151*9880d681SAndroid Build Coastguard Worker 152*9880d681SAndroid Build Coastguard Worker SectionEntry &Section = Sections[SectionID]; 153*9880d681SAndroid Build Coastguard Worker uint32_t RelocType = Obj.getAnyRelocationType(RE); 154*9880d681SAndroid Build Coastguard Worker bool IsPCRel = Obj.getAnyRelocationPCRel(RE); 155*9880d681SAndroid Build Coastguard Worker unsigned Size = Obj.getAnyRelocationLength(RE); 156*9880d681SAndroid Build Coastguard Worker uint64_t Offset = RelI->getOffset(); 157*9880d681SAndroid Build Coastguard Worker uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 158*9880d681SAndroid Build Coastguard Worker unsigned NumBytes = 1 << Size; 159*9880d681SAndroid Build Coastguard Worker uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); 160*9880d681SAndroid Build Coastguard Worker 161*9880d681SAndroid Build Coastguard Worker ++RelI; 162*9880d681SAndroid Build Coastguard Worker MachO::any_relocation_info RE2 = 163*9880d681SAndroid Build Coastguard Worker Obj.getRelocation(RelI->getRawDataRefImpl()); 164*9880d681SAndroid Build Coastguard Worker 165*9880d681SAndroid Build Coastguard Worker uint32_t AddrA = Obj.getScatteredRelocationValue(RE); 166*9880d681SAndroid Build Coastguard Worker section_iterator SAI = getSectionByAddress(Obj, AddrA); 167*9880d681SAndroid Build Coastguard Worker assert(SAI != Obj.section_end() && "Can't find section for address A"); 168*9880d681SAndroid Build Coastguard Worker uint64_t SectionABase = SAI->getAddress(); 169*9880d681SAndroid Build Coastguard Worker uint64_t SectionAOffset = AddrA - SectionABase; 170*9880d681SAndroid Build Coastguard Worker SectionRef SectionA = *SAI; 171*9880d681SAndroid Build Coastguard Worker bool IsCode = SectionA.isText(); 172*9880d681SAndroid Build Coastguard Worker uint32_t SectionAID = ~0U; 173*9880d681SAndroid Build Coastguard Worker if (auto SectionAIDOrErr = 174*9880d681SAndroid Build Coastguard Worker findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID)) 175*9880d681SAndroid Build Coastguard Worker SectionAID = *SectionAIDOrErr; 176*9880d681SAndroid Build Coastguard Worker else 177*9880d681SAndroid Build Coastguard Worker return SectionAIDOrErr.takeError(); 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); 180*9880d681SAndroid Build Coastguard Worker section_iterator SBI = getSectionByAddress(Obj, AddrB); 181*9880d681SAndroid Build Coastguard Worker assert(SBI != Obj.section_end() && "Can't find section for address B"); 182*9880d681SAndroid Build Coastguard Worker uint64_t SectionBBase = SBI->getAddress(); 183*9880d681SAndroid Build Coastguard Worker uint64_t SectionBOffset = AddrB - SectionBBase; 184*9880d681SAndroid Build Coastguard Worker SectionRef SectionB = *SBI; 185*9880d681SAndroid Build Coastguard Worker uint32_t SectionBID = ~0U; 186*9880d681SAndroid Build Coastguard Worker if (auto SectionBIDOrErr = 187*9880d681SAndroid Build Coastguard Worker findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID)) 188*9880d681SAndroid Build Coastguard Worker SectionBID = *SectionBIDOrErr; 189*9880d681SAndroid Build Coastguard Worker else 190*9880d681SAndroid Build Coastguard Worker return SectionBIDOrErr.takeError(); 191*9880d681SAndroid Build Coastguard Worker 192*9880d681SAndroid Build Coastguard Worker // Compute the addend 'C' from the original expression 'A - B + C'. 193*9880d681SAndroid Build Coastguard Worker Addend -= AddrA - AddrB; 194*9880d681SAndroid Build Coastguard Worker 195*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB 196*9880d681SAndroid Build Coastguard Worker << ", Addend: " << Addend << ", SectionA ID: " << SectionAID 197*9880d681SAndroid Build Coastguard Worker << ", SectionAOffset: " << SectionAOffset 198*9880d681SAndroid Build Coastguard Worker << ", SectionB ID: " << SectionBID 199*9880d681SAndroid Build Coastguard Worker << ", SectionBOffset: " << SectionBOffset << "\n"); 200*9880d681SAndroid Build Coastguard Worker RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, 201*9880d681SAndroid Build Coastguard Worker SectionAOffset, SectionBID, SectionBOffset, 202*9880d681SAndroid Build Coastguard Worker IsPCRel, Size); 203*9880d681SAndroid Build Coastguard Worker 204*9880d681SAndroid Build Coastguard Worker addRelocationForSection(R, SectionAID); 205*9880d681SAndroid Build Coastguard Worker 206*9880d681SAndroid Build Coastguard Worker return ++RelI; 207*9880d681SAndroid Build Coastguard Worker } 208*9880d681SAndroid Build Coastguard Worker 209*9880d681SAndroid Build Coastguard Worker // Populate stubs in __jump_table section. populateJumpTable(const MachOObjectFile & Obj,const SectionRef & JTSection,unsigned JTSectionID)210*9880d681SAndroid Build Coastguard Worker Error populateJumpTable(const MachOObjectFile &Obj, 211*9880d681SAndroid Build Coastguard Worker const SectionRef &JTSection, 212*9880d681SAndroid Build Coastguard Worker unsigned JTSectionID) { 213*9880d681SAndroid Build Coastguard Worker MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 214*9880d681SAndroid Build Coastguard Worker MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); 215*9880d681SAndroid Build Coastguard Worker uint32_t JTSectionSize = Sec32.size; 216*9880d681SAndroid Build Coastguard Worker unsigned FirstIndirectSymbol = Sec32.reserved1; 217*9880d681SAndroid Build Coastguard Worker unsigned JTEntrySize = Sec32.reserved2; 218*9880d681SAndroid Build Coastguard Worker unsigned NumJTEntries = JTSectionSize / JTEntrySize; 219*9880d681SAndroid Build Coastguard Worker uint8_t *JTSectionAddr = getSectionAddress(JTSectionID); 220*9880d681SAndroid Build Coastguard Worker unsigned JTEntryOffset = 0; 221*9880d681SAndroid Build Coastguard Worker 222*9880d681SAndroid Build Coastguard Worker if (JTSectionSize % JTEntrySize != 0) 223*9880d681SAndroid Build Coastguard Worker return make_error<RuntimeDyldError>("Jump-table section does not contain " 224*9880d681SAndroid Build Coastguard Worker "a whole number of stubs?"); 225*9880d681SAndroid Build Coastguard Worker 226*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumJTEntries; ++i) { 227*9880d681SAndroid Build Coastguard Worker unsigned SymbolIndex = 228*9880d681SAndroid Build Coastguard Worker Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 229*9880d681SAndroid Build Coastguard Worker symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 230*9880d681SAndroid Build Coastguard Worker Expected<StringRef> IndirectSymbolName = SI->getName(); 231*9880d681SAndroid Build Coastguard Worker if (!IndirectSymbolName) 232*9880d681SAndroid Build Coastguard Worker return IndirectSymbolName.takeError(); 233*9880d681SAndroid Build Coastguard Worker uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset; 234*9880d681SAndroid Build Coastguard Worker createStubFunction(JTEntryAddr); 235*9880d681SAndroid Build Coastguard Worker RelocationEntry RE(JTSectionID, JTEntryOffset + 1, 236*9880d681SAndroid Build Coastguard Worker MachO::GENERIC_RELOC_VANILLA, 0, true, 2); 237*9880d681SAndroid Build Coastguard Worker addRelocationForSymbol(RE, *IndirectSymbolName); 238*9880d681SAndroid Build Coastguard Worker JTEntryOffset += JTEntrySize; 239*9880d681SAndroid Build Coastguard Worker } 240*9880d681SAndroid Build Coastguard Worker 241*9880d681SAndroid Build Coastguard Worker return Error::success(); 242*9880d681SAndroid Build Coastguard Worker } 243*9880d681SAndroid Build Coastguard Worker 244*9880d681SAndroid Build Coastguard Worker }; 245*9880d681SAndroid Build Coastguard Worker } 246*9880d681SAndroid Build Coastguard Worker 247*9880d681SAndroid Build Coastguard Worker #undef DEBUG_TYPE 248*9880d681SAndroid Build Coastguard Worker 249*9880d681SAndroid Build Coastguard Worker #endif 250