//===-- RuntimeDyld.cpp - Run-time dynamic linker for MC-JIT ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Implementation of the MC-JIT runtime dynamic linker. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dyld" #include "RuntimeDyldImpl.h" #include "RuntimeDyldELF.h" #include "RuntimeDyldMachO.h" #include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::object; // Empty out-of-line virtual destructor as the key function. RTDyldMemoryManager::~RTDyldMemoryManager() {} RuntimeDyldImpl::~RuntimeDyldImpl() {} namespace llvm { void RuntimeDyldImpl::extractFunction(StringRef Name, uint8_t *StartAddress, uint8_t *EndAddress) { // FIXME: DEPRECATED in favor of by-section allocation. // Allocate memory for the function via the memory manager. uintptr_t Size = EndAddress - StartAddress + 1; uintptr_t AllocSize = Size; uint8_t *Mem = MemMgr->startFunctionBody(Name.data(), AllocSize); assert(Size >= (uint64_t)(EndAddress - StartAddress + 1) && "Memory manager failed to allocate enough memory!"); // Copy the function payload into the memory block. memcpy(Mem, StartAddress, Size); MemMgr->endFunctionBody(Name.data(), Mem, Mem + Size); // Remember where we put it. unsigned SectionID = Sections.size(); Sections.push_back(sys::MemoryBlock(Mem, Size)); // Default the assigned address for this symbol to wherever this // allocated it. SymbolTable[Name] = SymbolLoc(SectionID, 0); DEBUG(dbgs() << " allocated to [" << Mem << ", " << Mem + Size << "]\n"); } // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { // Just iterate over the sections we have and resolve all the relocations // in them. Gross overkill, but it gets the job done. for (int i = 0, e = Sections.size(); i != e; ++i) { reassignSectionAddress(i, SectionLoadAddress[i]); } } void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress, uint64_t TargetAddress) { assert(SectionLocalMemToID.count(LocalAddress) && "Attempting to remap address of unknown section!"); unsigned SectionID = SectionLocalMemToID[LocalAddress]; reassignSectionAddress(SectionID, TargetAddress); } //===----------------------------------------------------------------------===// // RuntimeDyld class implementation RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { Dyld = 0; MM = mm; } RuntimeDyld::~RuntimeDyld() { delete Dyld; } bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) { if (!Dyld) { sys::LLVMFileType type = sys::IdentifyFileType( InputBuffer->getBufferStart(), static_cast(InputBuffer->getBufferSize())); switch (type) { case sys::ELF_Relocatable_FileType: case sys::ELF_Executable_FileType: case sys::ELF_SharedObject_FileType: case sys::ELF_Core_FileType: Dyld = new RuntimeDyldELF(MM); break; case sys::Mach_O_Object_FileType: case sys::Mach_O_Executable_FileType: case sys::Mach_O_FixedVirtualMemorySharedLib_FileType: case sys::Mach_O_Core_FileType: case sys::Mach_O_PreloadExecutable_FileType: case sys::Mach_O_DynamicallyLinkedSharedLib_FileType: case sys::Mach_O_DynamicLinker_FileType: case sys::Mach_O_Bundle_FileType: case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType: case sys::Mach_O_DSYMCompanion_FileType: Dyld = new RuntimeDyldMachO(MM); break; case sys::Unknown_FileType: case sys::Bitcode_FileType: case sys::Archive_FileType: case sys::COFF_FileType: report_fatal_error("Incompatible object format!"); } } else { if (!Dyld->isCompatibleFormat(InputBuffer)) report_fatal_error("Incompatible object format!"); } return Dyld->loadObject(InputBuffer); } void *RuntimeDyld::getSymbolAddress(StringRef Name) { return Dyld->getSymbolAddress(Name); } void RuntimeDyld::resolveRelocations() { Dyld->resolveRelocations(); } void RuntimeDyld::reassignSectionAddress(unsigned SectionID, uint64_t Addr) { Dyld->reassignSectionAddress(SectionID, Addr); } void RuntimeDyld::mapSectionAddress(void *LocalAddress, uint64_t TargetAddress) { Dyld->mapSectionAddress(LocalAddress, TargetAddress); } StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); } } // end namespace llvm