1 //===-- llvm-rtdyld.cpp - MCJIT Testing Tool ------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This is a testing tool for use with the MC-JIT LLVM components.
12 //===----------------------------------------------------------------------===//
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"
25 using namespace llvm::object
;
27 static cl::list
<std::string
>
28 InputFileList(cl::Positional
, cl::ZeroOrMore
,
29 cl::desc("<input file>"));
35 static cl::opt
<ActionType
>
36 Action(cl::desc("Action to perform:"),
38 cl::values(clEnumValN(AC_Execute
, "execute",
39 "Load, link, and execute the inputs."),
42 static cl::opt
<std::string
>
44 cl::desc("Function to call as entry point."),
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
{
53 SmallVector
<sys::MemoryBlock
, 16> FunctionMemory
;
55 uint8_t *startFunctionBody(const char *Name
, uintptr_t &Size
);
56 void endFunctionBody(const char *Name
, uint8_t *FunctionStart
,
57 uint8_t *FunctionEnd
);
60 uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name
,
62 return (uint8_t*)sys::Memory::AllocateRWX(Size
, 0, 0).base();
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
));
72 static const char *ProgramName
;
74 static void Message(const char *Type
, const Twine
&Msg
) {
75 errs() << ProgramName
<< ": " << Type
<< ": " << Msg
<< "\n";
78 static int Error(const Twine
&Msg
) {
79 Message("error", Msg
);
85 static int executeInput() {
86 // Instantiate a dynamic linker.
87 TrivialMemoryManager
*MemMgr
= new TrivialMemoryManager
;
88 RuntimeDyld
Dyld(MemMgr
);
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
],
98 return Error("unable to read input: '" + ec
.message() + "'");
100 // Load the object file into it.
101 if (Dyld
.loadObject(InputBuffer
.take())) {
102 return Error(Dyld
.getErrorString());
106 // Resolve all the relocations we can.
107 Dyld
.resolveRelocations();
109 // FIXME: Error out if there are unresolved relocations.
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
+ "'");
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
+ "'");
126 // Dispatch to _main().
127 errs() << "loaded '" << EntryPoint
<< "' at: " << (void*)MainAddress
<< "\n";
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();
135 return Main(1, Argv
);
138 int main(int argc
, char **argv
) {
139 ProgramName
= argv
[0];
140 llvm_shutdown_obj Y
; // Call llvm_shutdown() on exit.
142 cl::ParseCommandLineOptions(argc
, argv
, "llvm MC-JIT tool\n");
147 return executeInput();