166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===-- llvm-rtdyld.cpp - MCJIT Testing Tool ------------------------------===// 266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// The LLVM Compiler Infrastructure 466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This file is distributed under the University of Illinois Open Source 666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// License. See LICENSE.TXT for details. 766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 1066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// This is a testing tool for use with the MC-JIT LLVM components. 1166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// 1266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman//===----------------------------------------------------------------------===// 1366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 1466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/ADT/StringMap.h" 1566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/ADT/OwningPtr.h" 1666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/ExecutionEngine/RuntimeDyld.h" 1766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Object/MachOObject.h" 1866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/CommandLine.h" 1966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/ManagedStatic.h" 2066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/Memory.h" 2166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/MemoryBuffer.h" 2266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/raw_ostream.h" 2366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman#include "llvm/Support/system_error.h" 2466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanusing namespace llvm; 2566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanusing namespace llvm::object; 2666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 2766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic cl::list<std::string> 2866b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanInputFileList(cl::Positional, cl::ZeroOrMore, 2966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("<input file>")); 3066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanenum ActionType { 3266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman AC_Execute 3366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}; 3466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 3566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic cl::opt<ActionType> 3666b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanAction(cl::desc("Action to perform:"), 3766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::init(AC_Execute), 3866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::values(clEnumValN(AC_Execute, "execute", 3966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman "Load, link, and execute the inputs."), 4066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman clEnumValEnd)); 4166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic cl::opt<std::string> 4366b8ab22586debccb1f787d4d52b7f042d4ddeb8John BaumanEntryPoint("entry", 4466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::desc("Function to call as entry point."), 4566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::init("_main")); 4666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/* *** */ 4866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 4966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// A trivial memory manager that doesn't do anything fancy, just uses the 5066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman// support library allocation routines directly. 5166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanclass TrivialMemoryManager : public RTDyldMemoryManager { 5266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanpublic: 5366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman SmallVector<sys::MemoryBlock, 16> FunctionMemory; 5466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 5566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman uint8_t *startFunctionBody(const char *Name, uintptr_t &Size); 5666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman void endFunctionBody(const char *Name, uint8_t *FunctionStart, 5766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman uint8_t *FunctionEnd); 5866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman}; 5966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanuint8_t *TrivialMemoryManager::startFunctionBody(const char *Name, 6166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman uintptr_t &Size) { 6266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); 6366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 6466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 6566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanvoid TrivialMemoryManager::endFunctionBody(const char *Name, 6666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman uint8_t *FunctionStart, 6766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman uint8_t *FunctionEnd) { 6866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman uintptr_t Size = FunctionEnd - FunctionStart + 1; 6966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman FunctionMemory.push_back(sys::MemoryBlock(FunctionStart, Size)); 7066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 7166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic const char *ProgramName; 7366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic void Message(const char *Type, const Twine &Msg) { 7566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; 7666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 7766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 7866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic int Error(const Twine &Msg) { 7966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Message("error", Msg); 8066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 1; 8166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 8266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman/* *** */ 8466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 8566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanstatic int executeInput() { 8666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Instantiate a dynamic linker. 8766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman TrivialMemoryManager *MemMgr = new TrivialMemoryManager; 8866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman RuntimeDyld Dyld(MemMgr); 8966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 9066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // If we don't have any input files, read from stdin. 9166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!InputFileList.size()) 9266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman InputFileList.push_back("-"); 9366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { 9466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Load the input memory buffer. 9566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman OwningPtr<MemoryBuffer> InputBuffer; 9666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], 9766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman InputBuffer)) 9866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return Error("unable to read input: '" + ec.message() + "'"); 9966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Load the object file into it. 10166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (Dyld.loadObject(InputBuffer.take())) { 10266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return Error(Dyld.getErrorString()); 10366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 10466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 10566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Resolve all the relocations we can. 10766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Dyld.resolveRelocations(); 10866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 10966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // FIXME: Error out if there are unresolved relocations. 11066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 11166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Get the address of the entry point (_main by default). 11266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman void *MainAddress = Dyld.getSymbolAddress(EntryPoint); 11366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (MainAddress == 0) 11466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return Error("no definition for '" + EntryPoint + "'"); 11566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 11666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Invalidate the instruction cache for each loaded function. 11766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman for (unsigned i = 0, e = MemMgr->FunctionMemory.size(); i != e; ++i) { 11866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::MemoryBlock &Data = MemMgr->FunctionMemory[i]; 11966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Make sure the memory is executable. 12066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman std::string ErrorStr; 12166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); 12266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman if (!sys::Memory::setExecutable(Data, &ErrorStr)) 12366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return Error("unable to mark function executable: '" + ErrorStr + "'"); 12466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 12566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 12666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Dispatch to _main(). 12766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n"; 12866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 12966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman int (*Main)(int, const char**) = 13066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman (int(*)(int,const char**)) uintptr_t(MainAddress); 13166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman const char **Argv = new const char*[2]; 13266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman // Use the name of the first input object module as argv[0] for the target. 13366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Argv[0] = InputFileList[0].c_str(); 13466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman Argv[1] = 0; 13566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return Main(1, Argv); 13666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 13766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 13866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Baumanint main(int argc, char **argv) { 13966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman ProgramName = argv[0]; 14066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 14166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 14266b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n"); 14366b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 14466b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman switch (Action) { 14566b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman default: 14666b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman case AC_Execute: 14766b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return executeInput(); 14866b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman } 14966b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman 15066b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman return 0; 15166b8ab22586debccb1f787d4d52b7f042d4ddeb8John Bauman} 152