Add a method to indicate section address re-assignment is finished.
authorAndrew Kaylor <andrew.kaylor@intel.com>
Mon, 5 Nov 2012 20:57:16 +0000 (20:57 +0000)
committerAndrew Kaylor <andrew.kaylor@intel.com>
Mon, 5 Nov 2012 20:57:16 +0000 (20:57 +0000)
Prior to this patch RuntimeDyld attempted to re-apply relocations every time reassignSectionAddress was called (via MCJIT::mapSectionAddress).  In addition to being inefficient and redundant, this led to a problem when a section was temporarily moved too far away from another section with a relative relocation referencing the section being moved.  To fix this, I'm adding a new method (finalizeObject) which the client can call to indicate that it is finished rearranging section addresses so the relocations can safely be applied.

llvm-svn: 167400

llvm/include/llvm/ExecutionEngine/ExecutionEngine.h
llvm/lib/ExecutionEngine/MCJIT/MCJIT.cpp
llvm/lib/ExecutionEngine/MCJIT/MCJIT.h
llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
llvm/tools/lli/lli.cpp

index 04756ca601f1770c7288bebcec809d6b5e7e3870..8073d8f92c512655a735192ff538ca7f807e2ab7 100644 (file)
@@ -249,6 +249,13 @@ public:
                      "EE!");
   }
 
+  // finalizeObject - This method should be called after sections within an
+  // object have been relocated using mapSectionAddress.  When this method is
+  // called the MCJIT execution engine will reapply relocations for a loaded
+  // object.  This method has no effect for the legacy JIT engine or the
+  // interpeter.
+  virtual void finalizeObject() {}
+
   /// runStaticConstructorsDestructors - This method is used to execute all of
   /// the static constructors or destructors for a program.
   ///
index a0ad985145b0aa70e855267f57c2faf2c243a2d8..71d713468b67ca26d9795cfd9dad6cc3d7e7a0a6 100644 (file)
@@ -111,6 +111,21 @@ void MCJIT::emitObject(Module *m) {
   isCompiled = true;
 }
 
+// FIXME: Add a parameter to identify which object is being finalized when
+// MCJIT supports multiple modules.
+void MCJIT::finalizeObject() {
+  // If the module hasn't been compiled, just do that.
+  if (!isCompiled) {
+    // If the call to Dyld.resolveRelocations() is removed from emitObject()
+    // we'll need to do that here.
+    emitObject(M);
+    return;
+  }
+
+  // Resolve any relocations.
+  Dyld.resolveRelocations();
+}
+
 void *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
   report_fatal_error("not yet implemented");
 }
index b9ff06e701f0fe2b1dfba19270f52eafafec633f..6cffcc5b82b675f29cdded58c68905ac5c16d7ea 100644 (file)
@@ -42,6 +42,8 @@ public:
   /// @name ExecutionEngine interface implementation
   /// @{
 
+  virtual void finalizeObject();
+
   virtual void *getPointerToBasicBlock(BasicBlock *BB);
 
   virtual void *getPointerToFunction(Function *F);
index 950b4208a9fb0f9a56d1805bf16aee3d4f0db8ef..f6dccb106d9bbe38e9b9e7bdbd0335c930ab727b 100644 (file)
@@ -36,7 +36,11 @@ void RuntimeDyldImpl::resolveRelocations() {
   // Just iterate over the sections we have and resolve all the relocations
   // in them. Gross overkill, but it gets the job done.
   for (int i = 0, e = Sections.size(); i != e; ++i) {
-    reassignSectionAddress(i, Sections[i].LoadAddress);
+    uint64_t Addr = Sections[i].LoadAddress;
+    DEBUG(dbgs() << "Resolving relocations Section #" << i
+            << "\t" << format("%p", (uint8_t *)Addr)
+            << "\n");
+    resolveRelocationList(Relocations[i], Addr);
   }
 }
 
@@ -387,17 +391,15 @@ void RuntimeDyldImpl::reassignSectionAddress(unsigned SectionID,
                                              uint64_t Addr) {
   // The address to use for relocation resolution is not
   // the address of the local section buffer. We must be doing
-  // a remote execution environment of some sort. Re-apply any
-  // relocations referencing this section with the given address.
+  // a remote execution environment of some sort. Relocations can't
+  // be applied until all the sections have been moved.  The client must
+  // trigger this with a call to MCJIT::finalize() or
+  // RuntimeDyld::resolveRelocations().
   //
   // Addr is a uint64_t because we can't assume the pointer width
   // of the target is the same as that of the host. Just use a generic
   // "big enough" type.
   Sections[SectionID].LoadAddress = Addr;
-  DEBUG(dbgs() << "Resolving relocations Section #" << SectionID
-          << "\t" << format("%p", (uint8_t *)Addr)
-          << "\n");
-  resolveRelocationList(Relocations[SectionID], Addr);
 }
 
 void RuntimeDyldImpl::resolveRelocationEntry(const RelocationEntry &RE,
index 9a27a4c94110a5d938194020447d1984c84b5881..d41a595de857132b06781d7a084e87dfb5192348 100644 (file)
@@ -475,6 +475,10 @@ void layoutRemoteTargetMemory(RemoteTarget *T, RecordingMemoryManager *JMM) {
                  << " to remote: " << format("%p", Addr) << "\n");
 
   }
+
+  // Trigger application of relocations
+  EE->finalizeObject();
+
   // Now load it all to the target.
   for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
     uint64_t Addr = RemoteAddr + Offsets[i].second;