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