Author: Matej Košík Date: 2026-02-24T13:08:04Z New Revision: 75383421c1c6b8a33e762b42b83242dbd85e466e
URL: https://github.com/llvm/llvm-project/commit/75383421c1c6b8a33e762b42b83242dbd85e466e DIFF: https://github.com/llvm/llvm-project/commit/75383421c1c6b8a33e762b42b83242dbd85e466e.diff LOG: [lldb] generalize the GDBRemoteCommunicationClient::GetVContSupported method (#182287) This is a conservative generalization of the `GDBRemoteCommunicationClient::GetVContSupported` method so that: - the new version of this method handles the reply to the `vCont?` packet the same way as the original version of this method - the new version of this method can be easily adapted to situation when the actions are represented by multiple letters. Imagine that, in addition to the [existing actions](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Packets.html#vCont-packet): - `c` - `C` - `s` - `S` - `t` - `r` the other party would also advertise that it supports (e.g.) `sc` action (meaning e.g. that we can ask the other party to step into microcode). The new version of this method can be easily adapted to handle such a case without compromising correct handling of the original actions represented by single characters. --------- Co-authored-by: Matej Košík <[email protected]> Co-authored-by: Jonas Devlieghere <[email protected]> Added: Modified: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp Removed: ################################################################################ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 11f164c2426ce..738e4013b6154 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -480,7 +480,9 @@ bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() { } return m_supports_thread_suffix; } -bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { + +bool GDBRemoteCommunicationClient::GetVContSupported(llvm::StringRef flavor) { + assert(!flavor.empty()); if (m_supports_vCont_c == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_vCont_any = eLazyBoolNo; @@ -491,18 +493,16 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { m_supports_vCont_S = eLazyBoolNo; if (SendPacketAndWaitForResponse("vCont?", response) == PacketResult::Success) { - const char *response_cstr = response.GetStringRef().data(); - if (::strstr(response_cstr, ";c")) - m_supports_vCont_c = eLazyBoolYes; - - if (::strstr(response_cstr, ";C")) - m_supports_vCont_C = eLazyBoolYes; - - if (::strstr(response_cstr, ";s")) - m_supports_vCont_s = eLazyBoolYes; - - if (::strstr(response_cstr, ";S")) - m_supports_vCont_S = eLazyBoolYes; + for (llvm::StringRef token : llvm::split(response.GetStringRef(), ';')) { + if (token == "c") + m_supports_vCont_c = eLazyBoolYes; + if (token == "C") + m_supports_vCont_C = eLazyBoolYes; + if (token == "s") + m_supports_vCont_s = eLazyBoolYes; + if (token == "S") + m_supports_vCont_S = eLazyBoolYes; + } if (m_supports_vCont_c == eLazyBoolYes && m_supports_vCont_C == eLazyBoolYes && @@ -520,23 +520,14 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { } } - switch (flavor) { - case 'a': - return m_supports_vCont_any; - case 'A': - return m_supports_vCont_all; - case 'c': - return m_supports_vCont_c; - case 'C': - return m_supports_vCont_C; - case 's': - return m_supports_vCont_s; - case 'S': - return m_supports_vCont_S; - default: - break; - } - return false; + return llvm::StringSwitch<bool>(flavor) + .Case("a", m_supports_vCont_any) + .Case("A", m_supports_vCont_all) + .Case("c", m_supports_vCont_c) + .Case("C", m_supports_vCont_C) + .Case("s", m_supports_vCont_s) + .Case("S", m_supports_vCont_S) + .Default(false); } GDBRemoteCommunication::PacketResult diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index ad590a25d0f16..d04f6370bb6ae 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -214,7 +214,7 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { void GetRemoteQSupported(); - bool GetVContSupported(char flavor); + bool GetVContSupported(llvm::StringRef flavor); bool GetpPacketSupported(lldb::tid_t tid); @@ -262,9 +262,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { bool GetGroupName(uint32_t gid, std::string &name); - bool HasFullVContSupport() { return GetVContSupported('A'); } + bool HasFullVContSupport() { return GetVContSupported("A"); } - bool HasAnyVContSupport() { return GetVContSupported('a'); } + bool HasAnyVContSupport() { return GetVContSupported("a"); } bool GetStopReply(StringExtractorGDBRemote &response); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 57d86ef71eecc..75b28f90d08b8 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -925,7 +925,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { m_gdb_comm.GetThreadSuffixSupported(); m_gdb_comm.GetListThreadsInStopReplySupported(); m_gdb_comm.GetHostInfo(); - m_gdb_comm.GetVContSupported('c'); + m_gdb_comm.GetVContSupported("c"); m_gdb_comm.GetVAttachOrWaitSupported(); m_gdb_comm.EnableErrorStringInPacket(); @@ -1305,7 +1305,7 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) { continue_packet.PutCString("vCont"); if (!m_continue_c_tids.empty()) { - if (m_gdb_comm.GetVContSupported('c')) { + if (m_gdb_comm.GetVContSupported("c")) { for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); @@ -1316,7 +1316,7 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) { } if (!continue_packet_error && !m_continue_C_tids.empty()) { - if (m_gdb_comm.GetVContSupported('C')) { + if (m_gdb_comm.GetVContSupported("C")) { for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); @@ -1328,7 +1328,7 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) { } if (!continue_packet_error && !m_continue_s_tids.empty()) { - if (m_gdb_comm.GetVContSupported('s')) { + if (m_gdb_comm.GetVContSupported("s")) { for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); @@ -1339,7 +1339,7 @@ Status ProcessGDBRemote::DoResume(RunDirection direction) { } if (!continue_packet_error && !m_continue_S_tids.empty()) { - if (m_gdb_comm.GetVContSupported('S')) { + if (m_gdb_comm.GetVContSupported("S")) { for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp index 966b37e09ee55..a5156326a1447 100644 --- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -77,6 +77,54 @@ class GDBRemoteCommunicationClientTest : public GDBRemoteTest { MockServer server; }; +TEST_F(GDBRemoteCommunicationClientTest, vCont_c) { + std::future<bool> write_result = std::async( + std::launch::async, [&] { return client.GetVContSupported("c"); }); + HandlePacket(server, "vCont?", "$vCont;c#16"); + ASSERT_TRUE(write_result.get()); + ASSERT_FALSE(client.GetVContSupported("C")); + ASSERT_FALSE(client.GetVContSupported("s")); + ASSERT_FALSE(client.GetVContSupported("S")); + ASSERT_TRUE(client.GetVContSupported("a")); + ASSERT_FALSE(client.GetVContSupported("A")); +} + +TEST_F(GDBRemoteCommunicationClientTest, vCont_C) { + std::future<bool> write_result = std::async( + std::launch::async, [&] { return client.GetVContSupported("c"); }); + HandlePacket(server, "vCont?", "$vCont;C#16"); + ASSERT_FALSE(write_result.get()); + ASSERT_TRUE(client.GetVContSupported("C")); + ASSERT_FALSE(client.GetVContSupported("s")); + ASSERT_FALSE(client.GetVContSupported("S")); + ASSERT_TRUE(client.GetVContSupported("a")); + ASSERT_FALSE(client.GetVContSupported("A")); +} + +TEST_F(GDBRemoteCommunicationClientTest, vCont_c_C) { + std::future<bool> write_result = std::async( + std::launch::async, [&] { return client.GetVContSupported("c"); }); + HandlePacket(server, "vCont?", "$vCont;c;C#16"); + ASSERT_TRUE(write_result.get()); + ASSERT_TRUE(client.GetVContSupported("C")); + ASSERT_FALSE(client.GetVContSupported("s")); + ASSERT_FALSE(client.GetVContSupported("S")); + ASSERT_TRUE(client.GetVContSupported("a")); + ASSERT_FALSE(client.GetVContSupported("A")); +} + +TEST_F(GDBRemoteCommunicationClientTest, vCont_cC_notAFeature) { + std::future<bool> write_result = std::async( + std::launch::async, [&] { return client.GetVContSupported("c"); }); + HandlePacket(server, "vCont?", "$vCont;cC;notAFeature#16"); + ASSERT_FALSE(write_result.get()); + ASSERT_FALSE(client.GetVContSupported("C")); + ASSERT_FALSE(client.GetVContSupported("s")); + ASSERT_FALSE(client.GetVContSupported("S")); + ASSERT_FALSE(client.GetVContSupported("a")); + ASSERT_FALSE(client.GetVContSupported("A")); +} + TEST_F(GDBRemoteCommunicationClientTest, WriteRegister) { const lldb::tid_t tid = 0x47; const uint32_t reg_num = 4; _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
