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