llvm-rtdyld.cpp revision 263508
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/OwningPtr.h" 15#include "llvm/ADT/StringMap.h" 16#include "llvm/DebugInfo/DIContext.h" 17#include "llvm/ExecutionEngine/ObjectBuffer.h" 18#include "llvm/ExecutionEngine/ObjectImage.h" 19#include "llvm/ExecutionEngine/RuntimeDyld.h" 20#include "llvm/Object/MachO.h" 21#include "llvm/Support/CommandLine.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 "llvm/Support/system_error.h" 29using namespace llvm; 30using namespace llvm::object; 31 32static cl::list<std::string> 33InputFileList(cl::Positional, cl::ZeroOrMore, 34 cl::desc("<input file>")); 35 36enum ActionType { 37 AC_Execute, 38 AC_PrintLineInfo 39}; 40 41static cl::opt<ActionType> 42Action(cl::desc("Action to perform:"), 43 cl::init(AC_Execute), 44 cl::values(clEnumValN(AC_Execute, "execute", 45 "Load, link, and execute the inputs."), 46 clEnumValN(AC_PrintLineInfo, "printline", 47 "Load, link, and print line information for each function."), 48 clEnumValEnd)); 49 50static cl::opt<std::string> 51EntryPoint("entry", 52 cl::desc("Function to call as entry point."), 53 cl::init("_main")); 54 55/* *** */ 56 57// A trivial memory manager that doesn't do anything fancy, just uses the 58// support library allocation routines directly. 59class TrivialMemoryManager : public RTDyldMemoryManager { 60public: 61 SmallVector<sys::MemoryBlock, 16> FunctionMemory; 62 SmallVector<sys::MemoryBlock, 16> DataMemory; 63 64 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 65 unsigned SectionID, StringRef SectionName); 66 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 67 unsigned SectionID, StringRef SectionName, 68 bool IsReadOnly); 69 70 virtual void *getPointerToNamedFunction(const std::string &Name, 71 bool AbortOnFailure = true) { 72 return 0; 73 } 74 75 bool finalizeMemory(std::string *ErrMsg) { return false; } 76 77 // Invalidate instruction cache for sections with execute permissions. 78 // Some platforms with separate data cache and instruction cache require 79 // explicit cache flush, otherwise JIT code manipulations (like resolved 80 // relocations) will get to the data cache but not to the instruction cache. 81 virtual void invalidateInstructionCache(); 82}; 83 84uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, 85 unsigned Alignment, 86 unsigned SectionID, 87 StringRef SectionName) { 88 sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); 89 FunctionMemory.push_back(MB); 90 return (uint8_t*)MB.base(); 91} 92 93uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, 94 unsigned Alignment, 95 unsigned SectionID, 96 StringRef SectionName, 97 bool IsReadOnly) { 98 sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); 99 DataMemory.push_back(MB); 100 return (uint8_t*)MB.base(); 101} 102 103void TrivialMemoryManager::invalidateInstructionCache() { 104 for (int i = 0, e = FunctionMemory.size(); i != e; ++i) 105 sys::Memory::InvalidateInstructionCache(FunctionMemory[i].base(), 106 FunctionMemory[i].size()); 107 108 for (int i = 0, e = DataMemory.size(); i != e; ++i) 109 sys::Memory::InvalidateInstructionCache(DataMemory[i].base(), 110 DataMemory[i].size()); 111} 112 113static const char *ProgramName; 114 115static void Message(const char *Type, const Twine &Msg) { 116 errs() << ProgramName << ": " << Type << ": " << Msg << "\n"; 117} 118 119static int Error(const Twine &Msg) { 120 Message("error", Msg); 121 return 1; 122} 123 124/* *** */ 125 126static int printLineInfoForInput() { 127 // If we don't have any input files, read from stdin. 128 if (!InputFileList.size()) 129 InputFileList.push_back("-"); 130 for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { 131 // Instantiate a dynamic linker. 132 TrivialMemoryManager MemMgr; 133 RuntimeDyld Dyld(&MemMgr); 134 135 // Load the input memory buffer. 136 OwningPtr<MemoryBuffer> InputBuffer; 137 OwningPtr<ObjectImage> LoadedObject; 138 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], 139 InputBuffer)) 140 return Error("unable to read input: '" + ec.message() + "'"); 141 142 // Load the object file 143 LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take()))); 144 if (!LoadedObject) { 145 return Error(Dyld.getErrorString()); 146 } 147 148 // Resolve all the relocations we can. 149 Dyld.resolveRelocations(); 150 151 OwningPtr<DIContext> Context(DIContext::getDWARFContext(LoadedObject->getObjectFile())); 152 153 // Use symbol info to iterate functions in the object. 154 error_code ec; 155 for (object::symbol_iterator I = LoadedObject->begin_symbols(), 156 E = LoadedObject->end_symbols(); 157 I != E && !ec; 158 I.increment(ec)) { 159 object::SymbolRef::Type SymType; 160 if (I->getType(SymType)) continue; 161 if (SymType == object::SymbolRef::ST_Function) { 162 StringRef Name; 163 uint64_t Addr; 164 uint64_t Size; 165 if (I->getName(Name)) continue; 166 if (I->getAddress(Addr)) continue; 167 if (I->getSize(Size)) continue; 168 169 outs() << "Function: " << Name << ", Size = " << Size << "\n"; 170 171 DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); 172 DILineInfoTable::iterator Begin = Lines.begin(); 173 DILineInfoTable::iterator End = Lines.end(); 174 for (DILineInfoTable::iterator It = Begin; It != End; ++It) { 175 outs() << " Line info @ " << It->first - Addr << ": " 176 << It->second.getFileName() 177 << ", line:" << It->second.getLine() << "\n"; 178 } 179 } 180 } 181 } 182 183 return 0; 184} 185 186static int executeInput() { 187 // Instantiate a dynamic linker. 188 TrivialMemoryManager MemMgr; 189 RuntimeDyld Dyld(&MemMgr); 190 191 // If we don't have any input files, read from stdin. 192 if (!InputFileList.size()) 193 InputFileList.push_back("-"); 194 for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { 195 // Load the input memory buffer. 196 OwningPtr<MemoryBuffer> InputBuffer; 197 OwningPtr<ObjectImage> LoadedObject; 198 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], 199 InputBuffer)) 200 return Error("unable to read input: '" + ec.message() + "'"); 201 202 // Load the object file 203 LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take()))); 204 if (!LoadedObject) { 205 return Error(Dyld.getErrorString()); 206 } 207 } 208 209 // Resolve all the relocations we can. 210 Dyld.resolveRelocations(); 211 // Clear instruction cache before code will be executed. 212 MemMgr.invalidateInstructionCache(); 213 214 // FIXME: Error out if there are unresolved relocations. 215 216 // Get the address of the entry point (_main by default). 217 void *MainAddress = Dyld.getSymbolAddress(EntryPoint); 218 if (MainAddress == 0) 219 return Error("no definition for '" + EntryPoint + "'"); 220 221 // Invalidate the instruction cache for each loaded function. 222 for (unsigned i = 0, e = MemMgr.FunctionMemory.size(); i != e; ++i) { 223 sys::MemoryBlock &Data = MemMgr.FunctionMemory[i]; 224 // Make sure the memory is executable. 225 std::string ErrorStr; 226 sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); 227 if (!sys::Memory::setExecutable(Data, &ErrorStr)) 228 return Error("unable to mark function executable: '" + ErrorStr + "'"); 229 } 230 231 // Dispatch to _main(). 232 errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n"; 233 234 int (*Main)(int, const char**) = 235 (int(*)(int,const char**)) uintptr_t(MainAddress); 236 const char **Argv = new const char*[2]; 237 // Use the name of the first input object module as argv[0] for the target. 238 Argv[0] = InputFileList[0].c_str(); 239 Argv[1] = 0; 240 return Main(1, Argv); 241} 242 243int main(int argc, char **argv) { 244 sys::PrintStackTraceOnErrorSignal(); 245 PrettyStackTraceProgram X(argc, argv); 246 247 ProgramName = argv[0]; 248 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 249 250 cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n"); 251 252 switch (Action) { 253 case AC_Execute: 254 return executeInput(); 255 case AC_PrintLineInfo: 256 return printLineInfoForInput(); 257 } 258} 259