[llvm] [llvm-c] Expose debug object registration in Orc C-API bindings (PR #73257)

Stefan Gränitz via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 24 08:07:51 PST 2023


https://github.com/weliveindetail updated https://github.com/llvm/llvm-project/pull/73257

>From 5b93cab0f0d4cd43dab720ffb4a952a66a99ec79 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Thu, 23 Nov 2023 09:41:30 +0100
Subject: [PATCH 1/4] [llvm-c] Expose debug object registration in Orc bindings

---
 llvm/include/llvm-c/Orc.h                     | 19 +++++++++++++
 .../ExecutionEngine/Orc/OrcV2CBindings.cpp    | 28 +++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h
index 304833cca2d4332..633f191b9836941 100644
--- a/llvm/include/llvm-c/Orc.h
+++ b/llvm/include/llvm-c/Orc.h
@@ -1206,6 +1206,25 @@ void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer,
                             LLVMOrcMaterializationResponsibilityRef R,
                             LLVMMemoryBufferRef ObjBuffer);
 
+/**
+ * Install the plugin that submits debug objects to the executor. Out-of-process
+ * executors must provide the llvm_orc_registerJITLoaderGDBWrapper symbol.
+ *
+ * RequireDebugSectionsFlag lets the plugin pass debug objects only if they
+ * contain actual debug info. Turning this off may allow minimal debugging based
+ * on raw symbol names. It may cause significant memory and transport overhead
+ * for objects built with a release configuration.
+ *
+ * AutoRegisterCodeFlag lets the executor 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 turned off, the user has to issue
+ * the call to __jit_debug_register_code() on the executor side manually.
+ */
+LLVMErrorRef
+LLVMOrcObjectLayerRegisterPluginJITLoaderGDB(LLVMOrcObjectLayerRef ObjLayer,
+                                             LLVMBool RequireDebugSectionsFlag,
+                                             LLVMBool AutoRegisterCodeFlag);
+
 /**
  * Dispose of an ObjectLayer.
  */
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index a73aec6d98c64c9..871a9b44306ac49 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -11,10 +11,13 @@
 #include "llvm-c/OrcEE.h"
 #include "llvm-c/TargetMachine.h"
 
+#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
+#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 
 using namespace llvm;
@@ -863,6 +866,31 @@ void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer,
       std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer)));
 }
 
+LLVMErrorRef
+LLVMOrcObjectLayerRegisterPluginJITLoaderGDB(LLVMOrcObjectLayerRef ObjLayer,
+                                             LLVMBool RequireDebugSectionsFlag,
+                                             LLVMBool AutoRegisterCodeFlag) {
+  ExecutionSession &ES = unwrap(ObjLayer)->getExecutionSession();
+  auto Registrar = createJITLoaderGDBRegistrar(ES);
+  if (!Registrar)
+    return wrap(Registrar.takeError());
+
+  auto *ObjLinkingLayer = cast<ObjectLinkingLayer>(unwrap(ObjLayer));
+  if (!ObjLinkingLayer)
+    return wrap(
+        createStringError(inconvertibleErrorCode(),
+                          "No debug support for given object layer type"));
+
+  ObjLinkingLayer->addPlugin(std::make_unique<DebugObjectManagerPlugin>(
+      ES, std::move(*Registrar), RequireDebugSectionsFlag,
+      AutoRegisterCodeFlag));
+
+  auto TargetProcessFn = &llvm_orc_registerJITLoaderGDBWrapper;
+  (void)TargetProcessFn;
+
+  return LLVMErrorSuccess;
+}
+
 void LLVMOrcDisposeObjectLayer(LLVMOrcObjectLayerRef ObjLayer) {
   delete unwrap(ObjLayer);
 }

>From c9060de4f90e9a84b7b8acf2c0c8d6da2c13cd72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Thu, 23 Nov 2023 18:03:00 +0100
Subject: [PATCH 2/4] [llvm-c] Add unit test for Orc debug object registration

---
 .../ExecutionEngine/Orc/OrcCAPITest.cpp       | 66 +++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
index cbdd4af47e1d47d..6f72d5ddc5dca91 100644
--- a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
@@ -13,6 +13,7 @@
 #include "gtest/gtest.h"
 
 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IRReader/IRReader.h"
@@ -27,6 +28,7 @@ using namespace llvm;
 using namespace llvm::orc;
 
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectLayer, LLVMOrcObjectLayerRef)
 
 // OrcCAPITestBase contains several helper methods and pointers for unit tests
 // written for the LLVM-C API. It provides the following helpers:
@@ -494,6 +496,70 @@ TEST_F(OrcCAPITestBase, AddObjectBuffer) {
   ASSERT_TRUE(!!SumAddr);
 }
 
+// This must be kept in sync with gdb/gdb/jit.h .
+extern "C" {
+
+typedef enum {
+  JIT_NOACTION = 0,
+  JIT_REGISTER_FN,
+  JIT_UNREGISTER_FN
+} jit_actions_t;
+
+struct jit_code_entry {
+  struct jit_code_entry *next_entry;
+  struct jit_code_entry *prev_entry;
+  const char *symfile_addr;
+  uint64_t symfile_size;
+};
+
+struct jit_descriptor {
+  uint32_t version;
+  // This should be jit_actions_t, but we want to be specific about the
+  // bit-width.
+  uint32_t action_flag;
+  struct jit_code_entry *relevant_entry;
+  struct jit_code_entry *first_entry;
+};
+
+// We put information about the JITed function in this global, which the
+// debugger reads.  Make sure to specify the version statically, because the
+// debugger checks the version before we can set it during runtime.
+extern "C" struct jit_descriptor __jit_debug_descriptor;
+}
+
+#if defined(_AIX)
+TEST_F(OrcCAPITestBase, DISABLED_RegisterJITLoaderGDB) {
+#else
+TEST_F(OrcCAPITestBase, RegisterJITLoaderGDB) {
+#endif
+  LLVMOrcObjectLayerRef ObjLayer = LLVMOrcLLJITGetObjLinkingLayer(Jit);
+  auto *ObjLinkingLayer = cast<orc::ObjectLinkingLayer>(unwrap(ObjLayer));
+  ASSERT_TRUE(ObjLinkingLayer);
+
+  constexpr bool RequireDebugSectionsFlag = false;
+  constexpr bool AutoRegisterCodeFlag = true;
+  LLVMErrorRef E = LLVMOrcObjectLayerRegisterPluginJITLoaderGDB(
+      ObjLayer, RequireDebugSectionsFlag, AutoRegisterCodeFlag);
+  if (E)
+    FAIL() << "Failed to register plugin to ObjLinkingLayer (triple = "
+           << TargetTriple << "): " << toString(E);
+
+  ASSERT_EQ(__jit_debug_descriptor.first_entry, nullptr);
+
+  LLVMMemoryBufferRef ObjBuffer = createTestObject(SumExample, "sum.ll");
+  if (LLVMErrorRef E =
+          LLVMOrcObjectLayerAddObjectFile(ObjLayer, MainDylib, ObjBuffer))
+    FAIL() << "Failed to add object file to ObjLinkingLayer (triple = "
+           << TargetTriple << "): " << toString(E);
+
+  LLVMOrcJITTargetAddress SumAddr;
+  if (LLVMErrorRef E = LLVMOrcLLJITLookup(Jit, &SumAddr, "sum"))
+    FAIL() << "Symbol \"sum\" was not added into JIT (triple = " << TargetTriple
+           << "): " << toString(E);
+
+  ASSERT_NE(__jit_debug_descriptor.first_entry, nullptr);
+}
+
 #if defined(_AIX)
 TEST_F(OrcCAPITestBase, DISABLED_ExecutionTest) {
 #else

>From 786088e41a92428f9573b4da37ea6c8a1b04d0f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Thu, 23 Nov 2023 21:32:22 +0100
Subject: [PATCH 3/4] [llvm-c] Run RegisterJITLoaderGDB test only on native
 __ELF__ targets

---
 llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
index 6f72d5ddc5dca91..88b47be82689f2b 100644
--- a/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
@@ -527,7 +527,7 @@ struct jit_descriptor {
 extern "C" struct jit_descriptor __jit_debug_descriptor;
 }
 
-#if defined(_AIX)
+#if not defined(__ELF__)
 TEST_F(OrcCAPITestBase, DISABLED_RegisterJITLoaderGDB) {
 #else
 TEST_F(OrcCAPITestBase, RegisterJITLoaderGDB) {

>From dad137d84ea65eb9166e85bf663708e9f8c0cab0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Fri, 24 Nov 2023 17:05:49 +0100
Subject: [PATCH 4/4] [llvm-c] Drop dependency to OrcTargetProcess and update
 docs

---
 llvm/include/llvm-c/Orc.h                       | 4 ++--
 llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp | 4 ----
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h
index 633f191b9836941..114b44e876baa5e 100644
--- a/llvm/include/llvm-c/Orc.h
+++ b/llvm/include/llvm-c/Orc.h
@@ -1207,8 +1207,8 @@ void LLVMOrcObjectLayerEmit(LLVMOrcObjectLayerRef ObjLayer,
                             LLVMMemoryBufferRef ObjBuffer);
 
 /**
- * Install the plugin that submits debug objects to the executor. Out-of-process
- * executors must provide the llvm_orc_registerJITLoaderGDBWrapper symbol.
+ * Install the plugin that submits debug objects to the executor. Executors must
+ * expose the llvm_orc_registerJITLoaderGDBWrapper symbol.
  *
  * RequireDebugSectionsFlag lets the plugin pass debug objects only if they
  * contain actual debug info. Turning this off may allow minimal debugging based
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
index 871a9b44306ac49..1462549de45c36b 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcV2CBindings.cpp
@@ -17,7 +17,6 @@
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 
 using namespace llvm;
@@ -885,9 +884,6 @@ LLVMOrcObjectLayerRegisterPluginJITLoaderGDB(LLVMOrcObjectLayerRef ObjLayer,
       ES, std::move(*Registrar), RequireDebugSectionsFlag,
       AutoRegisterCodeFlag));
 
-  auto TargetProcessFn = &llvm_orc_registerJITLoaderGDBWrapper;
-  (void)TargetProcessFn;
-
   return LLVMErrorSuccess;
 }
 



More information about the llvm-commits mailing list