[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));
}
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 2df71a5..5cc8ef5 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -1190,16 +1190,16 @@
void RuntimeDyldImpl::finalizeAsync(
std::unique_ptr<RuntimeDyldImpl> This,
- unique_function<void(Error)> OnEmitted,
- std::unique_ptr<MemoryBuffer> UnderlyingBuffer) {
+ unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
+ OnEmitted,
+ object::OwningBinary<object::ObjectFile> O) {
auto SharedThis = std::shared_ptr<RuntimeDyldImpl>(std::move(This));
auto PostResolveContinuation =
- [SharedThis, OnEmitted = std::move(OnEmitted),
- UnderlyingBuffer = std::move(UnderlyingBuffer)](
+ [SharedThis, OnEmitted = std::move(OnEmitted), O = std::move(O)](
Expected<JITSymbolResolver::LookupResult> Result) mutable {
if (!Result) {
- OnEmitted(Result.takeError());
+ OnEmitted(std::move(O), Result.takeError());
return;
}
@@ -1213,10 +1213,11 @@
SharedThis->registerEHFrames();
std::string ErrMsg;
if (SharedThis->MemMgr.finalizeMemory(&ErrMsg))
- OnEmitted(make_error<StringError>(std::move(ErrMsg),
+ OnEmitted(std::move(O),
+ make_error<StringError>(std::move(ErrMsg),
inconvertibleErrorCode()));
else
- OnEmitted(Error::success());
+ OnEmitted(std::move(O), Error::success());
};
JITSymbolResolver::LookupSet Symbols;
@@ -1403,32 +1404,35 @@
// FIXME: Kill this with fire once we have a new JIT linker: this is only here
// so that we can re-use RuntimeDyld's implementation without twisting the
// interface any further for ORC's purposes.
-void jitLinkForORC(object::ObjectFile &Obj,
- std::unique_ptr<MemoryBuffer> UnderlyingBuffer,
- RuntimeDyld::MemoryManager &MemMgr,
- JITSymbolResolver &Resolver, bool ProcessAllSections,
- unique_function<Error(
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObj,
- std::map<StringRef, JITEvaluatedSymbol>)>
- OnLoaded,
- unique_function<void(Error)> OnEmitted) {
+void jitLinkForORC(
+ object::OwningBinary<object::ObjectFile> O,
+ RuntimeDyld::MemoryManager &MemMgr, JITSymbolResolver &Resolver,
+ bool ProcessAllSections,
+ unique_function<
+ Error(const object::ObjectFile &Obj,
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObj,
+ std::map<StringRef, JITEvaluatedSymbol>)>
+ OnLoaded,
+ unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
+ OnEmitted) {
RuntimeDyld RTDyld(MemMgr, Resolver);
RTDyld.setProcessAllSections(ProcessAllSections);
- auto Info = RTDyld.loadObject(Obj);
+ auto Info = RTDyld.loadObject(*O.getBinary());
if (RTDyld.hasError()) {
- OnEmitted(make_error<StringError>(RTDyld.getErrorString(),
- inconvertibleErrorCode()));
+ OnEmitted(std::move(O), make_error<StringError>(RTDyld.getErrorString(),
+ inconvertibleErrorCode()));
return;
}
- if (auto Err = OnLoaded(std::move(Info), RTDyld.getSymbolTable()))
- OnEmitted(std::move(Err));
+ if (auto Err =
+ OnLoaded(*O.getBinary(), std::move(Info), RTDyld.getSymbolTable()))
+ OnEmitted(std::move(O), std::move(Err));
RuntimeDyldImpl::finalizeAsync(std::move(RTDyld.Dyld), std::move(OnEmitted),
- std::move(UnderlyingBuffer));
+ std::move(O));
}
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index 3505dd7..d1d2e43 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -549,9 +549,11 @@
void resolveLocalRelocations();
- static void finalizeAsync(std::unique_ptr<RuntimeDyldImpl> This,
- unique_function<void(Error)> OnEmitted,
- std::unique_ptr<MemoryBuffer> UnderlyingBuffer);
+ static void finalizeAsync(
+ std::unique_ptr<RuntimeDyldImpl> This,
+ unique_function<void(object::OwningBinary<object::ObjectFile>, Error)>
+ OnEmitted,
+ object::OwningBinary<object::ObjectFile> O);
void reassignSectionAddress(unsigned SectionID, uint64_t Addr);