1234353Sdim//===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=// 2224133Sdim// 3224133Sdim// The LLVM Compiler Infrastructure 4224133Sdim// 5224133Sdim// This file is distributed under the University of Illinois Open Source 6224133Sdim// License. See LICENSE.TXT for details. 7224133Sdim// 8224133Sdim//===----------------------------------------------------------------------===// 9224133Sdim// 10224133Sdim// Implementation of the MC-JIT runtime dynamic linker. 11224133Sdim// 12224133Sdim//===----------------------------------------------------------------------===// 13224133Sdim 14249423Sdim#include "RuntimeDyldMachO.h" 15280031Sdim#include "Targets/RuntimeDyldMachOAArch64.h" 16276479Sdim#include "Targets/RuntimeDyldMachOARM.h" 17276479Sdim#include "Targets/RuntimeDyldMachOI386.h" 18276479Sdim#include "Targets/RuntimeDyldMachOX86_64.h" 19280031Sdim#include "llvm/ADT/STLExtras.h" 20280031Sdim#include "llvm/ADT/StringRef.h" 21276479Sdim 22224133Sdimusing namespace llvm; 23224133Sdimusing namespace llvm::object; 24224133Sdim 25276479Sdim#define DEBUG_TYPE "dyld" 26276479Sdim 27280031Sdimnamespace { 28280031Sdim 29296417Sdimclass LoadedMachOObjectInfo final 30288943Sdim : public RuntimeDyld::LoadedObjectInfoHelper<LoadedMachOObjectInfo> { 31280031Sdimpublic: 32296417Sdim LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, 33296417Sdim ObjSectionToIDMap ObjSecToIDMap) 34296417Sdim : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {} 35280031Sdim 36280031Sdim OwningBinary<ObjectFile> 37280031Sdim getObjectForDebug(const ObjectFile &Obj) const override { 38280031Sdim return OwningBinary<ObjectFile>(); 39280031Sdim } 40280031Sdim}; 41280031Sdim 42280031Sdim} 43280031Sdim 44224133Sdimnamespace llvm { 45224133Sdim 46280031Sdimint64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { 47280031Sdim unsigned NumBytes = 1 << RE.Size; 48296417Sdim uint8_t *Src = Sections[RE.SectionID].getAddress() + RE.Offset; 49280031Sdim 50280031Sdim return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes)); 51276479Sdim} 52276479Sdim 53296417Sdimrelocation_iterator RuntimeDyldMachO::processScatteredVANILLA( 54296417Sdim unsigned SectionID, relocation_iterator RelI, 55296417Sdim const ObjectFile &BaseObjT, 56296417Sdim RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { 57296417Sdim const MachOObjectFile &Obj = 58296417Sdim static_cast<const MachOObjectFile&>(BaseObjT); 59296417Sdim MachO::any_relocation_info RE = 60296417Sdim Obj.getRelocation(RelI->getRawDataRefImpl()); 61296417Sdim 62296417Sdim SectionEntry &Section = Sections[SectionID]; 63296417Sdim uint32_t RelocType = Obj.getAnyRelocationType(RE); 64296417Sdim bool IsPCRel = Obj.getAnyRelocationPCRel(RE); 65296417Sdim unsigned Size = Obj.getAnyRelocationLength(RE); 66296417Sdim uint64_t Offset = RelI->getOffset(); 67296417Sdim uint8_t *LocalAddress = Section.getAddressWithOffset(Offset); 68296417Sdim unsigned NumBytes = 1 << Size; 69296417Sdim int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); 70296417Sdim 71296417Sdim unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE); 72296417Sdim section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr); 73296417Sdim assert(TargetSI != Obj.section_end() && "Can't find section for symbol"); 74296417Sdim uint64_t SectionBaseAddr = TargetSI->getAddress(); 75296417Sdim SectionRef TargetSection = *TargetSI; 76296417Sdim bool IsCode = TargetSection.isText(); 77296417Sdim uint32_t TargetSectionID = 78296417Sdim findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID); 79296417Sdim 80296417Sdim Addend -= SectionBaseAddr; 81296417Sdim RelocationEntry R(SectionID, Offset, RelocType, Addend, IsPCRel, Size); 82296417Sdim 83296417Sdim addRelocationForSection(R, TargetSectionID); 84296417Sdim 85296417Sdim return ++RelI; 86296417Sdim} 87296417Sdim 88296417Sdim 89276479SdimRelocationValueRef RuntimeDyldMachO::getRelocationValueRef( 90280031Sdim const ObjectFile &BaseTObj, const relocation_iterator &RI, 91280031Sdim const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { 92276479Sdim 93276479Sdim const MachOObjectFile &Obj = 94280031Sdim static_cast<const MachOObjectFile &>(BaseTObj); 95276479Sdim MachO::any_relocation_info RelInfo = 96276479Sdim Obj.getRelocation(RI->getRawDataRefImpl()); 97276479Sdim RelocationValueRef Value; 98276479Sdim 99276479Sdim bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); 100276479Sdim if (IsExternal) { 101276479Sdim symbol_iterator Symbol = RI->getSymbol(); 102288943Sdim ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); 103288943Sdim if (std::error_code EC = TargetNameOrErr.getError()) 104288943Sdim report_fatal_error(EC.message()); 105288943Sdim StringRef TargetName = *TargetNameOrErr; 106288943Sdim RTDyldSymbolTable::const_iterator SI = 107280031Sdim GlobalSymbolTable.find(TargetName.data()); 108280031Sdim if (SI != GlobalSymbolTable.end()) { 109288943Sdim const auto &SymInfo = SI->second; 110288943Sdim Value.SectionID = SymInfo.getSectionID(); 111288943Sdim Value.Offset = SymInfo.getOffset() + RE.Addend; 112276479Sdim } else { 113280031Sdim Value.SymbolName = TargetName.data(); 114280031Sdim Value.Offset = RE.Addend; 115276479Sdim } 116276479Sdim } else { 117288943Sdim SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); 118280031Sdim bool IsCode = Sec.isText(); 119280031Sdim Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); 120280031Sdim uint64_t Addr = Sec.getAddress(); 121280031Sdim Value.Offset = RE.Addend - Addr; 122276479Sdim } 123276479Sdim 124276479Sdim return Value; 125276479Sdim} 126276479Sdim 127276479Sdimvoid RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, 128280031Sdim const relocation_iterator &RI, 129280031Sdim unsigned OffsetToNextPC) { 130288943Sdim auto &O = *cast<MachOObjectFile>(RI->getObject()); 131288943Sdim section_iterator SecI = O.getRelocationRelocatedSection(RI); 132288943Sdim Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress(); 133276479Sdim} 134276479Sdim 135276479Sdimvoid RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE, 136276479Sdim uint64_t Value) const { 137276479Sdim const SectionEntry &Section = Sections[RE.SectionID]; 138296417Sdim uint8_t *LocalAddress = Section.getAddress() + RE.Offset; 139296417Sdim uint64_t FinalAddress = Section.getLoadAddress() + RE.Offset; 140276479Sdim 141276479Sdim dbgs() << "resolveRelocation Section: " << RE.SectionID 142276479Sdim << " LocalAddress: " << format("%p", LocalAddress) 143280031Sdim << " FinalAddress: " << format("0x%016" PRIx64, FinalAddress) 144280031Sdim << " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend 145276479Sdim << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType 146276479Sdim << " Size: " << (1 << RE.Size) << "\n"; 147276479Sdim} 148276479Sdim 149280031Sdimsection_iterator 150280031SdimRuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, 151280031Sdim uint64_t Addr) { 152280031Sdim section_iterator SI = Obj.section_begin(); 153280031Sdim section_iterator SE = Obj.section_end(); 154280031Sdim 155280031Sdim for (; SI != SE; ++SI) { 156280031Sdim uint64_t SAddr = SI->getAddress(); 157280031Sdim uint64_t SSize = SI->getSize(); 158280031Sdim if ((Addr >= SAddr) && (Addr < SAddr + SSize)) 159280031Sdim return SI; 160276479Sdim } 161276479Sdim 162280031Sdim return SE; 163276479Sdim} 164276479Sdim 165280031Sdim 166280031Sdim// Populate __pointers section. 167280031Sdimvoid RuntimeDyldMachO::populateIndirectSymbolPointersSection( 168280031Sdim const MachOObjectFile &Obj, 169280031Sdim const SectionRef &PTSection, 170280031Sdim unsigned PTSectionID) { 171280031Sdim assert(!Obj.is64Bit() && 172280031Sdim "Pointer table section not supported in 64-bit MachO."); 173280031Sdim 174280031Sdim MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 175280031Sdim MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); 176280031Sdim uint32_t PTSectionSize = Sec32.size; 177280031Sdim unsigned FirstIndirectSymbol = Sec32.reserved1; 178280031Sdim const unsigned PTEntrySize = 4; 179280031Sdim unsigned NumPTEntries = PTSectionSize / PTEntrySize; 180280031Sdim unsigned PTEntryOffset = 0; 181280031Sdim 182280031Sdim assert((PTSectionSize % PTEntrySize) == 0 && 183280031Sdim "Pointers section does not contain a whole number of stubs?"); 184280031Sdim 185280031Sdim DEBUG(dbgs() << "Populating pointer table section " 186296417Sdim << Sections[PTSectionID].getName() << ", Section ID " 187296417Sdim << PTSectionID << ", " << NumPTEntries << " entries, " 188296417Sdim << PTEntrySize << " bytes each:\n"); 189280031Sdim 190280031Sdim for (unsigned i = 0; i < NumPTEntries; ++i) { 191280031Sdim unsigned SymbolIndex = 192280031Sdim Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 193280031Sdim symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 194288943Sdim ErrorOr<StringRef> IndirectSymbolNameOrErr = SI->getName(); 195288943Sdim if (std::error_code EC = IndirectSymbolNameOrErr.getError()) 196288943Sdim report_fatal_error(EC.message()); 197288943Sdim StringRef IndirectSymbolName = *IndirectSymbolNameOrErr; 198280031Sdim DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex 199280031Sdim << ", PT offset: " << PTEntryOffset << "\n"); 200280031Sdim RelocationEntry RE(PTSectionID, PTEntryOffset, 201280031Sdim MachO::GENERIC_RELOC_VANILLA, 0, false, 2); 202280031Sdim addRelocationForSymbol(RE, IndirectSymbolName); 203280031Sdim PTEntryOffset += PTEntrySize; 204280031Sdim } 205276479Sdim} 206276479Sdim 207280031Sdimbool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { 208280031Sdim return Obj.isMachO(); 209276479Sdim} 210276479Sdim 211280031Sdimtemplate <typename Impl> 212283526Sdimvoid RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj, 213280031Sdim ObjSectionToIDMap &SectionMap) { 214280031Sdim unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; 215280031Sdim unsigned TextSID = RTDYLD_INVALID_SECTION_ID; 216280031Sdim unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; 217280031Sdim 218283526Sdim for (const auto &Section : Obj.sections()) { 219280031Sdim StringRef Name; 220280031Sdim Section.getName(Name); 221283526Sdim 222283526Sdim // Force emission of the __text, __eh_frame, and __gcc_except_tab sections 223283526Sdim // if they're present. Otherwise call down to the impl to handle other 224283526Sdim // sections that have already been emitted. 225283526Sdim if (Name == "__text") 226283526Sdim TextSID = findOrEmitSection(Obj, Section, true, SectionMap); 227283526Sdim else if (Name == "__eh_frame") 228283526Sdim EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap); 229280031Sdim else if (Name == "__gcc_except_tab") 230283526Sdim ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap); 231283526Sdim else { 232283526Sdim auto I = SectionMap.find(Section); 233283526Sdim if (I != SectionMap.end()) 234283526Sdim impl().finalizeSection(Obj, I->second, Section); 235283526Sdim } 236280031Sdim } 237280031Sdim UnregisteredEHFrameSections.push_back( 238280031Sdim EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); 239280031Sdim} 240280031Sdim 241280031Sdimtemplate <typename Impl> 242296417Sdimunsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(uint8_t *P, 243280031Sdim int64_t DeltaForText, 244280031Sdim int64_t DeltaForEH) { 245280031Sdim typedef typename Impl::TargetPtrT TargetPtrT; 246280031Sdim 247276479Sdim DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText 248276479Sdim << ", Delta for EH: " << DeltaForEH << "\n"); 249280031Sdim uint32_t Length = readBytesUnaligned(P, 4); 250251662Sdim P += 4; 251296417Sdim uint8_t *Ret = P + Length; 252280031Sdim uint32_t Offset = readBytesUnaligned(P, 4); 253251662Sdim if (Offset == 0) // is a CIE 254251662Sdim return Ret; 255251662Sdim 256251662Sdim P += 4; 257280031Sdim TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT)); 258280031Sdim TargetPtrT NewLocation = FDELocation - DeltaForText; 259280031Sdim writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT)); 260251662Sdim 261280031Sdim P += sizeof(TargetPtrT); 262280031Sdim 263251662Sdim // Skip the FDE address range 264280031Sdim P += sizeof(TargetPtrT); 265251662Sdim 266251662Sdim uint8_t Augmentationsize = *P; 267251662Sdim P += 1; 268251662Sdim if (Augmentationsize != 0) { 269280031Sdim TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT)); 270280031Sdim TargetPtrT NewLSDA = LSDA - DeltaForEH; 271280031Sdim writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT)); 272251662Sdim } 273251662Sdim 274251662Sdim return Ret; 275251662Sdim} 276251662Sdim 277280031Sdimstatic int64_t computeDelta(SectionEntry *A, SectionEntry *B) { 278296417Sdim int64_t ObjDistance = static_cast<int64_t>(A->getObjAddress()) - 279296417Sdim static_cast<int64_t>(B->getObjAddress()); 280296417Sdim int64_t MemDistance = A->getLoadAddress() - B->getLoadAddress(); 281251662Sdim return ObjDistance - MemDistance; 282251662Sdim} 283251662Sdim 284280031Sdimtemplate <typename Impl> 285280031Sdimvoid RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { 286251662Sdim 287261991Sdim for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { 288261991Sdim EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; 289261991Sdim if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || 290261991Sdim SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) 291261991Sdim continue; 292261991Sdim SectionEntry *Text = &Sections[SectionInfo.TextSID]; 293261991Sdim SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; 294276479Sdim SectionEntry *ExceptTab = nullptr; 295261991Sdim if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) 296261991Sdim ExceptTab = &Sections[SectionInfo.ExceptTabSID]; 297251662Sdim 298280031Sdim int64_t DeltaForText = computeDelta(Text, EHFrame); 299280031Sdim int64_t DeltaForEH = 0; 300261991Sdim if (ExceptTab) 301261991Sdim DeltaForEH = computeDelta(ExceptTab, EHFrame); 302251662Sdim 303296417Sdim uint8_t *P = EHFrame->getAddress(); 304296417Sdim uint8_t *End = P + EHFrame->getSize(); 305276479Sdim do { 306261991Sdim P = processFDE(P, DeltaForText, DeltaForEH); 307276479Sdim } while (P != End); 308261991Sdim 309296417Sdim MemMgr.registerEHFrames(EHFrame->getAddress(), EHFrame->getLoadAddress(), 310296417Sdim EHFrame->getSize()); 311261991Sdim } 312261991Sdim UnregisteredEHFrameSections.clear(); 313251662Sdim} 314251662Sdim 315276479Sdimstd::unique_ptr<RuntimeDyldMachO> 316288943SdimRuntimeDyldMachO::create(Triple::ArchType Arch, 317288943Sdim RuntimeDyld::MemoryManager &MemMgr, 318288943Sdim RuntimeDyld::SymbolResolver &Resolver) { 319234353Sdim switch (Arch) { 320234353Sdim default: 321276479Sdim llvm_unreachable("Unsupported target for RuntimeDyldMachO."); 322224133Sdim break; 323288943Sdim case Triple::arm: 324288943Sdim return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver); 325288943Sdim case Triple::aarch64: 326288943Sdim return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver); 327288943Sdim case Triple::x86: 328288943Sdim return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver); 329288943Sdim case Triple::x86_64: 330288943Sdim return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver); 331224133Sdim } 332224133Sdim} 333224133Sdim 334280031Sdimstd::unique_ptr<RuntimeDyld::LoadedObjectInfo> 335280031SdimRuntimeDyldMachO::loadObject(const object::ObjectFile &O) { 336296417Sdim return llvm::make_unique<LoadedMachOObjectInfo>(*this, loadObjectImpl(O)); 337280031Sdim} 338280031Sdim 339224133Sdim} // end namespace llvm 340