Adding a basic ELF dynamic loader and MC-JIT for ELF. Functionality is currently...
[oota-llvm.git] / lib / ExecutionEngine / RuntimeDyld / RuntimeDyld.cpp
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"
16 #include "llvm/Support/Path.h"
17 using namespace llvm;
18 using namespace llvm::object;
19
20 // Empty out-of-line virtual destructor as the key function.
21 RTDyldMemoryManager::~RTDyldMemoryManager() {}
22 RuntimeDyldImpl::~RuntimeDyldImpl() {}
23
24 namespace llvm {
25
26 void RuntimeDyldImpl::extractFunction(StringRef Name, uint8_t *StartAddress,
27                                       uint8_t *EndAddress) {
28   // Allocate memory for the function via the memory manager.
29   uintptr_t Size = EndAddress - StartAddress + 1;
30   uintptr_t AllocSize = Size;
31   uint8_t *Mem = MemMgr->startFunctionBody(Name.data(), AllocSize);
32   assert(Size >= (uint64_t)(EndAddress - StartAddress + 1) &&
33          "Memory manager failed to allocate enough memory!");
34   // Copy the function payload into the memory block.
35   memcpy(Mem, StartAddress, Size);
36   MemMgr->endFunctionBody(Name.data(), Mem, Mem + Size);
37   // Remember where we put it.
38   Functions[Name] = sys::MemoryBlock(Mem, Size);
39   // Default the assigned address for this symbol to wherever this
40   // allocated it.
41   SymbolTable[Name] = Mem;
42   DEBUG(dbgs() << "    allocated to [" << Mem << ", " << Mem + Size << "]\n");
43 }
44
45 // Resolve the relocations for all symbols we currently know about.
46 void RuntimeDyldImpl::resolveRelocations() {
47   // Just iterate over the symbols in our symbol table and assign their
48   // addresses.
49   StringMap<uint8_t*>::iterator i = SymbolTable.begin();
50   StringMap<uint8_t*>::iterator e = SymbolTable.end();
51   for (;i != e; ++i)
52     reassignSymbolAddress(i->getKey(), i->getValue());
53 }
54
55 //===----------------------------------------------------------------------===//
56 // RuntimeDyld class implementation
57 RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
58   Dyld = 0;
59   MM = mm;
60 }
61
62 RuntimeDyld::~RuntimeDyld() {
63   delete Dyld;
64 }
65
66 bool RuntimeDyld::loadObject(MemoryBuffer *InputBuffer) {
67   if (!Dyld) {
68     sys::LLVMFileType type = sys::IdentifyFileType(
69             InputBuffer->getBufferStart(),
70             static_cast<unsigned>(InputBuffer->getBufferSize()));
71     switch (type) {
72       case sys::ELF_Relocatable_FileType:
73       case sys::ELF_Executable_FileType:
74       case sys::ELF_SharedObject_FileType:
75       case sys::ELF_Core_FileType:
76         Dyld = new RuntimeDyldELF(MM);
77         break;
78       case sys::Mach_O_Object_FileType:
79       case sys::Mach_O_Executable_FileType:
80       case sys::Mach_O_FixedVirtualMemorySharedLib_FileType:
81       case sys::Mach_O_Core_FileType:
82       case sys::Mach_O_PreloadExecutable_FileType:
83       case sys::Mach_O_DynamicallyLinkedSharedLib_FileType:
84       case sys::Mach_O_DynamicLinker_FileType:
85       case sys::Mach_O_Bundle_FileType:
86       case sys::Mach_O_DynamicallyLinkedSharedLibStub_FileType:
87       case sys::Mach_O_DSYMCompanion_FileType:
88         Dyld = new RuntimeDyldMachO(MM);
89         break;
90       case sys::Unknown_FileType:
91       case sys::Bitcode_FileType:
92       case sys::Archive_FileType:
93       case sys::COFF_FileType:
94         report_fatal_error("Incompatible object format!");
95     }
96   } else {
97     if (!Dyld->isCompatibleFormat(InputBuffer))
98       report_fatal_error("Incompatible object format!");
99   }
100
101   return Dyld->loadObject(InputBuffer);
102 }
103
104 void *RuntimeDyld::getSymbolAddress(StringRef Name) {
105   return Dyld->getSymbolAddress(Name);
106 }
107
108 void RuntimeDyld::resolveRelocations() {
109   Dyld->resolveRelocations();
110 }
111
112 void RuntimeDyld::reassignSymbolAddress(StringRef Name, uint8_t *Addr) {
113   Dyld->reassignSymbolAddress(Name, Addr);
114 }
115
116 StringRef RuntimeDyld::getErrorString() {
117   return Dyld->getErrorString();
118 }
119
120 } // end namespace llvm