diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index e4f276d0fad..4dca870bec7 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -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; } diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index fd9f338669f..0b6b75be48b 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -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 diff --git a/lib/ExecutionEngine/MCJIT/MCJIT.h b/lib/ExecutionEngine/MCJIT/MCJIT.h index 16a9f3710b7..066ecebaa25 100644 --- a/lib/ExecutionEngine/MCJIT/MCJIT.h +++ b/lib/ExecutionEngine/MCJIT/MCJIT.h @@ -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. diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 5d6a2c0f123..310b206a067 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -161,25 +161,22 @@ ObjectImage* RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { 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(RTDyldMemoryManager *mm) { // permissions are applied. Dyld = 0; MM = mm; + ProcessAllSections = false; } RuntimeDyld::~RuntimeDyld() { delete Dyld; } +static std::unique_ptr createRuntimeDyldELF( + RTDyldMemoryManager *MM, + bool ProcessAllSections) { + std::unique_ptr Dyld(new RuntimeDyldELF(MM)); + Dyld->setProcessAllSections(ProcessAllSections); + return Dyld; +} + +static std::unique_ptr createRuntimeDyldMachO( + RTDyldMemoryManager *MM, + bool ProcessAllSections) { + std::unique_ptr Dyld(new RuntimeDyldMachO(MM)); + Dyld->setProcessAllSections(ProcessAllSections); + return Dyld; +} + ObjectImage *RuntimeDyld::loadObject(ObjectFile *InputObject) { std::unique_ptr 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(ObjectBuffer *InputBuffer) { 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(ObjectBuffer *InputBuffer) { 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: diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 8fd55920f2e..0b7de17a6e9 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -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) {