xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- GDBRemoteCommunicationClient.cpp ----------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "GDBRemoteCommunicationClient.h"
10061da546Spatrick 
11be691f3bSpatrick #include <cmath>
12061da546Spatrick #include <sys/stat.h>
13061da546Spatrick 
14061da546Spatrick #include <numeric>
15*f6aab3d8Srobert #include <optional>
16061da546Spatrick #include <sstream>
17061da546Spatrick 
18061da546Spatrick #include "lldb/Core/ModuleSpec.h"
19061da546Spatrick #include "lldb/Host/HostInfo.h"
20061da546Spatrick #include "lldb/Host/XML.h"
21061da546Spatrick #include "lldb/Symbol/Symbol.h"
22061da546Spatrick #include "lldb/Target/MemoryRegionInfo.h"
23061da546Spatrick #include "lldb/Target/Target.h"
24061da546Spatrick #include "lldb/Target/UnixSignals.h"
25061da546Spatrick #include "lldb/Utility/Args.h"
26061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
27061da546Spatrick #include "lldb/Utility/LLDBAssert.h"
28*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
29061da546Spatrick #include "lldb/Utility/Log.h"
30061da546Spatrick #include "lldb/Utility/State.h"
31061da546Spatrick #include "lldb/Utility/StreamString.h"
32061da546Spatrick 
33061da546Spatrick #include "ProcessGDBRemote.h"
34061da546Spatrick #include "ProcessGDBRemoteLog.h"
35061da546Spatrick #include "lldb/Host/Config.h"
36061da546Spatrick #include "lldb/Utility/StringExtractorGDBRemote.h"
37061da546Spatrick 
38061da546Spatrick #include "llvm/ADT/StringSwitch.h"
39061da546Spatrick #include "llvm/Support/JSON.h"
40061da546Spatrick 
41061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
42061da546Spatrick #include <compression.h>
43061da546Spatrick #endif
44061da546Spatrick 
45061da546Spatrick using namespace lldb;
46061da546Spatrick using namespace lldb_private::process_gdb_remote;
47061da546Spatrick using namespace lldb_private;
48061da546Spatrick using namespace std::chrono;
49061da546Spatrick 
operator <<(llvm::raw_ostream & os,const QOffsets & offsets)50dda28197Spatrick llvm::raw_ostream &process_gdb_remote::operator<<(llvm::raw_ostream &os,
51dda28197Spatrick                                                   const QOffsets &offsets) {
52dda28197Spatrick   return os << llvm::formatv(
53dda28197Spatrick              "QOffsets({0}, [{1:@[x]}])", offsets.segments,
54dda28197Spatrick              llvm::make_range(offsets.offsets.begin(), offsets.offsets.end()));
55dda28197Spatrick }
56dda28197Spatrick 
57061da546Spatrick // GDBRemoteCommunicationClient constructor
GDBRemoteCommunicationClient()58061da546Spatrick GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
59*f6aab3d8Srobert     : GDBRemoteClientBase("gdb-remote.client"),
60be691f3bSpatrick 
61061da546Spatrick       m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
62061da546Spatrick       m_supports_qUserName(true), m_supports_qGroupName(true),
63061da546Spatrick       m_supports_qThreadStopInfo(true), m_supports_z0(true),
64061da546Spatrick       m_supports_z1(true), m_supports_z2(true), m_supports_z3(true),
65061da546Spatrick       m_supports_z4(true), m_supports_QEnvironment(true),
66061da546Spatrick       m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true),
67061da546Spatrick       m_qSymbol_requests_done(false), m_supports_qModuleInfo(true),
68061da546Spatrick       m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true),
69*f6aab3d8Srobert       m_supports_vFileSize(true), m_supports_vFileMode(true),
70*f6aab3d8Srobert       m_supports_vFileExists(true), m_supports_vRun(true),
71be691f3bSpatrick 
72be691f3bSpatrick       m_host_arch(), m_process_arch(), m_os_build(), m_os_kernel(),
73be691f3bSpatrick       m_hostname(), m_gdb_server_name(), m_default_packet_timeout(0),
74be691f3bSpatrick       m_qSupported_response(), m_supported_async_json_packets_sp(),
75be691f3bSpatrick       m_qXfer_memory_map() {}
76061da546Spatrick 
77061da546Spatrick // Destructor
~GDBRemoteCommunicationClient()78061da546Spatrick GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
79061da546Spatrick   if (IsConnected())
80061da546Spatrick     Disconnect();
81061da546Spatrick }
82061da546Spatrick 
HandshakeWithServer(Status * error_ptr)83061da546Spatrick bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
84061da546Spatrick   ResetDiscoverableSettings(false);
85061da546Spatrick 
86061da546Spatrick   // Start the read thread after we send the handshake ack since if we fail to
87061da546Spatrick   // send the handshake ack, there is no reason to continue...
88*f6aab3d8Srobert   std::chrono::steady_clock::time_point start_of_handshake =
89*f6aab3d8Srobert       std::chrono::steady_clock::now();
90061da546Spatrick   if (SendAck()) {
91061da546Spatrick     // The return value from QueryNoAckModeSupported() is true if the packet
92061da546Spatrick     // was sent and _any_ response (including UNIMPLEMENTED) was received), or
93061da546Spatrick     // false if no response was received. This quickly tells us if we have a
94061da546Spatrick     // live connection to a remote GDB server...
95061da546Spatrick     if (QueryNoAckModeSupported()) {
96061da546Spatrick       return true;
97061da546Spatrick     } else {
98*f6aab3d8Srobert       std::chrono::steady_clock::time_point end_of_handshake =
99*f6aab3d8Srobert           std::chrono::steady_clock::now();
100*f6aab3d8Srobert       auto handshake_timeout =
101*f6aab3d8Srobert           std::chrono::duration<double>(end_of_handshake - start_of_handshake)
102*f6aab3d8Srobert               .count();
103*f6aab3d8Srobert       if (error_ptr) {
104*f6aab3d8Srobert         if (!IsConnected())
105*f6aab3d8Srobert           error_ptr->SetErrorString("Connection shut down by remote side "
106*f6aab3d8Srobert                                     "while waiting for reply to initial "
107*f6aab3d8Srobert                                     "handshake packet");
108*f6aab3d8Srobert         else
109*f6aab3d8Srobert           error_ptr->SetErrorStringWithFormat(
110*f6aab3d8Srobert               "failed to get reply to handshake packet within timeout of "
111*f6aab3d8Srobert               "%.1f seconds",
112*f6aab3d8Srobert               handshake_timeout);
113*f6aab3d8Srobert       }
114061da546Spatrick     }
115061da546Spatrick   } else {
116061da546Spatrick     if (error_ptr)
117061da546Spatrick       error_ptr->SetErrorString("failed to send the handshake ack");
118061da546Spatrick   }
119061da546Spatrick   return false;
120061da546Spatrick }
121061da546Spatrick 
GetEchoSupported()122061da546Spatrick bool GDBRemoteCommunicationClient::GetEchoSupported() {
123061da546Spatrick   if (m_supports_qEcho == eLazyBoolCalculate) {
124061da546Spatrick     GetRemoteQSupported();
125061da546Spatrick   }
126061da546Spatrick   return m_supports_qEcho == eLazyBoolYes;
127061da546Spatrick }
128061da546Spatrick 
GetQPassSignalsSupported()129061da546Spatrick bool GDBRemoteCommunicationClient::GetQPassSignalsSupported() {
130061da546Spatrick   if (m_supports_QPassSignals == eLazyBoolCalculate) {
131061da546Spatrick     GetRemoteQSupported();
132061da546Spatrick   }
133061da546Spatrick   return m_supports_QPassSignals == eLazyBoolYes;
134061da546Spatrick }
135061da546Spatrick 
GetAugmentedLibrariesSVR4ReadSupported()136061da546Spatrick bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() {
137061da546Spatrick   if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) {
138061da546Spatrick     GetRemoteQSupported();
139061da546Spatrick   }
140061da546Spatrick   return m_supports_augmented_libraries_svr4_read == eLazyBoolYes;
141061da546Spatrick }
142061da546Spatrick 
GetQXferLibrariesSVR4ReadSupported()143061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported() {
144061da546Spatrick   if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) {
145061da546Spatrick     GetRemoteQSupported();
146061da546Spatrick   }
147061da546Spatrick   return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes;
148061da546Spatrick }
149061da546Spatrick 
GetQXferLibrariesReadSupported()150061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported() {
151061da546Spatrick   if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) {
152061da546Spatrick     GetRemoteQSupported();
153061da546Spatrick   }
154061da546Spatrick   return m_supports_qXfer_libraries_read == eLazyBoolYes;
155061da546Spatrick }
156061da546Spatrick 
GetQXferAuxvReadSupported()157061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferAuxvReadSupported() {
158061da546Spatrick   if (m_supports_qXfer_auxv_read == eLazyBoolCalculate) {
159061da546Spatrick     GetRemoteQSupported();
160061da546Spatrick   }
161061da546Spatrick   return m_supports_qXfer_auxv_read == eLazyBoolYes;
162061da546Spatrick }
163061da546Spatrick 
GetQXferFeaturesReadSupported()164061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() {
165061da546Spatrick   if (m_supports_qXfer_features_read == eLazyBoolCalculate) {
166061da546Spatrick     GetRemoteQSupported();
167061da546Spatrick   }
168061da546Spatrick   return m_supports_qXfer_features_read == eLazyBoolYes;
169061da546Spatrick }
170061da546Spatrick 
GetQXferMemoryMapReadSupported()171061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
172061da546Spatrick   if (m_supports_qXfer_memory_map_read == eLazyBoolCalculate) {
173061da546Spatrick     GetRemoteQSupported();
174061da546Spatrick   }
175061da546Spatrick   return m_supports_qXfer_memory_map_read == eLazyBoolYes;
176061da546Spatrick }
177061da546Spatrick 
GetQXferSigInfoReadSupported()178*f6aab3d8Srobert bool GDBRemoteCommunicationClient::GetQXferSigInfoReadSupported() {
179*f6aab3d8Srobert   if (m_supports_qXfer_siginfo_read == eLazyBoolCalculate) {
180*f6aab3d8Srobert     GetRemoteQSupported();
181*f6aab3d8Srobert   }
182*f6aab3d8Srobert   return m_supports_qXfer_siginfo_read == eLazyBoolYes;
183*f6aab3d8Srobert }
184*f6aab3d8Srobert 
GetMultiprocessSupported()185*f6aab3d8Srobert bool GDBRemoteCommunicationClient::GetMultiprocessSupported() {
186*f6aab3d8Srobert   if (m_supports_memory_tagging == eLazyBoolCalculate)
187*f6aab3d8Srobert     GetRemoteQSupported();
188*f6aab3d8Srobert   return m_supports_multiprocess == eLazyBoolYes;
189*f6aab3d8Srobert }
190*f6aab3d8Srobert 
GetRemoteMaxPacketSize()191061da546Spatrick uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
192061da546Spatrick   if (m_max_packet_size == 0) {
193061da546Spatrick     GetRemoteQSupported();
194061da546Spatrick   }
195061da546Spatrick   return m_max_packet_size;
196061da546Spatrick }
197061da546Spatrick 
QueryNoAckModeSupported()198061da546Spatrick bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
199061da546Spatrick   if (m_supports_not_sending_acks == eLazyBoolCalculate) {
200061da546Spatrick     m_send_acks = true;
201061da546Spatrick     m_supports_not_sending_acks = eLazyBoolNo;
202061da546Spatrick 
203061da546Spatrick     // This is the first real packet that we'll send in a debug session and it
204061da546Spatrick     // may take a little longer than normal to receive a reply.  Wait at least
205061da546Spatrick     // 6 seconds for a reply to this packet.
206061da546Spatrick 
207061da546Spatrick     ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
208061da546Spatrick 
209061da546Spatrick     StringExtractorGDBRemote response;
210be691f3bSpatrick     if (SendPacketAndWaitForResponse("QStartNoAckMode", response) ==
211061da546Spatrick         PacketResult::Success) {
212061da546Spatrick       if (response.IsOKResponse()) {
213061da546Spatrick         m_send_acks = false;
214061da546Spatrick         m_supports_not_sending_acks = eLazyBoolYes;
215061da546Spatrick       }
216061da546Spatrick       return true;
217061da546Spatrick     }
218061da546Spatrick   }
219061da546Spatrick   return false;
220061da546Spatrick }
221061da546Spatrick 
GetListThreadsInStopReplySupported()222061da546Spatrick void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() {
223061da546Spatrick   if (m_supports_threads_in_stop_reply == eLazyBoolCalculate) {
224061da546Spatrick     m_supports_threads_in_stop_reply = eLazyBoolNo;
225061da546Spatrick 
226061da546Spatrick     StringExtractorGDBRemote response;
227be691f3bSpatrick     if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response) ==
228be691f3bSpatrick         PacketResult::Success) {
229061da546Spatrick       if (response.IsOKResponse())
230061da546Spatrick         m_supports_threads_in_stop_reply = eLazyBoolYes;
231061da546Spatrick     }
232061da546Spatrick   }
233061da546Spatrick }
234061da546Spatrick 
GetVAttachOrWaitSupported()235061da546Spatrick bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() {
236061da546Spatrick   if (m_attach_or_wait_reply == eLazyBoolCalculate) {
237061da546Spatrick     m_attach_or_wait_reply = eLazyBoolNo;
238061da546Spatrick 
239061da546Spatrick     StringExtractorGDBRemote response;
240be691f3bSpatrick     if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response) ==
241be691f3bSpatrick         PacketResult::Success) {
242061da546Spatrick       if (response.IsOKResponse())
243061da546Spatrick         m_attach_or_wait_reply = eLazyBoolYes;
244061da546Spatrick     }
245061da546Spatrick   }
246061da546Spatrick   return m_attach_or_wait_reply == eLazyBoolYes;
247061da546Spatrick }
248061da546Spatrick 
GetSyncThreadStateSupported()249061da546Spatrick bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
250061da546Spatrick   if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) {
251061da546Spatrick     m_prepare_for_reg_writing_reply = eLazyBoolNo;
252061da546Spatrick 
253061da546Spatrick     StringExtractorGDBRemote response;
254be691f3bSpatrick     if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response) ==
255be691f3bSpatrick         PacketResult::Success) {
256061da546Spatrick       if (response.IsOKResponse())
257061da546Spatrick         m_prepare_for_reg_writing_reply = eLazyBoolYes;
258061da546Spatrick     }
259061da546Spatrick   }
260061da546Spatrick   return m_prepare_for_reg_writing_reply == eLazyBoolYes;
261061da546Spatrick }
262061da546Spatrick 
ResetDiscoverableSettings(bool did_exec)263061da546Spatrick void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
264061da546Spatrick   if (!did_exec) {
265061da546Spatrick     // Hard reset everything, this is when we first connect to a GDB server
266061da546Spatrick     m_supports_not_sending_acks = eLazyBoolCalculate;
267061da546Spatrick     m_supports_thread_suffix = eLazyBoolCalculate;
268061da546Spatrick     m_supports_threads_in_stop_reply = eLazyBoolCalculate;
269061da546Spatrick     m_supports_vCont_c = eLazyBoolCalculate;
270061da546Spatrick     m_supports_vCont_C = eLazyBoolCalculate;
271061da546Spatrick     m_supports_vCont_s = eLazyBoolCalculate;
272061da546Spatrick     m_supports_vCont_S = eLazyBoolCalculate;
273061da546Spatrick     m_supports_p = eLazyBoolCalculate;
274061da546Spatrick     m_supports_x = eLazyBoolCalculate;
275061da546Spatrick     m_supports_QSaveRegisterState = eLazyBoolCalculate;
276061da546Spatrick     m_qHostInfo_is_valid = eLazyBoolCalculate;
277061da546Spatrick     m_curr_pid_is_valid = eLazyBoolCalculate;
278061da546Spatrick     m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
279061da546Spatrick     m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
280061da546Spatrick     m_supports_memory_region_info = eLazyBoolCalculate;
281061da546Spatrick     m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
282061da546Spatrick     m_attach_or_wait_reply = eLazyBoolCalculate;
283061da546Spatrick     m_avoid_g_packets = eLazyBoolCalculate;
284be691f3bSpatrick     m_supports_multiprocess = eLazyBoolCalculate;
285*f6aab3d8Srobert     m_supports_qSaveCore = eLazyBoolCalculate;
286061da546Spatrick     m_supports_qXfer_auxv_read = eLazyBoolCalculate;
287061da546Spatrick     m_supports_qXfer_libraries_read = eLazyBoolCalculate;
288061da546Spatrick     m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
289061da546Spatrick     m_supports_qXfer_features_read = eLazyBoolCalculate;
290061da546Spatrick     m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
291*f6aab3d8Srobert     m_supports_qXfer_siginfo_read = eLazyBoolCalculate;
292061da546Spatrick     m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
293*f6aab3d8Srobert     m_uses_native_signals = eLazyBoolCalculate;
294061da546Spatrick     m_supports_qProcessInfoPID = true;
295061da546Spatrick     m_supports_qfProcessInfo = true;
296061da546Spatrick     m_supports_qUserName = true;
297061da546Spatrick     m_supports_qGroupName = true;
298061da546Spatrick     m_supports_qThreadStopInfo = true;
299061da546Spatrick     m_supports_z0 = true;
300061da546Spatrick     m_supports_z1 = true;
301061da546Spatrick     m_supports_z2 = true;
302061da546Spatrick     m_supports_z3 = true;
303061da546Spatrick     m_supports_z4 = true;
304061da546Spatrick     m_supports_QEnvironment = true;
305061da546Spatrick     m_supports_QEnvironmentHexEncoded = true;
306061da546Spatrick     m_supports_qSymbol = true;
307061da546Spatrick     m_qSymbol_requests_done = false;
308061da546Spatrick     m_supports_qModuleInfo = true;
309061da546Spatrick     m_host_arch.Clear();
310061da546Spatrick     m_os_version = llvm::VersionTuple();
311061da546Spatrick     m_os_build.clear();
312061da546Spatrick     m_os_kernel.clear();
313061da546Spatrick     m_hostname.clear();
314061da546Spatrick     m_gdb_server_name.clear();
315061da546Spatrick     m_gdb_server_version = UINT32_MAX;
316061da546Spatrick     m_default_packet_timeout = seconds(0);
317be691f3bSpatrick     m_target_vm_page_size = 0;
318061da546Spatrick     m_max_packet_size = 0;
319061da546Spatrick     m_qSupported_response.clear();
320061da546Spatrick     m_supported_async_json_packets_is_valid = false;
321061da546Spatrick     m_supported_async_json_packets_sp.reset();
322061da546Spatrick     m_supports_jModulesInfo = true;
323061da546Spatrick   }
324061da546Spatrick 
325061da546Spatrick   // These flags should be reset when we first connect to a GDB server and when
326061da546Spatrick   // our inferior process execs
327061da546Spatrick   m_qProcessInfo_is_valid = eLazyBoolCalculate;
328061da546Spatrick   m_process_arch.Clear();
329061da546Spatrick }
330061da546Spatrick 
GetRemoteQSupported()331061da546Spatrick void GDBRemoteCommunicationClient::GetRemoteQSupported() {
332061da546Spatrick   // Clear out any capabilities we expect to see in the qSupported response
333061da546Spatrick   m_supports_qXfer_auxv_read = eLazyBoolNo;
334061da546Spatrick   m_supports_qXfer_libraries_read = eLazyBoolNo;
335061da546Spatrick   m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
336061da546Spatrick   m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
337061da546Spatrick   m_supports_qXfer_features_read = eLazyBoolNo;
338061da546Spatrick   m_supports_qXfer_memory_map_read = eLazyBoolNo;
339*f6aab3d8Srobert   m_supports_qXfer_siginfo_read = eLazyBoolNo;
340be691f3bSpatrick   m_supports_multiprocess = eLazyBoolNo;
341be691f3bSpatrick   m_supports_qEcho = eLazyBoolNo;
342be691f3bSpatrick   m_supports_QPassSignals = eLazyBoolNo;
343be691f3bSpatrick   m_supports_memory_tagging = eLazyBoolNo;
344*f6aab3d8Srobert   m_supports_qSaveCore = eLazyBoolNo;
345*f6aab3d8Srobert   m_uses_native_signals = eLazyBoolNo;
346be691f3bSpatrick 
347061da546Spatrick   m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
348061da546Spatrick                                   // not, we assume no limit
349061da546Spatrick 
350061da546Spatrick   // build the qSupported packet
351be691f3bSpatrick   std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc",
352*f6aab3d8Srobert                                        "multiprocess+", "fork-events+",
353*f6aab3d8Srobert                                        "vfork-events+"};
354061da546Spatrick   StreamString packet;
355061da546Spatrick   packet.PutCString("qSupported");
356061da546Spatrick   for (uint32_t i = 0; i < features.size(); ++i) {
357061da546Spatrick     packet.PutCString(i == 0 ? ":" : ";");
358061da546Spatrick     packet.PutCString(features[i]);
359061da546Spatrick   }
360061da546Spatrick 
361061da546Spatrick   StringExtractorGDBRemote response;
362be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
363061da546Spatrick       PacketResult::Success) {
364061da546Spatrick     // Hang on to the qSupported packet, so that platforms can do custom
365061da546Spatrick     // configuration of the transport before attaching/launching the process.
366be691f3bSpatrick     m_qSupported_response = response.GetStringRef().str();
367061da546Spatrick 
368*f6aab3d8Srobert     for (llvm::StringRef x : llvm::split(response.GetStringRef(), ';')) {
369be691f3bSpatrick       if (x == "qXfer:auxv:read+")
370061da546Spatrick         m_supports_qXfer_auxv_read = eLazyBoolYes;
371be691f3bSpatrick       else if (x == "qXfer:libraries-svr4:read+")
372061da546Spatrick         m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
373be691f3bSpatrick       else if (x == "augmented-libraries-svr4-read") {
374061da546Spatrick         m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
375061da546Spatrick         m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
376be691f3bSpatrick       } else if (x == "qXfer:libraries:read+")
377061da546Spatrick         m_supports_qXfer_libraries_read = eLazyBoolYes;
378be691f3bSpatrick       else if (x == "qXfer:features:read+")
379061da546Spatrick         m_supports_qXfer_features_read = eLazyBoolYes;
380be691f3bSpatrick       else if (x == "qXfer:memory-map:read+")
381061da546Spatrick         m_supports_qXfer_memory_map_read = eLazyBoolYes;
382*f6aab3d8Srobert       else if (x == "qXfer:siginfo:read+")
383*f6aab3d8Srobert         m_supports_qXfer_siginfo_read = eLazyBoolYes;
384be691f3bSpatrick       else if (x == "qEcho")
385be691f3bSpatrick         m_supports_qEcho = eLazyBoolYes;
386be691f3bSpatrick       else if (x == "QPassSignals+")
387be691f3bSpatrick         m_supports_QPassSignals = eLazyBoolYes;
388be691f3bSpatrick       else if (x == "multiprocess+")
389be691f3bSpatrick         m_supports_multiprocess = eLazyBoolYes;
390be691f3bSpatrick       else if (x == "memory-tagging+")
391be691f3bSpatrick         m_supports_memory_tagging = eLazyBoolYes;
392*f6aab3d8Srobert       else if (x == "qSaveCore+")
393*f6aab3d8Srobert         m_supports_qSaveCore = eLazyBoolYes;
394*f6aab3d8Srobert       else if (x == "native-signals+")
395*f6aab3d8Srobert         m_uses_native_signals = eLazyBoolYes;
396061da546Spatrick       // Look for a list of compressions in the features list e.g.
397061da546Spatrick       // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
398061da546Spatrick       // deflate,lzma
399be691f3bSpatrick       else if (x.consume_front("SupportedCompressions=")) {
400be691f3bSpatrick         llvm::SmallVector<llvm::StringRef, 4> compressions;
401be691f3bSpatrick         x.split(compressions, ',');
402be691f3bSpatrick         if (!compressions.empty())
403be691f3bSpatrick           MaybeEnableCompression(compressions);
404be691f3bSpatrick       } else if (x.consume_front("PacketSize=")) {
405be691f3bSpatrick         StringExtractorGDBRemote packet_response(x);
406061da546Spatrick         m_max_packet_size =
407061da546Spatrick             packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
408061da546Spatrick         if (m_max_packet_size == 0) {
409061da546Spatrick           m_max_packet_size = UINT64_MAX; // Must have been a garbled response
410*f6aab3d8Srobert           Log *log(GetLog(GDBRLog::Process));
411061da546Spatrick           LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response");
412061da546Spatrick         }
413061da546Spatrick       }
414061da546Spatrick     }
415061da546Spatrick   }
416be691f3bSpatrick }
417061da546Spatrick 
GetThreadSuffixSupported()418061da546Spatrick bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() {
419061da546Spatrick   if (m_supports_thread_suffix == eLazyBoolCalculate) {
420061da546Spatrick     StringExtractorGDBRemote response;
421061da546Spatrick     m_supports_thread_suffix = eLazyBoolNo;
422be691f3bSpatrick     if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response) ==
423be691f3bSpatrick         PacketResult::Success) {
424061da546Spatrick       if (response.IsOKResponse())
425061da546Spatrick         m_supports_thread_suffix = eLazyBoolYes;
426061da546Spatrick     }
427061da546Spatrick   }
428061da546Spatrick   return m_supports_thread_suffix;
429061da546Spatrick }
GetVContSupported(char flavor)430061da546Spatrick bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) {
431061da546Spatrick   if (m_supports_vCont_c == eLazyBoolCalculate) {
432061da546Spatrick     StringExtractorGDBRemote response;
433061da546Spatrick     m_supports_vCont_any = eLazyBoolNo;
434061da546Spatrick     m_supports_vCont_all = eLazyBoolNo;
435061da546Spatrick     m_supports_vCont_c = eLazyBoolNo;
436061da546Spatrick     m_supports_vCont_C = eLazyBoolNo;
437061da546Spatrick     m_supports_vCont_s = eLazyBoolNo;
438061da546Spatrick     m_supports_vCont_S = eLazyBoolNo;
439be691f3bSpatrick     if (SendPacketAndWaitForResponse("vCont?", response) ==
440061da546Spatrick         PacketResult::Success) {
441061da546Spatrick       const char *response_cstr = response.GetStringRef().data();
442061da546Spatrick       if (::strstr(response_cstr, ";c"))
443061da546Spatrick         m_supports_vCont_c = eLazyBoolYes;
444061da546Spatrick 
445061da546Spatrick       if (::strstr(response_cstr, ";C"))
446061da546Spatrick         m_supports_vCont_C = eLazyBoolYes;
447061da546Spatrick 
448061da546Spatrick       if (::strstr(response_cstr, ";s"))
449061da546Spatrick         m_supports_vCont_s = eLazyBoolYes;
450061da546Spatrick 
451061da546Spatrick       if (::strstr(response_cstr, ";S"))
452061da546Spatrick         m_supports_vCont_S = eLazyBoolYes;
453061da546Spatrick 
454061da546Spatrick       if (m_supports_vCont_c == eLazyBoolYes &&
455061da546Spatrick           m_supports_vCont_C == eLazyBoolYes &&
456061da546Spatrick           m_supports_vCont_s == eLazyBoolYes &&
457061da546Spatrick           m_supports_vCont_S == eLazyBoolYes) {
458061da546Spatrick         m_supports_vCont_all = eLazyBoolYes;
459061da546Spatrick       }
460061da546Spatrick 
461061da546Spatrick       if (m_supports_vCont_c == eLazyBoolYes ||
462061da546Spatrick           m_supports_vCont_C == eLazyBoolYes ||
463061da546Spatrick           m_supports_vCont_s == eLazyBoolYes ||
464061da546Spatrick           m_supports_vCont_S == eLazyBoolYes) {
465061da546Spatrick         m_supports_vCont_any = eLazyBoolYes;
466061da546Spatrick       }
467061da546Spatrick     }
468061da546Spatrick   }
469061da546Spatrick 
470061da546Spatrick   switch (flavor) {
471061da546Spatrick   case 'a':
472061da546Spatrick     return m_supports_vCont_any;
473061da546Spatrick   case 'A':
474061da546Spatrick     return m_supports_vCont_all;
475061da546Spatrick   case 'c':
476061da546Spatrick     return m_supports_vCont_c;
477061da546Spatrick   case 'C':
478061da546Spatrick     return m_supports_vCont_C;
479061da546Spatrick   case 's':
480061da546Spatrick     return m_supports_vCont_s;
481061da546Spatrick   case 'S':
482061da546Spatrick     return m_supports_vCont_S;
483061da546Spatrick   default:
484061da546Spatrick     break;
485061da546Spatrick   }
486061da546Spatrick   return false;
487061da546Spatrick }
488061da546Spatrick 
489061da546Spatrick GDBRemoteCommunication::PacketResult
SendThreadSpecificPacketAndWaitForResponse(lldb::tid_t tid,StreamString && payload,StringExtractorGDBRemote & response)490061da546Spatrick GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
491be691f3bSpatrick     lldb::tid_t tid, StreamString &&payload,
492be691f3bSpatrick     StringExtractorGDBRemote &response) {
493be691f3bSpatrick   Lock lock(*this);
494061da546Spatrick   if (!lock) {
495*f6aab3d8Srobert     if (Log *log = GetLog(GDBRLog::Process | GDBRLog::Packets))
496061da546Spatrick       LLDB_LOGF(log,
497061da546Spatrick                 "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex "
498061da546Spatrick                 "for %s packet.",
499061da546Spatrick                 __FUNCTION__, payload.GetData());
500061da546Spatrick     return PacketResult::ErrorNoSequenceLock;
501061da546Spatrick   }
502061da546Spatrick 
503061da546Spatrick   if (GetThreadSuffixSupported())
504061da546Spatrick     payload.Printf(";thread:%4.4" PRIx64 ";", tid);
505061da546Spatrick   else {
506061da546Spatrick     if (!SetCurrentThread(tid))
507061da546Spatrick       return PacketResult::ErrorSendFailed;
508061da546Spatrick   }
509061da546Spatrick 
510061da546Spatrick   return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
511061da546Spatrick }
512061da546Spatrick 
513061da546Spatrick // Check if the target supports 'p' packet. It sends out a 'p' packet and
514061da546Spatrick // checks the response. A normal packet will tell us that support is available.
515061da546Spatrick //
516061da546Spatrick // Takes a valid thread ID because p needs to apply to a thread.
GetpPacketSupported(lldb::tid_t tid)517061da546Spatrick bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
518061da546Spatrick   if (m_supports_p == eLazyBoolCalculate)
519061da546Spatrick     m_supports_p = GetThreadPacketSupported(tid, "p0");
520061da546Spatrick   return m_supports_p;
521061da546Spatrick }
522061da546Spatrick 
GetThreadPacketSupported(lldb::tid_t tid,llvm::StringRef packetStr)523061da546Spatrick LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported(
524061da546Spatrick     lldb::tid_t tid, llvm::StringRef packetStr) {
525061da546Spatrick   StreamString payload;
526061da546Spatrick   payload.PutCString(packetStr);
527061da546Spatrick   StringExtractorGDBRemote response;
528061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
529be691f3bSpatrick           tid, std::move(payload), response) == PacketResult::Success &&
530061da546Spatrick       response.IsNormalResponse()) {
531061da546Spatrick     return eLazyBoolYes;
532061da546Spatrick   }
533061da546Spatrick   return eLazyBoolNo;
534061da546Spatrick }
535061da546Spatrick 
GetSaveCoreSupported() const536*f6aab3d8Srobert bool GDBRemoteCommunicationClient::GetSaveCoreSupported() const {
537*f6aab3d8Srobert   return m_supports_qSaveCore == eLazyBoolYes;
538*f6aab3d8Srobert }
539*f6aab3d8Srobert 
GetThreadsInfo()540061da546Spatrick StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
541061da546Spatrick   // Get information on all threads at one using the "jThreadsInfo" packet
542061da546Spatrick   StructuredData::ObjectSP object_sp;
543061da546Spatrick 
544061da546Spatrick   if (m_supports_jThreadsInfo) {
545061da546Spatrick     StringExtractorGDBRemote response;
546061da546Spatrick     response.SetResponseValidatorToJSON();
547be691f3bSpatrick     if (SendPacketAndWaitForResponse("jThreadsInfo", response) ==
548061da546Spatrick         PacketResult::Success) {
549061da546Spatrick       if (response.IsUnsupportedResponse()) {
550061da546Spatrick         m_supports_jThreadsInfo = false;
551061da546Spatrick       } else if (!response.Empty()) {
552dda28197Spatrick         object_sp =
553dda28197Spatrick             StructuredData::ParseJSON(std::string(response.GetStringRef()));
554061da546Spatrick       }
555061da546Spatrick     }
556061da546Spatrick   }
557061da546Spatrick   return object_sp;
558061da546Spatrick }
559061da546Spatrick 
GetThreadExtendedInfoSupported()560061da546Spatrick bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
561061da546Spatrick   if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) {
562061da546Spatrick     StringExtractorGDBRemote response;
563061da546Spatrick     m_supports_jThreadExtendedInfo = eLazyBoolNo;
564be691f3bSpatrick     if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response) ==
565061da546Spatrick         PacketResult::Success) {
566061da546Spatrick       if (response.IsOKResponse()) {
567061da546Spatrick         m_supports_jThreadExtendedInfo = eLazyBoolYes;
568061da546Spatrick       }
569061da546Spatrick     }
570061da546Spatrick   }
571061da546Spatrick   return m_supports_jThreadExtendedInfo;
572061da546Spatrick }
573061da546Spatrick 
EnableErrorStringInPacket()574061da546Spatrick void GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
575061da546Spatrick   if (m_supports_error_string_reply == eLazyBoolCalculate) {
576061da546Spatrick     StringExtractorGDBRemote response;
577061da546Spatrick     // We try to enable error strings in remote packets but if we fail, we just
578061da546Spatrick     // work in the older way.
579061da546Spatrick     m_supports_error_string_reply = eLazyBoolNo;
580be691f3bSpatrick     if (SendPacketAndWaitForResponse("QEnableErrorStrings", response) ==
581061da546Spatrick         PacketResult::Success) {
582061da546Spatrick       if (response.IsOKResponse()) {
583061da546Spatrick         m_supports_error_string_reply = eLazyBoolYes;
584061da546Spatrick       }
585061da546Spatrick     }
586061da546Spatrick   }
587061da546Spatrick }
588061da546Spatrick 
GetLoadedDynamicLibrariesInfosSupported()589061da546Spatrick bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() {
590061da546Spatrick   if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) {
591061da546Spatrick     StringExtractorGDBRemote response;
592061da546Spatrick     m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
593061da546Spatrick     if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:",
594be691f3bSpatrick                                      response) == PacketResult::Success) {
595061da546Spatrick       if (response.IsOKResponse()) {
596061da546Spatrick         m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
597061da546Spatrick       }
598061da546Spatrick     }
599061da546Spatrick   }
600061da546Spatrick   return m_supports_jLoadedDynamicLibrariesInfos;
601061da546Spatrick }
602061da546Spatrick 
GetSharedCacheInfoSupported()603061da546Spatrick bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() {
604061da546Spatrick   if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) {
605061da546Spatrick     StringExtractorGDBRemote response;
606061da546Spatrick     m_supports_jGetSharedCacheInfo = eLazyBoolNo;
607be691f3bSpatrick     if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response) ==
608061da546Spatrick         PacketResult::Success) {
609061da546Spatrick       if (response.IsOKResponse()) {
610061da546Spatrick         m_supports_jGetSharedCacheInfo = eLazyBoolYes;
611061da546Spatrick       }
612061da546Spatrick     }
613061da546Spatrick   }
614061da546Spatrick   return m_supports_jGetSharedCacheInfo;
615061da546Spatrick }
616061da546Spatrick 
GetDynamicLoaderProcessStateSupported()617*f6aab3d8Srobert bool GDBRemoteCommunicationClient::GetDynamicLoaderProcessStateSupported() {
618*f6aab3d8Srobert   if (m_supports_jGetDyldProcessState == eLazyBoolCalculate) {
619*f6aab3d8Srobert     StringExtractorGDBRemote response;
620*f6aab3d8Srobert     m_supports_jGetDyldProcessState = eLazyBoolNo;
621*f6aab3d8Srobert     if (SendPacketAndWaitForResponse("jGetDyldProcessState", response) ==
622*f6aab3d8Srobert         PacketResult::Success) {
623*f6aab3d8Srobert       if (!response.IsUnsupportedResponse())
624*f6aab3d8Srobert         m_supports_jGetDyldProcessState = eLazyBoolYes;
625*f6aab3d8Srobert     }
626*f6aab3d8Srobert   }
627*f6aab3d8Srobert   return m_supports_jGetDyldProcessState;
628*f6aab3d8Srobert }
629*f6aab3d8Srobert 
GetMemoryTaggingSupported()630be691f3bSpatrick bool GDBRemoteCommunicationClient::GetMemoryTaggingSupported() {
631be691f3bSpatrick   if (m_supports_memory_tagging == eLazyBoolCalculate) {
632be691f3bSpatrick     GetRemoteQSupported();
633be691f3bSpatrick   }
634be691f3bSpatrick   return m_supports_memory_tagging == eLazyBoolYes;
635be691f3bSpatrick }
636be691f3bSpatrick 
ReadMemoryTags(lldb::addr_t addr,size_t len,int32_t type)637be691f3bSpatrick DataBufferSP GDBRemoteCommunicationClient::ReadMemoryTags(lldb::addr_t addr,
638be691f3bSpatrick                                                           size_t len,
639be691f3bSpatrick                                                           int32_t type) {
640be691f3bSpatrick   StreamString packet;
641be691f3bSpatrick   packet.Printf("qMemTags:%" PRIx64 ",%zx:%" PRIx32, addr, len, type);
642be691f3bSpatrick   StringExtractorGDBRemote response;
643be691f3bSpatrick 
644*f6aab3d8Srobert   Log *log = GetLog(GDBRLog::Memory);
645be691f3bSpatrick 
646be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
647be691f3bSpatrick           PacketResult::Success ||
648be691f3bSpatrick       !response.IsNormalResponse()) {
649be691f3bSpatrick     LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s: qMemTags packet failed",
650be691f3bSpatrick               __FUNCTION__);
651be691f3bSpatrick     return nullptr;
652be691f3bSpatrick   }
653be691f3bSpatrick 
654be691f3bSpatrick   // We are expecting
655be691f3bSpatrick   // m<hex encoded bytes>
656be691f3bSpatrick 
657be691f3bSpatrick   if (response.GetChar() != 'm') {
658be691f3bSpatrick     LLDB_LOGF(log,
659be691f3bSpatrick               "GDBRemoteCommunicationClient::%s: qMemTags response did not "
660be691f3bSpatrick               "begin with \"m\"",
661be691f3bSpatrick               __FUNCTION__);
662be691f3bSpatrick     return nullptr;
663be691f3bSpatrick   }
664be691f3bSpatrick 
665be691f3bSpatrick   size_t expected_bytes = response.GetBytesLeft() / 2;
666*f6aab3d8Srobert   WritableDataBufferSP buffer_sp(new DataBufferHeap(expected_bytes, 0));
667be691f3bSpatrick   size_t got_bytes = response.GetHexBytesAvail(buffer_sp->GetData());
668be691f3bSpatrick   // Check both because in some situations chars are consumed even
669be691f3bSpatrick   // if the decoding fails.
670be691f3bSpatrick   if (response.GetBytesLeft() || (expected_bytes != got_bytes)) {
671be691f3bSpatrick     LLDB_LOGF(
672be691f3bSpatrick         log,
673be691f3bSpatrick         "GDBRemoteCommunicationClient::%s: Invalid data in qMemTags response",
674be691f3bSpatrick         __FUNCTION__);
675be691f3bSpatrick     return nullptr;
676be691f3bSpatrick   }
677be691f3bSpatrick 
678be691f3bSpatrick   return buffer_sp;
679be691f3bSpatrick }
680be691f3bSpatrick 
WriteMemoryTags(lldb::addr_t addr,size_t len,int32_t type,const std::vector<uint8_t> & tags)681be691f3bSpatrick Status GDBRemoteCommunicationClient::WriteMemoryTags(
682be691f3bSpatrick     lldb::addr_t addr, size_t len, int32_t type,
683be691f3bSpatrick     const std::vector<uint8_t> &tags) {
684be691f3bSpatrick   // Format QMemTags:address,length:type:tags
685be691f3bSpatrick   StreamString packet;
686be691f3bSpatrick   packet.Printf("QMemTags:%" PRIx64 ",%zx:%" PRIx32 ":", addr, len, type);
687be691f3bSpatrick   packet.PutBytesAsRawHex8(tags.data(), tags.size());
688be691f3bSpatrick 
689be691f3bSpatrick   Status status;
690be691f3bSpatrick   StringExtractorGDBRemote response;
691be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
692be691f3bSpatrick           PacketResult::Success ||
693be691f3bSpatrick       !response.IsOKResponse()) {
694be691f3bSpatrick     status.SetErrorString("QMemTags packet failed");
695be691f3bSpatrick   }
696be691f3bSpatrick   return status;
697be691f3bSpatrick }
698be691f3bSpatrick 
GetxPacketSupported()699061da546Spatrick bool GDBRemoteCommunicationClient::GetxPacketSupported() {
700061da546Spatrick   if (m_supports_x == eLazyBoolCalculate) {
701061da546Spatrick     StringExtractorGDBRemote response;
702061da546Spatrick     m_supports_x = eLazyBoolNo;
703061da546Spatrick     char packet[256];
704061da546Spatrick     snprintf(packet, sizeof(packet), "x0,0");
705be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
706061da546Spatrick         PacketResult::Success) {
707061da546Spatrick       if (response.IsOKResponse())
708061da546Spatrick         m_supports_x = eLazyBoolYes;
709061da546Spatrick     }
710061da546Spatrick   }
711061da546Spatrick   return m_supports_x;
712061da546Spatrick }
713061da546Spatrick 
GetCurrentProcessID(bool allow_lazy)714061da546Spatrick lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
715061da546Spatrick   if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes)
716061da546Spatrick     return m_curr_pid;
717061da546Spatrick 
718061da546Spatrick   // First try to retrieve the pid via the qProcessInfo request.
719061da546Spatrick   GetCurrentProcessInfo(allow_lazy);
720061da546Spatrick   if (m_curr_pid_is_valid == eLazyBoolYes) {
721061da546Spatrick     // We really got it.
722061da546Spatrick     return m_curr_pid;
723061da546Spatrick   } else {
724061da546Spatrick     // If we don't get a response for qProcessInfo, check if $qC gives us a
725061da546Spatrick     // result. $qC only returns a real process id on older debugserver and
726061da546Spatrick     // lldb-platform stubs. The gdb remote protocol documents $qC as returning
727061da546Spatrick     // the thread id, which newer debugserver and lldb-gdbserver stubs return
728061da546Spatrick     // correctly.
729061da546Spatrick     StringExtractorGDBRemote response;
730be691f3bSpatrick     if (SendPacketAndWaitForResponse("qC", response) == PacketResult::Success) {
731061da546Spatrick       if (response.GetChar() == 'Q') {
732061da546Spatrick         if (response.GetChar() == 'C') {
733be691f3bSpatrick           m_curr_pid_run = m_curr_pid =
734be691f3bSpatrick               response.GetHexMaxU64(false, LLDB_INVALID_PROCESS_ID);
735061da546Spatrick           if (m_curr_pid != LLDB_INVALID_PROCESS_ID) {
736061da546Spatrick             m_curr_pid_is_valid = eLazyBoolYes;
737061da546Spatrick             return m_curr_pid;
738061da546Spatrick           }
739061da546Spatrick         }
740061da546Spatrick       }
741061da546Spatrick     }
742061da546Spatrick 
743061da546Spatrick     // If we don't get a response for $qC, check if $qfThreadID gives us a
744061da546Spatrick     // result.
745061da546Spatrick     if (m_curr_pid == LLDB_INVALID_PROCESS_ID) {
746061da546Spatrick       bool sequence_mutex_unavailable;
747be691f3bSpatrick       auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
748be691f3bSpatrick       if (!ids.empty() && !sequence_mutex_unavailable) {
749be691f3bSpatrick         // If server returned an explicit PID, use that.
750be691f3bSpatrick         m_curr_pid_run = m_curr_pid = ids.front().first;
751be691f3bSpatrick         // Otherwise, use the TID of the first thread (Linux hack).
752be691f3bSpatrick         if (m_curr_pid == LLDB_INVALID_PROCESS_ID)
753be691f3bSpatrick           m_curr_pid_run = m_curr_pid = ids.front().second;
754061da546Spatrick         m_curr_pid_is_valid = eLazyBoolYes;
755061da546Spatrick         return m_curr_pid;
756061da546Spatrick       }
757061da546Spatrick     }
758061da546Spatrick   }
759061da546Spatrick 
760061da546Spatrick   return LLDB_INVALID_PROCESS_ID;
761061da546Spatrick }
762061da546Spatrick 
LaunchProcess(const Args & args)763*f6aab3d8Srobert llvm::Error GDBRemoteCommunicationClient::LaunchProcess(const Args &args) {
764*f6aab3d8Srobert   if (!args.GetArgumentAtIndex(0))
765*f6aab3d8Srobert     return llvm::createStringError(llvm::inconvertibleErrorCode(),
766*f6aab3d8Srobert                                    "Nothing to launch");
767*f6aab3d8Srobert   // try vRun first
768*f6aab3d8Srobert   if (m_supports_vRun) {
769*f6aab3d8Srobert     StreamString packet;
770*f6aab3d8Srobert     packet.PutCString("vRun");
771*f6aab3d8Srobert     for (const Args::ArgEntry &arg : args) {
772*f6aab3d8Srobert       packet.PutChar(';');
773*f6aab3d8Srobert       packet.PutStringAsRawHex8(arg.ref());
774061da546Spatrick     }
775061da546Spatrick 
776*f6aab3d8Srobert     StringExtractorGDBRemote response;
777*f6aab3d8Srobert     if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
778*f6aab3d8Srobert         PacketResult::Success)
779*f6aab3d8Srobert       return llvm::createStringError(llvm::inconvertibleErrorCode(),
780*f6aab3d8Srobert                                      "Sending vRun packet failed");
781*f6aab3d8Srobert 
782*f6aab3d8Srobert     if (response.IsErrorResponse())
783*f6aab3d8Srobert       return response.GetStatus().ToError();
784*f6aab3d8Srobert 
785*f6aab3d8Srobert     // vRun replies with a stop reason packet
786*f6aab3d8Srobert     // FIXME: right now we just discard the packet and LLDB queries
787*f6aab3d8Srobert     // for stop reason again
788*f6aab3d8Srobert     if (!response.IsUnsupportedResponse())
789*f6aab3d8Srobert       return llvm::Error::success();
790*f6aab3d8Srobert 
791*f6aab3d8Srobert     m_supports_vRun = false;
792061da546Spatrick   }
793*f6aab3d8Srobert 
794*f6aab3d8Srobert   // fallback to A
795061da546Spatrick   StreamString packet;
796061da546Spatrick   packet.PutChar('A');
797*f6aab3d8Srobert   llvm::ListSeparator LS(",");
798*f6aab3d8Srobert   for (const auto &arg : llvm::enumerate(args)) {
799*f6aab3d8Srobert     packet << LS;
800*f6aab3d8Srobert     packet.Format("{0},{1},", arg.value().ref().size() * 2, arg.index());
801*f6aab3d8Srobert     packet.PutStringAsRawHex8(arg.value().ref());
802061da546Spatrick   }
803061da546Spatrick 
804061da546Spatrick   StringExtractorGDBRemote response;
805*f6aab3d8Srobert   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
806061da546Spatrick       PacketResult::Success) {
807*f6aab3d8Srobert     return llvm::createStringError(llvm::inconvertibleErrorCode(),
808*f6aab3d8Srobert                                    "Sending A packet failed");
809*f6aab3d8Srobert   }
810*f6aab3d8Srobert   if (!response.IsOKResponse())
811*f6aab3d8Srobert     return response.GetStatus().ToError();
812*f6aab3d8Srobert 
813*f6aab3d8Srobert   if (SendPacketAndWaitForResponse("qLaunchSuccess", response) !=
814*f6aab3d8Srobert       PacketResult::Success) {
815*f6aab3d8Srobert     return llvm::createStringError(llvm::inconvertibleErrorCode(),
816*f6aab3d8Srobert                                    "Sending qLaunchSuccess packet failed");
817*f6aab3d8Srobert   }
818061da546Spatrick   if (response.IsOKResponse())
819*f6aab3d8Srobert     return llvm::Error::success();
820*f6aab3d8Srobert   if (response.GetChar() == 'E') {
821*f6aab3d8Srobert     return llvm::createStringError(llvm::inconvertibleErrorCode(),
822*f6aab3d8Srobert                                    response.GetStringRef().substr(1));
823061da546Spatrick   }
824*f6aab3d8Srobert   return llvm::createStringError(llvm::inconvertibleErrorCode(),
825*f6aab3d8Srobert                                  "unknown error occurred launching process");
826061da546Spatrick }
827061da546Spatrick 
SendEnvironment(const Environment & env)828061da546Spatrick int GDBRemoteCommunicationClient::SendEnvironment(const Environment &env) {
829061da546Spatrick   for (const auto &KV : env) {
830061da546Spatrick     int r = SendEnvironmentPacket(Environment::compose(KV).c_str());
831061da546Spatrick     if (r != 0)
832061da546Spatrick       return r;
833061da546Spatrick   }
834061da546Spatrick   return 0;
835061da546Spatrick }
836061da546Spatrick 
SendEnvironmentPacket(char const * name_equal_value)837061da546Spatrick int GDBRemoteCommunicationClient::SendEnvironmentPacket(
838061da546Spatrick     char const *name_equal_value) {
839061da546Spatrick   if (name_equal_value && name_equal_value[0]) {
840061da546Spatrick     bool send_hex_encoding = false;
841061da546Spatrick     for (const char *p = name_equal_value; *p != '\0' && !send_hex_encoding;
842061da546Spatrick          ++p) {
843dda28197Spatrick       if (llvm::isPrint(*p)) {
844061da546Spatrick         switch (*p) {
845061da546Spatrick         case '$':
846061da546Spatrick         case '#':
847061da546Spatrick         case '*':
848061da546Spatrick         case '}':
849061da546Spatrick           send_hex_encoding = true;
850061da546Spatrick           break;
851061da546Spatrick         default:
852061da546Spatrick           break;
853061da546Spatrick         }
854061da546Spatrick       } else {
855061da546Spatrick         // We have non printable characters, lets hex encode this...
856061da546Spatrick         send_hex_encoding = true;
857061da546Spatrick       }
858061da546Spatrick     }
859061da546Spatrick 
860061da546Spatrick     StringExtractorGDBRemote response;
861*f6aab3d8Srobert     // Prefer sending unencoded, if possible and the server supports it.
862*f6aab3d8Srobert     if (!send_hex_encoding && m_supports_QEnvironment) {
863*f6aab3d8Srobert       StreamString packet;
864*f6aab3d8Srobert       packet.Printf("QEnvironment:%s", name_equal_value);
865*f6aab3d8Srobert       if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
866*f6aab3d8Srobert           PacketResult::Success)
867*f6aab3d8Srobert         return -1;
868*f6aab3d8Srobert 
869061da546Spatrick       if (response.IsOKResponse())
870061da546Spatrick         return 0;
871*f6aab3d8Srobert       if (response.IsUnsupportedResponse())
872*f6aab3d8Srobert         m_supports_QEnvironment = false;
873*f6aab3d8Srobert       else {
874061da546Spatrick         uint8_t error = response.GetError();
875061da546Spatrick         if (error)
876061da546Spatrick           return error;
877*f6aab3d8Srobert         return -1;
878061da546Spatrick       }
879061da546Spatrick     }
880061da546Spatrick 
881*f6aab3d8Srobert     if (m_supports_QEnvironmentHexEncoded) {
882*f6aab3d8Srobert       StreamString packet;
883*f6aab3d8Srobert       packet.PutCString("QEnvironmentHexEncoded:");
884*f6aab3d8Srobert       packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value));
885*f6aab3d8Srobert       if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
886*f6aab3d8Srobert           PacketResult::Success)
887*f6aab3d8Srobert         return -1;
888*f6aab3d8Srobert 
889061da546Spatrick       if (response.IsOKResponse())
890061da546Spatrick         return 0;
891*f6aab3d8Srobert       if (response.IsUnsupportedResponse())
892*f6aab3d8Srobert         m_supports_QEnvironmentHexEncoded = false;
893*f6aab3d8Srobert       else {
894061da546Spatrick         uint8_t error = response.GetError();
895061da546Spatrick         if (error)
896061da546Spatrick           return error;
897*f6aab3d8Srobert         return -1;
898061da546Spatrick       }
899061da546Spatrick     }
900061da546Spatrick   }
901061da546Spatrick   return -1;
902061da546Spatrick }
903061da546Spatrick 
SendLaunchArchPacket(char const * arch)904061da546Spatrick int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) {
905061da546Spatrick   if (arch && arch[0]) {
906061da546Spatrick     StreamString packet;
907061da546Spatrick     packet.Printf("QLaunchArch:%s", arch);
908061da546Spatrick     StringExtractorGDBRemote response;
909be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
910061da546Spatrick         PacketResult::Success) {
911061da546Spatrick       if (response.IsOKResponse())
912061da546Spatrick         return 0;
913061da546Spatrick       uint8_t error = response.GetError();
914061da546Spatrick       if (error)
915061da546Spatrick         return error;
916061da546Spatrick     }
917061da546Spatrick   }
918061da546Spatrick   return -1;
919061da546Spatrick }
920061da546Spatrick 
SendLaunchEventDataPacket(char const * data,bool * was_supported)921061da546Spatrick int GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
922061da546Spatrick     char const *data, bool *was_supported) {
923061da546Spatrick   if (data && *data != '\0') {
924061da546Spatrick     StreamString packet;
925061da546Spatrick     packet.Printf("QSetProcessEvent:%s", data);
926061da546Spatrick     StringExtractorGDBRemote response;
927be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
928061da546Spatrick         PacketResult::Success) {
929061da546Spatrick       if (response.IsOKResponse()) {
930061da546Spatrick         if (was_supported)
931061da546Spatrick           *was_supported = true;
932061da546Spatrick         return 0;
933061da546Spatrick       } else if (response.IsUnsupportedResponse()) {
934061da546Spatrick         if (was_supported)
935061da546Spatrick           *was_supported = false;
936061da546Spatrick         return -1;
937061da546Spatrick       } else {
938061da546Spatrick         uint8_t error = response.GetError();
939061da546Spatrick         if (was_supported)
940061da546Spatrick           *was_supported = true;
941061da546Spatrick         if (error)
942061da546Spatrick           return error;
943061da546Spatrick       }
944061da546Spatrick     }
945061da546Spatrick   }
946061da546Spatrick   return -1;
947061da546Spatrick }
948061da546Spatrick 
GetOSVersion()949061da546Spatrick llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() {
950061da546Spatrick   GetHostInfo();
951061da546Spatrick   return m_os_version;
952061da546Spatrick }
953061da546Spatrick 
GetMacCatalystVersion()954061da546Spatrick llvm::VersionTuple GDBRemoteCommunicationClient::GetMacCatalystVersion() {
955061da546Spatrick   GetHostInfo();
956061da546Spatrick   return m_maccatalyst_version;
957061da546Spatrick }
958061da546Spatrick 
GetOSBuildString()959*f6aab3d8Srobert std::optional<std::string> GDBRemoteCommunicationClient::GetOSBuildString() {
960061da546Spatrick   if (GetHostInfo()) {
961*f6aab3d8Srobert     if (!m_os_build.empty())
962*f6aab3d8Srobert       return m_os_build;
963061da546Spatrick   }
964*f6aab3d8Srobert   return std::nullopt;
965061da546Spatrick }
966061da546Spatrick 
967*f6aab3d8Srobert std::optional<std::string>
GetOSKernelDescription()968*f6aab3d8Srobert GDBRemoteCommunicationClient::GetOSKernelDescription() {
969061da546Spatrick   if (GetHostInfo()) {
970*f6aab3d8Srobert     if (!m_os_kernel.empty())
971*f6aab3d8Srobert       return m_os_kernel;
972061da546Spatrick   }
973*f6aab3d8Srobert   return std::nullopt;
974061da546Spatrick }
975061da546Spatrick 
GetHostname(std::string & s)976061da546Spatrick bool GDBRemoteCommunicationClient::GetHostname(std::string &s) {
977061da546Spatrick   if (GetHostInfo()) {
978061da546Spatrick     if (!m_hostname.empty()) {
979061da546Spatrick       s = m_hostname;
980061da546Spatrick       return true;
981061da546Spatrick     }
982061da546Spatrick   }
983061da546Spatrick   s.clear();
984061da546Spatrick   return false;
985061da546Spatrick }
986061da546Spatrick 
GetSystemArchitecture()987061da546Spatrick ArchSpec GDBRemoteCommunicationClient::GetSystemArchitecture() {
988061da546Spatrick   if (GetHostInfo())
989061da546Spatrick     return m_host_arch;
990061da546Spatrick   return ArchSpec();
991061da546Spatrick }
992061da546Spatrick 
993061da546Spatrick const lldb_private::ArchSpec &
GetProcessArchitecture()994061da546Spatrick GDBRemoteCommunicationClient::GetProcessArchitecture() {
995061da546Spatrick   if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
996061da546Spatrick     GetCurrentProcessInfo();
997061da546Spatrick   return m_process_arch;
998061da546Spatrick }
999061da546Spatrick 
GetProcessStandaloneBinary(UUID & uuid,addr_t & value,bool & value_is_offset)1000*f6aab3d8Srobert bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary(
1001*f6aab3d8Srobert     UUID &uuid, addr_t &value, bool &value_is_offset) {
1002*f6aab3d8Srobert   if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
1003*f6aab3d8Srobert     GetCurrentProcessInfo();
1004*f6aab3d8Srobert 
1005*f6aab3d8Srobert   // Return true if we have a UUID or an address/offset of the
1006*f6aab3d8Srobert   // main standalone / firmware binary being used.
1007*f6aab3d8Srobert   if (!m_process_standalone_uuid.IsValid() &&
1008*f6aab3d8Srobert       m_process_standalone_value == LLDB_INVALID_ADDRESS)
1009*f6aab3d8Srobert     return false;
1010*f6aab3d8Srobert 
1011*f6aab3d8Srobert   uuid = m_process_standalone_uuid;
1012*f6aab3d8Srobert   value = m_process_standalone_value;
1013*f6aab3d8Srobert   value_is_offset = m_process_standalone_value_is_offset;
1014*f6aab3d8Srobert   return true;
1015*f6aab3d8Srobert }
1016*f6aab3d8Srobert 
1017*f6aab3d8Srobert std::vector<addr_t>
GetProcessStandaloneBinaries()1018*f6aab3d8Srobert GDBRemoteCommunicationClient::GetProcessStandaloneBinaries() {
1019*f6aab3d8Srobert   if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
1020*f6aab3d8Srobert     GetCurrentProcessInfo();
1021*f6aab3d8Srobert   return m_binary_addresses;
1022*f6aab3d8Srobert }
1023*f6aab3d8Srobert 
GetGDBServerVersion()1024061da546Spatrick bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
1025061da546Spatrick   if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
1026061da546Spatrick     m_gdb_server_name.clear();
1027061da546Spatrick     m_gdb_server_version = 0;
1028061da546Spatrick     m_qGDBServerVersion_is_valid = eLazyBoolNo;
1029061da546Spatrick 
1030061da546Spatrick     StringExtractorGDBRemote response;
1031be691f3bSpatrick     if (SendPacketAndWaitForResponse("qGDBServerVersion", response) ==
1032061da546Spatrick         PacketResult::Success) {
1033061da546Spatrick       if (response.IsNormalResponse()) {
1034061da546Spatrick         llvm::StringRef name, value;
1035061da546Spatrick         bool success = false;
1036061da546Spatrick         while (response.GetNameColonValue(name, value)) {
1037061da546Spatrick           if (name.equals("name")) {
1038061da546Spatrick             success = true;
1039dda28197Spatrick             m_gdb_server_name = std::string(value);
1040061da546Spatrick           } else if (name.equals("version")) {
1041061da546Spatrick             llvm::StringRef major, minor;
1042061da546Spatrick             std::tie(major, minor) = value.split('.');
1043061da546Spatrick             if (!major.getAsInteger(0, m_gdb_server_version))
1044061da546Spatrick               success = true;
1045061da546Spatrick           }
1046061da546Spatrick         }
1047061da546Spatrick         if (success)
1048061da546Spatrick           m_qGDBServerVersion_is_valid = eLazyBoolYes;
1049061da546Spatrick       }
1050061da546Spatrick     }
1051061da546Spatrick   }
1052061da546Spatrick   return m_qGDBServerVersion_is_valid == eLazyBoolYes;
1053061da546Spatrick }
1054061da546Spatrick 
MaybeEnableCompression(llvm::ArrayRef<llvm::StringRef> supported_compressions)1055061da546Spatrick void GDBRemoteCommunicationClient::MaybeEnableCompression(
1056be691f3bSpatrick     llvm::ArrayRef<llvm::StringRef> supported_compressions) {
1057061da546Spatrick   CompressionType avail_type = CompressionType::None;
1058be691f3bSpatrick   llvm::StringRef avail_name;
1059061da546Spatrick 
1060061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
1061061da546Spatrick   if (avail_type == CompressionType::None) {
1062061da546Spatrick     for (auto compression : supported_compressions) {
1063061da546Spatrick       if (compression == "lzfse") {
1064061da546Spatrick         avail_type = CompressionType::LZFSE;
1065061da546Spatrick         avail_name = compression;
1066061da546Spatrick         break;
1067061da546Spatrick       }
1068061da546Spatrick     }
1069061da546Spatrick   }
1070061da546Spatrick #endif
1071061da546Spatrick 
1072061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
1073061da546Spatrick   if (avail_type == CompressionType::None) {
1074061da546Spatrick     for (auto compression : supported_compressions) {
1075061da546Spatrick       if (compression == "zlib-deflate") {
1076061da546Spatrick         avail_type = CompressionType::ZlibDeflate;
1077061da546Spatrick         avail_name = compression;
1078061da546Spatrick         break;
1079061da546Spatrick       }
1080061da546Spatrick     }
1081061da546Spatrick   }
1082061da546Spatrick #endif
1083061da546Spatrick 
1084be691f3bSpatrick #if LLVM_ENABLE_ZLIB
1085061da546Spatrick   if (avail_type == CompressionType::None) {
1086061da546Spatrick     for (auto compression : supported_compressions) {
1087061da546Spatrick       if (compression == "zlib-deflate") {
1088061da546Spatrick         avail_type = CompressionType::ZlibDeflate;
1089061da546Spatrick         avail_name = compression;
1090061da546Spatrick         break;
1091061da546Spatrick       }
1092061da546Spatrick     }
1093061da546Spatrick   }
1094061da546Spatrick #endif
1095061da546Spatrick 
1096061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
1097061da546Spatrick   if (avail_type == CompressionType::None) {
1098061da546Spatrick     for (auto compression : supported_compressions) {
1099061da546Spatrick       if (compression == "lz4") {
1100061da546Spatrick         avail_type = CompressionType::LZ4;
1101061da546Spatrick         avail_name = compression;
1102061da546Spatrick         break;
1103061da546Spatrick       }
1104061da546Spatrick     }
1105061da546Spatrick   }
1106061da546Spatrick #endif
1107061da546Spatrick 
1108061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
1109061da546Spatrick   if (avail_type == CompressionType::None) {
1110061da546Spatrick     for (auto compression : supported_compressions) {
1111061da546Spatrick       if (compression == "lzma") {
1112061da546Spatrick         avail_type = CompressionType::LZMA;
1113061da546Spatrick         avail_name = compression;
1114061da546Spatrick         break;
1115061da546Spatrick       }
1116061da546Spatrick     }
1117061da546Spatrick   }
1118061da546Spatrick #endif
1119061da546Spatrick 
1120061da546Spatrick   if (avail_type != CompressionType::None) {
1121061da546Spatrick     StringExtractorGDBRemote response;
1122*f6aab3d8Srobert     std::string packet = "QEnableCompression:type:" + avail_name.str() + ";";
1123*f6aab3d8Srobert     if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
1124061da546Spatrick       return;
1125061da546Spatrick 
1126061da546Spatrick     if (response.IsOKResponse()) {
1127061da546Spatrick       m_compression_type = avail_type;
1128061da546Spatrick     }
1129061da546Spatrick   }
1130061da546Spatrick }
1131061da546Spatrick 
GetGDBServerProgramName()1132061da546Spatrick const char *GDBRemoteCommunicationClient::GetGDBServerProgramName() {
1133061da546Spatrick   if (GetGDBServerVersion()) {
1134061da546Spatrick     if (!m_gdb_server_name.empty())
1135061da546Spatrick       return m_gdb_server_name.c_str();
1136061da546Spatrick   }
1137061da546Spatrick   return nullptr;
1138061da546Spatrick }
1139061da546Spatrick 
GetGDBServerProgramVersion()1140061da546Spatrick uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() {
1141061da546Spatrick   if (GetGDBServerVersion())
1142061da546Spatrick     return m_gdb_server_version;
1143061da546Spatrick   return 0;
1144061da546Spatrick }
1145061da546Spatrick 
GetDefaultThreadId(lldb::tid_t & tid)1146061da546Spatrick bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
1147061da546Spatrick   StringExtractorGDBRemote response;
1148be691f3bSpatrick   if (SendPacketAndWaitForResponse("qC", response) != PacketResult::Success)
1149061da546Spatrick     return false;
1150061da546Spatrick 
1151061da546Spatrick   if (!response.IsNormalResponse())
1152061da546Spatrick     return false;
1153061da546Spatrick 
1154be691f3bSpatrick   if (response.GetChar() == 'Q' && response.GetChar() == 'C') {
1155be691f3bSpatrick     auto pid_tid = response.GetPidTid(0);
1156be691f3bSpatrick     if (!pid_tid)
1157be691f3bSpatrick       return false;
1158be691f3bSpatrick 
1159be691f3bSpatrick     lldb::pid_t pid = pid_tid->first;
1160be691f3bSpatrick     // invalid
1161be691f3bSpatrick     if (pid == StringExtractorGDBRemote::AllProcesses)
1162be691f3bSpatrick       return false;
1163be691f3bSpatrick 
1164be691f3bSpatrick     // if we get pid as well, update m_curr_pid
1165be691f3bSpatrick     if (pid != 0) {
1166be691f3bSpatrick       m_curr_pid_run = m_curr_pid = pid;
1167be691f3bSpatrick       m_curr_pid_is_valid = eLazyBoolYes;
1168be691f3bSpatrick     }
1169be691f3bSpatrick     tid = pid_tid->second;
1170be691f3bSpatrick   }
1171061da546Spatrick 
1172061da546Spatrick   return true;
1173061da546Spatrick }
1174061da546Spatrick 
ParseOSType(llvm::StringRef value,std::string & os_name,std::string & environment)1175dda28197Spatrick static void ParseOSType(llvm::StringRef value, std::string &os_name,
1176dda28197Spatrick                         std::string &environment) {
1177dda28197Spatrick   if (value.equals("iossimulator") || value.equals("tvossimulator") ||
1178dda28197Spatrick       value.equals("watchossimulator")) {
1179dda28197Spatrick     environment = "simulator";
1180dda28197Spatrick     os_name = value.drop_back(environment.size()).str();
1181dda28197Spatrick   } else if (value.equals("maccatalyst")) {
1182dda28197Spatrick     os_name = "ios";
1183dda28197Spatrick     environment = "macabi";
1184dda28197Spatrick   } else {
1185dda28197Spatrick     os_name = value.str();
1186dda28197Spatrick   }
1187dda28197Spatrick }
1188dda28197Spatrick 
GetHostInfo(bool force)1189061da546Spatrick bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
1190*f6aab3d8Srobert   Log *log = GetLog(GDBRLog::Process);
1191061da546Spatrick 
1192061da546Spatrick   if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) {
1193061da546Spatrick     // host info computation can require DNS traffic and shelling out to external processes.
1194061da546Spatrick     // Increase the timeout to account for that.
1195061da546Spatrick     ScopedTimeout timeout(*this, seconds(10));
1196061da546Spatrick     m_qHostInfo_is_valid = eLazyBoolNo;
1197061da546Spatrick     StringExtractorGDBRemote response;
1198be691f3bSpatrick     if (SendPacketAndWaitForResponse("qHostInfo", response) ==
1199061da546Spatrick         PacketResult::Success) {
1200061da546Spatrick       if (response.IsNormalResponse()) {
1201061da546Spatrick         llvm::StringRef name;
1202061da546Spatrick         llvm::StringRef value;
1203061da546Spatrick         uint32_t cpu = LLDB_INVALID_CPUTYPE;
1204061da546Spatrick         uint32_t sub = 0;
1205061da546Spatrick         std::string arch_name;
1206061da546Spatrick         std::string os_name;
1207061da546Spatrick         std::string environment;
1208061da546Spatrick         std::string vendor_name;
1209061da546Spatrick         std::string triple;
1210061da546Spatrick         std::string distribution_id;
1211061da546Spatrick         uint32_t pointer_byte_size = 0;
1212061da546Spatrick         ByteOrder byte_order = eByteOrderInvalid;
1213061da546Spatrick         uint32_t num_keys_decoded = 0;
1214061da546Spatrick         while (response.GetNameColonValue(name, value)) {
1215061da546Spatrick           if (name.equals("cputype")) {
1216061da546Spatrick             // exception type in big endian hex
1217061da546Spatrick             if (!value.getAsInteger(0, cpu))
1218061da546Spatrick               ++num_keys_decoded;
1219061da546Spatrick           } else if (name.equals("cpusubtype")) {
1220061da546Spatrick             // exception count in big endian hex
1221061da546Spatrick             if (!value.getAsInteger(0, sub))
1222061da546Spatrick               ++num_keys_decoded;
1223061da546Spatrick           } else if (name.equals("arch")) {
1224dda28197Spatrick             arch_name = std::string(value);
1225061da546Spatrick             ++num_keys_decoded;
1226061da546Spatrick           } else if (name.equals("triple")) {
1227061da546Spatrick             StringExtractor extractor(value);
1228061da546Spatrick             extractor.GetHexByteString(triple);
1229061da546Spatrick             ++num_keys_decoded;
1230061da546Spatrick           } else if (name.equals("distribution_id")) {
1231061da546Spatrick             StringExtractor extractor(value);
1232061da546Spatrick             extractor.GetHexByteString(distribution_id);
1233061da546Spatrick             ++num_keys_decoded;
1234061da546Spatrick           } else if (name.equals("os_build")) {
1235061da546Spatrick             StringExtractor extractor(value);
1236061da546Spatrick             extractor.GetHexByteString(m_os_build);
1237061da546Spatrick             ++num_keys_decoded;
1238061da546Spatrick           } else if (name.equals("hostname")) {
1239061da546Spatrick             StringExtractor extractor(value);
1240061da546Spatrick             extractor.GetHexByteString(m_hostname);
1241061da546Spatrick             ++num_keys_decoded;
1242061da546Spatrick           } else if (name.equals("os_kernel")) {
1243061da546Spatrick             StringExtractor extractor(value);
1244061da546Spatrick             extractor.GetHexByteString(m_os_kernel);
1245061da546Spatrick             ++num_keys_decoded;
1246061da546Spatrick           } else if (name.equals("ostype")) {
1247dda28197Spatrick             ParseOSType(value, os_name, environment);
1248061da546Spatrick             ++num_keys_decoded;
1249061da546Spatrick           } else if (name.equals("vendor")) {
1250dda28197Spatrick             vendor_name = std::string(value);
1251061da546Spatrick             ++num_keys_decoded;
1252061da546Spatrick           } else if (name.equals("endian")) {
1253061da546Spatrick             byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
1254061da546Spatrick                              .Case("little", eByteOrderLittle)
1255061da546Spatrick                              .Case("big", eByteOrderBig)
1256061da546Spatrick                              .Case("pdp", eByteOrderPDP)
1257061da546Spatrick                              .Default(eByteOrderInvalid);
1258061da546Spatrick             if (byte_order != eByteOrderInvalid)
1259061da546Spatrick               ++num_keys_decoded;
1260061da546Spatrick           } else if (name.equals("ptrsize")) {
1261061da546Spatrick             if (!value.getAsInteger(0, pointer_byte_size))
1262061da546Spatrick               ++num_keys_decoded;
1263be691f3bSpatrick           } else if (name.equals("addressing_bits")) {
1264be691f3bSpatrick             if (!value.getAsInteger(0, m_addressing_bits))
1265be691f3bSpatrick               ++num_keys_decoded;
1266061da546Spatrick           } else if (name.equals("os_version") ||
1267be691f3bSpatrick                      name.equals("version")) // Older debugserver binaries used
1268be691f3bSpatrick                                              // the "version" key instead of
1269061da546Spatrick                                              // "os_version"...
1270061da546Spatrick           {
1271061da546Spatrick             if (!m_os_version.tryParse(value))
1272061da546Spatrick               ++num_keys_decoded;
1273061da546Spatrick           } else if (name.equals("maccatalyst_version")) {
1274061da546Spatrick             if (!m_maccatalyst_version.tryParse(value))
1275061da546Spatrick               ++num_keys_decoded;
1276061da546Spatrick           } else if (name.equals("watchpoint_exceptions_received")) {
1277061da546Spatrick             m_watchpoints_trigger_after_instruction =
1278061da546Spatrick                 llvm::StringSwitch<LazyBool>(value)
1279061da546Spatrick                     .Case("before", eLazyBoolNo)
1280061da546Spatrick                     .Case("after", eLazyBoolYes)
1281061da546Spatrick                     .Default(eLazyBoolCalculate);
1282061da546Spatrick             if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate)
1283061da546Spatrick               ++num_keys_decoded;
1284061da546Spatrick           } else if (name.equals("default_packet_timeout")) {
1285061da546Spatrick             uint32_t timeout_seconds;
1286061da546Spatrick             if (!value.getAsInteger(0, timeout_seconds)) {
1287061da546Spatrick               m_default_packet_timeout = seconds(timeout_seconds);
1288061da546Spatrick               SetPacketTimeout(m_default_packet_timeout);
1289061da546Spatrick               ++num_keys_decoded;
1290061da546Spatrick             }
1291be691f3bSpatrick           } else if (name.equals("vm-page-size")) {
1292be691f3bSpatrick             int page_size;
1293be691f3bSpatrick             if (!value.getAsInteger(0, page_size)) {
1294be691f3bSpatrick               m_target_vm_page_size = page_size;
1295be691f3bSpatrick               ++num_keys_decoded;
1296be691f3bSpatrick             }
1297061da546Spatrick           }
1298061da546Spatrick         }
1299061da546Spatrick 
1300061da546Spatrick         if (num_keys_decoded > 0)
1301061da546Spatrick           m_qHostInfo_is_valid = eLazyBoolYes;
1302061da546Spatrick 
1303061da546Spatrick         if (triple.empty()) {
1304061da546Spatrick           if (arch_name.empty()) {
1305061da546Spatrick             if (cpu != LLDB_INVALID_CPUTYPE) {
1306061da546Spatrick               m_host_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
1307061da546Spatrick               if (pointer_byte_size) {
1308061da546Spatrick                 assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1309061da546Spatrick               }
1310061da546Spatrick               if (byte_order != eByteOrderInvalid) {
1311061da546Spatrick                 assert(byte_order == m_host_arch.GetByteOrder());
1312061da546Spatrick               }
1313061da546Spatrick 
1314061da546Spatrick               if (!vendor_name.empty())
1315061da546Spatrick                 m_host_arch.GetTriple().setVendorName(
1316061da546Spatrick                     llvm::StringRef(vendor_name));
1317061da546Spatrick               if (!os_name.empty())
1318061da546Spatrick                 m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name));
1319061da546Spatrick               if (!environment.empty())
1320061da546Spatrick                 m_host_arch.GetTriple().setEnvironmentName(environment);
1321061da546Spatrick             }
1322061da546Spatrick           } else {
1323061da546Spatrick             std::string triple;
1324061da546Spatrick             triple += arch_name;
1325061da546Spatrick             if (!vendor_name.empty() || !os_name.empty()) {
1326061da546Spatrick               triple += '-';
1327061da546Spatrick               if (vendor_name.empty())
1328061da546Spatrick                 triple += "unknown";
1329061da546Spatrick               else
1330061da546Spatrick                 triple += vendor_name;
1331061da546Spatrick               triple += '-';
1332061da546Spatrick               if (os_name.empty())
1333061da546Spatrick                 triple += "unknown";
1334061da546Spatrick               else
1335061da546Spatrick                 triple += os_name;
1336061da546Spatrick             }
1337061da546Spatrick             m_host_arch.SetTriple(triple.c_str());
1338061da546Spatrick 
1339061da546Spatrick             llvm::Triple &host_triple = m_host_arch.GetTriple();
1340061da546Spatrick             if (host_triple.getVendor() == llvm::Triple::Apple &&
1341061da546Spatrick                 host_triple.getOS() == llvm::Triple::Darwin) {
1342061da546Spatrick               switch (m_host_arch.GetMachine()) {
1343061da546Spatrick               case llvm::Triple::aarch64:
1344061da546Spatrick               case llvm::Triple::aarch64_32:
1345061da546Spatrick               case llvm::Triple::arm:
1346061da546Spatrick               case llvm::Triple::thumb:
1347061da546Spatrick                 host_triple.setOS(llvm::Triple::IOS);
1348061da546Spatrick                 break;
1349061da546Spatrick               default:
1350061da546Spatrick                 host_triple.setOS(llvm::Triple::MacOSX);
1351061da546Spatrick                 break;
1352061da546Spatrick               }
1353061da546Spatrick             }
1354061da546Spatrick             if (pointer_byte_size) {
1355061da546Spatrick               assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1356061da546Spatrick             }
1357061da546Spatrick             if (byte_order != eByteOrderInvalid) {
1358061da546Spatrick               assert(byte_order == m_host_arch.GetByteOrder());
1359061da546Spatrick             }
1360061da546Spatrick           }
1361061da546Spatrick         } else {
1362061da546Spatrick           m_host_arch.SetTriple(triple.c_str());
1363061da546Spatrick           if (pointer_byte_size) {
1364061da546Spatrick             assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1365061da546Spatrick           }
1366061da546Spatrick           if (byte_order != eByteOrderInvalid) {
1367061da546Spatrick             assert(byte_order == m_host_arch.GetByteOrder());
1368061da546Spatrick           }
1369061da546Spatrick 
1370061da546Spatrick           LLDB_LOGF(log,
1371061da546Spatrick                     "GDBRemoteCommunicationClient::%s parsed host "
1372061da546Spatrick                     "architecture as %s, triple as %s from triple text %s",
1373061da546Spatrick                     __FUNCTION__,
1374061da546Spatrick                     m_host_arch.GetArchitectureName()
1375061da546Spatrick                         ? m_host_arch.GetArchitectureName()
1376061da546Spatrick                         : "<null-arch-name>",
1377061da546Spatrick                     m_host_arch.GetTriple().getTriple().c_str(),
1378061da546Spatrick                     triple.c_str());
1379061da546Spatrick         }
1380061da546Spatrick         if (!distribution_id.empty())
1381061da546Spatrick           m_host_arch.SetDistributionId(distribution_id.c_str());
1382061da546Spatrick       }
1383061da546Spatrick     }
1384061da546Spatrick   }
1385061da546Spatrick   return m_qHostInfo_is_valid == eLazyBoolYes;
1386061da546Spatrick }
1387061da546Spatrick 
SendStdinNotification(const char * data,size_t data_len)1388061da546Spatrick int GDBRemoteCommunicationClient::SendStdinNotification(const char *data,
1389061da546Spatrick                                                         size_t data_len) {
1390061da546Spatrick   StreamString packet;
1391061da546Spatrick   packet.PutCString("I");
1392061da546Spatrick   packet.PutBytesAsRawHex8(data, data_len);
1393061da546Spatrick   StringExtractorGDBRemote response;
1394be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1395061da546Spatrick       PacketResult::Success) {
1396061da546Spatrick     return 0;
1397061da546Spatrick   }
1398061da546Spatrick   return response.GetError();
1399061da546Spatrick }
1400061da546Spatrick 
1401061da546Spatrick const lldb_private::ArchSpec &
GetHostArchitecture()1402061da546Spatrick GDBRemoteCommunicationClient::GetHostArchitecture() {
1403061da546Spatrick   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1404061da546Spatrick     GetHostInfo();
1405061da546Spatrick   return m_host_arch;
1406061da546Spatrick }
1407061da546Spatrick 
GetAddressingBits()1408be691f3bSpatrick uint32_t GDBRemoteCommunicationClient::GetAddressingBits() {
1409be691f3bSpatrick   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1410be691f3bSpatrick     GetHostInfo();
1411be691f3bSpatrick   return m_addressing_bits;
1412be691f3bSpatrick }
GetHostDefaultPacketTimeout()1413061da546Spatrick seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() {
1414061da546Spatrick   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1415061da546Spatrick     GetHostInfo();
1416061da546Spatrick   return m_default_packet_timeout;
1417061da546Spatrick }
1418061da546Spatrick 
AllocateMemory(size_t size,uint32_t permissions)1419061da546Spatrick addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size,
1420061da546Spatrick                                                     uint32_t permissions) {
1421061da546Spatrick   if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
1422061da546Spatrick     m_supports_alloc_dealloc_memory = eLazyBoolYes;
1423061da546Spatrick     char packet[64];
1424061da546Spatrick     const int packet_len = ::snprintf(
1425061da546Spatrick         packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s", (uint64_t)size,
1426061da546Spatrick         permissions & lldb::ePermissionsReadable ? "r" : "",
1427061da546Spatrick         permissions & lldb::ePermissionsWritable ? "w" : "",
1428061da546Spatrick         permissions & lldb::ePermissionsExecutable ? "x" : "");
1429061da546Spatrick     assert(packet_len < (int)sizeof(packet));
1430061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
1431061da546Spatrick     StringExtractorGDBRemote response;
1432be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
1433061da546Spatrick         PacketResult::Success) {
1434061da546Spatrick       if (response.IsUnsupportedResponse())
1435061da546Spatrick         m_supports_alloc_dealloc_memory = eLazyBoolNo;
1436061da546Spatrick       else if (!response.IsErrorResponse())
1437061da546Spatrick         return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
1438061da546Spatrick     } else {
1439061da546Spatrick       m_supports_alloc_dealloc_memory = eLazyBoolNo;
1440061da546Spatrick     }
1441061da546Spatrick   }
1442061da546Spatrick   return LLDB_INVALID_ADDRESS;
1443061da546Spatrick }
1444061da546Spatrick 
DeallocateMemory(addr_t addr)1445061da546Spatrick bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) {
1446061da546Spatrick   if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
1447061da546Spatrick     m_supports_alloc_dealloc_memory = eLazyBoolYes;
1448061da546Spatrick     char packet[64];
1449061da546Spatrick     const int packet_len =
1450061da546Spatrick         ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
1451061da546Spatrick     assert(packet_len < (int)sizeof(packet));
1452061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
1453061da546Spatrick     StringExtractorGDBRemote response;
1454be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
1455061da546Spatrick         PacketResult::Success) {
1456061da546Spatrick       if (response.IsUnsupportedResponse())
1457061da546Spatrick         m_supports_alloc_dealloc_memory = eLazyBoolNo;
1458061da546Spatrick       else if (response.IsOKResponse())
1459061da546Spatrick         return true;
1460061da546Spatrick     } else {
1461061da546Spatrick       m_supports_alloc_dealloc_memory = eLazyBoolNo;
1462061da546Spatrick     }
1463061da546Spatrick   }
1464061da546Spatrick   return false;
1465061da546Spatrick }
1466061da546Spatrick 
Detach(bool keep_stopped,lldb::pid_t pid)1467*f6aab3d8Srobert Status GDBRemoteCommunicationClient::Detach(bool keep_stopped,
1468*f6aab3d8Srobert                                             lldb::pid_t pid) {
1469061da546Spatrick   Status error;
1470*f6aab3d8Srobert   lldb_private::StreamString packet;
1471061da546Spatrick 
1472*f6aab3d8Srobert   packet.PutChar('D');
1473061da546Spatrick   if (keep_stopped) {
1474061da546Spatrick     if (m_supports_detach_stay_stopped == eLazyBoolCalculate) {
1475061da546Spatrick       char packet[64];
1476061da546Spatrick       const int packet_len =
1477061da546Spatrick           ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
1478061da546Spatrick       assert(packet_len < (int)sizeof(packet));
1479061da546Spatrick       UNUSED_IF_ASSERT_DISABLED(packet_len);
1480061da546Spatrick       StringExtractorGDBRemote response;
1481be691f3bSpatrick       if (SendPacketAndWaitForResponse(packet, response) ==
1482061da546Spatrick               PacketResult::Success &&
1483061da546Spatrick           response.IsOKResponse()) {
1484061da546Spatrick         m_supports_detach_stay_stopped = eLazyBoolYes;
1485061da546Spatrick       } else {
1486061da546Spatrick         m_supports_detach_stay_stopped = eLazyBoolNo;
1487061da546Spatrick       }
1488061da546Spatrick     }
1489061da546Spatrick 
1490061da546Spatrick     if (m_supports_detach_stay_stopped == eLazyBoolNo) {
1491061da546Spatrick       error.SetErrorString("Stays stopped not supported by this target.");
1492061da546Spatrick       return error;
1493061da546Spatrick     } else {
1494*f6aab3d8Srobert       packet.PutChar('1');
1495061da546Spatrick     }
1496061da546Spatrick   }
1497*f6aab3d8Srobert 
1498*f6aab3d8Srobert   if (GetMultiprocessSupported()) {
1499*f6aab3d8Srobert     // Some servers (e.g. qemu) require specifying the PID even if only a single
1500*f6aab3d8Srobert     // process is running.
1501*f6aab3d8Srobert     if (pid == LLDB_INVALID_PROCESS_ID)
1502*f6aab3d8Srobert       pid = GetCurrentProcessID();
1503*f6aab3d8Srobert     packet.PutChar(';');
1504*f6aab3d8Srobert     packet.PutHex64(pid);
1505*f6aab3d8Srobert   } else if (pid != LLDB_INVALID_PROCESS_ID) {
1506*f6aab3d8Srobert     error.SetErrorString("Multiprocess extension not supported by the server.");
1507*f6aab3d8Srobert     return error;
1508*f6aab3d8Srobert   }
1509*f6aab3d8Srobert 
1510*f6aab3d8Srobert   StringExtractorGDBRemote response;
1511*f6aab3d8Srobert   PacketResult packet_result =
1512*f6aab3d8Srobert       SendPacketAndWaitForResponse(packet.GetString(), response);
1513*f6aab3d8Srobert   if (packet_result != PacketResult::Success)
1514*f6aab3d8Srobert     error.SetErrorString("Sending isconnect packet failed.");
1515061da546Spatrick   return error;
1516061da546Spatrick }
1517061da546Spatrick 
GetMemoryRegionInfo(lldb::addr_t addr,lldb_private::MemoryRegionInfo & region_info)1518061da546Spatrick Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
1519061da546Spatrick     lldb::addr_t addr, lldb_private::MemoryRegionInfo &region_info) {
1520061da546Spatrick   Status error;
1521061da546Spatrick   region_info.Clear();
1522061da546Spatrick 
1523061da546Spatrick   if (m_supports_memory_region_info != eLazyBoolNo) {
1524061da546Spatrick     m_supports_memory_region_info = eLazyBoolYes;
1525061da546Spatrick     char packet[64];
1526061da546Spatrick     const int packet_len = ::snprintf(
1527061da546Spatrick         packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
1528061da546Spatrick     assert(packet_len < (int)sizeof(packet));
1529061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
1530061da546Spatrick     StringExtractorGDBRemote response;
1531be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
1532061da546Spatrick             PacketResult::Success &&
1533061da546Spatrick         response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
1534061da546Spatrick       llvm::StringRef name;
1535061da546Spatrick       llvm::StringRef value;
1536061da546Spatrick       addr_t addr_value = LLDB_INVALID_ADDRESS;
1537061da546Spatrick       bool success = true;
1538061da546Spatrick       bool saw_permissions = false;
1539061da546Spatrick       while (success && response.GetNameColonValue(name, value)) {
1540061da546Spatrick         if (name.equals("start")) {
1541061da546Spatrick           if (!value.getAsInteger(16, addr_value))
1542061da546Spatrick             region_info.GetRange().SetRangeBase(addr_value);
1543061da546Spatrick         } else if (name.equals("size")) {
1544*f6aab3d8Srobert           if (!value.getAsInteger(16, addr_value)) {
1545061da546Spatrick             region_info.GetRange().SetByteSize(addr_value);
1546*f6aab3d8Srobert             if (region_info.GetRange().GetRangeEnd() <
1547*f6aab3d8Srobert                 region_info.GetRange().GetRangeBase()) {
1548*f6aab3d8Srobert               // Range size overflowed, truncate it.
1549*f6aab3d8Srobert               region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
1550*f6aab3d8Srobert             }
1551*f6aab3d8Srobert           }
1552061da546Spatrick         } else if (name.equals("permissions") &&
1553061da546Spatrick                    region_info.GetRange().IsValid()) {
1554061da546Spatrick           saw_permissions = true;
1555061da546Spatrick           if (region_info.GetRange().Contains(addr)) {
1556*f6aab3d8Srobert             if (value.contains('r'))
1557061da546Spatrick               region_info.SetReadable(MemoryRegionInfo::eYes);
1558061da546Spatrick             else
1559061da546Spatrick               region_info.SetReadable(MemoryRegionInfo::eNo);
1560061da546Spatrick 
1561*f6aab3d8Srobert             if (value.contains('w'))
1562061da546Spatrick               region_info.SetWritable(MemoryRegionInfo::eYes);
1563061da546Spatrick             else
1564061da546Spatrick               region_info.SetWritable(MemoryRegionInfo::eNo);
1565061da546Spatrick 
1566*f6aab3d8Srobert             if (value.contains('x'))
1567061da546Spatrick               region_info.SetExecutable(MemoryRegionInfo::eYes);
1568061da546Spatrick             else
1569061da546Spatrick               region_info.SetExecutable(MemoryRegionInfo::eNo);
1570061da546Spatrick 
1571061da546Spatrick             region_info.SetMapped(MemoryRegionInfo::eYes);
1572061da546Spatrick           } else {
1573061da546Spatrick             // The reported region does not contain this address -- we're
1574061da546Spatrick             // looking at an unmapped page
1575061da546Spatrick             region_info.SetReadable(MemoryRegionInfo::eNo);
1576061da546Spatrick             region_info.SetWritable(MemoryRegionInfo::eNo);
1577061da546Spatrick             region_info.SetExecutable(MemoryRegionInfo::eNo);
1578061da546Spatrick             region_info.SetMapped(MemoryRegionInfo::eNo);
1579061da546Spatrick           }
1580061da546Spatrick         } else if (name.equals("name")) {
1581061da546Spatrick           StringExtractorGDBRemote name_extractor(value);
1582061da546Spatrick           std::string name;
1583061da546Spatrick           name_extractor.GetHexByteString(name);
1584061da546Spatrick           region_info.SetName(name.c_str());
1585be691f3bSpatrick         } else if (name.equals("flags")) {
1586be691f3bSpatrick           region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
1587be691f3bSpatrick 
1588be691f3bSpatrick           llvm::StringRef flags = value;
1589be691f3bSpatrick           llvm::StringRef flag;
1590be691f3bSpatrick           while (flags.size()) {
1591be691f3bSpatrick             flags = flags.ltrim();
1592be691f3bSpatrick             std::tie(flag, flags) = flags.split(' ');
1593be691f3bSpatrick             // To account for trailing whitespace
1594be691f3bSpatrick             if (flag.size()) {
1595be691f3bSpatrick               if (flag == "mt") {
1596be691f3bSpatrick                 region_info.SetMemoryTagged(MemoryRegionInfo::eYes);
1597be691f3bSpatrick                 break;
1598be691f3bSpatrick               }
1599be691f3bSpatrick             }
1600be691f3bSpatrick           }
1601*f6aab3d8Srobert         } else if (name.equals("type")) {
1602*f6aab3d8Srobert           std::string comma_sep_str = value.str();
1603*f6aab3d8Srobert           size_t comma_pos;
1604*f6aab3d8Srobert           while ((comma_pos = comma_sep_str.find(',')) != std::string::npos) {
1605*f6aab3d8Srobert             comma_sep_str[comma_pos] = '\0';
1606*f6aab3d8Srobert             if (comma_sep_str == "stack") {
1607*f6aab3d8Srobert               region_info.SetIsStackMemory(MemoryRegionInfo::eYes);
1608*f6aab3d8Srobert             }
1609*f6aab3d8Srobert           }
1610*f6aab3d8Srobert           // handle final (or only) type of "stack"
1611*f6aab3d8Srobert           if (comma_sep_str == "stack") {
1612*f6aab3d8Srobert             region_info.SetIsStackMemory(MemoryRegionInfo::eYes);
1613*f6aab3d8Srobert           }
1614061da546Spatrick         } else if (name.equals("error")) {
1615061da546Spatrick           StringExtractorGDBRemote error_extractor(value);
1616061da546Spatrick           std::string error_string;
1617061da546Spatrick           // Now convert the HEX bytes into a string value
1618061da546Spatrick           error_extractor.GetHexByteString(error_string);
1619061da546Spatrick           error.SetErrorString(error_string.c_str());
1620be691f3bSpatrick         } else if (name.equals("dirty-pages")) {
1621be691f3bSpatrick           std::vector<addr_t> dirty_page_list;
1622*f6aab3d8Srobert           for (llvm::StringRef x : llvm::split(value, ',')) {
1623be691f3bSpatrick             addr_t page;
1624*f6aab3d8Srobert             x.consume_front("0x");
1625*f6aab3d8Srobert             if (llvm::to_integer(x, page, 16))
1626be691f3bSpatrick               dirty_page_list.push_back(page);
1627be691f3bSpatrick           }
1628be691f3bSpatrick           region_info.SetDirtyPageList(dirty_page_list);
1629061da546Spatrick         }
1630061da546Spatrick       }
1631061da546Spatrick 
1632be691f3bSpatrick       if (m_target_vm_page_size != 0)
1633be691f3bSpatrick         region_info.SetPageSize(m_target_vm_page_size);
1634be691f3bSpatrick 
1635061da546Spatrick       if (region_info.GetRange().IsValid()) {
1636061da546Spatrick         // We got a valid address range back but no permissions -- which means
1637061da546Spatrick         // this is an unmapped page
1638061da546Spatrick         if (!saw_permissions) {
1639061da546Spatrick           region_info.SetReadable(MemoryRegionInfo::eNo);
1640061da546Spatrick           region_info.SetWritable(MemoryRegionInfo::eNo);
1641061da546Spatrick           region_info.SetExecutable(MemoryRegionInfo::eNo);
1642061da546Spatrick           region_info.SetMapped(MemoryRegionInfo::eNo);
1643061da546Spatrick         }
1644061da546Spatrick       } else {
1645061da546Spatrick         // We got an invalid address range back
1646061da546Spatrick         error.SetErrorString("Server returned invalid range");
1647061da546Spatrick       }
1648061da546Spatrick     } else {
1649061da546Spatrick       m_supports_memory_region_info = eLazyBoolNo;
1650061da546Spatrick     }
1651061da546Spatrick   }
1652061da546Spatrick 
1653061da546Spatrick   if (m_supports_memory_region_info == eLazyBoolNo) {
1654061da546Spatrick     error.SetErrorString("qMemoryRegionInfo is not supported");
1655061da546Spatrick   }
1656061da546Spatrick 
1657061da546Spatrick   // Try qXfer:memory-map:read to get region information not included in
1658061da546Spatrick   // qMemoryRegionInfo
1659061da546Spatrick   MemoryRegionInfo qXfer_region_info;
1660061da546Spatrick   Status qXfer_error = GetQXferMemoryMapRegionInfo(addr, qXfer_region_info);
1661061da546Spatrick 
1662061da546Spatrick   if (error.Fail()) {
1663061da546Spatrick     // If qMemoryRegionInfo failed, but qXfer:memory-map:read succeeded, use
1664061da546Spatrick     // the qXfer result as a fallback
1665061da546Spatrick     if (qXfer_error.Success()) {
1666061da546Spatrick       region_info = qXfer_region_info;
1667061da546Spatrick       error.Clear();
1668061da546Spatrick     } else {
1669061da546Spatrick       region_info.Clear();
1670061da546Spatrick     }
1671061da546Spatrick   } else if (qXfer_error.Success()) {
1672061da546Spatrick     // If both qMemoryRegionInfo and qXfer:memory-map:read succeeded, and if
1673061da546Spatrick     // both regions are the same range, update the result to include the flash-
1674061da546Spatrick     // memory information that is specific to the qXfer result.
1675061da546Spatrick     if (region_info.GetRange() == qXfer_region_info.GetRange()) {
1676061da546Spatrick       region_info.SetFlash(qXfer_region_info.GetFlash());
1677061da546Spatrick       region_info.SetBlocksize(qXfer_region_info.GetBlocksize());
1678061da546Spatrick     }
1679061da546Spatrick   }
1680061da546Spatrick   return error;
1681061da546Spatrick }
1682061da546Spatrick 
GetQXferMemoryMapRegionInfo(lldb::addr_t addr,MemoryRegionInfo & region)1683061da546Spatrick Status GDBRemoteCommunicationClient::GetQXferMemoryMapRegionInfo(
1684061da546Spatrick     lldb::addr_t addr, MemoryRegionInfo &region) {
1685061da546Spatrick   Status error = LoadQXferMemoryMap();
1686061da546Spatrick   if (!error.Success())
1687061da546Spatrick     return error;
1688061da546Spatrick   for (const auto &map_region : m_qXfer_memory_map) {
1689061da546Spatrick     if (map_region.GetRange().Contains(addr)) {
1690061da546Spatrick       region = map_region;
1691061da546Spatrick       return error;
1692061da546Spatrick     }
1693061da546Spatrick   }
1694061da546Spatrick   error.SetErrorString("Region not found");
1695061da546Spatrick   return error;
1696061da546Spatrick }
1697061da546Spatrick 
LoadQXferMemoryMap()1698061da546Spatrick Status GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
1699061da546Spatrick 
1700061da546Spatrick   Status error;
1701061da546Spatrick 
1702061da546Spatrick   if (m_qXfer_memory_map_loaded)
1703061da546Spatrick     // Already loaded, return success
1704061da546Spatrick     return error;
1705061da546Spatrick 
1706061da546Spatrick   if (!XMLDocument::XMLEnabled()) {
1707061da546Spatrick     error.SetErrorString("XML is not supported");
1708061da546Spatrick     return error;
1709061da546Spatrick   }
1710061da546Spatrick 
1711061da546Spatrick   if (!GetQXferMemoryMapReadSupported()) {
1712061da546Spatrick     error.SetErrorString("Memory map is not supported");
1713061da546Spatrick     return error;
1714061da546Spatrick   }
1715061da546Spatrick 
1716*f6aab3d8Srobert   llvm::Expected<std::string> xml = ReadExtFeature("memory-map", "");
1717*f6aab3d8Srobert   if (!xml)
1718*f6aab3d8Srobert     return Status(xml.takeError());
1719061da546Spatrick 
1720061da546Spatrick   XMLDocument xml_document;
1721061da546Spatrick 
1722*f6aab3d8Srobert   if (!xml_document.ParseMemory(xml->c_str(), xml->size())) {
1723061da546Spatrick     error.SetErrorString("Failed to parse memory map xml");
1724061da546Spatrick     return error;
1725061da546Spatrick   }
1726061da546Spatrick 
1727061da546Spatrick   XMLNode map_node = xml_document.GetRootElement("memory-map");
1728061da546Spatrick   if (!map_node) {
1729061da546Spatrick     error.SetErrorString("Invalid root node in memory map xml");
1730061da546Spatrick     return error;
1731061da546Spatrick   }
1732061da546Spatrick 
1733061da546Spatrick   m_qXfer_memory_map.clear();
1734061da546Spatrick 
1735061da546Spatrick   map_node.ForEachChildElement([this](const XMLNode &memory_node) -> bool {
1736061da546Spatrick     if (!memory_node.IsElement())
1737061da546Spatrick       return true;
1738061da546Spatrick     if (memory_node.GetName() != "memory")
1739061da546Spatrick       return true;
1740061da546Spatrick     auto type = memory_node.GetAttributeValue("type", "");
1741061da546Spatrick     uint64_t start;
1742061da546Spatrick     uint64_t length;
1743061da546Spatrick     if (!memory_node.GetAttributeValueAsUnsigned("start", start))
1744061da546Spatrick       return true;
1745061da546Spatrick     if (!memory_node.GetAttributeValueAsUnsigned("length", length))
1746061da546Spatrick       return true;
1747061da546Spatrick     MemoryRegionInfo region;
1748061da546Spatrick     region.GetRange().SetRangeBase(start);
1749061da546Spatrick     region.GetRange().SetByteSize(length);
1750061da546Spatrick     if (type == "rom") {
1751061da546Spatrick       region.SetReadable(MemoryRegionInfo::eYes);
1752061da546Spatrick       this->m_qXfer_memory_map.push_back(region);
1753061da546Spatrick     } else if (type == "ram") {
1754061da546Spatrick       region.SetReadable(MemoryRegionInfo::eYes);
1755061da546Spatrick       region.SetWritable(MemoryRegionInfo::eYes);
1756061da546Spatrick       this->m_qXfer_memory_map.push_back(region);
1757061da546Spatrick     } else if (type == "flash") {
1758061da546Spatrick       region.SetFlash(MemoryRegionInfo::eYes);
1759061da546Spatrick       memory_node.ForEachChildElement(
1760061da546Spatrick           [&region](const XMLNode &prop_node) -> bool {
1761061da546Spatrick             if (!prop_node.IsElement())
1762061da546Spatrick               return true;
1763061da546Spatrick             if (prop_node.GetName() != "property")
1764061da546Spatrick               return true;
1765061da546Spatrick             auto propname = prop_node.GetAttributeValue("name", "");
1766061da546Spatrick             if (propname == "blocksize") {
1767061da546Spatrick               uint64_t blocksize;
1768061da546Spatrick               if (prop_node.GetElementTextAsUnsigned(blocksize))
1769061da546Spatrick                 region.SetBlocksize(blocksize);
1770061da546Spatrick             }
1771061da546Spatrick             return true;
1772061da546Spatrick           });
1773061da546Spatrick       this->m_qXfer_memory_map.push_back(region);
1774061da546Spatrick     }
1775061da546Spatrick     return true;
1776061da546Spatrick   });
1777061da546Spatrick 
1778061da546Spatrick   m_qXfer_memory_map_loaded = true;
1779061da546Spatrick 
1780061da546Spatrick   return error;
1781061da546Spatrick }
1782061da546Spatrick 
GetWatchpointSupportInfo(uint32_t & num)1783061da546Spatrick Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
1784061da546Spatrick   Status error;
1785061da546Spatrick 
1786061da546Spatrick   if (m_supports_watchpoint_support_info == eLazyBoolYes) {
1787061da546Spatrick     num = m_num_supported_hardware_watchpoints;
1788061da546Spatrick     return error;
1789061da546Spatrick   }
1790061da546Spatrick 
1791061da546Spatrick   // Set num to 0 first.
1792061da546Spatrick   num = 0;
1793061da546Spatrick   if (m_supports_watchpoint_support_info != eLazyBoolNo) {
1794061da546Spatrick     StringExtractorGDBRemote response;
1795be691f3bSpatrick     if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) ==
1796061da546Spatrick         PacketResult::Success) {
1797061da546Spatrick       m_supports_watchpoint_support_info = eLazyBoolYes;
1798061da546Spatrick       llvm::StringRef name;
1799061da546Spatrick       llvm::StringRef value;
1800061da546Spatrick       bool found_num_field = false;
1801061da546Spatrick       while (response.GetNameColonValue(name, value)) {
1802061da546Spatrick         if (name.equals("num")) {
1803061da546Spatrick           value.getAsInteger(0, m_num_supported_hardware_watchpoints);
1804061da546Spatrick           num = m_num_supported_hardware_watchpoints;
1805061da546Spatrick           found_num_field = true;
1806061da546Spatrick         }
1807061da546Spatrick       }
1808061da546Spatrick       if (!found_num_field) {
1809061da546Spatrick         m_supports_watchpoint_support_info = eLazyBoolNo;
1810061da546Spatrick       }
1811061da546Spatrick     } else {
1812061da546Spatrick       m_supports_watchpoint_support_info = eLazyBoolNo;
1813061da546Spatrick     }
1814061da546Spatrick   }
1815061da546Spatrick 
1816061da546Spatrick   if (m_supports_watchpoint_support_info == eLazyBoolNo) {
1817061da546Spatrick     error.SetErrorString("qWatchpointSupportInfo is not supported");
1818061da546Spatrick   }
1819061da546Spatrick   return error;
1820061da546Spatrick }
1821061da546Spatrick 
GetWatchpointSupportInfo(uint32_t & num,bool & after,const ArchSpec & arch)1822061da546Spatrick lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(
1823061da546Spatrick     uint32_t &num, bool &after, const ArchSpec &arch) {
1824061da546Spatrick   Status error(GetWatchpointSupportInfo(num));
1825061da546Spatrick   if (error.Success())
1826061da546Spatrick     error = GetWatchpointsTriggerAfterInstruction(after, arch);
1827061da546Spatrick   return error;
1828061da546Spatrick }
1829061da546Spatrick 
1830061da546Spatrick lldb_private::Status
GetWatchpointsTriggerAfterInstruction(bool & after,const ArchSpec & arch)1831061da546Spatrick GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
1832061da546Spatrick     bool &after, const ArchSpec &arch) {
1833061da546Spatrick   Status error;
1834061da546Spatrick   llvm::Triple triple = arch.GetTriple();
1835061da546Spatrick 
1836061da546Spatrick   // we assume watchpoints will happen after running the relevant opcode and we
1837061da546Spatrick   // only want to override this behavior if we have explicitly received a
1838061da546Spatrick   // qHostInfo telling us otherwise
1839061da546Spatrick   if (m_qHostInfo_is_valid != eLazyBoolYes) {
1840061da546Spatrick     // On targets like MIPS and ppc64, watchpoint exceptions are always
1841061da546Spatrick     // generated before the instruction is executed. The connected target may
1842061da546Spatrick     // not support qHostInfo or qWatchpointSupportInfo packets.
1843061da546Spatrick     after = !(triple.isMIPS() || triple.isPPC64());
1844061da546Spatrick   } else {
1845061da546Spatrick     // For MIPS and ppc64, set m_watchpoints_trigger_after_instruction to
1846061da546Spatrick     // eLazyBoolNo if it is not calculated before.
1847061da546Spatrick     if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate &&
1848061da546Spatrick         (triple.isMIPS() || triple.isPPC64()))
1849061da546Spatrick       m_watchpoints_trigger_after_instruction = eLazyBoolNo;
1850061da546Spatrick 
1851061da546Spatrick     after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
1852061da546Spatrick   }
1853061da546Spatrick   return error;
1854061da546Spatrick }
1855061da546Spatrick 
SetSTDIN(const FileSpec & file_spec)1856061da546Spatrick int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) {
1857061da546Spatrick   if (file_spec) {
1858061da546Spatrick     std::string path{file_spec.GetPath(false)};
1859061da546Spatrick     StreamString packet;
1860061da546Spatrick     packet.PutCString("QSetSTDIN:");
1861061da546Spatrick     packet.PutStringAsRawHex8(path);
1862061da546Spatrick 
1863061da546Spatrick     StringExtractorGDBRemote response;
1864be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1865061da546Spatrick         PacketResult::Success) {
1866061da546Spatrick       if (response.IsOKResponse())
1867061da546Spatrick         return 0;
1868061da546Spatrick       uint8_t error = response.GetError();
1869061da546Spatrick       if (error)
1870061da546Spatrick         return error;
1871061da546Spatrick     }
1872061da546Spatrick   }
1873061da546Spatrick   return -1;
1874061da546Spatrick }
1875061da546Spatrick 
SetSTDOUT(const FileSpec & file_spec)1876061da546Spatrick int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) {
1877061da546Spatrick   if (file_spec) {
1878061da546Spatrick     std::string path{file_spec.GetPath(false)};
1879061da546Spatrick     StreamString packet;
1880061da546Spatrick     packet.PutCString("QSetSTDOUT:");
1881061da546Spatrick     packet.PutStringAsRawHex8(path);
1882061da546Spatrick 
1883061da546Spatrick     StringExtractorGDBRemote response;
1884be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1885061da546Spatrick         PacketResult::Success) {
1886061da546Spatrick       if (response.IsOKResponse())
1887061da546Spatrick         return 0;
1888061da546Spatrick       uint8_t error = response.GetError();
1889061da546Spatrick       if (error)
1890061da546Spatrick         return error;
1891061da546Spatrick     }
1892061da546Spatrick   }
1893061da546Spatrick   return -1;
1894061da546Spatrick }
1895061da546Spatrick 
SetSTDERR(const FileSpec & file_spec)1896061da546Spatrick int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) {
1897061da546Spatrick   if (file_spec) {
1898061da546Spatrick     std::string path{file_spec.GetPath(false)};
1899061da546Spatrick     StreamString packet;
1900061da546Spatrick     packet.PutCString("QSetSTDERR:");
1901061da546Spatrick     packet.PutStringAsRawHex8(path);
1902061da546Spatrick 
1903061da546Spatrick     StringExtractorGDBRemote response;
1904be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1905061da546Spatrick         PacketResult::Success) {
1906061da546Spatrick       if (response.IsOKResponse())
1907061da546Spatrick         return 0;
1908061da546Spatrick       uint8_t error = response.GetError();
1909061da546Spatrick       if (error)
1910061da546Spatrick         return error;
1911061da546Spatrick     }
1912061da546Spatrick   }
1913061da546Spatrick   return -1;
1914061da546Spatrick }
1915061da546Spatrick 
GetWorkingDir(FileSpec & working_dir)1916061da546Spatrick bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
1917061da546Spatrick   StringExtractorGDBRemote response;
1918be691f3bSpatrick   if (SendPacketAndWaitForResponse("qGetWorkingDir", response) ==
1919061da546Spatrick       PacketResult::Success) {
1920061da546Spatrick     if (response.IsUnsupportedResponse())
1921061da546Spatrick       return false;
1922061da546Spatrick     if (response.IsErrorResponse())
1923061da546Spatrick       return false;
1924061da546Spatrick     std::string cwd;
1925061da546Spatrick     response.GetHexByteString(cwd);
1926061da546Spatrick     working_dir.SetFile(cwd, GetHostArchitecture().GetTriple());
1927061da546Spatrick     return !cwd.empty();
1928061da546Spatrick   }
1929061da546Spatrick   return false;
1930061da546Spatrick }
1931061da546Spatrick 
SetWorkingDir(const FileSpec & working_dir)1932061da546Spatrick int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) {
1933061da546Spatrick   if (working_dir) {
1934061da546Spatrick     std::string path{working_dir.GetPath(false)};
1935061da546Spatrick     StreamString packet;
1936061da546Spatrick     packet.PutCString("QSetWorkingDir:");
1937061da546Spatrick     packet.PutStringAsRawHex8(path);
1938061da546Spatrick 
1939061da546Spatrick     StringExtractorGDBRemote response;
1940be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1941061da546Spatrick         PacketResult::Success) {
1942061da546Spatrick       if (response.IsOKResponse())
1943061da546Spatrick         return 0;
1944061da546Spatrick       uint8_t error = response.GetError();
1945061da546Spatrick       if (error)
1946061da546Spatrick         return error;
1947061da546Spatrick     }
1948061da546Spatrick   }
1949061da546Spatrick   return -1;
1950061da546Spatrick }
1951061da546Spatrick 
SetDisableASLR(bool enable)1952061da546Spatrick int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) {
1953061da546Spatrick   char packet[32];
1954061da546Spatrick   const int packet_len =
1955061da546Spatrick       ::snprintf(packet, sizeof(packet), "QSetDisableASLR:%i", enable ? 1 : 0);
1956061da546Spatrick   assert(packet_len < (int)sizeof(packet));
1957061da546Spatrick   UNUSED_IF_ASSERT_DISABLED(packet_len);
1958061da546Spatrick   StringExtractorGDBRemote response;
1959be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
1960061da546Spatrick     if (response.IsOKResponse())
1961061da546Spatrick       return 0;
1962061da546Spatrick     uint8_t error = response.GetError();
1963061da546Spatrick     if (error)
1964061da546Spatrick       return error;
1965061da546Spatrick   }
1966061da546Spatrick   return -1;
1967061da546Spatrick }
1968061da546Spatrick 
SetDetachOnError(bool enable)1969061da546Spatrick int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) {
1970061da546Spatrick   char packet[32];
1971061da546Spatrick   const int packet_len = ::snprintf(packet, sizeof(packet),
1972061da546Spatrick                                     "QSetDetachOnError:%i", enable ? 1 : 0);
1973061da546Spatrick   assert(packet_len < (int)sizeof(packet));
1974061da546Spatrick   UNUSED_IF_ASSERT_DISABLED(packet_len);
1975061da546Spatrick   StringExtractorGDBRemote response;
1976be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
1977061da546Spatrick     if (response.IsOKResponse())
1978061da546Spatrick       return 0;
1979061da546Spatrick     uint8_t error = response.GetError();
1980061da546Spatrick     if (error)
1981061da546Spatrick       return error;
1982061da546Spatrick   }
1983061da546Spatrick   return -1;
1984061da546Spatrick }
1985061da546Spatrick 
DecodeProcessInfoResponse(StringExtractorGDBRemote & response,ProcessInstanceInfo & process_info)1986061da546Spatrick bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
1987061da546Spatrick     StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) {
1988061da546Spatrick   if (response.IsNormalResponse()) {
1989061da546Spatrick     llvm::StringRef name;
1990061da546Spatrick     llvm::StringRef value;
1991061da546Spatrick     StringExtractor extractor;
1992061da546Spatrick 
1993061da546Spatrick     uint32_t cpu = LLDB_INVALID_CPUTYPE;
1994061da546Spatrick     uint32_t sub = 0;
1995061da546Spatrick     std::string vendor;
1996061da546Spatrick     std::string os_type;
1997061da546Spatrick 
1998061da546Spatrick     while (response.GetNameColonValue(name, value)) {
1999061da546Spatrick       if (name.equals("pid")) {
2000061da546Spatrick         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
2001061da546Spatrick         value.getAsInteger(0, pid);
2002061da546Spatrick         process_info.SetProcessID(pid);
2003061da546Spatrick       } else if (name.equals("ppid")) {
2004061da546Spatrick         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
2005061da546Spatrick         value.getAsInteger(0, pid);
2006061da546Spatrick         process_info.SetParentProcessID(pid);
2007061da546Spatrick       } else if (name.equals("uid")) {
2008061da546Spatrick         uint32_t uid = UINT32_MAX;
2009061da546Spatrick         value.getAsInteger(0, uid);
2010061da546Spatrick         process_info.SetUserID(uid);
2011061da546Spatrick       } else if (name.equals("euid")) {
2012061da546Spatrick         uint32_t uid = UINT32_MAX;
2013061da546Spatrick         value.getAsInteger(0, uid);
2014061da546Spatrick         process_info.SetEffectiveUserID(uid);
2015061da546Spatrick       } else if (name.equals("gid")) {
2016061da546Spatrick         uint32_t gid = UINT32_MAX;
2017061da546Spatrick         value.getAsInteger(0, gid);
2018061da546Spatrick         process_info.SetGroupID(gid);
2019061da546Spatrick       } else if (name.equals("egid")) {
2020061da546Spatrick         uint32_t gid = UINT32_MAX;
2021061da546Spatrick         value.getAsInteger(0, gid);
2022061da546Spatrick         process_info.SetEffectiveGroupID(gid);
2023061da546Spatrick       } else if (name.equals("triple")) {
2024061da546Spatrick         StringExtractor extractor(value);
2025061da546Spatrick         std::string triple;
2026061da546Spatrick         extractor.GetHexByteString(triple);
2027061da546Spatrick         process_info.GetArchitecture().SetTriple(triple.c_str());
2028061da546Spatrick       } else if (name.equals("name")) {
2029061da546Spatrick         StringExtractor extractor(value);
2030061da546Spatrick         // The process name from ASCII hex bytes since we can't control the
2031061da546Spatrick         // characters in a process name
2032061da546Spatrick         std::string name;
2033061da546Spatrick         extractor.GetHexByteString(name);
2034061da546Spatrick         process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);
2035061da546Spatrick       } else if (name.equals("args")) {
2036061da546Spatrick         llvm::StringRef encoded_args(value), hex_arg;
2037061da546Spatrick 
2038061da546Spatrick         bool is_arg0 = true;
2039061da546Spatrick         while (!encoded_args.empty()) {
2040061da546Spatrick           std::tie(hex_arg, encoded_args) = encoded_args.split('-');
2041061da546Spatrick           std::string arg;
2042061da546Spatrick           StringExtractor extractor(hex_arg);
2043061da546Spatrick           if (extractor.GetHexByteString(arg) * 2 != hex_arg.size()) {
2044061da546Spatrick             // In case of wrong encoding, we discard all the arguments
2045061da546Spatrick             process_info.GetArguments().Clear();
2046061da546Spatrick             process_info.SetArg0("");
2047061da546Spatrick             break;
2048061da546Spatrick           }
2049061da546Spatrick           if (is_arg0)
2050061da546Spatrick             process_info.SetArg0(arg);
2051061da546Spatrick           else
2052061da546Spatrick             process_info.GetArguments().AppendArgument(arg);
2053061da546Spatrick           is_arg0 = false;
2054061da546Spatrick         }
2055061da546Spatrick       } else if (name.equals("cputype")) {
2056061da546Spatrick         value.getAsInteger(0, cpu);
2057061da546Spatrick       } else if (name.equals("cpusubtype")) {
2058061da546Spatrick         value.getAsInteger(0, sub);
2059061da546Spatrick       } else if (name.equals("vendor")) {
2060dda28197Spatrick         vendor = std::string(value);
2061061da546Spatrick       } else if (name.equals("ostype")) {
2062dda28197Spatrick         os_type = std::string(value);
2063061da546Spatrick       }
2064061da546Spatrick     }
2065061da546Spatrick 
2066061da546Spatrick     if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty()) {
2067061da546Spatrick       if (vendor == "apple") {
2068061da546Spatrick         process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu,
2069061da546Spatrick                                                        sub);
2070061da546Spatrick         process_info.GetArchitecture().GetTriple().setVendorName(
2071061da546Spatrick             llvm::StringRef(vendor));
2072061da546Spatrick         process_info.GetArchitecture().GetTriple().setOSName(
2073061da546Spatrick             llvm::StringRef(os_type));
2074061da546Spatrick       }
2075061da546Spatrick     }
2076061da546Spatrick 
2077061da546Spatrick     if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
2078061da546Spatrick       return true;
2079061da546Spatrick   }
2080061da546Spatrick   return false;
2081061da546Spatrick }
2082061da546Spatrick 
GetProcessInfo(lldb::pid_t pid,ProcessInstanceInfo & process_info)2083061da546Spatrick bool GDBRemoteCommunicationClient::GetProcessInfo(
2084061da546Spatrick     lldb::pid_t pid, ProcessInstanceInfo &process_info) {
2085061da546Spatrick   process_info.Clear();
2086061da546Spatrick 
2087061da546Spatrick   if (m_supports_qProcessInfoPID) {
2088061da546Spatrick     char packet[32];
2089061da546Spatrick     const int packet_len =
2090061da546Spatrick         ::snprintf(packet, sizeof(packet), "qProcessInfoPID:%" PRIu64, pid);
2091061da546Spatrick     assert(packet_len < (int)sizeof(packet));
2092061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
2093061da546Spatrick     StringExtractorGDBRemote response;
2094be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
2095061da546Spatrick         PacketResult::Success) {
2096061da546Spatrick       return DecodeProcessInfoResponse(response, process_info);
2097061da546Spatrick     } else {
2098061da546Spatrick       m_supports_qProcessInfoPID = false;
2099061da546Spatrick       return false;
2100061da546Spatrick     }
2101061da546Spatrick   }
2102061da546Spatrick   return false;
2103061da546Spatrick }
2104061da546Spatrick 
GetCurrentProcessInfo(bool allow_lazy)2105061da546Spatrick bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
2106*f6aab3d8Srobert   Log *log(GetLog(GDBRLog::Process | GDBRLog::Packets));
2107061da546Spatrick 
2108061da546Spatrick   if (allow_lazy) {
2109061da546Spatrick     if (m_qProcessInfo_is_valid == eLazyBoolYes)
2110061da546Spatrick       return true;
2111061da546Spatrick     if (m_qProcessInfo_is_valid == eLazyBoolNo)
2112061da546Spatrick       return false;
2113061da546Spatrick   }
2114061da546Spatrick 
2115061da546Spatrick   GetHostInfo();
2116061da546Spatrick 
2117061da546Spatrick   StringExtractorGDBRemote response;
2118be691f3bSpatrick   if (SendPacketAndWaitForResponse("qProcessInfo", response) ==
2119061da546Spatrick       PacketResult::Success) {
2120061da546Spatrick     if (response.IsNormalResponse()) {
2121061da546Spatrick       llvm::StringRef name;
2122061da546Spatrick       llvm::StringRef value;
2123061da546Spatrick       uint32_t cpu = LLDB_INVALID_CPUTYPE;
2124061da546Spatrick       uint32_t sub = 0;
2125061da546Spatrick       std::string arch_name;
2126061da546Spatrick       std::string os_name;
2127061da546Spatrick       std::string environment;
2128061da546Spatrick       std::string vendor_name;
2129061da546Spatrick       std::string triple;
2130061da546Spatrick       std::string elf_abi;
2131061da546Spatrick       uint32_t pointer_byte_size = 0;
2132061da546Spatrick       StringExtractor extractor;
2133061da546Spatrick       ByteOrder byte_order = eByteOrderInvalid;
2134061da546Spatrick       uint32_t num_keys_decoded = 0;
2135061da546Spatrick       lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
2136061da546Spatrick       while (response.GetNameColonValue(name, value)) {
2137061da546Spatrick         if (name.equals("cputype")) {
2138061da546Spatrick           if (!value.getAsInteger(16, cpu))
2139061da546Spatrick             ++num_keys_decoded;
2140061da546Spatrick         } else if (name.equals("cpusubtype")) {
2141061da546Spatrick           if (!value.getAsInteger(16, sub))
2142061da546Spatrick             ++num_keys_decoded;
2143061da546Spatrick         } else if (name.equals("triple")) {
2144061da546Spatrick           StringExtractor extractor(value);
2145061da546Spatrick           extractor.GetHexByteString(triple);
2146061da546Spatrick           ++num_keys_decoded;
2147061da546Spatrick         } else if (name.equals("ostype")) {
2148dda28197Spatrick           ParseOSType(value, os_name, environment);
2149061da546Spatrick           ++num_keys_decoded;
2150061da546Spatrick         } else if (name.equals("vendor")) {
2151dda28197Spatrick           vendor_name = std::string(value);
2152061da546Spatrick           ++num_keys_decoded;
2153061da546Spatrick         } else if (name.equals("endian")) {
2154061da546Spatrick           byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
2155061da546Spatrick                            .Case("little", eByteOrderLittle)
2156061da546Spatrick                            .Case("big", eByteOrderBig)
2157061da546Spatrick                            .Case("pdp", eByteOrderPDP)
2158061da546Spatrick                            .Default(eByteOrderInvalid);
2159061da546Spatrick           if (byte_order != eByteOrderInvalid)
2160061da546Spatrick             ++num_keys_decoded;
2161061da546Spatrick         } else if (name.equals("ptrsize")) {
2162061da546Spatrick           if (!value.getAsInteger(16, pointer_byte_size))
2163061da546Spatrick             ++num_keys_decoded;
2164061da546Spatrick         } else if (name.equals("pid")) {
2165061da546Spatrick           if (!value.getAsInteger(16, pid))
2166061da546Spatrick             ++num_keys_decoded;
2167061da546Spatrick         } else if (name.equals("elf_abi")) {
2168dda28197Spatrick           elf_abi = std::string(value);
2169061da546Spatrick           ++num_keys_decoded;
2170*f6aab3d8Srobert         } else if (name.equals("main-binary-uuid")) {
2171*f6aab3d8Srobert           m_process_standalone_uuid.SetFromStringRef(value);
2172*f6aab3d8Srobert           ++num_keys_decoded;
2173*f6aab3d8Srobert         } else if (name.equals("main-binary-slide")) {
2174*f6aab3d8Srobert           StringExtractor extractor(value);
2175*f6aab3d8Srobert           m_process_standalone_value =
2176*f6aab3d8Srobert               extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
2177*f6aab3d8Srobert           if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
2178*f6aab3d8Srobert             m_process_standalone_value_is_offset = true;
2179*f6aab3d8Srobert             ++num_keys_decoded;
2180*f6aab3d8Srobert           }
2181*f6aab3d8Srobert         } else if (name.equals("main-binary-address")) {
2182*f6aab3d8Srobert           StringExtractor extractor(value);
2183*f6aab3d8Srobert           m_process_standalone_value =
2184*f6aab3d8Srobert               extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
2185*f6aab3d8Srobert           if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
2186*f6aab3d8Srobert             m_process_standalone_value_is_offset = false;
2187*f6aab3d8Srobert             ++num_keys_decoded;
2188*f6aab3d8Srobert           }
2189*f6aab3d8Srobert         } else if (name.equals("binary-addresses")) {
2190*f6aab3d8Srobert           m_binary_addresses.clear();
2191*f6aab3d8Srobert           ++num_keys_decoded;
2192*f6aab3d8Srobert           for (llvm::StringRef x : llvm::split(value, ',')) {
2193*f6aab3d8Srobert             addr_t vmaddr;
2194*f6aab3d8Srobert             x.consume_front("0x");
2195*f6aab3d8Srobert             if (llvm::to_integer(x, vmaddr, 16))
2196*f6aab3d8Srobert               m_binary_addresses.push_back(vmaddr);
2197*f6aab3d8Srobert           }
2198061da546Spatrick         }
2199061da546Spatrick       }
2200061da546Spatrick       if (num_keys_decoded > 0)
2201061da546Spatrick         m_qProcessInfo_is_valid = eLazyBoolYes;
2202061da546Spatrick       if (pid != LLDB_INVALID_PROCESS_ID) {
2203061da546Spatrick         m_curr_pid_is_valid = eLazyBoolYes;
2204be691f3bSpatrick         m_curr_pid_run = m_curr_pid = pid;
2205061da546Spatrick       }
2206061da546Spatrick 
2207061da546Spatrick       // Set the ArchSpec from the triple if we have it.
2208061da546Spatrick       if (!triple.empty()) {
2209061da546Spatrick         m_process_arch.SetTriple(triple.c_str());
2210061da546Spatrick         m_process_arch.SetFlags(elf_abi);
2211061da546Spatrick         if (pointer_byte_size) {
2212061da546Spatrick           assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
2213061da546Spatrick         }
2214061da546Spatrick       } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() &&
2215061da546Spatrick                  !vendor_name.empty()) {
2216061da546Spatrick         llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name);
2217061da546Spatrick         if (!environment.empty())
2218061da546Spatrick             triple.setEnvironmentName(environment);
2219061da546Spatrick 
2220061da546Spatrick         assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat);
2221061da546Spatrick         assert(triple.getObjectFormat() != llvm::Triple::Wasm);
2222061da546Spatrick         assert(triple.getObjectFormat() != llvm::Triple::XCOFF);
2223061da546Spatrick         switch (triple.getObjectFormat()) {
2224061da546Spatrick         case llvm::Triple::MachO:
2225061da546Spatrick           m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
2226061da546Spatrick           break;
2227061da546Spatrick         case llvm::Triple::ELF:
2228061da546Spatrick           m_process_arch.SetArchitecture(eArchTypeELF, cpu, sub);
2229061da546Spatrick           break;
2230061da546Spatrick         case llvm::Triple::COFF:
2231061da546Spatrick           m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub);
2232061da546Spatrick           break;
2233be691f3bSpatrick         case llvm::Triple::GOFF:
2234*f6aab3d8Srobert         case llvm::Triple::SPIRV:
2235061da546Spatrick         case llvm::Triple::Wasm:
2236061da546Spatrick         case llvm::Triple::XCOFF:
2237*f6aab3d8Srobert         case llvm::Triple::DXContainer:
2238061da546Spatrick           LLDB_LOGF(log, "error: not supported target architecture");
2239061da546Spatrick           return false;
2240061da546Spatrick         case llvm::Triple::UnknownObjectFormat:
2241061da546Spatrick           LLDB_LOGF(log, "error: failed to determine target architecture");
2242061da546Spatrick           return false;
2243061da546Spatrick         }
2244061da546Spatrick 
2245061da546Spatrick         if (pointer_byte_size) {
2246061da546Spatrick           assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
2247061da546Spatrick         }
2248061da546Spatrick         if (byte_order != eByteOrderInvalid) {
2249061da546Spatrick           assert(byte_order == m_process_arch.GetByteOrder());
2250061da546Spatrick         }
2251061da546Spatrick         m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name));
2252061da546Spatrick         m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name));
2253061da546Spatrick         m_process_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment));
2254061da546Spatrick       }
2255061da546Spatrick       return true;
2256061da546Spatrick     }
2257061da546Spatrick   } else {
2258061da546Spatrick     m_qProcessInfo_is_valid = eLazyBoolNo;
2259061da546Spatrick   }
2260061da546Spatrick 
2261061da546Spatrick   return false;
2262061da546Spatrick }
2263061da546Spatrick 
FindProcesses(const ProcessInstanceInfoMatch & match_info,ProcessInstanceInfoList & process_infos)2264061da546Spatrick uint32_t GDBRemoteCommunicationClient::FindProcesses(
2265061da546Spatrick     const ProcessInstanceInfoMatch &match_info,
2266061da546Spatrick     ProcessInstanceInfoList &process_infos) {
2267dda28197Spatrick   process_infos.clear();
2268061da546Spatrick 
2269061da546Spatrick   if (m_supports_qfProcessInfo) {
2270061da546Spatrick     StreamString packet;
2271061da546Spatrick     packet.PutCString("qfProcessInfo");
2272061da546Spatrick     if (!match_info.MatchAllProcesses()) {
2273061da546Spatrick       packet.PutChar(':');
2274061da546Spatrick       const char *name = match_info.GetProcessInfo().GetName();
2275061da546Spatrick       bool has_name_match = false;
2276061da546Spatrick       if (name && name[0]) {
2277061da546Spatrick         has_name_match = true;
2278061da546Spatrick         NameMatch name_match_type = match_info.GetNameMatchType();
2279061da546Spatrick         switch (name_match_type) {
2280061da546Spatrick         case NameMatch::Ignore:
2281061da546Spatrick           has_name_match = false;
2282061da546Spatrick           break;
2283061da546Spatrick 
2284061da546Spatrick         case NameMatch::Equals:
2285061da546Spatrick           packet.PutCString("name_match:equals;");
2286061da546Spatrick           break;
2287061da546Spatrick 
2288061da546Spatrick         case NameMatch::Contains:
2289061da546Spatrick           packet.PutCString("name_match:contains;");
2290061da546Spatrick           break;
2291061da546Spatrick 
2292061da546Spatrick         case NameMatch::StartsWith:
2293061da546Spatrick           packet.PutCString("name_match:starts_with;");
2294061da546Spatrick           break;
2295061da546Spatrick 
2296061da546Spatrick         case NameMatch::EndsWith:
2297061da546Spatrick           packet.PutCString("name_match:ends_with;");
2298061da546Spatrick           break;
2299061da546Spatrick 
2300061da546Spatrick         case NameMatch::RegularExpression:
2301061da546Spatrick           packet.PutCString("name_match:regex;");
2302061da546Spatrick           break;
2303061da546Spatrick         }
2304061da546Spatrick         if (has_name_match) {
2305061da546Spatrick           packet.PutCString("name:");
2306061da546Spatrick           packet.PutBytesAsRawHex8(name, ::strlen(name));
2307061da546Spatrick           packet.PutChar(';');
2308061da546Spatrick         }
2309061da546Spatrick       }
2310061da546Spatrick 
2311061da546Spatrick       if (match_info.GetProcessInfo().ProcessIDIsValid())
2312061da546Spatrick         packet.Printf("pid:%" PRIu64 ";",
2313061da546Spatrick                       match_info.GetProcessInfo().GetProcessID());
2314061da546Spatrick       if (match_info.GetProcessInfo().ParentProcessIDIsValid())
2315061da546Spatrick         packet.Printf("parent_pid:%" PRIu64 ";",
2316061da546Spatrick                       match_info.GetProcessInfo().GetParentProcessID());
2317061da546Spatrick       if (match_info.GetProcessInfo().UserIDIsValid())
2318061da546Spatrick         packet.Printf("uid:%u;", match_info.GetProcessInfo().GetUserID());
2319061da546Spatrick       if (match_info.GetProcessInfo().GroupIDIsValid())
2320061da546Spatrick         packet.Printf("gid:%u;", match_info.GetProcessInfo().GetGroupID());
2321061da546Spatrick       if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
2322061da546Spatrick         packet.Printf("euid:%u;",
2323061da546Spatrick                       match_info.GetProcessInfo().GetEffectiveUserID());
2324061da546Spatrick       if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
2325061da546Spatrick         packet.Printf("egid:%u;",
2326061da546Spatrick                       match_info.GetProcessInfo().GetEffectiveGroupID());
2327061da546Spatrick       packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0);
2328061da546Spatrick       if (match_info.GetProcessInfo().GetArchitecture().IsValid()) {
2329061da546Spatrick         const ArchSpec &match_arch =
2330061da546Spatrick             match_info.GetProcessInfo().GetArchitecture();
2331061da546Spatrick         const llvm::Triple &triple = match_arch.GetTriple();
2332061da546Spatrick         packet.PutCString("triple:");
2333061da546Spatrick         packet.PutCString(triple.getTriple());
2334061da546Spatrick         packet.PutChar(';');
2335061da546Spatrick       }
2336061da546Spatrick     }
2337061da546Spatrick     StringExtractorGDBRemote response;
2338061da546Spatrick     // Increase timeout as the first qfProcessInfo packet takes a long time on
2339061da546Spatrick     // Android. The value of 1min was arrived at empirically.
2340061da546Spatrick     ScopedTimeout timeout(*this, minutes(1));
2341be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
2342061da546Spatrick         PacketResult::Success) {
2343061da546Spatrick       do {
2344061da546Spatrick         ProcessInstanceInfo process_info;
2345061da546Spatrick         if (!DecodeProcessInfoResponse(response, process_info))
2346061da546Spatrick           break;
2347dda28197Spatrick         process_infos.push_back(process_info);
2348061da546Spatrick         response = StringExtractorGDBRemote();
2349be691f3bSpatrick       } while (SendPacketAndWaitForResponse("qsProcessInfo", response) ==
2350061da546Spatrick                PacketResult::Success);
2351061da546Spatrick     } else {
2352061da546Spatrick       m_supports_qfProcessInfo = false;
2353061da546Spatrick       return 0;
2354061da546Spatrick     }
2355061da546Spatrick   }
2356dda28197Spatrick   return process_infos.size();
2357061da546Spatrick }
2358061da546Spatrick 
GetUserName(uint32_t uid,std::string & name)2359061da546Spatrick bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
2360061da546Spatrick                                                std::string &name) {
2361061da546Spatrick   if (m_supports_qUserName) {
2362061da546Spatrick     char packet[32];
2363061da546Spatrick     const int packet_len =
2364061da546Spatrick         ::snprintf(packet, sizeof(packet), "qUserName:%i", uid);
2365061da546Spatrick     assert(packet_len < (int)sizeof(packet));
2366061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
2367061da546Spatrick     StringExtractorGDBRemote response;
2368be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
2369061da546Spatrick         PacketResult::Success) {
2370061da546Spatrick       if (response.IsNormalResponse()) {
2371061da546Spatrick         // Make sure we parsed the right number of characters. The response is
2372061da546Spatrick         // the hex encoded user name and should make up the entire packet. If
2373061da546Spatrick         // there are any non-hex ASCII bytes, the length won't match below..
2374061da546Spatrick         if (response.GetHexByteString(name) * 2 ==
2375061da546Spatrick             response.GetStringRef().size())
2376061da546Spatrick           return true;
2377061da546Spatrick       }
2378061da546Spatrick     } else {
2379061da546Spatrick       m_supports_qUserName = false;
2380061da546Spatrick       return false;
2381061da546Spatrick     }
2382061da546Spatrick   }
2383061da546Spatrick   return false;
2384061da546Spatrick }
2385061da546Spatrick 
GetGroupName(uint32_t gid,std::string & name)2386061da546Spatrick bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
2387061da546Spatrick                                                 std::string &name) {
2388061da546Spatrick   if (m_supports_qGroupName) {
2389061da546Spatrick     char packet[32];
2390061da546Spatrick     const int packet_len =
2391061da546Spatrick         ::snprintf(packet, sizeof(packet), "qGroupName:%i", gid);
2392061da546Spatrick     assert(packet_len < (int)sizeof(packet));
2393061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
2394061da546Spatrick     StringExtractorGDBRemote response;
2395be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
2396061da546Spatrick         PacketResult::Success) {
2397061da546Spatrick       if (response.IsNormalResponse()) {
2398061da546Spatrick         // Make sure we parsed the right number of characters. The response is
2399061da546Spatrick         // the hex encoded group name and should make up the entire packet. If
2400061da546Spatrick         // there are any non-hex ASCII bytes, the length won't match below..
2401061da546Spatrick         if (response.GetHexByteString(name) * 2 ==
2402061da546Spatrick             response.GetStringRef().size())
2403061da546Spatrick           return true;
2404061da546Spatrick       }
2405061da546Spatrick     } else {
2406061da546Spatrick       m_supports_qGroupName = false;
2407061da546Spatrick       return false;
2408061da546Spatrick     }
2409061da546Spatrick   }
2410061da546Spatrick   return false;
2411061da546Spatrick }
2412061da546Spatrick 
MakeSpeedTestPacket(StreamString & packet,uint32_t send_size,uint32_t recv_size)2413061da546Spatrick static void MakeSpeedTestPacket(StreamString &packet, uint32_t send_size,
2414061da546Spatrick                                 uint32_t recv_size) {
2415061da546Spatrick   packet.Clear();
2416061da546Spatrick   packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
2417061da546Spatrick   uint32_t bytes_left = send_size;
2418061da546Spatrick   while (bytes_left > 0) {
2419061da546Spatrick     if (bytes_left >= 26) {
2420061da546Spatrick       packet.PutCString("abcdefghijklmnopqrstuvwxyz");
2421061da546Spatrick       bytes_left -= 26;
2422061da546Spatrick     } else {
2423061da546Spatrick       packet.Printf("%*.*s;", bytes_left, bytes_left,
2424061da546Spatrick                     "abcdefghijklmnopqrstuvwxyz");
2425061da546Spatrick       bytes_left = 0;
2426061da546Spatrick     }
2427061da546Spatrick   }
2428061da546Spatrick }
2429061da546Spatrick 
2430061da546Spatrick duration<float>
calculate_standard_deviation(const std::vector<duration<float>> & v)2431061da546Spatrick calculate_standard_deviation(const std::vector<duration<float>> &v) {
2432*f6aab3d8Srobert   if (v.size() == 0)
2433*f6aab3d8Srobert     return duration<float>::zero();
2434061da546Spatrick   using Dur = duration<float>;
2435061da546Spatrick   Dur sum = std::accumulate(std::begin(v), std::end(v), Dur());
2436061da546Spatrick   Dur mean = sum / v.size();
2437061da546Spatrick   float accum = 0;
2438061da546Spatrick   for (auto d : v) {
2439061da546Spatrick     float delta = (d - mean).count();
2440061da546Spatrick     accum += delta * delta;
2441061da546Spatrick   };
2442061da546Spatrick 
2443061da546Spatrick   return Dur(sqrtf(accum / (v.size() - 1)));
2444061da546Spatrick }
2445061da546Spatrick 
TestPacketSpeed(const uint32_t num_packets,uint32_t max_send,uint32_t max_recv,uint64_t recv_amount,bool json,Stream & strm)2446061da546Spatrick void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
2447061da546Spatrick                                                    uint32_t max_send,
2448061da546Spatrick                                                    uint32_t max_recv,
2449061da546Spatrick                                                    uint64_t recv_amount,
2450061da546Spatrick                                                    bool json, Stream &strm) {
2451*f6aab3d8Srobert 
2452061da546Spatrick   if (SendSpeedTestPacket(0, 0)) {
2453061da546Spatrick     StreamString packet;
2454061da546Spatrick     if (json)
2455061da546Spatrick       strm.Printf("{ \"packet_speeds\" : {\n    \"num_packets\" : %u,\n    "
2456061da546Spatrick                   "\"results\" : [",
2457061da546Spatrick                   num_packets);
2458061da546Spatrick     else
2459061da546Spatrick       strm.Printf("Testing sending %u packets of various sizes:\n",
2460061da546Spatrick                   num_packets);
2461061da546Spatrick     strm.Flush();
2462061da546Spatrick 
2463061da546Spatrick     uint32_t result_idx = 0;
2464061da546Spatrick     uint32_t send_size;
2465061da546Spatrick     std::vector<duration<float>> packet_times;
2466061da546Spatrick 
2467061da546Spatrick     for (send_size = 0; send_size <= max_send;
2468061da546Spatrick          send_size ? send_size *= 2 : send_size = 4) {
2469061da546Spatrick       for (uint32_t recv_size = 0; recv_size <= max_recv;
2470061da546Spatrick            recv_size ? recv_size *= 2 : recv_size = 4) {
2471061da546Spatrick         MakeSpeedTestPacket(packet, send_size, recv_size);
2472061da546Spatrick 
2473061da546Spatrick         packet_times.clear();
2474061da546Spatrick         // Test how long it takes to send 'num_packets' packets
2475061da546Spatrick         const auto start_time = steady_clock::now();
2476*f6aab3d8Srobert         for (uint32_t i = 0; i < num_packets; ++i) {
2477061da546Spatrick           const auto packet_start_time = steady_clock::now();
2478061da546Spatrick           StringExtractorGDBRemote response;
2479be691f3bSpatrick           SendPacketAndWaitForResponse(packet.GetString(), response);
2480061da546Spatrick           const auto packet_end_time = steady_clock::now();
2481061da546Spatrick           packet_times.push_back(packet_end_time - packet_start_time);
2482061da546Spatrick         }
2483061da546Spatrick         const auto end_time = steady_clock::now();
2484061da546Spatrick         const auto total_time = end_time - start_time;
2485061da546Spatrick 
2486061da546Spatrick         float packets_per_second =
2487061da546Spatrick             ((float)num_packets) / duration<float>(total_time).count();
2488*f6aab3d8Srobert         auto average_per_packet = num_packets > 0 ? total_time / num_packets
2489*f6aab3d8Srobert                                                   : duration<float>::zero();
2490061da546Spatrick         const duration<float> standard_deviation =
2491061da546Spatrick             calculate_standard_deviation(packet_times);
2492061da546Spatrick         if (json) {
2493061da546Spatrick           strm.Format("{0}\n     {{\"send_size\" : {1,6}, \"recv_size\" : "
2494061da546Spatrick                       "{2,6}, \"total_time_nsec\" : {3,12:ns-}, "
2495061da546Spatrick                       "\"standard_deviation_nsec\" : {4,9:ns-f0}}",
2496061da546Spatrick                       result_idx > 0 ? "," : "", send_size, recv_size,
2497061da546Spatrick                       total_time, standard_deviation);
2498061da546Spatrick           ++result_idx;
2499061da546Spatrick         } else {
2500061da546Spatrick           strm.Format("qSpeedTest(send={0,7}, recv={1,7}) in {2:s+f9} for "
2501061da546Spatrick                       "{3,9:f2} packets/s ({4,10:ms+f6} per packet) with "
2502061da546Spatrick                       "standard deviation of {5,10:ms+f6}\n",
2503061da546Spatrick                       send_size, recv_size, duration<float>(total_time),
2504061da546Spatrick                       packets_per_second, duration<float>(average_per_packet),
2505061da546Spatrick                       standard_deviation);
2506061da546Spatrick         }
2507061da546Spatrick         strm.Flush();
2508061da546Spatrick       }
2509061da546Spatrick     }
2510061da546Spatrick 
2511061da546Spatrick     const float k_recv_amount_mb = (float)recv_amount / (1024.0f * 1024.0f);
2512061da546Spatrick     if (json)
2513061da546Spatrick       strm.Printf("\n    ]\n  },\n  \"download_speed\" : {\n    \"byte_size\" "
2514061da546Spatrick                   ": %" PRIu64 ",\n    \"results\" : [",
2515061da546Spatrick                   recv_amount);
2516061da546Spatrick     else
2517061da546Spatrick       strm.Printf("Testing receiving %2.1fMB of data using varying receive "
2518061da546Spatrick                   "packet sizes:\n",
2519061da546Spatrick                   k_recv_amount_mb);
2520061da546Spatrick     strm.Flush();
2521061da546Spatrick     send_size = 0;
2522061da546Spatrick     result_idx = 0;
2523061da546Spatrick     for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) {
2524061da546Spatrick       MakeSpeedTestPacket(packet, send_size, recv_size);
2525061da546Spatrick 
2526061da546Spatrick       // If we have a receive size, test how long it takes to receive 4MB of
2527061da546Spatrick       // data
2528061da546Spatrick       if (recv_size > 0) {
2529061da546Spatrick         const auto start_time = steady_clock::now();
2530061da546Spatrick         uint32_t bytes_read = 0;
2531061da546Spatrick         uint32_t packet_count = 0;
2532061da546Spatrick         while (bytes_read < recv_amount) {
2533061da546Spatrick           StringExtractorGDBRemote response;
2534be691f3bSpatrick           SendPacketAndWaitForResponse(packet.GetString(), response);
2535061da546Spatrick           bytes_read += recv_size;
2536061da546Spatrick           ++packet_count;
2537061da546Spatrick         }
2538061da546Spatrick         const auto end_time = steady_clock::now();
2539061da546Spatrick         const auto total_time = end_time - start_time;
2540061da546Spatrick         float mb_second = ((float)recv_amount) /
2541061da546Spatrick                           duration<float>(total_time).count() /
2542061da546Spatrick                           (1024.0 * 1024.0);
2543061da546Spatrick         float packets_per_second =
2544061da546Spatrick             ((float)packet_count) / duration<float>(total_time).count();
2545*f6aab3d8Srobert         const auto average_per_packet = packet_count > 0
2546*f6aab3d8Srobert                                             ? total_time / packet_count
2547*f6aab3d8Srobert                                             : duration<float>::zero();
2548061da546Spatrick 
2549061da546Spatrick         if (json) {
2550061da546Spatrick           strm.Format("{0}\n     {{\"send_size\" : {1,6}, \"recv_size\" : "
2551061da546Spatrick                       "{2,6}, \"total_time_nsec\" : {3,12:ns-}}",
2552061da546Spatrick                       result_idx > 0 ? "," : "", send_size, recv_size,
2553061da546Spatrick                       total_time);
2554061da546Spatrick           ++result_idx;
2555061da546Spatrick         } else {
2556061da546Spatrick           strm.Format("qSpeedTest(send={0,7}, recv={1,7}) {2,6} packets needed "
2557061da546Spatrick                       "to receive {3:f1}MB in {4:s+f9} for {5} MB/sec for "
2558061da546Spatrick                       "{6,9:f2} packets/sec ({7,10:ms+f6} per packet)\n",
2559061da546Spatrick                       send_size, recv_size, packet_count, k_recv_amount_mb,
2560061da546Spatrick                       duration<float>(total_time), mb_second,
2561061da546Spatrick                       packets_per_second, duration<float>(average_per_packet));
2562061da546Spatrick         }
2563061da546Spatrick         strm.Flush();
2564061da546Spatrick       }
2565061da546Spatrick     }
2566061da546Spatrick     if (json)
2567061da546Spatrick       strm.Printf("\n    ]\n  }\n}\n");
2568061da546Spatrick     else
2569061da546Spatrick       strm.EOL();
2570061da546Spatrick   }
2571061da546Spatrick }
2572061da546Spatrick 
SendSpeedTestPacket(uint32_t send_size,uint32_t recv_size)2573061da546Spatrick bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size,
2574061da546Spatrick                                                        uint32_t recv_size) {
2575061da546Spatrick   StreamString packet;
2576061da546Spatrick   packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
2577061da546Spatrick   uint32_t bytes_left = send_size;
2578061da546Spatrick   while (bytes_left > 0) {
2579061da546Spatrick     if (bytes_left >= 26) {
2580061da546Spatrick       packet.PutCString("abcdefghijklmnopqrstuvwxyz");
2581061da546Spatrick       bytes_left -= 26;
2582061da546Spatrick     } else {
2583061da546Spatrick       packet.Printf("%*.*s;", bytes_left, bytes_left,
2584061da546Spatrick                     "abcdefghijklmnopqrstuvwxyz");
2585061da546Spatrick       bytes_left = 0;
2586061da546Spatrick     }
2587061da546Spatrick   }
2588061da546Spatrick 
2589061da546Spatrick   StringExtractorGDBRemote response;
2590be691f3bSpatrick   return SendPacketAndWaitForResponse(packet.GetString(), response) ==
2591061da546Spatrick          PacketResult::Success;
2592061da546Spatrick }
2593061da546Spatrick 
LaunchGDBServer(const char * remote_accept_hostname,lldb::pid_t & pid,uint16_t & port,std::string & socket_name)2594061da546Spatrick bool GDBRemoteCommunicationClient::LaunchGDBServer(
2595061da546Spatrick     const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port,
2596061da546Spatrick     std::string &socket_name) {
2597061da546Spatrick   pid = LLDB_INVALID_PROCESS_ID;
2598061da546Spatrick   port = 0;
2599061da546Spatrick   socket_name.clear();
2600061da546Spatrick 
2601061da546Spatrick   StringExtractorGDBRemote response;
2602061da546Spatrick   StreamString stream;
2603061da546Spatrick   stream.PutCString("qLaunchGDBServer;");
2604061da546Spatrick   std::string hostname;
2605061da546Spatrick   if (remote_accept_hostname && remote_accept_hostname[0])
2606061da546Spatrick     hostname = remote_accept_hostname;
2607061da546Spatrick   else {
2608061da546Spatrick     if (HostInfo::GetHostname(hostname)) {
2609061da546Spatrick       // Make the GDB server we launch only accept connections from this host
2610061da546Spatrick       stream.Printf("host:%s;", hostname.c_str());
2611061da546Spatrick     } else {
2612061da546Spatrick       // Make the GDB server we launch accept connections from any host since
2613061da546Spatrick       // we can't figure out the hostname
2614061da546Spatrick       stream.Printf("host:*;");
2615061da546Spatrick     }
2616061da546Spatrick   }
2617061da546Spatrick   // give the process a few seconds to startup
2618061da546Spatrick   ScopedTimeout timeout(*this, seconds(10));
2619061da546Spatrick 
2620be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
2621061da546Spatrick       PacketResult::Success) {
2622061da546Spatrick     llvm::StringRef name;
2623061da546Spatrick     llvm::StringRef value;
2624061da546Spatrick     while (response.GetNameColonValue(name, value)) {
2625061da546Spatrick       if (name.equals("port"))
2626061da546Spatrick         value.getAsInteger(0, port);
2627061da546Spatrick       else if (name.equals("pid"))
2628061da546Spatrick         value.getAsInteger(0, pid);
2629061da546Spatrick       else if (name.compare("socket_name") == 0) {
2630061da546Spatrick         StringExtractor extractor(value);
2631061da546Spatrick         extractor.GetHexByteString(socket_name);
2632061da546Spatrick       }
2633061da546Spatrick     }
2634061da546Spatrick     return true;
2635061da546Spatrick   }
2636061da546Spatrick   return false;
2637061da546Spatrick }
2638061da546Spatrick 
QueryGDBServer(std::vector<std::pair<uint16_t,std::string>> & connection_urls)2639061da546Spatrick size_t GDBRemoteCommunicationClient::QueryGDBServer(
2640061da546Spatrick     std::vector<std::pair<uint16_t, std::string>> &connection_urls) {
2641061da546Spatrick   connection_urls.clear();
2642061da546Spatrick 
2643061da546Spatrick   StringExtractorGDBRemote response;
2644be691f3bSpatrick   if (SendPacketAndWaitForResponse("qQueryGDBServer", response) !=
2645061da546Spatrick       PacketResult::Success)
2646061da546Spatrick     return 0;
2647061da546Spatrick 
2648061da546Spatrick   StructuredData::ObjectSP data =
2649dda28197Spatrick       StructuredData::ParseJSON(std::string(response.GetStringRef()));
2650061da546Spatrick   if (!data)
2651061da546Spatrick     return 0;
2652061da546Spatrick 
2653061da546Spatrick   StructuredData::Array *array = data->GetAsArray();
2654061da546Spatrick   if (!array)
2655061da546Spatrick     return 0;
2656061da546Spatrick 
2657061da546Spatrick   for (size_t i = 0, count = array->GetSize(); i < count; ++i) {
2658061da546Spatrick     StructuredData::Dictionary *element = nullptr;
2659061da546Spatrick     if (!array->GetItemAtIndexAsDictionary(i, element))
2660061da546Spatrick       continue;
2661061da546Spatrick 
2662061da546Spatrick     uint16_t port = 0;
2663061da546Spatrick     if (StructuredData::ObjectSP port_osp =
2664061da546Spatrick             element->GetValueForKey(llvm::StringRef("port")))
2665061da546Spatrick       port = port_osp->GetIntegerValue(0);
2666061da546Spatrick 
2667061da546Spatrick     std::string socket_name;
2668061da546Spatrick     if (StructuredData::ObjectSP socket_name_osp =
2669061da546Spatrick             element->GetValueForKey(llvm::StringRef("socket_name")))
2670dda28197Spatrick       socket_name = std::string(socket_name_osp->GetStringValue());
2671061da546Spatrick 
2672061da546Spatrick     if (port != 0 || !socket_name.empty())
2673061da546Spatrick       connection_urls.emplace_back(port, socket_name);
2674061da546Spatrick   }
2675061da546Spatrick   return connection_urls.size();
2676061da546Spatrick }
2677061da546Spatrick 
KillSpawnedProcess(lldb::pid_t pid)2678061da546Spatrick bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) {
2679061da546Spatrick   StreamString stream;
2680061da546Spatrick   stream.Printf("qKillSpawnedProcess:%" PRId64, pid);
2681061da546Spatrick 
2682061da546Spatrick   StringExtractorGDBRemote response;
2683be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
2684061da546Spatrick       PacketResult::Success) {
2685061da546Spatrick     if (response.IsOKResponse())
2686061da546Spatrick       return true;
2687061da546Spatrick   }
2688061da546Spatrick   return false;
2689061da546Spatrick }
2690061da546Spatrick 
SendSetCurrentThreadPacket(uint64_t tid,uint64_t pid,char op)2691*f6aab3d8Srobert std::optional<PidTid> GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(
2692*f6aab3d8Srobert     uint64_t tid, uint64_t pid, char op) {
2693be691f3bSpatrick   lldb_private::StreamString packet;
2694be691f3bSpatrick   packet.PutChar('H');
2695be691f3bSpatrick   packet.PutChar(op);
2696061da546Spatrick 
2697be691f3bSpatrick   if (pid != LLDB_INVALID_PROCESS_ID)
2698be691f3bSpatrick     packet.Printf("p%" PRIx64 ".", pid);
2699be691f3bSpatrick 
2700061da546Spatrick   if (tid == UINT64_MAX)
2701be691f3bSpatrick     packet.PutCString("-1");
2702061da546Spatrick   else
2703be691f3bSpatrick     packet.Printf("%" PRIx64, tid);
2704be691f3bSpatrick 
2705061da546Spatrick   StringExtractorGDBRemote response;
2706*f6aab3d8Srobert   if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
2707*f6aab3d8Srobert       PacketResult::Success) {
2708be691f3bSpatrick     if (response.IsOKResponse())
2709be691f3bSpatrick       return {{pid, tid}};
2710061da546Spatrick 
2711061da546Spatrick     /*
2712061da546Spatrick      * Connected bare-iron target (like YAMON gdb-stub) may not have support for
2713061da546Spatrick      * Hg packet.
2714061da546Spatrick      * The reply from '?' packet could be as simple as 'S05'. There is no packet
2715061da546Spatrick      * which can
2716061da546Spatrick      * give us pid and/or tid. Assume pid=tid=1 in such cases.
2717061da546Spatrick      */
2718be691f3bSpatrick     if (response.IsUnsupportedResponse() && IsConnected())
2719be691f3bSpatrick       return {{1, 1}};
2720061da546Spatrick   }
2721*f6aab3d8Srobert   return std::nullopt;
2722061da546Spatrick }
2723061da546Spatrick 
SetCurrentThread(uint64_t tid,uint64_t pid)2724be691f3bSpatrick bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid,
2725be691f3bSpatrick                                                     uint64_t pid) {
2726be691f3bSpatrick   if (m_curr_tid == tid &&
2727be691f3bSpatrick       (m_curr_pid == pid || LLDB_INVALID_PROCESS_ID == pid))
2728061da546Spatrick     return true;
2729061da546Spatrick 
2730*f6aab3d8Srobert   std::optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'g');
2731*f6aab3d8Srobert   if (ret) {
2732be691f3bSpatrick     if (ret->pid != LLDB_INVALID_PROCESS_ID)
2733be691f3bSpatrick       m_curr_pid = ret->pid;
2734be691f3bSpatrick     m_curr_tid = ret->tid;
2735be691f3bSpatrick   }
2736*f6aab3d8Srobert   return ret.has_value();
2737061da546Spatrick }
2738061da546Spatrick 
SetCurrentThreadForRun(uint64_t tid,uint64_t pid)2739be691f3bSpatrick bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid,
2740be691f3bSpatrick                                                           uint64_t pid) {
2741be691f3bSpatrick   if (m_curr_tid_run == tid &&
2742be691f3bSpatrick       (m_curr_pid_run == pid || LLDB_INVALID_PROCESS_ID == pid))
2743061da546Spatrick     return true;
2744be691f3bSpatrick 
2745*f6aab3d8Srobert   std::optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'c');
2746*f6aab3d8Srobert   if (ret) {
2747be691f3bSpatrick     if (ret->pid != LLDB_INVALID_PROCESS_ID)
2748be691f3bSpatrick       m_curr_pid_run = ret->pid;
2749be691f3bSpatrick     m_curr_tid_run = ret->tid;
2750061da546Spatrick   }
2751*f6aab3d8Srobert   return ret.has_value();
2752061da546Spatrick }
2753061da546Spatrick 
GetStopReply(StringExtractorGDBRemote & response)2754061da546Spatrick bool GDBRemoteCommunicationClient::GetStopReply(
2755061da546Spatrick     StringExtractorGDBRemote &response) {
2756be691f3bSpatrick   if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success)
2757061da546Spatrick     return response.IsNormalResponse();
2758061da546Spatrick   return false;
2759061da546Spatrick }
2760061da546Spatrick 
GetThreadStopInfo(lldb::tid_t tid,StringExtractorGDBRemote & response)2761061da546Spatrick bool GDBRemoteCommunicationClient::GetThreadStopInfo(
2762061da546Spatrick     lldb::tid_t tid, StringExtractorGDBRemote &response) {
2763061da546Spatrick   if (m_supports_qThreadStopInfo) {
2764061da546Spatrick     char packet[256];
2765061da546Spatrick     int packet_len =
2766061da546Spatrick         ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
2767061da546Spatrick     assert(packet_len < (int)sizeof(packet));
2768061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
2769be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
2770061da546Spatrick         PacketResult::Success) {
2771061da546Spatrick       if (response.IsUnsupportedResponse())
2772061da546Spatrick         m_supports_qThreadStopInfo = false;
2773061da546Spatrick       else if (response.IsNormalResponse())
2774061da546Spatrick         return true;
2775061da546Spatrick       else
2776061da546Spatrick         return false;
2777061da546Spatrick     } else {
2778061da546Spatrick       m_supports_qThreadStopInfo = false;
2779061da546Spatrick     }
2780061da546Spatrick   }
2781061da546Spatrick   return false;
2782061da546Spatrick }
2783061da546Spatrick 
SendGDBStoppointTypePacket(GDBStoppointType type,bool insert,addr_t addr,uint32_t length,std::chrono::seconds timeout)2784061da546Spatrick uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
2785be691f3bSpatrick     GDBStoppointType type, bool insert, addr_t addr, uint32_t length,
2786be691f3bSpatrick     std::chrono::seconds timeout) {
2787*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Breakpoints);
2788061da546Spatrick   LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
2789061da546Spatrick             __FUNCTION__, insert ? "add" : "remove", addr);
2790061da546Spatrick 
2791061da546Spatrick   // Check if the stub is known not to support this breakpoint type
2792061da546Spatrick   if (!SupportsGDBStoppointPacket(type))
2793061da546Spatrick     return UINT8_MAX;
2794061da546Spatrick   // Construct the breakpoint packet
2795061da546Spatrick   char packet[64];
2796061da546Spatrick   const int packet_len =
2797061da546Spatrick       ::snprintf(packet, sizeof(packet), "%c%i,%" PRIx64 ",%x",
2798061da546Spatrick                  insert ? 'Z' : 'z', type, addr, length);
2799061da546Spatrick   // Check we haven't overwritten the end of the packet buffer
2800061da546Spatrick   assert(packet_len + 1 < (int)sizeof(packet));
2801061da546Spatrick   UNUSED_IF_ASSERT_DISABLED(packet_len);
2802061da546Spatrick   StringExtractorGDBRemote response;
2803061da546Spatrick   // Make sure the response is either "OK", "EXX" where XX are two hex digits,
2804061da546Spatrick   // or "" (unsupported)
2805061da546Spatrick   response.SetResponseValidatorToOKErrorNotSupported();
2806061da546Spatrick   // Try to send the breakpoint packet, and check that it was correctly sent
2807be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response, timeout) ==
2808061da546Spatrick       PacketResult::Success) {
2809061da546Spatrick     // Receive and OK packet when the breakpoint successfully placed
2810061da546Spatrick     if (response.IsOKResponse())
2811061da546Spatrick       return 0;
2812061da546Spatrick 
2813061da546Spatrick     // Status while setting breakpoint, send back specific error
2814061da546Spatrick     if (response.IsErrorResponse())
2815061da546Spatrick       return response.GetError();
2816061da546Spatrick 
2817061da546Spatrick     // Empty packet informs us that breakpoint is not supported
2818061da546Spatrick     if (response.IsUnsupportedResponse()) {
2819061da546Spatrick       // Disable this breakpoint type since it is unsupported
2820061da546Spatrick       switch (type) {
2821061da546Spatrick       case eBreakpointSoftware:
2822061da546Spatrick         m_supports_z0 = false;
2823061da546Spatrick         break;
2824061da546Spatrick       case eBreakpointHardware:
2825061da546Spatrick         m_supports_z1 = false;
2826061da546Spatrick         break;
2827061da546Spatrick       case eWatchpointWrite:
2828061da546Spatrick         m_supports_z2 = false;
2829061da546Spatrick         break;
2830061da546Spatrick       case eWatchpointRead:
2831061da546Spatrick         m_supports_z3 = false;
2832061da546Spatrick         break;
2833061da546Spatrick       case eWatchpointReadWrite:
2834061da546Spatrick         m_supports_z4 = false;
2835061da546Spatrick         break;
2836061da546Spatrick       case eStoppointInvalid:
2837061da546Spatrick         return UINT8_MAX;
2838061da546Spatrick       }
2839061da546Spatrick     }
2840061da546Spatrick   }
2841061da546Spatrick   // Signal generic failure
2842061da546Spatrick   return UINT8_MAX;
2843061da546Spatrick }
2844061da546Spatrick 
2845be691f3bSpatrick std::vector<std::pair<lldb::pid_t, lldb::tid_t>>
GetCurrentProcessAndThreadIDs(bool & sequence_mutex_unavailable)2846be691f3bSpatrick GDBRemoteCommunicationClient::GetCurrentProcessAndThreadIDs(
2847be691f3bSpatrick     bool &sequence_mutex_unavailable) {
2848be691f3bSpatrick   std::vector<std::pair<lldb::pid_t, lldb::tid_t>> ids;
2849061da546Spatrick 
2850be691f3bSpatrick   Lock lock(*this);
2851061da546Spatrick   if (lock) {
2852061da546Spatrick     sequence_mutex_unavailable = false;
2853061da546Spatrick     StringExtractorGDBRemote response;
2854061da546Spatrick 
2855061da546Spatrick     PacketResult packet_result;
2856061da546Spatrick     for (packet_result =
2857061da546Spatrick              SendPacketAndWaitForResponseNoLock("qfThreadInfo", response);
2858061da546Spatrick          packet_result == PacketResult::Success && response.IsNormalResponse();
2859061da546Spatrick          packet_result =
2860061da546Spatrick              SendPacketAndWaitForResponseNoLock("qsThreadInfo", response)) {
2861061da546Spatrick       char ch = response.GetChar();
2862061da546Spatrick       if (ch == 'l')
2863061da546Spatrick         break;
2864061da546Spatrick       if (ch == 'm') {
2865061da546Spatrick         do {
2866be691f3bSpatrick           auto pid_tid = response.GetPidTid(LLDB_INVALID_PROCESS_ID);
2867*f6aab3d8Srobert           // If we get an invalid response, break out of the loop.
2868*f6aab3d8Srobert           // If there are valid tids, they have been added to ids.
2869*f6aab3d8Srobert           // If there are no valid tids, we'll fall through to the
2870*f6aab3d8Srobert           // bare-iron target handling below.
2871be691f3bSpatrick           if (!pid_tid)
2872*f6aab3d8Srobert             break;
2873061da546Spatrick 
2874*f6aab3d8Srobert           ids.push_back(*pid_tid);
2875061da546Spatrick           ch = response.GetChar(); // Skip the command separator
2876061da546Spatrick         } while (ch == ',');       // Make sure we got a comma separator
2877061da546Spatrick       }
2878061da546Spatrick     }
2879061da546Spatrick 
2880061da546Spatrick     /*
2881061da546Spatrick      * Connected bare-iron target (like YAMON gdb-stub) may not have support for
2882061da546Spatrick      * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet
2883061da546Spatrick      * could
2884061da546Spatrick      * be as simple as 'S05'. There is no packet which can give us pid and/or
2885061da546Spatrick      * tid.
2886061da546Spatrick      * Assume pid=tid=1 in such cases.
2887061da546Spatrick      */
2888061da546Spatrick     if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) &&
2889be691f3bSpatrick         ids.size() == 0 && IsConnected()) {
2890be691f3bSpatrick       ids.emplace_back(1, 1);
2891061da546Spatrick     }
2892061da546Spatrick   } else {
2893*f6aab3d8Srobert     Log *log(GetLog(GDBRLog::Process | GDBRLog::Packets));
2894dda28197Spatrick     LLDB_LOG(log, "error: failed to get packet sequence mutex, not sending "
2895061da546Spatrick                   "packet 'qfThreadInfo'");
2896061da546Spatrick     sequence_mutex_unavailable = true;
2897061da546Spatrick   }
2898be691f3bSpatrick 
2899be691f3bSpatrick   return ids;
2900be691f3bSpatrick }
2901be691f3bSpatrick 
GetCurrentThreadIDs(std::vector<lldb::tid_t> & thread_ids,bool & sequence_mutex_unavailable)2902be691f3bSpatrick size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
2903be691f3bSpatrick     std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
2904be691f3bSpatrick   lldb::pid_t pid = GetCurrentProcessID();
2905be691f3bSpatrick   thread_ids.clear();
2906be691f3bSpatrick 
2907be691f3bSpatrick   auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
2908be691f3bSpatrick   if (ids.empty() || sequence_mutex_unavailable)
2909be691f3bSpatrick     return 0;
2910be691f3bSpatrick 
2911be691f3bSpatrick   for (auto id : ids) {
2912be691f3bSpatrick     // skip threads that do not belong to the current process
2913be691f3bSpatrick     if (id.first != LLDB_INVALID_PROCESS_ID && id.first != pid)
2914be691f3bSpatrick       continue;
2915be691f3bSpatrick     if (id.second != LLDB_INVALID_THREAD_ID &&
2916be691f3bSpatrick         id.second != StringExtractorGDBRemote::AllThreads)
2917be691f3bSpatrick       thread_ids.push_back(id.second);
2918be691f3bSpatrick   }
2919be691f3bSpatrick 
2920061da546Spatrick   return thread_ids.size();
2921061da546Spatrick }
2922061da546Spatrick 
GetShlibInfoAddr()2923061da546Spatrick lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() {
2924061da546Spatrick   StringExtractorGDBRemote response;
2925be691f3bSpatrick   if (SendPacketAndWaitForResponse("qShlibInfoAddr", response) !=
2926061da546Spatrick           PacketResult::Success ||
2927061da546Spatrick       !response.IsNormalResponse())
2928061da546Spatrick     return LLDB_INVALID_ADDRESS;
2929061da546Spatrick   return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
2930061da546Spatrick }
2931061da546Spatrick 
RunShellCommand(llvm::StringRef command,const FileSpec & working_dir,int * status_ptr,int * signo_ptr,std::string * command_output,const Timeout<std::micro> & timeout)2932061da546Spatrick lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
2933be691f3bSpatrick     llvm::StringRef command,
2934061da546Spatrick     const FileSpec &
2935061da546Spatrick         working_dir, // Pass empty FileSpec to use the current working directory
2936061da546Spatrick     int *status_ptr, // Pass NULL if you don't want the process exit status
2937061da546Spatrick     int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
2938061da546Spatrick                      // process to exit
2939061da546Spatrick     std::string
2940061da546Spatrick         *command_output, // Pass NULL if you don't want the command output
2941061da546Spatrick     const Timeout<std::micro> &timeout) {
2942061da546Spatrick   lldb_private::StreamString stream;
2943061da546Spatrick   stream.PutCString("qPlatform_shell:");
2944be691f3bSpatrick   stream.PutBytesAsRawHex8(command.data(), command.size());
2945061da546Spatrick   stream.PutChar(',');
2946061da546Spatrick   uint32_t timeout_sec = UINT32_MAX;
2947061da546Spatrick   if (timeout) {
2948061da546Spatrick     // TODO: Use chrono version of std::ceil once c++17 is available.
2949061da546Spatrick     timeout_sec = std::ceil(std::chrono::duration<double>(*timeout).count());
2950061da546Spatrick   }
2951061da546Spatrick   stream.PutHex32(timeout_sec);
2952061da546Spatrick   if (working_dir) {
2953061da546Spatrick     std::string path{working_dir.GetPath(false)};
2954061da546Spatrick     stream.PutChar(',');
2955061da546Spatrick     stream.PutStringAsRawHex8(path);
2956061da546Spatrick   }
2957061da546Spatrick   StringExtractorGDBRemote response;
2958be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
2959061da546Spatrick       PacketResult::Success) {
2960061da546Spatrick     if (response.GetChar() != 'F')
2961061da546Spatrick       return Status("malformed reply");
2962061da546Spatrick     if (response.GetChar() != ',')
2963061da546Spatrick       return Status("malformed reply");
2964061da546Spatrick     uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
2965061da546Spatrick     if (exitcode == UINT32_MAX)
2966061da546Spatrick       return Status("unable to run remote process");
2967061da546Spatrick     else if (status_ptr)
2968061da546Spatrick       *status_ptr = exitcode;
2969061da546Spatrick     if (response.GetChar() != ',')
2970061da546Spatrick       return Status("malformed reply");
2971061da546Spatrick     uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
2972061da546Spatrick     if (signo_ptr)
2973061da546Spatrick       *signo_ptr = signo;
2974061da546Spatrick     if (response.GetChar() != ',')
2975061da546Spatrick       return Status("malformed reply");
2976061da546Spatrick     std::string output;
2977061da546Spatrick     response.GetEscapedBinaryData(output);
2978061da546Spatrick     if (command_output)
2979061da546Spatrick       command_output->assign(output);
2980061da546Spatrick     return Status();
2981061da546Spatrick   }
2982061da546Spatrick   return Status("unable to send packet");
2983061da546Spatrick }
2984061da546Spatrick 
MakeDirectory(const FileSpec & file_spec,uint32_t file_permissions)2985061da546Spatrick Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec,
2986061da546Spatrick                                                    uint32_t file_permissions) {
2987061da546Spatrick   std::string path{file_spec.GetPath(false)};
2988061da546Spatrick   lldb_private::StreamString stream;
2989061da546Spatrick   stream.PutCString("qPlatform_mkdir:");
2990061da546Spatrick   stream.PutHex32(file_permissions);
2991061da546Spatrick   stream.PutChar(',');
2992061da546Spatrick   stream.PutStringAsRawHex8(path);
2993061da546Spatrick   llvm::StringRef packet = stream.GetString();
2994061da546Spatrick   StringExtractorGDBRemote response;
2995061da546Spatrick 
2996be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
2997061da546Spatrick     return Status("failed to send '%s' packet", packet.str().c_str());
2998061da546Spatrick 
2999061da546Spatrick   if (response.GetChar() != 'F')
3000061da546Spatrick     return Status("invalid response to '%s' packet", packet.str().c_str());
3001061da546Spatrick 
3002*f6aab3d8Srobert   return Status(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX);
3003061da546Spatrick }
3004061da546Spatrick 
3005061da546Spatrick Status
SetFilePermissions(const FileSpec & file_spec,uint32_t file_permissions)3006061da546Spatrick GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec,
3007061da546Spatrick                                                  uint32_t file_permissions) {
3008061da546Spatrick   std::string path{file_spec.GetPath(false)};
3009061da546Spatrick   lldb_private::StreamString stream;
3010061da546Spatrick   stream.PutCString("qPlatform_chmod:");
3011061da546Spatrick   stream.PutHex32(file_permissions);
3012061da546Spatrick   stream.PutChar(',');
3013061da546Spatrick   stream.PutStringAsRawHex8(path);
3014061da546Spatrick   llvm::StringRef packet = stream.GetString();
3015061da546Spatrick   StringExtractorGDBRemote response;
3016061da546Spatrick 
3017be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
3018061da546Spatrick     return Status("failed to send '%s' packet", stream.GetData());
3019061da546Spatrick 
3020061da546Spatrick   if (response.GetChar() != 'F')
3021061da546Spatrick     return Status("invalid response to '%s' packet", stream.GetData());
3022061da546Spatrick 
3023*f6aab3d8Srobert   return Status(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX);
3024*f6aab3d8Srobert }
3025*f6aab3d8Srobert 
gdb_errno_to_system(int err)3026*f6aab3d8Srobert static int gdb_errno_to_system(int err) {
3027*f6aab3d8Srobert   switch (err) {
3028*f6aab3d8Srobert #define HANDLE_ERRNO(name, value)                                              \
3029*f6aab3d8Srobert   case GDB_##name:                                                             \
3030*f6aab3d8Srobert     return name;
3031*f6aab3d8Srobert #include "Plugins/Process/gdb-remote/GDBRemoteErrno.def"
3032*f6aab3d8Srobert   default:
3033*f6aab3d8Srobert     return -1;
3034*f6aab3d8Srobert   }
3035061da546Spatrick }
3036061da546Spatrick 
ParseHostIOPacketResponse(StringExtractorGDBRemote & response,uint64_t fail_result,Status & error)3037061da546Spatrick static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response,
3038061da546Spatrick                                           uint64_t fail_result, Status &error) {
3039061da546Spatrick   response.SetFilePos(0);
3040061da546Spatrick   if (response.GetChar() != 'F')
3041061da546Spatrick     return fail_result;
3042*f6aab3d8Srobert   int32_t result = response.GetS32(-2, 16);
3043061da546Spatrick   if (result == -2)
3044061da546Spatrick     return fail_result;
3045061da546Spatrick   if (response.GetChar() == ',') {
3046*f6aab3d8Srobert     int result_errno = gdb_errno_to_system(response.GetS32(-1, 16));
3047*f6aab3d8Srobert     if (result_errno != -1)
3048061da546Spatrick       error.SetError(result_errno, eErrorTypePOSIX);
3049061da546Spatrick     else
3050061da546Spatrick       error.SetError(-1, eErrorTypeGeneric);
3051061da546Spatrick   } else
3052061da546Spatrick     error.Clear();
3053061da546Spatrick   return result;
3054061da546Spatrick }
3055061da546Spatrick lldb::user_id_t
OpenFile(const lldb_private::FileSpec & file_spec,File::OpenOptions flags,mode_t mode,Status & error)3056061da546Spatrick GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec,
3057061da546Spatrick                                        File::OpenOptions flags, mode_t mode,
3058061da546Spatrick                                        Status &error) {
3059061da546Spatrick   std::string path(file_spec.GetPath(false));
3060061da546Spatrick   lldb_private::StreamString stream;
3061061da546Spatrick   stream.PutCString("vFile:open:");
3062061da546Spatrick   if (path.empty())
3063061da546Spatrick     return UINT64_MAX;
3064061da546Spatrick   stream.PutStringAsRawHex8(path);
3065061da546Spatrick   stream.PutChar(',');
3066061da546Spatrick   stream.PutHex32(flags);
3067061da546Spatrick   stream.PutChar(',');
3068061da546Spatrick   stream.PutHex32(mode);
3069061da546Spatrick   StringExtractorGDBRemote response;
3070be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3071061da546Spatrick       PacketResult::Success) {
3072061da546Spatrick     return ParseHostIOPacketResponse(response, UINT64_MAX, error);
3073061da546Spatrick   }
3074061da546Spatrick   return UINT64_MAX;
3075061da546Spatrick }
3076061da546Spatrick 
CloseFile(lldb::user_id_t fd,Status & error)3077061da546Spatrick bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd,
3078061da546Spatrick                                              Status &error) {
3079061da546Spatrick   lldb_private::StreamString stream;
3080*f6aab3d8Srobert   stream.Printf("vFile:close:%x", (int)fd);
3081061da546Spatrick   StringExtractorGDBRemote response;
3082be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3083061da546Spatrick       PacketResult::Success) {
3084061da546Spatrick     return ParseHostIOPacketResponse(response, -1, error) == 0;
3085061da546Spatrick   }
3086061da546Spatrick   return false;
3087061da546Spatrick }
3088061da546Spatrick 
3089*f6aab3d8Srobert std::optional<GDBRemoteFStatData>
FStat(lldb::user_id_t fd)3090*f6aab3d8Srobert GDBRemoteCommunicationClient::FStat(lldb::user_id_t fd) {
3091*f6aab3d8Srobert   lldb_private::StreamString stream;
3092*f6aab3d8Srobert   stream.Printf("vFile:fstat:%" PRIx64, fd);
3093*f6aab3d8Srobert   StringExtractorGDBRemote response;
3094*f6aab3d8Srobert   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3095*f6aab3d8Srobert       PacketResult::Success) {
3096*f6aab3d8Srobert     if (response.GetChar() != 'F')
3097*f6aab3d8Srobert       return std::nullopt;
3098*f6aab3d8Srobert     int64_t size = response.GetS64(-1, 16);
3099*f6aab3d8Srobert     if (size > 0 && response.GetChar() == ';') {
3100*f6aab3d8Srobert       std::string buffer;
3101*f6aab3d8Srobert       if (response.GetEscapedBinaryData(buffer)) {
3102*f6aab3d8Srobert         GDBRemoteFStatData out;
3103*f6aab3d8Srobert         if (buffer.size() != sizeof(out))
3104*f6aab3d8Srobert           return std::nullopt;
3105*f6aab3d8Srobert         memcpy(&out, buffer.data(), sizeof(out));
3106*f6aab3d8Srobert         return out;
3107*f6aab3d8Srobert       }
3108*f6aab3d8Srobert     }
3109*f6aab3d8Srobert   }
3110*f6aab3d8Srobert   return std::nullopt;
3111*f6aab3d8Srobert }
3112*f6aab3d8Srobert 
3113*f6aab3d8Srobert std::optional<GDBRemoteFStatData>
Stat(const lldb_private::FileSpec & file_spec)3114*f6aab3d8Srobert GDBRemoteCommunicationClient::Stat(const lldb_private::FileSpec &file_spec) {
3115*f6aab3d8Srobert   Status error;
3116*f6aab3d8Srobert   lldb::user_id_t fd = OpenFile(file_spec, File::eOpenOptionReadOnly, 0, error);
3117*f6aab3d8Srobert   if (fd == UINT64_MAX)
3118*f6aab3d8Srobert     return std::nullopt;
3119*f6aab3d8Srobert   std::optional<GDBRemoteFStatData> st = FStat(fd);
3120*f6aab3d8Srobert   CloseFile(fd, error);
3121*f6aab3d8Srobert   return st;
3122*f6aab3d8Srobert }
3123*f6aab3d8Srobert 
3124061da546Spatrick // Extension of host I/O packets to get the file size.
GetFileSize(const lldb_private::FileSpec & file_spec)3125061da546Spatrick lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize(
3126061da546Spatrick     const lldb_private::FileSpec &file_spec) {
3127*f6aab3d8Srobert   if (m_supports_vFileSize) {
3128061da546Spatrick     std::string path(file_spec.GetPath(false));
3129061da546Spatrick     lldb_private::StreamString stream;
3130061da546Spatrick     stream.PutCString("vFile:size:");
3131061da546Spatrick     stream.PutStringAsRawHex8(path);
3132061da546Spatrick     StringExtractorGDBRemote response;
3133*f6aab3d8Srobert     if (SendPacketAndWaitForResponse(stream.GetString(), response) !=
3134*f6aab3d8Srobert         PacketResult::Success)
3135*f6aab3d8Srobert       return UINT64_MAX;
3136*f6aab3d8Srobert 
3137*f6aab3d8Srobert     if (!response.IsUnsupportedResponse()) {
3138061da546Spatrick       if (response.GetChar() != 'F')
3139061da546Spatrick         return UINT64_MAX;
3140061da546Spatrick       uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
3141061da546Spatrick       return retcode;
3142061da546Spatrick     }
3143*f6aab3d8Srobert     m_supports_vFileSize = false;
3144*f6aab3d8Srobert   }
3145*f6aab3d8Srobert 
3146*f6aab3d8Srobert   // Fallback to fstat.
3147*f6aab3d8Srobert   std::optional<GDBRemoteFStatData> st = Stat(file_spec);
3148*f6aab3d8Srobert   return st ? st->gdb_st_size : UINT64_MAX;
3149061da546Spatrick }
3150061da546Spatrick 
AutoCompleteDiskFileOrDirectory(CompletionRequest & request,bool only_dir)3151be691f3bSpatrick void GDBRemoteCommunicationClient::AutoCompleteDiskFileOrDirectory(
3152be691f3bSpatrick     CompletionRequest &request, bool only_dir) {
3153be691f3bSpatrick   lldb_private::StreamString stream;
3154be691f3bSpatrick   stream.PutCString("qPathComplete:");
3155be691f3bSpatrick   stream.PutHex32(only_dir ? 1 : 0);
3156be691f3bSpatrick   stream.PutChar(',');
3157be691f3bSpatrick   stream.PutStringAsRawHex8(request.GetCursorArgumentPrefix());
3158be691f3bSpatrick   StringExtractorGDBRemote response;
3159be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3160be691f3bSpatrick       PacketResult::Success) {
3161be691f3bSpatrick     StreamString strm;
3162be691f3bSpatrick     char ch = response.GetChar();
3163be691f3bSpatrick     if (ch != 'M')
3164be691f3bSpatrick       return;
3165be691f3bSpatrick     while (response.Peek()) {
3166be691f3bSpatrick       strm.Clear();
3167be691f3bSpatrick       while ((ch = response.GetHexU8(0, false)) != '\0')
3168be691f3bSpatrick         strm.PutChar(ch);
3169be691f3bSpatrick       request.AddCompletion(strm.GetString());
3170be691f3bSpatrick       if (response.GetChar() != ',')
3171be691f3bSpatrick         break;
3172be691f3bSpatrick     }
3173be691f3bSpatrick   }
3174be691f3bSpatrick }
3175be691f3bSpatrick 
3176061da546Spatrick Status
GetFilePermissions(const FileSpec & file_spec,uint32_t & file_permissions)3177061da546Spatrick GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec,
3178061da546Spatrick                                                  uint32_t &file_permissions) {
3179*f6aab3d8Srobert   if (m_supports_vFileMode) {
3180061da546Spatrick     std::string path{file_spec.GetPath(false)};
3181061da546Spatrick     Status error;
3182061da546Spatrick     lldb_private::StreamString stream;
3183061da546Spatrick     stream.PutCString("vFile:mode:");
3184061da546Spatrick     stream.PutStringAsRawHex8(path);
3185061da546Spatrick     StringExtractorGDBRemote response;
3186*f6aab3d8Srobert     if (SendPacketAndWaitForResponse(stream.GetString(), response) !=
3187061da546Spatrick         PacketResult::Success) {
3188*f6aab3d8Srobert       error.SetErrorStringWithFormat("failed to send '%s' packet",
3189*f6aab3d8Srobert                                      stream.GetData());
3190*f6aab3d8Srobert       return error;
3191*f6aab3d8Srobert     }
3192*f6aab3d8Srobert     if (!response.IsUnsupportedResponse()) {
3193061da546Spatrick       if (response.GetChar() != 'F') {
3194061da546Spatrick         error.SetErrorStringWithFormat("invalid response to '%s' packet",
3195061da546Spatrick                                        stream.GetData());
3196061da546Spatrick       } else {
3197*f6aab3d8Srobert         const uint32_t mode = response.GetS32(-1, 16);
3198061da546Spatrick         if (static_cast<int32_t>(mode) == -1) {
3199061da546Spatrick           if (response.GetChar() == ',') {
3200*f6aab3d8Srobert             int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
3201061da546Spatrick             if (response_errno > 0)
3202061da546Spatrick               error.SetError(response_errno, lldb::eErrorTypePOSIX);
3203061da546Spatrick             else
3204061da546Spatrick               error.SetErrorToGenericError();
3205061da546Spatrick           } else
3206061da546Spatrick             error.SetErrorToGenericError();
3207061da546Spatrick         } else {
3208061da546Spatrick           file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO);
3209061da546Spatrick         }
3210061da546Spatrick       }
3211061da546Spatrick       return error;
3212*f6aab3d8Srobert     } else { // response.IsUnsupportedResponse()
3213*f6aab3d8Srobert       m_supports_vFileMode = false;
3214*f6aab3d8Srobert     }
3215*f6aab3d8Srobert   }
3216*f6aab3d8Srobert 
3217*f6aab3d8Srobert   // Fallback to fstat.
3218*f6aab3d8Srobert   if (std::optional<GDBRemoteFStatData> st = Stat(file_spec)) {
3219*f6aab3d8Srobert     file_permissions = st->gdb_st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
3220*f6aab3d8Srobert     return Status();
3221*f6aab3d8Srobert   }
3222*f6aab3d8Srobert   return Status("fstat failed");
3223061da546Spatrick }
3224061da546Spatrick 
ReadFile(lldb::user_id_t fd,uint64_t offset,void * dst,uint64_t dst_len,Status & error)3225061da546Spatrick uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd,
3226061da546Spatrick                                                 uint64_t offset, void *dst,
3227061da546Spatrick                                                 uint64_t dst_len,
3228061da546Spatrick                                                 Status &error) {
3229061da546Spatrick   lldb_private::StreamString stream;
3230*f6aab3d8Srobert   stream.Printf("vFile:pread:%x,%" PRIx64 ",%" PRIx64, (int)fd, dst_len,
3231061da546Spatrick                 offset);
3232061da546Spatrick   StringExtractorGDBRemote response;
3233be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3234061da546Spatrick       PacketResult::Success) {
3235061da546Spatrick     if (response.GetChar() != 'F')
3236061da546Spatrick       return 0;
3237*f6aab3d8Srobert     int64_t retcode = response.GetS64(-1, 16);
3238*f6aab3d8Srobert     if (retcode == -1) {
3239*f6aab3d8Srobert       error.SetErrorToGenericError();
3240*f6aab3d8Srobert       if (response.GetChar() == ',') {
3241*f6aab3d8Srobert         int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
3242*f6aab3d8Srobert         if (response_errno > 0)
3243*f6aab3d8Srobert           error.SetError(response_errno, lldb::eErrorTypePOSIX);
3244*f6aab3d8Srobert       }
3245*f6aab3d8Srobert       return -1;
3246*f6aab3d8Srobert     }
3247061da546Spatrick     const char next = (response.Peek() ? *response.Peek() : 0);
3248061da546Spatrick     if (next == ',')
3249061da546Spatrick       return 0;
3250061da546Spatrick     if (next == ';') {
3251061da546Spatrick       response.GetChar(); // skip the semicolon
3252061da546Spatrick       std::string buffer;
3253061da546Spatrick       if (response.GetEscapedBinaryData(buffer)) {
3254061da546Spatrick         const uint64_t data_to_write =
3255061da546Spatrick             std::min<uint64_t>(dst_len, buffer.size());
3256061da546Spatrick         if (data_to_write > 0)
3257061da546Spatrick           memcpy(dst, &buffer[0], data_to_write);
3258061da546Spatrick         return data_to_write;
3259061da546Spatrick       }
3260061da546Spatrick     }
3261061da546Spatrick   }
3262061da546Spatrick   return 0;
3263061da546Spatrick }
3264061da546Spatrick 
WriteFile(lldb::user_id_t fd,uint64_t offset,const void * src,uint64_t src_len,Status & error)3265061da546Spatrick uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd,
3266061da546Spatrick                                                  uint64_t offset,
3267061da546Spatrick                                                  const void *src,
3268061da546Spatrick                                                  uint64_t src_len,
3269061da546Spatrick                                                  Status &error) {
3270061da546Spatrick   lldb_private::StreamGDBRemote stream;
3271*f6aab3d8Srobert   stream.Printf("vFile:pwrite:%x,%" PRIx64 ",", (int)fd, offset);
3272061da546Spatrick   stream.PutEscapedBytes(src, src_len);
3273061da546Spatrick   StringExtractorGDBRemote response;
3274be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3275061da546Spatrick       PacketResult::Success) {
3276061da546Spatrick     if (response.GetChar() != 'F') {
3277061da546Spatrick       error.SetErrorStringWithFormat("write file failed");
3278061da546Spatrick       return 0;
3279061da546Spatrick     }
3280*f6aab3d8Srobert     int64_t bytes_written = response.GetS64(-1, 16);
3281*f6aab3d8Srobert     if (bytes_written == -1) {
3282061da546Spatrick       error.SetErrorToGenericError();
3283061da546Spatrick       if (response.GetChar() == ',') {
3284*f6aab3d8Srobert         int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
3285061da546Spatrick         if (response_errno > 0)
3286061da546Spatrick           error.SetError(response_errno, lldb::eErrorTypePOSIX);
3287061da546Spatrick       }
3288*f6aab3d8Srobert       return -1;
3289061da546Spatrick     }
3290061da546Spatrick     return bytes_written;
3291061da546Spatrick   } else {
3292061da546Spatrick     error.SetErrorString("failed to send vFile:pwrite packet");
3293061da546Spatrick   }
3294061da546Spatrick   return 0;
3295061da546Spatrick }
3296061da546Spatrick 
CreateSymlink(const FileSpec & src,const FileSpec & dst)3297061da546Spatrick Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src,
3298061da546Spatrick                                                    const FileSpec &dst) {
3299061da546Spatrick   std::string src_path{src.GetPath(false)}, dst_path{dst.GetPath(false)};
3300061da546Spatrick   Status error;
3301061da546Spatrick   lldb_private::StreamGDBRemote stream;
3302061da546Spatrick   stream.PutCString("vFile:symlink:");
3303061da546Spatrick   // the unix symlink() command reverses its parameters where the dst if first,
3304061da546Spatrick   // so we follow suit here
3305061da546Spatrick   stream.PutStringAsRawHex8(dst_path);
3306061da546Spatrick   stream.PutChar(',');
3307061da546Spatrick   stream.PutStringAsRawHex8(src_path);
3308061da546Spatrick   StringExtractorGDBRemote response;
3309be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3310061da546Spatrick       PacketResult::Success) {
3311061da546Spatrick     if (response.GetChar() == 'F') {
3312*f6aab3d8Srobert       uint32_t result = response.GetHexMaxU32(false, UINT32_MAX);
3313061da546Spatrick       if (result != 0) {
3314061da546Spatrick         error.SetErrorToGenericError();
3315061da546Spatrick         if (response.GetChar() == ',') {
3316*f6aab3d8Srobert           int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
3317061da546Spatrick           if (response_errno > 0)
3318061da546Spatrick             error.SetError(response_errno, lldb::eErrorTypePOSIX);
3319061da546Spatrick         }
3320061da546Spatrick       }
3321061da546Spatrick     } else {
3322061da546Spatrick       // Should have returned with 'F<result>[,<errno>]'
3323061da546Spatrick       error.SetErrorStringWithFormat("symlink failed");
3324061da546Spatrick     }
3325061da546Spatrick   } else {
3326061da546Spatrick     error.SetErrorString("failed to send vFile:symlink packet");
3327061da546Spatrick   }
3328061da546Spatrick   return error;
3329061da546Spatrick }
3330061da546Spatrick 
Unlink(const FileSpec & file_spec)3331061da546Spatrick Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) {
3332061da546Spatrick   std::string path{file_spec.GetPath(false)};
3333061da546Spatrick   Status error;
3334061da546Spatrick   lldb_private::StreamGDBRemote stream;
3335061da546Spatrick   stream.PutCString("vFile:unlink:");
3336061da546Spatrick   // the unix symlink() command reverses its parameters where the dst if first,
3337061da546Spatrick   // so we follow suit here
3338061da546Spatrick   stream.PutStringAsRawHex8(path);
3339061da546Spatrick   StringExtractorGDBRemote response;
3340be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3341061da546Spatrick       PacketResult::Success) {
3342061da546Spatrick     if (response.GetChar() == 'F') {
3343*f6aab3d8Srobert       uint32_t result = response.GetHexMaxU32(false, UINT32_MAX);
3344061da546Spatrick       if (result != 0) {
3345061da546Spatrick         error.SetErrorToGenericError();
3346061da546Spatrick         if (response.GetChar() == ',') {
3347*f6aab3d8Srobert           int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
3348061da546Spatrick           if (response_errno > 0)
3349061da546Spatrick             error.SetError(response_errno, lldb::eErrorTypePOSIX);
3350061da546Spatrick         }
3351061da546Spatrick       }
3352061da546Spatrick     } else {
3353061da546Spatrick       // Should have returned with 'F<result>[,<errno>]'
3354061da546Spatrick       error.SetErrorStringWithFormat("unlink failed");
3355061da546Spatrick     }
3356061da546Spatrick   } else {
3357061da546Spatrick     error.SetErrorString("failed to send vFile:unlink packet");
3358061da546Spatrick   }
3359061da546Spatrick   return error;
3360061da546Spatrick }
3361061da546Spatrick 
3362061da546Spatrick // Extension of host I/O packets to get whether a file exists.
GetFileExists(const lldb_private::FileSpec & file_spec)3363061da546Spatrick bool GDBRemoteCommunicationClient::GetFileExists(
3364061da546Spatrick     const lldb_private::FileSpec &file_spec) {
3365*f6aab3d8Srobert   if (m_supports_vFileExists) {
3366061da546Spatrick     std::string path(file_spec.GetPath(false));
3367061da546Spatrick     lldb_private::StreamString stream;
3368061da546Spatrick     stream.PutCString("vFile:exists:");
3369061da546Spatrick     stream.PutStringAsRawHex8(path);
3370061da546Spatrick     StringExtractorGDBRemote response;
3371*f6aab3d8Srobert     if (SendPacketAndWaitForResponse(stream.GetString(), response) !=
3372*f6aab3d8Srobert         PacketResult::Success)
3373*f6aab3d8Srobert       return false;
3374*f6aab3d8Srobert     if (!response.IsUnsupportedResponse()) {
3375061da546Spatrick       if (response.GetChar() != 'F')
3376061da546Spatrick         return false;
3377061da546Spatrick       if (response.GetChar() != ',')
3378061da546Spatrick         return false;
3379061da546Spatrick       bool retcode = (response.GetChar() != '0');
3380061da546Spatrick       return retcode;
3381*f6aab3d8Srobert     } else
3382*f6aab3d8Srobert       m_supports_vFileExists = false;
3383061da546Spatrick   }
3384*f6aab3d8Srobert 
3385*f6aab3d8Srobert   // Fallback to open.
3386*f6aab3d8Srobert   Status error;
3387*f6aab3d8Srobert   lldb::user_id_t fd = OpenFile(file_spec, File::eOpenOptionReadOnly, 0, error);
3388*f6aab3d8Srobert   if (fd == UINT64_MAX)
3389061da546Spatrick     return false;
3390*f6aab3d8Srobert   CloseFile(fd, error);
3391*f6aab3d8Srobert   return true;
3392061da546Spatrick }
3393061da546Spatrick 
CalculateMD5(const lldb_private::FileSpec & file_spec,uint64_t & high,uint64_t & low)3394061da546Spatrick bool GDBRemoteCommunicationClient::CalculateMD5(
3395061da546Spatrick     const lldb_private::FileSpec &file_spec, uint64_t &high, uint64_t &low) {
3396061da546Spatrick   std::string path(file_spec.GetPath(false));
3397061da546Spatrick   lldb_private::StreamString stream;
3398061da546Spatrick   stream.PutCString("vFile:MD5:");
3399061da546Spatrick   stream.PutStringAsRawHex8(path);
3400061da546Spatrick   StringExtractorGDBRemote response;
3401be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3402061da546Spatrick       PacketResult::Success) {
3403061da546Spatrick     if (response.GetChar() != 'F')
3404061da546Spatrick       return false;
3405061da546Spatrick     if (response.GetChar() != ',')
3406061da546Spatrick       return false;
3407061da546Spatrick     if (response.Peek() && *response.Peek() == 'x')
3408061da546Spatrick       return false;
3409061da546Spatrick     low = response.GetHexMaxU64(false, UINT64_MAX);
3410061da546Spatrick     high = response.GetHexMaxU64(false, UINT64_MAX);
3411061da546Spatrick     return true;
3412061da546Spatrick   }
3413061da546Spatrick   return false;
3414061da546Spatrick }
3415061da546Spatrick 
AvoidGPackets(ProcessGDBRemote * process)3416061da546Spatrick bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) {
3417061da546Spatrick   // Some targets have issues with g/G packets and we need to avoid using them
3418061da546Spatrick   if (m_avoid_g_packets == eLazyBoolCalculate) {
3419061da546Spatrick     if (process) {
3420061da546Spatrick       m_avoid_g_packets = eLazyBoolNo;
3421061da546Spatrick       const ArchSpec &arch = process->GetTarget().GetArchitecture();
3422061da546Spatrick       if (arch.IsValid() &&
3423061da546Spatrick           arch.GetTriple().getVendor() == llvm::Triple::Apple &&
3424061da546Spatrick           arch.GetTriple().getOS() == llvm::Triple::IOS &&
3425061da546Spatrick           (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
3426061da546Spatrick            arch.GetTriple().getArch() == llvm::Triple::aarch64_32)) {
3427061da546Spatrick         m_avoid_g_packets = eLazyBoolYes;
3428061da546Spatrick         uint32_t gdb_server_version = GetGDBServerProgramVersion();
3429061da546Spatrick         if (gdb_server_version != 0) {
3430061da546Spatrick           const char *gdb_server_name = GetGDBServerProgramName();
3431061da546Spatrick           if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0) {
3432061da546Spatrick             if (gdb_server_version >= 310)
3433061da546Spatrick               m_avoid_g_packets = eLazyBoolNo;
3434061da546Spatrick           }
3435061da546Spatrick         }
3436061da546Spatrick       }
3437061da546Spatrick     }
3438061da546Spatrick   }
3439061da546Spatrick   return m_avoid_g_packets == eLazyBoolYes;
3440061da546Spatrick }
3441061da546Spatrick 
ReadRegister(lldb::tid_t tid,uint32_t reg)3442061da546Spatrick DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid,
3443061da546Spatrick                                                         uint32_t reg) {
3444061da546Spatrick   StreamString payload;
3445061da546Spatrick   payload.Printf("p%x", reg);
3446061da546Spatrick   StringExtractorGDBRemote response;
3447061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
3448be691f3bSpatrick           tid, std::move(payload), response) != PacketResult::Success ||
3449061da546Spatrick       !response.IsNormalResponse())
3450061da546Spatrick     return nullptr;
3451061da546Spatrick 
3452*f6aab3d8Srobert   WritableDataBufferSP buffer_sp(
3453061da546Spatrick       new DataBufferHeap(response.GetStringRef().size() / 2, 0));
3454061da546Spatrick   response.GetHexBytes(buffer_sp->GetData(), '\xcc');
3455061da546Spatrick   return buffer_sp;
3456061da546Spatrick }
3457061da546Spatrick 
ReadAllRegisters(lldb::tid_t tid)3458061da546Spatrick DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) {
3459061da546Spatrick   StreamString payload;
3460061da546Spatrick   payload.PutChar('g');
3461061da546Spatrick   StringExtractorGDBRemote response;
3462061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
3463be691f3bSpatrick           tid, std::move(payload), response) != PacketResult::Success ||
3464061da546Spatrick       !response.IsNormalResponse())
3465061da546Spatrick     return nullptr;
3466061da546Spatrick 
3467*f6aab3d8Srobert   WritableDataBufferSP buffer_sp(
3468061da546Spatrick       new DataBufferHeap(response.GetStringRef().size() / 2, 0));
3469061da546Spatrick   response.GetHexBytes(buffer_sp->GetData(), '\xcc');
3470061da546Spatrick   return buffer_sp;
3471061da546Spatrick }
3472061da546Spatrick 
WriteRegister(lldb::tid_t tid,uint32_t reg_num,llvm::ArrayRef<uint8_t> data)3473061da546Spatrick bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid,
3474061da546Spatrick                                                  uint32_t reg_num,
3475061da546Spatrick                                                  llvm::ArrayRef<uint8_t> data) {
3476061da546Spatrick   StreamString payload;
3477061da546Spatrick   payload.Printf("P%x=", reg_num);
3478061da546Spatrick   payload.PutBytesAsRawHex8(data.data(), data.size(),
3479061da546Spatrick                             endian::InlHostByteOrder(),
3480061da546Spatrick                             endian::InlHostByteOrder());
3481061da546Spatrick   StringExtractorGDBRemote response;
3482be691f3bSpatrick   return SendThreadSpecificPacketAndWaitForResponse(
3483be691f3bSpatrick              tid, std::move(payload), response) == PacketResult::Success &&
3484061da546Spatrick          response.IsOKResponse();
3485061da546Spatrick }
3486061da546Spatrick 
WriteAllRegisters(lldb::tid_t tid,llvm::ArrayRef<uint8_t> data)3487061da546Spatrick bool GDBRemoteCommunicationClient::WriteAllRegisters(
3488061da546Spatrick     lldb::tid_t tid, llvm::ArrayRef<uint8_t> data) {
3489061da546Spatrick   StreamString payload;
3490061da546Spatrick   payload.PutChar('G');
3491061da546Spatrick   payload.PutBytesAsRawHex8(data.data(), data.size(),
3492061da546Spatrick                             endian::InlHostByteOrder(),
3493061da546Spatrick                             endian::InlHostByteOrder());
3494061da546Spatrick   StringExtractorGDBRemote response;
3495be691f3bSpatrick   return SendThreadSpecificPacketAndWaitForResponse(
3496be691f3bSpatrick              tid, std::move(payload), response) == PacketResult::Success &&
3497061da546Spatrick          response.IsOKResponse();
3498061da546Spatrick }
3499061da546Spatrick 
SaveRegisterState(lldb::tid_t tid,uint32_t & save_id)3500061da546Spatrick bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
3501061da546Spatrick                                                      uint32_t &save_id) {
3502061da546Spatrick   save_id = 0; // Set to invalid save ID
3503061da546Spatrick   if (m_supports_QSaveRegisterState == eLazyBoolNo)
3504061da546Spatrick     return false;
3505061da546Spatrick 
3506061da546Spatrick   m_supports_QSaveRegisterState = eLazyBoolYes;
3507061da546Spatrick   StreamString payload;
3508061da546Spatrick   payload.PutCString("QSaveRegisterState");
3509061da546Spatrick   StringExtractorGDBRemote response;
3510061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
3511be691f3bSpatrick           tid, std::move(payload), response) != PacketResult::Success)
3512061da546Spatrick     return false;
3513061da546Spatrick 
3514061da546Spatrick   if (response.IsUnsupportedResponse())
3515061da546Spatrick     m_supports_QSaveRegisterState = eLazyBoolNo;
3516061da546Spatrick 
3517061da546Spatrick   const uint32_t response_save_id = response.GetU32(0);
3518061da546Spatrick   if (response_save_id == 0)
3519061da546Spatrick     return false;
3520061da546Spatrick 
3521061da546Spatrick   save_id = response_save_id;
3522061da546Spatrick   return true;
3523061da546Spatrick }
3524061da546Spatrick 
RestoreRegisterState(lldb::tid_t tid,uint32_t save_id)3525061da546Spatrick bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
3526061da546Spatrick                                                         uint32_t save_id) {
3527061da546Spatrick   // We use the "m_supports_QSaveRegisterState" variable here because the
3528061da546Spatrick   // QSaveRegisterState and QRestoreRegisterState packets must both be
3529061da546Spatrick   // supported in order to be useful
3530061da546Spatrick   if (m_supports_QSaveRegisterState == eLazyBoolNo)
3531061da546Spatrick     return false;
3532061da546Spatrick 
3533061da546Spatrick   StreamString payload;
3534061da546Spatrick   payload.Printf("QRestoreRegisterState:%u", save_id);
3535061da546Spatrick   StringExtractorGDBRemote response;
3536061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
3537be691f3bSpatrick           tid, std::move(payload), response) != PacketResult::Success)
3538061da546Spatrick     return false;
3539061da546Spatrick 
3540061da546Spatrick   if (response.IsOKResponse())
3541061da546Spatrick     return true;
3542061da546Spatrick 
3543061da546Spatrick   if (response.IsUnsupportedResponse())
3544061da546Spatrick     m_supports_QSaveRegisterState = eLazyBoolNo;
3545061da546Spatrick   return false;
3546061da546Spatrick }
3547061da546Spatrick 
SyncThreadState(lldb::tid_t tid)3548061da546Spatrick bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) {
3549061da546Spatrick   if (!GetSyncThreadStateSupported())
3550061da546Spatrick     return false;
3551061da546Spatrick 
3552061da546Spatrick   StreamString packet;
3553061da546Spatrick   StringExtractorGDBRemote response;
3554061da546Spatrick   packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid);
3555be691f3bSpatrick   return SendPacketAndWaitForResponse(packet.GetString(), response) ==
3556061da546Spatrick              GDBRemoteCommunication::PacketResult::Success &&
3557061da546Spatrick          response.IsOKResponse();
3558061da546Spatrick }
3559061da546Spatrick 
3560be691f3bSpatrick llvm::Expected<TraceSupportedResponse>
SendTraceSupported(std::chrono::seconds timeout)3561be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceSupported(std::chrono::seconds timeout) {
3562*f6aab3d8Srobert   Log *log = GetLog(GDBRLog::Process);
3563061da546Spatrick 
3564061da546Spatrick   StreamGDBRemote escaped_packet;
3565be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceSupported");
3566061da546Spatrick 
3567061da546Spatrick   StringExtractorGDBRemote response;
3568061da546Spatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3569be691f3bSpatrick                                    timeout) ==
3570061da546Spatrick       GDBRemoteCommunication::PacketResult::Success) {
3571be691f3bSpatrick     if (response.IsErrorResponse())
3572be691f3bSpatrick       return response.GetStatus().ToError();
3573be691f3bSpatrick     if (response.IsUnsupportedResponse())
3574be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3575be691f3bSpatrick                                      "jLLDBTraceSupported is unsupported");
3576be691f3bSpatrick 
3577be691f3bSpatrick     return llvm::json::parse<TraceSupportedResponse>(response.Peek(),
3578be691f3bSpatrick                                                      "TraceSupportedResponse");
3579061da546Spatrick   }
3580be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceSupported");
3581be691f3bSpatrick   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3582be691f3bSpatrick                                  "failed to send packet: jLLDBTraceSupported");
3583be691f3bSpatrick }
3584be691f3bSpatrick 
3585be691f3bSpatrick llvm::Error
SendTraceStop(const TraceStopRequest & request,std::chrono::seconds timeout)3586be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request,
3587be691f3bSpatrick                                             std::chrono::seconds timeout) {
3588*f6aab3d8Srobert   Log *log = GetLog(GDBRLog::Process);
3589be691f3bSpatrick 
3590be691f3bSpatrick   StreamGDBRemote escaped_packet;
3591be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceStop:");
3592be691f3bSpatrick 
3593be691f3bSpatrick   std::string json_string;
3594be691f3bSpatrick   llvm::raw_string_ostream os(json_string);
3595be691f3bSpatrick   os << toJSON(request);
3596be691f3bSpatrick   os.flush();
3597be691f3bSpatrick 
3598be691f3bSpatrick   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3599be691f3bSpatrick 
3600be691f3bSpatrick   StringExtractorGDBRemote response;
3601be691f3bSpatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3602be691f3bSpatrick                                    timeout) ==
3603be691f3bSpatrick       GDBRemoteCommunication::PacketResult::Success) {
3604be691f3bSpatrick     if (response.IsErrorResponse())
3605be691f3bSpatrick       return response.GetStatus().ToError();
3606be691f3bSpatrick     if (response.IsUnsupportedResponse())
3607be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3608be691f3bSpatrick                                      "jLLDBTraceStop is unsupported");
3609be691f3bSpatrick     if (response.IsOKResponse())
3610be691f3bSpatrick       return llvm::Error::success();
3611be691f3bSpatrick     return llvm::createStringError(llvm::inconvertibleErrorCode(),
3612be691f3bSpatrick                                    "Invalid jLLDBTraceStart response");
3613be691f3bSpatrick   }
3614be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceStop");
3615be691f3bSpatrick   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3616be691f3bSpatrick                                  "failed to send packet: jLLDBTraceStop '%s'",
3617061da546Spatrick                                  escaped_packet.GetData());
3618061da546Spatrick }
3619061da546Spatrick 
3620be691f3bSpatrick llvm::Error
SendTraceStart(const llvm::json::Value & params,std::chrono::seconds timeout)3621be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value &params,
3622be691f3bSpatrick                                              std::chrono::seconds timeout) {
3623*f6aab3d8Srobert   Log *log = GetLog(GDBRLog::Process);
3624be691f3bSpatrick 
3625be691f3bSpatrick   StreamGDBRemote escaped_packet;
3626be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceStart:");
3627be691f3bSpatrick 
3628be691f3bSpatrick   std::string json_string;
3629be691f3bSpatrick   llvm::raw_string_ostream os(json_string);
3630be691f3bSpatrick   os << params;
3631be691f3bSpatrick   os.flush();
3632be691f3bSpatrick 
3633be691f3bSpatrick   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3634be691f3bSpatrick 
3635061da546Spatrick   StringExtractorGDBRemote response;
3636061da546Spatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3637be691f3bSpatrick                                    timeout) ==
3638061da546Spatrick       GDBRemoteCommunication::PacketResult::Success) {
3639be691f3bSpatrick     if (response.IsErrorResponse())
3640be691f3bSpatrick       return response.GetStatus().ToError();
3641be691f3bSpatrick     if (response.IsUnsupportedResponse())
3642be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3643be691f3bSpatrick                                      "jLLDBTraceStart is unsupported");
3644be691f3bSpatrick     if (response.IsOKResponse())
3645be691f3bSpatrick       return llvm::Error::success();
3646be691f3bSpatrick     return llvm::createStringError(llvm::inconvertibleErrorCode(),
3647be691f3bSpatrick                                    "Invalid jLLDBTraceStart response");
3648061da546Spatrick   }
3649be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceStart");
3650be691f3bSpatrick   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3651be691f3bSpatrick                                  "failed to send packet: jLLDBTraceStart '%s'",
3652061da546Spatrick                                  escaped_packet.GetData());
3653061da546Spatrick }
3654061da546Spatrick 
3655be691f3bSpatrick llvm::Expected<std::string>
SendTraceGetState(llvm::StringRef type,std::chrono::seconds timeout)3656be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type,
3657be691f3bSpatrick                                                 std::chrono::seconds timeout) {
3658*f6aab3d8Srobert   Log *log = GetLog(GDBRLog::Process);
3659061da546Spatrick 
3660be691f3bSpatrick   StreamGDBRemote escaped_packet;
3661be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceGetState:");
3662061da546Spatrick 
3663be691f3bSpatrick   std::string json_string;
3664be691f3bSpatrick   llvm::raw_string_ostream os(json_string);
3665be691f3bSpatrick   os << toJSON(TraceGetStateRequest{type.str()});
3666be691f3bSpatrick   os.flush();
3667061da546Spatrick 
3668be691f3bSpatrick   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3669061da546Spatrick 
3670061da546Spatrick   StringExtractorGDBRemote response;
3671be691f3bSpatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3672be691f3bSpatrick                                    timeout) ==
3673061da546Spatrick       GDBRemoteCommunication::PacketResult::Success) {
3674be691f3bSpatrick     if (response.IsErrorResponse())
3675be691f3bSpatrick       return response.GetStatus().ToError();
3676be691f3bSpatrick     if (response.IsUnsupportedResponse())
3677be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3678be691f3bSpatrick                                      "jLLDBTraceGetState is unsupported");
3679be691f3bSpatrick     return std::string(response.Peek());
3680061da546Spatrick   }
3681be691f3bSpatrick 
3682be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceGetState");
3683be691f3bSpatrick   return llvm::createStringError(
3684be691f3bSpatrick       llvm::inconvertibleErrorCode(),
3685be691f3bSpatrick       "failed to send packet: jLLDBTraceGetState '%s'",
3686be691f3bSpatrick       escaped_packet.GetData());
3687061da546Spatrick }
3688be691f3bSpatrick 
3689be691f3bSpatrick llvm::Expected<std::vector<uint8_t>>
SendTraceGetBinaryData(const TraceGetBinaryDataRequest & request,std::chrono::seconds timeout)3690be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceGetBinaryData(
3691be691f3bSpatrick     const TraceGetBinaryDataRequest &request, std::chrono::seconds timeout) {
3692*f6aab3d8Srobert   Log *log = GetLog(GDBRLog::Process);
3693be691f3bSpatrick 
3694be691f3bSpatrick   StreamGDBRemote escaped_packet;
3695be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceGetBinaryData:");
3696be691f3bSpatrick 
3697be691f3bSpatrick   std::string json_string;
3698be691f3bSpatrick   llvm::raw_string_ostream os(json_string);
3699be691f3bSpatrick   os << toJSON(request);
3700be691f3bSpatrick   os.flush();
3701be691f3bSpatrick 
3702be691f3bSpatrick   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3703be691f3bSpatrick 
3704be691f3bSpatrick   StringExtractorGDBRemote response;
3705be691f3bSpatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3706be691f3bSpatrick                                    timeout) ==
3707be691f3bSpatrick       GDBRemoteCommunication::PacketResult::Success) {
3708be691f3bSpatrick     if (response.IsErrorResponse())
3709be691f3bSpatrick       return response.GetStatus().ToError();
3710be691f3bSpatrick     std::string data;
3711be691f3bSpatrick     response.GetEscapedBinaryData(data);
3712be691f3bSpatrick     return std::vector<uint8_t>(data.begin(), data.end());
3713be691f3bSpatrick   }
3714be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceGetBinaryData");
3715be691f3bSpatrick   return llvm::createStringError(
3716be691f3bSpatrick       llvm::inconvertibleErrorCode(),
3717be691f3bSpatrick       "failed to send packet: jLLDBTraceGetBinaryData '%s'",
3718be691f3bSpatrick       escaped_packet.GetData());
3719061da546Spatrick }
3720061da546Spatrick 
GetQOffsets()3721*f6aab3d8Srobert std::optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() {
3722dda28197Spatrick   StringExtractorGDBRemote response;
3723be691f3bSpatrick   if (SendPacketAndWaitForResponse("qOffsets", response) !=
3724be691f3bSpatrick       PacketResult::Success)
3725*f6aab3d8Srobert     return std::nullopt;
3726dda28197Spatrick   if (!response.IsNormalResponse())
3727*f6aab3d8Srobert     return std::nullopt;
3728dda28197Spatrick 
3729dda28197Spatrick   QOffsets result;
3730dda28197Spatrick   llvm::StringRef ref = response.GetStringRef();
3731dda28197Spatrick   const auto &GetOffset = [&] {
3732dda28197Spatrick     addr_t offset;
3733dda28197Spatrick     if (ref.consumeInteger(16, offset))
3734dda28197Spatrick       return false;
3735dda28197Spatrick     result.offsets.push_back(offset);
3736dda28197Spatrick     return true;
3737dda28197Spatrick   };
3738dda28197Spatrick 
3739dda28197Spatrick   if (ref.consume_front("Text=")) {
3740dda28197Spatrick     result.segments = false;
3741dda28197Spatrick     if (!GetOffset())
3742*f6aab3d8Srobert       return std::nullopt;
3743dda28197Spatrick     if (!ref.consume_front(";Data=") || !GetOffset())
3744*f6aab3d8Srobert       return std::nullopt;
3745dda28197Spatrick     if (ref.empty())
3746dda28197Spatrick       return result;
3747dda28197Spatrick     if (ref.consume_front(";Bss=") && GetOffset() && ref.empty())
3748dda28197Spatrick       return result;
3749dda28197Spatrick   } else if (ref.consume_front("TextSeg=")) {
3750dda28197Spatrick     result.segments = true;
3751dda28197Spatrick     if (!GetOffset())
3752*f6aab3d8Srobert       return std::nullopt;
3753dda28197Spatrick     if (ref.empty())
3754dda28197Spatrick       return result;
3755dda28197Spatrick     if (ref.consume_front(";DataSeg=") && GetOffset() && ref.empty())
3756dda28197Spatrick       return result;
3757dda28197Spatrick   }
3758*f6aab3d8Srobert   return std::nullopt;
3759dda28197Spatrick }
3760dda28197Spatrick 
GetModuleInfo(const FileSpec & module_file_spec,const lldb_private::ArchSpec & arch_spec,ModuleSpec & module_spec)3761061da546Spatrick bool GDBRemoteCommunicationClient::GetModuleInfo(
3762061da546Spatrick     const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec,
3763061da546Spatrick     ModuleSpec &module_spec) {
3764061da546Spatrick   if (!m_supports_qModuleInfo)
3765061da546Spatrick     return false;
3766061da546Spatrick 
3767061da546Spatrick   std::string module_path = module_file_spec.GetPath(false);
3768061da546Spatrick   if (module_path.empty())
3769061da546Spatrick     return false;
3770061da546Spatrick 
3771061da546Spatrick   StreamString packet;
3772061da546Spatrick   packet.PutCString("qModuleInfo:");
3773061da546Spatrick   packet.PutStringAsRawHex8(module_path);
3774061da546Spatrick   packet.PutCString(";");
3775061da546Spatrick   const auto &triple = arch_spec.GetTriple().getTriple();
3776061da546Spatrick   packet.PutStringAsRawHex8(triple);
3777061da546Spatrick 
3778061da546Spatrick   StringExtractorGDBRemote response;
3779be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
3780061da546Spatrick       PacketResult::Success)
3781061da546Spatrick     return false;
3782061da546Spatrick 
3783061da546Spatrick   if (response.IsErrorResponse())
3784061da546Spatrick     return false;
3785061da546Spatrick 
3786061da546Spatrick   if (response.IsUnsupportedResponse()) {
3787061da546Spatrick     m_supports_qModuleInfo = false;
3788061da546Spatrick     return false;
3789061da546Spatrick   }
3790061da546Spatrick 
3791061da546Spatrick   llvm::StringRef name;
3792061da546Spatrick   llvm::StringRef value;
3793061da546Spatrick 
3794061da546Spatrick   module_spec.Clear();
3795061da546Spatrick   module_spec.GetFileSpec() = module_file_spec;
3796061da546Spatrick 
3797061da546Spatrick   while (response.GetNameColonValue(name, value)) {
3798061da546Spatrick     if (name == "uuid" || name == "md5") {
3799061da546Spatrick       StringExtractor extractor(value);
3800061da546Spatrick       std::string uuid;
3801061da546Spatrick       extractor.GetHexByteString(uuid);
3802dda28197Spatrick       module_spec.GetUUID().SetFromStringRef(uuid);
3803061da546Spatrick     } else if (name == "triple") {
3804061da546Spatrick       StringExtractor extractor(value);
3805061da546Spatrick       std::string triple;
3806061da546Spatrick       extractor.GetHexByteString(triple);
3807061da546Spatrick       module_spec.GetArchitecture().SetTriple(triple.c_str());
3808061da546Spatrick     } else if (name == "file_offset") {
3809061da546Spatrick       uint64_t ival = 0;
3810061da546Spatrick       if (!value.getAsInteger(16, ival))
3811061da546Spatrick         module_spec.SetObjectOffset(ival);
3812061da546Spatrick     } else if (name == "file_size") {
3813061da546Spatrick       uint64_t ival = 0;
3814061da546Spatrick       if (!value.getAsInteger(16, ival))
3815061da546Spatrick         module_spec.SetObjectSize(ival);
3816061da546Spatrick     } else if (name == "file_path") {
3817061da546Spatrick       StringExtractor extractor(value);
3818061da546Spatrick       std::string path;
3819061da546Spatrick       extractor.GetHexByteString(path);
3820061da546Spatrick       module_spec.GetFileSpec() = FileSpec(path, arch_spec.GetTriple());
3821061da546Spatrick     }
3822061da546Spatrick   }
3823061da546Spatrick 
3824061da546Spatrick   return true;
3825061da546Spatrick }
3826061da546Spatrick 
3827*f6aab3d8Srobert static std::optional<ModuleSpec>
ParseModuleSpec(StructuredData::Dictionary * dict)3828061da546Spatrick ParseModuleSpec(StructuredData::Dictionary *dict) {
3829061da546Spatrick   ModuleSpec result;
3830061da546Spatrick   if (!dict)
3831*f6aab3d8Srobert     return std::nullopt;
3832061da546Spatrick 
3833061da546Spatrick   llvm::StringRef string;
3834061da546Spatrick   uint64_t integer;
3835061da546Spatrick 
3836061da546Spatrick   if (!dict->GetValueForKeyAsString("uuid", string))
3837*f6aab3d8Srobert     return std::nullopt;
3838dda28197Spatrick   if (!result.GetUUID().SetFromStringRef(string))
3839*f6aab3d8Srobert     return std::nullopt;
3840061da546Spatrick 
3841061da546Spatrick   if (!dict->GetValueForKeyAsInteger("file_offset", integer))
3842*f6aab3d8Srobert     return std::nullopt;
3843061da546Spatrick   result.SetObjectOffset(integer);
3844061da546Spatrick 
3845061da546Spatrick   if (!dict->GetValueForKeyAsInteger("file_size", integer))
3846*f6aab3d8Srobert     return std::nullopt;
3847061da546Spatrick   result.SetObjectSize(integer);
3848061da546Spatrick 
3849061da546Spatrick   if (!dict->GetValueForKeyAsString("triple", string))
3850*f6aab3d8Srobert     return std::nullopt;
3851061da546Spatrick   result.GetArchitecture().SetTriple(string);
3852061da546Spatrick 
3853061da546Spatrick   if (!dict->GetValueForKeyAsString("file_path", string))
3854*f6aab3d8Srobert     return std::nullopt;
3855061da546Spatrick   result.GetFileSpec() = FileSpec(string, result.GetArchitecture().GetTriple());
3856061da546Spatrick 
3857061da546Spatrick   return result;
3858061da546Spatrick }
3859061da546Spatrick 
3860*f6aab3d8Srobert std::optional<std::vector<ModuleSpec>>
GetModulesInfo(llvm::ArrayRef<FileSpec> module_file_specs,const llvm::Triple & triple)3861061da546Spatrick GDBRemoteCommunicationClient::GetModulesInfo(
3862061da546Spatrick     llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) {
3863061da546Spatrick   namespace json = llvm::json;
3864061da546Spatrick 
3865061da546Spatrick   if (!m_supports_jModulesInfo)
3866*f6aab3d8Srobert     return std::nullopt;
3867061da546Spatrick 
3868061da546Spatrick   json::Array module_array;
3869061da546Spatrick   for (const FileSpec &module_file_spec : module_file_specs) {
3870061da546Spatrick     module_array.push_back(
3871061da546Spatrick         json::Object{{"file", module_file_spec.GetPath(false)},
3872061da546Spatrick                      {"triple", triple.getTriple()}});
3873061da546Spatrick   }
3874061da546Spatrick   StreamString unescaped_payload;
3875061da546Spatrick   unescaped_payload.PutCString("jModulesInfo:");
3876061da546Spatrick   unescaped_payload.AsRawOstream() << std::move(module_array);
3877061da546Spatrick 
3878061da546Spatrick   StreamGDBRemote payload;
3879061da546Spatrick   payload.PutEscapedBytes(unescaped_payload.GetString().data(),
3880061da546Spatrick                           unescaped_payload.GetSize());
3881061da546Spatrick 
3882061da546Spatrick   // Increase the timeout for jModulesInfo since this packet can take longer.
3883061da546Spatrick   ScopedTimeout timeout(*this, std::chrono::seconds(10));
3884061da546Spatrick 
3885061da546Spatrick   StringExtractorGDBRemote response;
3886be691f3bSpatrick   if (SendPacketAndWaitForResponse(payload.GetString(), response) !=
3887061da546Spatrick           PacketResult::Success ||
3888061da546Spatrick       response.IsErrorResponse())
3889*f6aab3d8Srobert     return std::nullopt;
3890061da546Spatrick 
3891061da546Spatrick   if (response.IsUnsupportedResponse()) {
3892061da546Spatrick     m_supports_jModulesInfo = false;
3893*f6aab3d8Srobert     return std::nullopt;
3894061da546Spatrick   }
3895061da546Spatrick 
3896061da546Spatrick   StructuredData::ObjectSP response_object_sp =
3897dda28197Spatrick       StructuredData::ParseJSON(std::string(response.GetStringRef()));
3898061da546Spatrick   if (!response_object_sp)
3899*f6aab3d8Srobert     return std::nullopt;
3900061da546Spatrick 
3901061da546Spatrick   StructuredData::Array *response_array = response_object_sp->GetAsArray();
3902061da546Spatrick   if (!response_array)
3903*f6aab3d8Srobert     return std::nullopt;
3904061da546Spatrick 
3905061da546Spatrick   std::vector<ModuleSpec> result;
3906061da546Spatrick   for (size_t i = 0; i < response_array->GetSize(); ++i) {
3907*f6aab3d8Srobert     if (std::optional<ModuleSpec> module_spec = ParseModuleSpec(
3908061da546Spatrick             response_array->GetItemAtIndex(i)->GetAsDictionary()))
3909061da546Spatrick       result.push_back(*module_spec);
3910061da546Spatrick   }
3911061da546Spatrick 
3912061da546Spatrick   return result;
3913061da546Spatrick }
3914061da546Spatrick 
3915061da546Spatrick // query the target remote for extended information using the qXfer packet
3916061da546Spatrick //
3917*f6aab3d8Srobert // example: object='features', annex='target.xml'
3918*f6aab3d8Srobert // return: <xml output> or error
3919*f6aab3d8Srobert llvm::Expected<std::string>
ReadExtFeature(llvm::StringRef object,llvm::StringRef annex)3920*f6aab3d8Srobert GDBRemoteCommunicationClient::ReadExtFeature(llvm::StringRef object,
3921*f6aab3d8Srobert                                              llvm::StringRef annex) {
3922061da546Spatrick 
3923*f6aab3d8Srobert   std::string output;
3924*f6aab3d8Srobert   llvm::raw_string_ostream output_stream(output);
3925061da546Spatrick   StringExtractorGDBRemote chunk;
3926061da546Spatrick 
3927061da546Spatrick   uint64_t size = GetRemoteMaxPacketSize();
3928061da546Spatrick   if (size == 0)
3929061da546Spatrick     size = 0x1000;
3930061da546Spatrick   size = size - 1; // Leave space for the 'm' or 'l' character in the response
3931061da546Spatrick   int offset = 0;
3932061da546Spatrick   bool active = true;
3933061da546Spatrick 
3934061da546Spatrick   // loop until all data has been read
3935061da546Spatrick   while (active) {
3936061da546Spatrick 
3937061da546Spatrick     // send query extended feature packet
3938*f6aab3d8Srobert     std::string packet =
3939*f6aab3d8Srobert         ("qXfer:" + object + ":read:" + annex + ":" +
3940*f6aab3d8Srobert          llvm::Twine::utohexstr(offset) + "," + llvm::Twine::utohexstr(size))
3941*f6aab3d8Srobert             .str();
3942061da546Spatrick 
3943061da546Spatrick     GDBRemoteCommunication::PacketResult res =
3944*f6aab3d8Srobert         SendPacketAndWaitForResponse(packet, chunk);
3945061da546Spatrick 
3946*f6aab3d8Srobert     if (res != GDBRemoteCommunication::PacketResult::Success ||
3947*f6aab3d8Srobert         chunk.GetStringRef().empty()) {
3948*f6aab3d8Srobert       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3949*f6aab3d8Srobert                                      "Error sending $qXfer packet");
3950061da546Spatrick     }
3951061da546Spatrick 
3952061da546Spatrick     // check packet code
3953*f6aab3d8Srobert     switch (chunk.GetStringRef()[0]) {
3954061da546Spatrick     // last chunk
3955061da546Spatrick     case ('l'):
3956061da546Spatrick       active = false;
3957*f6aab3d8Srobert       [[fallthrough]];
3958061da546Spatrick 
3959061da546Spatrick     // more chunks
3960061da546Spatrick     case ('m'):
3961*f6aab3d8Srobert       output_stream << chunk.GetStringRef().drop_front();
3962*f6aab3d8Srobert       offset += chunk.GetStringRef().size() - 1;
3963061da546Spatrick       break;
3964061da546Spatrick 
3965061da546Spatrick     // unknown chunk
3966061da546Spatrick     default:
3967*f6aab3d8Srobert       return llvm::createStringError(
3968*f6aab3d8Srobert           llvm::inconvertibleErrorCode(),
3969*f6aab3d8Srobert           "Invalid continuation code from $qXfer packet");
3970061da546Spatrick     }
3971061da546Spatrick   }
3972061da546Spatrick 
3973*f6aab3d8Srobert   return output_stream.str();
3974061da546Spatrick }
3975061da546Spatrick 
3976061da546Spatrick // Notify the target that gdb is prepared to serve symbol lookup requests.
3977061da546Spatrick //  packet: "qSymbol::"
3978061da546Spatrick //  reply:
3979061da546Spatrick //  OK                  The target does not need to look up any (more) symbols.
3980061da546Spatrick //  qSymbol:<sym_name>  The target requests the value of symbol sym_name (hex
3981061da546Spatrick //  encoded).
3982061da546Spatrick //                      LLDB may provide the value by sending another qSymbol
3983061da546Spatrick //                      packet
3984061da546Spatrick //                      in the form of"qSymbol:<sym_value>:<sym_name>".
3985061da546Spatrick //
3986061da546Spatrick //  Three examples:
3987061da546Spatrick //
3988061da546Spatrick //  lldb sends:    qSymbol::
3989061da546Spatrick //  lldb receives: OK
3990061da546Spatrick //     Remote gdb stub does not need to know the addresses of any symbols, lldb
3991061da546Spatrick //     does not
3992061da546Spatrick //     need to ask again in this session.
3993061da546Spatrick //
3994061da546Spatrick //  lldb sends:    qSymbol::
3995061da546Spatrick //  lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
3996061da546Spatrick //  lldb sends:    qSymbol::64697370617463685f71756575655f6f666673657473
3997061da546Spatrick //  lldb receives: OK
3998061da546Spatrick //     Remote gdb stub asks for address of 'dispatch_queue_offsets'.  lldb does
3999061da546Spatrick //     not know
4000061da546Spatrick //     the address at this time.  lldb needs to send qSymbol:: again when it has
4001061da546Spatrick //     more
4002061da546Spatrick //     solibs loaded.
4003061da546Spatrick //
4004061da546Spatrick //  lldb sends:    qSymbol::
4005061da546Spatrick //  lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
4006061da546Spatrick //  lldb sends:    qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473
4007061da546Spatrick //  lldb receives: OK
4008061da546Spatrick //     Remote gdb stub asks for address of 'dispatch_queue_offsets'.  lldb says
4009061da546Spatrick //     that it
4010061da546Spatrick //     is at address 0x2bc97554.  Remote gdb stub sends 'OK' indicating that it
4011061da546Spatrick //     does not
4012061da546Spatrick //     need any more symbols.  lldb does not need to ask again in this session.
4013061da546Spatrick 
ServeSymbolLookups(lldb_private::Process * process)4014061da546Spatrick void GDBRemoteCommunicationClient::ServeSymbolLookups(
4015061da546Spatrick     lldb_private::Process *process) {
4016061da546Spatrick   // Set to true once we've resolved a symbol to an address for the remote
4017061da546Spatrick   // stub. If we get an 'OK' response after this, the remote stub doesn't need
4018061da546Spatrick   // any more symbols and we can stop asking.
4019061da546Spatrick   bool symbol_response_provided = false;
4020061da546Spatrick 
4021061da546Spatrick   // Is this the initial qSymbol:: packet?
4022061da546Spatrick   bool first_qsymbol_query = true;
4023061da546Spatrick 
4024061da546Spatrick   if (m_supports_qSymbol && !m_qSymbol_requests_done) {
4025be691f3bSpatrick     Lock lock(*this);
4026061da546Spatrick     if (lock) {
4027061da546Spatrick       StreamString packet;
4028061da546Spatrick       packet.PutCString("qSymbol::");
4029061da546Spatrick       StringExtractorGDBRemote response;
4030061da546Spatrick       while (SendPacketAndWaitForResponseNoLock(packet.GetString(), response) ==
4031061da546Spatrick              PacketResult::Success) {
4032061da546Spatrick         if (response.IsOKResponse()) {
4033061da546Spatrick           if (symbol_response_provided || first_qsymbol_query) {
4034061da546Spatrick             m_qSymbol_requests_done = true;
4035061da546Spatrick           }
4036061da546Spatrick 
4037061da546Spatrick           // We are done serving symbols requests
4038061da546Spatrick           return;
4039061da546Spatrick         }
4040061da546Spatrick         first_qsymbol_query = false;
4041061da546Spatrick 
4042061da546Spatrick         if (response.IsUnsupportedResponse()) {
4043061da546Spatrick           // qSymbol is not supported by the current GDB server we are
4044061da546Spatrick           // connected to
4045061da546Spatrick           m_supports_qSymbol = false;
4046061da546Spatrick           return;
4047061da546Spatrick         } else {
4048061da546Spatrick           llvm::StringRef response_str(response.GetStringRef());
4049061da546Spatrick           if (response_str.startswith("qSymbol:")) {
4050061da546Spatrick             response.SetFilePos(strlen("qSymbol:"));
4051061da546Spatrick             std::string symbol_name;
4052061da546Spatrick             if (response.GetHexByteString(symbol_name)) {
4053061da546Spatrick               if (symbol_name.empty())
4054061da546Spatrick                 return;
4055061da546Spatrick 
4056061da546Spatrick               addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
4057061da546Spatrick               lldb_private::SymbolContextList sc_list;
4058061da546Spatrick               process->GetTarget().GetImages().FindSymbolsWithNameAndType(
4059061da546Spatrick                   ConstString(symbol_name), eSymbolTypeAny, sc_list);
4060061da546Spatrick               if (!sc_list.IsEmpty()) {
4061061da546Spatrick                 const size_t num_scs = sc_list.GetSize();
4062061da546Spatrick                 for (size_t sc_idx = 0;
4063061da546Spatrick                      sc_idx < num_scs &&
4064061da546Spatrick                      symbol_load_addr == LLDB_INVALID_ADDRESS;
4065061da546Spatrick                      ++sc_idx) {
4066061da546Spatrick                   SymbolContext sc;
4067061da546Spatrick                   if (sc_list.GetContextAtIndex(sc_idx, sc)) {
4068061da546Spatrick                     if (sc.symbol) {
4069061da546Spatrick                       switch (sc.symbol->GetType()) {
4070061da546Spatrick                       case eSymbolTypeInvalid:
4071061da546Spatrick                       case eSymbolTypeAbsolute:
4072061da546Spatrick                       case eSymbolTypeUndefined:
4073061da546Spatrick                       case eSymbolTypeSourceFile:
4074061da546Spatrick                       case eSymbolTypeHeaderFile:
4075061da546Spatrick                       case eSymbolTypeObjectFile:
4076061da546Spatrick                       case eSymbolTypeCommonBlock:
4077061da546Spatrick                       case eSymbolTypeBlock:
4078061da546Spatrick                       case eSymbolTypeLocal:
4079061da546Spatrick                       case eSymbolTypeParam:
4080061da546Spatrick                       case eSymbolTypeVariable:
4081061da546Spatrick                       case eSymbolTypeVariableType:
4082061da546Spatrick                       case eSymbolTypeLineEntry:
4083061da546Spatrick                       case eSymbolTypeLineHeader:
4084061da546Spatrick                       case eSymbolTypeScopeBegin:
4085061da546Spatrick                       case eSymbolTypeScopeEnd:
4086061da546Spatrick                       case eSymbolTypeAdditional:
4087061da546Spatrick                       case eSymbolTypeCompiler:
4088061da546Spatrick                       case eSymbolTypeInstrumentation:
4089061da546Spatrick                       case eSymbolTypeTrampoline:
4090061da546Spatrick                         break;
4091061da546Spatrick 
4092061da546Spatrick                       case eSymbolTypeCode:
4093061da546Spatrick                       case eSymbolTypeResolver:
4094061da546Spatrick                       case eSymbolTypeData:
4095061da546Spatrick                       case eSymbolTypeRuntime:
4096061da546Spatrick                       case eSymbolTypeException:
4097061da546Spatrick                       case eSymbolTypeObjCClass:
4098061da546Spatrick                       case eSymbolTypeObjCMetaClass:
4099061da546Spatrick                       case eSymbolTypeObjCIVar:
4100061da546Spatrick                       case eSymbolTypeReExported:
4101061da546Spatrick                         symbol_load_addr =
4102061da546Spatrick                             sc.symbol->GetLoadAddress(&process->GetTarget());
4103061da546Spatrick                         break;
4104061da546Spatrick                       }
4105061da546Spatrick                     }
4106061da546Spatrick                   }
4107061da546Spatrick                 }
4108061da546Spatrick               }
4109061da546Spatrick               // This is the normal path where our symbol lookup was successful
4110061da546Spatrick               // and we want to send a packet with the new symbol value and see
4111061da546Spatrick               // if another lookup needs to be done.
4112061da546Spatrick 
4113061da546Spatrick               // Change "packet" to contain the requested symbol value and name
4114061da546Spatrick               packet.Clear();
4115061da546Spatrick               packet.PutCString("qSymbol:");
4116061da546Spatrick               if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
4117061da546Spatrick                 packet.Printf("%" PRIx64, symbol_load_addr);
4118061da546Spatrick                 symbol_response_provided = true;
4119061da546Spatrick               } else {
4120061da546Spatrick                 symbol_response_provided = false;
4121061da546Spatrick               }
4122061da546Spatrick               packet.PutCString(":");
4123061da546Spatrick               packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
4124061da546Spatrick               continue; // go back to the while loop and send "packet" and wait
4125061da546Spatrick                         // for another response
4126061da546Spatrick             }
4127061da546Spatrick           }
4128061da546Spatrick         }
4129061da546Spatrick       }
4130061da546Spatrick       // If we make it here, the symbol request packet response wasn't valid or
4131061da546Spatrick       // our symbol lookup failed so we must abort
4132061da546Spatrick       return;
4133061da546Spatrick 
4134*f6aab3d8Srobert     } else if (Log *log = GetLog(GDBRLog::Process | GDBRLog::Packets)) {
4135061da546Spatrick       LLDB_LOGF(log,
4136061da546Spatrick                 "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.",
4137061da546Spatrick                 __FUNCTION__);
4138061da546Spatrick     }
4139061da546Spatrick   }
4140061da546Spatrick }
4141061da546Spatrick 
4142061da546Spatrick StructuredData::Array *
GetSupportedStructuredDataPlugins()4143061da546Spatrick GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
4144061da546Spatrick   if (!m_supported_async_json_packets_is_valid) {
4145061da546Spatrick     // Query the server for the array of supported asynchronous JSON packets.
4146061da546Spatrick     m_supported_async_json_packets_is_valid = true;
4147061da546Spatrick 
4148*f6aab3d8Srobert     Log *log = GetLog(GDBRLog::Process);
4149061da546Spatrick 
4150061da546Spatrick     // Poll it now.
4151061da546Spatrick     StringExtractorGDBRemote response;
4152be691f3bSpatrick     if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response) ==
4153be691f3bSpatrick         PacketResult::Success) {
4154061da546Spatrick       m_supported_async_json_packets_sp =
4155dda28197Spatrick           StructuredData::ParseJSON(std::string(response.GetStringRef()));
4156061da546Spatrick       if (m_supported_async_json_packets_sp &&
4157061da546Spatrick           !m_supported_async_json_packets_sp->GetAsArray()) {
4158061da546Spatrick         // We were returned something other than a JSON array.  This is
4159061da546Spatrick         // invalid.  Clear it out.
4160061da546Spatrick         LLDB_LOGF(log,
4161061da546Spatrick                   "GDBRemoteCommunicationClient::%s(): "
4162061da546Spatrick                   "QSupportedAsyncJSONPackets returned invalid "
4163061da546Spatrick                   "result: %s",
4164061da546Spatrick                   __FUNCTION__, response.GetStringRef().data());
4165061da546Spatrick         m_supported_async_json_packets_sp.reset();
4166061da546Spatrick       }
4167061da546Spatrick     } else {
4168061da546Spatrick       LLDB_LOGF(log,
4169061da546Spatrick                 "GDBRemoteCommunicationClient::%s(): "
4170061da546Spatrick                 "QSupportedAsyncJSONPackets unsupported",
4171061da546Spatrick                 __FUNCTION__);
4172061da546Spatrick     }
4173061da546Spatrick 
4174061da546Spatrick     if (log && m_supported_async_json_packets_sp) {
4175061da546Spatrick       StreamString stream;
4176061da546Spatrick       m_supported_async_json_packets_sp->Dump(stream);
4177061da546Spatrick       LLDB_LOGF(log,
4178061da546Spatrick                 "GDBRemoteCommunicationClient::%s(): supported async "
4179061da546Spatrick                 "JSON packets: %s",
4180061da546Spatrick                 __FUNCTION__, stream.GetData());
4181061da546Spatrick     }
4182061da546Spatrick   }
4183061da546Spatrick 
4184061da546Spatrick   return m_supported_async_json_packets_sp
4185061da546Spatrick              ? m_supported_async_json_packets_sp->GetAsArray()
4186061da546Spatrick              : nullptr;
4187061da546Spatrick }
4188061da546Spatrick 
SendSignalsToIgnore(llvm::ArrayRef<int32_t> signals)4189061da546Spatrick Status GDBRemoteCommunicationClient::SendSignalsToIgnore(
4190061da546Spatrick     llvm::ArrayRef<int32_t> signals) {
4191061da546Spatrick   // Format packet:
4192061da546Spatrick   // QPassSignals:<hex_sig1>;<hex_sig2>...;<hex_sigN>
4193061da546Spatrick   auto range = llvm::make_range(signals.begin(), signals.end());
4194061da546Spatrick   std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str();
4195061da546Spatrick 
4196061da546Spatrick   StringExtractorGDBRemote response;
4197be691f3bSpatrick   auto send_status = SendPacketAndWaitForResponse(packet, response);
4198061da546Spatrick 
4199061da546Spatrick   if (send_status != GDBRemoteCommunication::PacketResult::Success)
4200061da546Spatrick     return Status("Sending QPassSignals packet failed");
4201061da546Spatrick 
4202061da546Spatrick   if (response.IsOKResponse()) {
4203061da546Spatrick     return Status();
4204061da546Spatrick   } else {
4205061da546Spatrick     return Status("Unknown error happened during sending QPassSignals packet.");
4206061da546Spatrick   }
4207061da546Spatrick }
4208061da546Spatrick 
ConfigureRemoteStructuredData(ConstString type_name,const StructuredData::ObjectSP & config_sp)4209061da546Spatrick Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
4210061da546Spatrick     ConstString type_name, const StructuredData::ObjectSP &config_sp) {
4211061da546Spatrick   Status error;
4212061da546Spatrick 
4213061da546Spatrick   if (type_name.GetLength() == 0) {
4214061da546Spatrick     error.SetErrorString("invalid type_name argument");
4215061da546Spatrick     return error;
4216061da546Spatrick   }
4217061da546Spatrick 
4218061da546Spatrick   // Build command: Configure{type_name}: serialized config data.
4219061da546Spatrick   StreamGDBRemote stream;
4220061da546Spatrick   stream.PutCString("QConfigure");
4221dda28197Spatrick   stream.PutCString(type_name.GetStringRef());
4222061da546Spatrick   stream.PutChar(':');
4223061da546Spatrick   if (config_sp) {
4224061da546Spatrick     // Gather the plain-text version of the configuration data.
4225061da546Spatrick     StreamString unescaped_stream;
4226061da546Spatrick     config_sp->Dump(unescaped_stream);
4227061da546Spatrick     unescaped_stream.Flush();
4228061da546Spatrick 
4229061da546Spatrick     // Add it to the stream in escaped fashion.
4230061da546Spatrick     stream.PutEscapedBytes(unescaped_stream.GetString().data(),
4231061da546Spatrick                            unescaped_stream.GetSize());
4232061da546Spatrick   }
4233061da546Spatrick   stream.Flush();
4234061da546Spatrick 
4235061da546Spatrick   // Send the packet.
4236061da546Spatrick   StringExtractorGDBRemote response;
4237be691f3bSpatrick   auto result = SendPacketAndWaitForResponse(stream.GetString(), response);
4238061da546Spatrick   if (result == PacketResult::Success) {
4239061da546Spatrick     // We failed if the config result comes back other than OK.
4240061da546Spatrick     if (strcmp(response.GetStringRef().data(), "OK") == 0) {
4241061da546Spatrick       // Okay!
4242061da546Spatrick       error.Clear();
4243061da546Spatrick     } else {
4244061da546Spatrick       error.SetErrorStringWithFormat("configuring StructuredData feature "
4245061da546Spatrick                                      "%s failed with error %s",
4246061da546Spatrick                                      type_name.AsCString(),
4247061da546Spatrick                                      response.GetStringRef().data());
4248061da546Spatrick     }
4249061da546Spatrick   } else {
4250061da546Spatrick     // Can we get more data here on the failure?
4251061da546Spatrick     error.SetErrorStringWithFormat("configuring StructuredData feature %s "
4252061da546Spatrick                                    "failed when sending packet: "
4253061da546Spatrick                                    "PacketResult=%d",
4254061da546Spatrick                                    type_name.AsCString(), (int)result);
4255061da546Spatrick   }
4256061da546Spatrick   return error;
4257061da546Spatrick }
4258061da546Spatrick 
OnRunPacketSent(bool first)4259061da546Spatrick void GDBRemoteCommunicationClient::OnRunPacketSent(bool first) {
4260061da546Spatrick   GDBRemoteClientBase::OnRunPacketSent(first);
4261061da546Spatrick   m_curr_tid = LLDB_INVALID_THREAD_ID;
4262061da546Spatrick }
4263*f6aab3d8Srobert 
UsesNativeSignals()4264*f6aab3d8Srobert bool GDBRemoteCommunicationClient::UsesNativeSignals() {
4265*f6aab3d8Srobert   if (m_uses_native_signals == eLazyBoolCalculate)
4266*f6aab3d8Srobert     GetRemoteQSupported();
4267*f6aab3d8Srobert   if (m_uses_native_signals == eLazyBoolYes)
4268*f6aab3d8Srobert     return true;
4269*f6aab3d8Srobert 
4270*f6aab3d8Srobert   // If the remote didn't indicate native-signal support explicitly,
4271*f6aab3d8Srobert   // check whether it is an old version of lldb-server.
4272*f6aab3d8Srobert   return GetThreadSuffixSupported();
4273*f6aab3d8Srobert }
4274*f6aab3d8Srobert 
KillProcess(lldb::pid_t pid)4275*f6aab3d8Srobert llvm::Expected<int> GDBRemoteCommunicationClient::KillProcess(lldb::pid_t pid) {
4276*f6aab3d8Srobert   StringExtractorGDBRemote response;
4277*f6aab3d8Srobert   GDBRemoteCommunication::ScopedTimeout(*this, seconds(3));
4278*f6aab3d8Srobert 
4279*f6aab3d8Srobert   if (SendPacketAndWaitForResponse("k", response, GetPacketTimeout()) !=
4280*f6aab3d8Srobert       PacketResult::Success)
4281*f6aab3d8Srobert     return llvm::createStringError(llvm::inconvertibleErrorCode(),
4282*f6aab3d8Srobert                                    "failed to send k packet");
4283*f6aab3d8Srobert 
4284*f6aab3d8Srobert   char packet_cmd = response.GetChar(0);
4285*f6aab3d8Srobert   if (packet_cmd == 'W' || packet_cmd == 'X')
4286*f6aab3d8Srobert     return response.GetHexU8();
4287*f6aab3d8Srobert 
4288*f6aab3d8Srobert   return llvm::createStringError(llvm::inconvertibleErrorCode(),
4289*f6aab3d8Srobert                                  "unexpected response to k packet: %s",
4290*f6aab3d8Srobert                                  response.GetStringRef().str().c_str());
4291*f6aab3d8Srobert }
4292