| //===-- 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<unsigned>(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 |