1//===-- llvm-rtdyld.cpp - MCJIT Testing Tool ------------------------------===// 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// This is a testing tool for use with the MC-JIT LLVM components. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/ADT/StringMap.h" 15#include "llvm/ADT/OwningPtr.h" 16#include "llvm/ExecutionEngine/RuntimeDyld.h" 17#include "llvm/Object/MachOObject.h" 18#include "llvm/Support/CommandLine.h" 19#include "llvm/Support/ManagedStatic.h" 20#include "llvm/Support/Memory.h" 21#include "llvm/Support/MemoryBuffer.h" 22#include "llvm/Support/raw_ostream.h" 23#include "llvm/Support/system_error.h" 24using namespace llvm; 25using namespace llvm::object; 26 27static cl::list<std::string> 28InputFileList(cl::Positional, cl::ZeroOrMore, 29 cl::desc("<input file>")); 30 31enum ActionType { 32 AC_Execute 33}; 34 35static cl::opt<ActionType> 36Action(cl::desc("Action to perform:"), 37 cl::init(AC_Execute), 38 cl::values(clEnumValN(AC_Execute, "execute", 39 "Load, link, and execute the inputs."), 40 clEnumValEnd)); 41 42static cl::opt<std::string> 43EntryPoint("entry", 44 cl::desc("Function to call as entry point."), 45 cl::init("_main")); 46 47/* *** */ 48 49// A trivial memory manager that doesn't do anything fancy, just uses the 50// support library allocation routines directly. 51class TrivialMemoryManager : public RTDyldMemoryManager { 52public: 53 SmallVector<sys::MemoryBlock, 16> FunctionMemory; 54 55 uint8_t *startFunctionBody(const char *Name, uintptr_t &Size); 56 void endFunctionBody(const char *Name, uint8_t *FunctionStart, 57 uint8_t *FunctionEnd); 58}; 59 60uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name, 61 uintptr_t &Size) { 62 return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); 63} 64 65void TrivialMemoryManager::endFunctionBody(const char *Name, 66 uint8_t *FunctionStart, 67 uint8_t *FunctionEnd) { 68 uintptr_t Size = FunctionEnd - FunctionStart + 1; 69 FunctionMemory.push_back(sys::MemoryBlock(FunctionStart, Size)); 70} 71 72static const char *ProgramName; 73 74static void Message(const char *Type, const Twine &Msg) { 75 errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; 76} 77 78static int Error(const Twine &Msg) { 79 Message("error", Msg); 80 return 1; 81} 82 83/* *** */ 84 85static int executeInput() { 86 // Instantiate a dynamic linker. 87 TrivialMemoryManager *MemMgr = new TrivialMemoryManager; 88 RuntimeDyld Dyld(MemMgr); 89 90 // If we don't have any input files, read from stdin. 91 if (!InputFileList.size()) 92 InputFileList.push_back("-"); 93 for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { 94 // Load the input memory buffer. 95 OwningPtr<MemoryBuffer> InputBuffer; 96 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], 97 InputBuffer)) 98 return Error("unable to read input: '" + ec.message() + "'"); 99 100 // Load the object file into it. 101 if (Dyld.loadObject(InputBuffer.take())) { 102 return Error(Dyld.getErrorString()); 103 } 104 } 105 106 // Resolve all the relocations we can. 107 Dyld.resolveRelocations(); 108 109 // FIXME: Error out if there are unresolved relocations. 110 111 // Get the address of the entry point (_main by default). 112 void *MainAddress = Dyld.getSymbolAddress(EntryPoint); 113 if (MainAddress == 0) 114 return Error("no definition for '" + EntryPoint + "'"); 115 116 // Invalidate the instruction cache for each loaded function. 117 for (unsigned i = 0, e = MemMgr->FunctionMemory.size(); i != e; ++i) { 118 sys::MemoryBlock &Data = MemMgr->FunctionMemory[i]; 119 // Make sure the memory is executable. 120 std::string ErrorStr; 121 sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); 122 if (!sys::Memory::setExecutable(Data, &ErrorStr)) 123 return Error("unable to mark function executable: '" + ErrorStr + "'"); 124 } 125 126 // Dispatch to _main(). 127 errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n"; 128 129 int (*Main)(int, const char**) = 130 (int(*)(int,const char**)) uintptr_t(MainAddress); 131 const char **Argv = new const char*[2]; 132 // Use the name of the first input object module as argv[0] for the target. 133 Argv[0] = InputFileList[0].c_str(); 134 Argv[1] = 0; 135 return Main(1, Argv); 136} 137 138int main(int argc, char **argv) { 139 ProgramName = argv[0]; 140 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 141 142 cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n"); 143 144 switch (Action) { 145 default: 146 case AC_Execute: 147 return executeInput(); 148 } 149 150 return 0; 151} 152