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