[MCJIT] Add options to llvm-rtdyld to describe a phony target address space for
authorLang Hames <lhames@gmail.com>
Tue, 29 Jul 2014 23:43:13 +0000 (23:43 +0000)
committerLang Hames <lhames@gmail.com>
Tue, 29 Jul 2014 23:43:13 +0000 (23:43 +0000)
use in -verify mode.

This patch adds three hidden command line options to llvm-rtdyld:

 -target-addr-start <start-addr> : Specify the start of the virtual address
                                   space on the phony target.

 -target-addr-end   <end-addr>   : Specify the end of the virtual address space
                                   on the phony target.

 -target-section-sep <sep>       : Specify the separation (in bytes) between the
                                   end of one section and the start of the next.

These options automatically default to sane values for the target platform. In
particular, they allow narrow (e.g. 32-bit, 16-bit) targets to be tested from
wider (e.g. 64-bit, 32-bit) hosts without overflowing pointers.

The section separation option defaults to zero, but can be set to a large number
(e.g. 1 << 32) to force large separations between sections in order to
stress-test large-code-model code.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214255 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
tools/llvm-rtdyld/llvm-rtdyld.cpp

index 9873897..d244f45 100644 (file)
@@ -749,12 +749,12 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubAddrFor(
 
   uint64_t Addr;
   if (IsInsideLoad) {
-    uint64_t SectionBase = getRTDyld().Sections[SectionID].LoadAddress;
-    Addr = SectionBase + StubOffset;
-  } else {
     uintptr_t SectionBase =
         reinterpret_cast<uintptr_t>(getRTDyld().Sections[SectionID].Address);
     Addr = static_cast<uint64_t>(SectionBase) + StubOffset;
+  } else {
+    uint64_t SectionBase = getRTDyld().Sections[SectionID].LoadAddress;
+    Addr = SectionBase + StubOffset;
   }
 
   return std::make_pair(Addr, std::string(""));
index 0bed9df..5cea465 100644 (file)
@@ -78,6 +78,26 @@ CheckFiles("check",
            cl::desc("File containing RuntimeDyld verifier checks."),
            cl::ZeroOrMore);
 
+static cl::opt<uint64_t>
+TargetAddrStart("target-addr-start",
+                cl::desc("For -verify only: start of phony target address "
+                         "range."),
+                cl::init(4096), // Start at "page 1" - no allocating at "null".
+                cl::Hidden);
+
+static cl::opt<uint64_t>
+TargetAddrEnd("target-addr-end",
+              cl::desc("For -verify only: end of phony target address range."),
+              cl::init(~0ULL),
+              cl::Hidden);
+
+static cl::opt<uint64_t>
+TargetSectionSep("target-section-sep",
+                 cl::desc("For -verify only: Separation between sections in "
+                          "phony target address space."),
+                 cl::init(0),
+                 cl::Hidden);
+
 /* *** */
 
 // A trivial memory manager that doesn't do anything fancy, just uses the
@@ -300,6 +320,50 @@ static int checkAllExpressions(RuntimeDyldChecker &Checker) {
   return 0;
 }
 
+// Scatter sections in all directions!
+// Remaps section addresses for -verify mode. The following command line options
+// can be used to customize the layout of the memory within the phony target's
+// address space:
+// -target-addr-start <s> -- Specify where the phony target addres range starts.
+// -target-addr-end   <e> -- Specify where the phony target address range ends.
+// -target-section-sep <d> -- Specify how big a gap should be left between the
+//                            end of one section and the start of the next.
+//                            Defaults to zero. Set to something big
+//                            (e.g. 1 << 32) to stress-test stubs, GOTs, etc.
+//
+void remapSections(const llvm::Triple &TargetTriple,
+                   const TrivialMemoryManager &MemMgr,
+                   RuntimeDyld &RTDyld) {
+
+  // If the -target-addr-end option wasn't explicitly passed, then set it to a
+  // sensible default based on the target triple.
+  if (TargetAddrEnd.getNumOccurrences() == 0) {
+    if (TargetTriple.isArch16Bit())
+      TargetAddrEnd = (1ULL << 16) - 1;
+    else if (TargetTriple.isArch32Bit())
+      TargetAddrEnd = (1ULL << 32) - 1;
+    // TargetAddrEnd already has a sensible default for 64-bit systems, so
+    // there's nothing to do in the 64-bit case.
+  }
+
+  uint64_t NextSectionAddress = TargetAddrStart;
+
+  // Remap code sections.
+  for (const auto& CodeSection : MemMgr.FunctionMemory) {
+    RTDyld.mapSectionAddress(CodeSection.base(), NextSectionAddress);
+    NextSectionAddress += CodeSection.size() + TargetSectionSep;
+  }
+
+  // Remap data sections.
+  for (const auto& DataSection : MemMgr.DataMemory) {
+    RTDyld.mapSectionAddress(DataSection.base(), NextSectionAddress);
+    NextSectionAddress += DataSection.size() + TargetSectionSep;
+  }
+}
+
+// Load and link the objects specified on the command line, but do not execute
+// anything. Instead, attach a RuntimeDyldChecker instance and call it to
+// verify the correctness of the linked memory.
 static int linkAndVerify() {
 
   // Check for missing triple.