llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: satyanarayana reddy janga (satyajanga)

<details>
<summary>Changes</summary>

 Context:
 
 This is part PR#<!-- -->2 of a PR stack adding dynamic loader support for 
accelerator (GPU) targets to lldb:

 Relevant Parallel PR:
  1. **#<!-- -->214873** — `[lldb] Support loading an object file that is a 
slice of another file`
    
  
This and   **#<!-- -->214873** are needed for **#<!-- -->214581**

In this PR we are adding the protocol foundation for the dyld
- Added handling of new GDB Remote packet 
`jAcceleratorPluginGetDynamicLoaderLibraryInfo` and testing it with the Mock 
Server Plugin




---
Full diff: https://github.com/llvm/llvm-project/pull/214564.diff


12 Files Affected:

- (modified) lldb/docs/resources/lldbgdbremote.md (+34) 
- (modified) lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h (+54) 
- (modified) lldb/include/lldb/Utility/StringExtractorGDBRemote.h (+1) 
- (modified) 
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp 
(+33) 
- (modified) 
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (+3) 
- (modified) 
lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h (+5) 
- (modified) lldb/source/Utility/AcceleratorGDBRemotePackets.cpp (+59) 
- (modified) lldb/source/Utility/StringExtractorGDBRemote.cpp (+2) 
- (modified) lldb/test/API/accelerator/mock/TestMockAcceleratorPackets.py (+25) 
- (modified) 
lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp
 (+12) 
- (modified) 
lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h
 (+3) 
- (modified) lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp (+81) 


``````````diff
diff --git a/lldb/docs/resources/lldbgdbremote.md 
b/lldb/docs/resources/lldbgdbremote.md
index 93090c19c5ec0..56885f4117629 100644
--- a/lldb/docs/resources/lldbgdbremote.md
+++ b/lldb/docs/resources/lldbgdbremote.md
@@ -2862,3 +2862,37 @@ STUB REPLIES:  
{"disable_bp":true,"auto_resume_native":false,"actions":{"plugin_
 
 **Priority To Implement:** Required for hardware accelerator debugging
 support. Not needed for non-hardware-accelerator debugging.
+
+### jAcceleratorPluginGetDynamicLoaderLibraryInfo
+
+Requests shared library information from an accelerator plugin. The client
+sends this packet when it needs to load or update the accelerator's shared
+library list. This packet requires the `accelerator-plugins+` feature from
+`qSupported`.
+
+```
+LLDB SENDS:    jAcceleratorPluginGetDynamicLoaderLibraryInfo:<json>
+STUB REPLIES:  <json_response>
+```
+
+The request JSON has the following fields:
+
+| Key           | Type   | Description |
+|---------------|--------|-------------|
+| `plugin_name` | string | Name of the accelerator plugin to query. |
+| `full`        | bool   | If true, return all libraries. If false, return 
only updates since the last query. |
+
+The response JSON has the following fields:
+
+| Key             | Type  | Description |
+|-----------------|-------|-------------|
+| `library_infos` | array | Array of library info objects, each with 
`pathname`, `load` (bool), and optional `load_address`, `loaded_sections`, 
`uuid`, `native_memory_address`, `native_memory_size`, `file_offset`, 
`file_size`. |
+
+Example:
+```
+LLDB SENDS:    
jAcceleratorPluginGetDynamicLoaderLibraryInfo:{"plugin_name":"mock","full":true}
+STUB REPLIES:  
{"library_infos":[{"pathname":"/usr/lib/libmock_accel.so","load":true,"load_address":2130706432,"loaded_sections":[]}]}
+```
+
+**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 faa7f5575f157..9964580c16469 100644
--- a/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h
+++ b/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h
@@ -166,6 +166,60 @@ bool fromJSON(const llvm::json::Value &value,
               AcceleratorBreakpointHitResponse &data, llvm::json::Path path);
 llvm::json::Value toJSON(const AcceleratorBreakpointHitResponse &data);
 
+struct AcceleratorSectionInfo {
+  /// Each name is looked up as a child of the previous one, e.g.
+  /// ["PT_LOAD[0]", ".text"].
+  std::vector<std::string> names;
+  uint64_t load_address = 0;
+};
+
+bool fromJSON(const llvm::json::Value &value, AcceleratorSectionInfo &data,
+              llvm::json::Path path);
+llvm::json::Value toJSON(const AcceleratorSectionInfo &data);
+
+struct AcceleratorDynamicLoaderLibraryInfo {
+  std::string pathname;
+  std::optional<std::string> uuid_str;
+  /// False means unload.
+  bool load = true;
+  /// Slides the whole object file. If unset, use \a loaded_sections or the
+  /// file addresses.
+  std::optional<uint64_t> load_address;
+  /// Used when sections load at independent addresses.
+  std::vector<AcceleratorSectionInfo> loaded_sections;
+  /// Where the image can be read in the native process.
+  std::optional<uint64_t> native_memory_address;
+  std::optional<uint64_t> native_memory_size;
+  /// Slice of \a pathname holding the object file, when embedded in a
+  /// container.
+  std::optional<uint64_t> file_offset;
+  std::optional<uint64_t> file_size;
+};
+
+bool fromJSON(const llvm::json::Value &value,
+              AcceleratorDynamicLoaderLibraryInfo &data, llvm::json::Path 
path);
+llvm::json::Value toJSON(const AcceleratorDynamicLoaderLibraryInfo &data);
+
+/// Arguments for the jAcceleratorPluginGetDynamicLoaderLibraryInfo packet.
+struct AcceleratorDynamicLoaderArgs {
+  std::string plugin_name;
+  /// If false, return only updates since the last query.
+  bool full = true;
+};
+
+bool fromJSON(const llvm::json::Value &value,
+              AcceleratorDynamicLoaderArgs &data, llvm::json::Path path);
+llvm::json::Value toJSON(const AcceleratorDynamicLoaderArgs &data);
+
+/// Response from the jAcceleratorPluginGetDynamicLoaderLibraryInfo packet.
+struct AcceleratorDynamicLoaderResponse {
+  std::vector<AcceleratorDynamicLoaderLibraryInfo> library_infos;
+};
+
+bool fromJSON(const llvm::json::Value &value,
+              AcceleratorDynamicLoaderResponse &data, llvm::json::Path path);
+llvm::json::Value toJSON(const AcceleratorDynamicLoaderResponse &data);
+
 } // namespace lldb_private
 
 #endif // LLDB_UTILITY_ACCELERATORGDBREMOTEPACKETS_H
diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h 
b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
index 624a2febe857e..0236891dfcde1 100644
--- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
+++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -176,6 +176,7 @@ class StringExtractorGDBRemote : public StringExtractor {
     eServerPacketType_jMultiBreakpoint,
     eServerPacketType_jAcceleratorPluginInitialize,
     eServerPacketType_jAcceleratorPluginBreakpointHit,
+    eServerPacketType_jAcceleratorPluginGetDynamicLoaderLibraryInfo,
 
     eServerPacketType_qMemTags, // read memory tags
     eServerPacketType_QMemTags, // write memory tags
diff --git 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 2e824282079b4..791c02fd96b20 100644
--- 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -233,6 +233,11 @@ void 
GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
           eServerPacketType_jAcceleratorPluginBreakpointHit,
       &GDBRemoteCommunicationServerLLGS::
           Handle_jAcceleratorPluginBreakpointHit);
+  RegisterMemberFunctionHandler(
+      StringExtractorGDBRemote::
+          eServerPacketType_jAcceleratorPluginGetDynamicLoaderLibraryInfo,
+      &GDBRemoteCommunicationServerLLGS::
+          Handle_jAcceleratorPluginGetDynamicLoaderLibraryInfo);
 
   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
                                 &GDBRemoteCommunicationServerLLGS::Handle_g);
@@ -4643,3 +4648,31 @@ 
GDBRemoteCommunicationServerLLGS::Handle_jAcceleratorPluginBreakpointHit(
   return SendErrorResponse(
       Status::FromErrorString("unknown accelerator plugin name"));
 }
+
+GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::
+    Handle_jAcceleratorPluginGetDynamicLoaderLibraryInfo(
+        StringExtractorGDBRemote &packet) {
+  packet.ConsumeFront("jAcceleratorPluginGetDynamicLoaderLibraryInfo:");
+  llvm::Expected<AcceleratorDynamicLoaderArgs> args =
+      llvm::json::parse<AcceleratorDynamicLoaderArgs>(
+          packet.Peek(), "AcceleratorDynamicLoaderArgs");
+  if (!args)
+    return SendErrorResponse(args.takeError());
+
+  for (std::unique_ptr<lldb_server::LLDBServerAcceleratorPlugin> &plugin_up :
+       m_accelerator_plugins) {
+    if (plugin_up->GetPluginName() == args->plugin_name) {
+      std::optional<AcceleratorDynamicLoaderResponse> response =
+          plugin_up->GetDynamicLoaderLibraryInfos(*args);
+      if (response) {
+        StreamGDBRemote stream;
+        stream.PutAsJSON(*response, /*hex_ascii=*/false);
+        return SendPacketNoLock(stream.GetString());
+      }
+      return SendErrorResponse(
+          Status::FromErrorString("no dynamic loader info available"));
+    }
+  }
+  return SendErrorResponse(
+      Status::FromErrorString("unknown accelerator plugin name"));
+}
diff --git 
a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h 
b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index e5b4c9ec0bed0..3c8afe699bbaf 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -302,6 +302,9 @@ class GDBRemoteCommunicationServerLLGS
   PacketResult
   Handle_jAcceleratorPluginBreakpointHit(StringExtractorGDBRemote &packet);
 
+  PacketResult Handle_jAcceleratorPluginGetDynamicLoaderLibraryInfo(
+      StringExtractorGDBRemote &packet);
+
   void SetCurrentThreadID(lldb::tid_t tid);
 
   lldb::tid_t GetCurrentThreadID() const;
diff --git 
a/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h 
b/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h
index f16ee82a39d95..2e585d9a64c6a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h
+++ b/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h
@@ -47,6 +47,11 @@ class LLDBServerAcceleratorPlugin {
                               ++m_accelerator_action_identifier);
   }
 
+  virtual std::optional<AcceleratorDynamicLoaderResponse>
+  GetDynamicLoaderLibraryInfos(const AcceleratorDynamicLoaderArgs &args) {
+    return std::nullopt;
+  }
+
 protected:
   GDBServer &m_native_gdb_server;
   MainLoop &m_native_main_loop;
diff --git a/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp 
b/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp
index 3b9edada64c65..180b2121c6155 100644
--- a/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp
+++ b/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp
@@ -142,4 +142,63 @@ json::Value toJSON(const AcceleratorBreakpointHitResponse 
&data) {
   return obj;
 }
 
+bool fromJSON(const Value &value, AcceleratorSectionInfo &data, Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("names", data.names) &&
+         o.map("load_address", data.load_address);
+}
+
+json::Value toJSON(const AcceleratorSectionInfo &data) {
+  return Object{{"names", data.names},
+                {"load_address", static_cast<int64_t>(data.load_address)}};
+}
+
+bool fromJSON(const Value &value, AcceleratorDynamicLoaderLibraryInfo &data,
+              Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("pathname", data.pathname) &&
+         o.mapOptional("uuid", data.uuid_str) && o.map("load", data.load) &&
+         o.mapOptional("load_address", data.load_address) &&
+         o.mapOptional("loaded_sections", data.loaded_sections) &&
+         o.mapOptional("native_memory_address", data.native_memory_address) &&
+         o.mapOptional("native_memory_size", data.native_memory_size) &&
+         o.mapOptional("file_offset", data.file_offset) &&
+         o.mapOptional("file_size", data.file_size);
+}
+
+json::Value toJSON(const AcceleratorDynamicLoaderLibraryInfo &data) {
+  return Object{
+      {"pathname", data.pathname},
+      {"uuid", data.uuid_str},
+      {"load", data.load},
+      {"load_address", data.load_address},
+      {"loaded_sections", data.loaded_sections},
+      {"native_memory_address", data.native_memory_address},
+      {"native_memory_size", data.native_memory_size},
+      {"file_offset", data.file_offset},
+      {"file_size", data.file_size},
+  };
+}
+
+bool fromJSON(const Value &value, AcceleratorDynamicLoaderArgs &data,
+              Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("plugin_name", data.plugin_name) &&
+         o.map("full", data.full);
+}
+
+json::Value toJSON(const AcceleratorDynamicLoaderArgs &data) {
+  return Object{{"plugin_name", data.plugin_name}, {"full", data.full}};
+}
+
+bool fromJSON(const Value &value, AcceleratorDynamicLoaderResponse &data,
+              Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("library_infos", data.library_infos);
+}
+
+json::Value toJSON(const AcceleratorDynamicLoaderResponse &data) {
+  return Object{{"library_infos", data.library_infos}};
+}
+
 } // namespace lldb_private
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp 
b/lldb/source/Utility/StringExtractorGDBRemote.cpp
index 6fc3b63e02dd1..953a2cd3090d1 100644
--- a/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -338,6 +338,8 @@ StringExtractorGDBRemote::GetServerPacketType() const {
       return eServerPacketType_jAcceleratorPluginInitialize;
     if (PACKET_STARTS_WITH("jAcceleratorPluginBreakpointHit:"))
       return eServerPacketType_jAcceleratorPluginBreakpointHit;
+    if (PACKET_STARTS_WITH("jAcceleratorPluginGetDynamicLoaderLibraryInfo:"))
+      return eServerPacketType_jAcceleratorPluginGetDynamicLoaderLibraryInfo;
     break;
 
   case 'v':
diff --git a/lldb/test/API/accelerator/mock/TestMockAcceleratorPackets.py 
b/lldb/test/API/accelerator/mock/TestMockAcceleratorPackets.py
index 941e0c97a8f2e..865fd590e745f 100644
--- a/lldb/test/API/accelerator/mock/TestMockAcceleratorPackets.py
+++ b/lldb/test/API/accelerator/mock/TestMockAcceleratorPackets.py
@@ -186,3 +186,28 @@ def 
test_jAcceleratorPluginBreakpointHit_returns_connect_info(self):
             connect_info["connect_url"],
         )
         self.assertTrue(connect_info["synchronous"])
+
+    @add_test_categories(["llgs"])
+    def test_jAcceleratorPluginGetDynamicLoaderLibraryInfo(self):
+        self.build()
+        self.set_inferior_startup_launch()
+        self.prep_debug_monitor_and_inferior()
+
+        self.add_qSupported_packets()
+        self.expect_gdbremote_sequence()
+
+        dyld_args = {"plugin_name": "mock", "full": True}
+        dyld_json = json.dumps(dyld_args, separators=(",", ":"))
+        escaped_json = escape_binary(dyld_json)
+        response = self.send_and_decode_json(
+            "jAcceleratorPluginGetDynamicLoaderLibraryInfo:" + escaped_json
+        )
+
+        self.assertIn("library_infos", response)
+        libs = response["library_infos"]
+        self.assertGreater(len(libs), 0)
+
+        lib = libs[0]
+        self.assertEqual(lib["pathname"], "/path/to/lib.so")
+        self.assertTrue(lib["load"])
+        self.assertEqual(lib["load_address"], 0x7F000000)
diff --git 
a/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp
 
b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp
index 6c1d23fef8a71..0cce2955f6e0d 100644
--- 
a/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp
+++ 
b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp
@@ -220,3 +220,15 @@ LLDBServerMockAcceleratorPlugin::CreateConnection() {
   info.synchronous = true;
   return info;
 }
+
+std::optional<AcceleratorDynamicLoaderResponse>
+LLDBServerMockAcceleratorPlugin::GetDynamicLoaderLibraryInfos(
+    const AcceleratorDynamicLoaderArgs &args) {
+  AcceleratorDynamicLoaderResponse response;
+  AcceleratorDynamicLoaderLibraryInfo lib;
+  lib.pathname = "/path/to/lib.so";
+  lib.load = true;
+  lib.load_address = 0x7f000000;
+  response.library_infos.push_back(std::move(lib));
+  return response;
+}
diff --git 
a/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h
 
b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h
index b07266d0ef65f..36f6aa2500ba8 100644
--- 
a/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h
+++ 
b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h
@@ -34,6 +34,9 @@ class LLDBServerMockAcceleratorPlugin : public 
LLDBServerAcceleratorPlugin {
   llvm::Expected<AcceleratorBreakpointHitResponse>
   BreakpointWasHit(AcceleratorBreakpointHitArgs &args) override;
 
+  std::optional<AcceleratorDynamicLoaderResponse> GetDynamicLoaderLibraryInfos(
+      const AcceleratorDynamicLoaderArgs &args) override;
+
 private:
   // Lazily bring up the mock accelerator GDB server and return its connection
   // info. Called on the connection breakpoint hit, so inferiors that never
diff --git a/lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp 
b/lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp
index 571dd2cab124a..8d64b4a8acf78 100644
--- a/lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp
+++ b/lldb/unittests/Utility/AcceleratorGDBRemotePacketsTest.cpp
@@ -244,3 +244,84 @@ TEST(AcceleratorGDBRemotePacketsTest, 
AcceleratorActionsWithoutConnectInfo) {
   ASSERT_THAT_EXPECTED(deserialized, Succeeded());
   EXPECT_FALSE(deserialized->connect_info.has_value());
 }
+
+TEST(AcceleratorGDBRemotePacketsTest, AcceleratorSectionInfo) {
+  AcceleratorSectionInfo section;
+  section.names = {"PT_LOAD[0]", ".text"};
+  section.load_address = 0x400000;
+
+  Expected<AcceleratorSectionInfo> deserialized = roundtripJSON(section);
+  ASSERT_THAT_EXPECTED(deserialized, Succeeded());
+  EXPECT_EQ(section.names, deserialized->names);
+  EXPECT_EQ(section.load_address, deserialized->load_address);
+}
+
+TEST(AcceleratorGDBRemotePacketsTest, AcceleratorDynamicLoaderLibraryInfo) {
+  AcceleratorDynamicLoaderLibraryInfo lib;
+  lib.pathname = "/usr/lib/libgpu.so";
+  lib.uuid_str = "AABBCCDD";
+  lib.load = true;
+  lib.load_address = 0x7f000000;
+  lib.native_memory_address = 0x1000;
+  lib.native_memory_size = 0x2000;
+  lib.file_offset = 4096;
+  lib.file_size = 8192;
+
+  AcceleratorSectionInfo section;
+  section.names = {".text"};
+  section.load_address = 0x7f001000;
+  lib.loaded_sections.push_back(std::move(section));
+
+  Expected<AcceleratorDynamicLoaderLibraryInfo> deserialized =
+      roundtripJSON(lib);
+  ASSERT_THAT_EXPECTED(deserialized, Succeeded());
+  EXPECT_EQ(lib.pathname, deserialized->pathname);
+  EXPECT_EQ(lib.uuid_str, deserialized->uuid_str);
+  EXPECT_EQ(lib.load, deserialized->load);
+  EXPECT_EQ(lib.load_address, deserialized->load_address);
+  EXPECT_EQ(lib.native_memory_address, deserialized->native_memory_address);
+  EXPECT_EQ(lib.native_memory_size, deserialized->native_memory_size);
+  EXPECT_EQ(lib.file_offset, deserialized->file_offset);
+  EXPECT_EQ(lib.file_size, deserialized->file_size);
+  ASSERT_EQ(1u, deserialized->loaded_sections.size());
+  EXPECT_EQ(0x7f001000u, deserialized->loaded_sections[0].load_address);
+}
+
+TEST(AcceleratorGDBRemotePacketsTest, AcceleratorDynamicLoaderArgs) {
+  AcceleratorDynamicLoaderArgs args;
+  args.plugin_name = "mock";
+  args.full = true;
+
+  Expected<AcceleratorDynamicLoaderArgs> deserialized = roundtripJSON(args);
+  ASSERT_THAT_EXPECTED(deserialized, Succeeded());
+  EXPECT_EQ(args.plugin_name, deserialized->plugin_name);
+  EXPECT_EQ(args.full, deserialized->full);
+}
+
+TEST(AcceleratorGDBRemotePacketsTest, AcceleratorDynamicLoaderResponse) {
+  AcceleratorDynamicLoaderResponse response;
+  AcceleratorDynamicLoaderLibraryInfo lib;
+  lib.pathname = "/path/to/lib.so";
+  lib.load = true;
+  response.library_infos.push_back(std::move(lib));
+
+  Expected<AcceleratorDynamicLoaderResponse> deserialized =
+      roundtripJSON(response);
+  ASSERT_THAT_EXPECTED(deserialized, Succeeded());
+  ASSERT_EQ(1u, deserialized->library_infos.size());
+  EXPECT_EQ("/path/to/lib.so", deserialized->library_infos[0].pathname);
+  EXPECT_TRUE(deserialized->library_infos[0].load);
+}
+
+TEST(AcceleratorGDBRemotePacketsTest, DynamicLoaderLibraryInfoOptionalFields) {
+  // A server with no per-section addresses can omit "loaded_sections".
+  Expected<AcceleratorDynamicLoaderLibraryInfo> deserialized =
+      json::parse<AcceleratorDynamicLoaderLibraryInfo>(
+          R"({"pathname":"/path/to/lib.so","load":true})",
+          "AcceleratorDynamicLoaderLibraryInfo");
+  ASSERT_THAT_EXPECTED(deserialized, Succeeded());
+  EXPECT_EQ("/path/to/lib.so", deserialized->pathname);
+  EXPECT_TRUE(deserialized->load);
+  EXPECT_TRUE(deserialized->loaded_sections.empty());
+  EXPECT_FALSE(deserialized->load_address.has_value());
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/214564
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to