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/DebugInfo/DIContext.h"
16 #include "llvm/ExecutionEngine/ObjectBuffer.h"
17 #include "llvm/ExecutionEngine/ObjectImage.h"
18 #include "llvm/ExecutionEngine/RuntimeDyld.h"
19 #include "llvm/Object/MachO.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/DynamicLibrary.h"
22 #include "llvm/Support/ManagedStatic.h"
23 #include "llvm/Support/Memory.h"
24 #include "llvm/Support/MemoryBuffer.h"
25 #include "llvm/Support/PrettyStackTrace.h"
26 #include "llvm/Support/Signals.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include <system_error>
30 using namespace llvm::object;
31 using std::error_code;
33 static cl::list<std::string>
34 InputFileList(cl::Positional, cl::ZeroOrMore,
35 cl::desc("<input file>"));
42 static cl::opt<ActionType>
43 Action(cl::desc("Action to perform:"),
45 cl::values(clEnumValN(AC_Execute, "execute",
46 "Load, link, and execute the inputs."),
47 clEnumValN(AC_PrintLineInfo, "printline",
48 "Load, link, and print line information for each function."),
51 static cl::opt<std::string>
53 cl::desc("Function to call as entry point."),
56 static cl::list<std::string>
58 cl::desc("Add library."),
63 // A trivial memory manager that doesn't do anything fancy, just uses the
64 // support library allocation routines directly.
65 class TrivialMemoryManager : public RTDyldMemoryManager {
67 SmallVector<sys::MemoryBlock, 16> FunctionMemory;
68 SmallVector<sys::MemoryBlock, 16> DataMemory;
70 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
72 StringRef SectionName) override;
73 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
74 unsigned SectionID, StringRef SectionName,
75 bool IsReadOnly) override;
77 void *getPointerToNamedFunction(const std::string &Name,
78 bool AbortOnFailure = true) override {
82 bool finalizeMemory(std::string *ErrMsg) override { return false; }
84 // Invalidate instruction cache for sections with execute permissions.
85 // Some platforms with separate data cache and instruction cache require
86 // explicit cache flush, otherwise JIT code manipulations (like resolved
87 // relocations) will get to the data cache but not to the instruction cache.
88 virtual void invalidateInstructionCache();
91 uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size,
94 StringRef SectionName) {
95 sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr);
96 FunctionMemory.push_back(MB);
97 return (uint8_t*)MB.base();
100 uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size,
103 StringRef SectionName,
105 sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr);
106 DataMemory.push_back(MB);
107 return (uint8_t*)MB.base();
110 void TrivialMemoryManager::invalidateInstructionCache() {
111 for (int i = 0, e = FunctionMemory.size(); i != e; ++i)
112 sys::Memory::InvalidateInstructionCache(FunctionMemory[i].base(),
113 FunctionMemory[i].size());
115 for (int i = 0, e = DataMemory.size(); i != e; ++i)
116 sys::Memory::InvalidateInstructionCache(DataMemory[i].base(),
117 DataMemory[i].size());
120 static const char *ProgramName;
122 static void Message(const char *Type, const Twine &Msg) {
123 errs() << ProgramName << ": " << Type << ": " << Msg << "\n";
126 static int Error(const Twine &Msg) {
127 Message("error", Msg);
131 static void loadDylibs() {
132 for (const std::string &Dylib : Dylibs) {
133 if (sys::fs::is_regular_file(Dylib)) {
135 if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg))
136 llvm::errs() << "Error loading '" << Dylib << "': "
139 llvm::errs() << "Dylib not found: '" << Dylib << "'.\n";
146 static int printLineInfoForInput() {
147 // Load any dylibs requested on the command line.
150 // If we don't have any input files, read from stdin.
151 if (!InputFileList.size())
152 InputFileList.push_back("-");
153 for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
154 // Instantiate a dynamic linker.
155 TrivialMemoryManager MemMgr;
156 RuntimeDyld Dyld(&MemMgr);
158 // Load the input memory buffer.
159 std::unique_ptr<MemoryBuffer> InputBuffer;
160 std::unique_ptr<ObjectImage> LoadedObject;
161 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i],
163 return Error("unable to read input: '" + ec.message() + "'");
165 // Load the object file
166 LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.release())));
168 return Error(Dyld.getErrorString());
171 // Resolve all the relocations we can.
172 Dyld.resolveRelocations();
174 std::unique_ptr<DIContext> Context(
175 DIContext::getDWARFContext(LoadedObject->getObjectFile()));
177 // Use symbol info to iterate functions in the object.
178 for (object::symbol_iterator I = LoadedObject->begin_symbols(),
179 E = LoadedObject->end_symbols();
181 object::SymbolRef::Type SymType;
182 if (I->getType(SymType)) continue;
183 if (SymType == object::SymbolRef::ST_Function) {
187 if (I->getName(Name)) continue;
188 if (I->getAddress(Addr)) continue;
189 if (I->getSize(Size)) continue;
191 outs() << "Function: " << Name << ", Size = " << Size << "\n";
193 DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
194 DILineInfoTable::iterator Begin = Lines.begin();
195 DILineInfoTable::iterator End = Lines.end();
196 for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
197 outs() << " Line info @ " << It->first - Addr << ": "
198 << It->second.FileName << ", line:" << It->second.Line << "\n";
207 static int executeInput() {
208 // Load any dylibs requested on the command line.
211 // Instantiate a dynamic linker.
212 TrivialMemoryManager MemMgr;
213 RuntimeDyld Dyld(&MemMgr);
215 // If we don't have any input files, read from stdin.
216 if (!InputFileList.size())
217 InputFileList.push_back("-");
218 for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
219 // Load the input memory buffer.
220 std::unique_ptr<MemoryBuffer> InputBuffer;
221 std::unique_ptr<ObjectImage> LoadedObject;
222 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i],
224 return Error("unable to read input: '" + ec.message() + "'");
226 // Load the object file
227 LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.release())));
229 return Error(Dyld.getErrorString());
233 // Resolve all the relocations we can.
234 Dyld.resolveRelocations();
235 // Clear instruction cache before code will be executed.
236 MemMgr.invalidateInstructionCache();
238 // FIXME: Error out if there are unresolved relocations.
240 // Get the address of the entry point (_main by default).
241 void *MainAddress = Dyld.getSymbolAddress(EntryPoint);
243 return Error("no definition for '" + EntryPoint + "'");
245 // Invalidate the instruction cache for each loaded function.
246 for (unsigned i = 0, e = MemMgr.FunctionMemory.size(); i != e; ++i) {
247 sys::MemoryBlock &Data = MemMgr.FunctionMemory[i];
248 // Make sure the memory is executable.
249 std::string ErrorStr;
250 sys::Memory::InvalidateInstructionCache(Data.base(), Data.size());
251 if (!sys::Memory::setExecutable(Data, &ErrorStr))
252 return Error("unable to mark function executable: '" + ErrorStr + "'");
255 // Dispatch to _main().
256 errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n";
258 int (*Main)(int, const char**) =
259 (int(*)(int,const char**)) uintptr_t(MainAddress);
260 const char **Argv = new const char*[2];
261 // Use the name of the first input object module as argv[0] for the target.
262 Argv[0] = InputFileList[0].c_str();
264 return Main(1, Argv);
267 int main(int argc, char **argv) {
268 sys::PrintStackTraceOnErrorSignal();
269 PrettyStackTraceProgram X(argc, argv);
271 ProgramName = argv[0];
272 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
274 cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n");
278 return executeInput();
279 case AC_PrintLineInfo:
280 return printLineInfoForInput();