[compiler-rt] [llvm] [ORC][Runtime] Add `dlupdate` for elf (PR #110406)

via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 28 22:23:35 PDT 2024


https://github.com/SahilPatidar created https://github.com/llvm/llvm-project/pull/110406

With the help of @lhames, This pull request introduces the dlupdate function in the ORC runtime. dlupdate enables incremental execution of new initializers introduced in the REPL environment. Unlike traditional dlopen, which manages initializers, code mapping, and library reference counts, dlupdate focuses exclusively on running new initializers.

>From 64fd4b9dc3909ff96052af1127903d192d04f483 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Sat, 28 Sep 2024 17:46:35 +0530
Subject: [PATCH 1/2] Add `dlupdate` for elf

---
 compiler-rt/lib/orc/dlfcn_wrapper.cpp   |  2 +-
 compiler-rt/lib/orc/elfnix_platform.cpp | 62 +++++++++++++++++++++++++
 compiler-rt/lib/orc/elfnix_platform.h   |  1 +
 llvm/lib/ExecutionEngine/Orc/LLJIT.cpp  | 10 ++--
 4 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/orc/dlfcn_wrapper.cpp b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
index bbbc79f607f270..744268be68a584 100644
--- a/compiler-rt/lib/orc/dlfcn_wrapper.cpp
+++ b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
@@ -42,7 +42,7 @@ __orc_rt_jit_dlopen_wrapper(const char *ArgData, size_t ArgSize) {
       .release();
 }
 
-#ifdef __APPLE__
+#ifndef _WIN32
 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
 __orc_rt_jit_dlupdate_wrapper(const char *ArgData, size_t ArgSize) {
   return WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::handle(
diff --git a/compiler-rt/lib/orc/elfnix_platform.cpp b/compiler-rt/lib/orc/elfnix_platform.cpp
index e0813a40f1e3a5..ee57e35edf73fb 100644
--- a/compiler-rt/lib/orc/elfnix_platform.cpp
+++ b/compiler-rt/lib/orc/elfnix_platform.cpp
@@ -104,6 +104,7 @@ class ELFNixPlatformRuntimeState {
 
   const char *dlerror();
   void *dlopen(std::string_view Name, int Mode);
+  int dlupdate(void *DSOHandle, int Mode);
   int dlclose(void *DSOHandle);
   void *dlsym(void *DSOHandle, std::string_view Symbol);
 
@@ -135,6 +136,10 @@ class ELFNixPlatformRuntimeState {
   Error dlopenInitialize(std::unique_lock<std::recursive_mutex> &JDStatesLock,
                          PerJITDylibState &JDS,
                          ELFNixJITDylibDepInfoMap &DepInfo);
+  Error dlupdateImpl(void *DSOHandle, int Mode);
+  Error dlupdateFull(std::unique_lock<std::recursive_mutex> &JDStatesLock,
+                     PerJITDylibState &JDS);
+
   Error dlcloseImpl(void *DSOHandle);
   Error dlcloseInitialize(std::unique_lock<std::recursive_mutex> &JDStatesLock,
                           PerJITDylibState &JDS);
@@ -308,6 +313,15 @@ void *ELFNixPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {
   }
 }
 
+int ELFNixPlatformRuntimeState::dlupdate(void *DSOHandle, int Mode) {
+  if (auto Err = dlupdateImpl(DSOHandle, Mode)) {
+    // FIXME: Make dlerror thread safe.
+    DLFcnError = toString(std::move(Err));
+    return -1;
+  }
+  return 0;
+}
+
 int ELFNixPlatformRuntimeState::dlclose(void *DSOHandle) {
   if (auto Err = dlcloseImpl(DSOHandle)) {
     DLFcnError = toString(std::move(Err));
@@ -522,6 +536,50 @@ Error ELFNixPlatformRuntimeState::dlopenInitialize(
   return Error::success();
 }
 
+Error ELFNixPlatformRuntimeState::dlupdateImpl(void *DSOHandle, int Mode) {
+  std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);
+
+  // Try to find JITDylib state by name.
+  auto *JDS = getJITDylibStateByHeaderAddr(DSOHandle);
+
+  if (!JDS) {
+    std::ostringstream ErrStream;
+    ErrStream << "No registered JITDylib for " << DSOHandle;
+    return make_error<StringError>(ErrStream.str());
+  }
+
+  if (!JDS->referenced())
+    return make_error<StringError>("Dylib must be referenced");
+
+  if (auto Err = dlupdateFull(Lock, *JDS))
+    return Err;
+
+  return Error::success();
+}
+
+Error ELFNixPlatformRuntimeState::dlupdateFull(
+    std::unique_lock<std::recursive_mutex> &JDStatesLock,
+    PerJITDylibState &JDS) {
+  // Call back to the JIT to push the initializers.
+  Expected<ELFNixJITDylibDepInfoMap> DepInfo((ELFNixJITDylibDepInfoMap()));
+  // Unlock so that we can accept the initializer update.
+  JDStatesLock.unlock();
+  if (auto Err = WrapperFunction<SPSExpected<SPSELFNixJITDylibDepInfoMap>(
+          SPSExecutorAddr)>::
+          call(JITDispatch(&__orc_rt_elfnix_push_initializers_tag), DepInfo,
+               ExecutorAddr::fromPtr(JDS.Header)))
+    return Err;
+  JDStatesLock.lock();
+
+  if (!DepInfo)
+    return DepInfo.takeError();
+
+  if (auto Err = runInits(JDStatesLock, JDS))
+    return Err;
+
+  return Error::success();
+}
+
 Error ELFNixPlatformRuntimeState::dlcloseImpl(void *DSOHandle) {
 
   std::unique_lock<std::recursive_mutex> Lock(JDStatesMutex);
@@ -764,6 +822,10 @@ void *__orc_rt_elfnix_jit_dlopen(const char *path, int mode) {
   return ELFNixPlatformRuntimeState::get().dlopen(path, mode);
 }
 
+int __orc_rt_elfnix_jit_dlupdate(void *dso_handle, int mode) {
+  return ELFNixPlatformRuntimeState::get().dlupdate(dso_handle, mode);
+}
+
 int __orc_rt_elfnix_jit_dlclose(void *dso_handle) {
   return ELFNixPlatformRuntimeState::get().dlclose(dso_handle);
 }
diff --git a/compiler-rt/lib/orc/elfnix_platform.h b/compiler-rt/lib/orc/elfnix_platform.h
index 5ecbdf0cb9c86f..0e72cc865aecc2 100644
--- a/compiler-rt/lib/orc/elfnix_platform.h
+++ b/compiler-rt/lib/orc/elfnix_platform.h
@@ -25,6 +25,7 @@ ORC_RT_INTERFACE void __orc_rt_elfnix_cxa_finalize(void *dso_handle);
 // dlfcn functions.
 ORC_RT_INTERFACE const char *__orc_rt_elfnix_jit_dlerror();
 ORC_RT_INTERFACE void *__orc_rt_elfnix_jit_dlopen(const char *path, int mode);
+ORC_RT_INTERFACE int __orc_rt_elfnix_jit_dlupdate(void *dso_handle, int mode);
 ORC_RT_INTERFACE int __orc_rt_elfnix_jit_dlclose(void *dso_handle);
 ORC_RT_INTERFACE void *__orc_rt_elfnix_jit_dlsym(void *dso_handle,
                                                  const char *symbol);
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 19b3f3d6ea0380..8abc46b2a88333 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -615,7 +615,9 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
       [](const JITDylibSearchOrder &SO) { return SO; });
   StringRef WrapperToCall = "__orc_rt_jit_dlopen_wrapper";
   bool dlupdate = false;
-  if (ES.getTargetTriple().isOSBinFormatMachO()) {
+  const Triple &TT = ES.getTargetTriple();
+  if (TT.isOSBinFormatMachO() ||
+      TT.isOSBinFormatELF()) {
     if (InitializedDylib.contains(&JD)) {
       WrapperToCall = "__orc_rt_jit_dlupdate_wrapper";
       dlupdate = true;
@@ -630,12 +632,10 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
       auto E = ES.callSPSWrapper<SPSDLUpdateSig>(WrapperAddr->getAddress(),
                                                  result, DSOHandles[&JD],
                                                  int32_t(ORC_RT_RTLD_LAZY));
-      if (E)
-        return E;
-      else if (result)
+      if (result)
         return make_error<StringError>("dlupdate failed",
                                        inconvertibleErrorCode());
-      return Error::success();
+      return E;
     }
     return ES.callSPSWrapper<SPSDLOpenSig>(WrapperAddr->getAddress(),
                                            DSOHandles[&JD], JD.getName(),

>From 52d66d8cf91fc880dc612013147a652957997051 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Sun, 29 Sep 2024 10:52:05 +0530
Subject: [PATCH 2/2] Update error message

---
 compiler-rt/lib/orc/elfnix_platform.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/lib/orc/elfnix_platform.cpp b/compiler-rt/lib/orc/elfnix_platform.cpp
index ee57e35edf73fb..0c2c6ec32d2303 100644
--- a/compiler-rt/lib/orc/elfnix_platform.cpp
+++ b/compiler-rt/lib/orc/elfnix_platform.cpp
@@ -549,7 +549,7 @@ Error ELFNixPlatformRuntimeState::dlupdateImpl(void *DSOHandle, int Mode) {
   }
 
   if (!JDS->referenced())
-    return make_error<StringError>("Dylib must be referenced");
+    return make_error<StringError>("dlupdate failed, JITDylib must be open.");
 
   if (auto Err = dlupdateFull(Lock, *JDS))
     return Err;



More information about the llvm-commits mailing list