[llvm] r204398 - Add an option to MCJIT to have it forward all sections to the

Lang Hames lhames at gmail.com
Thu Mar 20 14:06:46 PDT 2014


Author: lhames
Date: Thu Mar 20 16:06:46 2014
New Revision: 204398

URL: http://llvm.org/viewvc/llvm-project?rev=204398&view=rev
Log:
Add an option to MCJIT to have it forward all sections to the
RTDyldMemoryManager, regardless of whether it thinks they're "required for
execution".

Currently, RuntimeDyld only passes sections that are "required for execution"
to the RTDyldMemoryManager, and takes "required for execution" to mean exactly
"contains symbols or relocations". There are two problems with this:
(1) It can drop sections with anonymous data that is referenced by code.
(2) It leaves the JIT client no way to inspect interesting sections that aren't
    actually required to run the program (e.g dwarf sections).

A test case is still in the works.

Future work: We may want to replace this with a generic section filtering
mechanism, but that will require more consideration. For now, this flag at least
allows clients to volunteer to do the filtering themselves.

Fixes <rdar://problem/15177691>.


Modified:
    llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h
    llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h
    llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
    llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h

Modified: llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h?rev=204398&r1=204397&r2=204398&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h Thu Mar 20 16:06:46 2014
@@ -462,6 +462,21 @@ public:
     llvm_unreachable("No support for an object cache");
   }
 
+  /// setProcessAllSections (MCJIT Only): By default, only sections that are
+  /// "required for execution" are passed to the RTDyldMemoryManager, and other
+  /// sections are discarded. Passing 'true' to this method will cause
+  /// RuntimeDyld to pass all sections to its RTDyldMemoryManager regardless
+  /// of whether they are "required to execute" in the usual sense.
+  ///
+  /// Rationale: Some MCJIT clients want to be able to inspect metadata
+  /// sections (e.g. Dwarf, Stack-maps) to enable functionality or analyze
+  /// performance. Passing these sections to the memory manager allows the
+  /// client to make policy about the relevant sections, rather than having
+  /// MCJIT do it.
+  virtual void setProcessAllSections(bool ProcessAllSections) {
+    llvm_unreachable("No support for ProcessAllSections option");
+  }
+
   /// Return the target machine (if available).
   virtual TargetMachine *getTargetMachine() { return NULL; }
 

Modified: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h?rev=204398&r1=204397&r2=204398&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h Thu Mar 20 16:06:46 2014
@@ -36,6 +36,7 @@ class RuntimeDyld {
   // interface.
   RuntimeDyldImpl *Dyld;
   RTDyldMemoryManager *MM;
+  bool ProcessAllSections;
 protected:
   // Change the address associated with a section when resolving relocations.
   // Any relocations already associated with the symbol will be re-resolved.
@@ -84,6 +85,19 @@ public:
   void deregisterEHFrames();
 
   StringRef getErrorString();
+
+  /// By default, only sections that are "required for execution" are passed to
+  /// the RTDyldMemoryManager, and other sections are discarded. Passing 'true'
+  /// to this method will cause RuntimeDyld to pass all sections to its
+  /// memory manager regardless of whether they are "required to execute" in the
+  /// usual sense. This is useful for inspecting metadata sections that may not
+  /// contain relocations, E.g. Debug info, stackmaps.
+  ///
+  /// Must be called before the first object file is loaded.
+  void setProcessAllSections(bool ProcessAllSections) {
+    assert(!Dyld && "setProcessAllSections must be called before loadObject.");
+    this->ProcessAllSections = ProcessAllSections;
+  }
 };
 
 } // end namespace llvm

Modified: llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h?rev=204398&r1=204397&r2=204398&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h (original)
+++ llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.h Thu Mar 20 16:06:46 2014
@@ -251,6 +251,10 @@ public:
   /// Sets the object manager that MCJIT should use to avoid compilation.
   void setObjectCache(ObjectCache *manager) override;
 
+  void setProcessAllSections(bool ProcessAllSections) override {
+    Dyld.setProcessAllSections(ProcessAllSections);
+  }
+
   void generateCodeForModule(Module *M) override;
 
   /// finalizeObject - ensure the module is fully processed and is usable.

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=204398&r1=204397&r2=204398&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Thu Mar 20 16:06:46 2014
@@ -161,25 +161,22 @@ ObjectImage* RuntimeDyldImpl::loadObject
   DEBUG(dbgs() << "Parse relocations:\n");
   for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections();
        SI != SE; ++SI) {
-    bool IsFirstRelocation = true;
     unsigned SectionID = 0;
     StubMap Stubs;
     section_iterator RelocatedSection = SI->getRelocatedSection();
 
-    for (const RelocationRef &Reloc : SI->relocations()) {
-      // If it's the first relocation in this section, find its SectionID
-      if (IsFirstRelocation) {
-        bool IsCode = false;
-        Check(RelocatedSection->isText(IsCode));
-        SectionID =
-            findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections);
-        DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
-        IsFirstRelocation = false;
-      }
+    if ((SI->relocation_begin() != SI->relocation_end()) ||
+        ProcessAllSections) {
+      bool IsCode = false;
+      Check(RelocatedSection->isText(IsCode));
+      SectionID =
+        findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections);
+      DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
+    }
 
+    for (const RelocationRef &Reloc : SI->relocations())
       processRelocationRef(SectionID, Reloc, *Obj, LocalSections, LocalSymbols,
                            Stubs);
-    }
   }
 
   // Give the subclasses a chance to tie-up any loose ends.
@@ -665,23 +662,40 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryMan
   // permissions are applied.
   Dyld = 0;
   MM = mm;
+  ProcessAllSections = false;
 }
 
 RuntimeDyld::~RuntimeDyld() {
   delete Dyld;
 }
 
+static std::unique_ptr<RuntimeDyldELF> createRuntimeDyldELF(
+                                                   RTDyldMemoryManager *MM,
+                                                   bool ProcessAllSections) {
+  std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM));
+  Dyld->setProcessAllSections(ProcessAllSections);
+  return Dyld;
+}
+
+static std::unique_ptr<RuntimeDyldMachO> createRuntimeDyldMachO(
+                                                   RTDyldMemoryManager *MM,
+                                                   bool ProcessAllSections) {
+  std::unique_ptr<RuntimeDyldMachO> Dyld(new RuntimeDyldMachO(MM));
+  Dyld->setProcessAllSections(ProcessAllSections);
+  return Dyld;
+}
+
 ObjectImage *RuntimeDyld::loadObject(ObjectFile *InputObject) {
   std::unique_ptr<ObjectImage> InputImage;
 
   if (InputObject->isELF()) {
     InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(InputObject));
     if (!Dyld)
-      Dyld = new RuntimeDyldELF(MM);
+      Dyld = createRuntimeDyldELF(MM, ProcessAllSections).release();
   } else if (InputObject->isMachO()) {
     InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(InputObject));
     if (!Dyld)
-      Dyld = new RuntimeDyldMachO(MM);
+      Dyld = createRuntimeDyldMachO(MM, ProcessAllSections).release();
   } else
     report_fatal_error("Incompatible object format!");
 
@@ -704,7 +718,7 @@ ObjectImage *RuntimeDyld::loadObject(Obj
   case sys::fs::file_magic::elf_core:
     InputImage.reset(RuntimeDyldELF::createObjectImage(InputBuffer));
     if (!Dyld)
-      Dyld = new RuntimeDyldELF(MM);
+      Dyld = createRuntimeDyldELF(MM, ProcessAllSections).release();
     break;
   case sys::fs::file_magic::macho_object:
   case sys::fs::file_magic::macho_executable:
@@ -718,7 +732,7 @@ ObjectImage *RuntimeDyld::loadObject(Obj
   case sys::fs::file_magic::macho_dsym_companion:
     InputImage.reset(RuntimeDyldMachO::createObjectImage(InputBuffer));
     if (!Dyld)
-      Dyld = new RuntimeDyldMachO(MM);
+      Dyld = createRuntimeDyldMachO(MM, ProcessAllSections).release();
     break;
   case sys::fs::file_magic::unknown:
   case sys::fs::file_magic::bitcode:

Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h?rev=204398&r1=204397&r2=204398&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h (original)
+++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h Thu Mar 20 16:06:46 2014
@@ -187,6 +187,10 @@ protected:
   Triple::ArchType Arch;
   bool IsTargetLittleEndian;
 
+  // True if all sections should be passed to the memory manager, false if only
+  // sections containing relocations should be. Defaults to 'false'.
+  bool ProcessAllSections;
+
   // This mutex prevents simultaneously loading objects from two different
   // threads.  This keeps us from having to protect individual data structures
   // and guarantees that section allocation requests to the memory manager
@@ -320,10 +324,15 @@ protected:
   unsigned computeSectionStubBufSize(ObjectImage &Obj, const SectionRef &Section); 
 
 public:
-  RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
+  RuntimeDyldImpl(RTDyldMemoryManager *mm)
+    : MemMgr(mm), ProcessAllSections(false), HasError(false) {}
 
   virtual ~RuntimeDyldImpl();
 
+  void setProcessAllSections(bool ProcessAllSections) {
+    this->ProcessAllSections = ProcessAllSections;
+  }
+
   ObjectImage* loadObject(ObjectImage* InputObject);
 
   void *getSymbolAddress(StringRef Name) {





More information about the llvm-commits mailing list