RuntimeDyldMachO.cpp revision 288943
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 29288943Sdimclass LoadedMachOObjectInfo 30288943Sdim : public RuntimeDyld::LoadedObjectInfoHelper<LoadedMachOObjectInfo> { 31280031Sdimpublic: 32280031Sdim LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, 33280031Sdim unsigned EndIdx) 34288943Sdim : LoadedObjectInfoHelper(RTDyld, BeginIdx, EndIdx) {} 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; 48280031Sdim uint8_t *Src = Sections[RE.SectionID].Address + RE.Offset; 49280031Sdim 50280031Sdim return static_cast<int64_t>(readBytesUnaligned(Src, NumBytes)); 51276479Sdim} 52276479Sdim 53276479SdimRelocationValueRef RuntimeDyldMachO::getRelocationValueRef( 54280031Sdim const ObjectFile &BaseTObj, const relocation_iterator &RI, 55280031Sdim const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { 56276479Sdim 57276479Sdim const MachOObjectFile &Obj = 58280031Sdim static_cast<const MachOObjectFile &>(BaseTObj); 59276479Sdim MachO::any_relocation_info RelInfo = 60276479Sdim Obj.getRelocation(RI->getRawDataRefImpl()); 61276479Sdim RelocationValueRef Value; 62276479Sdim 63276479Sdim bool IsExternal = Obj.getPlainRelocationExternal(RelInfo); 64276479Sdim if (IsExternal) { 65276479Sdim symbol_iterator Symbol = RI->getSymbol(); 66288943Sdim ErrorOr<StringRef> TargetNameOrErr = Symbol->getName(); 67288943Sdim if (std::error_code EC = TargetNameOrErr.getError()) 68288943Sdim report_fatal_error(EC.message()); 69288943Sdim StringRef TargetName = *TargetNameOrErr; 70288943Sdim RTDyldSymbolTable::const_iterator SI = 71280031Sdim GlobalSymbolTable.find(TargetName.data()); 72280031Sdim if (SI != GlobalSymbolTable.end()) { 73288943Sdim const auto &SymInfo = SI->second; 74288943Sdim Value.SectionID = SymInfo.getSectionID(); 75288943Sdim Value.Offset = SymInfo.getOffset() + RE.Addend; 76276479Sdim } else { 77280031Sdim Value.SymbolName = TargetName.data(); 78280031Sdim Value.Offset = RE.Addend; 79276479Sdim } 80276479Sdim } else { 81288943Sdim SectionRef Sec = Obj.getAnyRelocationSection(RelInfo); 82280031Sdim bool IsCode = Sec.isText(); 83280031Sdim Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); 84280031Sdim uint64_t Addr = Sec.getAddress(); 85280031Sdim Value.Offset = RE.Addend - Addr; 86276479Sdim } 87276479Sdim 88276479Sdim return Value; 89276479Sdim} 90276479Sdim 91276479Sdimvoid RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, 92280031Sdim const relocation_iterator &RI, 93280031Sdim unsigned OffsetToNextPC) { 94288943Sdim auto &O = *cast<MachOObjectFile>(RI->getObject()); 95288943Sdim section_iterator SecI = O.getRelocationRelocatedSection(RI); 96288943Sdim Value.Offset += RI->getOffset() + OffsetToNextPC + SecI->getAddress(); 97276479Sdim} 98276479Sdim 99276479Sdimvoid RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE, 100276479Sdim uint64_t Value) const { 101276479Sdim const SectionEntry &Section = Sections[RE.SectionID]; 102276479Sdim uint8_t *LocalAddress = Section.Address + RE.Offset; 103276479Sdim uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 104276479Sdim 105276479Sdim dbgs() << "resolveRelocation Section: " << RE.SectionID 106276479Sdim << " LocalAddress: " << format("%p", LocalAddress) 107280031Sdim << " FinalAddress: " << format("0x%016" PRIx64, FinalAddress) 108280031Sdim << " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend 109276479Sdim << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType 110276479Sdim << " Size: " << (1 << RE.Size) << "\n"; 111276479Sdim} 112276479Sdim 113280031Sdimsection_iterator 114280031SdimRuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, 115280031Sdim uint64_t Addr) { 116280031Sdim section_iterator SI = Obj.section_begin(); 117280031Sdim section_iterator SE = Obj.section_end(); 118280031Sdim 119280031Sdim for (; SI != SE; ++SI) { 120280031Sdim uint64_t SAddr = SI->getAddress(); 121280031Sdim uint64_t SSize = SI->getSize(); 122280031Sdim if ((Addr >= SAddr) && (Addr < SAddr + SSize)) 123280031Sdim return SI; 124276479Sdim } 125276479Sdim 126280031Sdim return SE; 127276479Sdim} 128276479Sdim 129280031Sdim 130280031Sdim// Populate __pointers section. 131280031Sdimvoid RuntimeDyldMachO::populateIndirectSymbolPointersSection( 132280031Sdim const MachOObjectFile &Obj, 133280031Sdim const SectionRef &PTSection, 134280031Sdim unsigned PTSectionID) { 135280031Sdim assert(!Obj.is64Bit() && 136280031Sdim "Pointer table section not supported in 64-bit MachO."); 137280031Sdim 138280031Sdim MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 139280031Sdim MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); 140280031Sdim uint32_t PTSectionSize = Sec32.size; 141280031Sdim unsigned FirstIndirectSymbol = Sec32.reserved1; 142280031Sdim const unsigned PTEntrySize = 4; 143280031Sdim unsigned NumPTEntries = PTSectionSize / PTEntrySize; 144280031Sdim unsigned PTEntryOffset = 0; 145280031Sdim 146280031Sdim assert((PTSectionSize % PTEntrySize) == 0 && 147280031Sdim "Pointers section does not contain a whole number of stubs?"); 148280031Sdim 149280031Sdim DEBUG(dbgs() << "Populating pointer table section " 150280031Sdim << Sections[PTSectionID].Name 151280031Sdim << ", Section ID " << PTSectionID << ", " 152280031Sdim << NumPTEntries << " entries, " << PTEntrySize 153280031Sdim << " bytes each:\n"); 154280031Sdim 155280031Sdim for (unsigned i = 0; i < NumPTEntries; ++i) { 156280031Sdim unsigned SymbolIndex = 157280031Sdim Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 158280031Sdim symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 159288943Sdim ErrorOr<StringRef> IndirectSymbolNameOrErr = SI->getName(); 160288943Sdim if (std::error_code EC = IndirectSymbolNameOrErr.getError()) 161288943Sdim report_fatal_error(EC.message()); 162288943Sdim StringRef IndirectSymbolName = *IndirectSymbolNameOrErr; 163280031Sdim DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex 164280031Sdim << ", PT offset: " << PTEntryOffset << "\n"); 165280031Sdim RelocationEntry RE(PTSectionID, PTEntryOffset, 166280031Sdim MachO::GENERIC_RELOC_VANILLA, 0, false, 2); 167280031Sdim addRelocationForSymbol(RE, IndirectSymbolName); 168280031Sdim PTEntryOffset += PTEntrySize; 169280031Sdim } 170276479Sdim} 171276479Sdim 172280031Sdimbool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { 173280031Sdim return Obj.isMachO(); 174276479Sdim} 175276479Sdim 176280031Sdimtemplate <typename Impl> 177283526Sdimvoid RuntimeDyldMachOCRTPBase<Impl>::finalizeLoad(const ObjectFile &Obj, 178280031Sdim ObjSectionToIDMap &SectionMap) { 179280031Sdim unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; 180280031Sdim unsigned TextSID = RTDYLD_INVALID_SECTION_ID; 181280031Sdim unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; 182280031Sdim 183283526Sdim for (const auto &Section : Obj.sections()) { 184280031Sdim StringRef Name; 185280031Sdim Section.getName(Name); 186283526Sdim 187283526Sdim // Force emission of the __text, __eh_frame, and __gcc_except_tab sections 188283526Sdim // if they're present. Otherwise call down to the impl to handle other 189283526Sdim // sections that have already been emitted. 190283526Sdim if (Name == "__text") 191283526Sdim TextSID = findOrEmitSection(Obj, Section, true, SectionMap); 192283526Sdim else if (Name == "__eh_frame") 193283526Sdim EHFrameSID = findOrEmitSection(Obj, Section, false, SectionMap); 194280031Sdim else if (Name == "__gcc_except_tab") 195283526Sdim ExceptTabSID = findOrEmitSection(Obj, Section, true, SectionMap); 196283526Sdim else { 197283526Sdim auto I = SectionMap.find(Section); 198283526Sdim if (I != SectionMap.end()) 199283526Sdim impl().finalizeSection(Obj, I->second, Section); 200283526Sdim } 201280031Sdim } 202280031Sdim UnregisteredEHFrameSections.push_back( 203280031Sdim EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); 204280031Sdim} 205280031Sdim 206280031Sdimtemplate <typename Impl> 207280031Sdimunsigned char *RuntimeDyldMachOCRTPBase<Impl>::processFDE(unsigned char *P, 208280031Sdim int64_t DeltaForText, 209280031Sdim int64_t DeltaForEH) { 210280031Sdim typedef typename Impl::TargetPtrT TargetPtrT; 211280031Sdim 212276479Sdim DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText 213276479Sdim << ", Delta for EH: " << DeltaForEH << "\n"); 214280031Sdim uint32_t Length = readBytesUnaligned(P, 4); 215251662Sdim P += 4; 216251662Sdim unsigned char *Ret = P + Length; 217280031Sdim uint32_t Offset = readBytesUnaligned(P, 4); 218251662Sdim if (Offset == 0) // is a CIE 219251662Sdim return Ret; 220251662Sdim 221251662Sdim P += 4; 222280031Sdim TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT)); 223280031Sdim TargetPtrT NewLocation = FDELocation - DeltaForText; 224280031Sdim writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT)); 225251662Sdim 226280031Sdim P += sizeof(TargetPtrT); 227280031Sdim 228251662Sdim // Skip the FDE address range 229280031Sdim P += sizeof(TargetPtrT); 230251662Sdim 231251662Sdim uint8_t Augmentationsize = *P; 232251662Sdim P += 1; 233251662Sdim if (Augmentationsize != 0) { 234280031Sdim TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT)); 235280031Sdim TargetPtrT NewLSDA = LSDA - DeltaForEH; 236280031Sdim writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT)); 237251662Sdim } 238251662Sdim 239251662Sdim return Ret; 240251662Sdim} 241251662Sdim 242280031Sdimstatic int64_t computeDelta(SectionEntry *A, SectionEntry *B) { 243283526Sdim int64_t ObjDistance = 244283526Sdim static_cast<int64_t>(A->ObjAddress) - static_cast<int64_t>(B->ObjAddress); 245280031Sdim int64_t MemDistance = A->LoadAddress - B->LoadAddress; 246251662Sdim return ObjDistance - MemDistance; 247251662Sdim} 248251662Sdim 249280031Sdimtemplate <typename Impl> 250280031Sdimvoid RuntimeDyldMachOCRTPBase<Impl>::registerEHFrames() { 251251662Sdim 252261991Sdim for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { 253261991Sdim EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; 254261991Sdim if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || 255261991Sdim SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) 256261991Sdim continue; 257261991Sdim SectionEntry *Text = &Sections[SectionInfo.TextSID]; 258261991Sdim SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; 259276479Sdim SectionEntry *ExceptTab = nullptr; 260261991Sdim if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) 261261991Sdim ExceptTab = &Sections[SectionInfo.ExceptTabSID]; 262251662Sdim 263280031Sdim int64_t DeltaForText = computeDelta(Text, EHFrame); 264280031Sdim int64_t DeltaForEH = 0; 265261991Sdim if (ExceptTab) 266261991Sdim DeltaForEH = computeDelta(ExceptTab, EHFrame); 267251662Sdim 268261991Sdim unsigned char *P = EHFrame->Address; 269261991Sdim unsigned char *End = P + EHFrame->Size; 270276479Sdim do { 271261991Sdim P = processFDE(P, DeltaForText, DeltaForEH); 272276479Sdim } while (P != End); 273261991Sdim 274288943Sdim MemMgr.registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, 275288943Sdim EHFrame->Size); 276261991Sdim } 277261991Sdim UnregisteredEHFrameSections.clear(); 278251662Sdim} 279251662Sdim 280276479Sdimstd::unique_ptr<RuntimeDyldMachO> 281288943SdimRuntimeDyldMachO::create(Triple::ArchType Arch, 282288943Sdim RuntimeDyld::MemoryManager &MemMgr, 283288943Sdim RuntimeDyld::SymbolResolver &Resolver) { 284234353Sdim switch (Arch) { 285234353Sdim default: 286276479Sdim llvm_unreachable("Unsupported target for RuntimeDyldMachO."); 287224133Sdim break; 288288943Sdim case Triple::arm: 289288943Sdim return make_unique<RuntimeDyldMachOARM>(MemMgr, Resolver); 290288943Sdim case Triple::aarch64: 291288943Sdim return make_unique<RuntimeDyldMachOAArch64>(MemMgr, Resolver); 292288943Sdim case Triple::x86: 293288943Sdim return make_unique<RuntimeDyldMachOI386>(MemMgr, Resolver); 294288943Sdim case Triple::x86_64: 295288943Sdim return make_unique<RuntimeDyldMachOX86_64>(MemMgr, Resolver); 296224133Sdim } 297224133Sdim} 298224133Sdim 299280031Sdimstd::unique_ptr<RuntimeDyld::LoadedObjectInfo> 300280031SdimRuntimeDyldMachO::loadObject(const object::ObjectFile &O) { 301280031Sdim unsigned SectionStartIdx, SectionEndIdx; 302280031Sdim std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); 303280031Sdim return llvm::make_unique<LoadedMachOObjectInfo>(*this, SectionStartIdx, 304280031Sdim SectionEndIdx); 305280031Sdim} 306280031Sdim 307224133Sdim} // end namespace llvm 308