[Orc] Add AutoRegisterCode option for DebugObjectManagerPlugin
authorStefan Gränitz <stefan.graenitz@gmail.com>
Mon, 3 Apr 2023 09:41:37 +0000 (11:41 +0200)
committerStefan Gränitz <stefan.graenitz@gmail.com>
Mon, 3 Apr 2023 13:38:07 +0000 (15:38 +0200)
Configure the plugin to automatically call the debugger rendezvous breakpoint `__jit_debug_register_code()` for every translation unit (enabled) or never at all (disabled). Default API and behavior remain unchanged.

If AutoRegisterCode is turned off, it's the client's own responsibility to call the rendezvous breakpoint function at an appropriate time.
Depending on the complexity of the debugger's rendezvous breakpoint implementation, this can provide significant performance improvements in cases where many debug objects are added in sequence.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D147310

llvm/examples/OrcV2Examples/LLJITWithRemoteDebugging/RemoteJITUtils.cpp
llvm/include/llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h
llvm/include/llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h
llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp
llvm/lib/ExecutionEngine/Orc/DebuggerSupportPlugin.cpp
llvm/lib/ExecutionEngine/Orc/EPCDebugObjectRegistrar.cpp
llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
llvm/tools/lli/lli.cpp
llvm/tools/llvm-jitlink/llvm-jitlink.cpp

index 82403a2..a5d2c2f 100644 (file)
@@ -37,8 +37,8 @@ Error addDebugSupport(ObjectLayer &ObjLayer) {
     return createStringError(inconvertibleErrorCode(),
                              "No debug support for given object layer type");
 
-  ObjLinkingLayer->addPlugin(
-      std::make_unique<DebugObjectManagerPlugin>(ES, std::move(*Registrar)));
+  ObjLinkingLayer->addPlugin(std::make_unique<DebugObjectManagerPlugin>(
+      ES, std::move(*Registrar), true, true));
   return Error::success();
 }
 
index 82bed96..70f5230 100644 (file)
@@ -60,9 +60,15 @@ public:
   ///   names. Note that this may cause significant memory and transport
   ///   overhead for objects built with a release configuration.
   ///
+  /// AutoRegisterCode:
+  ///   Notify the debugger for each new debug object. This is a good default
+  ///   mode, but it may cause significant overhead when adding many modules in
+  ///   sequence. When turning this off, the user has to issue the call to
+  ///   __jit_debug_register_code() on the executor side manually.
+  ///
   DebugObjectManagerPlugin(ExecutionSession &ES,
                            std::unique_ptr<DebugObjectRegistrar> Target,
-                           bool RequireDebugSections);
+                           bool RequireDebugSections, bool AutoRegisterCode);
   ~DebugObjectManagerPlugin();
 
   void notifyMaterializing(MaterializationResponsibility &MR,
@@ -92,6 +98,7 @@ private:
 
   std::unique_ptr<DebugObjectRegistrar> Target;
   bool RequireDebugSections;
+  bool AutoRegisterCode;
 };
 
 } // namespace orc
index 7e14381..201d52a 100644 (file)
@@ -31,7 +31,8 @@ class ExecutionSession;
 /// Abstract interface for registering debug objects in the executor process.
 class DebugObjectRegistrar {
 public:
-  virtual Error registerDebugObject(ExecutorAddrRange TargetMem) = 0;
+  virtual Error registerDebugObject(ExecutorAddrRange TargetMem,
+                                    bool AutoRegisterCode) = 0;
   virtual ~DebugObjectRegistrar() = default;
 };
 
@@ -42,7 +43,8 @@ public:
   EPCDebugObjectRegistrar(ExecutionSession &ES, ExecutorAddr RegisterFn)
       : ES(ES), RegisterFn(RegisterFn) {}
 
-  Error registerDebugObject(ExecutorAddrRange TargetMem) override;
+  Error registerDebugObject(ExecutorAddrRange TargetMem,
+                            bool AutoRegisterCode) override;
 
 private:
   ExecutionSession &ES;
index 0f0839e..acbf338 100644 (file)
@@ -389,13 +389,14 @@ createDebugObjectFromBuffer(ExecutionSession &ES, LinkGraph &G,
 
 DebugObjectManagerPlugin::DebugObjectManagerPlugin(
     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target,
-    bool RequireDebugSections)
+    bool RequireDebugSections, bool AutoRegisterCode)
     : ES(ES), Target(std::move(Target)),
-      RequireDebugSections(RequireDebugSections) {}
+      RequireDebugSections(RequireDebugSections),
+      AutoRegisterCode(AutoRegisterCode) {}
 
 DebugObjectManagerPlugin::DebugObjectManagerPlugin(
     ExecutionSession &ES, std::unique_ptr<DebugObjectRegistrar> Target)
-    : DebugObjectManagerPlugin(ES, std::move(Target), true) {}
+    : DebugObjectManagerPlugin(ES, std::move(Target), true, true) {}
 
 DebugObjectManagerPlugin::~DebugObjectManagerPlugin() = default;
 
@@ -464,7 +465,8 @@ Error DebugObjectManagerPlugin::notifyEmitted(
           FinalizePromise.set_value(TargetMem.takeError());
           return;
         }
-        if (Error Err = Target->registerDebugObject(*TargetMem)) {
+        if (Error Err =
+                Target->registerDebugObject(*TargetMem, AutoRegisterCode)) {
           FinalizePromise.set_value(std::move(Err));
           return;
         }
index 5c7348a..830582b 100644 (file)
@@ -348,11 +348,12 @@ public:
       Writer.write(SecCmd);
     }
 
+    static constexpr bool AutoRegisterCode = true;
     SectionRange R(MachOContainerBlock->getSection());
     G.allocActions().push_back(
         {cantFail(shared::WrapperFunctionCall::Create<
-                  shared::SPSArgList<shared::SPSExecutorAddrRange>>(
-             RegisterActionAddr, R.getRange())),
+                  shared::SPSArgList<shared::SPSExecutorAddrRange, bool>>(
+             RegisterActionAddr, R.getRange(), AutoRegisterCode)),
          {}});
     return Error::success();
   }
index 6777a20..b8969de 100644 (file)
@@ -48,10 +48,10 @@ Expected<std::unique_ptr<EPCDebugObjectRegistrar>> createJITLoaderGDBRegistrar(
   return std::make_unique<EPCDebugObjectRegistrar>(ES, (*Result)[0][0]);
 }
 
-Error EPCDebugObjectRegistrar::registerDebugObject(
-    ExecutorAddrRange TargetMem) {
-  return ES.callSPSWrapper<void(shared::SPSExecutorAddrRange)>(RegisterFn,
-                                                               TargetMem);
+Error EPCDebugObjectRegistrar::registerDebugObject(ExecutorAddrRange TargetMem,
+                                                   bool AutoRegisterCode) {
+  return ES.callSPSWrapper<void(shared::SPSExecutorAddrRange, bool)>(
+      RegisterFn, TargetMem, AutoRegisterCode);
 }
 
 } // namespace orc
index 8296b03..8eca874 100644 (file)
@@ -67,9 +67,9 @@ using namespace llvm;
 using namespace llvm::orc;
 
 // Register debug object, return error message or null for success.
-static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
+static void appendJITDebugDescriptor(const char *ObjAddr, size_t Size) {
   LLVM_DEBUG({
-    dbgs() << "Registering debug object with GDB JIT interface "
+    dbgs() << "Adding debug object to GDB JIT interface "
            << formatv("([{0:x16} -- {1:x16}])",
                       reinterpret_cast<uintptr_t>(ObjAddr),
                       reinterpret_cast<uintptr_t>(ObjAddr + Size))
@@ -94,20 +94,20 @@ static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
 
   __jit_debug_descriptor.first_entry = E;
   __jit_debug_descriptor.relevant_entry = E;
-
-  // Run into the rendezvous breakpoint.
   __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
-  __jit_debug_register_code();
 }
 
 extern "C" orc::shared::CWrapperFunctionResult
 llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size) {
   using namespace orc::shared;
-  return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
+  return WrapperFunction<SPSError(SPSExecutorAddrRange, bool)>::handle(
              Data, Size,
-             [](ExecutorAddrRange R) {
-               registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
+             [](ExecutorAddrRange R, bool AutoRegisterCode) {
+               appendJITDebugDescriptor(R.Start.toPtr<const char *>(),
                                         R.size());
+               // Run into the rendezvous breakpoint.
+               if (AutoRegisterCode)
+                 __jit_debug_register_code();
                return Error::success();
              })
       .release();
@@ -116,11 +116,14 @@ llvm_orc_registerJITLoaderGDBAllocAction(const char *Data, size_t Size) {
 extern "C" orc::shared::CWrapperFunctionResult
 llvm_orc_registerJITLoaderGDBWrapper(const char *Data, uint64_t Size) {
   using namespace orc::shared;
-  return WrapperFunction<SPSError(SPSExecutorAddrRange)>::handle(
+  return WrapperFunction<SPSError(SPSExecutorAddrRange, bool)>::handle(
              Data, Size,
-             [](ExecutorAddrRange R) {
-               registerJITLoaderGDBImpl(R.Start.toPtr<const char *>(),
+             [](ExecutorAddrRange R, bool AutoRegisterCode) {
+               appendJITDebugDescriptor(R.Start.toPtr<const char *>(),
                                         R.size());
+               // Run into the rendezvous breakpoint.
+               if (AutoRegisterCode)
+                 __jit_debug_register_code();
                return Error::success();
              })
       .release();
index d6baa7a..464db8f 100644 (file)
@@ -938,7 +938,7 @@ int runOrcJIT(const char *ProgName) {
         L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
             ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
         L->addPlugin(std::make_unique<orc::DebugObjectManagerPlugin>(
-            ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES))));
+            ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES)), true, true));
       }
       return L;
     });
index 5f057cd..332e3e7 100644 (file)
@@ -1027,7 +1027,7 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
           ES, ExitOnErr(EPCEHFrameRegistrar::Create(this->ES))));
     if (DebuggerSupport)
       ObjLayer.addPlugin(std::make_unique<DebugObjectManagerPlugin>(
-          ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES))));
+          ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES)), true, true));
   }
 
   ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));