summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h15
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyld.h14
-rw-r--r--lib/ExecutionEngine/MCJIT/MCJIT.h4
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp46
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h11
5 files changed, 73 insertions, 17 deletions
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index e4f276d0fa..4dca870bec 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 fd9f338669..0b6b75be48 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 16a9f3710b..066ecebaa2 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 5d6a2c0f12..310b206a06 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<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(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 8fd55920f2..0b7de17a6e 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) {