summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2014-06-27 20:20:57 +0000
committerLang Hames <lhames@gmail.com>2014-06-27 20:20:57 +0000
commitc3747f276a212e73119980479409281df57a8269 (patch)
tree0ef07885b61475d454088c60c249aee194e70b03 /tools
parent63195d7e5a1d8715566c5a33902885e28a8977c2 (diff)
downloadllvm-c3747f276a212e73119980479409281df57a8269.tar.gz
llvm-c3747f276a212e73119980479409281df57a8269.tar.bz2
llvm-c3747f276a212e73119980479409281df57a8269.tar.xz
[RuntimeDyld] Add a framework for testing relocation logic in RuntimeDyld.
This patch adds a "-verify" mode to the llvm-rtdyld utility. In verify mode, llvm-rtdyld will test supplied expressions against the linked program images that it creates in memory. This scheme can be used to verify the correctness of the relocation logic applied by RuntimeDyld. The expressions to test will be read out of files passed via the -check option (there may be more than one of these). Expressions to check are extracted from lines of the form: # rtdyld-check: <expression> This system is designed to fit the llvm-lit regression test workflow. It is format and target agnostic, and supports verification of images linked for remote targets. The expression language is defined in llvm/include/llvm/RuntimeDyldChecker.h . Examples can be found in test/ExecutionEngine/RuntimeDyld. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211956 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/llvm-rtdyld/CMakeLists.txt2
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp121
2 files changed, 120 insertions, 3 deletions
diff --git a/tools/llvm-rtdyld/CMakeLists.txt b/tools/llvm-rtdyld/CMakeLists.txt
index 3ad127fd73..feb213489d 100644
--- a/tools/llvm-rtdyld/CMakeLists.txt
+++ b/tools/llvm-rtdyld/CMakeLists.txt
@@ -1,6 +1,8 @@
set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
DebugInfo
ExecutionEngine
+ MC
RuntimeDyld
Support
)
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index f1364d5350..fcda9e7f8a 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -16,6 +16,13 @@
#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"
@@ -23,9 +30,12 @@
#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/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>
@@ -57,6 +70,14 @@ 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
@@ -139,7 +160,6 @@ static void loadDylibs() {
}
}
-
/* *** */
static int printLineInfoForInput() {
@@ -263,6 +283,95 @@ static int executeInput() {
return Main(1, Argv);
}
+static int checkAllExpressions(RuntimeDyldChecker &Checker) {
+ for (const auto& CheckerFileName : CheckFiles) {
+ std::unique_ptr<MemoryBuffer> CheckerFileBuf;
+ if (std::error_code EC =
+ MemoryBuffer::getFileOrSTDIN(CheckerFileName, CheckerFileBuf))
+ return Error("unable to read input '" + CheckerFileName + "': " +
+ EC.message());
+
+ if (!Checker.checkAllRulesInBuffer("# rtdyld-check:", CheckerFileBuf.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.
+ std::unique_ptr<MemoryBuffer> InputBuffer;
+ std::unique_ptr<ObjectImage> LoadedObject;
+ if (std::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.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);
@@ -270,6 +379,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) {
@@ -277,5 +390,7 @@ int main(int argc, char **argv) {
return executeInput();
case AC_PrintLineInfo:
return printLineInfoForInput();
+ case AC_Verify:
+ return linkAndVerify();
}
}