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" 24 using namespace llvm; 25 using namespace llvm::object; 26 27 static cl::list<std::string> 28 InputFileList(cl::Positional, cl::ZeroOrMore, 29 cl::desc("<input file>")); 30 31 enum ActionType { 32 AC_Execute 33 }; 34 35 static cl::opt<ActionType> 36 Action(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 42 static cl::opt<std::string> 43 EntryPoint("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. 51 class TrivialMemoryManager : public RTDyldMemoryManager { 52 public: 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 60 uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name, 61 uintptr_t &Size) { 62 return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); 63 } 64 65 void 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 72 static const char *ProgramName; 73 74 static void Message(const char *Type, const Twine &Msg) { 75 errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; 76 } 77 78 static int Error(const Twine &Msg) { 79 Message("error", Msg); 80 return 1; 81 } 82 83 /* *** */ 84 85 static 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 138 int 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