X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-rtdyld%2Fllvm-rtdyld.cpp;h=65c0ab72553895fd5ddf7c198a3520ee229d05c7;hb=3bd3f426a517f8a8f05e20ebc0c1a56e2a6365ac;hp=9fec7c464c5dbb8cfa1e89c383f6c7c603aca18e;hpb=61425c0a7f4e3608a85f7bbf254cd052a15b7446;p=oota-llvm.git diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 9fec7c464c5..65c0ab72553 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -11,14 +11,19 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/ExecutionEngine/ObjectBuffer.h" +#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachO.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Memory.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" using namespace llvm; @@ -29,7 +34,8 @@ InputFileList(cl::Positional, cl::ZeroOrMore, cl::desc("")); enum ActionType { - AC_Execute + AC_Execute, + AC_PrintLineInfo }; static cl::opt @@ -37,6 +43,8 @@ Action(cl::desc("Action to perform:"), cl::init(AC_Execute), cl::values(clEnumValN(AC_Execute, "execute", "Load, link, and execute the inputs."), + clEnumValN(AC_PrintLineInfo, "printline", + "Load, link, and print line information for each function."), clEnumValEnd)); static cl::opt @@ -54,37 +62,52 @@ public: SmallVector DataMemory; uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, StringRef SectionName); uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID); + unsigned SectionID, StringRef SectionName, + bool IsReadOnly); + + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) { + return 0; + } + + bool finalizeMemory(std::string *ErrMsg) { return false; } - uint8_t *startFunctionBody(const char *Name, uintptr_t &Size); - void endFunctionBody(const char *Name, uint8_t *FunctionStart, - uint8_t *FunctionEnd); + // Invalidate instruction cache for sections with execute permissions. + // Some platforms with separate data cache and instruction cache require + // explicit cache flush, otherwise JIT code manipulations (like resolved + // relocations) will get to the data cache but not to the instruction cache. + virtual void invalidateInstructionCache(); }; uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) { - return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); + unsigned SectionID, + StringRef SectionName) { + sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); + FunctionMemory.push_back(MB); + return (uint8_t*)MB.base(); } uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID) { - return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) { + sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); + DataMemory.push_back(MB); + return (uint8_t*)MB.base(); } -uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name, - uintptr_t &Size) { - return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); -} +void TrivialMemoryManager::invalidateInstructionCache() { + for (int i = 0, e = FunctionMemory.size(); i != e; ++i) + sys::Memory::InvalidateInstructionCache(FunctionMemory[i].base(), + FunctionMemory[i].size()); -void TrivialMemoryManager::endFunctionBody(const char *Name, - uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - uintptr_t Size = FunctionEnd - FunctionStart + 1; - FunctionMemory.push_back(sys::MemoryBlock(FunctionStart, Size)); + for (int i = 0, e = DataMemory.size(); i != e; ++i) + sys::Memory::InvalidateInstructionCache(DataMemory[i].base(), + DataMemory[i].size()); } static const char *ProgramName; @@ -100,10 +123,68 @@ static int Error(const Twine &Msg) { /* *** */ +static int printLineInfoForInput() { + // If we don't have any input files, read from stdin. + if (!InputFileList.size()) + InputFileList.push_back("-"); + for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { + // Instantiate a dynamic linker. + TrivialMemoryManager MemMgr; + RuntimeDyld Dyld(&MemMgr); + + // Load the input memory buffer. + OwningPtr InputBuffer; + OwningPtr LoadedObject; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], + InputBuffer)) + return Error("unable to read input: '" + ec.message() + "'"); + + // Load the object file + LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take()))); + if (!LoadedObject) { + return Error(Dyld.getErrorString()); + } + + // Resolve all the relocations we can. + Dyld.resolveRelocations(); + + OwningPtr Context(DIContext::getDWARFContext(LoadedObject->getObjectFile())); + + // Use symbol info to iterate functions in the object. + for (object::symbol_iterator I = LoadedObject->begin_symbols(), + E = LoadedObject->end_symbols(); + I != E; ++I) { + object::SymbolRef::Type SymType; + if (I->getType(SymType)) continue; + if (SymType == object::SymbolRef::ST_Function) { + StringRef Name; + uint64_t Addr; + uint64_t Size; + if (I->getName(Name)) continue; + if (I->getAddress(Addr)) continue; + if (I->getSize(Size)) continue; + + outs() << "Function: " << Name << ", Size = " << Size << "\n"; + + DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); + DILineInfoTable::iterator Begin = Lines.begin(); + DILineInfoTable::iterator End = Lines.end(); + for (DILineInfoTable::iterator It = Begin; It != End; ++It) { + outs() << " Line info @ " << It->first - Addr << ": " + << It->second.getFileName() + << ", line:" << It->second.getLine() << "\n"; + } + } + } + } + + return 0; +} + static int executeInput() { // Instantiate a dynamic linker. - TrivialMemoryManager *MemMgr = new TrivialMemoryManager; - RuntimeDyld Dyld(MemMgr); + TrivialMemoryManager MemMgr; + RuntimeDyld Dyld(&MemMgr); // If we don't have any input files, read from stdin. if (!InputFileList.size()) @@ -111,18 +192,22 @@ static int executeInput() { for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Load the input memory buffer. OwningPtr InputBuffer; + OwningPtr LoadedObject; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], InputBuffer)) return Error("unable to read input: '" + ec.message() + "'"); - // Load the object file into it. - if (Dyld.loadObject(InputBuffer.take())) { + // Load the object file + LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take()))); + if (!LoadedObject) { return Error(Dyld.getErrorString()); } } // Resolve all the relocations we can. Dyld.resolveRelocations(); + // Clear instruction cache before code will be executed. + MemMgr.invalidateInstructionCache(); // FIXME: Error out if there are unresolved relocations. @@ -132,8 +217,8 @@ static int executeInput() { return Error("no definition for '" + EntryPoint + "'"); // Invalidate the instruction cache for each loaded function. - for (unsigned i = 0, e = MemMgr->FunctionMemory.size(); i != e; ++i) { - sys::MemoryBlock &Data = MemMgr->FunctionMemory[i]; + for (unsigned i = 0, e = MemMgr.FunctionMemory.size(); i != e; ++i) { + sys::MemoryBlock &Data = MemMgr.FunctionMemory[i]; // Make sure the memory is executable. std::string ErrorStr; sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); @@ -154,6 +239,9 @@ static int executeInput() { } int main(int argc, char **argv) { + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + ProgramName = argv[0]; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. @@ -162,7 +250,7 @@ int main(int argc, char **argv) { switch (Action) { case AC_Execute: return executeInput(); + case AC_PrintLineInfo: + return printLineInfoForInput(); } - - return 0; }