10b57cec5SDimitry Andric //===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- C++ -*-=// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 100b57cec5SDimitry Andric #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "../RuntimeDyldMachO.h" 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #define DEBUG_TYPE "dyld" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric namespace llvm { 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric class RuntimeDyldMachOI386 190b57cec5SDimitry Andric : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> { 200b57cec5SDimitry Andric public: 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric typedef uint32_t TargetPtrT; 230b57cec5SDimitry Andric RuntimeDyldMachOI386(RuntimeDyld::MemoryManager & MM,JITSymbolResolver & Resolver)240b57cec5SDimitry Andric RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM, 250b57cec5SDimitry Andric JITSymbolResolver &Resolver) 260b57cec5SDimitry Andric : RuntimeDyldMachOCRTPBase(MM, Resolver) {} 270b57cec5SDimitry Andric getMaxStubSize()280b57cec5SDimitry Andric unsigned getMaxStubSize() const override { return 0; } 290b57cec5SDimitry Andric getStubAlignment()30*bdd1243dSDimitry Andric Align getStubAlignment() override { return Align(1); } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric Expected<relocation_iterator> processRelocationRef(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID,StubMap & Stubs)330b57cec5SDimitry Andric processRelocationRef(unsigned SectionID, relocation_iterator RelI, 340b57cec5SDimitry Andric const ObjectFile &BaseObjT, 350b57cec5SDimitry Andric ObjSectionToIDMap &ObjSectionToID, 360b57cec5SDimitry Andric StubMap &Stubs) override { 370b57cec5SDimitry Andric const MachOObjectFile &Obj = 380b57cec5SDimitry Andric static_cast<const MachOObjectFile &>(BaseObjT); 390b57cec5SDimitry Andric MachO::any_relocation_info RelInfo = 400b57cec5SDimitry Andric Obj.getRelocation(RelI->getRawDataRefImpl()); 410b57cec5SDimitry Andric uint32_t RelType = Obj.getAnyRelocationType(RelInfo); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric if (Obj.isRelocationScattered(RelInfo)) { 440b57cec5SDimitry Andric if (RelType == MachO::GENERIC_RELOC_SECTDIFF || 450b57cec5SDimitry Andric RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) 460b57cec5SDimitry Andric return processSECTDIFFRelocation(SectionID, RelI, Obj, 470b57cec5SDimitry Andric ObjSectionToID); 480b57cec5SDimitry Andric else if (RelType == MachO::GENERIC_RELOC_VANILLA) 490b57cec5SDimitry Andric return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); 500b57cec5SDimitry Andric return make_error<RuntimeDyldError>(("Unhandled I386 scattered relocation " 510b57cec5SDimitry Andric "type: " + Twine(RelType)).str()); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric switch (RelType) { 550b57cec5SDimitry Andric UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR); 560b57cec5SDimitry Andric UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR); 570b57cec5SDimitry Andric UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV); 580b57cec5SDimitry Andric default: 590b57cec5SDimitry Andric if (RelType > MachO::GENERIC_RELOC_TLV) 600b57cec5SDimitry Andric return make_error<RuntimeDyldError>(("MachO I386 relocation type " + 610b57cec5SDimitry Andric Twine(RelType) + 620b57cec5SDimitry Andric " is out of range").str()); 630b57cec5SDimitry Andric break; 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); 670b57cec5SDimitry Andric RE.Addend = memcpyAddend(RE); 680b57cec5SDimitry Andric RelocationValueRef Value; 690b57cec5SDimitry Andric if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)) 700b57cec5SDimitry Andric Value = *ValueOrErr; 710b57cec5SDimitry Andric else 720b57cec5SDimitry Andric return ValueOrErr.takeError(); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Addends for external, PC-rel relocations on i386 point back to the zero 750b57cec5SDimitry Andric // offset. Calculate the final offset from the relocation target instead. 760b57cec5SDimitry Andric // This allows us to use the same logic for both external and internal 770b57cec5SDimitry Andric // relocations in resolveI386RelocationRef. 780b57cec5SDimitry Andric // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); 790b57cec5SDimitry Andric // if (IsExtern && RE.IsPCRel) { 800b57cec5SDimitry Andric // uint64_t RelocAddr = 0; 810b57cec5SDimitry Andric // RelI->getAddress(RelocAddr); 820b57cec5SDimitry Andric // Value.Addend += RelocAddr + 4; 830b57cec5SDimitry Andric // } 840b57cec5SDimitry Andric if (RE.IsPCRel) 850b57cec5SDimitry Andric makeValueAddendPCRel(Value, RelI, 1 << RE.Size); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric RE.Addend = Value.Offset; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric if (Value.SymbolName) 900b57cec5SDimitry Andric addRelocationForSymbol(RE, Value.SymbolName); 910b57cec5SDimitry Andric else 920b57cec5SDimitry Andric addRelocationForSection(RE, Value.SectionID); 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric return ++RelI; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric resolveRelocation(const RelocationEntry & RE,uint64_t Value)970b57cec5SDimitry Andric void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { 980b57cec5SDimitry Andric LLVM_DEBUG(dumpRelocationToResolve(RE, Value)); 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric const SectionEntry &Section = Sections[RE.SectionID]; 1010b57cec5SDimitry Andric uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric if (RE.IsPCRel) { 1040b57cec5SDimitry Andric uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset); 1050b57cec5SDimitry Andric Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric switch (RE.RelType) { 1090b57cec5SDimitry Andric case MachO::GENERIC_RELOC_VANILLA: 1100b57cec5SDimitry Andric writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); 1110b57cec5SDimitry Andric break; 1120b57cec5SDimitry Andric case MachO::GENERIC_RELOC_SECTDIFF: 1130b57cec5SDimitry Andric case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 1140b57cec5SDimitry Andric uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress(); 1150b57cec5SDimitry Andric uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress(); 1160b57cec5SDimitry Andric assert((Value == SectionABase || Value == SectionBBase) && 1170b57cec5SDimitry Andric "Unexpected SECTDIFF relocation value."); 1180b57cec5SDimitry Andric Value = SectionABase - SectionBBase + RE.Addend; 1190b57cec5SDimitry Andric writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); 1200b57cec5SDimitry Andric break; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric default: 1230b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type!"); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric finalizeSection(const ObjectFile & Obj,unsigned SectionID,const SectionRef & Section)1270b57cec5SDimitry Andric Error finalizeSection(const ObjectFile &Obj, unsigned SectionID, 1280b57cec5SDimitry Andric const SectionRef &Section) { 1290b57cec5SDimitry Andric StringRef Name; 1308bcb0991SDimitry Andric if (Expected<StringRef> NameOrErr = Section.getName()) 1318bcb0991SDimitry Andric Name = *NameOrErr; 1328bcb0991SDimitry Andric else 1338bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric if (Name == "__jump_table") 1360b57cec5SDimitry Andric return populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID); 1370b57cec5SDimitry Andric else if (Name == "__pointers") 1380b57cec5SDimitry Andric return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj), 1390b57cec5SDimitry Andric Section, SectionID); 1400b57cec5SDimitry Andric return Error::success(); 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric private: 1440b57cec5SDimitry Andric Expected<relocation_iterator> processSECTDIFFRelocation(unsigned SectionID,relocation_iterator RelI,const ObjectFile & BaseObjT,ObjSectionToIDMap & ObjSectionToID)1450b57cec5SDimitry Andric processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, 1460b57cec5SDimitry Andric const ObjectFile &BaseObjT, 1470b57cec5SDimitry Andric ObjSectionToIDMap &ObjSectionToID) { 1480b57cec5SDimitry Andric const MachOObjectFile &Obj = 1490b57cec5SDimitry Andric static_cast<const MachOObjectFile&>(BaseObjT); 1500b57cec5SDimitry Andric MachO::any_relocation_info RE = 1510b57cec5SDimitry Andric Obj.getRelocation(RelI->getRawDataRefImpl()); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric SectionEntry &Section = Sections[SectionID]; 1540b57cec5SDimitry Andric uint32_t RelocType = Obj.getAnyRelocationType(RE); 1550b57cec5SDimitry Andric bool IsPCRel = Obj.getAnyRelocationPCRel(RE); 1560b57cec5SDimitry Andric unsigned Size = Obj.getAnyRelocationLength(RE); 1570b57cec5SDimitry Andric uint64_t Offset = RelI->getOffset(); 1580b57cec5SDimitry Andric uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 1590b57cec5SDimitry Andric unsigned NumBytes = 1 << Size; 1600b57cec5SDimitry Andric uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric ++RelI; 1630b57cec5SDimitry Andric MachO::any_relocation_info RE2 = 1640b57cec5SDimitry Andric Obj.getRelocation(RelI->getRawDataRefImpl()); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric uint32_t AddrA = Obj.getScatteredRelocationValue(RE); 1670b57cec5SDimitry Andric section_iterator SAI = getSectionByAddress(Obj, AddrA); 1680b57cec5SDimitry Andric assert(SAI != Obj.section_end() && "Can't find section for address A"); 1690b57cec5SDimitry Andric uint64_t SectionABase = SAI->getAddress(); 1700b57cec5SDimitry Andric uint64_t SectionAOffset = AddrA - SectionABase; 1710b57cec5SDimitry Andric SectionRef SectionA = *SAI; 1720b57cec5SDimitry Andric bool IsCode = SectionA.isText(); 1730b57cec5SDimitry Andric uint32_t SectionAID = ~0U; 1740b57cec5SDimitry Andric if (auto SectionAIDOrErr = 1750b57cec5SDimitry Andric findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID)) 1760b57cec5SDimitry Andric SectionAID = *SectionAIDOrErr; 1770b57cec5SDimitry Andric else 1780b57cec5SDimitry Andric return SectionAIDOrErr.takeError(); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); 1810b57cec5SDimitry Andric section_iterator SBI = getSectionByAddress(Obj, AddrB); 1820b57cec5SDimitry Andric assert(SBI != Obj.section_end() && "Can't find section for address B"); 1830b57cec5SDimitry Andric uint64_t SectionBBase = SBI->getAddress(); 1840b57cec5SDimitry Andric uint64_t SectionBOffset = AddrB - SectionBBase; 1850b57cec5SDimitry Andric SectionRef SectionB = *SBI; 1860b57cec5SDimitry Andric uint32_t SectionBID = ~0U; 1870b57cec5SDimitry Andric if (auto SectionBIDOrErr = 1880b57cec5SDimitry Andric findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID)) 1890b57cec5SDimitry Andric SectionBID = *SectionBIDOrErr; 1900b57cec5SDimitry Andric else 1910b57cec5SDimitry Andric return SectionBIDOrErr.takeError(); 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric // Compute the addend 'C' from the original expression 'A - B + C'. 1940b57cec5SDimitry Andric Addend -= AddrA - AddrB; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA 1970b57cec5SDimitry Andric << ", AddrB: " << AddrB << ", Addend: " << Addend 1980b57cec5SDimitry Andric << ", SectionA ID: " << SectionAID << ", SectionAOffset: " 1990b57cec5SDimitry Andric << SectionAOffset << ", SectionB ID: " << SectionBID 2000b57cec5SDimitry Andric << ", SectionBOffset: " << SectionBOffset << "\n"); 2010b57cec5SDimitry Andric RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, 2020b57cec5SDimitry Andric SectionAOffset, SectionBID, SectionBOffset, 2030b57cec5SDimitry Andric IsPCRel, Size); 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric addRelocationForSection(R, SectionAID); 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric return ++RelI; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric // Populate stubs in __jump_table section. populateJumpTable(const MachOObjectFile & Obj,const SectionRef & JTSection,unsigned JTSectionID)2110b57cec5SDimitry Andric Error populateJumpTable(const MachOObjectFile &Obj, 2120b57cec5SDimitry Andric const SectionRef &JTSection, 2130b57cec5SDimitry Andric unsigned JTSectionID) { 2140b57cec5SDimitry Andric MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 2150b57cec5SDimitry Andric MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); 2160b57cec5SDimitry Andric uint32_t JTSectionSize = Sec32.size; 2170b57cec5SDimitry Andric unsigned FirstIndirectSymbol = Sec32.reserved1; 2180b57cec5SDimitry Andric unsigned JTEntrySize = Sec32.reserved2; 2190b57cec5SDimitry Andric unsigned NumJTEntries = JTSectionSize / JTEntrySize; 2200b57cec5SDimitry Andric uint8_t *JTSectionAddr = getSectionAddress(JTSectionID); 2210b57cec5SDimitry Andric unsigned JTEntryOffset = 0; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric if (JTSectionSize % JTEntrySize != 0) 2240b57cec5SDimitry Andric return make_error<RuntimeDyldError>("Jump-table section does not contain " 2250b57cec5SDimitry Andric "a whole number of stubs?"); 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric for (unsigned i = 0; i < NumJTEntries; ++i) { 2280b57cec5SDimitry Andric unsigned SymbolIndex = 2290b57cec5SDimitry Andric Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 2300b57cec5SDimitry Andric symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 2310b57cec5SDimitry Andric Expected<StringRef> IndirectSymbolName = SI->getName(); 2320b57cec5SDimitry Andric if (!IndirectSymbolName) 2330b57cec5SDimitry Andric return IndirectSymbolName.takeError(); 2340b57cec5SDimitry Andric uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset; 2350b57cec5SDimitry Andric createStubFunction(JTEntryAddr); 2360b57cec5SDimitry Andric RelocationEntry RE(JTSectionID, JTEntryOffset + 1, 2370b57cec5SDimitry Andric MachO::GENERIC_RELOC_VANILLA, 0, true, 2); 2380b57cec5SDimitry Andric addRelocationForSymbol(RE, *IndirectSymbolName); 2390b57cec5SDimitry Andric JTEntryOffset += JTEntrySize; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric return Error::success(); 2430b57cec5SDimitry Andric } 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric }; 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric #undef DEBUG_TYPE 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric #endif 251