https://github.com/satyajanga updated https://github.com/llvm/llvm-project/pull/201449
>From c3066373d89e5ea8c862a0ae1419acb0ca0345b6 Mon Sep 17 00:00:00 2001 From: satya janga <[email protected]> Date: Sat, 6 Jun 2026 08:25:45 -0700 Subject: [PATCH] [lldb] Add connection info to the accelerator plugin protocol Add AcceleratorConnectionInfo, describing how the client should create a new target and reverse-connect to a separate GDB server that serves an accelerator's state (e.g. a GPU debug stub). It carries the connect URL and optional exe path, platform name, triple, and a synchronous flag. A connect_info field is added to AcceleratorActions so a plugin can ask the client to establish such a connection alongside (or instead of) setting breakpoints. This is the wire-format foundation; the client-side handling that acts on connect_info comes in a follow-up. Adds JSON serialization, unit tests, and documents the new fields in the jAcceleratorPluginInitialize packet. --- lldb/docs/resources/lldbgdbremote.md | 16 +++++- .../Utility/AcceleratorGDBRemotePackets.h | 27 ++++++++++ .../Utility/AcceleratorGDBRemotePackets.cpp | 25 ++++++++- .../AcceleratorGDBRemotePacketsTest.cpp | 53 +++++++++++++++++++ 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md index 1fc04e5ce9e11..862e696f156f1 100644 --- a/lldb/docs/resources/lldbgdbremote.md +++ b/lldb/docs/resources/lldbgdbremote.md @@ -2750,9 +2750,21 @@ breakpoints to be set in the native process. See `jAcceleratorPluginBreakpointHit` for the callback when those breakpoints are hit. +An `accelerator_action` may also include a `connect_info` object asking the +client to create a new target and connect to a separate GDB server that +serves the accelerator's state (for example a GPU debug stub). It has the +following fields: + +| Key | Type | Description | +|-----------------|--------|-------------| +| `connect_url` | string | Connection URL to connect to, as used by `process connect <url>`. | +| `exe_path` | string | Optional path to the executable to use when creating the accelerator target. If omitted, an empty target is created. | +| `platform_name` | string | Optional name of the platform to select for the accelerator target. | +| `triple` | string | Optional target triple to use as the architecture for the accelerator target. | +| `synchronous` | bool | If true, the client waits for the accelerator process to finish initializing before continuing. | + In future patches, each `accelerator_action` will include additional fields -such as connection info for secondary debug sessions and synchronization -options. +such as synchronization options for the accelerator process. **Priority To Implement:** Required for hardware accelerator debugging support. Not needed for non-hardware-accelerator debugging. diff --git a/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h b/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h index 9ba36fc540a52..69cf2bd2e7def 100644 --- a/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h +++ b/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h @@ -85,6 +85,30 @@ bool fromJSON(const llvm::json::Value &value, AcceleratorBreakpointHitArgs &data, llvm::json::Path path); llvm::json::Value toJSON(const AcceleratorBreakpointHitArgs &data); +/// Information the client needs to create a reverse connection to an +/// accelerator GDB server (e.g. a separate process serving the accelerator's +/// register and memory state). When an AcceleratorActions carries this, the +/// client creates a new target and connects to \a connect_url. +struct AcceleratorConnectionInfo { + /// Path to the executable to use when creating the accelerator target. If + /// not set, an empty target is created. + std::optional<std::string> exe_path; + /// Name of the platform to select for the accelerator target. + std::optional<std::string> platform_name; + /// Target triple to use as the architecture for the accelerator target. + std::optional<std::string> triple; + /// Connection URL the client should connect to (as in "process connect + /// <url>"). + std::string connect_url; + /// If true, the client waits for the accelerator process to finish + /// initializing before continuing. + bool synchronous = false; +}; + +bool fromJSON(const llvm::json::Value &value, AcceleratorConnectionInfo &data, + llvm::json::Path path); +llvm::json::Value toJSON(const AcceleratorConnectionInfo &data); + /// Actions to be performed in the native process on behalf of an accelerator /// plugin. AcceleratorActions are returned in the following contexts: /// @@ -114,6 +138,9 @@ struct AcceleratorActions { int64_t identifier = 0; /// New breakpoints to set. Nothing to set if this is empty. std::vector<AcceleratorBreakpointInfo> breakpoints; + /// If set, the client should create a new target and connect to the + /// accelerator GDB server described here. + std::optional<AcceleratorConnectionInfo> connect_info; }; bool fromJSON(const llvm::json::Value &value, AcceleratorActions &data, diff --git a/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp b/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp index 34067b1fa64c7..18282b5ebdfb3 100644 --- a/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp +++ b/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp @@ -86,21 +86,42 @@ AcceleratorBreakpointHitArgs::GetSymbolValue(StringRef symbol_name) const { return std::nullopt; } +bool fromJSON(const Value &value, AcceleratorConnectionInfo &data, Path path) { + ObjectMapper o(value, path); + return o && o.mapOptional("exe_path", data.exe_path) && + o.mapOptional("platform_name", data.platform_name) && + o.mapOptional("triple", data.triple) && + o.map("connect_url", data.connect_url) && + o.map("synchronous", data.synchronous); +} + +json::Value toJSON(const AcceleratorConnectionInfo &data) { + return Object{ + {"exe_path", data.exe_path}, {"platform_name", data.platform_name}, + {"triple", data.triple}, {"connect_url", data.connect_url}, + {"synchronous", data.synchronous}, + }; +} + bool fromJSON(const Value &value, AcceleratorActions &data, Path path) { ObjectMapper o(value, path); return o && o.map("plugin_name", data.plugin_name) && o.map("session_name", data.session_name) && o.map("identifier", data.identifier) && - o.map("breakpoints", data.breakpoints); + o.map("breakpoints", data.breakpoints) && + o.mapOptional("connect_info", data.connect_info); } json::Value toJSON(const AcceleratorActions &data) { - return Object{ + Object obj{ {"plugin_name", data.plugin_name}, {"session_name", data.session_name}, {"identifier", data.identifier}, {"breakpoints", data.breakpoints}, }; + if (data.connect_info) + obj["connect_info"] = *data.connect_info; + return obj; } bool fromJSON(const Value &value, AcceleratorBreakpointHitResponse &data, diff --git a/lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp b/lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp index fdcb0585fa3c7..f06df0119617a 100644 --- a/lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp +++ b/lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp @@ -187,3 +187,56 @@ TEST(AcceleratorGDBRemotePacketsTest, EXPECT_EQ("exit", deserialized->actions->breakpoints[0].by_name->function_name); } + +TEST(AcceleratorGDBRemotePacketsTest, AcceleratorConnectionInfo) { + AcceleratorConnectionInfo conn; + conn.exe_path = "/path/to/accel.elf"; + conn.platform_name = "remote-gdb-server"; + conn.triple = "amdgcn-amd-amdhsa"; + conn.connect_url = "connect://localhost:1234"; + conn.synchronous = true; + + Expected<AcceleratorConnectionInfo> deserialized = roundtripJSON(conn); + ASSERT_THAT_EXPECTED(deserialized, Succeeded()); + EXPECT_EQ(conn.exe_path, deserialized->exe_path); + EXPECT_EQ(conn.platform_name, deserialized->platform_name); + EXPECT_EQ(conn.triple, deserialized->triple); + EXPECT_EQ(conn.connect_url, deserialized->connect_url); + EXPECT_EQ(conn.synchronous, deserialized->synchronous); +} + +TEST(AcceleratorGDBRemotePacketsTest, AcceleratorConnectionInfoMinimal) { + AcceleratorConnectionInfo conn; + conn.connect_url = "connect://localhost:5678"; + + Expected<AcceleratorConnectionInfo> deserialized = roundtripJSON(conn); + ASSERT_THAT_EXPECTED(deserialized, Succeeded()); + EXPECT_EQ(std::nullopt, deserialized->exe_path); + EXPECT_EQ(std::nullopt, deserialized->platform_name); + EXPECT_EQ(std::nullopt, deserialized->triple); + EXPECT_EQ(conn.connect_url, deserialized->connect_url); + EXPECT_FALSE(deserialized->synchronous); +} + +TEST(AcceleratorGDBRemotePacketsTest, AcceleratorActionsWithConnectInfo) { + AcceleratorActions actions("mock", 3); + AcceleratorConnectionInfo conn; + conn.connect_url = "connect://localhost:9999"; + conn.synchronous = true; + actions.connect_info = std::move(conn); + + Expected<AcceleratorActions> deserialized = roundtripJSON(actions); + ASSERT_THAT_EXPECTED(deserialized, Succeeded()); + ASSERT_TRUE(deserialized->connect_info.has_value()); + EXPECT_EQ("connect://localhost:9999", + deserialized->connect_info->connect_url); + EXPECT_TRUE(deserialized->connect_info->synchronous); +} + +TEST(AcceleratorGDBRemotePacketsTest, AcceleratorActionsWithoutConnectInfo) { + AcceleratorActions actions("mock", 4); + + Expected<AcceleratorActions> deserialized = roundtripJSON(actions); + ASSERT_THAT_EXPECTED(deserialized, Succeeded()); + EXPECT_FALSE(deserialized->connect_info.has_value()); +} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
