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

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 26 23:26:24 PDT 2024


https://github.com/SahilPatidar updated https://github.com/llvm/llvm-project/pull/97441

>From 93a7cd44a7c25a33679af0fd181e3fca414b6186 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Sat, 29 Jun 2024 16:53:53 +0530
Subject: [PATCH 1/6] [ORC][Runtime] Add `dlupdate` for MachO

---
 compiler-rt/lib/orc/dlfcn_wrapper.cpp         |  12 ++
 compiler-rt/lib/orc/macho_platform.cpp        | 152 ++++++++++++++++++
 compiler-rt/lib/orc/macho_platform.h          |   1 +
 llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h |   2 +
 llvm/lib/ExecutionEngine/Orc/LLJIT.cpp        |   9 +-
 .../lib/ExecutionEngine/Orc/MachOPlatform.cpp |   1 +
 6 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/compiler-rt/lib/orc/dlfcn_wrapper.cpp b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
index ece63da2cb48e..b2c4857e31392 100644
--- a/compiler-rt/lib/orc/dlfcn_wrapper.cpp
+++ b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
@@ -20,6 +20,7 @@ using namespace __orc_rt;
 
 extern "C" const char *__orc_rt_jit_dlerror();
 extern "C" void *__orc_rt_jit_dlopen(const char *path, int mode);
+extern "C" void *__orc_rt_jit_dlupdate(const char *path, int mode);
 extern "C" int __orc_rt_jit_dlclose(void *dso_handle);
 
 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
@@ -41,6 +42,17 @@ __orc_rt_jit_dlopen_wrapper(const char *ArgData, size_t ArgSize) {
       .release();
 }
 
+ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
+__orc_rt_jit_dlupdate_wrapper(const char *ArgData, size_t ArgSize) {
+  return WrapperFunction<SPSExecutorAddr(SPSString, int32_t)>::handle(
+             ArgData, ArgSize,
+             [](const std::string &Path, int32_t mode) {
+               return ExecutorAddr::fromPtr(
+                   __orc_rt_jit_dlupdate(Path.c_str(), mode));
+             })
+      .release();
+}
+
 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
 __orc_rt_jit_dlclose_wrapper(const char *ArgData, size_t ArgSize) {
   return WrapperFunction<int32_t(SPSExecutorAddr)>::handle(
diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index 340846f5f9001..9233b33e6a5ec 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -330,6 +330,7 @@ class MachOPlatformRuntimeState {
 
   const char *dlerror();
   void *dlopen(std::string_view Name, int Mode);
+  void *dlupdate(std::string_view Name, int Mode);
   int dlclose(void *DSOHandle);
   void *dlsym(void *DSOHandle, const char *Symbol);
 
@@ -377,6 +378,12 @@ class MachOPlatformRuntimeState {
   Error dlopenInitialize(std::unique_lock<std::mutex> &JDStatesLock,
                          JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);
 
+  Expected<void *> dlupdateImpl(std::string_view Path, int Mode);
+  Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock,
+                   JITDylibState &JDS);
+  Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock,
+                         JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);
+
   Error dlcloseImpl(void *DSOHandle);
   Error dlcloseDeinitialize(std::unique_lock<std::mutex> &JDStatesLock,
                             JITDylibState &JDS);
@@ -786,6 +793,21 @@ void *MachOPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {
   }
 }
 
+void *MachOPlatformRuntimeState::dlupdate(std::string_view Path, int Mode) {
+  ORC_RT_DEBUG({
+    std::string S(Path.data(), Path.size());
+    printdbg("MachOPlatform::dlupdate(\"%s\")\n", S.c_str());
+  });
+  std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex);
+  if (auto H = dlupdateImpl(Path, Mode))
+    return *H;
+  else {
+    // FIXME: Make dlerror thread safe.
+    DLFcnError = toString(H.takeError());
+    return nullptr;
+  }
+}
+
 int MachOPlatformRuntimeState::dlclose(void *DSOHandle) {
   ORC_RT_DEBUG({
     auto *JDS = getJITDylibStateByHeader(DSOHandle);
@@ -1236,6 +1258,132 @@ Error MachOPlatformRuntimeState::dlopenInitialize(
   return Error::success();
 }
 
+Expected<void *> MachOPlatformRuntimeState::dlupdateImpl(std::string_view Path,
+                                                       int Mode) {
+  std::unique_lock<std::mutex> Lock(JDStatesMutex);
+
+  // Try to find JITDylib state by name.
+  auto *JDS = getJITDylibStateByName(Path);
+
+  if (!JDS)
+    return make_error<StringError>("No registered JTIDylib for path " +
+                                   std::string(Path.data(), Path.size()));
+
+  // If this JITDylib is unsealed, or this is the first dlopen then run
+  // full dlopen path (update deps, push and run initializers, update ref
+  // counts on all JITDylibs in the dep tree).
+  if (!JDS->referenced() || !JDS->Sealed) {
+    if (auto Err = dlupdateFull(Lock, *JDS))
+      return std::move(Err);
+  }
+
+  // Return the header address.
+  return JDS->Header;
+}
+
+Error MachOPlatformRuntimeState::dlupdateFull(
+    std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) {
+  // Call back to the JIT to push the initializers.
+  Expected<MachOJITDylibDepInfoMap> DepInfo((MachOJITDylibDepInfoMap()));
+  // Unlock so that we can accept the initializer update.
+  JDStatesLock.unlock();
+  if (auto Err = WrapperFunction<SPSExpected<SPSMachOJITDylibDepInfoMap>(
+          SPSExecutorAddr)>::call(&__orc_rt_macho_push_initializers_tag,
+                                  DepInfo, ExecutorAddr::fromPtr(JDS.Header)))
+    return Err;
+  JDStatesLock.lock();
+
+  if (!DepInfo)
+    return DepInfo.takeError();
+
+  if (auto Err = dlupdateInitialize(JDStatesLock, JDS, *DepInfo))
+    return Err;
+
+  if (!DepInfo->empty()) {
+    ORC_RT_DEBUG({
+      printdbg("Unrecognized dep-info key headers in dlupdate of %s\n",
+               JDS.Name.c_str());
+    });
+    std::ostringstream ErrStream;
+    ErrStream << "Encountered unrecognized dep-info key headers "
+                 "while processing dlupdate of "
+              << JDS.Name;
+    return make_error<StringError>(ErrStream.str());
+  }
+
+  return Error::success();
+}
+
+Error MachOPlatformRuntimeState::dlupdateInitialize(
+    std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS,
+    MachOJITDylibDepInfoMap &DepInfo) {
+  ORC_RT_DEBUG({
+    printdbg("MachOPlatformRuntimeState::dlupdateInitialize(\"%s\")\n",
+             JDS.Name.c_str());
+  });
+
+  // If the header is not present in the dep map then assume that we
+  // already processed it earlier in the dlopenInitialize traversal and
+  // return.
+  // TODO: Keep a visited set instead so that we can error out on missing
+  //       entries?
+  auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header));
+  if (I == DepInfo.end())
+    return Error::success();
+
+  auto DI = std::move(I->second);
+  DepInfo.erase(I);
+
+  // We don't need to re-initialize sealed JITDylibs that have already been
+  // initialized. Just check that their dep-map entry is empty as expected.
+  if (JDS.Sealed) {
+    if (!DI.DepHeaders.empty()) {
+      std::ostringstream ErrStream;
+      ErrStream << "Sealed JITDylib " << JDS.Header
+                << " already has registered dependencies";
+      return make_error<StringError>(ErrStream.str());
+    }
+    if (JDS.referenced())
+      return Error::success();
+  } else
+    JDS.Sealed = DI.Sealed;
+
+  // This is an unsealed or newly sealed JITDylib. Run initializers.
+  std::vector<JITDylibState *> OldDeps;
+  std::swap(JDS.Deps, OldDeps);
+  JDS.Deps.reserve(DI.DepHeaders.size());
+  for (auto DepHeaderAddr : DI.DepHeaders) {
+    auto *DepJDS = getJITDylibStateByHeader(DepHeaderAddr.toPtr<void *>());
+    if (!DepJDS) {
+      std::ostringstream ErrStream;
+      ErrStream << "Encountered unrecognized dep header "
+                << DepHeaderAddr.toPtr<void *>() << " while initializing "
+                << JDS.Name;
+      return make_error<StringError>(ErrStream.str());
+    }
+
+    if (auto Err = dlupdateInitialize(JDStatesLock, *DepJDS, DepInfo))
+      return Err;
+  }
+
+  // Initialize this JITDylib.
+  if (auto Err = registerObjCRegistrationObjects(JDS))
+    return Err;
+  if (auto Err = runModInits(JDStatesLock, JDS))
+    return Err;
+
+  // Decrement old deps.
+  // FIXME: We should probably continue and just report deinitialize errors
+  // here.
+  for (auto *DepJDS : OldDeps) {
+    if (!DepJDS->referenced())
+      if (auto Err = dlcloseDeinitialize(JDStatesLock, *DepJDS))
+        return Err;
+  }
+
+  return Error::success();
+}
+
 Error MachOPlatformRuntimeState::dlcloseImpl(void *DSOHandle) {
   std::unique_lock<std::mutex> Lock(JDStatesMutex);
 
@@ -1509,6 +1657,10 @@ void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
   return MachOPlatformRuntimeState::get().dlopen(path, mode);
 }
 
+void *__orc_rt_macho_jit_dlupdate(const char *path, int mode) {
+  return MachOPlatformRuntimeState::get().dlupdate(path, mode);
+}
+
 int __orc_rt_macho_jit_dlclose(void *dso_handle) {
   return MachOPlatformRuntimeState::get().dlclose(dso_handle);
 }
diff --git a/compiler-rt/lib/orc/macho_platform.h b/compiler-rt/lib/orc/macho_platform.h
index 3b2242ab27ce8..ae9c8b487262a 100644
--- a/compiler-rt/lib/orc/macho_platform.h
+++ b/compiler-rt/lib/orc/macho_platform.h
@@ -24,6 +24,7 @@ ORC_RT_INTERFACE void __orc_rt_macho_cxa_finalize(void *dso_handle);
 // dlfcn functions.
 ORC_RT_INTERFACE const char *__orc_rt_macho_jit_dlerror();
 ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlopen(const char *path, int mode);
+ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlupdate(const char *path, int mode);
 ORC_RT_INTERFACE int __orc_rt_macho_jit_dlclose(void *dso_handle);
 ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlsym(void *dso_handle,
                                                 const char *symbol);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
index 3a71ddc88ce95..b42f13bf3fca8 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -22,6 +22,7 @@
 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ThreadPool.h"
+#include "llvm/ADT/SmallSet.h"
 #include <variant>
 
 namespace llvm {
@@ -620,6 +621,7 @@ class ORCPlatformSupport : public LLJIT::PlatformSupport {
 private:
   orc::LLJIT &J;
   DenseMap<orc::JITDylib *, orc::ExecutorAddr> DSOHandles;
+  SmallPtrSet<JITDylib const *, 8> InitializedDylib;
 };
 
 } // End namespace orc
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 568b2ececaa09..56339cfa359b1 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -611,9 +611,16 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
   auto &ES = J.getExecutionSession();
   auto MainSearchOrder = J.getMainJITDylib().withLinkOrderDo(
       [](const JITDylibSearchOrder &SO) { return SO; });
+  StringRef WrapperToCall = "__orc_rt_jit_dlopen_wrapper";
+  if (ES.getTargetTriple().isOSBinFormatMachO()) {
+    if (InitializedDylib.contains(&JD))
+      WrapperToCall = "__orc_rt_jit_dlupdate_wrapper";
+    else
+      InitializedDylib.insert(&JD);
+  }
 
   if (auto WrapperAddr = ES.lookup(
-          MainSearchOrder, J.mangleAndIntern("__orc_rt_jit_dlopen_wrapper"))) {
+          MainSearchOrder, J.mangleAndIntern(WrapperToCall))) {
     return ES.callSPSWrapper<SPSDLOpenSig>(WrapperAddr->getAddress(),
                                            DSOHandles[&JD], JD.getName(),
                                            int32_t(ORC_RT_RTLD_LAZY));
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index b477a48af2906..80a75988b9112 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -425,6 +425,7 @@ MachOPlatform::standardRuntimeUtilityAliases() {
           {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
           {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
           {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
+          {"___orc_rt_jit_dlupdate", "___orc_rt_macho_jit_dlupdate"},
           {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
           {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
           {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};

>From 3d16e5c04c559d456dd70e13c4ab736c85d1e574 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Tue, 2 Jul 2024 17:02:20 +0530
Subject: [PATCH 2/6] Modify `dlupdate` to take `DSOHandle` instead of a path.

---
 compiler-rt/lib/orc/dlfcn_wrapper.cpp  |   8 +-
 compiler-rt/lib/orc/macho_platform.cpp | 103 +++++--------------------
 compiler-rt/lib/orc/macho_platform.h   |   2 +-
 llvm/lib/ExecutionEngine/Orc/LLJIT.cpp |  11 ++-
 4 files changed, 34 insertions(+), 90 deletions(-)

diff --git a/compiler-rt/lib/orc/dlfcn_wrapper.cpp b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
index b2c4857e31392..a6ed7545807c8 100644
--- a/compiler-rt/lib/orc/dlfcn_wrapper.cpp
+++ b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
@@ -20,7 +20,7 @@ using namespace __orc_rt;
 
 extern "C" const char *__orc_rt_jit_dlerror();
 extern "C" void *__orc_rt_jit_dlopen(const char *path, int mode);
-extern "C" void *__orc_rt_jit_dlupdate(const char *path, int mode);
+extern "C" void *__orc_rt_jit_dlupdate(void *dso_handle, int mode);
 extern "C" int __orc_rt_jit_dlclose(void *dso_handle);
 
 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
@@ -44,11 +44,11 @@ __orc_rt_jit_dlopen_wrapper(const char *ArgData, size_t ArgSize) {
 
 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
 __orc_rt_jit_dlupdate_wrapper(const char *ArgData, size_t ArgSize) {
-  return WrapperFunction<SPSExecutorAddr(SPSString, int32_t)>::handle(
+  return WrapperFunction<SPSExecutorAddr(SPSExecutorAddr, int32_t)>::handle(
              ArgData, ArgSize,
-             [](const std::string &Path, int32_t mode) {
+             [](ExecutorAddr &DSOHandle, int32_t mode) {
                return ExecutorAddr::fromPtr(
-                   __orc_rt_jit_dlupdate(Path.c_str(), mode));
+                   __orc_rt_jit_dlupdate(DSOHandle.toPtr<void *>(), mode));
              })
       .release();
 }
diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index 9233b33e6a5ec..353e2fa8ae313 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -330,7 +330,7 @@ class MachOPlatformRuntimeState {
 
   const char *dlerror();
   void *dlopen(std::string_view Name, int Mode);
-  void *dlupdate(std::string_view Name, int Mode);
+  void *dlupdate(void *DSOHandle, int Mode);
   int dlclose(void *DSOHandle);
   void *dlsym(void *DSOHandle, const char *Symbol);
 
@@ -378,7 +378,7 @@ class MachOPlatformRuntimeState {
   Error dlopenInitialize(std::unique_lock<std::mutex> &JDStatesLock,
                          JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);
 
-  Expected<void *> dlupdateImpl(std::string_view Path, int Mode);
+  Expected<void *> dlupdateImpl(void *DSOHandle, int Mode);
   Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock,
                    JITDylibState &JDS);
   Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock,
@@ -793,13 +793,13 @@ void *MachOPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {
   }
 }
 
-void *MachOPlatformRuntimeState::dlupdate(std::string_view Path, int Mode) {
+void *MachOPlatformRuntimeState::dlupdate(void *DSOHandle, int Mode) {
   ORC_RT_DEBUG({
-    std::string S(Path.data(), Path.size());
-    printdbg("MachOPlatform::dlupdate(\"%s\")\n", S.c_str());
+    std::string S;
+    printdbg("MachOPlatform::dlupdate(%p) (%s)\n", DSOHandle, S.c_str());
   });
   std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex);
-  if (auto H = dlupdateImpl(Path, Mode))
+  if (auto H = dlupdateImpl(DSOHandle, Mode))
     return *H;
   else {
     // FIXME: Make dlerror thread safe.
@@ -1258,21 +1258,23 @@ Error MachOPlatformRuntimeState::dlopenInitialize(
   return Error::success();
 }
 
-Expected<void *> MachOPlatformRuntimeState::dlupdateImpl(std::string_view Path,
+Expected<void *> MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle,
                                                        int Mode) {
   std::unique_lock<std::mutex> Lock(JDStatesMutex);
 
-  // Try to find JITDylib state by name.
-  auto *JDS = getJITDylibStateByName(Path);
+  // Try to find JITDylib state by DSOHandle.
+  auto *JDS = getJITDylibStateByHeader(DSOHandle);
 
-  if (!JDS)
-    return make_error<StringError>("No registered JTIDylib for path " +
-                                   std::string(Path.data(), Path.size()));
+  if (!JDS) {
+    std::ostringstream ErrStream;
+    ErrStream << "No registered JITDylib for " << DSOHandle;
+    return make_error<StringError>(ErrStream.str());
+  }
 
-  // If this JITDylib is unsealed, or this is the first dlopen then run
-  // full dlopen path (update deps, push and run initializers, update ref
-  // counts on all JITDylibs in the dep tree).
-  if (!JDS->referenced() || !JDS->Sealed) {
+  if (!JDS->referenced())
+    return make_error<StringError>("dlupdate failed, JITDylib must be open.");
+
+  if (!JDS->Sealed) {
     if (auto Err = dlupdateFull(Lock, *JDS))
       return std::move(Err);
   }
@@ -1299,18 +1301,6 @@ Error MachOPlatformRuntimeState::dlupdateFull(
   if (auto Err = dlupdateInitialize(JDStatesLock, JDS, *DepInfo))
     return Err;
 
-  if (!DepInfo->empty()) {
-    ORC_RT_DEBUG({
-      printdbg("Unrecognized dep-info key headers in dlupdate of %s\n",
-               JDS.Name.c_str());
-    });
-    std::ostringstream ErrStream;
-    ErrStream << "Encountered unrecognized dep-info key headers "
-                 "while processing dlupdate of "
-              << JDS.Name;
-    return make_error<StringError>(ErrStream.str());
-  }
-
   return Error::success();
 }
 
@@ -1322,65 +1312,12 @@ Error MachOPlatformRuntimeState::dlupdateInitialize(
              JDS.Name.c_str());
   });
 
-  // If the header is not present in the dep map then assume that we
-  // already processed it earlier in the dlopenInitialize traversal and
-  // return.
-  // TODO: Keep a visited set instead so that we can error out on missing
-  //       entries?
-  auto I = DepInfo.find(ExecutorAddr::fromPtr(JDS.Header));
-  if (I == DepInfo.end())
-    return Error::success();
-
-  auto DI = std::move(I->second);
-  DepInfo.erase(I);
-
-  // We don't need to re-initialize sealed JITDylibs that have already been
-  // initialized. Just check that their dep-map entry is empty as expected.
-  if (JDS.Sealed) {
-    if (!DI.DepHeaders.empty()) {
-      std::ostringstream ErrStream;
-      ErrStream << "Sealed JITDylib " << JDS.Header
-                << " already has registered dependencies";
-      return make_error<StringError>(ErrStream.str());
-    }
-    if (JDS.referenced())
-      return Error::success();
-  } else
-    JDS.Sealed = DI.Sealed;
-
-  // This is an unsealed or newly sealed JITDylib. Run initializers.
-  std::vector<JITDylibState *> OldDeps;
-  std::swap(JDS.Deps, OldDeps);
-  JDS.Deps.reserve(DI.DepHeaders.size());
-  for (auto DepHeaderAddr : DI.DepHeaders) {
-    auto *DepJDS = getJITDylibStateByHeader(DepHeaderAddr.toPtr<void *>());
-    if (!DepJDS) {
-      std::ostringstream ErrStream;
-      ErrStream << "Encountered unrecognized dep header "
-                << DepHeaderAddr.toPtr<void *>() << " while initializing "
-                << JDS.Name;
-      return make_error<StringError>(ErrStream.str());
-    }
-
-    if (auto Err = dlupdateInitialize(JDStatesLock, *DepJDS, DepInfo))
-      return Err;
-  }
-
   // Initialize this JITDylib.
   if (auto Err = registerObjCRegistrationObjects(JDS))
     return Err;
   if (auto Err = runModInits(JDStatesLock, JDS))
     return Err;
 
-  // Decrement old deps.
-  // FIXME: We should probably continue and just report deinitialize errors
-  // here.
-  for (auto *DepJDS : OldDeps) {
-    if (!DepJDS->referenced())
-      if (auto Err = dlcloseDeinitialize(JDStatesLock, *DepJDS))
-        return Err;
-  }
-
   return Error::success();
 }
 
@@ -1657,8 +1594,8 @@ void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
   return MachOPlatformRuntimeState::get().dlopen(path, mode);
 }
 
-void *__orc_rt_macho_jit_dlupdate(const char *path, int mode) {
-  return MachOPlatformRuntimeState::get().dlupdate(path, mode);
+void *__orc_rt_macho_jit_dlupdate(void *dso_handle, int mode) {
+  return MachOPlatformRuntimeState::get().dlupdate(dso_handle, mode);
 }
 
 int __orc_rt_macho_jit_dlclose(void *dso_handle) {
diff --git a/compiler-rt/lib/orc/macho_platform.h b/compiler-rt/lib/orc/macho_platform.h
index ae9c8b487262a..c17331739aed4 100644
--- a/compiler-rt/lib/orc/macho_platform.h
+++ b/compiler-rt/lib/orc/macho_platform.h
@@ -24,7 +24,7 @@ ORC_RT_INTERFACE void __orc_rt_macho_cxa_finalize(void *dso_handle);
 // dlfcn functions.
 ORC_RT_INTERFACE const char *__orc_rt_macho_jit_dlerror();
 ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlopen(const char *path, int mode);
-ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlupdate(const char *path, int mode);
+ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlupdate(void *dso_handle, int mode);
 ORC_RT_INTERFACE int __orc_rt_macho_jit_dlclose(void *dso_handle);
 ORC_RT_INTERFACE void *__orc_rt_macho_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 56339cfa359b1..374365882318d 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -601,6 +601,7 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
   using llvm::orc::shared::SPSExecutorAddr;
   using llvm::orc::shared::SPSString;
   using SPSDLOpenSig = SPSExecutorAddr(SPSString, int32_t);
+  using SPSDLUpdateSig = SPSExecutorAddr(SPSExecutorAddr, int32_t);
   enum dlopen_mode : int32_t {
     ORC_RT_RTLD_LAZY = 0x1,
     ORC_RT_RTLD_NOW = 0x2,
@@ -612,15 +613,21 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
   auto MainSearchOrder = J.getMainJITDylib().withLinkOrderDo(
       [](const JITDylibSearchOrder &SO) { return SO; });
   StringRef WrapperToCall = "__orc_rt_jit_dlopen_wrapper";
+  bool dlupdate = false;
   if (ES.getTargetTriple().isOSBinFormatMachO()) {
-    if (InitializedDylib.contains(&JD))
+    if (InitializedDylib.contains(&JD)) {
       WrapperToCall = "__orc_rt_jit_dlupdate_wrapper";
-    else
+      dlupdate = true;
+    } else
       InitializedDylib.insert(&JD);
   }
 
   if (auto WrapperAddr = ES.lookup(
           MainSearchOrder, J.mangleAndIntern(WrapperToCall))) {
+    if (dlupdate)
+      return ES.callSPSWrapper<SPSDLUpdateSig>(WrapperAddr->getAddress(),
+                                               DSOHandles[&JD], DSOHandles[&JD],
+                                               int32_t(ORC_RT_RTLD_LAZY));
     return ES.callSPSWrapper<SPSDLOpenSig>(WrapperAddr->getAddress(),
                                            DSOHandles[&JD], JD.getName(),
                                            int32_t(ORC_RT_RTLD_LAZY));

>From a9ec1aa5d2039d9b4661ade1ef77ae1e0322db44 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Wed, 3 Jul 2024 09:30:53 +0530
Subject: [PATCH 3/6] Refactor code.

---
 compiler-rt/lib/orc/macho_platform.cpp        | 7 ++++---
 llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h | 2 +-
 llvm/lib/ExecutionEngine/Orc/LLJIT.cpp        | 4 ++--
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index 353e2fa8ae313..f229e155853a8 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -380,9 +380,10 @@ class MachOPlatformRuntimeState {
 
   Expected<void *> dlupdateImpl(void *DSOHandle, int Mode);
   Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock,
-                   JITDylibState &JDS);
+                     JITDylibState &JDS);
   Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock,
-                         JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);
+                           JITDylibState &JDS,
+                           MachOJITDylibDepInfoMap &DepInfo);
 
   Error dlcloseImpl(void *DSOHandle);
   Error dlcloseDeinitialize(std::unique_lock<std::mutex> &JDStatesLock,
@@ -1259,7 +1260,7 @@ Error MachOPlatformRuntimeState::dlopenInitialize(
 }
 
 Expected<void *> MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle,
-                                                       int Mode) {
+                                                         int Mode) {
   std::unique_lock<std::mutex> Lock(JDStatesMutex);
 
   // Try to find JITDylib state by DSOHandle.
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
index b42f13bf3fca8..2660b9f74f405 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
 #define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
 
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
@@ -22,7 +23,6 @@
 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ThreadPool.h"
-#include "llvm/ADT/SmallSet.h"
 #include <variant>
 
 namespace llvm {
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 374365882318d..75c8d0dd74c16 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -622,8 +622,8 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
       InitializedDylib.insert(&JD);
   }
 
-  if (auto WrapperAddr = ES.lookup(
-          MainSearchOrder, J.mangleAndIntern(WrapperToCall))) {
+  if (auto WrapperAddr =
+          ES.lookup(MainSearchOrder, J.mangleAndIntern(WrapperToCall))) {
     if (dlupdate)
       return ES.callSPSWrapper<SPSDLUpdateSig>(WrapperAddr->getAddress(),
                                                DSOHandles[&JD], DSOHandles[&JD],

>From 99969487416e14630f9e7d5cd36271c900bd5ec5 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Fri, 5 Jul 2024 14:58:33 +0530
Subject: [PATCH 4/6] Fix deinitialize issue, This change ensures that the
 `deinitialize` operation correctly removes the `JITDylib` from the set of
 initialized `JITDylibs`.

---
 llvm/lib/ExecutionEngine/Orc/LLJIT.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 75c8d0dd74c16..0f8b9d3a3bbd4 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -654,6 +654,7 @@ Error ORCPlatformSupport::deinitialize(orc::JITDylib &JD) {
       return make_error<StringError>("dlclose failed",
                                      inconvertibleErrorCode());
     DSOHandles.erase(&JD);
+    InitializedDylib.erase(&JD);
   } else
     return WrapperAddr.takeError();
   return Error::success();

>From 7ca77fd9597d633614f82398031e5803637e82d6 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Sat, 6 Jul 2024 09:29:28 +0530
Subject: [PATCH 5/6] Remove the unused `DepInfo` argument from
 `dlupdateInitialize`.

---
 compiler-rt/lib/orc/macho_platform.cpp | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index f229e155853a8..a7e7a0b0da689 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -382,8 +382,7 @@ class MachOPlatformRuntimeState {
   Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock,
                      JITDylibState &JDS);
   Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock,
-                           JITDylibState &JDS,
-                           MachOJITDylibDepInfoMap &DepInfo);
+                           JITDylibState &JDS);
 
   Error dlcloseImpl(void *DSOHandle);
   Error dlcloseDeinitialize(std::unique_lock<std::mutex> &JDStatesLock,
@@ -1299,15 +1298,14 @@ Error MachOPlatformRuntimeState::dlupdateFull(
   if (!DepInfo)
     return DepInfo.takeError();
 
-  if (auto Err = dlupdateInitialize(JDStatesLock, JDS, *DepInfo))
+  if (auto Err = dlupdateInitialize(JDStatesLock, JDS))
     return Err;
 
   return Error::success();
 }
 
 Error MachOPlatformRuntimeState::dlupdateInitialize(
-    std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS,
-    MachOJITDylibDepInfoMap &DepInfo) {
+    std::unique_lock<std::mutex> &JDStatesLock, JITDylibState &JDS) {
   ORC_RT_DEBUG({
     printdbg("MachOPlatformRuntimeState::dlupdateInitialize(\"%s\")\n",
              JDS.Name.c_str());

>From c09a2a802060178b40a1c44e478bceb93efb1449 Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Sat, 27 Jul 2024 11:35:30 +0530
Subject: [PATCH 6/6] Modify dlupdate to return error code instead of
 dso_handle

---
 compiler-rt/lib/orc/dlfcn_wrapper.cpp  |  7 +++----
 compiler-rt/lib/orc/macho_platform.cpp | 24 +++++++++++-------------
 compiler-rt/lib/orc/macho_platform.h   |  2 +-
 llvm/lib/ExecutionEngine/Orc/LLJIT.cpp | 16 +++++++++++-----
 4 files changed, 26 insertions(+), 23 deletions(-)

diff --git a/compiler-rt/lib/orc/dlfcn_wrapper.cpp b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
index a6ed7545807c8..9a6096930c553 100644
--- a/compiler-rt/lib/orc/dlfcn_wrapper.cpp
+++ b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
@@ -20,7 +20,7 @@ using namespace __orc_rt;
 
 extern "C" const char *__orc_rt_jit_dlerror();
 extern "C" void *__orc_rt_jit_dlopen(const char *path, int mode);
-extern "C" void *__orc_rt_jit_dlupdate(void *dso_handle, int mode);
+extern "C" int __orc_rt_jit_dlupdate(void *dso_handle, int mode);
 extern "C" int __orc_rt_jit_dlclose(void *dso_handle);
 
 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
@@ -44,11 +44,10 @@ __orc_rt_jit_dlopen_wrapper(const char *ArgData, size_t ArgSize) {
 
 ORC_RT_INTERFACE orc_rt_CWrapperFunctionResult
 __orc_rt_jit_dlupdate_wrapper(const char *ArgData, size_t ArgSize) {
-  return WrapperFunction<SPSExecutorAddr(SPSExecutorAddr, int32_t)>::handle(
+  return WrapperFunction<int32_t(SPSExecutorAddr, int32_t)>::handle(
              ArgData, ArgSize,
              [](ExecutorAddr &DSOHandle, int32_t mode) {
-               return ExecutorAddr::fromPtr(
-                   __orc_rt_jit_dlupdate(DSOHandle.toPtr<void *>(), mode));
+               return __orc_rt_jit_dlupdate(DSOHandle.toPtr<void *>(), mode);
              })
       .release();
 }
diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index a7e7a0b0da689..8c68347bf1551 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -330,7 +330,7 @@ class MachOPlatformRuntimeState {
 
   const char *dlerror();
   void *dlopen(std::string_view Name, int Mode);
-  void *dlupdate(void *DSOHandle, int Mode);
+  int dlupdate(void *DSOHandle, int Mode);
   int dlclose(void *DSOHandle);
   void *dlsym(void *DSOHandle, const char *Symbol);
 
@@ -378,7 +378,7 @@ class MachOPlatformRuntimeState {
   Error dlopenInitialize(std::unique_lock<std::mutex> &JDStatesLock,
                          JITDylibState &JDS, MachOJITDylibDepInfoMap &DepInfo);
 
-  Expected<void *> dlupdateImpl(void *DSOHandle, int Mode);
+  Error dlupdateImpl(void *DSOHandle, int Mode);
   Error dlupdateFull(std::unique_lock<std::mutex> &JDStatesLock,
                      JITDylibState &JDS);
   Error dlupdateInitialize(std::unique_lock<std::mutex> &JDStatesLock,
@@ -793,19 +793,18 @@ void *MachOPlatformRuntimeState::dlopen(std::string_view Path, int Mode) {
   }
 }
 
-void *MachOPlatformRuntimeState::dlupdate(void *DSOHandle, int Mode) {
+int MachOPlatformRuntimeState::dlupdate(void *DSOHandle, int Mode) {
   ORC_RT_DEBUG({
     std::string S;
     printdbg("MachOPlatform::dlupdate(%p) (%s)\n", DSOHandle, S.c_str());
   });
   std::lock_guard<std::recursive_mutex> Lock(DyldAPIMutex);
-  if (auto H = dlupdateImpl(DSOHandle, Mode))
-    return *H;
-  else {
+  if (auto Err = dlupdateImpl(DSOHandle, Mode)) {
     // FIXME: Make dlerror thread safe.
-    DLFcnError = toString(H.takeError());
-    return nullptr;
+    DLFcnError = toString(std::move(Err));
+    return -1;
   }
+  return 0;
 }
 
 int MachOPlatformRuntimeState::dlclose(void *DSOHandle) {
@@ -1258,7 +1257,7 @@ Error MachOPlatformRuntimeState::dlopenInitialize(
   return Error::success();
 }
 
-Expected<void *> MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle,
+Error MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle,
                                                          int Mode) {
   std::unique_lock<std::mutex> Lock(JDStatesMutex);
 
@@ -1276,11 +1275,10 @@ Expected<void *> MachOPlatformRuntimeState::dlupdateImpl(void *DSOHandle,
 
   if (!JDS->Sealed) {
     if (auto Err = dlupdateFull(Lock, *JDS))
-      return std::move(Err);
+      return Err;
   }
 
-  // Return the header address.
-  return JDS->Header;
+  return Error::success();
 }
 
 Error MachOPlatformRuntimeState::dlupdateFull(
@@ -1593,7 +1591,7 @@ void *__orc_rt_macho_jit_dlopen(const char *path, int mode) {
   return MachOPlatformRuntimeState::get().dlopen(path, mode);
 }
 
-void *__orc_rt_macho_jit_dlupdate(void *dso_handle, int mode) {
+int __orc_rt_macho_jit_dlupdate(void *dso_handle, int mode) {
   return MachOPlatformRuntimeState::get().dlupdate(dso_handle, mode);
 }
 
diff --git a/compiler-rt/lib/orc/macho_platform.h b/compiler-rt/lib/orc/macho_platform.h
index c17331739aed4..b297befc3881d 100644
--- a/compiler-rt/lib/orc/macho_platform.h
+++ b/compiler-rt/lib/orc/macho_platform.h
@@ -24,7 +24,7 @@ ORC_RT_INTERFACE void __orc_rt_macho_cxa_finalize(void *dso_handle);
 // dlfcn functions.
 ORC_RT_INTERFACE const char *__orc_rt_macho_jit_dlerror();
 ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlopen(const char *path, int mode);
-ORC_RT_INTERFACE void *__orc_rt_macho_jit_dlupdate(void *dso_handle, int mode);
+ORC_RT_INTERFACE int __orc_rt_macho_jit_dlupdate(void *dso_handle, int mode);
 ORC_RT_INTERFACE int __orc_rt_macho_jit_dlclose(void *dso_handle);
 ORC_RT_INTERFACE void *__orc_rt_macho_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 0f8b9d3a3bbd4..4327d94dcc71f 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -601,7 +601,7 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
   using llvm::orc::shared::SPSExecutorAddr;
   using llvm::orc::shared::SPSString;
   using SPSDLOpenSig = SPSExecutorAddr(SPSString, int32_t);
-  using SPSDLUpdateSig = SPSExecutorAddr(SPSExecutorAddr, int32_t);
+  using SPSDLUpdateSig = int32_t(SPSExecutorAddr, int32_t);
   enum dlopen_mode : int32_t {
     ORC_RT_RTLD_LAZY = 0x1,
     ORC_RT_RTLD_NOW = 0x2,
@@ -624,10 +624,16 @@ Error ORCPlatformSupport::initialize(orc::JITDylib &JD) {
 
   if (auto WrapperAddr =
           ES.lookup(MainSearchOrder, J.mangleAndIntern(WrapperToCall))) {
-    if (dlupdate)
-      return ES.callSPSWrapper<SPSDLUpdateSig>(WrapperAddr->getAddress(),
-                                               DSOHandles[&JD], DSOHandles[&JD],
-                                               int32_t(ORC_RT_RTLD_LAZY));
+    if (dlupdate) {
+      int32_t result;
+      auto E = ES.callSPSWrapper<SPSDLUpdateSig>(WrapperAddr->getAddress(),
+                                                 result, DSOHandles[&JD],
+                                                 int32_t(ORC_RT_RTLD_LAZY));
+      if (result)
+        return make_error<StringError>("dlupdate failed",
+                                       inconvertibleErrorCode());
+      return E;
+    }
     return ES.callSPSWrapper<SPSDLOpenSig>(WrapperAddr->getAddress(),
                                            DSOHandles[&JD], JD.getName(),
                                            int32_t(ORC_RT_RTLD_LAZY));



More information about the llvm-commits mailing list