1//===-- RuntimeDyld.cpp - Run-time dynamic linker for MC-JIT ------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Implementation of the MC-JIT runtime dynamic linker.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "dyld"
15#include "RuntimeDyldImpl.h"
16using namespace llvm;
17using namespace llvm::object;
18
19// Empty out-of-line virtual destructor as the key function.
20RTDyldMemoryManager::~RTDyldMemoryManager() {}
21RuntimeDyldImpl::~RuntimeDyldImpl() {}
22
23namespace llvm {
24
25void RuntimeDyldImpl::extractFunction(StringRef Name, uint8_t *StartAddress,
26                                      uint8_t *EndAddress) {
27  // Allocate memory for the function via the memory manager.
28  uintptr_t Size = EndAddress - StartAddress + 1;
29  uintptr_t AllocSize = Size;
30  uint8_t *Mem = MemMgr->startFunctionBody(Name.data(), AllocSize);
31  assert(Size >= (uint64_t)(EndAddress - StartAddress + 1) &&
32         "Memory manager failed to allocate enough memory!");
33  // Copy the function payload into the memory block.
34  memcpy(Mem, StartAddress, Size);
35  MemMgr->endFunctionBody(Name.data(), Mem, Mem + Size);
36  // Remember where we put it.
37  Functions[Name] = sys::MemoryBlock(Mem, Size);
38  // Default the assigned address for this symbol to wherever this
39  // allocated it.
40  SymbolTable[Name] = Mem;
41  DEBUG(dbgs() << "    allocated to [" << Mem << ", " << Mem + Size << "]\n");
42}
43
44// Resolve the relocations for all symbols we currently know about.
45void RuntimeDyldImpl::resolveRelocations() {
46  // Just iterate over the symbols in our symbol table and assign their
47  // addresses.
48  StringMap<uint8_t*>::iterator i = SymbolTable.begin();
49  StringMap<uint8_t*>::iterator e = SymbolTable.end();
50  for (;i != e; ++i)
51    reassignSymbolAddress(i->getKey(), i->getValue());
52}
53
54//===----------------------------------------------------------------------===//
55// RuntimeDyld class implementation
56RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
57  Dyld = 0;
58  MM = mm;
59}
60
61RuntimeDyld::~RuntimeDyld() {
62  delete Dyld;
63}
64
65bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) {
66  if (!Dyld) {
67    if (RuntimeDyldMachO::isKnownFormat(InputBuffer))
68      Dyld = new RuntimeDyldMachO(MM);
69    else
70      report_fatal_error("Unknown object format!");
71  } else {
72    if(!Dyld->isCompatibleFormat(InputBuffer))
73      report_fatal_error("Incompatible object format!");
74  }
75
76  return Dyld->loadObject(InputBuffer);
77}
78
79void *RuntimeDyld::getSymbolAddress(StringRef Name) {
80  return Dyld->getSymbolAddress(Name);
81}
82
83void RuntimeDyld::resolveRelocations() {
84  Dyld->resolveRelocations();
85}
86
87void RuntimeDyld::reassignSymbolAddress(StringRef Name, uint8_t *Addr) {
88  Dyld->reassignSymbolAddress(Name, Addr);
89}
90
91StringRef RuntimeDyld::getErrorString() {
92  return Dyld->getErrorString();
93}
94
95} // end namespace llvm
96