diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 17:02:24 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 17:02:24 +0000 |
commit | 91bc56ed825ba56b3cc264aa5c95ab84f86832ab (patch) | |
tree | 4df130b28021d86e13bf4565ef58c1c5a5e093b4 /contrib/llvm/tools/llvm-rtdyld | |
parent | 9efc7e72bb1daf5d6019871d9c93a1c488a11229 (diff) | |
parent | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (diff) | |
download | src-91bc56ed825ba56b3cc264aa5c95ab84f86832ab.tar.gz src-91bc56ed825ba56b3cc264aa5c95ab84f86832ab.zip |
Merge llvm 3.5.0 release from ^/vendor/llvm/dist, resolve conflicts, and
preserve our customizations, where necessary.
Notes
Notes:
svn path=/projects/clang350-import/; revision=274968
Diffstat (limited to 'contrib/llvm/tools/llvm-rtdyld')
-rw-r--r-- | contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp | 207 |
1 files changed, 174 insertions, 33 deletions
diff --git a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp index 531595eacddd..45734f4b7ba6 100644 --- a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -11,21 +11,31 @@ // //===----------------------------------------------------------------------===// -#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/ExecutionEngine/RuntimeDyldChecker.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Object/MachO.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/DynamicLibrary.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" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include <system_error> + using namespace llvm; using namespace llvm::object; @@ -35,7 +45,8 @@ InputFileList(cl::Positional, cl::ZeroOrMore, enum ActionType { AC_Execute, - AC_PrintLineInfo + AC_PrintLineInfo, + AC_Verify }; static cl::opt<ActionType> @@ -45,6 +56,8 @@ Action(cl::desc("Action to perform:"), "Load, link, and execute the inputs."), clEnumValN(AC_PrintLineInfo, "printline", "Load, link, and print line information for each function."), + clEnumValN(AC_Verify, "verify", + "Load, link and verify the resulting memory image."), clEnumValEnd)); static cl::opt<std::string> @@ -52,6 +65,19 @@ EntryPoint("entry", cl::desc("Function to call as entry point."), cl::init("_main")); +static cl::list<std::string> +Dylibs("dylib", + cl::desc("Add library."), + cl::ZeroOrMore); + +static cl::opt<std::string> +TripleName("triple", cl::desc("Target triple for disassembler")); + +static cl::list<std::string> +CheckFiles("check", + cl::desc("File containing RuntimeDyld verifier checks."), + cl::ZeroOrMore); + /* *** */ // A trivial memory manager that doesn't do anything fancy, just uses the @@ -62,17 +88,18 @@ public: SmallVector<sys::MemoryBlock, 16> DataMemory; uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, StringRef SectionName); + unsigned SectionID, + StringRef SectionName) override; uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, - bool IsReadOnly); + bool IsReadOnly) override; - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { - return 0; + void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) override { + return nullptr; } - bool finalizeMemory(std::string *ErrMsg) { return false; } + bool finalizeMemory(std::string *ErrMsg) override { return false; } // Invalidate instruction cache for sections with execute permissions. // Some platforms with separate data cache and instruction cache require @@ -85,7 +112,7 @@ uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) { - sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); + sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr); FunctionMemory.push_back(MB); return (uint8_t*)MB.base(); } @@ -95,7 +122,7 @@ uint8_t *TrivialMemoryManager::allocateDataSection(uintptr_t Size, unsigned SectionID, StringRef SectionName, bool IsReadOnly) { - sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, 0, 0); + sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr); DataMemory.push_back(MB); return (uint8_t*)MB.base(); } @@ -121,9 +148,24 @@ static int Error(const Twine &Msg) { return 1; } +static void loadDylibs() { + for (const std::string &Dylib : Dylibs) { + if (sys::fs::is_regular_file(Dylib)) { + std::string ErrMsg; + if (sys::DynamicLibrary::LoadLibraryPermanently(Dylib.c_str(), &ErrMsg)) + llvm::errs() << "Error loading '" << Dylib << "': " + << ErrMsg << "\n"; + } else + llvm::errs() << "Dylib not found: '" << Dylib << "'.\n"; + } +} + /* *** */ static int printLineInfoForInput() { + // Load any dylibs requested on the command line. + loadDylibs(); + // If we don't have any input files, read from stdin. if (!InputFileList.size()) InputFileList.push_back("-"); @@ -133,14 +175,16 @@ static int printLineInfoForInput() { RuntimeDyld Dyld(&MemMgr); // Load the input memory buffer. - OwningPtr<MemoryBuffer> InputBuffer; - OwningPtr<ObjectImage> LoadedObject; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], - InputBuffer)) - return Error("unable to read input: '" + ec.message() + "'"); + ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer = + MemoryBuffer::getFileOrSTDIN(InputFileList[i]); + if (std::error_code EC = InputBuffer.getError()) + return Error("unable to read input: '" + EC.message() + "'"); + + std::unique_ptr<ObjectImage> LoadedObject; // Load the object file - LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take()))); + LoadedObject.reset( + Dyld.loadObject(new ObjectBuffer(InputBuffer.get().release()))); if (!LoadedObject) { return Error(Dyld.getErrorString()); } @@ -148,14 +192,13 @@ static int printLineInfoForInput() { // Resolve all the relocations we can. Dyld.resolveRelocations(); - OwningPtr<DIContext> Context(DIContext::getDWARFContext(LoadedObject->getObjectFile())); + std::unique_ptr<DIContext> Context( + DIContext::getDWARFContext(LoadedObject->getObjectFile())); // Use symbol info to iterate functions in the object. - error_code ec; for (object::symbol_iterator I = LoadedObject->begin_symbols(), E = LoadedObject->end_symbols(); - I != E && !ec; - I.increment(ec)) { + I != E; ++I) { object::SymbolRef::Type SymType; if (I->getType(SymType)) continue; if (SymType == object::SymbolRef::ST_Function) { @@ -173,8 +216,7 @@ static int printLineInfoForInput() { 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"; + << It->second.FileName << ", line:" << It->second.Line << "\n"; } } } @@ -184,6 +226,9 @@ static int printLineInfoForInput() { } static int executeInput() { + // Load any dylibs requested on the command line. + loadDylibs(); + // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; RuntimeDyld Dyld(&MemMgr); @@ -193,14 +238,14 @@ static int executeInput() { InputFileList.push_back("-"); for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Load the input memory buffer. - OwningPtr<MemoryBuffer> InputBuffer; - OwningPtr<ObjectImage> LoadedObject; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], - InputBuffer)) - return Error("unable to read input: '" + ec.message() + "'"); - + ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer = + MemoryBuffer::getFileOrSTDIN(InputFileList[i]); + if (std::error_code EC = InputBuffer.getError()) + return Error("unable to read input: '" + EC.message() + "'"); + std::unique_ptr<ObjectImage> LoadedObject; // Load the object file - LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take()))); + LoadedObject.reset( + Dyld.loadObject(new ObjectBuffer(InputBuffer.get().release()))); if (!LoadedObject) { return Error(Dyld.getErrorString()); } @@ -215,7 +260,7 @@ static int executeInput() { // Get the address of the entry point (_main by default). void *MainAddress = Dyld.getSymbolAddress(EntryPoint); - if (MainAddress == 0) + if (!MainAddress) return Error("no definition for '" + EntryPoint + "'"); // Invalidate the instruction cache for each loaded function. @@ -236,10 +281,100 @@ static int executeInput() { const char **Argv = new const char*[2]; // Use the name of the first input object module as argv[0] for the target. Argv[0] = InputFileList[0].c_str(); - Argv[1] = 0; + Argv[1] = nullptr; return Main(1, Argv); } +static int checkAllExpressions(RuntimeDyldChecker &Checker) { + for (const auto& CheckerFileName : CheckFiles) { + ErrorOr<std::unique_ptr<MemoryBuffer>> CheckerFileBuf = + MemoryBuffer::getFileOrSTDIN(CheckerFileName); + if (std::error_code EC = CheckerFileBuf.getError()) + return Error("unable to read input '" + CheckerFileName + "': " + + EC.message()); + + if (!Checker.checkAllRulesInBuffer("# rtdyld-check:", + CheckerFileBuf.get().get())) + return Error("some checks in '" + CheckerFileName + "' failed"); + } + return 0; +} + +static int linkAndVerify() { + + // Check for missing triple. + if (TripleName == "") { + llvm::errs() << "Error: -triple required when running in -verify mode.\n"; + return 1; + } + + // Look up the target and build the disassembler. + Triple TheTriple(Triple::normalize(TripleName)); + std::string ErrorStr; + const Target *TheTarget = + TargetRegistry::lookupTarget("", TheTriple, ErrorStr); + if (!TheTarget) { + llvm::errs() << "Error accessing target '" << TripleName << "': " + << ErrorStr << "\n"; + return 1; + } + TripleName = TheTriple.getTriple(); + + std::unique_ptr<MCSubtargetInfo> STI( + TheTarget->createMCSubtargetInfo(TripleName, "", "")); + assert(STI && "Unable to create subtarget info!"); + + std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); + assert(MRI && "Unable to create target register info!"); + + std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); + assert(MAI && "Unable to create target asm info!"); + + MCContext Ctx(MAI.get(), MRI.get(), nullptr); + + std::unique_ptr<MCDisassembler> Disassembler( + TheTarget->createMCDisassembler(*STI, Ctx)); + assert(Disassembler && "Unable to create disassembler!"); + + std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo()); + + std::unique_ptr<MCInstPrinter> InstPrinter( + TheTarget->createMCInstPrinter(0, *MAI, *MII, *MRI, *STI)); + + // Load any dylibs requested on the command line. + loadDylibs(); + + // Instantiate a dynamic linker. + TrivialMemoryManager MemMgr; + RuntimeDyld Dyld(&MemMgr); + + // 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) { + // Load the input memory buffer. + ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer = + MemoryBuffer::getFileOrSTDIN(InputFileList[i]); + if (std::error_code EC = InputBuffer.getError()) + return Error("unable to read input: '" + EC.message() + "'"); + + std::unique_ptr<ObjectImage> LoadedObject; + // Load the object file + LoadedObject.reset( + Dyld.loadObject(new ObjectBuffer(InputBuffer.get().release()))); + if (!LoadedObject) { + return Error(Dyld.getErrorString()); + } + } + + // Resolve all the relocations we can. + Dyld.resolveRelocations(); + + RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(), + llvm::dbgs()); + return checkAllExpressions(Checker); +} + int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); @@ -247,6 +382,10 @@ int main(int argc, char **argv) { ProgramName = argv[0]; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllDisassemblers(); + cl::ParseCommandLineOptions(argc, argv, "llvm MC-JIT tool\n"); switch (Action) { @@ -254,5 +393,7 @@ int main(int argc, char **argv) { return executeInput(); case AC_PrintLineInfo: return printLineInfoForInput(); + case AC_Verify: + return linkAndVerify(); } } |