1274955Ssvnmir//===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- C++ -*-=// 2274955Ssvnmir// 3274955Ssvnmir// The LLVM Compiler Infrastructure 4274955Ssvnmir// 5274955Ssvnmir// This file is distributed under the University of Illinois Open Source 6274955Ssvnmir// License. See LICENSE.TXT for details. 7274955Ssvnmir// 8274955Ssvnmir//===----------------------------------------------------------------------===// 9274955Ssvnmir 10280031Sdim#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 11280031Sdim#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 12274955Ssvnmir 13274955Ssvnmir#include "../RuntimeDyldMachO.h" 14274955Ssvnmir 15274955Ssvnmir#define DEBUG_TYPE "dyld" 16274955Ssvnmir 17274955Ssvnmirnamespace llvm { 18274955Ssvnmir 19274955Ssvnmirclass RuntimeDyldMachOI386 20274955Ssvnmir : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { 21274955Ssvnmirpublic: 22280031Sdim 23280031Sdim typedef uint32_t TargetPtrT; 24280031Sdim 25288943Sdim RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM, 26288943Sdim RuntimeDyld::SymbolResolver &Resolver) 27288943Sdim : RuntimeDyldMachOCRTPBase(MM, Resolver) {} 28274955Ssvnmir 29274955Ssvnmir unsigned getMaxStubSize() override { return 0; } 30274955Ssvnmir 31274955Ssvnmir unsigned getStubAlignment() override { return 1; } 32274955Ssvnmir 33274955Ssvnmir relocation_iterator 34274955Ssvnmir processRelocationRef(unsigned SectionID, relocation_iterator RelI, 35280031Sdim const ObjectFile &BaseObjT, 36280031Sdim ObjSectionToIDMap &ObjSectionToID, 37280031Sdim StubMap &Stubs) override { 38274955Ssvnmir const MachOObjectFile &Obj = 39280031Sdim static_cast<const MachOObjectFile &>(BaseObjT); 40274955Ssvnmir MachO::any_relocation_info RelInfo = 41274955Ssvnmir Obj.getRelocation(RelI->getRawDataRefImpl()); 42274955Ssvnmir uint32_t RelType = Obj.getAnyRelocationType(RelInfo); 43274955Ssvnmir 44274955Ssvnmir if (Obj.isRelocationScattered(RelInfo)) { 45274955Ssvnmir if (RelType == MachO::GENERIC_RELOC_SECTDIFF || 46274955Ssvnmir RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) 47280031Sdim return processSECTDIFFRelocation(SectionID, RelI, Obj, 48274955Ssvnmir ObjSectionToID); 49280031Sdim else if (RelType == MachO::GENERIC_RELOC_VANILLA) 50296417Sdim return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); 51274955Ssvnmir llvm_unreachable("Unhandled scattered relocation."); 52274955Ssvnmir } 53274955Ssvnmir 54280031Sdim RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 55280031Sdim RE.Addend = memcpyAddend(RE); 56274955Ssvnmir RelocationValueRef Value( 57280031Sdim getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); 58274955Ssvnmir 59274955Ssvnmir // Addends for external, PC-rel relocations on i386 point back to the zero 60274955Ssvnmir // offset. Calculate the final offset from the relocation target instead. 61274955Ssvnmir // This allows us to use the same logic for both external and internal 62274955Ssvnmir // relocations in resolveI386RelocationRef. 63274955Ssvnmir // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 64274955Ssvnmir // if (IsExtern && RE.IsPCRel) { 65274955Ssvnmir // uint64_t RelocAddr = 0; 66274955Ssvnmir // RelI->getAddress(RelocAddr); 67274955Ssvnmir // Value.Addend += RelocAddr + 4; 68274955Ssvnmir // } 69274955Ssvnmir if (RE.IsPCRel) 70288943Sdim makeValueAddendPCRel(Value, RelI, 1 << RE.Size); 71274955Ssvnmir 72280031Sdim RE.Addend = Value.Offset; 73274955Ssvnmir 74274955Ssvnmir if (Value.SymbolName) 75274955Ssvnmir addRelocationForSymbol(RE, Value.SymbolName); 76274955Ssvnmir else 77274955Ssvnmir addRelocationForSection(RE, Value.SectionID); 78274955Ssvnmir 79274955Ssvnmir return ++RelI; 80274955Ssvnmir } 81274955Ssvnmir 82280031Sdim void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 83274955Ssvnmir DEBUG(dumpRelocationToResolve(RE, Value)); 84274955Ssvnmir 85274955Ssvnmir const SectionEntry &Section = Sections[RE.SectionID]; 86296417Sdim uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 87274955Ssvnmir 88274955Ssvnmir if (RE.IsPCRel) { 89296417Sdim uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 90274955Ssvnmir Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 91274955Ssvnmir } 92274955Ssvnmir 93274955Ssvnmir switch (RE.RelType) { 94274955Ssvnmir default: 95274955Ssvnmir llvm_unreachable("Invalid relocation type!"); 96274955Ssvnmir case MachO::GENERIC_RELOC_VANILLA: 97280031Sdim writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 98274955Ssvnmir break; 99274955Ssvnmir case MachO::GENERIC_RELOC_SECTDIFF: 100274955Ssvnmir case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 101296417Sdim uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress(); 102296417Sdim uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress(); 103274955Ssvnmir assert((Value == SectionABase || Value == SectionBBase) && 104274955Ssvnmir "Unexpected SECTDIFF relocation value."); 105274955Ssvnmir Value = SectionABase - SectionBBase + RE.Addend; 106280031Sdim writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); 107274955Ssvnmir break; 108274955Ssvnmir } 109274955Ssvnmir case MachO::GENERIC_RELOC_PB_LA_PTR: 110274955Ssvnmir Error("Relocation type not implemented yet!"); 111274955Ssvnmir } 112274955Ssvnmir } 113274955Ssvnmir 114280031Sdim void finalizeSection(const ObjectFile &Obj, unsigned SectionID, 115274955Ssvnmir const SectionRef &Section) { 116274955Ssvnmir StringRef Name; 117274955Ssvnmir Section.getName(Name); 118274955Ssvnmir 119274955Ssvnmir if (Name == "__jump_table") 120280031Sdim populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID); 121274955Ssvnmir else if (Name == "__pointers") 122280031Sdim populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), 123280031Sdim Section, SectionID); 124274955Ssvnmir } 125274955Ssvnmir 126274955Ssvnmirprivate: 127274955Ssvnmir relocation_iterator 128274955Ssvnmir processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 129280031Sdim const ObjectFile &BaseObjT, 130274955Ssvnmir ObjSectionToIDMap &ObjSectionToID) { 131280031Sdim const MachOObjectFile &Obj = 132280031Sdim static_cast<const MachOObjectFile&>(BaseObjT); 133274955Ssvnmir MachO::any_relocation_info RE = 134280031Sdim Obj.getRelocation(RelI->getRawDataRefImpl()); 135274955Ssvnmir 136274955Ssvnmir SectionEntry &Section = Sections[SectionID]; 137280031Sdim uint32_t RelocType = Obj.getAnyRelocationType(RE); 138280031Sdim bool IsPCRel = Obj.getAnyRelocationPCRel(RE); 139280031Sdim unsigned Size = Obj.getAnyRelocationLength(RE); 140288943Sdim uint64_t Offset = RelI->getOffset(); 141296417Sdim uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 142274955Ssvnmir unsigned NumBytes = 1 << Size; 143280031Sdim uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); 144274955Ssvnmir 145274955Ssvnmir ++RelI; 146274955Ssvnmir MachO::any_relocation_info RE2 = 147280031Sdim Obj.getRelocation(RelI->getRawDataRefImpl()); 148274955Ssvnmir 149280031Sdim uint32_t AddrA = Obj.getScatteredRelocationValue(RE); 150280031Sdim section_iterator SAI = getSectionByAddress(Obj, AddrA); 151280031Sdim assert(SAI != Obj.section_end() && "Can't find section for address A"); 152280031Sdim uint64_t SectionABase = SAI->getAddress(); 153274955Ssvnmir uint64_t SectionAOffset = AddrA - SectionABase; 154274955Ssvnmir SectionRef SectionA = *SAI; 155280031Sdim bool IsCode = SectionA.isText(); 156274955Ssvnmir uint32_t SectionAID = 157274955Ssvnmir findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); 158274955Ssvnmir 159280031Sdim uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); 160280031Sdim section_iterator SBI = getSectionByAddress(Obj, AddrB); 161280031Sdim assert(SBI != Obj.section_end() && "Can't find section for address B"); 162280031Sdim uint64_t SectionBBase = SBI->getAddress(); 163274955Ssvnmir uint64_t SectionBOffset = AddrB - SectionBBase; 164274955Ssvnmir SectionRef SectionB = *SBI; 165274955Ssvnmir uint32_t SectionBID = 166274955Ssvnmir findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID); 167274955Ssvnmir 168288943Sdim // Compute the addend 'C' from the original expression 'A - B + C'. 169288943Sdim Addend -= AddrA - AddrB; 170274955Ssvnmir 171274955Ssvnmir DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB 172274955Ssvnmir << ", Addend: " << Addend << ", SectionA ID: " << SectionAID 173274955Ssvnmir << ", SectionAOffset: " << SectionAOffset 174274955Ssvnmir << ", SectionB ID: " << SectionBID 175274955Ssvnmir << ", SectionBOffset: " << SectionBOffset << "\n"); 176288943Sdim RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, 177288943Sdim SectionAOffset, SectionBID, SectionBOffset, 178288943Sdim IsPCRel, Size); 179274955Ssvnmir 180274955Ssvnmir addRelocationForSection(R, SectionAID); 181274955Ssvnmir 182274955Ssvnmir return ++RelI; 183274955Ssvnmir } 184274955Ssvnmir 185274955Ssvnmir // Populate stubs in __jump_table section. 186280031Sdim void populateJumpTable(const MachOObjectFile &Obj, const SectionRef &JTSection, 187274955Ssvnmir unsigned JTSectionID) { 188274955Ssvnmir assert(!Obj.is64Bit() && 189274955Ssvnmir "__jump_table section not supported in 64-bit MachO."); 190274955Ssvnmir 191274955Ssvnmir MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 192274955Ssvnmir MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); 193274955Ssvnmir uint32_t JTSectionSize = Sec32.size; 194274955Ssvnmir unsigned FirstIndirectSymbol = Sec32.reserved1; 195274955Ssvnmir unsigned JTEntrySize = Sec32.reserved2; 196274955Ssvnmir unsigned NumJTEntries = JTSectionSize / JTEntrySize; 197274955Ssvnmir uint8_t *JTSectionAddr = getSectionAddress(JTSectionID); 198274955Ssvnmir unsigned JTEntryOffset = 0; 199274955Ssvnmir 200274955Ssvnmir assert((JTSectionSize % JTEntrySize) == 0 && 201274955Ssvnmir "Jump-table section does not contain a whole number of stubs?"); 202274955Ssvnmir 203274955Ssvnmir for (unsigned i = 0; i < NumJTEntries; ++i) { 204274955Ssvnmir unsigned SymbolIndex = 205274955Ssvnmir Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 206274955Ssvnmir symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 207288943Sdim ErrorOr<StringRef> IndirectSymbolName = SI->getName(); 208288943Sdim if (std::error_code EC = IndirectSymbolName.getError()) 209288943Sdim report_fatal_error(EC.message()); 210274955Ssvnmir uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset; 211274955Ssvnmir createStubFunction(JTEntryAddr); 212274955Ssvnmir RelocationEntry RE(JTSectionID, JTEntryOffset + 1, 213274955Ssvnmir MachO::GENERIC_RELOC_VANILLA, 0, true, 2); 214288943Sdim addRelocationForSymbol(RE, *IndirectSymbolName); 215274955Ssvnmir JTEntryOffset += JTEntrySize; 216274955Ssvnmir } 217274955Ssvnmir } 218274955Ssvnmir 219274955Ssvnmir}; 220274955Ssvnmir} 221274955Ssvnmir 222274955Ssvnmir#undef DEBUG_TYPE 223274955Ssvnmir 224280031Sdim#endif 225