| //===-- 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" | |
| 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) { | |
| // 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. | |
| Functions[Name] = sys::MemoryBlock(Mem, Size); | |
| // Default the assigned address for this symbol to wherever this | |
| // allocated it. | |
| SymbolTable[Name] = Mem; | |
| 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 symbols in our symbol table and assign their | |
| // addresses. | |
| StringMap<uint8_t*>::iterator i = SymbolTable.begin(); | |
| StringMap<uint8_t*>::iterator e = SymbolTable.end(); | |
| for (;i != e; ++i) | |
| reassignSymbolAddress(i->getKey(), i->getValue()); | |
| } | |
| //===----------------------------------------------------------------------===// | |
| // RuntimeDyld class implementation | |
| RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) { | |
| Dyld = 0; | |
| MM = mm; | |
| } | |
| RuntimeDyld::~RuntimeDyld() { | |
| delete Dyld; | |
| } | |
| bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) { | |
| if (!Dyld) { | |
| if (RuntimeDyldMachO::isKnownFormat(InputBuffer)) | |
| Dyld = new RuntimeDyldMachO(MM); | |
| else | |
| report_fatal_error("Unknown 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::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { | |
| Dyld->reassignSymbolAddress(Name, Addr); | |
| } | |
| StringRef RuntimeDyld::getErrorString() { | |
| return Dyld->getErrorString(); | |
| } | |
| } // end namespace llvm |