[ORC] Re-apply 98f2bb44610, enable JITEventListeners in OrcV2, with fixes.
Updates the object buffer ownership scheme in jitLinkForOrc and related
functions: Ownership of both the object::ObjectFile and underlying
MemoryBuffer is passed into jitLinkForOrc and passed back to the onEmit
callback once linking is complete. This avoids the use-after-free errors
that were seen in 98f2bb44610.
diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
index f51bd9d..f660c42 100644
--- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp
@@ -81,8 +81,12 @@
RTDyldObjectLinkingLayer::~RTDyldObjectLinkingLayer() {
std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
- for (auto &MemMgr : MemMgrs)
+ for (auto &MemMgr : MemMgrs) {
+ for (auto *L : EventListeners)
+ L->notifyFreeingObject(
+ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(MemMgr.get())));
MemMgr->deregisterEHFrames();
+ }
}
void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R,
@@ -97,13 +101,7 @@
auto &ES = getExecutionSession();
- // Create a MemoryBufferRef backed MemoryBuffer (i.e. shallow) copy of the
- // the underlying buffer to pass into RuntimeDyld. This allows us to hold
- // ownership of the real underlying buffer and return it to the user once
- // the object has been emitted.
- auto ObjBuffer = MemoryBuffer::getMemBuffer(O->getMemBufferRef(), false);
-
- auto Obj = object::ObjectFile::createObjectFile(*ObjBuffer);
+ auto Obj = object::ObjectFile::createObjectFile(*O);
if (!Obj) {
getExecutionSession().reportError(Obj.takeError());
@@ -154,20 +152,39 @@
JITDylibSearchOrderResolver Resolver(*SharedR);
jitLinkForORC(
- **Obj, std::move(O), *MemMgr, Resolver, ProcessAllSections,
- [this, K, SharedR, &Obj, InternalSymbols](
+ object::OwningBinary<object::ObjectFile>(std::move(*Obj), std::move(O)),
+ *MemMgr, Resolver, ProcessAllSections,
+ [this, K, SharedR, MemMgr, InternalSymbols](
+ const object::ObjectFile &Obj,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
std::map<StringRef, JITEvaluatedSymbol> ResolvedSymbols) {
- return onObjLoad(K, *SharedR, **Obj, std::move(LoadedObjInfo),
+ return onObjLoad(K, *SharedR, Obj, MemMgr, std::move(LoadedObjInfo),
ResolvedSymbols, *InternalSymbols);
},
- [this, K, SharedR, O = std::move(O)](Error Err) mutable {
- onObjEmit(K, std::move(O), *SharedR, std::move(Err));
+ [this, K, SharedR, MemMgr](object::OwningBinary<object::ObjectFile> Obj,
+ Error Err) mutable {
+ onObjEmit(K, *SharedR, std::move(Obj), MemMgr, std::move(Err));
});
}
+void RTDyldObjectLinkingLayer::registerJITEventListener(JITEventListener &L) {
+ std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
+ assert(llvm::none_of(EventListeners,
+ [&](JITEventListener *O) { return O == &L; }) &&
+ "Listener has already been registered");
+ EventListeners.push_back(&L);
+}
+
+void RTDyldObjectLinkingLayer::unregisterJITEventListener(JITEventListener &L) {
+ std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
+ auto I = llvm::find(EventListeners, &L);
+ assert(I != EventListeners.end() && "Listener not registered");
+ EventListeners.erase(I);
+}
+
Error RTDyldObjectLinkingLayer::onObjLoad(
- VModuleKey K, MaterializationResponsibility &R, object::ObjectFile &Obj,
+ VModuleKey K, MaterializationResponsibility &R,
+ const object::ObjectFile &Obj, RuntimeDyld::MemoryManager *MemMgr,
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo,
std::map<StringRef, JITEvaluatedSymbol> Resolved,
std::set<StringRef> &InternalSymbols) {
@@ -252,12 +269,17 @@
if (NotifyLoaded)
NotifyLoaded(K, Obj, *LoadedObjInfo);
+ std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
+ assert(!LoadedObjInfos.count(MemMgr) && "Duplicate loaded info for MemMgr");
+ LoadedObjInfos[MemMgr] = std::move(LoadedObjInfo);
+
return Error::success();
}
void RTDyldObjectLinkingLayer::onObjEmit(
- VModuleKey K, std::unique_ptr<MemoryBuffer> ObjBuffer,
- MaterializationResponsibility &R, Error Err) {
+ VModuleKey K, MaterializationResponsibility &R,
+ object::OwningBinary<object::ObjectFile> O,
+ RuntimeDyld::MemoryManager *MemMgr, Error Err) {
if (Err) {
getExecutionSession().reportError(std::move(Err));
R.failMaterialization();
@@ -270,6 +292,22 @@
return;
}
+ std::unique_ptr<object::ObjectFile> Obj;
+ std::unique_ptr<MemoryBuffer> ObjBuffer;
+ std::tie(Obj, ObjBuffer) = O.takeBinary();
+
+ // Run EventListener notifyLoaded callbacks.
+ {
+ std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
+ auto LOIItr = LoadedObjInfos.find(MemMgr);
+ assert(LOIItr != LoadedObjInfos.end() && "LoadedObjInfo missing");
+ for (auto *L : EventListeners)
+ L->notifyObjectLoaded(
+ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(MemMgr)), *Obj,
+ *LOIItr->second);
+ LoadedObjInfos.erase(MemMgr);
+ }
+
if (NotifyEmitted)
NotifyEmitted(K, std::move(ObjBuffer));
}