xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (revision be691f3bb6417f04a68938fadbcaee2d5795e764)
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 
11*be691f3bSpatrick #include <cmath>
12061da546Spatrick #include <sys/stat.h>
13061da546Spatrick 
14061da546Spatrick #include <numeric>
15061da546Spatrick #include <sstream>
16061da546Spatrick 
17061da546Spatrick #include "lldb/Core/ModuleSpec.h"
18061da546Spatrick #include "lldb/Host/HostInfo.h"
19*be691f3bSpatrick #include "lldb/Host/StringConvert.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"
28061da546Spatrick #include "lldb/Utility/Log.h"
29061da546Spatrick #include "lldb/Utility/State.h"
30061da546Spatrick #include "lldb/Utility/StreamString.h"
31061da546Spatrick 
32061da546Spatrick #include "ProcessGDBRemote.h"
33061da546Spatrick #include "ProcessGDBRemoteLog.h"
34061da546Spatrick #include "lldb/Host/Config.h"
35061da546Spatrick #include "lldb/Utility/StringExtractorGDBRemote.h"
36061da546Spatrick 
37061da546Spatrick #include "llvm/ADT/StringSwitch.h"
38061da546Spatrick #include "llvm/Support/JSON.h"
39061da546Spatrick 
40061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
41061da546Spatrick #include <compression.h>
42061da546Spatrick #endif
43061da546Spatrick 
44061da546Spatrick using namespace lldb;
45061da546Spatrick using namespace lldb_private::process_gdb_remote;
46061da546Spatrick using namespace lldb_private;
47061da546Spatrick using namespace std::chrono;
48061da546Spatrick 
49dda28197Spatrick llvm::raw_ostream &process_gdb_remote::operator<<(llvm::raw_ostream &os,
50dda28197Spatrick                                                   const QOffsets &offsets) {
51dda28197Spatrick   return os << llvm::formatv(
52dda28197Spatrick              "QOffsets({0}, [{1:@[x]}])", offsets.segments,
53dda28197Spatrick              llvm::make_range(offsets.offsets.begin(), offsets.offsets.end()));
54dda28197Spatrick }
55dda28197Spatrick 
56061da546Spatrick // GDBRemoteCommunicationClient constructor
57061da546Spatrick GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
58061da546Spatrick     : GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"),
59*be691f3bSpatrick 
60061da546Spatrick       m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
61061da546Spatrick       m_supports_qUserName(true), m_supports_qGroupName(true),
62061da546Spatrick       m_supports_qThreadStopInfo(true), m_supports_z0(true),
63061da546Spatrick       m_supports_z1(true), m_supports_z2(true), m_supports_z3(true),
64061da546Spatrick       m_supports_z4(true), m_supports_QEnvironment(true),
65061da546Spatrick       m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true),
66061da546Spatrick       m_qSymbol_requests_done(false), m_supports_qModuleInfo(true),
67061da546Spatrick       m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true),
68*be691f3bSpatrick 
69*be691f3bSpatrick       m_host_arch(), m_process_arch(), m_os_build(), m_os_kernel(),
70*be691f3bSpatrick       m_hostname(), m_gdb_server_name(), m_default_packet_timeout(0),
71*be691f3bSpatrick       m_qSupported_response(), m_supported_async_json_packets_sp(),
72*be691f3bSpatrick       m_qXfer_memory_map() {}
73061da546Spatrick 
74061da546Spatrick // Destructor
75061da546Spatrick GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
76061da546Spatrick   if (IsConnected())
77061da546Spatrick     Disconnect();
78061da546Spatrick }
79061da546Spatrick 
80061da546Spatrick bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
81061da546Spatrick   ResetDiscoverableSettings(false);
82061da546Spatrick 
83061da546Spatrick   // Start the read thread after we send the handshake ack since if we fail to
84061da546Spatrick   // send the handshake ack, there is no reason to continue...
85061da546Spatrick   if (SendAck()) {
86061da546Spatrick     // Wait for any responses that might have been queued up in the remote
87061da546Spatrick     // GDB server and flush them all
88061da546Spatrick     StringExtractorGDBRemote response;
89061da546Spatrick     PacketResult packet_result = PacketResult::Success;
90061da546Spatrick     while (packet_result == PacketResult::Success)
91061da546Spatrick       packet_result = ReadPacket(response, milliseconds(10), false);
92061da546Spatrick 
93061da546Spatrick     // The return value from QueryNoAckModeSupported() is true if the packet
94061da546Spatrick     // was sent and _any_ response (including UNIMPLEMENTED) was received), or
95061da546Spatrick     // false if no response was received. This quickly tells us if we have a
96061da546Spatrick     // live connection to a remote GDB server...
97061da546Spatrick     if (QueryNoAckModeSupported()) {
98061da546Spatrick       return true;
99061da546Spatrick     } else {
100061da546Spatrick       if (error_ptr)
101061da546Spatrick         error_ptr->SetErrorString("failed to get reply to handshake packet");
102061da546Spatrick     }
103061da546Spatrick   } else {
104061da546Spatrick     if (error_ptr)
105061da546Spatrick       error_ptr->SetErrorString("failed to send the handshake ack");
106061da546Spatrick   }
107061da546Spatrick   return false;
108061da546Spatrick }
109061da546Spatrick 
110061da546Spatrick bool GDBRemoteCommunicationClient::GetEchoSupported() {
111061da546Spatrick   if (m_supports_qEcho == eLazyBoolCalculate) {
112061da546Spatrick     GetRemoteQSupported();
113061da546Spatrick   }
114061da546Spatrick   return m_supports_qEcho == eLazyBoolYes;
115061da546Spatrick }
116061da546Spatrick 
117061da546Spatrick bool GDBRemoteCommunicationClient::GetQPassSignalsSupported() {
118061da546Spatrick   if (m_supports_QPassSignals == eLazyBoolCalculate) {
119061da546Spatrick     GetRemoteQSupported();
120061da546Spatrick   }
121061da546Spatrick   return m_supports_QPassSignals == eLazyBoolYes;
122061da546Spatrick }
123061da546Spatrick 
124061da546Spatrick bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() {
125061da546Spatrick   if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) {
126061da546Spatrick     GetRemoteQSupported();
127061da546Spatrick   }
128061da546Spatrick   return m_supports_augmented_libraries_svr4_read == eLazyBoolYes;
129061da546Spatrick }
130061da546Spatrick 
131061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported() {
132061da546Spatrick   if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) {
133061da546Spatrick     GetRemoteQSupported();
134061da546Spatrick   }
135061da546Spatrick   return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes;
136061da546Spatrick }
137061da546Spatrick 
138061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported() {
139061da546Spatrick   if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) {
140061da546Spatrick     GetRemoteQSupported();
141061da546Spatrick   }
142061da546Spatrick   return m_supports_qXfer_libraries_read == eLazyBoolYes;
143061da546Spatrick }
144061da546Spatrick 
145061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferAuxvReadSupported() {
146061da546Spatrick   if (m_supports_qXfer_auxv_read == eLazyBoolCalculate) {
147061da546Spatrick     GetRemoteQSupported();
148061da546Spatrick   }
149061da546Spatrick   return m_supports_qXfer_auxv_read == eLazyBoolYes;
150061da546Spatrick }
151061da546Spatrick 
152061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() {
153061da546Spatrick   if (m_supports_qXfer_features_read == eLazyBoolCalculate) {
154061da546Spatrick     GetRemoteQSupported();
155061da546Spatrick   }
156061da546Spatrick   return m_supports_qXfer_features_read == eLazyBoolYes;
157061da546Spatrick }
158061da546Spatrick 
159061da546Spatrick bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
160061da546Spatrick   if (m_supports_qXfer_memory_map_read == eLazyBoolCalculate) {
161061da546Spatrick     GetRemoteQSupported();
162061da546Spatrick   }
163061da546Spatrick   return m_supports_qXfer_memory_map_read == eLazyBoolYes;
164061da546Spatrick }
165061da546Spatrick 
166061da546Spatrick uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
167061da546Spatrick   if (m_max_packet_size == 0) {
168061da546Spatrick     GetRemoteQSupported();
169061da546Spatrick   }
170061da546Spatrick   return m_max_packet_size;
171061da546Spatrick }
172061da546Spatrick 
173061da546Spatrick bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
174061da546Spatrick   if (m_supports_not_sending_acks == eLazyBoolCalculate) {
175061da546Spatrick     m_send_acks = true;
176061da546Spatrick     m_supports_not_sending_acks = eLazyBoolNo;
177061da546Spatrick 
178061da546Spatrick     // This is the first real packet that we'll send in a debug session and it
179061da546Spatrick     // may take a little longer than normal to receive a reply.  Wait at least
180061da546Spatrick     // 6 seconds for a reply to this packet.
181061da546Spatrick 
182061da546Spatrick     ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
183061da546Spatrick 
184061da546Spatrick     StringExtractorGDBRemote response;
185*be691f3bSpatrick     if (SendPacketAndWaitForResponse("QStartNoAckMode", response) ==
186061da546Spatrick         PacketResult::Success) {
187061da546Spatrick       if (response.IsOKResponse()) {
188061da546Spatrick         m_send_acks = false;
189061da546Spatrick         m_supports_not_sending_acks = eLazyBoolYes;
190061da546Spatrick       }
191061da546Spatrick       return true;
192061da546Spatrick     }
193061da546Spatrick   }
194061da546Spatrick   return false;
195061da546Spatrick }
196061da546Spatrick 
197061da546Spatrick void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() {
198061da546Spatrick   if (m_supports_threads_in_stop_reply == eLazyBoolCalculate) {
199061da546Spatrick     m_supports_threads_in_stop_reply = eLazyBoolNo;
200061da546Spatrick 
201061da546Spatrick     StringExtractorGDBRemote response;
202*be691f3bSpatrick     if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response) ==
203*be691f3bSpatrick         PacketResult::Success) {
204061da546Spatrick       if (response.IsOKResponse())
205061da546Spatrick         m_supports_threads_in_stop_reply = eLazyBoolYes;
206061da546Spatrick     }
207061da546Spatrick   }
208061da546Spatrick }
209061da546Spatrick 
210061da546Spatrick bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() {
211061da546Spatrick   if (m_attach_or_wait_reply == eLazyBoolCalculate) {
212061da546Spatrick     m_attach_or_wait_reply = eLazyBoolNo;
213061da546Spatrick 
214061da546Spatrick     StringExtractorGDBRemote response;
215*be691f3bSpatrick     if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response) ==
216*be691f3bSpatrick         PacketResult::Success) {
217061da546Spatrick       if (response.IsOKResponse())
218061da546Spatrick         m_attach_or_wait_reply = eLazyBoolYes;
219061da546Spatrick     }
220061da546Spatrick   }
221061da546Spatrick   return m_attach_or_wait_reply == eLazyBoolYes;
222061da546Spatrick }
223061da546Spatrick 
224061da546Spatrick bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
225061da546Spatrick   if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) {
226061da546Spatrick     m_prepare_for_reg_writing_reply = eLazyBoolNo;
227061da546Spatrick 
228061da546Spatrick     StringExtractorGDBRemote response;
229*be691f3bSpatrick     if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response) ==
230*be691f3bSpatrick         PacketResult::Success) {
231061da546Spatrick       if (response.IsOKResponse())
232061da546Spatrick         m_prepare_for_reg_writing_reply = eLazyBoolYes;
233061da546Spatrick     }
234061da546Spatrick   }
235061da546Spatrick   return m_prepare_for_reg_writing_reply == eLazyBoolYes;
236061da546Spatrick }
237061da546Spatrick 
238061da546Spatrick void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
239061da546Spatrick   if (!did_exec) {
240061da546Spatrick     // Hard reset everything, this is when we first connect to a GDB server
241061da546Spatrick     m_supports_not_sending_acks = eLazyBoolCalculate;
242061da546Spatrick     m_supports_thread_suffix = eLazyBoolCalculate;
243061da546Spatrick     m_supports_threads_in_stop_reply = eLazyBoolCalculate;
244061da546Spatrick     m_supports_vCont_c = eLazyBoolCalculate;
245061da546Spatrick     m_supports_vCont_C = eLazyBoolCalculate;
246061da546Spatrick     m_supports_vCont_s = eLazyBoolCalculate;
247061da546Spatrick     m_supports_vCont_S = eLazyBoolCalculate;
248061da546Spatrick     m_supports_p = eLazyBoolCalculate;
249061da546Spatrick     m_supports_x = eLazyBoolCalculate;
250061da546Spatrick     m_supports_QSaveRegisterState = eLazyBoolCalculate;
251061da546Spatrick     m_qHostInfo_is_valid = eLazyBoolCalculate;
252061da546Spatrick     m_curr_pid_is_valid = eLazyBoolCalculate;
253061da546Spatrick     m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
254061da546Spatrick     m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
255061da546Spatrick     m_supports_memory_region_info = eLazyBoolCalculate;
256061da546Spatrick     m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
257061da546Spatrick     m_attach_or_wait_reply = eLazyBoolCalculate;
258061da546Spatrick     m_avoid_g_packets = eLazyBoolCalculate;
259*be691f3bSpatrick     m_supports_multiprocess = eLazyBoolCalculate;
260061da546Spatrick     m_supports_qXfer_auxv_read = eLazyBoolCalculate;
261061da546Spatrick     m_supports_qXfer_libraries_read = eLazyBoolCalculate;
262061da546Spatrick     m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
263061da546Spatrick     m_supports_qXfer_features_read = eLazyBoolCalculate;
264061da546Spatrick     m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
265061da546Spatrick     m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
266061da546Spatrick     m_supports_qProcessInfoPID = true;
267061da546Spatrick     m_supports_qfProcessInfo = true;
268061da546Spatrick     m_supports_qUserName = true;
269061da546Spatrick     m_supports_qGroupName = true;
270061da546Spatrick     m_supports_qThreadStopInfo = true;
271061da546Spatrick     m_supports_z0 = true;
272061da546Spatrick     m_supports_z1 = true;
273061da546Spatrick     m_supports_z2 = true;
274061da546Spatrick     m_supports_z3 = true;
275061da546Spatrick     m_supports_z4 = true;
276061da546Spatrick     m_supports_QEnvironment = true;
277061da546Spatrick     m_supports_QEnvironmentHexEncoded = true;
278061da546Spatrick     m_supports_qSymbol = true;
279061da546Spatrick     m_qSymbol_requests_done = false;
280061da546Spatrick     m_supports_qModuleInfo = true;
281061da546Spatrick     m_host_arch.Clear();
282061da546Spatrick     m_os_version = llvm::VersionTuple();
283061da546Spatrick     m_os_build.clear();
284061da546Spatrick     m_os_kernel.clear();
285061da546Spatrick     m_hostname.clear();
286061da546Spatrick     m_gdb_server_name.clear();
287061da546Spatrick     m_gdb_server_version = UINT32_MAX;
288061da546Spatrick     m_default_packet_timeout = seconds(0);
289*be691f3bSpatrick     m_target_vm_page_size = 0;
290061da546Spatrick     m_max_packet_size = 0;
291061da546Spatrick     m_qSupported_response.clear();
292061da546Spatrick     m_supported_async_json_packets_is_valid = false;
293061da546Spatrick     m_supported_async_json_packets_sp.reset();
294061da546Spatrick     m_supports_jModulesInfo = true;
295061da546Spatrick   }
296061da546Spatrick 
297061da546Spatrick   // These flags should be reset when we first connect to a GDB server and when
298061da546Spatrick   // our inferior process execs
299061da546Spatrick   m_qProcessInfo_is_valid = eLazyBoolCalculate;
300061da546Spatrick   m_process_arch.Clear();
301061da546Spatrick }
302061da546Spatrick 
303061da546Spatrick void GDBRemoteCommunicationClient::GetRemoteQSupported() {
304061da546Spatrick   // Clear out any capabilities we expect to see in the qSupported response
305061da546Spatrick   m_supports_qXfer_auxv_read = eLazyBoolNo;
306061da546Spatrick   m_supports_qXfer_libraries_read = eLazyBoolNo;
307061da546Spatrick   m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
308061da546Spatrick   m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
309061da546Spatrick   m_supports_qXfer_features_read = eLazyBoolNo;
310061da546Spatrick   m_supports_qXfer_memory_map_read = eLazyBoolNo;
311*be691f3bSpatrick   m_supports_multiprocess = eLazyBoolNo;
312*be691f3bSpatrick   m_supports_qEcho = eLazyBoolNo;
313*be691f3bSpatrick   m_supports_QPassSignals = eLazyBoolNo;
314*be691f3bSpatrick   m_supports_memory_tagging = eLazyBoolNo;
315*be691f3bSpatrick 
316061da546Spatrick   m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
317061da546Spatrick                                   // not, we assume no limit
318061da546Spatrick 
319061da546Spatrick   // build the qSupported packet
320*be691f3bSpatrick   std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc",
321*be691f3bSpatrick                                        "multiprocess+"};
322061da546Spatrick   StreamString packet;
323061da546Spatrick   packet.PutCString("qSupported");
324061da546Spatrick   for (uint32_t i = 0; i < features.size(); ++i) {
325061da546Spatrick     packet.PutCString(i == 0 ? ":" : ";");
326061da546Spatrick     packet.PutCString(features[i]);
327061da546Spatrick   }
328061da546Spatrick 
329061da546Spatrick   StringExtractorGDBRemote response;
330*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
331061da546Spatrick       PacketResult::Success) {
332061da546Spatrick     // Hang on to the qSupported packet, so that platforms can do custom
333061da546Spatrick     // configuration of the transport before attaching/launching the process.
334*be691f3bSpatrick     m_qSupported_response = response.GetStringRef().str();
335061da546Spatrick 
336*be691f3bSpatrick     llvm::SmallVector<llvm::StringRef, 16> server_features;
337*be691f3bSpatrick     response.GetStringRef().split(server_features, ';');
338*be691f3bSpatrick 
339*be691f3bSpatrick     for (llvm::StringRef x : server_features) {
340*be691f3bSpatrick       if (x == "qXfer:auxv:read+")
341061da546Spatrick         m_supports_qXfer_auxv_read = eLazyBoolYes;
342*be691f3bSpatrick       else if (x == "qXfer:libraries-svr4:read+")
343061da546Spatrick         m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
344*be691f3bSpatrick       else if (x == "augmented-libraries-svr4-read") {
345061da546Spatrick         m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
346061da546Spatrick         m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
347*be691f3bSpatrick       } else if (x == "qXfer:libraries:read+")
348061da546Spatrick         m_supports_qXfer_libraries_read = eLazyBoolYes;
349*be691f3bSpatrick       else if (x == "qXfer:features:read+")
350061da546Spatrick         m_supports_qXfer_features_read = eLazyBoolYes;
351*be691f3bSpatrick       else if (x == "qXfer:memory-map:read+")
352061da546Spatrick         m_supports_qXfer_memory_map_read = eLazyBoolYes;
353*be691f3bSpatrick       else if (x == "qEcho")
354*be691f3bSpatrick         m_supports_qEcho = eLazyBoolYes;
355*be691f3bSpatrick       else if (x == "QPassSignals+")
356*be691f3bSpatrick         m_supports_QPassSignals = eLazyBoolYes;
357*be691f3bSpatrick       else if (x == "multiprocess+")
358*be691f3bSpatrick         m_supports_multiprocess = eLazyBoolYes;
359*be691f3bSpatrick       else if (x == "memory-tagging+")
360*be691f3bSpatrick         m_supports_memory_tagging = eLazyBoolYes;
361061da546Spatrick       // Look for a list of compressions in the features list e.g.
362061da546Spatrick       // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
363061da546Spatrick       // deflate,lzma
364*be691f3bSpatrick       else if (x.consume_front("SupportedCompressions=")) {
365*be691f3bSpatrick         llvm::SmallVector<llvm::StringRef, 4> compressions;
366*be691f3bSpatrick         x.split(compressions, ',');
367*be691f3bSpatrick         if (!compressions.empty())
368*be691f3bSpatrick           MaybeEnableCompression(compressions);
369*be691f3bSpatrick       } else if (x.consume_front("PacketSize=")) {
370*be691f3bSpatrick         StringExtractorGDBRemote packet_response(x);
371061da546Spatrick         m_max_packet_size =
372061da546Spatrick             packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
373061da546Spatrick         if (m_max_packet_size == 0) {
374061da546Spatrick           m_max_packet_size = UINT64_MAX; // Must have been a garbled response
375061da546Spatrick           Log *log(
376061da546Spatrick               ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
377061da546Spatrick           LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response");
378061da546Spatrick         }
379061da546Spatrick       }
380061da546Spatrick     }
381061da546Spatrick   }
382*be691f3bSpatrick }
383061da546Spatrick 
384061da546Spatrick bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() {
385061da546Spatrick   if (m_supports_thread_suffix == eLazyBoolCalculate) {
386061da546Spatrick     StringExtractorGDBRemote response;
387061da546Spatrick     m_supports_thread_suffix = eLazyBoolNo;
388*be691f3bSpatrick     if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response) ==
389*be691f3bSpatrick         PacketResult::Success) {
390061da546Spatrick       if (response.IsOKResponse())
391061da546Spatrick         m_supports_thread_suffix = eLazyBoolYes;
392061da546Spatrick     }
393061da546Spatrick   }
394061da546Spatrick   return m_supports_thread_suffix;
395061da546Spatrick }
396061da546Spatrick bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) {
397061da546Spatrick   if (m_supports_vCont_c == eLazyBoolCalculate) {
398061da546Spatrick     StringExtractorGDBRemote response;
399061da546Spatrick     m_supports_vCont_any = eLazyBoolNo;
400061da546Spatrick     m_supports_vCont_all = eLazyBoolNo;
401061da546Spatrick     m_supports_vCont_c = eLazyBoolNo;
402061da546Spatrick     m_supports_vCont_C = eLazyBoolNo;
403061da546Spatrick     m_supports_vCont_s = eLazyBoolNo;
404061da546Spatrick     m_supports_vCont_S = eLazyBoolNo;
405*be691f3bSpatrick     if (SendPacketAndWaitForResponse("vCont?", response) ==
406061da546Spatrick         PacketResult::Success) {
407061da546Spatrick       const char *response_cstr = response.GetStringRef().data();
408061da546Spatrick       if (::strstr(response_cstr, ";c"))
409061da546Spatrick         m_supports_vCont_c = eLazyBoolYes;
410061da546Spatrick 
411061da546Spatrick       if (::strstr(response_cstr, ";C"))
412061da546Spatrick         m_supports_vCont_C = eLazyBoolYes;
413061da546Spatrick 
414061da546Spatrick       if (::strstr(response_cstr, ";s"))
415061da546Spatrick         m_supports_vCont_s = eLazyBoolYes;
416061da546Spatrick 
417061da546Spatrick       if (::strstr(response_cstr, ";S"))
418061da546Spatrick         m_supports_vCont_S = eLazyBoolYes;
419061da546Spatrick 
420061da546Spatrick       if (m_supports_vCont_c == eLazyBoolYes &&
421061da546Spatrick           m_supports_vCont_C == eLazyBoolYes &&
422061da546Spatrick           m_supports_vCont_s == eLazyBoolYes &&
423061da546Spatrick           m_supports_vCont_S == eLazyBoolYes) {
424061da546Spatrick         m_supports_vCont_all = eLazyBoolYes;
425061da546Spatrick       }
426061da546Spatrick 
427061da546Spatrick       if (m_supports_vCont_c == eLazyBoolYes ||
428061da546Spatrick           m_supports_vCont_C == eLazyBoolYes ||
429061da546Spatrick           m_supports_vCont_s == eLazyBoolYes ||
430061da546Spatrick           m_supports_vCont_S == eLazyBoolYes) {
431061da546Spatrick         m_supports_vCont_any = eLazyBoolYes;
432061da546Spatrick       }
433061da546Spatrick     }
434061da546Spatrick   }
435061da546Spatrick 
436061da546Spatrick   switch (flavor) {
437061da546Spatrick   case 'a':
438061da546Spatrick     return m_supports_vCont_any;
439061da546Spatrick   case 'A':
440061da546Spatrick     return m_supports_vCont_all;
441061da546Spatrick   case 'c':
442061da546Spatrick     return m_supports_vCont_c;
443061da546Spatrick   case 'C':
444061da546Spatrick     return m_supports_vCont_C;
445061da546Spatrick   case 's':
446061da546Spatrick     return m_supports_vCont_s;
447061da546Spatrick   case 'S':
448061da546Spatrick     return m_supports_vCont_S;
449061da546Spatrick   default:
450061da546Spatrick     break;
451061da546Spatrick   }
452061da546Spatrick   return false;
453061da546Spatrick }
454061da546Spatrick 
455061da546Spatrick GDBRemoteCommunication::PacketResult
456061da546Spatrick GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
457*be691f3bSpatrick     lldb::tid_t tid, StreamString &&payload,
458*be691f3bSpatrick     StringExtractorGDBRemote &response) {
459*be691f3bSpatrick   Lock lock(*this);
460061da546Spatrick   if (!lock) {
461061da546Spatrick     if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
462061da546Spatrick             GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
463061da546Spatrick       LLDB_LOGF(log,
464061da546Spatrick                 "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex "
465061da546Spatrick                 "for %s packet.",
466061da546Spatrick                 __FUNCTION__, payload.GetData());
467061da546Spatrick     return PacketResult::ErrorNoSequenceLock;
468061da546Spatrick   }
469061da546Spatrick 
470061da546Spatrick   if (GetThreadSuffixSupported())
471061da546Spatrick     payload.Printf(";thread:%4.4" PRIx64 ";", tid);
472061da546Spatrick   else {
473061da546Spatrick     if (!SetCurrentThread(tid))
474061da546Spatrick       return PacketResult::ErrorSendFailed;
475061da546Spatrick   }
476061da546Spatrick 
477061da546Spatrick   return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
478061da546Spatrick }
479061da546Spatrick 
480061da546Spatrick // Check if the target supports 'p' packet. It sends out a 'p' packet and
481061da546Spatrick // checks the response. A normal packet will tell us that support is available.
482061da546Spatrick //
483061da546Spatrick // Takes a valid thread ID because p needs to apply to a thread.
484061da546Spatrick bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
485061da546Spatrick   if (m_supports_p == eLazyBoolCalculate)
486061da546Spatrick     m_supports_p = GetThreadPacketSupported(tid, "p0");
487061da546Spatrick   return m_supports_p;
488061da546Spatrick }
489061da546Spatrick 
490061da546Spatrick LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported(
491061da546Spatrick     lldb::tid_t tid, llvm::StringRef packetStr) {
492061da546Spatrick   StreamString payload;
493061da546Spatrick   payload.PutCString(packetStr);
494061da546Spatrick   StringExtractorGDBRemote response;
495061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
496*be691f3bSpatrick           tid, std::move(payload), response) == PacketResult::Success &&
497061da546Spatrick       response.IsNormalResponse()) {
498061da546Spatrick     return eLazyBoolYes;
499061da546Spatrick   }
500061da546Spatrick   return eLazyBoolNo;
501061da546Spatrick }
502061da546Spatrick 
503061da546Spatrick StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
504061da546Spatrick   // Get information on all threads at one using the "jThreadsInfo" packet
505061da546Spatrick   StructuredData::ObjectSP object_sp;
506061da546Spatrick 
507061da546Spatrick   if (m_supports_jThreadsInfo) {
508061da546Spatrick     StringExtractorGDBRemote response;
509061da546Spatrick     response.SetResponseValidatorToJSON();
510*be691f3bSpatrick     if (SendPacketAndWaitForResponse("jThreadsInfo", response) ==
511061da546Spatrick         PacketResult::Success) {
512061da546Spatrick       if (response.IsUnsupportedResponse()) {
513061da546Spatrick         m_supports_jThreadsInfo = false;
514061da546Spatrick       } else if (!response.Empty()) {
515dda28197Spatrick         object_sp =
516dda28197Spatrick             StructuredData::ParseJSON(std::string(response.GetStringRef()));
517061da546Spatrick       }
518061da546Spatrick     }
519061da546Spatrick   }
520061da546Spatrick   return object_sp;
521061da546Spatrick }
522061da546Spatrick 
523061da546Spatrick bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
524061da546Spatrick   if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) {
525061da546Spatrick     StringExtractorGDBRemote response;
526061da546Spatrick     m_supports_jThreadExtendedInfo = eLazyBoolNo;
527*be691f3bSpatrick     if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response) ==
528061da546Spatrick         PacketResult::Success) {
529061da546Spatrick       if (response.IsOKResponse()) {
530061da546Spatrick         m_supports_jThreadExtendedInfo = eLazyBoolYes;
531061da546Spatrick       }
532061da546Spatrick     }
533061da546Spatrick   }
534061da546Spatrick   return m_supports_jThreadExtendedInfo;
535061da546Spatrick }
536061da546Spatrick 
537061da546Spatrick void GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
538061da546Spatrick   if (m_supports_error_string_reply == eLazyBoolCalculate) {
539061da546Spatrick     StringExtractorGDBRemote response;
540061da546Spatrick     // We try to enable error strings in remote packets but if we fail, we just
541061da546Spatrick     // work in the older way.
542061da546Spatrick     m_supports_error_string_reply = eLazyBoolNo;
543*be691f3bSpatrick     if (SendPacketAndWaitForResponse("QEnableErrorStrings", response) ==
544061da546Spatrick         PacketResult::Success) {
545061da546Spatrick       if (response.IsOKResponse()) {
546061da546Spatrick         m_supports_error_string_reply = eLazyBoolYes;
547061da546Spatrick       }
548061da546Spatrick     }
549061da546Spatrick   }
550061da546Spatrick }
551061da546Spatrick 
552061da546Spatrick bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() {
553061da546Spatrick   if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) {
554061da546Spatrick     StringExtractorGDBRemote response;
555061da546Spatrick     m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
556061da546Spatrick     if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:",
557*be691f3bSpatrick                                      response) == PacketResult::Success) {
558061da546Spatrick       if (response.IsOKResponse()) {
559061da546Spatrick         m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
560061da546Spatrick       }
561061da546Spatrick     }
562061da546Spatrick   }
563061da546Spatrick   return m_supports_jLoadedDynamicLibrariesInfos;
564061da546Spatrick }
565061da546Spatrick 
566061da546Spatrick bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() {
567061da546Spatrick   if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) {
568061da546Spatrick     StringExtractorGDBRemote response;
569061da546Spatrick     m_supports_jGetSharedCacheInfo = eLazyBoolNo;
570*be691f3bSpatrick     if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response) ==
571061da546Spatrick         PacketResult::Success) {
572061da546Spatrick       if (response.IsOKResponse()) {
573061da546Spatrick         m_supports_jGetSharedCacheInfo = eLazyBoolYes;
574061da546Spatrick       }
575061da546Spatrick     }
576061da546Spatrick   }
577061da546Spatrick   return m_supports_jGetSharedCacheInfo;
578061da546Spatrick }
579061da546Spatrick 
580*be691f3bSpatrick bool GDBRemoteCommunicationClient::GetMemoryTaggingSupported() {
581*be691f3bSpatrick   if (m_supports_memory_tagging == eLazyBoolCalculate) {
582*be691f3bSpatrick     GetRemoteQSupported();
583*be691f3bSpatrick   }
584*be691f3bSpatrick   return m_supports_memory_tagging == eLazyBoolYes;
585*be691f3bSpatrick }
586*be691f3bSpatrick 
587*be691f3bSpatrick DataBufferSP GDBRemoteCommunicationClient::ReadMemoryTags(lldb::addr_t addr,
588*be691f3bSpatrick                                                           size_t len,
589*be691f3bSpatrick                                                           int32_t type) {
590*be691f3bSpatrick   StreamString packet;
591*be691f3bSpatrick   packet.Printf("qMemTags:%" PRIx64 ",%zx:%" PRIx32, addr, len, type);
592*be691f3bSpatrick   StringExtractorGDBRemote response;
593*be691f3bSpatrick 
594*be691f3bSpatrick   Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_MEMORY);
595*be691f3bSpatrick 
596*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
597*be691f3bSpatrick           PacketResult::Success ||
598*be691f3bSpatrick       !response.IsNormalResponse()) {
599*be691f3bSpatrick     LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s: qMemTags packet failed",
600*be691f3bSpatrick               __FUNCTION__);
601*be691f3bSpatrick     return nullptr;
602*be691f3bSpatrick   }
603*be691f3bSpatrick 
604*be691f3bSpatrick   // We are expecting
605*be691f3bSpatrick   // m<hex encoded bytes>
606*be691f3bSpatrick 
607*be691f3bSpatrick   if (response.GetChar() != 'm') {
608*be691f3bSpatrick     LLDB_LOGF(log,
609*be691f3bSpatrick               "GDBRemoteCommunicationClient::%s: qMemTags response did not "
610*be691f3bSpatrick               "begin with \"m\"",
611*be691f3bSpatrick               __FUNCTION__);
612*be691f3bSpatrick     return nullptr;
613*be691f3bSpatrick   }
614*be691f3bSpatrick 
615*be691f3bSpatrick   size_t expected_bytes = response.GetBytesLeft() / 2;
616*be691f3bSpatrick   DataBufferSP buffer_sp(new DataBufferHeap(expected_bytes, 0));
617*be691f3bSpatrick   size_t got_bytes = response.GetHexBytesAvail(buffer_sp->GetData());
618*be691f3bSpatrick   // Check both because in some situations chars are consumed even
619*be691f3bSpatrick   // if the decoding fails.
620*be691f3bSpatrick   if (response.GetBytesLeft() || (expected_bytes != got_bytes)) {
621*be691f3bSpatrick     LLDB_LOGF(
622*be691f3bSpatrick         log,
623*be691f3bSpatrick         "GDBRemoteCommunicationClient::%s: Invalid data in qMemTags response",
624*be691f3bSpatrick         __FUNCTION__);
625*be691f3bSpatrick     return nullptr;
626*be691f3bSpatrick   }
627*be691f3bSpatrick 
628*be691f3bSpatrick   return buffer_sp;
629*be691f3bSpatrick }
630*be691f3bSpatrick 
631*be691f3bSpatrick Status GDBRemoteCommunicationClient::WriteMemoryTags(
632*be691f3bSpatrick     lldb::addr_t addr, size_t len, int32_t type,
633*be691f3bSpatrick     const std::vector<uint8_t> &tags) {
634*be691f3bSpatrick   // Format QMemTags:address,length:type:tags
635*be691f3bSpatrick   StreamString packet;
636*be691f3bSpatrick   packet.Printf("QMemTags:%" PRIx64 ",%zx:%" PRIx32 ":", addr, len, type);
637*be691f3bSpatrick   packet.PutBytesAsRawHex8(tags.data(), tags.size());
638*be691f3bSpatrick 
639*be691f3bSpatrick   Status status;
640*be691f3bSpatrick   StringExtractorGDBRemote response;
641*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
642*be691f3bSpatrick           PacketResult::Success ||
643*be691f3bSpatrick       !response.IsOKResponse()) {
644*be691f3bSpatrick     status.SetErrorString("QMemTags packet failed");
645*be691f3bSpatrick   }
646*be691f3bSpatrick   return status;
647*be691f3bSpatrick }
648*be691f3bSpatrick 
649061da546Spatrick bool GDBRemoteCommunicationClient::GetxPacketSupported() {
650061da546Spatrick   if (m_supports_x == eLazyBoolCalculate) {
651061da546Spatrick     StringExtractorGDBRemote response;
652061da546Spatrick     m_supports_x = eLazyBoolNo;
653061da546Spatrick     char packet[256];
654061da546Spatrick     snprintf(packet, sizeof(packet), "x0,0");
655*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
656061da546Spatrick         PacketResult::Success) {
657061da546Spatrick       if (response.IsOKResponse())
658061da546Spatrick         m_supports_x = eLazyBoolYes;
659061da546Spatrick     }
660061da546Spatrick   }
661061da546Spatrick   return m_supports_x;
662061da546Spatrick }
663061da546Spatrick 
664061da546Spatrick GDBRemoteCommunicationClient::PacketResult
665061da546Spatrick GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses(
666061da546Spatrick     const char *payload_prefix, std::string &response_string) {
667*be691f3bSpatrick   Lock lock(*this);
668061da546Spatrick   if (!lock) {
669061da546Spatrick     Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
670061da546Spatrick                                                            GDBR_LOG_PACKETS));
671061da546Spatrick     LLDB_LOGF(log,
672061da546Spatrick               "error: failed to get packet sequence mutex, not sending "
673061da546Spatrick               "packets with prefix '%s'",
674061da546Spatrick               payload_prefix);
675061da546Spatrick     return PacketResult::ErrorNoSequenceLock;
676061da546Spatrick   }
677061da546Spatrick 
678061da546Spatrick   response_string = "";
679061da546Spatrick   std::string payload_prefix_str(payload_prefix);
680061da546Spatrick   unsigned int response_size = 0x1000;
681061da546Spatrick   if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet
682061da546Spatrick     response_size = GetRemoteMaxPacketSize();
683061da546Spatrick   }
684061da546Spatrick 
685061da546Spatrick   for (unsigned int offset = 0; true; offset += response_size) {
686061da546Spatrick     StringExtractorGDBRemote this_response;
687061da546Spatrick     // Construct payload
688061da546Spatrick     char sizeDescriptor[128];
689061da546Spatrick     snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset,
690061da546Spatrick              response_size);
691061da546Spatrick     PacketResult result = SendPacketAndWaitForResponseNoLock(
692061da546Spatrick         payload_prefix_str + sizeDescriptor, this_response);
693061da546Spatrick     if (result != PacketResult::Success)
694061da546Spatrick       return result;
695061da546Spatrick 
696dda28197Spatrick     const std::string &this_string = std::string(this_response.GetStringRef());
697061da546Spatrick 
698061da546Spatrick     // Check for m or l as first character; l seems to mean this is the last
699061da546Spatrick     // chunk
700061da546Spatrick     char first_char = *this_string.c_str();
701061da546Spatrick     if (first_char != 'm' && first_char != 'l') {
702061da546Spatrick       return PacketResult::ErrorReplyInvalid;
703061da546Spatrick     }
704061da546Spatrick     // Concatenate the result so far (skipping 'm' or 'l')
705061da546Spatrick     response_string.append(this_string, 1, std::string::npos);
706061da546Spatrick     if (first_char == 'l')
707061da546Spatrick       // We're done
708061da546Spatrick       return PacketResult::Success;
709061da546Spatrick   }
710061da546Spatrick }
711061da546Spatrick 
712061da546Spatrick lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
713061da546Spatrick   if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes)
714061da546Spatrick     return m_curr_pid;
715061da546Spatrick 
716061da546Spatrick   // First try to retrieve the pid via the qProcessInfo request.
717061da546Spatrick   GetCurrentProcessInfo(allow_lazy);
718061da546Spatrick   if (m_curr_pid_is_valid == eLazyBoolYes) {
719061da546Spatrick     // We really got it.
720061da546Spatrick     return m_curr_pid;
721061da546Spatrick   } else {
722061da546Spatrick     // If we don't get a response for qProcessInfo, check if $qC gives us a
723061da546Spatrick     // result. $qC only returns a real process id on older debugserver and
724061da546Spatrick     // lldb-platform stubs. The gdb remote protocol documents $qC as returning
725061da546Spatrick     // the thread id, which newer debugserver and lldb-gdbserver stubs return
726061da546Spatrick     // correctly.
727061da546Spatrick     StringExtractorGDBRemote response;
728*be691f3bSpatrick     if (SendPacketAndWaitForResponse("qC", response) == PacketResult::Success) {
729061da546Spatrick       if (response.GetChar() == 'Q') {
730061da546Spatrick         if (response.GetChar() == 'C') {
731*be691f3bSpatrick           m_curr_pid_run = m_curr_pid =
732*be691f3bSpatrick               response.GetHexMaxU64(false, LLDB_INVALID_PROCESS_ID);
733061da546Spatrick           if (m_curr_pid != LLDB_INVALID_PROCESS_ID) {
734061da546Spatrick             m_curr_pid_is_valid = eLazyBoolYes;
735061da546Spatrick             return m_curr_pid;
736061da546Spatrick           }
737061da546Spatrick         }
738061da546Spatrick       }
739061da546Spatrick     }
740061da546Spatrick 
741061da546Spatrick     // If we don't get a response for $qC, check if $qfThreadID gives us a
742061da546Spatrick     // result.
743061da546Spatrick     if (m_curr_pid == LLDB_INVALID_PROCESS_ID) {
744061da546Spatrick       bool sequence_mutex_unavailable;
745*be691f3bSpatrick       auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
746*be691f3bSpatrick       if (!ids.empty() && !sequence_mutex_unavailable) {
747*be691f3bSpatrick         // If server returned an explicit PID, use that.
748*be691f3bSpatrick         m_curr_pid_run = m_curr_pid = ids.front().first;
749*be691f3bSpatrick         // Otherwise, use the TID of the first thread (Linux hack).
750*be691f3bSpatrick         if (m_curr_pid == LLDB_INVALID_PROCESS_ID)
751*be691f3bSpatrick           m_curr_pid_run = m_curr_pid = ids.front().second;
752061da546Spatrick         m_curr_pid_is_valid = eLazyBoolYes;
753061da546Spatrick         return m_curr_pid;
754061da546Spatrick       }
755061da546Spatrick     }
756061da546Spatrick   }
757061da546Spatrick 
758061da546Spatrick   return LLDB_INVALID_PROCESS_ID;
759061da546Spatrick }
760061da546Spatrick 
761061da546Spatrick bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) {
762061da546Spatrick   error_str.clear();
763061da546Spatrick   StringExtractorGDBRemote response;
764*be691f3bSpatrick   if (SendPacketAndWaitForResponse("qLaunchSuccess", response) ==
765061da546Spatrick       PacketResult::Success) {
766061da546Spatrick     if (response.IsOKResponse())
767061da546Spatrick       return true;
768061da546Spatrick     if (response.GetChar() == 'E') {
769061da546Spatrick       // A string the describes what failed when launching...
770dda28197Spatrick       error_str = std::string(response.GetStringRef().substr(1));
771061da546Spatrick     } else {
772061da546Spatrick       error_str.assign("unknown error occurred launching process");
773061da546Spatrick     }
774061da546Spatrick   } else {
775061da546Spatrick     error_str.assign("timed out waiting for app to launch");
776061da546Spatrick   }
777061da546Spatrick   return false;
778061da546Spatrick }
779061da546Spatrick 
780061da546Spatrick int GDBRemoteCommunicationClient::SendArgumentsPacket(
781061da546Spatrick     const ProcessLaunchInfo &launch_info) {
782061da546Spatrick   // Since we don't get the send argv0 separate from the executable path, we
783061da546Spatrick   // need to make sure to use the actual executable path found in the
784061da546Spatrick   // launch_info...
785061da546Spatrick   std::vector<const char *> argv;
786061da546Spatrick   FileSpec exe_file = launch_info.GetExecutableFile();
787061da546Spatrick   std::string exe_path;
788061da546Spatrick   const char *arg = nullptr;
789061da546Spatrick   const Args &launch_args = launch_info.GetArguments();
790061da546Spatrick   if (exe_file)
791061da546Spatrick     exe_path = exe_file.GetPath(false);
792061da546Spatrick   else {
793061da546Spatrick     arg = launch_args.GetArgumentAtIndex(0);
794061da546Spatrick     if (arg)
795061da546Spatrick       exe_path = arg;
796061da546Spatrick   }
797061da546Spatrick   if (!exe_path.empty()) {
798061da546Spatrick     argv.push_back(exe_path.c_str());
799061da546Spatrick     for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != nullptr;
800061da546Spatrick          ++i) {
801061da546Spatrick       if (arg)
802061da546Spatrick         argv.push_back(arg);
803061da546Spatrick     }
804061da546Spatrick   }
805061da546Spatrick   if (!argv.empty()) {
806061da546Spatrick     StreamString packet;
807061da546Spatrick     packet.PutChar('A');
808061da546Spatrick     for (size_t i = 0, n = argv.size(); i < n; ++i) {
809061da546Spatrick       arg = argv[i];
810061da546Spatrick       const int arg_len = strlen(arg);
811061da546Spatrick       if (i > 0)
812061da546Spatrick         packet.PutChar(',');
813061da546Spatrick       packet.Printf("%i,%i,", arg_len * 2, (int)i);
814061da546Spatrick       packet.PutBytesAsRawHex8(arg, arg_len);
815061da546Spatrick     }
816061da546Spatrick 
817061da546Spatrick     StringExtractorGDBRemote response;
818*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
819061da546Spatrick         PacketResult::Success) {
820061da546Spatrick       if (response.IsOKResponse())
821061da546Spatrick         return 0;
822061da546Spatrick       uint8_t error = response.GetError();
823061da546Spatrick       if (error)
824061da546Spatrick         return error;
825061da546Spatrick     }
826061da546Spatrick   }
827061da546Spatrick   return -1;
828061da546Spatrick }
829061da546Spatrick 
830061da546Spatrick int GDBRemoteCommunicationClient::SendEnvironment(const Environment &env) {
831061da546Spatrick   for (const auto &KV : env) {
832061da546Spatrick     int r = SendEnvironmentPacket(Environment::compose(KV).c_str());
833061da546Spatrick     if (r != 0)
834061da546Spatrick       return r;
835061da546Spatrick   }
836061da546Spatrick   return 0;
837061da546Spatrick }
838061da546Spatrick 
839061da546Spatrick int GDBRemoteCommunicationClient::SendEnvironmentPacket(
840061da546Spatrick     char const *name_equal_value) {
841061da546Spatrick   if (name_equal_value && name_equal_value[0]) {
842061da546Spatrick     StreamString packet;
843061da546Spatrick     bool send_hex_encoding = false;
844061da546Spatrick     for (const char *p = name_equal_value; *p != '\0' && !send_hex_encoding;
845061da546Spatrick          ++p) {
846dda28197Spatrick       if (llvm::isPrint(*p)) {
847061da546Spatrick         switch (*p) {
848061da546Spatrick         case '$':
849061da546Spatrick         case '#':
850061da546Spatrick         case '*':
851061da546Spatrick         case '}':
852061da546Spatrick           send_hex_encoding = true;
853061da546Spatrick           break;
854061da546Spatrick         default:
855061da546Spatrick           break;
856061da546Spatrick         }
857061da546Spatrick       } else {
858061da546Spatrick         // We have non printable characters, lets hex encode this...
859061da546Spatrick         send_hex_encoding = true;
860061da546Spatrick       }
861061da546Spatrick     }
862061da546Spatrick 
863061da546Spatrick     StringExtractorGDBRemote response;
864061da546Spatrick     if (send_hex_encoding) {
865061da546Spatrick       if (m_supports_QEnvironmentHexEncoded) {
866061da546Spatrick         packet.PutCString("QEnvironmentHexEncoded:");
867061da546Spatrick         packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value));
868*be691f3bSpatrick         if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
869061da546Spatrick             PacketResult::Success) {
870061da546Spatrick           if (response.IsOKResponse())
871061da546Spatrick             return 0;
872061da546Spatrick           uint8_t error = response.GetError();
873061da546Spatrick           if (error)
874061da546Spatrick             return error;
875061da546Spatrick           if (response.IsUnsupportedResponse())
876061da546Spatrick             m_supports_QEnvironmentHexEncoded = false;
877061da546Spatrick         }
878061da546Spatrick       }
879061da546Spatrick 
880061da546Spatrick     } else if (m_supports_QEnvironment) {
881061da546Spatrick       packet.Printf("QEnvironment:%s", name_equal_value);
882*be691f3bSpatrick       if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
883061da546Spatrick           PacketResult::Success) {
884061da546Spatrick         if (response.IsOKResponse())
885061da546Spatrick           return 0;
886061da546Spatrick         uint8_t error = response.GetError();
887061da546Spatrick         if (error)
888061da546Spatrick           return error;
889061da546Spatrick         if (response.IsUnsupportedResponse())
890061da546Spatrick           m_supports_QEnvironment = false;
891061da546Spatrick       }
892061da546Spatrick     }
893061da546Spatrick   }
894061da546Spatrick   return -1;
895061da546Spatrick }
896061da546Spatrick 
897061da546Spatrick int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) {
898061da546Spatrick   if (arch && arch[0]) {
899061da546Spatrick     StreamString packet;
900061da546Spatrick     packet.Printf("QLaunchArch:%s", arch);
901061da546Spatrick     StringExtractorGDBRemote response;
902*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
903061da546Spatrick         PacketResult::Success) {
904061da546Spatrick       if (response.IsOKResponse())
905061da546Spatrick         return 0;
906061da546Spatrick       uint8_t error = response.GetError();
907061da546Spatrick       if (error)
908061da546Spatrick         return error;
909061da546Spatrick     }
910061da546Spatrick   }
911061da546Spatrick   return -1;
912061da546Spatrick }
913061da546Spatrick 
914061da546Spatrick int GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
915061da546Spatrick     char const *data, bool *was_supported) {
916061da546Spatrick   if (data && *data != '\0') {
917061da546Spatrick     StreamString packet;
918061da546Spatrick     packet.Printf("QSetProcessEvent:%s", data);
919061da546Spatrick     StringExtractorGDBRemote response;
920*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
921061da546Spatrick         PacketResult::Success) {
922061da546Spatrick       if (response.IsOKResponse()) {
923061da546Spatrick         if (was_supported)
924061da546Spatrick           *was_supported = true;
925061da546Spatrick         return 0;
926061da546Spatrick       } else if (response.IsUnsupportedResponse()) {
927061da546Spatrick         if (was_supported)
928061da546Spatrick           *was_supported = false;
929061da546Spatrick         return -1;
930061da546Spatrick       } else {
931061da546Spatrick         uint8_t error = response.GetError();
932061da546Spatrick         if (was_supported)
933061da546Spatrick           *was_supported = true;
934061da546Spatrick         if (error)
935061da546Spatrick           return error;
936061da546Spatrick       }
937061da546Spatrick     }
938061da546Spatrick   }
939061da546Spatrick   return -1;
940061da546Spatrick }
941061da546Spatrick 
942061da546Spatrick llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() {
943061da546Spatrick   GetHostInfo();
944061da546Spatrick   return m_os_version;
945061da546Spatrick }
946061da546Spatrick 
947061da546Spatrick llvm::VersionTuple GDBRemoteCommunicationClient::GetMacCatalystVersion() {
948061da546Spatrick   GetHostInfo();
949061da546Spatrick   return m_maccatalyst_version;
950061da546Spatrick }
951061da546Spatrick 
952061da546Spatrick bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) {
953061da546Spatrick   if (GetHostInfo()) {
954061da546Spatrick     if (!m_os_build.empty()) {
955061da546Spatrick       s = m_os_build;
956061da546Spatrick       return true;
957061da546Spatrick     }
958061da546Spatrick   }
959061da546Spatrick   s.clear();
960061da546Spatrick   return false;
961061da546Spatrick }
962061da546Spatrick 
963061da546Spatrick bool GDBRemoteCommunicationClient::GetOSKernelDescription(std::string &s) {
964061da546Spatrick   if (GetHostInfo()) {
965061da546Spatrick     if (!m_os_kernel.empty()) {
966061da546Spatrick       s = m_os_kernel;
967061da546Spatrick       return true;
968061da546Spatrick     }
969061da546Spatrick   }
970061da546Spatrick   s.clear();
971061da546Spatrick   return false;
972061da546Spatrick }
973061da546Spatrick 
974061da546Spatrick bool GDBRemoteCommunicationClient::GetHostname(std::string &s) {
975061da546Spatrick   if (GetHostInfo()) {
976061da546Spatrick     if (!m_hostname.empty()) {
977061da546Spatrick       s = m_hostname;
978061da546Spatrick       return true;
979061da546Spatrick     }
980061da546Spatrick   }
981061da546Spatrick   s.clear();
982061da546Spatrick   return false;
983061da546Spatrick }
984061da546Spatrick 
985061da546Spatrick ArchSpec GDBRemoteCommunicationClient::GetSystemArchitecture() {
986061da546Spatrick   if (GetHostInfo())
987061da546Spatrick     return m_host_arch;
988061da546Spatrick   return ArchSpec();
989061da546Spatrick }
990061da546Spatrick 
991061da546Spatrick const lldb_private::ArchSpec &
992061da546Spatrick GDBRemoteCommunicationClient::GetProcessArchitecture() {
993061da546Spatrick   if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
994061da546Spatrick     GetCurrentProcessInfo();
995061da546Spatrick   return m_process_arch;
996061da546Spatrick }
997061da546Spatrick 
998061da546Spatrick bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
999061da546Spatrick   if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
1000061da546Spatrick     m_gdb_server_name.clear();
1001061da546Spatrick     m_gdb_server_version = 0;
1002061da546Spatrick     m_qGDBServerVersion_is_valid = eLazyBoolNo;
1003061da546Spatrick 
1004061da546Spatrick     StringExtractorGDBRemote response;
1005*be691f3bSpatrick     if (SendPacketAndWaitForResponse("qGDBServerVersion", response) ==
1006061da546Spatrick         PacketResult::Success) {
1007061da546Spatrick       if (response.IsNormalResponse()) {
1008061da546Spatrick         llvm::StringRef name, value;
1009061da546Spatrick         bool success = false;
1010061da546Spatrick         while (response.GetNameColonValue(name, value)) {
1011061da546Spatrick           if (name.equals("name")) {
1012061da546Spatrick             success = true;
1013dda28197Spatrick             m_gdb_server_name = std::string(value);
1014061da546Spatrick           } else if (name.equals("version")) {
1015061da546Spatrick             llvm::StringRef major, minor;
1016061da546Spatrick             std::tie(major, minor) = value.split('.');
1017061da546Spatrick             if (!major.getAsInteger(0, m_gdb_server_version))
1018061da546Spatrick               success = true;
1019061da546Spatrick           }
1020061da546Spatrick         }
1021061da546Spatrick         if (success)
1022061da546Spatrick           m_qGDBServerVersion_is_valid = eLazyBoolYes;
1023061da546Spatrick       }
1024061da546Spatrick     }
1025061da546Spatrick   }
1026061da546Spatrick   return m_qGDBServerVersion_is_valid == eLazyBoolYes;
1027061da546Spatrick }
1028061da546Spatrick 
1029061da546Spatrick void GDBRemoteCommunicationClient::MaybeEnableCompression(
1030*be691f3bSpatrick     llvm::ArrayRef<llvm::StringRef> supported_compressions) {
1031061da546Spatrick   CompressionType avail_type = CompressionType::None;
1032*be691f3bSpatrick   llvm::StringRef avail_name;
1033061da546Spatrick 
1034061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
1035061da546Spatrick   if (avail_type == CompressionType::None) {
1036061da546Spatrick     for (auto compression : supported_compressions) {
1037061da546Spatrick       if (compression == "lzfse") {
1038061da546Spatrick         avail_type = CompressionType::LZFSE;
1039061da546Spatrick         avail_name = compression;
1040061da546Spatrick         break;
1041061da546Spatrick       }
1042061da546Spatrick     }
1043061da546Spatrick   }
1044061da546Spatrick #endif
1045061da546Spatrick 
1046061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
1047061da546Spatrick   if (avail_type == CompressionType::None) {
1048061da546Spatrick     for (auto compression : supported_compressions) {
1049061da546Spatrick       if (compression == "zlib-deflate") {
1050061da546Spatrick         avail_type = CompressionType::ZlibDeflate;
1051061da546Spatrick         avail_name = compression;
1052061da546Spatrick         break;
1053061da546Spatrick       }
1054061da546Spatrick     }
1055061da546Spatrick   }
1056061da546Spatrick #endif
1057061da546Spatrick 
1058*be691f3bSpatrick #if LLVM_ENABLE_ZLIB
1059061da546Spatrick   if (avail_type == CompressionType::None) {
1060061da546Spatrick     for (auto compression : supported_compressions) {
1061061da546Spatrick       if (compression == "zlib-deflate") {
1062061da546Spatrick         avail_type = CompressionType::ZlibDeflate;
1063061da546Spatrick         avail_name = compression;
1064061da546Spatrick         break;
1065061da546Spatrick       }
1066061da546Spatrick     }
1067061da546Spatrick   }
1068061da546Spatrick #endif
1069061da546Spatrick 
1070061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
1071061da546Spatrick   if (avail_type == CompressionType::None) {
1072061da546Spatrick     for (auto compression : supported_compressions) {
1073061da546Spatrick       if (compression == "lz4") {
1074061da546Spatrick         avail_type = CompressionType::LZ4;
1075061da546Spatrick         avail_name = compression;
1076061da546Spatrick         break;
1077061da546Spatrick       }
1078061da546Spatrick     }
1079061da546Spatrick   }
1080061da546Spatrick #endif
1081061da546Spatrick 
1082061da546Spatrick #if defined(HAVE_LIBCOMPRESSION)
1083061da546Spatrick   if (avail_type == CompressionType::None) {
1084061da546Spatrick     for (auto compression : supported_compressions) {
1085061da546Spatrick       if (compression == "lzma") {
1086061da546Spatrick         avail_type = CompressionType::LZMA;
1087061da546Spatrick         avail_name = compression;
1088061da546Spatrick         break;
1089061da546Spatrick       }
1090061da546Spatrick     }
1091061da546Spatrick   }
1092061da546Spatrick #endif
1093061da546Spatrick 
1094061da546Spatrick   if (avail_type != CompressionType::None) {
1095061da546Spatrick     StringExtractorGDBRemote response;
1096*be691f3bSpatrick     llvm::Twine packet = "QEnableCompression:type:" + avail_name + ";";
1097*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.str(), response) !=
1098061da546Spatrick         PacketResult::Success)
1099061da546Spatrick       return;
1100061da546Spatrick 
1101061da546Spatrick     if (response.IsOKResponse()) {
1102061da546Spatrick       m_compression_type = avail_type;
1103061da546Spatrick     }
1104061da546Spatrick   }
1105061da546Spatrick }
1106061da546Spatrick 
1107061da546Spatrick const char *GDBRemoteCommunicationClient::GetGDBServerProgramName() {
1108061da546Spatrick   if (GetGDBServerVersion()) {
1109061da546Spatrick     if (!m_gdb_server_name.empty())
1110061da546Spatrick       return m_gdb_server_name.c_str();
1111061da546Spatrick   }
1112061da546Spatrick   return nullptr;
1113061da546Spatrick }
1114061da546Spatrick 
1115061da546Spatrick uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() {
1116061da546Spatrick   if (GetGDBServerVersion())
1117061da546Spatrick     return m_gdb_server_version;
1118061da546Spatrick   return 0;
1119061da546Spatrick }
1120061da546Spatrick 
1121061da546Spatrick bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
1122061da546Spatrick   StringExtractorGDBRemote response;
1123*be691f3bSpatrick   if (SendPacketAndWaitForResponse("qC", response) != PacketResult::Success)
1124061da546Spatrick     return false;
1125061da546Spatrick 
1126061da546Spatrick   if (!response.IsNormalResponse())
1127061da546Spatrick     return false;
1128061da546Spatrick 
1129*be691f3bSpatrick   if (response.GetChar() == 'Q' && response.GetChar() == 'C') {
1130*be691f3bSpatrick     auto pid_tid = response.GetPidTid(0);
1131*be691f3bSpatrick     if (!pid_tid)
1132*be691f3bSpatrick       return false;
1133*be691f3bSpatrick 
1134*be691f3bSpatrick     lldb::pid_t pid = pid_tid->first;
1135*be691f3bSpatrick     // invalid
1136*be691f3bSpatrick     if (pid == StringExtractorGDBRemote::AllProcesses)
1137*be691f3bSpatrick       return false;
1138*be691f3bSpatrick 
1139*be691f3bSpatrick     // if we get pid as well, update m_curr_pid
1140*be691f3bSpatrick     if (pid != 0) {
1141*be691f3bSpatrick       m_curr_pid_run = m_curr_pid = pid;
1142*be691f3bSpatrick       m_curr_pid_is_valid = eLazyBoolYes;
1143*be691f3bSpatrick     }
1144*be691f3bSpatrick     tid = pid_tid->second;
1145*be691f3bSpatrick   }
1146061da546Spatrick 
1147061da546Spatrick   return true;
1148061da546Spatrick }
1149061da546Spatrick 
1150dda28197Spatrick static void ParseOSType(llvm::StringRef value, std::string &os_name,
1151dda28197Spatrick                         std::string &environment) {
1152dda28197Spatrick   if (value.equals("iossimulator") || value.equals("tvossimulator") ||
1153dda28197Spatrick       value.equals("watchossimulator")) {
1154dda28197Spatrick     environment = "simulator";
1155dda28197Spatrick     os_name = value.drop_back(environment.size()).str();
1156dda28197Spatrick   } else if (value.equals("maccatalyst")) {
1157dda28197Spatrick     os_name = "ios";
1158dda28197Spatrick     environment = "macabi";
1159dda28197Spatrick   } else {
1160dda28197Spatrick     os_name = value.str();
1161dda28197Spatrick   }
1162dda28197Spatrick }
1163dda28197Spatrick 
1164061da546Spatrick bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
1165061da546Spatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS));
1166061da546Spatrick 
1167061da546Spatrick   if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) {
1168061da546Spatrick     // host info computation can require DNS traffic and shelling out to external processes.
1169061da546Spatrick     // Increase the timeout to account for that.
1170061da546Spatrick     ScopedTimeout timeout(*this, seconds(10));
1171061da546Spatrick     m_qHostInfo_is_valid = eLazyBoolNo;
1172061da546Spatrick     StringExtractorGDBRemote response;
1173*be691f3bSpatrick     if (SendPacketAndWaitForResponse("qHostInfo", response) ==
1174061da546Spatrick         PacketResult::Success) {
1175061da546Spatrick       if (response.IsNormalResponse()) {
1176061da546Spatrick         llvm::StringRef name;
1177061da546Spatrick         llvm::StringRef value;
1178061da546Spatrick         uint32_t cpu = LLDB_INVALID_CPUTYPE;
1179061da546Spatrick         uint32_t sub = 0;
1180061da546Spatrick         std::string arch_name;
1181061da546Spatrick         std::string os_name;
1182061da546Spatrick         std::string environment;
1183061da546Spatrick         std::string vendor_name;
1184061da546Spatrick         std::string triple;
1185061da546Spatrick         std::string distribution_id;
1186061da546Spatrick         uint32_t pointer_byte_size = 0;
1187061da546Spatrick         ByteOrder byte_order = eByteOrderInvalid;
1188061da546Spatrick         uint32_t num_keys_decoded = 0;
1189061da546Spatrick         while (response.GetNameColonValue(name, value)) {
1190061da546Spatrick           if (name.equals("cputype")) {
1191061da546Spatrick             // exception type in big endian hex
1192061da546Spatrick             if (!value.getAsInteger(0, cpu))
1193061da546Spatrick               ++num_keys_decoded;
1194061da546Spatrick           } else if (name.equals("cpusubtype")) {
1195061da546Spatrick             // exception count in big endian hex
1196061da546Spatrick             if (!value.getAsInteger(0, sub))
1197061da546Spatrick               ++num_keys_decoded;
1198061da546Spatrick           } else if (name.equals("arch")) {
1199dda28197Spatrick             arch_name = std::string(value);
1200061da546Spatrick             ++num_keys_decoded;
1201061da546Spatrick           } else if (name.equals("triple")) {
1202061da546Spatrick             StringExtractor extractor(value);
1203061da546Spatrick             extractor.GetHexByteString(triple);
1204061da546Spatrick             ++num_keys_decoded;
1205061da546Spatrick           } else if (name.equals("distribution_id")) {
1206061da546Spatrick             StringExtractor extractor(value);
1207061da546Spatrick             extractor.GetHexByteString(distribution_id);
1208061da546Spatrick             ++num_keys_decoded;
1209061da546Spatrick           } else if (name.equals("os_build")) {
1210061da546Spatrick             StringExtractor extractor(value);
1211061da546Spatrick             extractor.GetHexByteString(m_os_build);
1212061da546Spatrick             ++num_keys_decoded;
1213061da546Spatrick           } else if (name.equals("hostname")) {
1214061da546Spatrick             StringExtractor extractor(value);
1215061da546Spatrick             extractor.GetHexByteString(m_hostname);
1216061da546Spatrick             ++num_keys_decoded;
1217061da546Spatrick           } else if (name.equals("os_kernel")) {
1218061da546Spatrick             StringExtractor extractor(value);
1219061da546Spatrick             extractor.GetHexByteString(m_os_kernel);
1220061da546Spatrick             ++num_keys_decoded;
1221061da546Spatrick           } else if (name.equals("ostype")) {
1222dda28197Spatrick             ParseOSType(value, os_name, environment);
1223061da546Spatrick             ++num_keys_decoded;
1224061da546Spatrick           } else if (name.equals("vendor")) {
1225dda28197Spatrick             vendor_name = std::string(value);
1226061da546Spatrick             ++num_keys_decoded;
1227061da546Spatrick           } else if (name.equals("endian")) {
1228061da546Spatrick             byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
1229061da546Spatrick                              .Case("little", eByteOrderLittle)
1230061da546Spatrick                              .Case("big", eByteOrderBig)
1231061da546Spatrick                              .Case("pdp", eByteOrderPDP)
1232061da546Spatrick                              .Default(eByteOrderInvalid);
1233061da546Spatrick             if (byte_order != eByteOrderInvalid)
1234061da546Spatrick               ++num_keys_decoded;
1235061da546Spatrick           } else if (name.equals("ptrsize")) {
1236061da546Spatrick             if (!value.getAsInteger(0, pointer_byte_size))
1237061da546Spatrick               ++num_keys_decoded;
1238*be691f3bSpatrick           } else if (name.equals("addressing_bits")) {
1239*be691f3bSpatrick             if (!value.getAsInteger(0, m_addressing_bits))
1240*be691f3bSpatrick               ++num_keys_decoded;
1241061da546Spatrick           } else if (name.equals("os_version") ||
1242*be691f3bSpatrick                      name.equals("version")) // Older debugserver binaries used
1243*be691f3bSpatrick                                              // the "version" key instead of
1244061da546Spatrick                                              // "os_version"...
1245061da546Spatrick           {
1246061da546Spatrick             if (!m_os_version.tryParse(value))
1247061da546Spatrick               ++num_keys_decoded;
1248061da546Spatrick           } else if (name.equals("maccatalyst_version")) {
1249061da546Spatrick             if (!m_maccatalyst_version.tryParse(value))
1250061da546Spatrick               ++num_keys_decoded;
1251061da546Spatrick           } else if (name.equals("watchpoint_exceptions_received")) {
1252061da546Spatrick             m_watchpoints_trigger_after_instruction =
1253061da546Spatrick                 llvm::StringSwitch<LazyBool>(value)
1254061da546Spatrick                     .Case("before", eLazyBoolNo)
1255061da546Spatrick                     .Case("after", eLazyBoolYes)
1256061da546Spatrick                     .Default(eLazyBoolCalculate);
1257061da546Spatrick             if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate)
1258061da546Spatrick               ++num_keys_decoded;
1259061da546Spatrick           } else if (name.equals("default_packet_timeout")) {
1260061da546Spatrick             uint32_t timeout_seconds;
1261061da546Spatrick             if (!value.getAsInteger(0, timeout_seconds)) {
1262061da546Spatrick               m_default_packet_timeout = seconds(timeout_seconds);
1263061da546Spatrick               SetPacketTimeout(m_default_packet_timeout);
1264061da546Spatrick               ++num_keys_decoded;
1265061da546Spatrick             }
1266*be691f3bSpatrick           } else if (name.equals("vm-page-size")) {
1267*be691f3bSpatrick             int page_size;
1268*be691f3bSpatrick             if (!value.getAsInteger(0, page_size)) {
1269*be691f3bSpatrick               m_target_vm_page_size = page_size;
1270*be691f3bSpatrick               ++num_keys_decoded;
1271*be691f3bSpatrick             }
1272061da546Spatrick           }
1273061da546Spatrick         }
1274061da546Spatrick 
1275061da546Spatrick         if (num_keys_decoded > 0)
1276061da546Spatrick           m_qHostInfo_is_valid = eLazyBoolYes;
1277061da546Spatrick 
1278061da546Spatrick         if (triple.empty()) {
1279061da546Spatrick           if (arch_name.empty()) {
1280061da546Spatrick             if (cpu != LLDB_INVALID_CPUTYPE) {
1281061da546Spatrick               m_host_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
1282061da546Spatrick               if (pointer_byte_size) {
1283061da546Spatrick                 assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1284061da546Spatrick               }
1285061da546Spatrick               if (byte_order != eByteOrderInvalid) {
1286061da546Spatrick                 assert(byte_order == m_host_arch.GetByteOrder());
1287061da546Spatrick               }
1288061da546Spatrick 
1289061da546Spatrick               if (!vendor_name.empty())
1290061da546Spatrick                 m_host_arch.GetTriple().setVendorName(
1291061da546Spatrick                     llvm::StringRef(vendor_name));
1292061da546Spatrick               if (!os_name.empty())
1293061da546Spatrick                 m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name));
1294061da546Spatrick               if (!environment.empty())
1295061da546Spatrick                 m_host_arch.GetTriple().setEnvironmentName(environment);
1296061da546Spatrick             }
1297061da546Spatrick           } else {
1298061da546Spatrick             std::string triple;
1299061da546Spatrick             triple += arch_name;
1300061da546Spatrick             if (!vendor_name.empty() || !os_name.empty()) {
1301061da546Spatrick               triple += '-';
1302061da546Spatrick               if (vendor_name.empty())
1303061da546Spatrick                 triple += "unknown";
1304061da546Spatrick               else
1305061da546Spatrick                 triple += vendor_name;
1306061da546Spatrick               triple += '-';
1307061da546Spatrick               if (os_name.empty())
1308061da546Spatrick                 triple += "unknown";
1309061da546Spatrick               else
1310061da546Spatrick                 triple += os_name;
1311061da546Spatrick             }
1312061da546Spatrick             m_host_arch.SetTriple(triple.c_str());
1313061da546Spatrick 
1314061da546Spatrick             llvm::Triple &host_triple = m_host_arch.GetTriple();
1315061da546Spatrick             if (host_triple.getVendor() == llvm::Triple::Apple &&
1316061da546Spatrick                 host_triple.getOS() == llvm::Triple::Darwin) {
1317061da546Spatrick               switch (m_host_arch.GetMachine()) {
1318061da546Spatrick               case llvm::Triple::aarch64:
1319061da546Spatrick               case llvm::Triple::aarch64_32:
1320061da546Spatrick               case llvm::Triple::arm:
1321061da546Spatrick               case llvm::Triple::thumb:
1322061da546Spatrick                 host_triple.setOS(llvm::Triple::IOS);
1323061da546Spatrick                 break;
1324061da546Spatrick               default:
1325061da546Spatrick                 host_triple.setOS(llvm::Triple::MacOSX);
1326061da546Spatrick                 break;
1327061da546Spatrick               }
1328061da546Spatrick             }
1329061da546Spatrick             if (pointer_byte_size) {
1330061da546Spatrick               assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1331061da546Spatrick             }
1332061da546Spatrick             if (byte_order != eByteOrderInvalid) {
1333061da546Spatrick               assert(byte_order == m_host_arch.GetByteOrder());
1334061da546Spatrick             }
1335061da546Spatrick           }
1336061da546Spatrick         } else {
1337061da546Spatrick           m_host_arch.SetTriple(triple.c_str());
1338061da546Spatrick           if (pointer_byte_size) {
1339061da546Spatrick             assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1340061da546Spatrick           }
1341061da546Spatrick           if (byte_order != eByteOrderInvalid) {
1342061da546Spatrick             assert(byte_order == m_host_arch.GetByteOrder());
1343061da546Spatrick           }
1344061da546Spatrick 
1345061da546Spatrick           LLDB_LOGF(log,
1346061da546Spatrick                     "GDBRemoteCommunicationClient::%s parsed host "
1347061da546Spatrick                     "architecture as %s, triple as %s from triple text %s",
1348061da546Spatrick                     __FUNCTION__,
1349061da546Spatrick                     m_host_arch.GetArchitectureName()
1350061da546Spatrick                         ? m_host_arch.GetArchitectureName()
1351061da546Spatrick                         : "<null-arch-name>",
1352061da546Spatrick                     m_host_arch.GetTriple().getTriple().c_str(),
1353061da546Spatrick                     triple.c_str());
1354061da546Spatrick         }
1355061da546Spatrick         if (!distribution_id.empty())
1356061da546Spatrick           m_host_arch.SetDistributionId(distribution_id.c_str());
1357061da546Spatrick       }
1358061da546Spatrick     }
1359061da546Spatrick   }
1360061da546Spatrick   return m_qHostInfo_is_valid == eLazyBoolYes;
1361061da546Spatrick }
1362061da546Spatrick 
1363061da546Spatrick int GDBRemoteCommunicationClient::SendAttach(
1364061da546Spatrick     lldb::pid_t pid, StringExtractorGDBRemote &response) {
1365061da546Spatrick   if (pid != LLDB_INVALID_PROCESS_ID) {
1366061da546Spatrick     char packet[64];
1367061da546Spatrick     const int packet_len =
1368061da546Spatrick         ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid);
1369061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
1370061da546Spatrick     assert(packet_len < (int)sizeof(packet));
1371*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
1372061da546Spatrick         PacketResult::Success) {
1373061da546Spatrick       if (response.IsErrorResponse())
1374061da546Spatrick         return response.GetError();
1375061da546Spatrick       return 0;
1376061da546Spatrick     }
1377061da546Spatrick   }
1378061da546Spatrick   return -1;
1379061da546Spatrick }
1380061da546Spatrick 
1381061da546Spatrick int GDBRemoteCommunicationClient::SendStdinNotification(const char *data,
1382061da546Spatrick                                                         size_t data_len) {
1383061da546Spatrick   StreamString packet;
1384061da546Spatrick   packet.PutCString("I");
1385061da546Spatrick   packet.PutBytesAsRawHex8(data, data_len);
1386061da546Spatrick   StringExtractorGDBRemote response;
1387*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1388061da546Spatrick       PacketResult::Success) {
1389061da546Spatrick     return 0;
1390061da546Spatrick   }
1391061da546Spatrick   return response.GetError();
1392061da546Spatrick }
1393061da546Spatrick 
1394061da546Spatrick const lldb_private::ArchSpec &
1395061da546Spatrick GDBRemoteCommunicationClient::GetHostArchitecture() {
1396061da546Spatrick   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1397061da546Spatrick     GetHostInfo();
1398061da546Spatrick   return m_host_arch;
1399061da546Spatrick }
1400061da546Spatrick 
1401*be691f3bSpatrick uint32_t GDBRemoteCommunicationClient::GetAddressingBits() {
1402*be691f3bSpatrick   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1403*be691f3bSpatrick     GetHostInfo();
1404*be691f3bSpatrick   return m_addressing_bits;
1405*be691f3bSpatrick }
1406061da546Spatrick seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() {
1407061da546Spatrick   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1408061da546Spatrick     GetHostInfo();
1409061da546Spatrick   return m_default_packet_timeout;
1410061da546Spatrick }
1411061da546Spatrick 
1412061da546Spatrick addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size,
1413061da546Spatrick                                                     uint32_t permissions) {
1414061da546Spatrick   if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
1415061da546Spatrick     m_supports_alloc_dealloc_memory = eLazyBoolYes;
1416061da546Spatrick     char packet[64];
1417061da546Spatrick     const int packet_len = ::snprintf(
1418061da546Spatrick         packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s", (uint64_t)size,
1419061da546Spatrick         permissions & lldb::ePermissionsReadable ? "r" : "",
1420061da546Spatrick         permissions & lldb::ePermissionsWritable ? "w" : "",
1421061da546Spatrick         permissions & lldb::ePermissionsExecutable ? "x" : "");
1422061da546Spatrick     assert(packet_len < (int)sizeof(packet));
1423061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
1424061da546Spatrick     StringExtractorGDBRemote response;
1425*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
1426061da546Spatrick         PacketResult::Success) {
1427061da546Spatrick       if (response.IsUnsupportedResponse())
1428061da546Spatrick         m_supports_alloc_dealloc_memory = eLazyBoolNo;
1429061da546Spatrick       else if (!response.IsErrorResponse())
1430061da546Spatrick         return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
1431061da546Spatrick     } else {
1432061da546Spatrick       m_supports_alloc_dealloc_memory = eLazyBoolNo;
1433061da546Spatrick     }
1434061da546Spatrick   }
1435061da546Spatrick   return LLDB_INVALID_ADDRESS;
1436061da546Spatrick }
1437061da546Spatrick 
1438061da546Spatrick bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) {
1439061da546Spatrick   if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
1440061da546Spatrick     m_supports_alloc_dealloc_memory = eLazyBoolYes;
1441061da546Spatrick     char packet[64];
1442061da546Spatrick     const int packet_len =
1443061da546Spatrick         ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
1444061da546Spatrick     assert(packet_len < (int)sizeof(packet));
1445061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
1446061da546Spatrick     StringExtractorGDBRemote response;
1447*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
1448061da546Spatrick         PacketResult::Success) {
1449061da546Spatrick       if (response.IsUnsupportedResponse())
1450061da546Spatrick         m_supports_alloc_dealloc_memory = eLazyBoolNo;
1451061da546Spatrick       else if (response.IsOKResponse())
1452061da546Spatrick         return true;
1453061da546Spatrick     } else {
1454061da546Spatrick       m_supports_alloc_dealloc_memory = eLazyBoolNo;
1455061da546Spatrick     }
1456061da546Spatrick   }
1457061da546Spatrick   return false;
1458061da546Spatrick }
1459061da546Spatrick 
1460061da546Spatrick Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) {
1461061da546Spatrick   Status error;
1462061da546Spatrick 
1463061da546Spatrick   if (keep_stopped) {
1464061da546Spatrick     if (m_supports_detach_stay_stopped == eLazyBoolCalculate) {
1465061da546Spatrick       char packet[64];
1466061da546Spatrick       const int packet_len =
1467061da546Spatrick           ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
1468061da546Spatrick       assert(packet_len < (int)sizeof(packet));
1469061da546Spatrick       UNUSED_IF_ASSERT_DISABLED(packet_len);
1470061da546Spatrick       StringExtractorGDBRemote response;
1471*be691f3bSpatrick       if (SendPacketAndWaitForResponse(packet, response) ==
1472061da546Spatrick               PacketResult::Success &&
1473061da546Spatrick           response.IsOKResponse()) {
1474061da546Spatrick         m_supports_detach_stay_stopped = eLazyBoolYes;
1475061da546Spatrick       } else {
1476061da546Spatrick         m_supports_detach_stay_stopped = eLazyBoolNo;
1477061da546Spatrick       }
1478061da546Spatrick     }
1479061da546Spatrick 
1480061da546Spatrick     if (m_supports_detach_stay_stopped == eLazyBoolNo) {
1481061da546Spatrick       error.SetErrorString("Stays stopped not supported by this target.");
1482061da546Spatrick       return error;
1483061da546Spatrick     } else {
1484061da546Spatrick       StringExtractorGDBRemote response;
1485*be691f3bSpatrick       PacketResult packet_result = SendPacketAndWaitForResponse("D1", response);
1486061da546Spatrick       if (packet_result != PacketResult::Success)
1487061da546Spatrick         error.SetErrorString("Sending extended disconnect packet failed.");
1488061da546Spatrick     }
1489061da546Spatrick   } else {
1490061da546Spatrick     StringExtractorGDBRemote response;
1491*be691f3bSpatrick     PacketResult packet_result = SendPacketAndWaitForResponse("D", response);
1492061da546Spatrick     if (packet_result != PacketResult::Success)
1493061da546Spatrick       error.SetErrorString("Sending disconnect packet failed.");
1494061da546Spatrick   }
1495061da546Spatrick   return error;
1496061da546Spatrick }
1497061da546Spatrick 
1498061da546Spatrick Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
1499061da546Spatrick     lldb::addr_t addr, lldb_private::MemoryRegionInfo &region_info) {
1500061da546Spatrick   Status error;
1501061da546Spatrick   region_info.Clear();
1502061da546Spatrick 
1503061da546Spatrick   if (m_supports_memory_region_info != eLazyBoolNo) {
1504061da546Spatrick     m_supports_memory_region_info = eLazyBoolYes;
1505061da546Spatrick     char packet[64];
1506061da546Spatrick     const int packet_len = ::snprintf(
1507061da546Spatrick         packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
1508061da546Spatrick     assert(packet_len < (int)sizeof(packet));
1509061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
1510061da546Spatrick     StringExtractorGDBRemote response;
1511*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
1512061da546Spatrick             PacketResult::Success &&
1513061da546Spatrick         response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
1514061da546Spatrick       llvm::StringRef name;
1515061da546Spatrick       llvm::StringRef value;
1516061da546Spatrick       addr_t addr_value = LLDB_INVALID_ADDRESS;
1517061da546Spatrick       bool success = true;
1518061da546Spatrick       bool saw_permissions = false;
1519061da546Spatrick       while (success && response.GetNameColonValue(name, value)) {
1520061da546Spatrick         if (name.equals("start")) {
1521061da546Spatrick           if (!value.getAsInteger(16, addr_value))
1522061da546Spatrick             region_info.GetRange().SetRangeBase(addr_value);
1523061da546Spatrick         } else if (name.equals("size")) {
1524061da546Spatrick           if (!value.getAsInteger(16, addr_value))
1525061da546Spatrick             region_info.GetRange().SetByteSize(addr_value);
1526061da546Spatrick         } else if (name.equals("permissions") &&
1527061da546Spatrick                    region_info.GetRange().IsValid()) {
1528061da546Spatrick           saw_permissions = true;
1529061da546Spatrick           if (region_info.GetRange().Contains(addr)) {
1530061da546Spatrick             if (value.find('r') != llvm::StringRef::npos)
1531061da546Spatrick               region_info.SetReadable(MemoryRegionInfo::eYes);
1532061da546Spatrick             else
1533061da546Spatrick               region_info.SetReadable(MemoryRegionInfo::eNo);
1534061da546Spatrick 
1535061da546Spatrick             if (value.find('w') != llvm::StringRef::npos)
1536061da546Spatrick               region_info.SetWritable(MemoryRegionInfo::eYes);
1537061da546Spatrick             else
1538061da546Spatrick               region_info.SetWritable(MemoryRegionInfo::eNo);
1539061da546Spatrick 
1540061da546Spatrick             if (value.find('x') != llvm::StringRef::npos)
1541061da546Spatrick               region_info.SetExecutable(MemoryRegionInfo::eYes);
1542061da546Spatrick             else
1543061da546Spatrick               region_info.SetExecutable(MemoryRegionInfo::eNo);
1544061da546Spatrick 
1545061da546Spatrick             region_info.SetMapped(MemoryRegionInfo::eYes);
1546061da546Spatrick           } else {
1547061da546Spatrick             // The reported region does not contain this address -- we're
1548061da546Spatrick             // looking at an unmapped page
1549061da546Spatrick             region_info.SetReadable(MemoryRegionInfo::eNo);
1550061da546Spatrick             region_info.SetWritable(MemoryRegionInfo::eNo);
1551061da546Spatrick             region_info.SetExecutable(MemoryRegionInfo::eNo);
1552061da546Spatrick             region_info.SetMapped(MemoryRegionInfo::eNo);
1553061da546Spatrick           }
1554061da546Spatrick         } else if (name.equals("name")) {
1555061da546Spatrick           StringExtractorGDBRemote name_extractor(value);
1556061da546Spatrick           std::string name;
1557061da546Spatrick           name_extractor.GetHexByteString(name);
1558061da546Spatrick           region_info.SetName(name.c_str());
1559*be691f3bSpatrick         } else if (name.equals("flags")) {
1560*be691f3bSpatrick           region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
1561*be691f3bSpatrick 
1562*be691f3bSpatrick           llvm::StringRef flags = value;
1563*be691f3bSpatrick           llvm::StringRef flag;
1564*be691f3bSpatrick           while (flags.size()) {
1565*be691f3bSpatrick             flags = flags.ltrim();
1566*be691f3bSpatrick             std::tie(flag, flags) = flags.split(' ');
1567*be691f3bSpatrick             // To account for trailing whitespace
1568*be691f3bSpatrick             if (flag.size()) {
1569*be691f3bSpatrick               if (flag == "mt") {
1570*be691f3bSpatrick                 region_info.SetMemoryTagged(MemoryRegionInfo::eYes);
1571*be691f3bSpatrick                 break;
1572*be691f3bSpatrick               }
1573*be691f3bSpatrick             }
1574*be691f3bSpatrick           }
1575061da546Spatrick         } else if (name.equals("error")) {
1576061da546Spatrick           StringExtractorGDBRemote error_extractor(value);
1577061da546Spatrick           std::string error_string;
1578061da546Spatrick           // Now convert the HEX bytes into a string value
1579061da546Spatrick           error_extractor.GetHexByteString(error_string);
1580061da546Spatrick           error.SetErrorString(error_string.c_str());
1581*be691f3bSpatrick         } else if (name.equals("dirty-pages")) {
1582*be691f3bSpatrick           std::vector<addr_t> dirty_page_list;
1583*be691f3bSpatrick           std::string comma_sep_str = value.str();
1584*be691f3bSpatrick           size_t comma_pos;
1585*be691f3bSpatrick           addr_t page;
1586*be691f3bSpatrick           while ((comma_pos = comma_sep_str.find(',')) != std::string::npos) {
1587*be691f3bSpatrick             comma_sep_str[comma_pos] = '\0';
1588*be691f3bSpatrick             page = StringConvert::ToUInt64(comma_sep_str.c_str(),
1589*be691f3bSpatrick                                            LLDB_INVALID_ADDRESS, 16);
1590*be691f3bSpatrick             if (page != LLDB_INVALID_ADDRESS)
1591*be691f3bSpatrick               dirty_page_list.push_back(page);
1592*be691f3bSpatrick             comma_sep_str.erase(0, comma_pos + 1);
1593*be691f3bSpatrick           }
1594*be691f3bSpatrick           page = StringConvert::ToUInt64(comma_sep_str.c_str(),
1595*be691f3bSpatrick                                          LLDB_INVALID_ADDRESS, 16);
1596*be691f3bSpatrick           if (page != LLDB_INVALID_ADDRESS)
1597*be691f3bSpatrick             dirty_page_list.push_back(page);
1598*be691f3bSpatrick           region_info.SetDirtyPageList(dirty_page_list);
1599061da546Spatrick         }
1600061da546Spatrick       }
1601061da546Spatrick 
1602*be691f3bSpatrick       if (m_target_vm_page_size != 0)
1603*be691f3bSpatrick         region_info.SetPageSize(m_target_vm_page_size);
1604*be691f3bSpatrick 
1605061da546Spatrick       if (region_info.GetRange().IsValid()) {
1606061da546Spatrick         // We got a valid address range back but no permissions -- which means
1607061da546Spatrick         // this is an unmapped page
1608061da546Spatrick         if (!saw_permissions) {
1609061da546Spatrick           region_info.SetReadable(MemoryRegionInfo::eNo);
1610061da546Spatrick           region_info.SetWritable(MemoryRegionInfo::eNo);
1611061da546Spatrick           region_info.SetExecutable(MemoryRegionInfo::eNo);
1612061da546Spatrick           region_info.SetMapped(MemoryRegionInfo::eNo);
1613061da546Spatrick         }
1614061da546Spatrick       } else {
1615061da546Spatrick         // We got an invalid address range back
1616061da546Spatrick         error.SetErrorString("Server returned invalid range");
1617061da546Spatrick       }
1618061da546Spatrick     } else {
1619061da546Spatrick       m_supports_memory_region_info = eLazyBoolNo;
1620061da546Spatrick     }
1621061da546Spatrick   }
1622061da546Spatrick 
1623061da546Spatrick   if (m_supports_memory_region_info == eLazyBoolNo) {
1624061da546Spatrick     error.SetErrorString("qMemoryRegionInfo is not supported");
1625061da546Spatrick   }
1626061da546Spatrick 
1627061da546Spatrick   // Try qXfer:memory-map:read to get region information not included in
1628061da546Spatrick   // qMemoryRegionInfo
1629061da546Spatrick   MemoryRegionInfo qXfer_region_info;
1630061da546Spatrick   Status qXfer_error = GetQXferMemoryMapRegionInfo(addr, qXfer_region_info);
1631061da546Spatrick 
1632061da546Spatrick   if (error.Fail()) {
1633061da546Spatrick     // If qMemoryRegionInfo failed, but qXfer:memory-map:read succeeded, use
1634061da546Spatrick     // the qXfer result as a fallback
1635061da546Spatrick     if (qXfer_error.Success()) {
1636061da546Spatrick       region_info = qXfer_region_info;
1637061da546Spatrick       error.Clear();
1638061da546Spatrick     } else {
1639061da546Spatrick       region_info.Clear();
1640061da546Spatrick     }
1641061da546Spatrick   } else if (qXfer_error.Success()) {
1642061da546Spatrick     // If both qMemoryRegionInfo and qXfer:memory-map:read succeeded, and if
1643061da546Spatrick     // both regions are the same range, update the result to include the flash-
1644061da546Spatrick     // memory information that is specific to the qXfer result.
1645061da546Spatrick     if (region_info.GetRange() == qXfer_region_info.GetRange()) {
1646061da546Spatrick       region_info.SetFlash(qXfer_region_info.GetFlash());
1647061da546Spatrick       region_info.SetBlocksize(qXfer_region_info.GetBlocksize());
1648061da546Spatrick     }
1649061da546Spatrick   }
1650061da546Spatrick   return error;
1651061da546Spatrick }
1652061da546Spatrick 
1653061da546Spatrick Status GDBRemoteCommunicationClient::GetQXferMemoryMapRegionInfo(
1654061da546Spatrick     lldb::addr_t addr, MemoryRegionInfo &region) {
1655061da546Spatrick   Status error = LoadQXferMemoryMap();
1656061da546Spatrick   if (!error.Success())
1657061da546Spatrick     return error;
1658061da546Spatrick   for (const auto &map_region : m_qXfer_memory_map) {
1659061da546Spatrick     if (map_region.GetRange().Contains(addr)) {
1660061da546Spatrick       region = map_region;
1661061da546Spatrick       return error;
1662061da546Spatrick     }
1663061da546Spatrick   }
1664061da546Spatrick   error.SetErrorString("Region not found");
1665061da546Spatrick   return error;
1666061da546Spatrick }
1667061da546Spatrick 
1668061da546Spatrick Status GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
1669061da546Spatrick 
1670061da546Spatrick   Status error;
1671061da546Spatrick 
1672061da546Spatrick   if (m_qXfer_memory_map_loaded)
1673061da546Spatrick     // Already loaded, return success
1674061da546Spatrick     return error;
1675061da546Spatrick 
1676061da546Spatrick   if (!XMLDocument::XMLEnabled()) {
1677061da546Spatrick     error.SetErrorString("XML is not supported");
1678061da546Spatrick     return error;
1679061da546Spatrick   }
1680061da546Spatrick 
1681061da546Spatrick   if (!GetQXferMemoryMapReadSupported()) {
1682061da546Spatrick     error.SetErrorString("Memory map is not supported");
1683061da546Spatrick     return error;
1684061da546Spatrick   }
1685061da546Spatrick 
1686061da546Spatrick   std::string xml;
1687061da546Spatrick   lldb_private::Status lldberr;
1688061da546Spatrick   if (!ReadExtFeature(ConstString("memory-map"), ConstString(""), xml,
1689061da546Spatrick                       lldberr)) {
1690061da546Spatrick     error.SetErrorString("Failed to read memory map");
1691061da546Spatrick     return error;
1692061da546Spatrick   }
1693061da546Spatrick 
1694061da546Spatrick   XMLDocument xml_document;
1695061da546Spatrick 
1696061da546Spatrick   if (!xml_document.ParseMemory(xml.c_str(), xml.size())) {
1697061da546Spatrick     error.SetErrorString("Failed to parse memory map xml");
1698061da546Spatrick     return error;
1699061da546Spatrick   }
1700061da546Spatrick 
1701061da546Spatrick   XMLNode map_node = xml_document.GetRootElement("memory-map");
1702061da546Spatrick   if (!map_node) {
1703061da546Spatrick     error.SetErrorString("Invalid root node in memory map xml");
1704061da546Spatrick     return error;
1705061da546Spatrick   }
1706061da546Spatrick 
1707061da546Spatrick   m_qXfer_memory_map.clear();
1708061da546Spatrick 
1709061da546Spatrick   map_node.ForEachChildElement([this](const XMLNode &memory_node) -> bool {
1710061da546Spatrick     if (!memory_node.IsElement())
1711061da546Spatrick       return true;
1712061da546Spatrick     if (memory_node.GetName() != "memory")
1713061da546Spatrick       return true;
1714061da546Spatrick     auto type = memory_node.GetAttributeValue("type", "");
1715061da546Spatrick     uint64_t start;
1716061da546Spatrick     uint64_t length;
1717061da546Spatrick     if (!memory_node.GetAttributeValueAsUnsigned("start", start))
1718061da546Spatrick       return true;
1719061da546Spatrick     if (!memory_node.GetAttributeValueAsUnsigned("length", length))
1720061da546Spatrick       return true;
1721061da546Spatrick     MemoryRegionInfo region;
1722061da546Spatrick     region.GetRange().SetRangeBase(start);
1723061da546Spatrick     region.GetRange().SetByteSize(length);
1724061da546Spatrick     if (type == "rom") {
1725061da546Spatrick       region.SetReadable(MemoryRegionInfo::eYes);
1726061da546Spatrick       this->m_qXfer_memory_map.push_back(region);
1727061da546Spatrick     } else if (type == "ram") {
1728061da546Spatrick       region.SetReadable(MemoryRegionInfo::eYes);
1729061da546Spatrick       region.SetWritable(MemoryRegionInfo::eYes);
1730061da546Spatrick       this->m_qXfer_memory_map.push_back(region);
1731061da546Spatrick     } else if (type == "flash") {
1732061da546Spatrick       region.SetFlash(MemoryRegionInfo::eYes);
1733061da546Spatrick       memory_node.ForEachChildElement(
1734061da546Spatrick           [&region](const XMLNode &prop_node) -> bool {
1735061da546Spatrick             if (!prop_node.IsElement())
1736061da546Spatrick               return true;
1737061da546Spatrick             if (prop_node.GetName() != "property")
1738061da546Spatrick               return true;
1739061da546Spatrick             auto propname = prop_node.GetAttributeValue("name", "");
1740061da546Spatrick             if (propname == "blocksize") {
1741061da546Spatrick               uint64_t blocksize;
1742061da546Spatrick               if (prop_node.GetElementTextAsUnsigned(blocksize))
1743061da546Spatrick                 region.SetBlocksize(blocksize);
1744061da546Spatrick             }
1745061da546Spatrick             return true;
1746061da546Spatrick           });
1747061da546Spatrick       this->m_qXfer_memory_map.push_back(region);
1748061da546Spatrick     }
1749061da546Spatrick     return true;
1750061da546Spatrick   });
1751061da546Spatrick 
1752061da546Spatrick   m_qXfer_memory_map_loaded = true;
1753061da546Spatrick 
1754061da546Spatrick   return error;
1755061da546Spatrick }
1756061da546Spatrick 
1757061da546Spatrick Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
1758061da546Spatrick   Status error;
1759061da546Spatrick 
1760061da546Spatrick   if (m_supports_watchpoint_support_info == eLazyBoolYes) {
1761061da546Spatrick     num = m_num_supported_hardware_watchpoints;
1762061da546Spatrick     return error;
1763061da546Spatrick   }
1764061da546Spatrick 
1765061da546Spatrick   // Set num to 0 first.
1766061da546Spatrick   num = 0;
1767061da546Spatrick   if (m_supports_watchpoint_support_info != eLazyBoolNo) {
1768061da546Spatrick     StringExtractorGDBRemote response;
1769*be691f3bSpatrick     if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) ==
1770061da546Spatrick         PacketResult::Success) {
1771061da546Spatrick       m_supports_watchpoint_support_info = eLazyBoolYes;
1772061da546Spatrick       llvm::StringRef name;
1773061da546Spatrick       llvm::StringRef value;
1774061da546Spatrick       bool found_num_field = false;
1775061da546Spatrick       while (response.GetNameColonValue(name, value)) {
1776061da546Spatrick         if (name.equals("num")) {
1777061da546Spatrick           value.getAsInteger(0, m_num_supported_hardware_watchpoints);
1778061da546Spatrick           num = m_num_supported_hardware_watchpoints;
1779061da546Spatrick           found_num_field = true;
1780061da546Spatrick         }
1781061da546Spatrick       }
1782061da546Spatrick       if (!found_num_field) {
1783061da546Spatrick         m_supports_watchpoint_support_info = eLazyBoolNo;
1784061da546Spatrick       }
1785061da546Spatrick     } else {
1786061da546Spatrick       m_supports_watchpoint_support_info = eLazyBoolNo;
1787061da546Spatrick     }
1788061da546Spatrick   }
1789061da546Spatrick 
1790061da546Spatrick   if (m_supports_watchpoint_support_info == eLazyBoolNo) {
1791061da546Spatrick     error.SetErrorString("qWatchpointSupportInfo is not supported");
1792061da546Spatrick   }
1793061da546Spatrick   return error;
1794061da546Spatrick }
1795061da546Spatrick 
1796061da546Spatrick lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(
1797061da546Spatrick     uint32_t &num, bool &after, const ArchSpec &arch) {
1798061da546Spatrick   Status error(GetWatchpointSupportInfo(num));
1799061da546Spatrick   if (error.Success())
1800061da546Spatrick     error = GetWatchpointsTriggerAfterInstruction(after, arch);
1801061da546Spatrick   return error;
1802061da546Spatrick }
1803061da546Spatrick 
1804061da546Spatrick lldb_private::Status
1805061da546Spatrick GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
1806061da546Spatrick     bool &after, const ArchSpec &arch) {
1807061da546Spatrick   Status error;
1808061da546Spatrick   llvm::Triple triple = arch.GetTriple();
1809061da546Spatrick 
1810061da546Spatrick   // we assume watchpoints will happen after running the relevant opcode and we
1811061da546Spatrick   // only want to override this behavior if we have explicitly received a
1812061da546Spatrick   // qHostInfo telling us otherwise
1813061da546Spatrick   if (m_qHostInfo_is_valid != eLazyBoolYes) {
1814061da546Spatrick     // On targets like MIPS and ppc64, watchpoint exceptions are always
1815061da546Spatrick     // generated before the instruction is executed. The connected target may
1816061da546Spatrick     // not support qHostInfo or qWatchpointSupportInfo packets.
1817061da546Spatrick     after = !(triple.isMIPS() || triple.isPPC64());
1818061da546Spatrick   } else {
1819061da546Spatrick     // For MIPS and ppc64, set m_watchpoints_trigger_after_instruction to
1820061da546Spatrick     // eLazyBoolNo if it is not calculated before.
1821061da546Spatrick     if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate &&
1822061da546Spatrick         (triple.isMIPS() || triple.isPPC64()))
1823061da546Spatrick       m_watchpoints_trigger_after_instruction = eLazyBoolNo;
1824061da546Spatrick 
1825061da546Spatrick     after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
1826061da546Spatrick   }
1827061da546Spatrick   return error;
1828061da546Spatrick }
1829061da546Spatrick 
1830061da546Spatrick int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) {
1831061da546Spatrick   if (file_spec) {
1832061da546Spatrick     std::string path{file_spec.GetPath(false)};
1833061da546Spatrick     StreamString packet;
1834061da546Spatrick     packet.PutCString("QSetSTDIN:");
1835061da546Spatrick     packet.PutStringAsRawHex8(path);
1836061da546Spatrick 
1837061da546Spatrick     StringExtractorGDBRemote response;
1838*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1839061da546Spatrick         PacketResult::Success) {
1840061da546Spatrick       if (response.IsOKResponse())
1841061da546Spatrick         return 0;
1842061da546Spatrick       uint8_t error = response.GetError();
1843061da546Spatrick       if (error)
1844061da546Spatrick         return error;
1845061da546Spatrick     }
1846061da546Spatrick   }
1847061da546Spatrick   return -1;
1848061da546Spatrick }
1849061da546Spatrick 
1850061da546Spatrick int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) {
1851061da546Spatrick   if (file_spec) {
1852061da546Spatrick     std::string path{file_spec.GetPath(false)};
1853061da546Spatrick     StreamString packet;
1854061da546Spatrick     packet.PutCString("QSetSTDOUT:");
1855061da546Spatrick     packet.PutStringAsRawHex8(path);
1856061da546Spatrick 
1857061da546Spatrick     StringExtractorGDBRemote response;
1858*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1859061da546Spatrick         PacketResult::Success) {
1860061da546Spatrick       if (response.IsOKResponse())
1861061da546Spatrick         return 0;
1862061da546Spatrick       uint8_t error = response.GetError();
1863061da546Spatrick       if (error)
1864061da546Spatrick         return error;
1865061da546Spatrick     }
1866061da546Spatrick   }
1867061da546Spatrick   return -1;
1868061da546Spatrick }
1869061da546Spatrick 
1870061da546Spatrick int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) {
1871061da546Spatrick   if (file_spec) {
1872061da546Spatrick     std::string path{file_spec.GetPath(false)};
1873061da546Spatrick     StreamString packet;
1874061da546Spatrick     packet.PutCString("QSetSTDERR:");
1875061da546Spatrick     packet.PutStringAsRawHex8(path);
1876061da546Spatrick 
1877061da546Spatrick     StringExtractorGDBRemote response;
1878*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1879061da546Spatrick         PacketResult::Success) {
1880061da546Spatrick       if (response.IsOKResponse())
1881061da546Spatrick         return 0;
1882061da546Spatrick       uint8_t error = response.GetError();
1883061da546Spatrick       if (error)
1884061da546Spatrick         return error;
1885061da546Spatrick     }
1886061da546Spatrick   }
1887061da546Spatrick   return -1;
1888061da546Spatrick }
1889061da546Spatrick 
1890061da546Spatrick bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
1891061da546Spatrick   StringExtractorGDBRemote response;
1892*be691f3bSpatrick   if (SendPacketAndWaitForResponse("qGetWorkingDir", response) ==
1893061da546Spatrick       PacketResult::Success) {
1894061da546Spatrick     if (response.IsUnsupportedResponse())
1895061da546Spatrick       return false;
1896061da546Spatrick     if (response.IsErrorResponse())
1897061da546Spatrick       return false;
1898061da546Spatrick     std::string cwd;
1899061da546Spatrick     response.GetHexByteString(cwd);
1900061da546Spatrick     working_dir.SetFile(cwd, GetHostArchitecture().GetTriple());
1901061da546Spatrick     return !cwd.empty();
1902061da546Spatrick   }
1903061da546Spatrick   return false;
1904061da546Spatrick }
1905061da546Spatrick 
1906061da546Spatrick int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) {
1907061da546Spatrick   if (working_dir) {
1908061da546Spatrick     std::string path{working_dir.GetPath(false)};
1909061da546Spatrick     StreamString packet;
1910061da546Spatrick     packet.PutCString("QSetWorkingDir:");
1911061da546Spatrick     packet.PutStringAsRawHex8(path);
1912061da546Spatrick 
1913061da546Spatrick     StringExtractorGDBRemote response;
1914*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
1915061da546Spatrick         PacketResult::Success) {
1916061da546Spatrick       if (response.IsOKResponse())
1917061da546Spatrick         return 0;
1918061da546Spatrick       uint8_t error = response.GetError();
1919061da546Spatrick       if (error)
1920061da546Spatrick         return error;
1921061da546Spatrick     }
1922061da546Spatrick   }
1923061da546Spatrick   return -1;
1924061da546Spatrick }
1925061da546Spatrick 
1926061da546Spatrick int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) {
1927061da546Spatrick   char packet[32];
1928061da546Spatrick   const int packet_len =
1929061da546Spatrick       ::snprintf(packet, sizeof(packet), "QSetDisableASLR:%i", enable ? 1 : 0);
1930061da546Spatrick   assert(packet_len < (int)sizeof(packet));
1931061da546Spatrick   UNUSED_IF_ASSERT_DISABLED(packet_len);
1932061da546Spatrick   StringExtractorGDBRemote response;
1933*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
1934061da546Spatrick     if (response.IsOKResponse())
1935061da546Spatrick       return 0;
1936061da546Spatrick     uint8_t error = response.GetError();
1937061da546Spatrick     if (error)
1938061da546Spatrick       return error;
1939061da546Spatrick   }
1940061da546Spatrick   return -1;
1941061da546Spatrick }
1942061da546Spatrick 
1943061da546Spatrick int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) {
1944061da546Spatrick   char packet[32];
1945061da546Spatrick   const int packet_len = ::snprintf(packet, sizeof(packet),
1946061da546Spatrick                                     "QSetDetachOnError:%i", enable ? 1 : 0);
1947061da546Spatrick   assert(packet_len < (int)sizeof(packet));
1948061da546Spatrick   UNUSED_IF_ASSERT_DISABLED(packet_len);
1949061da546Spatrick   StringExtractorGDBRemote response;
1950*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
1951061da546Spatrick     if (response.IsOKResponse())
1952061da546Spatrick       return 0;
1953061da546Spatrick     uint8_t error = response.GetError();
1954061da546Spatrick     if (error)
1955061da546Spatrick       return error;
1956061da546Spatrick   }
1957061da546Spatrick   return -1;
1958061da546Spatrick }
1959061da546Spatrick 
1960061da546Spatrick bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
1961061da546Spatrick     StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) {
1962061da546Spatrick   if (response.IsNormalResponse()) {
1963061da546Spatrick     llvm::StringRef name;
1964061da546Spatrick     llvm::StringRef value;
1965061da546Spatrick     StringExtractor extractor;
1966061da546Spatrick 
1967061da546Spatrick     uint32_t cpu = LLDB_INVALID_CPUTYPE;
1968061da546Spatrick     uint32_t sub = 0;
1969061da546Spatrick     std::string vendor;
1970061da546Spatrick     std::string os_type;
1971061da546Spatrick 
1972061da546Spatrick     while (response.GetNameColonValue(name, value)) {
1973061da546Spatrick       if (name.equals("pid")) {
1974061da546Spatrick         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
1975061da546Spatrick         value.getAsInteger(0, pid);
1976061da546Spatrick         process_info.SetProcessID(pid);
1977061da546Spatrick       } else if (name.equals("ppid")) {
1978061da546Spatrick         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
1979061da546Spatrick         value.getAsInteger(0, pid);
1980061da546Spatrick         process_info.SetParentProcessID(pid);
1981061da546Spatrick       } else if (name.equals("uid")) {
1982061da546Spatrick         uint32_t uid = UINT32_MAX;
1983061da546Spatrick         value.getAsInteger(0, uid);
1984061da546Spatrick         process_info.SetUserID(uid);
1985061da546Spatrick       } else if (name.equals("euid")) {
1986061da546Spatrick         uint32_t uid = UINT32_MAX;
1987061da546Spatrick         value.getAsInteger(0, uid);
1988061da546Spatrick         process_info.SetEffectiveUserID(uid);
1989061da546Spatrick       } else if (name.equals("gid")) {
1990061da546Spatrick         uint32_t gid = UINT32_MAX;
1991061da546Spatrick         value.getAsInteger(0, gid);
1992061da546Spatrick         process_info.SetGroupID(gid);
1993061da546Spatrick       } else if (name.equals("egid")) {
1994061da546Spatrick         uint32_t gid = UINT32_MAX;
1995061da546Spatrick         value.getAsInteger(0, gid);
1996061da546Spatrick         process_info.SetEffectiveGroupID(gid);
1997061da546Spatrick       } else if (name.equals("triple")) {
1998061da546Spatrick         StringExtractor extractor(value);
1999061da546Spatrick         std::string triple;
2000061da546Spatrick         extractor.GetHexByteString(triple);
2001061da546Spatrick         process_info.GetArchitecture().SetTriple(triple.c_str());
2002061da546Spatrick       } else if (name.equals("name")) {
2003061da546Spatrick         StringExtractor extractor(value);
2004061da546Spatrick         // The process name from ASCII hex bytes since we can't control the
2005061da546Spatrick         // characters in a process name
2006061da546Spatrick         std::string name;
2007061da546Spatrick         extractor.GetHexByteString(name);
2008061da546Spatrick         process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);
2009061da546Spatrick       } else if (name.equals("args")) {
2010061da546Spatrick         llvm::StringRef encoded_args(value), hex_arg;
2011061da546Spatrick 
2012061da546Spatrick         bool is_arg0 = true;
2013061da546Spatrick         while (!encoded_args.empty()) {
2014061da546Spatrick           std::tie(hex_arg, encoded_args) = encoded_args.split('-');
2015061da546Spatrick           std::string arg;
2016061da546Spatrick           StringExtractor extractor(hex_arg);
2017061da546Spatrick           if (extractor.GetHexByteString(arg) * 2 != hex_arg.size()) {
2018061da546Spatrick             // In case of wrong encoding, we discard all the arguments
2019061da546Spatrick             process_info.GetArguments().Clear();
2020061da546Spatrick             process_info.SetArg0("");
2021061da546Spatrick             break;
2022061da546Spatrick           }
2023061da546Spatrick           if (is_arg0)
2024061da546Spatrick             process_info.SetArg0(arg);
2025061da546Spatrick           else
2026061da546Spatrick             process_info.GetArguments().AppendArgument(arg);
2027061da546Spatrick           is_arg0 = false;
2028061da546Spatrick         }
2029061da546Spatrick       } else if (name.equals("cputype")) {
2030061da546Spatrick         value.getAsInteger(0, cpu);
2031061da546Spatrick       } else if (name.equals("cpusubtype")) {
2032061da546Spatrick         value.getAsInteger(0, sub);
2033061da546Spatrick       } else if (name.equals("vendor")) {
2034dda28197Spatrick         vendor = std::string(value);
2035061da546Spatrick       } else if (name.equals("ostype")) {
2036dda28197Spatrick         os_type = std::string(value);
2037061da546Spatrick       }
2038061da546Spatrick     }
2039061da546Spatrick 
2040061da546Spatrick     if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty()) {
2041061da546Spatrick       if (vendor == "apple") {
2042061da546Spatrick         process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu,
2043061da546Spatrick                                                        sub);
2044061da546Spatrick         process_info.GetArchitecture().GetTriple().setVendorName(
2045061da546Spatrick             llvm::StringRef(vendor));
2046061da546Spatrick         process_info.GetArchitecture().GetTriple().setOSName(
2047061da546Spatrick             llvm::StringRef(os_type));
2048061da546Spatrick       }
2049061da546Spatrick     }
2050061da546Spatrick 
2051061da546Spatrick     if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
2052061da546Spatrick       return true;
2053061da546Spatrick   }
2054061da546Spatrick   return false;
2055061da546Spatrick }
2056061da546Spatrick 
2057061da546Spatrick bool GDBRemoteCommunicationClient::GetProcessInfo(
2058061da546Spatrick     lldb::pid_t pid, ProcessInstanceInfo &process_info) {
2059061da546Spatrick   process_info.Clear();
2060061da546Spatrick 
2061061da546Spatrick   if (m_supports_qProcessInfoPID) {
2062061da546Spatrick     char packet[32];
2063061da546Spatrick     const int packet_len =
2064061da546Spatrick         ::snprintf(packet, sizeof(packet), "qProcessInfoPID:%" PRIu64, pid);
2065061da546Spatrick     assert(packet_len < (int)sizeof(packet));
2066061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
2067061da546Spatrick     StringExtractorGDBRemote response;
2068*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
2069061da546Spatrick         PacketResult::Success) {
2070061da546Spatrick       return DecodeProcessInfoResponse(response, process_info);
2071061da546Spatrick     } else {
2072061da546Spatrick       m_supports_qProcessInfoPID = false;
2073061da546Spatrick       return false;
2074061da546Spatrick     }
2075061da546Spatrick   }
2076061da546Spatrick   return false;
2077061da546Spatrick }
2078061da546Spatrick 
2079061da546Spatrick bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
2080061da546Spatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
2081061da546Spatrick                                                          GDBR_LOG_PACKETS));
2082061da546Spatrick 
2083061da546Spatrick   if (allow_lazy) {
2084061da546Spatrick     if (m_qProcessInfo_is_valid == eLazyBoolYes)
2085061da546Spatrick       return true;
2086061da546Spatrick     if (m_qProcessInfo_is_valid == eLazyBoolNo)
2087061da546Spatrick       return false;
2088061da546Spatrick   }
2089061da546Spatrick 
2090061da546Spatrick   GetHostInfo();
2091061da546Spatrick 
2092061da546Spatrick   StringExtractorGDBRemote response;
2093*be691f3bSpatrick   if (SendPacketAndWaitForResponse("qProcessInfo", response) ==
2094061da546Spatrick       PacketResult::Success) {
2095061da546Spatrick     if (response.IsNormalResponse()) {
2096061da546Spatrick       llvm::StringRef name;
2097061da546Spatrick       llvm::StringRef value;
2098061da546Spatrick       uint32_t cpu = LLDB_INVALID_CPUTYPE;
2099061da546Spatrick       uint32_t sub = 0;
2100061da546Spatrick       std::string arch_name;
2101061da546Spatrick       std::string os_name;
2102061da546Spatrick       std::string environment;
2103061da546Spatrick       std::string vendor_name;
2104061da546Spatrick       std::string triple;
2105061da546Spatrick       std::string elf_abi;
2106061da546Spatrick       uint32_t pointer_byte_size = 0;
2107061da546Spatrick       StringExtractor extractor;
2108061da546Spatrick       ByteOrder byte_order = eByteOrderInvalid;
2109061da546Spatrick       uint32_t num_keys_decoded = 0;
2110061da546Spatrick       lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
2111061da546Spatrick       while (response.GetNameColonValue(name, value)) {
2112061da546Spatrick         if (name.equals("cputype")) {
2113061da546Spatrick           if (!value.getAsInteger(16, cpu))
2114061da546Spatrick             ++num_keys_decoded;
2115061da546Spatrick         } else if (name.equals("cpusubtype")) {
2116061da546Spatrick           if (!value.getAsInteger(16, sub))
2117061da546Spatrick             ++num_keys_decoded;
2118061da546Spatrick         } else if (name.equals("triple")) {
2119061da546Spatrick           StringExtractor extractor(value);
2120061da546Spatrick           extractor.GetHexByteString(triple);
2121061da546Spatrick           ++num_keys_decoded;
2122061da546Spatrick         } else if (name.equals("ostype")) {
2123dda28197Spatrick           ParseOSType(value, os_name, environment);
2124061da546Spatrick           ++num_keys_decoded;
2125061da546Spatrick         } else if (name.equals("vendor")) {
2126dda28197Spatrick           vendor_name = std::string(value);
2127061da546Spatrick           ++num_keys_decoded;
2128061da546Spatrick         } else if (name.equals("endian")) {
2129061da546Spatrick           byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
2130061da546Spatrick                            .Case("little", eByteOrderLittle)
2131061da546Spatrick                            .Case("big", eByteOrderBig)
2132061da546Spatrick                            .Case("pdp", eByteOrderPDP)
2133061da546Spatrick                            .Default(eByteOrderInvalid);
2134061da546Spatrick           if (byte_order != eByteOrderInvalid)
2135061da546Spatrick             ++num_keys_decoded;
2136061da546Spatrick         } else if (name.equals("ptrsize")) {
2137061da546Spatrick           if (!value.getAsInteger(16, pointer_byte_size))
2138061da546Spatrick             ++num_keys_decoded;
2139061da546Spatrick         } else if (name.equals("pid")) {
2140061da546Spatrick           if (!value.getAsInteger(16, pid))
2141061da546Spatrick             ++num_keys_decoded;
2142061da546Spatrick         } else if (name.equals("elf_abi")) {
2143dda28197Spatrick           elf_abi = std::string(value);
2144061da546Spatrick           ++num_keys_decoded;
2145061da546Spatrick         }
2146061da546Spatrick       }
2147061da546Spatrick       if (num_keys_decoded > 0)
2148061da546Spatrick         m_qProcessInfo_is_valid = eLazyBoolYes;
2149061da546Spatrick       if (pid != LLDB_INVALID_PROCESS_ID) {
2150061da546Spatrick         m_curr_pid_is_valid = eLazyBoolYes;
2151*be691f3bSpatrick         m_curr_pid_run = m_curr_pid = pid;
2152061da546Spatrick       }
2153061da546Spatrick 
2154061da546Spatrick       // Set the ArchSpec from the triple if we have it.
2155061da546Spatrick       if (!triple.empty()) {
2156061da546Spatrick         m_process_arch.SetTriple(triple.c_str());
2157061da546Spatrick         m_process_arch.SetFlags(elf_abi);
2158061da546Spatrick         if (pointer_byte_size) {
2159061da546Spatrick           assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
2160061da546Spatrick         }
2161061da546Spatrick       } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() &&
2162061da546Spatrick                  !vendor_name.empty()) {
2163061da546Spatrick         llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name);
2164061da546Spatrick         if (!environment.empty())
2165061da546Spatrick             triple.setEnvironmentName(environment);
2166061da546Spatrick 
2167061da546Spatrick         assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat);
2168061da546Spatrick         assert(triple.getObjectFormat() != llvm::Triple::Wasm);
2169061da546Spatrick         assert(triple.getObjectFormat() != llvm::Triple::XCOFF);
2170061da546Spatrick         switch (triple.getObjectFormat()) {
2171061da546Spatrick         case llvm::Triple::MachO:
2172061da546Spatrick           m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
2173061da546Spatrick           break;
2174061da546Spatrick         case llvm::Triple::ELF:
2175061da546Spatrick           m_process_arch.SetArchitecture(eArchTypeELF, cpu, sub);
2176061da546Spatrick           break;
2177061da546Spatrick         case llvm::Triple::COFF:
2178061da546Spatrick           m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub);
2179061da546Spatrick           break;
2180*be691f3bSpatrick         case llvm::Triple::GOFF:
2181061da546Spatrick         case llvm::Triple::Wasm:
2182061da546Spatrick         case llvm::Triple::XCOFF:
2183061da546Spatrick           LLDB_LOGF(log, "error: not supported target architecture");
2184061da546Spatrick           return false;
2185061da546Spatrick         case llvm::Triple::UnknownObjectFormat:
2186061da546Spatrick           LLDB_LOGF(log, "error: failed to determine target architecture");
2187061da546Spatrick           return false;
2188061da546Spatrick         }
2189061da546Spatrick 
2190061da546Spatrick         if (pointer_byte_size) {
2191061da546Spatrick           assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
2192061da546Spatrick         }
2193061da546Spatrick         if (byte_order != eByteOrderInvalid) {
2194061da546Spatrick           assert(byte_order == m_process_arch.GetByteOrder());
2195061da546Spatrick         }
2196061da546Spatrick         m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name));
2197061da546Spatrick         m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name));
2198061da546Spatrick         m_process_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment));
2199061da546Spatrick         m_host_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name));
2200061da546Spatrick         m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name));
2201061da546Spatrick         m_host_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment));
2202061da546Spatrick       }
2203061da546Spatrick       return true;
2204061da546Spatrick     }
2205061da546Spatrick   } else {
2206061da546Spatrick     m_qProcessInfo_is_valid = eLazyBoolNo;
2207061da546Spatrick   }
2208061da546Spatrick 
2209061da546Spatrick   return false;
2210061da546Spatrick }
2211061da546Spatrick 
2212061da546Spatrick uint32_t GDBRemoteCommunicationClient::FindProcesses(
2213061da546Spatrick     const ProcessInstanceInfoMatch &match_info,
2214061da546Spatrick     ProcessInstanceInfoList &process_infos) {
2215dda28197Spatrick   process_infos.clear();
2216061da546Spatrick 
2217061da546Spatrick   if (m_supports_qfProcessInfo) {
2218061da546Spatrick     StreamString packet;
2219061da546Spatrick     packet.PutCString("qfProcessInfo");
2220061da546Spatrick     if (!match_info.MatchAllProcesses()) {
2221061da546Spatrick       packet.PutChar(':');
2222061da546Spatrick       const char *name = match_info.GetProcessInfo().GetName();
2223061da546Spatrick       bool has_name_match = false;
2224061da546Spatrick       if (name && name[0]) {
2225061da546Spatrick         has_name_match = true;
2226061da546Spatrick         NameMatch name_match_type = match_info.GetNameMatchType();
2227061da546Spatrick         switch (name_match_type) {
2228061da546Spatrick         case NameMatch::Ignore:
2229061da546Spatrick           has_name_match = false;
2230061da546Spatrick           break;
2231061da546Spatrick 
2232061da546Spatrick         case NameMatch::Equals:
2233061da546Spatrick           packet.PutCString("name_match:equals;");
2234061da546Spatrick           break;
2235061da546Spatrick 
2236061da546Spatrick         case NameMatch::Contains:
2237061da546Spatrick           packet.PutCString("name_match:contains;");
2238061da546Spatrick           break;
2239061da546Spatrick 
2240061da546Spatrick         case NameMatch::StartsWith:
2241061da546Spatrick           packet.PutCString("name_match:starts_with;");
2242061da546Spatrick           break;
2243061da546Spatrick 
2244061da546Spatrick         case NameMatch::EndsWith:
2245061da546Spatrick           packet.PutCString("name_match:ends_with;");
2246061da546Spatrick           break;
2247061da546Spatrick 
2248061da546Spatrick         case NameMatch::RegularExpression:
2249061da546Spatrick           packet.PutCString("name_match:regex;");
2250061da546Spatrick           break;
2251061da546Spatrick         }
2252061da546Spatrick         if (has_name_match) {
2253061da546Spatrick           packet.PutCString("name:");
2254061da546Spatrick           packet.PutBytesAsRawHex8(name, ::strlen(name));
2255061da546Spatrick           packet.PutChar(';');
2256061da546Spatrick         }
2257061da546Spatrick       }
2258061da546Spatrick 
2259061da546Spatrick       if (match_info.GetProcessInfo().ProcessIDIsValid())
2260061da546Spatrick         packet.Printf("pid:%" PRIu64 ";",
2261061da546Spatrick                       match_info.GetProcessInfo().GetProcessID());
2262061da546Spatrick       if (match_info.GetProcessInfo().ParentProcessIDIsValid())
2263061da546Spatrick         packet.Printf("parent_pid:%" PRIu64 ";",
2264061da546Spatrick                       match_info.GetProcessInfo().GetParentProcessID());
2265061da546Spatrick       if (match_info.GetProcessInfo().UserIDIsValid())
2266061da546Spatrick         packet.Printf("uid:%u;", match_info.GetProcessInfo().GetUserID());
2267061da546Spatrick       if (match_info.GetProcessInfo().GroupIDIsValid())
2268061da546Spatrick         packet.Printf("gid:%u;", match_info.GetProcessInfo().GetGroupID());
2269061da546Spatrick       if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
2270061da546Spatrick         packet.Printf("euid:%u;",
2271061da546Spatrick                       match_info.GetProcessInfo().GetEffectiveUserID());
2272061da546Spatrick       if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
2273061da546Spatrick         packet.Printf("egid:%u;",
2274061da546Spatrick                       match_info.GetProcessInfo().GetEffectiveGroupID());
2275061da546Spatrick       packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0);
2276061da546Spatrick       if (match_info.GetProcessInfo().GetArchitecture().IsValid()) {
2277061da546Spatrick         const ArchSpec &match_arch =
2278061da546Spatrick             match_info.GetProcessInfo().GetArchitecture();
2279061da546Spatrick         const llvm::Triple &triple = match_arch.GetTriple();
2280061da546Spatrick         packet.PutCString("triple:");
2281061da546Spatrick         packet.PutCString(triple.getTriple());
2282061da546Spatrick         packet.PutChar(';');
2283061da546Spatrick       }
2284061da546Spatrick     }
2285061da546Spatrick     StringExtractorGDBRemote response;
2286061da546Spatrick     // Increase timeout as the first qfProcessInfo packet takes a long time on
2287061da546Spatrick     // Android. The value of 1min was arrived at empirically.
2288061da546Spatrick     ScopedTimeout timeout(*this, minutes(1));
2289*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
2290061da546Spatrick         PacketResult::Success) {
2291061da546Spatrick       do {
2292061da546Spatrick         ProcessInstanceInfo process_info;
2293061da546Spatrick         if (!DecodeProcessInfoResponse(response, process_info))
2294061da546Spatrick           break;
2295dda28197Spatrick         process_infos.push_back(process_info);
2296061da546Spatrick         response = StringExtractorGDBRemote();
2297*be691f3bSpatrick       } while (SendPacketAndWaitForResponse("qsProcessInfo", response) ==
2298061da546Spatrick                PacketResult::Success);
2299061da546Spatrick     } else {
2300061da546Spatrick       m_supports_qfProcessInfo = false;
2301061da546Spatrick       return 0;
2302061da546Spatrick     }
2303061da546Spatrick   }
2304dda28197Spatrick   return process_infos.size();
2305061da546Spatrick }
2306061da546Spatrick 
2307061da546Spatrick bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
2308061da546Spatrick                                                std::string &name) {
2309061da546Spatrick   if (m_supports_qUserName) {
2310061da546Spatrick     char packet[32];
2311061da546Spatrick     const int packet_len =
2312061da546Spatrick         ::snprintf(packet, sizeof(packet), "qUserName:%i", uid);
2313061da546Spatrick     assert(packet_len < (int)sizeof(packet));
2314061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
2315061da546Spatrick     StringExtractorGDBRemote response;
2316*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
2317061da546Spatrick         PacketResult::Success) {
2318061da546Spatrick       if (response.IsNormalResponse()) {
2319061da546Spatrick         // Make sure we parsed the right number of characters. The response is
2320061da546Spatrick         // the hex encoded user name and should make up the entire packet. If
2321061da546Spatrick         // there are any non-hex ASCII bytes, the length won't match below..
2322061da546Spatrick         if (response.GetHexByteString(name) * 2 ==
2323061da546Spatrick             response.GetStringRef().size())
2324061da546Spatrick           return true;
2325061da546Spatrick       }
2326061da546Spatrick     } else {
2327061da546Spatrick       m_supports_qUserName = false;
2328061da546Spatrick       return false;
2329061da546Spatrick     }
2330061da546Spatrick   }
2331061da546Spatrick   return false;
2332061da546Spatrick }
2333061da546Spatrick 
2334061da546Spatrick bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
2335061da546Spatrick                                                 std::string &name) {
2336061da546Spatrick   if (m_supports_qGroupName) {
2337061da546Spatrick     char packet[32];
2338061da546Spatrick     const int packet_len =
2339061da546Spatrick         ::snprintf(packet, sizeof(packet), "qGroupName:%i", gid);
2340061da546Spatrick     assert(packet_len < (int)sizeof(packet));
2341061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
2342061da546Spatrick     StringExtractorGDBRemote response;
2343*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
2344061da546Spatrick         PacketResult::Success) {
2345061da546Spatrick       if (response.IsNormalResponse()) {
2346061da546Spatrick         // Make sure we parsed the right number of characters. The response is
2347061da546Spatrick         // the hex encoded group name and should make up the entire packet. If
2348061da546Spatrick         // there are any non-hex ASCII bytes, the length won't match below..
2349061da546Spatrick         if (response.GetHexByteString(name) * 2 ==
2350061da546Spatrick             response.GetStringRef().size())
2351061da546Spatrick           return true;
2352061da546Spatrick       }
2353061da546Spatrick     } else {
2354061da546Spatrick       m_supports_qGroupName = false;
2355061da546Spatrick       return false;
2356061da546Spatrick     }
2357061da546Spatrick   }
2358061da546Spatrick   return false;
2359061da546Spatrick }
2360061da546Spatrick 
2361061da546Spatrick bool GDBRemoteCommunicationClient::SetNonStopMode(const bool enable) {
2362061da546Spatrick   // Form non-stop packet request
2363061da546Spatrick   char packet[32];
2364061da546Spatrick   const int packet_len =
2365061da546Spatrick       ::snprintf(packet, sizeof(packet), "QNonStop:%1d", (int)enable);
2366061da546Spatrick   assert(packet_len < (int)sizeof(packet));
2367061da546Spatrick   UNUSED_IF_ASSERT_DISABLED(packet_len);
2368061da546Spatrick 
2369061da546Spatrick   StringExtractorGDBRemote response;
2370061da546Spatrick   // Send to target
2371*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success)
2372061da546Spatrick     if (response.IsOKResponse())
2373061da546Spatrick       return true;
2374061da546Spatrick 
2375061da546Spatrick   // Failed or not supported
2376061da546Spatrick   return false;
2377061da546Spatrick }
2378061da546Spatrick 
2379061da546Spatrick static void MakeSpeedTestPacket(StreamString &packet, uint32_t send_size,
2380061da546Spatrick                                 uint32_t recv_size) {
2381061da546Spatrick   packet.Clear();
2382061da546Spatrick   packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
2383061da546Spatrick   uint32_t bytes_left = send_size;
2384061da546Spatrick   while (bytes_left > 0) {
2385061da546Spatrick     if (bytes_left >= 26) {
2386061da546Spatrick       packet.PutCString("abcdefghijklmnopqrstuvwxyz");
2387061da546Spatrick       bytes_left -= 26;
2388061da546Spatrick     } else {
2389061da546Spatrick       packet.Printf("%*.*s;", bytes_left, bytes_left,
2390061da546Spatrick                     "abcdefghijklmnopqrstuvwxyz");
2391061da546Spatrick       bytes_left = 0;
2392061da546Spatrick     }
2393061da546Spatrick   }
2394061da546Spatrick }
2395061da546Spatrick 
2396061da546Spatrick duration<float>
2397061da546Spatrick calculate_standard_deviation(const std::vector<duration<float>> &v) {
2398061da546Spatrick   using Dur = duration<float>;
2399061da546Spatrick   Dur sum = std::accumulate(std::begin(v), std::end(v), Dur());
2400061da546Spatrick   Dur mean = sum / v.size();
2401061da546Spatrick   float accum = 0;
2402061da546Spatrick   for (auto d : v) {
2403061da546Spatrick     float delta = (d - mean).count();
2404061da546Spatrick     accum += delta * delta;
2405061da546Spatrick   };
2406061da546Spatrick 
2407061da546Spatrick   return Dur(sqrtf(accum / (v.size() - 1)));
2408061da546Spatrick }
2409061da546Spatrick 
2410061da546Spatrick void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
2411061da546Spatrick                                                    uint32_t max_send,
2412061da546Spatrick                                                    uint32_t max_recv,
2413061da546Spatrick                                                    uint64_t recv_amount,
2414061da546Spatrick                                                    bool json, Stream &strm) {
2415061da546Spatrick   uint32_t i;
2416061da546Spatrick   if (SendSpeedTestPacket(0, 0)) {
2417061da546Spatrick     StreamString packet;
2418061da546Spatrick     if (json)
2419061da546Spatrick       strm.Printf("{ \"packet_speeds\" : {\n    \"num_packets\" : %u,\n    "
2420061da546Spatrick                   "\"results\" : [",
2421061da546Spatrick                   num_packets);
2422061da546Spatrick     else
2423061da546Spatrick       strm.Printf("Testing sending %u packets of various sizes:\n",
2424061da546Spatrick                   num_packets);
2425061da546Spatrick     strm.Flush();
2426061da546Spatrick 
2427061da546Spatrick     uint32_t result_idx = 0;
2428061da546Spatrick     uint32_t send_size;
2429061da546Spatrick     std::vector<duration<float>> packet_times;
2430061da546Spatrick 
2431061da546Spatrick     for (send_size = 0; send_size <= max_send;
2432061da546Spatrick          send_size ? send_size *= 2 : send_size = 4) {
2433061da546Spatrick       for (uint32_t recv_size = 0; recv_size <= max_recv;
2434061da546Spatrick            recv_size ? recv_size *= 2 : recv_size = 4) {
2435061da546Spatrick         MakeSpeedTestPacket(packet, send_size, recv_size);
2436061da546Spatrick 
2437061da546Spatrick         packet_times.clear();
2438061da546Spatrick         // Test how long it takes to send 'num_packets' packets
2439061da546Spatrick         const auto start_time = steady_clock::now();
2440061da546Spatrick         for (i = 0; i < num_packets; ++i) {
2441061da546Spatrick           const auto packet_start_time = steady_clock::now();
2442061da546Spatrick           StringExtractorGDBRemote response;
2443*be691f3bSpatrick           SendPacketAndWaitForResponse(packet.GetString(), response);
2444061da546Spatrick           const auto packet_end_time = steady_clock::now();
2445061da546Spatrick           packet_times.push_back(packet_end_time - packet_start_time);
2446061da546Spatrick         }
2447061da546Spatrick         const auto end_time = steady_clock::now();
2448061da546Spatrick         const auto total_time = end_time - start_time;
2449061da546Spatrick 
2450061da546Spatrick         float packets_per_second =
2451061da546Spatrick             ((float)num_packets) / duration<float>(total_time).count();
2452061da546Spatrick         auto average_per_packet = total_time / num_packets;
2453061da546Spatrick         const duration<float> standard_deviation =
2454061da546Spatrick             calculate_standard_deviation(packet_times);
2455061da546Spatrick         if (json) {
2456061da546Spatrick           strm.Format("{0}\n     {{\"send_size\" : {1,6}, \"recv_size\" : "
2457061da546Spatrick                       "{2,6}, \"total_time_nsec\" : {3,12:ns-}, "
2458061da546Spatrick                       "\"standard_deviation_nsec\" : {4,9:ns-f0}}",
2459061da546Spatrick                       result_idx > 0 ? "," : "", send_size, recv_size,
2460061da546Spatrick                       total_time, standard_deviation);
2461061da546Spatrick           ++result_idx;
2462061da546Spatrick         } else {
2463061da546Spatrick           strm.Format("qSpeedTest(send={0,7}, recv={1,7}) in {2:s+f9} for "
2464061da546Spatrick                       "{3,9:f2} packets/s ({4,10:ms+f6} per packet) with "
2465061da546Spatrick                       "standard deviation of {5,10:ms+f6}\n",
2466061da546Spatrick                       send_size, recv_size, duration<float>(total_time),
2467061da546Spatrick                       packets_per_second, duration<float>(average_per_packet),
2468061da546Spatrick                       standard_deviation);
2469061da546Spatrick         }
2470061da546Spatrick         strm.Flush();
2471061da546Spatrick       }
2472061da546Spatrick     }
2473061da546Spatrick 
2474061da546Spatrick     const float k_recv_amount_mb = (float)recv_amount / (1024.0f * 1024.0f);
2475061da546Spatrick     if (json)
2476061da546Spatrick       strm.Printf("\n    ]\n  },\n  \"download_speed\" : {\n    \"byte_size\" "
2477061da546Spatrick                   ": %" PRIu64 ",\n    \"results\" : [",
2478061da546Spatrick                   recv_amount);
2479061da546Spatrick     else
2480061da546Spatrick       strm.Printf("Testing receiving %2.1fMB of data using varying receive "
2481061da546Spatrick                   "packet sizes:\n",
2482061da546Spatrick                   k_recv_amount_mb);
2483061da546Spatrick     strm.Flush();
2484061da546Spatrick     send_size = 0;
2485061da546Spatrick     result_idx = 0;
2486061da546Spatrick     for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) {
2487061da546Spatrick       MakeSpeedTestPacket(packet, send_size, recv_size);
2488061da546Spatrick 
2489061da546Spatrick       // If we have a receive size, test how long it takes to receive 4MB of
2490061da546Spatrick       // data
2491061da546Spatrick       if (recv_size > 0) {
2492061da546Spatrick         const auto start_time = steady_clock::now();
2493061da546Spatrick         uint32_t bytes_read = 0;
2494061da546Spatrick         uint32_t packet_count = 0;
2495061da546Spatrick         while (bytes_read < recv_amount) {
2496061da546Spatrick           StringExtractorGDBRemote response;
2497*be691f3bSpatrick           SendPacketAndWaitForResponse(packet.GetString(), response);
2498061da546Spatrick           bytes_read += recv_size;
2499061da546Spatrick           ++packet_count;
2500061da546Spatrick         }
2501061da546Spatrick         const auto end_time = steady_clock::now();
2502061da546Spatrick         const auto total_time = end_time - start_time;
2503061da546Spatrick         float mb_second = ((float)recv_amount) /
2504061da546Spatrick                           duration<float>(total_time).count() /
2505061da546Spatrick                           (1024.0 * 1024.0);
2506061da546Spatrick         float packets_per_second =
2507061da546Spatrick             ((float)packet_count) / duration<float>(total_time).count();
2508061da546Spatrick         const auto average_per_packet = total_time / packet_count;
2509061da546Spatrick 
2510061da546Spatrick         if (json) {
2511061da546Spatrick           strm.Format("{0}\n     {{\"send_size\" : {1,6}, \"recv_size\" : "
2512061da546Spatrick                       "{2,6}, \"total_time_nsec\" : {3,12:ns-}}",
2513061da546Spatrick                       result_idx > 0 ? "," : "", send_size, recv_size,
2514061da546Spatrick                       total_time);
2515061da546Spatrick           ++result_idx;
2516061da546Spatrick         } else {
2517061da546Spatrick           strm.Format("qSpeedTest(send={0,7}, recv={1,7}) {2,6} packets needed "
2518061da546Spatrick                       "to receive {3:f1}MB in {4:s+f9} for {5} MB/sec for "
2519061da546Spatrick                       "{6,9:f2} packets/sec ({7,10:ms+f6} per packet)\n",
2520061da546Spatrick                       send_size, recv_size, packet_count, k_recv_amount_mb,
2521061da546Spatrick                       duration<float>(total_time), mb_second,
2522061da546Spatrick                       packets_per_second, duration<float>(average_per_packet));
2523061da546Spatrick         }
2524061da546Spatrick         strm.Flush();
2525061da546Spatrick       }
2526061da546Spatrick     }
2527061da546Spatrick     if (json)
2528061da546Spatrick       strm.Printf("\n    ]\n  }\n}\n");
2529061da546Spatrick     else
2530061da546Spatrick       strm.EOL();
2531061da546Spatrick   }
2532061da546Spatrick }
2533061da546Spatrick 
2534061da546Spatrick bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size,
2535061da546Spatrick                                                        uint32_t recv_size) {
2536061da546Spatrick   StreamString packet;
2537061da546Spatrick   packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
2538061da546Spatrick   uint32_t bytes_left = send_size;
2539061da546Spatrick   while (bytes_left > 0) {
2540061da546Spatrick     if (bytes_left >= 26) {
2541061da546Spatrick       packet.PutCString("abcdefghijklmnopqrstuvwxyz");
2542061da546Spatrick       bytes_left -= 26;
2543061da546Spatrick     } else {
2544061da546Spatrick       packet.Printf("%*.*s;", bytes_left, bytes_left,
2545061da546Spatrick                     "abcdefghijklmnopqrstuvwxyz");
2546061da546Spatrick       bytes_left = 0;
2547061da546Spatrick     }
2548061da546Spatrick   }
2549061da546Spatrick 
2550061da546Spatrick   StringExtractorGDBRemote response;
2551*be691f3bSpatrick   return SendPacketAndWaitForResponse(packet.GetString(), response) ==
2552061da546Spatrick          PacketResult::Success;
2553061da546Spatrick }
2554061da546Spatrick 
2555061da546Spatrick bool GDBRemoteCommunicationClient::LaunchGDBServer(
2556061da546Spatrick     const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port,
2557061da546Spatrick     std::string &socket_name) {
2558061da546Spatrick   pid = LLDB_INVALID_PROCESS_ID;
2559061da546Spatrick   port = 0;
2560061da546Spatrick   socket_name.clear();
2561061da546Spatrick 
2562061da546Spatrick   StringExtractorGDBRemote response;
2563061da546Spatrick   StreamString stream;
2564061da546Spatrick   stream.PutCString("qLaunchGDBServer;");
2565061da546Spatrick   std::string hostname;
2566061da546Spatrick   if (remote_accept_hostname && remote_accept_hostname[0])
2567061da546Spatrick     hostname = remote_accept_hostname;
2568061da546Spatrick   else {
2569061da546Spatrick     if (HostInfo::GetHostname(hostname)) {
2570061da546Spatrick       // Make the GDB server we launch only accept connections from this host
2571061da546Spatrick       stream.Printf("host:%s;", hostname.c_str());
2572061da546Spatrick     } else {
2573061da546Spatrick       // Make the GDB server we launch accept connections from any host since
2574061da546Spatrick       // we can't figure out the hostname
2575061da546Spatrick       stream.Printf("host:*;");
2576061da546Spatrick     }
2577061da546Spatrick   }
2578061da546Spatrick   // give the process a few seconds to startup
2579061da546Spatrick   ScopedTimeout timeout(*this, seconds(10));
2580061da546Spatrick 
2581*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
2582061da546Spatrick       PacketResult::Success) {
2583061da546Spatrick     llvm::StringRef name;
2584061da546Spatrick     llvm::StringRef value;
2585061da546Spatrick     while (response.GetNameColonValue(name, value)) {
2586061da546Spatrick       if (name.equals("port"))
2587061da546Spatrick         value.getAsInteger(0, port);
2588061da546Spatrick       else if (name.equals("pid"))
2589061da546Spatrick         value.getAsInteger(0, pid);
2590061da546Spatrick       else if (name.compare("socket_name") == 0) {
2591061da546Spatrick         StringExtractor extractor(value);
2592061da546Spatrick         extractor.GetHexByteString(socket_name);
2593061da546Spatrick       }
2594061da546Spatrick     }
2595061da546Spatrick     return true;
2596061da546Spatrick   }
2597061da546Spatrick   return false;
2598061da546Spatrick }
2599061da546Spatrick 
2600061da546Spatrick size_t GDBRemoteCommunicationClient::QueryGDBServer(
2601061da546Spatrick     std::vector<std::pair<uint16_t, std::string>> &connection_urls) {
2602061da546Spatrick   connection_urls.clear();
2603061da546Spatrick 
2604061da546Spatrick   StringExtractorGDBRemote response;
2605*be691f3bSpatrick   if (SendPacketAndWaitForResponse("qQueryGDBServer", response) !=
2606061da546Spatrick       PacketResult::Success)
2607061da546Spatrick     return 0;
2608061da546Spatrick 
2609061da546Spatrick   StructuredData::ObjectSP data =
2610dda28197Spatrick       StructuredData::ParseJSON(std::string(response.GetStringRef()));
2611061da546Spatrick   if (!data)
2612061da546Spatrick     return 0;
2613061da546Spatrick 
2614061da546Spatrick   StructuredData::Array *array = data->GetAsArray();
2615061da546Spatrick   if (!array)
2616061da546Spatrick     return 0;
2617061da546Spatrick 
2618061da546Spatrick   for (size_t i = 0, count = array->GetSize(); i < count; ++i) {
2619061da546Spatrick     StructuredData::Dictionary *element = nullptr;
2620061da546Spatrick     if (!array->GetItemAtIndexAsDictionary(i, element))
2621061da546Spatrick       continue;
2622061da546Spatrick 
2623061da546Spatrick     uint16_t port = 0;
2624061da546Spatrick     if (StructuredData::ObjectSP port_osp =
2625061da546Spatrick             element->GetValueForKey(llvm::StringRef("port")))
2626061da546Spatrick       port = port_osp->GetIntegerValue(0);
2627061da546Spatrick 
2628061da546Spatrick     std::string socket_name;
2629061da546Spatrick     if (StructuredData::ObjectSP socket_name_osp =
2630061da546Spatrick             element->GetValueForKey(llvm::StringRef("socket_name")))
2631dda28197Spatrick       socket_name = std::string(socket_name_osp->GetStringValue());
2632061da546Spatrick 
2633061da546Spatrick     if (port != 0 || !socket_name.empty())
2634061da546Spatrick       connection_urls.emplace_back(port, socket_name);
2635061da546Spatrick   }
2636061da546Spatrick   return connection_urls.size();
2637061da546Spatrick }
2638061da546Spatrick 
2639061da546Spatrick bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) {
2640061da546Spatrick   StreamString stream;
2641061da546Spatrick   stream.Printf("qKillSpawnedProcess:%" PRId64, pid);
2642061da546Spatrick 
2643061da546Spatrick   StringExtractorGDBRemote response;
2644*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
2645061da546Spatrick       PacketResult::Success) {
2646061da546Spatrick     if (response.IsOKResponse())
2647061da546Spatrick       return true;
2648061da546Spatrick   }
2649061da546Spatrick   return false;
2650061da546Spatrick }
2651061da546Spatrick 
2652*be691f3bSpatrick llvm::Optional<PidTid>
2653*be691f3bSpatrick GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid,
2654*be691f3bSpatrick                                                          uint64_t pid,
2655*be691f3bSpatrick                                                          char op) {
2656*be691f3bSpatrick   lldb_private::StreamString packet;
2657*be691f3bSpatrick   packet.PutChar('H');
2658*be691f3bSpatrick   packet.PutChar(op);
2659061da546Spatrick 
2660*be691f3bSpatrick   if (pid != LLDB_INVALID_PROCESS_ID)
2661*be691f3bSpatrick     packet.Printf("p%" PRIx64 ".", pid);
2662*be691f3bSpatrick 
2663061da546Spatrick   if (tid == UINT64_MAX)
2664*be691f3bSpatrick     packet.PutCString("-1");
2665061da546Spatrick   else
2666*be691f3bSpatrick     packet.Printf("%" PRIx64, tid);
2667*be691f3bSpatrick 
2668061da546Spatrick   StringExtractorGDBRemote response;
2669*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response)
2670*be691f3bSpatrick       == PacketResult::Success) {
2671*be691f3bSpatrick     if (response.IsOKResponse())
2672*be691f3bSpatrick       return {{pid, tid}};
2673061da546Spatrick 
2674061da546Spatrick     /*
2675061da546Spatrick      * Connected bare-iron target (like YAMON gdb-stub) may not have support for
2676061da546Spatrick      * Hg packet.
2677061da546Spatrick      * The reply from '?' packet could be as simple as 'S05'. There is no packet
2678061da546Spatrick      * which can
2679061da546Spatrick      * give us pid and/or tid. Assume pid=tid=1 in such cases.
2680061da546Spatrick      */
2681*be691f3bSpatrick     if (response.IsUnsupportedResponse() && IsConnected())
2682*be691f3bSpatrick       return {{1, 1}};
2683061da546Spatrick   }
2684*be691f3bSpatrick   return llvm::None;
2685061da546Spatrick }
2686061da546Spatrick 
2687*be691f3bSpatrick bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid,
2688*be691f3bSpatrick                                                     uint64_t pid) {
2689*be691f3bSpatrick   if (m_curr_tid == tid &&
2690*be691f3bSpatrick       (m_curr_pid == pid || LLDB_INVALID_PROCESS_ID == pid))
2691061da546Spatrick     return true;
2692061da546Spatrick 
2693*be691f3bSpatrick   llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'g');
2694*be691f3bSpatrick   if (ret.hasValue()) {
2695*be691f3bSpatrick     if (ret->pid != LLDB_INVALID_PROCESS_ID)
2696*be691f3bSpatrick       m_curr_pid = ret->pid;
2697*be691f3bSpatrick     m_curr_tid = ret->tid;
2698*be691f3bSpatrick   }
2699*be691f3bSpatrick   return ret.hasValue();
2700061da546Spatrick }
2701061da546Spatrick 
2702*be691f3bSpatrick bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid,
2703*be691f3bSpatrick                                                           uint64_t pid) {
2704*be691f3bSpatrick   if (m_curr_tid_run == tid &&
2705*be691f3bSpatrick       (m_curr_pid_run == pid || LLDB_INVALID_PROCESS_ID == pid))
2706061da546Spatrick     return true;
2707*be691f3bSpatrick 
2708*be691f3bSpatrick   llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'c');
2709*be691f3bSpatrick   if (ret.hasValue()) {
2710*be691f3bSpatrick     if (ret->pid != LLDB_INVALID_PROCESS_ID)
2711*be691f3bSpatrick       m_curr_pid_run = ret->pid;
2712*be691f3bSpatrick     m_curr_tid_run = ret->tid;
2713061da546Spatrick   }
2714*be691f3bSpatrick   return ret.hasValue();
2715061da546Spatrick }
2716061da546Spatrick 
2717061da546Spatrick bool GDBRemoteCommunicationClient::GetStopReply(
2718061da546Spatrick     StringExtractorGDBRemote &response) {
2719*be691f3bSpatrick   if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success)
2720061da546Spatrick     return response.IsNormalResponse();
2721061da546Spatrick   return false;
2722061da546Spatrick }
2723061da546Spatrick 
2724061da546Spatrick bool GDBRemoteCommunicationClient::GetThreadStopInfo(
2725061da546Spatrick     lldb::tid_t tid, StringExtractorGDBRemote &response) {
2726061da546Spatrick   if (m_supports_qThreadStopInfo) {
2727061da546Spatrick     char packet[256];
2728061da546Spatrick     int packet_len =
2729061da546Spatrick         ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
2730061da546Spatrick     assert(packet_len < (int)sizeof(packet));
2731061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(packet_len);
2732*be691f3bSpatrick     if (SendPacketAndWaitForResponse(packet, response) ==
2733061da546Spatrick         PacketResult::Success) {
2734061da546Spatrick       if (response.IsUnsupportedResponse())
2735061da546Spatrick         m_supports_qThreadStopInfo = false;
2736061da546Spatrick       else if (response.IsNormalResponse())
2737061da546Spatrick         return true;
2738061da546Spatrick       else
2739061da546Spatrick         return false;
2740061da546Spatrick     } else {
2741061da546Spatrick       m_supports_qThreadStopInfo = false;
2742061da546Spatrick     }
2743061da546Spatrick   }
2744061da546Spatrick   return false;
2745061da546Spatrick }
2746061da546Spatrick 
2747061da546Spatrick uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
2748*be691f3bSpatrick     GDBStoppointType type, bool insert, addr_t addr, uint32_t length,
2749*be691f3bSpatrick     std::chrono::seconds timeout) {
2750061da546Spatrick   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
2751061da546Spatrick   LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
2752061da546Spatrick             __FUNCTION__, insert ? "add" : "remove", addr);
2753061da546Spatrick 
2754061da546Spatrick   // Check if the stub is known not to support this breakpoint type
2755061da546Spatrick   if (!SupportsGDBStoppointPacket(type))
2756061da546Spatrick     return UINT8_MAX;
2757061da546Spatrick   // Construct the breakpoint packet
2758061da546Spatrick   char packet[64];
2759061da546Spatrick   const int packet_len =
2760061da546Spatrick       ::snprintf(packet, sizeof(packet), "%c%i,%" PRIx64 ",%x",
2761061da546Spatrick                  insert ? 'Z' : 'z', type, addr, length);
2762061da546Spatrick   // Check we haven't overwritten the end of the packet buffer
2763061da546Spatrick   assert(packet_len + 1 < (int)sizeof(packet));
2764061da546Spatrick   UNUSED_IF_ASSERT_DISABLED(packet_len);
2765061da546Spatrick   StringExtractorGDBRemote response;
2766061da546Spatrick   // Make sure the response is either "OK", "EXX" where XX are two hex digits,
2767061da546Spatrick   // or "" (unsupported)
2768061da546Spatrick   response.SetResponseValidatorToOKErrorNotSupported();
2769061da546Spatrick   // Try to send the breakpoint packet, and check that it was correctly sent
2770*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response, timeout) ==
2771061da546Spatrick       PacketResult::Success) {
2772061da546Spatrick     // Receive and OK packet when the breakpoint successfully placed
2773061da546Spatrick     if (response.IsOKResponse())
2774061da546Spatrick       return 0;
2775061da546Spatrick 
2776061da546Spatrick     // Status while setting breakpoint, send back specific error
2777061da546Spatrick     if (response.IsErrorResponse())
2778061da546Spatrick       return response.GetError();
2779061da546Spatrick 
2780061da546Spatrick     // Empty packet informs us that breakpoint is not supported
2781061da546Spatrick     if (response.IsUnsupportedResponse()) {
2782061da546Spatrick       // Disable this breakpoint type since it is unsupported
2783061da546Spatrick       switch (type) {
2784061da546Spatrick       case eBreakpointSoftware:
2785061da546Spatrick         m_supports_z0 = false;
2786061da546Spatrick         break;
2787061da546Spatrick       case eBreakpointHardware:
2788061da546Spatrick         m_supports_z1 = false;
2789061da546Spatrick         break;
2790061da546Spatrick       case eWatchpointWrite:
2791061da546Spatrick         m_supports_z2 = false;
2792061da546Spatrick         break;
2793061da546Spatrick       case eWatchpointRead:
2794061da546Spatrick         m_supports_z3 = false;
2795061da546Spatrick         break;
2796061da546Spatrick       case eWatchpointReadWrite:
2797061da546Spatrick         m_supports_z4 = false;
2798061da546Spatrick         break;
2799061da546Spatrick       case eStoppointInvalid:
2800061da546Spatrick         return UINT8_MAX;
2801061da546Spatrick       }
2802061da546Spatrick     }
2803061da546Spatrick   }
2804061da546Spatrick   // Signal generic failure
2805061da546Spatrick   return UINT8_MAX;
2806061da546Spatrick }
2807061da546Spatrick 
2808*be691f3bSpatrick std::vector<std::pair<lldb::pid_t, lldb::tid_t>>
2809*be691f3bSpatrick GDBRemoteCommunicationClient::GetCurrentProcessAndThreadIDs(
2810*be691f3bSpatrick     bool &sequence_mutex_unavailable) {
2811*be691f3bSpatrick   std::vector<std::pair<lldb::pid_t, lldb::tid_t>> ids;
2812061da546Spatrick 
2813*be691f3bSpatrick   Lock lock(*this);
2814061da546Spatrick   if (lock) {
2815061da546Spatrick     sequence_mutex_unavailable = false;
2816061da546Spatrick     StringExtractorGDBRemote response;
2817061da546Spatrick 
2818061da546Spatrick     PacketResult packet_result;
2819061da546Spatrick     for (packet_result =
2820061da546Spatrick              SendPacketAndWaitForResponseNoLock("qfThreadInfo", response);
2821061da546Spatrick          packet_result == PacketResult::Success && response.IsNormalResponse();
2822061da546Spatrick          packet_result =
2823061da546Spatrick              SendPacketAndWaitForResponseNoLock("qsThreadInfo", response)) {
2824061da546Spatrick       char ch = response.GetChar();
2825061da546Spatrick       if (ch == 'l')
2826061da546Spatrick         break;
2827061da546Spatrick       if (ch == 'm') {
2828061da546Spatrick         do {
2829*be691f3bSpatrick           auto pid_tid = response.GetPidTid(LLDB_INVALID_PROCESS_ID);
2830*be691f3bSpatrick           if (!pid_tid)
2831*be691f3bSpatrick             return {};
2832061da546Spatrick 
2833*be691f3bSpatrick           ids.push_back(pid_tid.getValue());
2834061da546Spatrick           ch = response.GetChar(); // Skip the command separator
2835061da546Spatrick         } while (ch == ',');       // Make sure we got a comma separator
2836061da546Spatrick       }
2837061da546Spatrick     }
2838061da546Spatrick 
2839061da546Spatrick     /*
2840061da546Spatrick      * Connected bare-iron target (like YAMON gdb-stub) may not have support for
2841061da546Spatrick      * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet
2842061da546Spatrick      * could
2843061da546Spatrick      * be as simple as 'S05'. There is no packet which can give us pid and/or
2844061da546Spatrick      * tid.
2845061da546Spatrick      * Assume pid=tid=1 in such cases.
2846061da546Spatrick      */
2847061da546Spatrick     if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) &&
2848*be691f3bSpatrick         ids.size() == 0 && IsConnected()) {
2849*be691f3bSpatrick       ids.emplace_back(1, 1);
2850061da546Spatrick     }
2851061da546Spatrick   } else {
2852061da546Spatrick     Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
2853061da546Spatrick                                                            GDBR_LOG_PACKETS));
2854dda28197Spatrick     LLDB_LOG(log, "error: failed to get packet sequence mutex, not sending "
2855061da546Spatrick                   "packet 'qfThreadInfo'");
2856061da546Spatrick     sequence_mutex_unavailable = true;
2857061da546Spatrick   }
2858*be691f3bSpatrick 
2859*be691f3bSpatrick   return ids;
2860*be691f3bSpatrick }
2861*be691f3bSpatrick 
2862*be691f3bSpatrick size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
2863*be691f3bSpatrick     std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
2864*be691f3bSpatrick   lldb::pid_t pid = GetCurrentProcessID();
2865*be691f3bSpatrick   thread_ids.clear();
2866*be691f3bSpatrick 
2867*be691f3bSpatrick   auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
2868*be691f3bSpatrick   if (ids.empty() || sequence_mutex_unavailable)
2869*be691f3bSpatrick     return 0;
2870*be691f3bSpatrick 
2871*be691f3bSpatrick   for (auto id : ids) {
2872*be691f3bSpatrick     // skip threads that do not belong to the current process
2873*be691f3bSpatrick     if (id.first != LLDB_INVALID_PROCESS_ID && id.first != pid)
2874*be691f3bSpatrick       continue;
2875*be691f3bSpatrick     if (id.second != LLDB_INVALID_THREAD_ID &&
2876*be691f3bSpatrick         id.second != StringExtractorGDBRemote::AllThreads)
2877*be691f3bSpatrick       thread_ids.push_back(id.second);
2878*be691f3bSpatrick   }
2879*be691f3bSpatrick 
2880061da546Spatrick   return thread_ids.size();
2881061da546Spatrick }
2882061da546Spatrick 
2883061da546Spatrick lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() {
2884061da546Spatrick   StringExtractorGDBRemote response;
2885*be691f3bSpatrick   if (SendPacketAndWaitForResponse("qShlibInfoAddr", response) !=
2886061da546Spatrick           PacketResult::Success ||
2887061da546Spatrick       !response.IsNormalResponse())
2888061da546Spatrick     return LLDB_INVALID_ADDRESS;
2889061da546Spatrick   return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
2890061da546Spatrick }
2891061da546Spatrick 
2892061da546Spatrick lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
2893*be691f3bSpatrick     llvm::StringRef command,
2894061da546Spatrick     const FileSpec &
2895061da546Spatrick         working_dir, // Pass empty FileSpec to use the current working directory
2896061da546Spatrick     int *status_ptr, // Pass NULL if you don't want the process exit status
2897061da546Spatrick     int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
2898061da546Spatrick                      // process to exit
2899061da546Spatrick     std::string
2900061da546Spatrick         *command_output, // Pass NULL if you don't want the command output
2901061da546Spatrick     const Timeout<std::micro> &timeout) {
2902061da546Spatrick   lldb_private::StreamString stream;
2903061da546Spatrick   stream.PutCString("qPlatform_shell:");
2904*be691f3bSpatrick   stream.PutBytesAsRawHex8(command.data(), command.size());
2905061da546Spatrick   stream.PutChar(',');
2906061da546Spatrick   uint32_t timeout_sec = UINT32_MAX;
2907061da546Spatrick   if (timeout) {
2908061da546Spatrick     // TODO: Use chrono version of std::ceil once c++17 is available.
2909061da546Spatrick     timeout_sec = std::ceil(std::chrono::duration<double>(*timeout).count());
2910061da546Spatrick   }
2911061da546Spatrick   stream.PutHex32(timeout_sec);
2912061da546Spatrick   if (working_dir) {
2913061da546Spatrick     std::string path{working_dir.GetPath(false)};
2914061da546Spatrick     stream.PutChar(',');
2915061da546Spatrick     stream.PutStringAsRawHex8(path);
2916061da546Spatrick   }
2917061da546Spatrick   StringExtractorGDBRemote response;
2918*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
2919061da546Spatrick       PacketResult::Success) {
2920061da546Spatrick     if (response.GetChar() != 'F')
2921061da546Spatrick       return Status("malformed reply");
2922061da546Spatrick     if (response.GetChar() != ',')
2923061da546Spatrick       return Status("malformed reply");
2924061da546Spatrick     uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
2925061da546Spatrick     if (exitcode == UINT32_MAX)
2926061da546Spatrick       return Status("unable to run remote process");
2927061da546Spatrick     else if (status_ptr)
2928061da546Spatrick       *status_ptr = exitcode;
2929061da546Spatrick     if (response.GetChar() != ',')
2930061da546Spatrick       return Status("malformed reply");
2931061da546Spatrick     uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
2932061da546Spatrick     if (signo_ptr)
2933061da546Spatrick       *signo_ptr = signo;
2934061da546Spatrick     if (response.GetChar() != ',')
2935061da546Spatrick       return Status("malformed reply");
2936061da546Spatrick     std::string output;
2937061da546Spatrick     response.GetEscapedBinaryData(output);
2938061da546Spatrick     if (command_output)
2939061da546Spatrick       command_output->assign(output);
2940061da546Spatrick     return Status();
2941061da546Spatrick   }
2942061da546Spatrick   return Status("unable to send packet");
2943061da546Spatrick }
2944061da546Spatrick 
2945061da546Spatrick Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec,
2946061da546Spatrick                                                    uint32_t file_permissions) {
2947061da546Spatrick   std::string path{file_spec.GetPath(false)};
2948061da546Spatrick   lldb_private::StreamString stream;
2949061da546Spatrick   stream.PutCString("qPlatform_mkdir:");
2950061da546Spatrick   stream.PutHex32(file_permissions);
2951061da546Spatrick   stream.PutChar(',');
2952061da546Spatrick   stream.PutStringAsRawHex8(path);
2953061da546Spatrick   llvm::StringRef packet = stream.GetString();
2954061da546Spatrick   StringExtractorGDBRemote response;
2955061da546Spatrick 
2956*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
2957061da546Spatrick     return Status("failed to send '%s' packet", packet.str().c_str());
2958061da546Spatrick 
2959061da546Spatrick   if (response.GetChar() != 'F')
2960061da546Spatrick     return Status("invalid response to '%s' packet", packet.str().c_str());
2961061da546Spatrick 
2962061da546Spatrick   return Status(response.GetU32(UINT32_MAX), eErrorTypePOSIX);
2963061da546Spatrick }
2964061da546Spatrick 
2965061da546Spatrick Status
2966061da546Spatrick GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec,
2967061da546Spatrick                                                  uint32_t file_permissions) {
2968061da546Spatrick   std::string path{file_spec.GetPath(false)};
2969061da546Spatrick   lldb_private::StreamString stream;
2970061da546Spatrick   stream.PutCString("qPlatform_chmod:");
2971061da546Spatrick   stream.PutHex32(file_permissions);
2972061da546Spatrick   stream.PutChar(',');
2973061da546Spatrick   stream.PutStringAsRawHex8(path);
2974061da546Spatrick   llvm::StringRef packet = stream.GetString();
2975061da546Spatrick   StringExtractorGDBRemote response;
2976061da546Spatrick 
2977*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
2978061da546Spatrick     return Status("failed to send '%s' packet", stream.GetData());
2979061da546Spatrick 
2980061da546Spatrick   if (response.GetChar() != 'F')
2981061da546Spatrick     return Status("invalid response to '%s' packet", stream.GetData());
2982061da546Spatrick 
2983061da546Spatrick   return Status(response.GetU32(UINT32_MAX), eErrorTypePOSIX);
2984061da546Spatrick }
2985061da546Spatrick 
2986061da546Spatrick static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response,
2987061da546Spatrick                                           uint64_t fail_result, Status &error) {
2988061da546Spatrick   response.SetFilePos(0);
2989061da546Spatrick   if (response.GetChar() != 'F')
2990061da546Spatrick     return fail_result;
2991061da546Spatrick   int32_t result = response.GetS32(-2);
2992061da546Spatrick   if (result == -2)
2993061da546Spatrick     return fail_result;
2994061da546Spatrick   if (response.GetChar() == ',') {
2995061da546Spatrick     int result_errno = response.GetS32(-2);
2996061da546Spatrick     if (result_errno != -2)
2997061da546Spatrick       error.SetError(result_errno, eErrorTypePOSIX);
2998061da546Spatrick     else
2999061da546Spatrick       error.SetError(-1, eErrorTypeGeneric);
3000061da546Spatrick   } else
3001061da546Spatrick     error.Clear();
3002061da546Spatrick   return result;
3003061da546Spatrick }
3004061da546Spatrick lldb::user_id_t
3005061da546Spatrick GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec,
3006061da546Spatrick                                        File::OpenOptions flags, mode_t mode,
3007061da546Spatrick                                        Status &error) {
3008061da546Spatrick   std::string path(file_spec.GetPath(false));
3009061da546Spatrick   lldb_private::StreamString stream;
3010061da546Spatrick   stream.PutCString("vFile:open:");
3011061da546Spatrick   if (path.empty())
3012061da546Spatrick     return UINT64_MAX;
3013061da546Spatrick   stream.PutStringAsRawHex8(path);
3014061da546Spatrick   stream.PutChar(',');
3015061da546Spatrick   stream.PutHex32(flags);
3016061da546Spatrick   stream.PutChar(',');
3017061da546Spatrick   stream.PutHex32(mode);
3018061da546Spatrick   StringExtractorGDBRemote response;
3019*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3020061da546Spatrick       PacketResult::Success) {
3021061da546Spatrick     return ParseHostIOPacketResponse(response, UINT64_MAX, error);
3022061da546Spatrick   }
3023061da546Spatrick   return UINT64_MAX;
3024061da546Spatrick }
3025061da546Spatrick 
3026061da546Spatrick bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd,
3027061da546Spatrick                                              Status &error) {
3028061da546Spatrick   lldb_private::StreamString stream;
3029061da546Spatrick   stream.Printf("vFile:close:%i", (int)fd);
3030061da546Spatrick   StringExtractorGDBRemote response;
3031*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3032061da546Spatrick       PacketResult::Success) {
3033061da546Spatrick     return ParseHostIOPacketResponse(response, -1, error) == 0;
3034061da546Spatrick   }
3035061da546Spatrick   return false;
3036061da546Spatrick }
3037061da546Spatrick 
3038061da546Spatrick // Extension of host I/O packets to get the file size.
3039061da546Spatrick lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize(
3040061da546Spatrick     const lldb_private::FileSpec &file_spec) {
3041061da546Spatrick   std::string path(file_spec.GetPath(false));
3042061da546Spatrick   lldb_private::StreamString stream;
3043061da546Spatrick   stream.PutCString("vFile:size:");
3044061da546Spatrick   stream.PutStringAsRawHex8(path);
3045061da546Spatrick   StringExtractorGDBRemote response;
3046*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3047061da546Spatrick       PacketResult::Success) {
3048061da546Spatrick     if (response.GetChar() != 'F')
3049061da546Spatrick       return UINT64_MAX;
3050061da546Spatrick     uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
3051061da546Spatrick     return retcode;
3052061da546Spatrick   }
3053061da546Spatrick   return UINT64_MAX;
3054061da546Spatrick }
3055061da546Spatrick 
3056*be691f3bSpatrick void GDBRemoteCommunicationClient::AutoCompleteDiskFileOrDirectory(
3057*be691f3bSpatrick     CompletionRequest &request, bool only_dir) {
3058*be691f3bSpatrick   lldb_private::StreamString stream;
3059*be691f3bSpatrick   stream.PutCString("qPathComplete:");
3060*be691f3bSpatrick   stream.PutHex32(only_dir ? 1 : 0);
3061*be691f3bSpatrick   stream.PutChar(',');
3062*be691f3bSpatrick   stream.PutStringAsRawHex8(request.GetCursorArgumentPrefix());
3063*be691f3bSpatrick   StringExtractorGDBRemote response;
3064*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3065*be691f3bSpatrick       PacketResult::Success) {
3066*be691f3bSpatrick     StreamString strm;
3067*be691f3bSpatrick     char ch = response.GetChar();
3068*be691f3bSpatrick     if (ch != 'M')
3069*be691f3bSpatrick       return;
3070*be691f3bSpatrick     while (response.Peek()) {
3071*be691f3bSpatrick       strm.Clear();
3072*be691f3bSpatrick       while ((ch = response.GetHexU8(0, false)) != '\0')
3073*be691f3bSpatrick         strm.PutChar(ch);
3074*be691f3bSpatrick       request.AddCompletion(strm.GetString());
3075*be691f3bSpatrick       if (response.GetChar() != ',')
3076*be691f3bSpatrick         break;
3077*be691f3bSpatrick     }
3078*be691f3bSpatrick   }
3079*be691f3bSpatrick }
3080*be691f3bSpatrick 
3081061da546Spatrick Status
3082061da546Spatrick GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec,
3083061da546Spatrick                                                  uint32_t &file_permissions) {
3084061da546Spatrick   std::string path{file_spec.GetPath(false)};
3085061da546Spatrick   Status error;
3086061da546Spatrick   lldb_private::StreamString stream;
3087061da546Spatrick   stream.PutCString("vFile:mode:");
3088061da546Spatrick   stream.PutStringAsRawHex8(path);
3089061da546Spatrick   StringExtractorGDBRemote response;
3090*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3091061da546Spatrick       PacketResult::Success) {
3092061da546Spatrick     if (response.GetChar() != 'F') {
3093061da546Spatrick       error.SetErrorStringWithFormat("invalid response to '%s' packet",
3094061da546Spatrick                                      stream.GetData());
3095061da546Spatrick     } else {
3096061da546Spatrick       const uint32_t mode = response.GetS32(-1);
3097061da546Spatrick       if (static_cast<int32_t>(mode) == -1) {
3098061da546Spatrick         if (response.GetChar() == ',') {
3099061da546Spatrick           int response_errno = response.GetS32(-1);
3100061da546Spatrick           if (response_errno > 0)
3101061da546Spatrick             error.SetError(response_errno, lldb::eErrorTypePOSIX);
3102061da546Spatrick           else
3103061da546Spatrick             error.SetErrorToGenericError();
3104061da546Spatrick         } else
3105061da546Spatrick           error.SetErrorToGenericError();
3106061da546Spatrick       } else {
3107061da546Spatrick         file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO);
3108061da546Spatrick       }
3109061da546Spatrick     }
3110061da546Spatrick   } else {
3111061da546Spatrick     error.SetErrorStringWithFormat("failed to send '%s' packet",
3112061da546Spatrick                                    stream.GetData());
3113061da546Spatrick   }
3114061da546Spatrick   return error;
3115061da546Spatrick }
3116061da546Spatrick 
3117061da546Spatrick uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd,
3118061da546Spatrick                                                 uint64_t offset, void *dst,
3119061da546Spatrick                                                 uint64_t dst_len,
3120061da546Spatrick                                                 Status &error) {
3121061da546Spatrick   lldb_private::StreamString stream;
3122061da546Spatrick   stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len,
3123061da546Spatrick                 offset);
3124061da546Spatrick   StringExtractorGDBRemote response;
3125*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3126061da546Spatrick       PacketResult::Success) {
3127061da546Spatrick     if (response.GetChar() != 'F')
3128061da546Spatrick       return 0;
3129061da546Spatrick     uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
3130061da546Spatrick     if (retcode == UINT32_MAX)
3131061da546Spatrick       return retcode;
3132061da546Spatrick     const char next = (response.Peek() ? *response.Peek() : 0);
3133061da546Spatrick     if (next == ',')
3134061da546Spatrick       return 0;
3135061da546Spatrick     if (next == ';') {
3136061da546Spatrick       response.GetChar(); // skip the semicolon
3137061da546Spatrick       std::string buffer;
3138061da546Spatrick       if (response.GetEscapedBinaryData(buffer)) {
3139061da546Spatrick         const uint64_t data_to_write =
3140061da546Spatrick             std::min<uint64_t>(dst_len, buffer.size());
3141061da546Spatrick         if (data_to_write > 0)
3142061da546Spatrick           memcpy(dst, &buffer[0], data_to_write);
3143061da546Spatrick         return data_to_write;
3144061da546Spatrick       }
3145061da546Spatrick     }
3146061da546Spatrick   }
3147061da546Spatrick   return 0;
3148061da546Spatrick }
3149061da546Spatrick 
3150061da546Spatrick uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd,
3151061da546Spatrick                                                  uint64_t offset,
3152061da546Spatrick                                                  const void *src,
3153061da546Spatrick                                                  uint64_t src_len,
3154061da546Spatrick                                                  Status &error) {
3155061da546Spatrick   lldb_private::StreamGDBRemote stream;
3156061da546Spatrick   stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
3157061da546Spatrick   stream.PutEscapedBytes(src, src_len);
3158061da546Spatrick   StringExtractorGDBRemote response;
3159*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3160061da546Spatrick       PacketResult::Success) {
3161061da546Spatrick     if (response.GetChar() != 'F') {
3162061da546Spatrick       error.SetErrorStringWithFormat("write file failed");
3163061da546Spatrick       return 0;
3164061da546Spatrick     }
3165061da546Spatrick     uint64_t bytes_written = response.GetU64(UINT64_MAX);
3166061da546Spatrick     if (bytes_written == UINT64_MAX) {
3167061da546Spatrick       error.SetErrorToGenericError();
3168061da546Spatrick       if (response.GetChar() == ',') {
3169061da546Spatrick         int response_errno = response.GetS32(-1);
3170061da546Spatrick         if (response_errno > 0)
3171061da546Spatrick           error.SetError(response_errno, lldb::eErrorTypePOSIX);
3172061da546Spatrick       }
3173061da546Spatrick       return 0;
3174061da546Spatrick     }
3175061da546Spatrick     return bytes_written;
3176061da546Spatrick   } else {
3177061da546Spatrick     error.SetErrorString("failed to send vFile:pwrite packet");
3178061da546Spatrick   }
3179061da546Spatrick   return 0;
3180061da546Spatrick }
3181061da546Spatrick 
3182061da546Spatrick Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src,
3183061da546Spatrick                                                    const FileSpec &dst) {
3184061da546Spatrick   std::string src_path{src.GetPath(false)}, dst_path{dst.GetPath(false)};
3185061da546Spatrick   Status error;
3186061da546Spatrick   lldb_private::StreamGDBRemote stream;
3187061da546Spatrick   stream.PutCString("vFile:symlink:");
3188061da546Spatrick   // the unix symlink() command reverses its parameters where the dst if first,
3189061da546Spatrick   // so we follow suit here
3190061da546Spatrick   stream.PutStringAsRawHex8(dst_path);
3191061da546Spatrick   stream.PutChar(',');
3192061da546Spatrick   stream.PutStringAsRawHex8(src_path);
3193061da546Spatrick   StringExtractorGDBRemote response;
3194*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3195061da546Spatrick       PacketResult::Success) {
3196061da546Spatrick     if (response.GetChar() == 'F') {
3197061da546Spatrick       uint32_t result = response.GetU32(UINT32_MAX);
3198061da546Spatrick       if (result != 0) {
3199061da546Spatrick         error.SetErrorToGenericError();
3200061da546Spatrick         if (response.GetChar() == ',') {
3201061da546Spatrick           int response_errno = response.GetS32(-1);
3202061da546Spatrick           if (response_errno > 0)
3203061da546Spatrick             error.SetError(response_errno, lldb::eErrorTypePOSIX);
3204061da546Spatrick         }
3205061da546Spatrick       }
3206061da546Spatrick     } else {
3207061da546Spatrick       // Should have returned with 'F<result>[,<errno>]'
3208061da546Spatrick       error.SetErrorStringWithFormat("symlink failed");
3209061da546Spatrick     }
3210061da546Spatrick   } else {
3211061da546Spatrick     error.SetErrorString("failed to send vFile:symlink packet");
3212061da546Spatrick   }
3213061da546Spatrick   return error;
3214061da546Spatrick }
3215061da546Spatrick 
3216061da546Spatrick Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) {
3217061da546Spatrick   std::string path{file_spec.GetPath(false)};
3218061da546Spatrick   Status error;
3219061da546Spatrick   lldb_private::StreamGDBRemote stream;
3220061da546Spatrick   stream.PutCString("vFile:unlink:");
3221061da546Spatrick   // the unix symlink() command reverses its parameters where the dst if first,
3222061da546Spatrick   // so we follow suit here
3223061da546Spatrick   stream.PutStringAsRawHex8(path);
3224061da546Spatrick   StringExtractorGDBRemote response;
3225*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3226061da546Spatrick       PacketResult::Success) {
3227061da546Spatrick     if (response.GetChar() == 'F') {
3228061da546Spatrick       uint32_t result = response.GetU32(UINT32_MAX);
3229061da546Spatrick       if (result != 0) {
3230061da546Spatrick         error.SetErrorToGenericError();
3231061da546Spatrick         if (response.GetChar() == ',') {
3232061da546Spatrick           int response_errno = response.GetS32(-1);
3233061da546Spatrick           if (response_errno > 0)
3234061da546Spatrick             error.SetError(response_errno, lldb::eErrorTypePOSIX);
3235061da546Spatrick         }
3236061da546Spatrick       }
3237061da546Spatrick     } else {
3238061da546Spatrick       // Should have returned with 'F<result>[,<errno>]'
3239061da546Spatrick       error.SetErrorStringWithFormat("unlink failed");
3240061da546Spatrick     }
3241061da546Spatrick   } else {
3242061da546Spatrick     error.SetErrorString("failed to send vFile:unlink packet");
3243061da546Spatrick   }
3244061da546Spatrick   return error;
3245061da546Spatrick }
3246061da546Spatrick 
3247061da546Spatrick // Extension of host I/O packets to get whether a file exists.
3248061da546Spatrick bool GDBRemoteCommunicationClient::GetFileExists(
3249061da546Spatrick     const lldb_private::FileSpec &file_spec) {
3250061da546Spatrick   std::string path(file_spec.GetPath(false));
3251061da546Spatrick   lldb_private::StreamString stream;
3252061da546Spatrick   stream.PutCString("vFile:exists:");
3253061da546Spatrick   stream.PutStringAsRawHex8(path);
3254061da546Spatrick   StringExtractorGDBRemote response;
3255*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3256061da546Spatrick       PacketResult::Success) {
3257061da546Spatrick     if (response.GetChar() != 'F')
3258061da546Spatrick       return false;
3259061da546Spatrick     if (response.GetChar() != ',')
3260061da546Spatrick       return false;
3261061da546Spatrick     bool retcode = (response.GetChar() != '0');
3262061da546Spatrick     return retcode;
3263061da546Spatrick   }
3264061da546Spatrick   return false;
3265061da546Spatrick }
3266061da546Spatrick 
3267061da546Spatrick bool GDBRemoteCommunicationClient::CalculateMD5(
3268061da546Spatrick     const lldb_private::FileSpec &file_spec, uint64_t &high, uint64_t &low) {
3269061da546Spatrick   std::string path(file_spec.GetPath(false));
3270061da546Spatrick   lldb_private::StreamString stream;
3271061da546Spatrick   stream.PutCString("vFile:MD5:");
3272061da546Spatrick   stream.PutStringAsRawHex8(path);
3273061da546Spatrick   StringExtractorGDBRemote response;
3274*be691f3bSpatrick   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3275061da546Spatrick       PacketResult::Success) {
3276061da546Spatrick     if (response.GetChar() != 'F')
3277061da546Spatrick       return false;
3278061da546Spatrick     if (response.GetChar() != ',')
3279061da546Spatrick       return false;
3280061da546Spatrick     if (response.Peek() && *response.Peek() == 'x')
3281061da546Spatrick       return false;
3282061da546Spatrick     low = response.GetHexMaxU64(false, UINT64_MAX);
3283061da546Spatrick     high = response.GetHexMaxU64(false, UINT64_MAX);
3284061da546Spatrick     return true;
3285061da546Spatrick   }
3286061da546Spatrick   return false;
3287061da546Spatrick }
3288061da546Spatrick 
3289061da546Spatrick bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) {
3290061da546Spatrick   // Some targets have issues with g/G packets and we need to avoid using them
3291061da546Spatrick   if (m_avoid_g_packets == eLazyBoolCalculate) {
3292061da546Spatrick     if (process) {
3293061da546Spatrick       m_avoid_g_packets = eLazyBoolNo;
3294061da546Spatrick       const ArchSpec &arch = process->GetTarget().GetArchitecture();
3295061da546Spatrick       if (arch.IsValid() &&
3296061da546Spatrick           arch.GetTriple().getVendor() == llvm::Triple::Apple &&
3297061da546Spatrick           arch.GetTriple().getOS() == llvm::Triple::IOS &&
3298061da546Spatrick           (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
3299061da546Spatrick            arch.GetTriple().getArch() == llvm::Triple::aarch64_32)) {
3300061da546Spatrick         m_avoid_g_packets = eLazyBoolYes;
3301061da546Spatrick         uint32_t gdb_server_version = GetGDBServerProgramVersion();
3302061da546Spatrick         if (gdb_server_version != 0) {
3303061da546Spatrick           const char *gdb_server_name = GetGDBServerProgramName();
3304061da546Spatrick           if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0) {
3305061da546Spatrick             if (gdb_server_version >= 310)
3306061da546Spatrick               m_avoid_g_packets = eLazyBoolNo;
3307061da546Spatrick           }
3308061da546Spatrick         }
3309061da546Spatrick       }
3310061da546Spatrick     }
3311061da546Spatrick   }
3312061da546Spatrick   return m_avoid_g_packets == eLazyBoolYes;
3313061da546Spatrick }
3314061da546Spatrick 
3315061da546Spatrick DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid,
3316061da546Spatrick                                                         uint32_t reg) {
3317061da546Spatrick   StreamString payload;
3318061da546Spatrick   payload.Printf("p%x", reg);
3319061da546Spatrick   StringExtractorGDBRemote response;
3320061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
3321*be691f3bSpatrick           tid, std::move(payload), response) != PacketResult::Success ||
3322061da546Spatrick       !response.IsNormalResponse())
3323061da546Spatrick     return nullptr;
3324061da546Spatrick 
3325061da546Spatrick   DataBufferSP buffer_sp(
3326061da546Spatrick       new DataBufferHeap(response.GetStringRef().size() / 2, 0));
3327061da546Spatrick   response.GetHexBytes(buffer_sp->GetData(), '\xcc');
3328061da546Spatrick   return buffer_sp;
3329061da546Spatrick }
3330061da546Spatrick 
3331061da546Spatrick DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) {
3332061da546Spatrick   StreamString payload;
3333061da546Spatrick   payload.PutChar('g');
3334061da546Spatrick   StringExtractorGDBRemote response;
3335061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
3336*be691f3bSpatrick           tid, std::move(payload), response) != PacketResult::Success ||
3337061da546Spatrick       !response.IsNormalResponse())
3338061da546Spatrick     return nullptr;
3339061da546Spatrick 
3340061da546Spatrick   DataBufferSP buffer_sp(
3341061da546Spatrick       new DataBufferHeap(response.GetStringRef().size() / 2, 0));
3342061da546Spatrick   response.GetHexBytes(buffer_sp->GetData(), '\xcc');
3343061da546Spatrick   return buffer_sp;
3344061da546Spatrick }
3345061da546Spatrick 
3346061da546Spatrick bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid,
3347061da546Spatrick                                                  uint32_t reg_num,
3348061da546Spatrick                                                  llvm::ArrayRef<uint8_t> data) {
3349061da546Spatrick   StreamString payload;
3350061da546Spatrick   payload.Printf("P%x=", reg_num);
3351061da546Spatrick   payload.PutBytesAsRawHex8(data.data(), data.size(),
3352061da546Spatrick                             endian::InlHostByteOrder(),
3353061da546Spatrick                             endian::InlHostByteOrder());
3354061da546Spatrick   StringExtractorGDBRemote response;
3355*be691f3bSpatrick   return SendThreadSpecificPacketAndWaitForResponse(
3356*be691f3bSpatrick              tid, std::move(payload), response) == PacketResult::Success &&
3357061da546Spatrick          response.IsOKResponse();
3358061da546Spatrick }
3359061da546Spatrick 
3360061da546Spatrick bool GDBRemoteCommunicationClient::WriteAllRegisters(
3361061da546Spatrick     lldb::tid_t tid, llvm::ArrayRef<uint8_t> data) {
3362061da546Spatrick   StreamString payload;
3363061da546Spatrick   payload.PutChar('G');
3364061da546Spatrick   payload.PutBytesAsRawHex8(data.data(), data.size(),
3365061da546Spatrick                             endian::InlHostByteOrder(),
3366061da546Spatrick                             endian::InlHostByteOrder());
3367061da546Spatrick   StringExtractorGDBRemote response;
3368*be691f3bSpatrick   return SendThreadSpecificPacketAndWaitForResponse(
3369*be691f3bSpatrick              tid, std::move(payload), response) == PacketResult::Success &&
3370061da546Spatrick          response.IsOKResponse();
3371061da546Spatrick }
3372061da546Spatrick 
3373061da546Spatrick bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
3374061da546Spatrick                                                      uint32_t &save_id) {
3375061da546Spatrick   save_id = 0; // Set to invalid save ID
3376061da546Spatrick   if (m_supports_QSaveRegisterState == eLazyBoolNo)
3377061da546Spatrick     return false;
3378061da546Spatrick 
3379061da546Spatrick   m_supports_QSaveRegisterState = eLazyBoolYes;
3380061da546Spatrick   StreamString payload;
3381061da546Spatrick   payload.PutCString("QSaveRegisterState");
3382061da546Spatrick   StringExtractorGDBRemote response;
3383061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
3384*be691f3bSpatrick           tid, std::move(payload), response) != PacketResult::Success)
3385061da546Spatrick     return false;
3386061da546Spatrick 
3387061da546Spatrick   if (response.IsUnsupportedResponse())
3388061da546Spatrick     m_supports_QSaveRegisterState = eLazyBoolNo;
3389061da546Spatrick 
3390061da546Spatrick   const uint32_t response_save_id = response.GetU32(0);
3391061da546Spatrick   if (response_save_id == 0)
3392061da546Spatrick     return false;
3393061da546Spatrick 
3394061da546Spatrick   save_id = response_save_id;
3395061da546Spatrick   return true;
3396061da546Spatrick }
3397061da546Spatrick 
3398061da546Spatrick bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
3399061da546Spatrick                                                         uint32_t save_id) {
3400061da546Spatrick   // We use the "m_supports_QSaveRegisterState" variable here because the
3401061da546Spatrick   // QSaveRegisterState and QRestoreRegisterState packets must both be
3402061da546Spatrick   // supported in order to be useful
3403061da546Spatrick   if (m_supports_QSaveRegisterState == eLazyBoolNo)
3404061da546Spatrick     return false;
3405061da546Spatrick 
3406061da546Spatrick   StreamString payload;
3407061da546Spatrick   payload.Printf("QRestoreRegisterState:%u", save_id);
3408061da546Spatrick   StringExtractorGDBRemote response;
3409061da546Spatrick   if (SendThreadSpecificPacketAndWaitForResponse(
3410*be691f3bSpatrick           tid, std::move(payload), response) != PacketResult::Success)
3411061da546Spatrick     return false;
3412061da546Spatrick 
3413061da546Spatrick   if (response.IsOKResponse())
3414061da546Spatrick     return true;
3415061da546Spatrick 
3416061da546Spatrick   if (response.IsUnsupportedResponse())
3417061da546Spatrick     m_supports_QSaveRegisterState = eLazyBoolNo;
3418061da546Spatrick   return false;
3419061da546Spatrick }
3420061da546Spatrick 
3421061da546Spatrick bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) {
3422061da546Spatrick   if (!GetSyncThreadStateSupported())
3423061da546Spatrick     return false;
3424061da546Spatrick 
3425061da546Spatrick   StreamString packet;
3426061da546Spatrick   StringExtractorGDBRemote response;
3427061da546Spatrick   packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid);
3428*be691f3bSpatrick   return SendPacketAndWaitForResponse(packet.GetString(), response) ==
3429061da546Spatrick              GDBRemoteCommunication::PacketResult::Success &&
3430061da546Spatrick          response.IsOKResponse();
3431061da546Spatrick }
3432061da546Spatrick 
3433*be691f3bSpatrick llvm::Expected<TraceSupportedResponse>
3434*be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceSupported(std::chrono::seconds timeout) {
3435061da546Spatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3436061da546Spatrick 
3437061da546Spatrick   StreamGDBRemote escaped_packet;
3438*be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceSupported");
3439061da546Spatrick 
3440061da546Spatrick   StringExtractorGDBRemote response;
3441061da546Spatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3442*be691f3bSpatrick                                    timeout) ==
3443061da546Spatrick       GDBRemoteCommunication::PacketResult::Success) {
3444*be691f3bSpatrick     if (response.IsErrorResponse())
3445*be691f3bSpatrick       return response.GetStatus().ToError();
3446*be691f3bSpatrick     if (response.IsUnsupportedResponse())
3447*be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3448*be691f3bSpatrick                                      "jLLDBTraceSupported is unsupported");
3449*be691f3bSpatrick 
3450*be691f3bSpatrick     return llvm::json::parse<TraceSupportedResponse>(response.Peek(),
3451*be691f3bSpatrick                                                      "TraceSupportedResponse");
3452061da546Spatrick   }
3453*be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceSupported");
3454*be691f3bSpatrick   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3455*be691f3bSpatrick                                  "failed to send packet: jLLDBTraceSupported");
3456*be691f3bSpatrick }
3457*be691f3bSpatrick 
3458*be691f3bSpatrick llvm::Error
3459*be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request,
3460*be691f3bSpatrick                                             std::chrono::seconds timeout) {
3461*be691f3bSpatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3462*be691f3bSpatrick 
3463*be691f3bSpatrick   StreamGDBRemote escaped_packet;
3464*be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceStop:");
3465*be691f3bSpatrick 
3466*be691f3bSpatrick   std::string json_string;
3467*be691f3bSpatrick   llvm::raw_string_ostream os(json_string);
3468*be691f3bSpatrick   os << toJSON(request);
3469*be691f3bSpatrick   os.flush();
3470*be691f3bSpatrick 
3471*be691f3bSpatrick   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3472*be691f3bSpatrick 
3473*be691f3bSpatrick   StringExtractorGDBRemote response;
3474*be691f3bSpatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3475*be691f3bSpatrick                                    timeout) ==
3476*be691f3bSpatrick       GDBRemoteCommunication::PacketResult::Success) {
3477*be691f3bSpatrick     if (response.IsErrorResponse())
3478*be691f3bSpatrick       return response.GetStatus().ToError();
3479*be691f3bSpatrick     if (response.IsUnsupportedResponse())
3480*be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3481*be691f3bSpatrick                                      "jLLDBTraceStop is unsupported");
3482*be691f3bSpatrick     if (response.IsOKResponse())
3483*be691f3bSpatrick       return llvm::Error::success();
3484*be691f3bSpatrick     return llvm::createStringError(llvm::inconvertibleErrorCode(),
3485*be691f3bSpatrick                                    "Invalid jLLDBTraceStart response");
3486*be691f3bSpatrick   }
3487*be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceStop");
3488*be691f3bSpatrick   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3489*be691f3bSpatrick                                  "failed to send packet: jLLDBTraceStop '%s'",
3490061da546Spatrick                                  escaped_packet.GetData());
3491061da546Spatrick }
3492061da546Spatrick 
3493*be691f3bSpatrick llvm::Error
3494*be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value &params,
3495*be691f3bSpatrick                                              std::chrono::seconds timeout) {
3496061da546Spatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3497*be691f3bSpatrick 
3498*be691f3bSpatrick   StreamGDBRemote escaped_packet;
3499*be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceStart:");
3500*be691f3bSpatrick 
3501*be691f3bSpatrick   std::string json_string;
3502*be691f3bSpatrick   llvm::raw_string_ostream os(json_string);
3503*be691f3bSpatrick   os << params;
3504*be691f3bSpatrick   os.flush();
3505*be691f3bSpatrick 
3506*be691f3bSpatrick   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3507*be691f3bSpatrick 
3508061da546Spatrick   StringExtractorGDBRemote response;
3509061da546Spatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3510*be691f3bSpatrick                                    timeout) ==
3511061da546Spatrick       GDBRemoteCommunication::PacketResult::Success) {
3512*be691f3bSpatrick     if (response.IsErrorResponse())
3513*be691f3bSpatrick       return response.GetStatus().ToError();
3514*be691f3bSpatrick     if (response.IsUnsupportedResponse())
3515*be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3516*be691f3bSpatrick                                      "jLLDBTraceStart is unsupported");
3517*be691f3bSpatrick     if (response.IsOKResponse())
3518*be691f3bSpatrick       return llvm::Error::success();
3519*be691f3bSpatrick     return llvm::createStringError(llvm::inconvertibleErrorCode(),
3520*be691f3bSpatrick                                    "Invalid jLLDBTraceStart response");
3521061da546Spatrick   }
3522*be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceStart");
3523*be691f3bSpatrick   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3524*be691f3bSpatrick                                  "failed to send packet: jLLDBTraceStart '%s'",
3525061da546Spatrick                                  escaped_packet.GetData());
3526061da546Spatrick }
3527061da546Spatrick 
3528*be691f3bSpatrick llvm::Expected<std::string>
3529*be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type,
3530*be691f3bSpatrick                                                 std::chrono::seconds timeout) {
3531061da546Spatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3532061da546Spatrick 
3533*be691f3bSpatrick   StreamGDBRemote escaped_packet;
3534*be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceGetState:");
3535061da546Spatrick 
3536*be691f3bSpatrick   std::string json_string;
3537*be691f3bSpatrick   llvm::raw_string_ostream os(json_string);
3538*be691f3bSpatrick   os << toJSON(TraceGetStateRequest{type.str()});
3539*be691f3bSpatrick   os.flush();
3540061da546Spatrick 
3541*be691f3bSpatrick   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3542061da546Spatrick 
3543061da546Spatrick   StringExtractorGDBRemote response;
3544*be691f3bSpatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3545*be691f3bSpatrick                                    timeout) ==
3546061da546Spatrick       GDBRemoteCommunication::PacketResult::Success) {
3547*be691f3bSpatrick     if (response.IsErrorResponse())
3548*be691f3bSpatrick       return response.GetStatus().ToError();
3549*be691f3bSpatrick     if (response.IsUnsupportedResponse())
3550*be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3551*be691f3bSpatrick                                      "jLLDBTraceGetState is unsupported");
3552*be691f3bSpatrick     return std::string(response.Peek());
3553061da546Spatrick   }
3554*be691f3bSpatrick 
3555*be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceGetState");
3556*be691f3bSpatrick   return llvm::createStringError(
3557*be691f3bSpatrick       llvm::inconvertibleErrorCode(),
3558*be691f3bSpatrick       "failed to send packet: jLLDBTraceGetState '%s'",
3559*be691f3bSpatrick       escaped_packet.GetData());
3560061da546Spatrick }
3561*be691f3bSpatrick 
3562*be691f3bSpatrick llvm::Expected<std::vector<uint8_t>>
3563*be691f3bSpatrick GDBRemoteCommunicationClient::SendTraceGetBinaryData(
3564*be691f3bSpatrick     const TraceGetBinaryDataRequest &request, std::chrono::seconds timeout) {
3565*be691f3bSpatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3566*be691f3bSpatrick 
3567*be691f3bSpatrick   StreamGDBRemote escaped_packet;
3568*be691f3bSpatrick   escaped_packet.PutCString("jLLDBTraceGetBinaryData:");
3569*be691f3bSpatrick 
3570*be691f3bSpatrick   std::string json_string;
3571*be691f3bSpatrick   llvm::raw_string_ostream os(json_string);
3572*be691f3bSpatrick   os << toJSON(request);
3573*be691f3bSpatrick   os.flush();
3574*be691f3bSpatrick 
3575*be691f3bSpatrick   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3576*be691f3bSpatrick 
3577*be691f3bSpatrick   StringExtractorGDBRemote response;
3578*be691f3bSpatrick   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3579*be691f3bSpatrick                                    timeout) ==
3580*be691f3bSpatrick       GDBRemoteCommunication::PacketResult::Success) {
3581*be691f3bSpatrick     if (response.IsErrorResponse())
3582*be691f3bSpatrick       return response.GetStatus().ToError();
3583*be691f3bSpatrick     if (response.IsUnsupportedResponse())
3584*be691f3bSpatrick       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3585*be691f3bSpatrick                                      "jLLDBTraceGetBinaryData is unsupported");
3586*be691f3bSpatrick     std::string data;
3587*be691f3bSpatrick     response.GetEscapedBinaryData(data);
3588*be691f3bSpatrick     return std::vector<uint8_t>(data.begin(), data.end());
3589*be691f3bSpatrick   }
3590*be691f3bSpatrick   LLDB_LOG(log, "failed to send packet: jLLDBTraceGetBinaryData");
3591*be691f3bSpatrick   return llvm::createStringError(
3592*be691f3bSpatrick       llvm::inconvertibleErrorCode(),
3593*be691f3bSpatrick       "failed to send packet: jLLDBTraceGetBinaryData '%s'",
3594*be691f3bSpatrick       escaped_packet.GetData());
3595061da546Spatrick }
3596061da546Spatrick 
3597dda28197Spatrick llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() {
3598dda28197Spatrick   StringExtractorGDBRemote response;
3599*be691f3bSpatrick   if (SendPacketAndWaitForResponse("qOffsets", response) !=
3600*be691f3bSpatrick       PacketResult::Success)
3601dda28197Spatrick     return llvm::None;
3602dda28197Spatrick   if (!response.IsNormalResponse())
3603dda28197Spatrick     return llvm::None;
3604dda28197Spatrick 
3605dda28197Spatrick   QOffsets result;
3606dda28197Spatrick   llvm::StringRef ref = response.GetStringRef();
3607dda28197Spatrick   const auto &GetOffset = [&] {
3608dda28197Spatrick     addr_t offset;
3609dda28197Spatrick     if (ref.consumeInteger(16, offset))
3610dda28197Spatrick       return false;
3611dda28197Spatrick     result.offsets.push_back(offset);
3612dda28197Spatrick     return true;
3613dda28197Spatrick   };
3614dda28197Spatrick 
3615dda28197Spatrick   if (ref.consume_front("Text=")) {
3616dda28197Spatrick     result.segments = false;
3617dda28197Spatrick     if (!GetOffset())
3618dda28197Spatrick       return llvm::None;
3619dda28197Spatrick     if (!ref.consume_front(";Data=") || !GetOffset())
3620dda28197Spatrick       return llvm::None;
3621dda28197Spatrick     if (ref.empty())
3622dda28197Spatrick       return result;
3623dda28197Spatrick     if (ref.consume_front(";Bss=") && GetOffset() && ref.empty())
3624dda28197Spatrick       return result;
3625dda28197Spatrick   } else if (ref.consume_front("TextSeg=")) {
3626dda28197Spatrick     result.segments = true;
3627dda28197Spatrick     if (!GetOffset())
3628dda28197Spatrick       return llvm::None;
3629dda28197Spatrick     if (ref.empty())
3630dda28197Spatrick       return result;
3631dda28197Spatrick     if (ref.consume_front(";DataSeg=") && GetOffset() && ref.empty())
3632dda28197Spatrick       return result;
3633dda28197Spatrick   }
3634dda28197Spatrick   return llvm::None;
3635dda28197Spatrick }
3636dda28197Spatrick 
3637061da546Spatrick bool GDBRemoteCommunicationClient::GetModuleInfo(
3638061da546Spatrick     const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec,
3639061da546Spatrick     ModuleSpec &module_spec) {
3640061da546Spatrick   if (!m_supports_qModuleInfo)
3641061da546Spatrick     return false;
3642061da546Spatrick 
3643061da546Spatrick   std::string module_path = module_file_spec.GetPath(false);
3644061da546Spatrick   if (module_path.empty())
3645061da546Spatrick     return false;
3646061da546Spatrick 
3647061da546Spatrick   StreamString packet;
3648061da546Spatrick   packet.PutCString("qModuleInfo:");
3649061da546Spatrick   packet.PutStringAsRawHex8(module_path);
3650061da546Spatrick   packet.PutCString(";");
3651061da546Spatrick   const auto &triple = arch_spec.GetTriple().getTriple();
3652061da546Spatrick   packet.PutStringAsRawHex8(triple);
3653061da546Spatrick 
3654061da546Spatrick   StringExtractorGDBRemote response;
3655*be691f3bSpatrick   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
3656061da546Spatrick       PacketResult::Success)
3657061da546Spatrick     return false;
3658061da546Spatrick 
3659061da546Spatrick   if (response.IsErrorResponse())
3660061da546Spatrick     return false;
3661061da546Spatrick 
3662061da546Spatrick   if (response.IsUnsupportedResponse()) {
3663061da546Spatrick     m_supports_qModuleInfo = false;
3664061da546Spatrick     return false;
3665061da546Spatrick   }
3666061da546Spatrick 
3667061da546Spatrick   llvm::StringRef name;
3668061da546Spatrick   llvm::StringRef value;
3669061da546Spatrick 
3670061da546Spatrick   module_spec.Clear();
3671061da546Spatrick   module_spec.GetFileSpec() = module_file_spec;
3672061da546Spatrick 
3673061da546Spatrick   while (response.GetNameColonValue(name, value)) {
3674061da546Spatrick     if (name == "uuid" || name == "md5") {
3675061da546Spatrick       StringExtractor extractor(value);
3676061da546Spatrick       std::string uuid;
3677061da546Spatrick       extractor.GetHexByteString(uuid);
3678dda28197Spatrick       module_spec.GetUUID().SetFromStringRef(uuid);
3679061da546Spatrick     } else if (name == "triple") {
3680061da546Spatrick       StringExtractor extractor(value);
3681061da546Spatrick       std::string triple;
3682061da546Spatrick       extractor.GetHexByteString(triple);
3683061da546Spatrick       module_spec.GetArchitecture().SetTriple(triple.c_str());
3684061da546Spatrick     } else if (name == "file_offset") {
3685061da546Spatrick       uint64_t ival = 0;
3686061da546Spatrick       if (!value.getAsInteger(16, ival))
3687061da546Spatrick         module_spec.SetObjectOffset(ival);
3688061da546Spatrick     } else if (name == "file_size") {
3689061da546Spatrick       uint64_t ival = 0;
3690061da546Spatrick       if (!value.getAsInteger(16, ival))
3691061da546Spatrick         module_spec.SetObjectSize(ival);
3692061da546Spatrick     } else if (name == "file_path") {
3693061da546Spatrick       StringExtractor extractor(value);
3694061da546Spatrick       std::string path;
3695061da546Spatrick       extractor.GetHexByteString(path);
3696061da546Spatrick       module_spec.GetFileSpec() = FileSpec(path, arch_spec.GetTriple());
3697061da546Spatrick     }
3698061da546Spatrick   }
3699061da546Spatrick 
3700061da546Spatrick   return true;
3701061da546Spatrick }
3702061da546Spatrick 
3703061da546Spatrick static llvm::Optional<ModuleSpec>
3704061da546Spatrick ParseModuleSpec(StructuredData::Dictionary *dict) {
3705061da546Spatrick   ModuleSpec result;
3706061da546Spatrick   if (!dict)
3707061da546Spatrick     return llvm::None;
3708061da546Spatrick 
3709061da546Spatrick   llvm::StringRef string;
3710061da546Spatrick   uint64_t integer;
3711061da546Spatrick 
3712061da546Spatrick   if (!dict->GetValueForKeyAsString("uuid", string))
3713061da546Spatrick     return llvm::None;
3714dda28197Spatrick   if (!result.GetUUID().SetFromStringRef(string))
3715061da546Spatrick     return llvm::None;
3716061da546Spatrick 
3717061da546Spatrick   if (!dict->GetValueForKeyAsInteger("file_offset", integer))
3718061da546Spatrick     return llvm::None;
3719061da546Spatrick   result.SetObjectOffset(integer);
3720061da546Spatrick 
3721061da546Spatrick   if (!dict->GetValueForKeyAsInteger("file_size", integer))
3722061da546Spatrick     return llvm::None;
3723061da546Spatrick   result.SetObjectSize(integer);
3724061da546Spatrick 
3725061da546Spatrick   if (!dict->GetValueForKeyAsString("triple", string))
3726061da546Spatrick     return llvm::None;
3727061da546Spatrick   result.GetArchitecture().SetTriple(string);
3728061da546Spatrick 
3729061da546Spatrick   if (!dict->GetValueForKeyAsString("file_path", string))
3730061da546Spatrick     return llvm::None;
3731061da546Spatrick   result.GetFileSpec() = FileSpec(string, result.GetArchitecture().GetTriple());
3732061da546Spatrick 
3733061da546Spatrick   return result;
3734061da546Spatrick }
3735061da546Spatrick 
3736061da546Spatrick llvm::Optional<std::vector<ModuleSpec>>
3737061da546Spatrick GDBRemoteCommunicationClient::GetModulesInfo(
3738061da546Spatrick     llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) {
3739061da546Spatrick   namespace json = llvm::json;
3740061da546Spatrick 
3741061da546Spatrick   if (!m_supports_jModulesInfo)
3742061da546Spatrick     return llvm::None;
3743061da546Spatrick 
3744061da546Spatrick   json::Array module_array;
3745061da546Spatrick   for (const FileSpec &module_file_spec : module_file_specs) {
3746061da546Spatrick     module_array.push_back(
3747061da546Spatrick         json::Object{{"file", module_file_spec.GetPath(false)},
3748061da546Spatrick                      {"triple", triple.getTriple()}});
3749061da546Spatrick   }
3750061da546Spatrick   StreamString unescaped_payload;
3751061da546Spatrick   unescaped_payload.PutCString("jModulesInfo:");
3752061da546Spatrick   unescaped_payload.AsRawOstream() << std::move(module_array);
3753061da546Spatrick 
3754061da546Spatrick   StreamGDBRemote payload;
3755061da546Spatrick   payload.PutEscapedBytes(unescaped_payload.GetString().data(),
3756061da546Spatrick                           unescaped_payload.GetSize());
3757061da546Spatrick 
3758061da546Spatrick   // Increase the timeout for jModulesInfo since this packet can take longer.
3759061da546Spatrick   ScopedTimeout timeout(*this, std::chrono::seconds(10));
3760061da546Spatrick 
3761061da546Spatrick   StringExtractorGDBRemote response;
3762*be691f3bSpatrick   if (SendPacketAndWaitForResponse(payload.GetString(), response) !=
3763061da546Spatrick           PacketResult::Success ||
3764061da546Spatrick       response.IsErrorResponse())
3765061da546Spatrick     return llvm::None;
3766061da546Spatrick 
3767061da546Spatrick   if (response.IsUnsupportedResponse()) {
3768061da546Spatrick     m_supports_jModulesInfo = false;
3769061da546Spatrick     return llvm::None;
3770061da546Spatrick   }
3771061da546Spatrick 
3772061da546Spatrick   StructuredData::ObjectSP response_object_sp =
3773dda28197Spatrick       StructuredData::ParseJSON(std::string(response.GetStringRef()));
3774061da546Spatrick   if (!response_object_sp)
3775061da546Spatrick     return llvm::None;
3776061da546Spatrick 
3777061da546Spatrick   StructuredData::Array *response_array = response_object_sp->GetAsArray();
3778061da546Spatrick   if (!response_array)
3779061da546Spatrick     return llvm::None;
3780061da546Spatrick 
3781061da546Spatrick   std::vector<ModuleSpec> result;
3782061da546Spatrick   for (size_t i = 0; i < response_array->GetSize(); ++i) {
3783061da546Spatrick     if (llvm::Optional<ModuleSpec> module_spec = ParseModuleSpec(
3784061da546Spatrick             response_array->GetItemAtIndex(i)->GetAsDictionary()))
3785061da546Spatrick       result.push_back(*module_spec);
3786061da546Spatrick   }
3787061da546Spatrick 
3788061da546Spatrick   return result;
3789061da546Spatrick }
3790061da546Spatrick 
3791061da546Spatrick // query the target remote for extended information using the qXfer packet
3792061da546Spatrick //
3793061da546Spatrick // example: object='features', annex='target.xml', out=<xml output> return:
3794061da546Spatrick // 'true'  on success
3795061da546Spatrick //          'false' on failure (err set)
3796061da546Spatrick bool GDBRemoteCommunicationClient::ReadExtFeature(
3797061da546Spatrick     const lldb_private::ConstString object,
3798061da546Spatrick     const lldb_private::ConstString annex, std::string &out,
3799061da546Spatrick     lldb_private::Status &err) {
3800061da546Spatrick 
3801061da546Spatrick   std::stringstream output;
3802061da546Spatrick   StringExtractorGDBRemote chunk;
3803061da546Spatrick 
3804061da546Spatrick   uint64_t size = GetRemoteMaxPacketSize();
3805061da546Spatrick   if (size == 0)
3806061da546Spatrick     size = 0x1000;
3807061da546Spatrick   size = size - 1; // Leave space for the 'm' or 'l' character in the response
3808061da546Spatrick   int offset = 0;
3809061da546Spatrick   bool active = true;
3810061da546Spatrick 
3811061da546Spatrick   // loop until all data has been read
3812061da546Spatrick   while (active) {
3813061da546Spatrick 
3814061da546Spatrick     // send query extended feature packet
3815061da546Spatrick     std::stringstream packet;
3816061da546Spatrick     packet << "qXfer:" << object.AsCString("")
3817061da546Spatrick            << ":read:" << annex.AsCString("") << ":" << std::hex << offset
3818061da546Spatrick            << "," << std::hex << size;
3819061da546Spatrick 
3820061da546Spatrick     GDBRemoteCommunication::PacketResult res =
3821*be691f3bSpatrick         SendPacketAndWaitForResponse(packet.str(), chunk);
3822061da546Spatrick 
3823061da546Spatrick     if (res != GDBRemoteCommunication::PacketResult::Success) {
3824061da546Spatrick       err.SetErrorString("Error sending $qXfer packet");
3825061da546Spatrick       return false;
3826061da546Spatrick     }
3827061da546Spatrick 
3828dda28197Spatrick     const std::string &str = std::string(chunk.GetStringRef());
3829061da546Spatrick     if (str.length() == 0) {
3830061da546Spatrick       // should have some data in chunk
3831061da546Spatrick       err.SetErrorString("Empty response from $qXfer packet");
3832061da546Spatrick       return false;
3833061da546Spatrick     }
3834061da546Spatrick 
3835061da546Spatrick     // check packet code
3836061da546Spatrick     switch (str[0]) {
3837061da546Spatrick     // last chunk
3838061da546Spatrick     case ('l'):
3839061da546Spatrick       active = false;
3840061da546Spatrick       LLVM_FALLTHROUGH;
3841061da546Spatrick 
3842061da546Spatrick     // more chunks
3843061da546Spatrick     case ('m'):
3844061da546Spatrick       if (str.length() > 1)
3845061da546Spatrick         output << &str[1];
3846061da546Spatrick       offset += str.length() - 1;
3847061da546Spatrick       break;
3848061da546Spatrick 
3849061da546Spatrick     // unknown chunk
3850061da546Spatrick     default:
3851061da546Spatrick       err.SetErrorString("Invalid continuation code from $qXfer packet");
3852061da546Spatrick       return false;
3853061da546Spatrick     }
3854061da546Spatrick   }
3855061da546Spatrick 
3856061da546Spatrick   out = output.str();
3857061da546Spatrick   err.Success();
3858061da546Spatrick   return true;
3859061da546Spatrick }
3860061da546Spatrick 
3861061da546Spatrick // Notify the target that gdb is prepared to serve symbol lookup requests.
3862061da546Spatrick //  packet: "qSymbol::"
3863061da546Spatrick //  reply:
3864061da546Spatrick //  OK                  The target does not need to look up any (more) symbols.
3865061da546Spatrick //  qSymbol:<sym_name>  The target requests the value of symbol sym_name (hex
3866061da546Spatrick //  encoded).
3867061da546Spatrick //                      LLDB may provide the value by sending another qSymbol
3868061da546Spatrick //                      packet
3869061da546Spatrick //                      in the form of"qSymbol:<sym_value>:<sym_name>".
3870061da546Spatrick //
3871061da546Spatrick //  Three examples:
3872061da546Spatrick //
3873061da546Spatrick //  lldb sends:    qSymbol::
3874061da546Spatrick //  lldb receives: OK
3875061da546Spatrick //     Remote gdb stub does not need to know the addresses of any symbols, lldb
3876061da546Spatrick //     does not
3877061da546Spatrick //     need to ask again in this session.
3878061da546Spatrick //
3879061da546Spatrick //  lldb sends:    qSymbol::
3880061da546Spatrick //  lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
3881061da546Spatrick //  lldb sends:    qSymbol::64697370617463685f71756575655f6f666673657473
3882061da546Spatrick //  lldb receives: OK
3883061da546Spatrick //     Remote gdb stub asks for address of 'dispatch_queue_offsets'.  lldb does
3884061da546Spatrick //     not know
3885061da546Spatrick //     the address at this time.  lldb needs to send qSymbol:: again when it has
3886061da546Spatrick //     more
3887061da546Spatrick //     solibs loaded.
3888061da546Spatrick //
3889061da546Spatrick //  lldb sends:    qSymbol::
3890061da546Spatrick //  lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
3891061da546Spatrick //  lldb sends:    qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473
3892061da546Spatrick //  lldb receives: OK
3893061da546Spatrick //     Remote gdb stub asks for address of 'dispatch_queue_offsets'.  lldb says
3894061da546Spatrick //     that it
3895061da546Spatrick //     is at address 0x2bc97554.  Remote gdb stub sends 'OK' indicating that it
3896061da546Spatrick //     does not
3897061da546Spatrick //     need any more symbols.  lldb does not need to ask again in this session.
3898061da546Spatrick 
3899061da546Spatrick void GDBRemoteCommunicationClient::ServeSymbolLookups(
3900061da546Spatrick     lldb_private::Process *process) {
3901061da546Spatrick   // Set to true once we've resolved a symbol to an address for the remote
3902061da546Spatrick   // stub. If we get an 'OK' response after this, the remote stub doesn't need
3903061da546Spatrick   // any more symbols and we can stop asking.
3904061da546Spatrick   bool symbol_response_provided = false;
3905061da546Spatrick 
3906061da546Spatrick   // Is this the initial qSymbol:: packet?
3907061da546Spatrick   bool first_qsymbol_query = true;
3908061da546Spatrick 
3909061da546Spatrick   if (m_supports_qSymbol && !m_qSymbol_requests_done) {
3910*be691f3bSpatrick     Lock lock(*this);
3911061da546Spatrick     if (lock) {
3912061da546Spatrick       StreamString packet;
3913061da546Spatrick       packet.PutCString("qSymbol::");
3914061da546Spatrick       StringExtractorGDBRemote response;
3915061da546Spatrick       while (SendPacketAndWaitForResponseNoLock(packet.GetString(), response) ==
3916061da546Spatrick              PacketResult::Success) {
3917061da546Spatrick         if (response.IsOKResponse()) {
3918061da546Spatrick           if (symbol_response_provided || first_qsymbol_query) {
3919061da546Spatrick             m_qSymbol_requests_done = true;
3920061da546Spatrick           }
3921061da546Spatrick 
3922061da546Spatrick           // We are done serving symbols requests
3923061da546Spatrick           return;
3924061da546Spatrick         }
3925061da546Spatrick         first_qsymbol_query = false;
3926061da546Spatrick 
3927061da546Spatrick         if (response.IsUnsupportedResponse()) {
3928061da546Spatrick           // qSymbol is not supported by the current GDB server we are
3929061da546Spatrick           // connected to
3930061da546Spatrick           m_supports_qSymbol = false;
3931061da546Spatrick           return;
3932061da546Spatrick         } else {
3933061da546Spatrick           llvm::StringRef response_str(response.GetStringRef());
3934061da546Spatrick           if (response_str.startswith("qSymbol:")) {
3935061da546Spatrick             response.SetFilePos(strlen("qSymbol:"));
3936061da546Spatrick             std::string symbol_name;
3937061da546Spatrick             if (response.GetHexByteString(symbol_name)) {
3938061da546Spatrick               if (symbol_name.empty())
3939061da546Spatrick                 return;
3940061da546Spatrick 
3941061da546Spatrick               addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
3942061da546Spatrick               lldb_private::SymbolContextList sc_list;
3943061da546Spatrick               process->GetTarget().GetImages().FindSymbolsWithNameAndType(
3944061da546Spatrick                   ConstString(symbol_name), eSymbolTypeAny, sc_list);
3945061da546Spatrick               if (!sc_list.IsEmpty()) {
3946061da546Spatrick                 const size_t num_scs = sc_list.GetSize();
3947061da546Spatrick                 for (size_t sc_idx = 0;
3948061da546Spatrick                      sc_idx < num_scs &&
3949061da546Spatrick                      symbol_load_addr == LLDB_INVALID_ADDRESS;
3950061da546Spatrick                      ++sc_idx) {
3951061da546Spatrick                   SymbolContext sc;
3952061da546Spatrick                   if (sc_list.GetContextAtIndex(sc_idx, sc)) {
3953061da546Spatrick                     if (sc.symbol) {
3954061da546Spatrick                       switch (sc.symbol->GetType()) {
3955061da546Spatrick                       case eSymbolTypeInvalid:
3956061da546Spatrick                       case eSymbolTypeAbsolute:
3957061da546Spatrick                       case eSymbolTypeUndefined:
3958061da546Spatrick                       case eSymbolTypeSourceFile:
3959061da546Spatrick                       case eSymbolTypeHeaderFile:
3960061da546Spatrick                       case eSymbolTypeObjectFile:
3961061da546Spatrick                       case eSymbolTypeCommonBlock:
3962061da546Spatrick                       case eSymbolTypeBlock:
3963061da546Spatrick                       case eSymbolTypeLocal:
3964061da546Spatrick                       case eSymbolTypeParam:
3965061da546Spatrick                       case eSymbolTypeVariable:
3966061da546Spatrick                       case eSymbolTypeVariableType:
3967061da546Spatrick                       case eSymbolTypeLineEntry:
3968061da546Spatrick                       case eSymbolTypeLineHeader:
3969061da546Spatrick                       case eSymbolTypeScopeBegin:
3970061da546Spatrick                       case eSymbolTypeScopeEnd:
3971061da546Spatrick                       case eSymbolTypeAdditional:
3972061da546Spatrick                       case eSymbolTypeCompiler:
3973061da546Spatrick                       case eSymbolTypeInstrumentation:
3974061da546Spatrick                       case eSymbolTypeTrampoline:
3975061da546Spatrick                         break;
3976061da546Spatrick 
3977061da546Spatrick                       case eSymbolTypeCode:
3978061da546Spatrick                       case eSymbolTypeResolver:
3979061da546Spatrick                       case eSymbolTypeData:
3980061da546Spatrick                       case eSymbolTypeRuntime:
3981061da546Spatrick                       case eSymbolTypeException:
3982061da546Spatrick                       case eSymbolTypeObjCClass:
3983061da546Spatrick                       case eSymbolTypeObjCMetaClass:
3984061da546Spatrick                       case eSymbolTypeObjCIVar:
3985061da546Spatrick                       case eSymbolTypeReExported:
3986061da546Spatrick                         symbol_load_addr =
3987061da546Spatrick                             sc.symbol->GetLoadAddress(&process->GetTarget());
3988061da546Spatrick                         break;
3989061da546Spatrick                       }
3990061da546Spatrick                     }
3991061da546Spatrick                   }
3992061da546Spatrick                 }
3993061da546Spatrick               }
3994061da546Spatrick               // This is the normal path where our symbol lookup was successful
3995061da546Spatrick               // and we want to send a packet with the new symbol value and see
3996061da546Spatrick               // if another lookup needs to be done.
3997061da546Spatrick 
3998061da546Spatrick               // Change "packet" to contain the requested symbol value and name
3999061da546Spatrick               packet.Clear();
4000061da546Spatrick               packet.PutCString("qSymbol:");
4001061da546Spatrick               if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
4002061da546Spatrick                 packet.Printf("%" PRIx64, symbol_load_addr);
4003061da546Spatrick                 symbol_response_provided = true;
4004061da546Spatrick               } else {
4005061da546Spatrick                 symbol_response_provided = false;
4006061da546Spatrick               }
4007061da546Spatrick               packet.PutCString(":");
4008061da546Spatrick               packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
4009061da546Spatrick               continue; // go back to the while loop and send "packet" and wait
4010061da546Spatrick                         // for another response
4011061da546Spatrick             }
4012061da546Spatrick           }
4013061da546Spatrick         }
4014061da546Spatrick       }
4015061da546Spatrick       // If we make it here, the symbol request packet response wasn't valid or
4016061da546Spatrick       // our symbol lookup failed so we must abort
4017061da546Spatrick       return;
4018061da546Spatrick 
4019061da546Spatrick     } else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
4020061da546Spatrick                    GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) {
4021061da546Spatrick       LLDB_LOGF(log,
4022061da546Spatrick                 "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.",
4023061da546Spatrick                 __FUNCTION__);
4024061da546Spatrick     }
4025061da546Spatrick   }
4026061da546Spatrick }
4027061da546Spatrick 
4028061da546Spatrick StructuredData::Array *
4029061da546Spatrick GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
4030061da546Spatrick   if (!m_supported_async_json_packets_is_valid) {
4031061da546Spatrick     // Query the server for the array of supported asynchronous JSON packets.
4032061da546Spatrick     m_supported_async_json_packets_is_valid = true;
4033061da546Spatrick 
4034061da546Spatrick     Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
4035061da546Spatrick 
4036061da546Spatrick     // Poll it now.
4037061da546Spatrick     StringExtractorGDBRemote response;
4038*be691f3bSpatrick     if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response) ==
4039*be691f3bSpatrick         PacketResult::Success) {
4040061da546Spatrick       m_supported_async_json_packets_sp =
4041dda28197Spatrick           StructuredData::ParseJSON(std::string(response.GetStringRef()));
4042061da546Spatrick       if (m_supported_async_json_packets_sp &&
4043061da546Spatrick           !m_supported_async_json_packets_sp->GetAsArray()) {
4044061da546Spatrick         // We were returned something other than a JSON array.  This is
4045061da546Spatrick         // invalid.  Clear it out.
4046061da546Spatrick         LLDB_LOGF(log,
4047061da546Spatrick                   "GDBRemoteCommunicationClient::%s(): "
4048061da546Spatrick                   "QSupportedAsyncJSONPackets returned invalid "
4049061da546Spatrick                   "result: %s",
4050061da546Spatrick                   __FUNCTION__, response.GetStringRef().data());
4051061da546Spatrick         m_supported_async_json_packets_sp.reset();
4052061da546Spatrick       }
4053061da546Spatrick     } else {
4054061da546Spatrick       LLDB_LOGF(log,
4055061da546Spatrick                 "GDBRemoteCommunicationClient::%s(): "
4056061da546Spatrick                 "QSupportedAsyncJSONPackets unsupported",
4057061da546Spatrick                 __FUNCTION__);
4058061da546Spatrick     }
4059061da546Spatrick 
4060061da546Spatrick     if (log && m_supported_async_json_packets_sp) {
4061061da546Spatrick       StreamString stream;
4062061da546Spatrick       m_supported_async_json_packets_sp->Dump(stream);
4063061da546Spatrick       LLDB_LOGF(log,
4064061da546Spatrick                 "GDBRemoteCommunicationClient::%s(): supported async "
4065061da546Spatrick                 "JSON packets: %s",
4066061da546Spatrick                 __FUNCTION__, stream.GetData());
4067061da546Spatrick     }
4068061da546Spatrick   }
4069061da546Spatrick 
4070061da546Spatrick   return m_supported_async_json_packets_sp
4071061da546Spatrick              ? m_supported_async_json_packets_sp->GetAsArray()
4072061da546Spatrick              : nullptr;
4073061da546Spatrick }
4074061da546Spatrick 
4075061da546Spatrick Status GDBRemoteCommunicationClient::SendSignalsToIgnore(
4076061da546Spatrick     llvm::ArrayRef<int32_t> signals) {
4077061da546Spatrick   // Format packet:
4078061da546Spatrick   // QPassSignals:<hex_sig1>;<hex_sig2>...;<hex_sigN>
4079061da546Spatrick   auto range = llvm::make_range(signals.begin(), signals.end());
4080061da546Spatrick   std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str();
4081061da546Spatrick 
4082061da546Spatrick   StringExtractorGDBRemote response;
4083*be691f3bSpatrick   auto send_status = SendPacketAndWaitForResponse(packet, response);
4084061da546Spatrick 
4085061da546Spatrick   if (send_status != GDBRemoteCommunication::PacketResult::Success)
4086061da546Spatrick     return Status("Sending QPassSignals packet failed");
4087061da546Spatrick 
4088061da546Spatrick   if (response.IsOKResponse()) {
4089061da546Spatrick     return Status();
4090061da546Spatrick   } else {
4091061da546Spatrick     return Status("Unknown error happened during sending QPassSignals packet.");
4092061da546Spatrick   }
4093061da546Spatrick }
4094061da546Spatrick 
4095061da546Spatrick Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
4096061da546Spatrick     ConstString type_name, const StructuredData::ObjectSP &config_sp) {
4097061da546Spatrick   Status error;
4098061da546Spatrick 
4099061da546Spatrick   if (type_name.GetLength() == 0) {
4100061da546Spatrick     error.SetErrorString("invalid type_name argument");
4101061da546Spatrick     return error;
4102061da546Spatrick   }
4103061da546Spatrick 
4104061da546Spatrick   // Build command: Configure{type_name}: serialized config data.
4105061da546Spatrick   StreamGDBRemote stream;
4106061da546Spatrick   stream.PutCString("QConfigure");
4107dda28197Spatrick   stream.PutCString(type_name.GetStringRef());
4108061da546Spatrick   stream.PutChar(':');
4109061da546Spatrick   if (config_sp) {
4110061da546Spatrick     // Gather the plain-text version of the configuration data.
4111061da546Spatrick     StreamString unescaped_stream;
4112061da546Spatrick     config_sp->Dump(unescaped_stream);
4113061da546Spatrick     unescaped_stream.Flush();
4114061da546Spatrick 
4115061da546Spatrick     // Add it to the stream in escaped fashion.
4116061da546Spatrick     stream.PutEscapedBytes(unescaped_stream.GetString().data(),
4117061da546Spatrick                            unescaped_stream.GetSize());
4118061da546Spatrick   }
4119061da546Spatrick   stream.Flush();
4120061da546Spatrick 
4121061da546Spatrick   // Send the packet.
4122061da546Spatrick   StringExtractorGDBRemote response;
4123*be691f3bSpatrick   auto result = SendPacketAndWaitForResponse(stream.GetString(), response);
4124061da546Spatrick   if (result == PacketResult::Success) {
4125061da546Spatrick     // We failed if the config result comes back other than OK.
4126061da546Spatrick     if (strcmp(response.GetStringRef().data(), "OK") == 0) {
4127061da546Spatrick       // Okay!
4128061da546Spatrick       error.Clear();
4129061da546Spatrick     } else {
4130061da546Spatrick       error.SetErrorStringWithFormat("configuring StructuredData feature "
4131061da546Spatrick                                      "%s failed with error %s",
4132061da546Spatrick                                      type_name.AsCString(),
4133061da546Spatrick                                      response.GetStringRef().data());
4134061da546Spatrick     }
4135061da546Spatrick   } else {
4136061da546Spatrick     // Can we get more data here on the failure?
4137061da546Spatrick     error.SetErrorStringWithFormat("configuring StructuredData feature %s "
4138061da546Spatrick                                    "failed when sending packet: "
4139061da546Spatrick                                    "PacketResult=%d",
4140061da546Spatrick                                    type_name.AsCString(), (int)result);
4141061da546Spatrick   }
4142061da546Spatrick   return error;
4143061da546Spatrick }
4144061da546Spatrick 
4145061da546Spatrick void GDBRemoteCommunicationClient::OnRunPacketSent(bool first) {
4146061da546Spatrick   GDBRemoteClientBase::OnRunPacketSent(first);
4147061da546Spatrick   m_curr_tid = LLDB_INVALID_THREAD_ID;
4148061da546Spatrick }
4149