1254721Semaste//===-- GDBRemoteCommunicationClient.cpp ------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "GDBRemoteCommunicationClient.h"
10254721Semaste
11288943Sdim#include <math.h>
12258054Semaste#include <sys/stat.h>
13258054Semaste
14314564Sdim#include <numeric>
15254721Semaste#include <sstream>
16254721Semaste
17288943Sdim#include "lldb/Core/ModuleSpec.h"
18276479Sdim#include "lldb/Host/HostInfo.h"
19341825Sdim#include "lldb/Host/XML.h"
20288943Sdim#include "lldb/Symbol/Symbol.h"
21314564Sdim#include "lldb/Target/MemoryRegionInfo.h"
22276479Sdim#include "lldb/Target/Target.h"
23288943Sdim#include "lldb/Target/UnixSignals.h"
24341825Sdim#include "lldb/Utility/Args.h"
25321369Sdim#include "lldb/Utility/DataBufferHeap.h"
26314564Sdim#include "lldb/Utility/LLDBAssert.h"
27321369Sdim#include "lldb/Utility/Log.h"
28344779Sdim#include "lldb/Utility/State.h"
29321369Sdim#include "lldb/Utility/StreamString.h"
30254721Semaste
31254721Semaste#include "ProcessGDBRemote.h"
32254721Semaste#include "ProcessGDBRemoteLog.h"
33258054Semaste#include "lldb/Host/Config.h"
34341825Sdim#include "lldb/Utility/StringExtractorGDBRemote.h"
35254721Semaste
36314564Sdim#include "llvm/ADT/StringSwitch.h"
37360784Sdim#include "llvm/Support/JSON.h"
38314564Sdim
39360784Sdim#if defined(HAVE_LIBCOMPRESSION)
40288943Sdim#include <compression.h>
41288943Sdim#endif
42288943Sdim
43254721Semasteusing namespace lldb;
44360784Sdimusing namespace lldb_private::process_gdb_remote;
45254721Semasteusing namespace lldb_private;
46314564Sdimusing namespace std::chrono;
47254721Semaste
48254721Semaste// GDBRemoteCommunicationClient constructor
49309124SdimGDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
50314564Sdim    : GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"),
51309124Sdim      m_supports_not_sending_acks(eLazyBoolCalculate),
52309124Sdim      m_supports_thread_suffix(eLazyBoolCalculate),
53309124Sdim      m_supports_threads_in_stop_reply(eLazyBoolCalculate),
54309124Sdim      m_supports_vCont_all(eLazyBoolCalculate),
55309124Sdim      m_supports_vCont_any(eLazyBoolCalculate),
56309124Sdim      m_supports_vCont_c(eLazyBoolCalculate),
57309124Sdim      m_supports_vCont_C(eLazyBoolCalculate),
58309124Sdim      m_supports_vCont_s(eLazyBoolCalculate),
59309124Sdim      m_supports_vCont_S(eLazyBoolCalculate),
60309124Sdim      m_qHostInfo_is_valid(eLazyBoolCalculate),
61309124Sdim      m_curr_pid_is_valid(eLazyBoolCalculate),
62309124Sdim      m_qProcessInfo_is_valid(eLazyBoolCalculate),
63309124Sdim      m_qGDBServerVersion_is_valid(eLazyBoolCalculate),
64309124Sdim      m_supports_alloc_dealloc_memory(eLazyBoolCalculate),
65309124Sdim      m_supports_memory_region_info(eLazyBoolCalculate),
66309124Sdim      m_supports_watchpoint_support_info(eLazyBoolCalculate),
67309124Sdim      m_supports_detach_stay_stopped(eLazyBoolCalculate),
68309124Sdim      m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
69309124Sdim      m_attach_or_wait_reply(eLazyBoolCalculate),
70309124Sdim      m_prepare_for_reg_writing_reply(eLazyBoolCalculate),
71314564Sdim      m_supports_p(eLazyBoolCalculate), m_supports_x(eLazyBoolCalculate),
72309124Sdim      m_avoid_g_packets(eLazyBoolCalculate),
73309124Sdim      m_supports_QSaveRegisterState(eLazyBoolCalculate),
74309124Sdim      m_supports_qXfer_auxv_read(eLazyBoolCalculate),
75309124Sdim      m_supports_qXfer_libraries_read(eLazyBoolCalculate),
76309124Sdim      m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate),
77309124Sdim      m_supports_qXfer_features_read(eLazyBoolCalculate),
78341825Sdim      m_supports_qXfer_memory_map_read(eLazyBoolCalculate),
79309124Sdim      m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate),
80309124Sdim      m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
81309124Sdim      m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
82314564Sdim      m_supports_jGetSharedCacheInfo(eLazyBoolCalculate),
83321369Sdim      m_supports_QPassSignals(eLazyBoolCalculate),
84321369Sdim      m_supports_error_string_reply(eLazyBoolCalculate),
85314564Sdim      m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
86314564Sdim      m_supports_qUserName(true), m_supports_qGroupName(true),
87314564Sdim      m_supports_qThreadStopInfo(true), m_supports_z0(true),
88314564Sdim      m_supports_z1(true), m_supports_z2(true), m_supports_z3(true),
89314564Sdim      m_supports_z4(true), m_supports_QEnvironment(true),
90314564Sdim      m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true),
91314564Sdim      m_qSymbol_requests_done(false), m_supports_qModuleInfo(true),
92314564Sdim      m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true),
93314564Sdim      m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID),
94309124Sdim      m_curr_tid_run(LLDB_INVALID_THREAD_ID),
95314564Sdim      m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(),
96341825Sdim      m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(),
97341825Sdim      m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0),
98341825Sdim      m_max_packet_size(0), m_qSupported_response(),
99341825Sdim      m_supported_async_json_packets_is_valid(false),
100341825Sdim      m_supported_async_json_packets_sp(), m_qXfer_memory_map(),
101341825Sdim      m_qXfer_memory_map_loaded(false) {}
102254721Semaste
103254721Semaste// Destructor
104314564SdimGDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
105314564Sdim  if (IsConnected())
106314564Sdim    Disconnect();
107254721Semaste}
108254721Semaste
109321369Sdimbool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
110314564Sdim  ResetDiscoverableSettings(false);
111258884Semaste
112341825Sdim  // Start the read thread after we send the handshake ack since if we fail to
113341825Sdim  // send the handshake ack, there is no reason to continue...
114314564Sdim  if (SendAck()) {
115314564Sdim    // Wait for any responses that might have been queued up in the remote
116314564Sdim    // GDB server and flush them all
117314564Sdim    StringExtractorGDBRemote response;
118314564Sdim    PacketResult packet_result = PacketResult::Success;
119314564Sdim    while (packet_result == PacketResult::Success)
120314564Sdim      packet_result = ReadPacket(response, milliseconds(10), false);
121262528Semaste
122314564Sdim    // The return value from QueryNoAckModeSupported() is true if the packet
123341825Sdim    // was sent and _any_ response (including UNIMPLEMENTED) was received), or
124341825Sdim    // false if no response was received. This quickly tells us if we have a
125341825Sdim    // live connection to a remote GDB server...
126314564Sdim    if (QueryNoAckModeSupported()) {
127314564Sdim      return true;
128314564Sdim    } else {
129314564Sdim      if (error_ptr)
130314564Sdim        error_ptr->SetErrorString("failed to get reply to handshake packet");
131258884Semaste    }
132314564Sdim  } else {
133314564Sdim    if (error_ptr)
134314564Sdim      error_ptr->SetErrorString("failed to send the handshake ack");
135314564Sdim  }
136314564Sdim  return false;
137254721Semaste}
138254721Semaste
139314564Sdimbool GDBRemoteCommunicationClient::GetEchoSupported() {
140314564Sdim  if (m_supports_qEcho == eLazyBoolCalculate) {
141314564Sdim    GetRemoteQSupported();
142314564Sdim  }
143314564Sdim  return m_supports_qEcho == eLazyBoolYes;
144288943Sdim}
145288943Sdim
146321369Sdimbool GDBRemoteCommunicationClient::GetQPassSignalsSupported() {
147321369Sdim  if (m_supports_QPassSignals == eLazyBoolCalculate) {
148321369Sdim    GetRemoteQSupported();
149321369Sdim  }
150321369Sdim  return m_supports_QPassSignals == eLazyBoolYes;
151321369Sdim}
152321369Sdim
153314564Sdimbool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() {
154314564Sdim  if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) {
155314564Sdim    GetRemoteQSupported();
156314564Sdim  }
157314564Sdim  return m_supports_augmented_libraries_svr4_read == eLazyBoolYes;
158262528Semaste}
159262528Semaste
160314564Sdimbool GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported() {
161314564Sdim  if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) {
162314564Sdim    GetRemoteQSupported();
163314564Sdim  }
164314564Sdim  return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes;
165262528Semaste}
166262528Semaste
167314564Sdimbool GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported() {
168314564Sdim  if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) {
169314564Sdim    GetRemoteQSupported();
170314564Sdim  }
171314564Sdim  return m_supports_qXfer_libraries_read == eLazyBoolYes;
172262528Semaste}
173262528Semaste
174314564Sdimbool GDBRemoteCommunicationClient::GetQXferAuxvReadSupported() {
175314564Sdim  if (m_supports_qXfer_auxv_read == eLazyBoolCalculate) {
176314564Sdim    GetRemoteQSupported();
177314564Sdim  }
178314564Sdim  return m_supports_qXfer_auxv_read == eLazyBoolYes;
179276479Sdim}
180276479Sdim
181314564Sdimbool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() {
182314564Sdim  if (m_supports_qXfer_features_read == eLazyBoolCalculate) {
183314564Sdim    GetRemoteQSupported();
184314564Sdim  }
185314564Sdim  return m_supports_qXfer_features_read == eLazyBoolYes;
186288943Sdim}
187288943Sdim
188341825Sdimbool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
189341825Sdim  if (m_supports_qXfer_memory_map_read == eLazyBoolCalculate) {
190341825Sdim    GetRemoteQSupported();
191341825Sdim  }
192341825Sdim  return m_supports_qXfer_memory_map_read == eLazyBoolYes;
193341825Sdim}
194341825Sdim
195314564Sdimuint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
196314564Sdim  if (m_max_packet_size == 0) {
197314564Sdim    GetRemoteQSupported();
198314564Sdim  }
199314564Sdim  return m_max_packet_size;
200262528Semaste}
201262528Semaste
202314564Sdimbool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
203314564Sdim  if (m_supports_not_sending_acks == eLazyBoolCalculate) {
204314564Sdim    m_send_acks = true;
205314564Sdim    m_supports_not_sending_acks = eLazyBoolNo;
206254721Semaste
207314564Sdim    // This is the first real packet that we'll send in a debug session and it
208341825Sdim    // may take a little longer than normal to receive a reply.  Wait at least
209341825Sdim    // 6 seconds for a reply to this packet.
210276479Sdim
211314564Sdim    ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
212276479Sdim
213314564Sdim    StringExtractorGDBRemote response;
214314564Sdim    if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) ==
215314564Sdim        PacketResult::Success) {
216314564Sdim      if (response.IsOKResponse()) {
217314564Sdim        m_send_acks = false;
218314564Sdim        m_supports_not_sending_acks = eLazyBoolYes;
219314564Sdim      }
220314564Sdim      return true;
221254721Semaste    }
222314564Sdim  }
223314564Sdim  return false;
224254721Semaste}
225254721Semaste
226314564Sdimvoid GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() {
227314564Sdim  if (m_supports_threads_in_stop_reply == eLazyBoolCalculate) {
228314564Sdim    m_supports_threads_in_stop_reply = eLazyBoolNo;
229314564Sdim
230314564Sdim    StringExtractorGDBRemote response;
231314564Sdim    if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response,
232314564Sdim                                     false) == PacketResult::Success) {
233314564Sdim      if (response.IsOKResponse())
234314564Sdim        m_supports_threads_in_stop_reply = eLazyBoolYes;
235254721Semaste    }
236314564Sdim  }
237254721Semaste}
238254721Semaste
239314564Sdimbool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() {
240314564Sdim  if (m_attach_or_wait_reply == eLazyBoolCalculate) {
241314564Sdim    m_attach_or_wait_reply = eLazyBoolNo;
242314564Sdim
243314564Sdim    StringExtractorGDBRemote response;
244314564Sdim    if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response,
245314564Sdim                                     false) == PacketResult::Success) {
246314564Sdim      if (response.IsOKResponse())
247314564Sdim        m_attach_or_wait_reply = eLazyBoolYes;
248254721Semaste    }
249314564Sdim  }
250344779Sdim  return m_attach_or_wait_reply == eLazyBoolYes;
251254721Semaste}
252254721Semaste
253314564Sdimbool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
254314564Sdim  if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) {
255314564Sdim    m_prepare_for_reg_writing_reply = eLazyBoolNo;
256314564Sdim
257314564Sdim    StringExtractorGDBRemote response;
258314564Sdim    if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response,
259314564Sdim                                     false) == PacketResult::Success) {
260314564Sdim      if (response.IsOKResponse())
261314564Sdim        m_prepare_for_reg_writing_reply = eLazyBoolYes;
262254721Semaste    }
263314564Sdim  }
264344779Sdim  return m_prepare_for_reg_writing_reply == eLazyBoolYes;
265254721Semaste}
266254721Semaste
267314564Sdimvoid GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
268344779Sdim  if (!did_exec) {
269314564Sdim    // Hard reset everything, this is when we first connect to a GDB server
270314564Sdim    m_supports_not_sending_acks = eLazyBoolCalculate;
271314564Sdim    m_supports_thread_suffix = eLazyBoolCalculate;
272314564Sdim    m_supports_threads_in_stop_reply = eLazyBoolCalculate;
273314564Sdim    m_supports_vCont_c = eLazyBoolCalculate;
274314564Sdim    m_supports_vCont_C = eLazyBoolCalculate;
275314564Sdim    m_supports_vCont_s = eLazyBoolCalculate;
276314564Sdim    m_supports_vCont_S = eLazyBoolCalculate;
277314564Sdim    m_supports_p = eLazyBoolCalculate;
278314564Sdim    m_supports_x = eLazyBoolCalculate;
279314564Sdim    m_supports_QSaveRegisterState = eLazyBoolCalculate;
280314564Sdim    m_qHostInfo_is_valid = eLazyBoolCalculate;
281314564Sdim    m_curr_pid_is_valid = eLazyBoolCalculate;
282314564Sdim    m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
283314564Sdim    m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
284314564Sdim    m_supports_memory_region_info = eLazyBoolCalculate;
285314564Sdim    m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
286314564Sdim    m_attach_or_wait_reply = eLazyBoolCalculate;
287314564Sdim    m_avoid_g_packets = eLazyBoolCalculate;
288314564Sdim    m_supports_qXfer_auxv_read = eLazyBoolCalculate;
289314564Sdim    m_supports_qXfer_libraries_read = eLazyBoolCalculate;
290314564Sdim    m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
291314564Sdim    m_supports_qXfer_features_read = eLazyBoolCalculate;
292341825Sdim    m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
293314564Sdim    m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
294314564Sdim    m_supports_qProcessInfoPID = true;
295314564Sdim    m_supports_qfProcessInfo = true;
296314564Sdim    m_supports_qUserName = true;
297314564Sdim    m_supports_qGroupName = true;
298314564Sdim    m_supports_qThreadStopInfo = true;
299314564Sdim    m_supports_z0 = true;
300314564Sdim    m_supports_z1 = true;
301314564Sdim    m_supports_z2 = true;
302314564Sdim    m_supports_z3 = true;
303314564Sdim    m_supports_z4 = true;
304314564Sdim    m_supports_QEnvironment = true;
305314564Sdim    m_supports_QEnvironmentHexEncoded = true;
306314564Sdim    m_supports_qSymbol = true;
307314564Sdim    m_qSymbol_requests_done = false;
308314564Sdim    m_supports_qModuleInfo = true;
309314564Sdim    m_host_arch.Clear();
310341825Sdim    m_os_version = llvm::VersionTuple();
311314564Sdim    m_os_build.clear();
312314564Sdim    m_os_kernel.clear();
313314564Sdim    m_hostname.clear();
314314564Sdim    m_gdb_server_name.clear();
315314564Sdim    m_gdb_server_version = UINT32_MAX;
316314564Sdim    m_default_packet_timeout = seconds(0);
317314564Sdim    m_max_packet_size = 0;
318314564Sdim    m_qSupported_response.clear();
319314564Sdim    m_supported_async_json_packets_is_valid = false;
320314564Sdim    m_supported_async_json_packets_sp.reset();
321314564Sdim    m_supports_jModulesInfo = true;
322314564Sdim  }
323254721Semaste
324341825Sdim  // These flags should be reset when we first connect to a GDB server and when
325341825Sdim  // our inferior process execs
326314564Sdim  m_qProcessInfo_is_valid = eLazyBoolCalculate;
327314564Sdim  m_process_arch.Clear();
328254721Semaste}
329254721Semaste
330314564Sdimvoid GDBRemoteCommunicationClient::GetRemoteQSupported() {
331314564Sdim  // Clear out any capabilities we expect to see in the qSupported response
332314564Sdim  m_supports_qXfer_auxv_read = eLazyBoolNo;
333314564Sdim  m_supports_qXfer_libraries_read = eLazyBoolNo;
334314564Sdim  m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
335314564Sdim  m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
336314564Sdim  m_supports_qXfer_features_read = eLazyBoolNo;
337341825Sdim  m_supports_qXfer_memory_map_read = eLazyBoolNo;
338314564Sdim  m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
339314564Sdim                                  // not, we assume no limit
340254721Semaste
341314564Sdim  // build the qSupported packet
342360784Sdim  std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc"};
343314564Sdim  StreamString packet;
344314564Sdim  packet.PutCString("qSupported");
345314564Sdim  for (uint32_t i = 0; i < features.size(); ++i) {
346314564Sdim    packet.PutCString(i == 0 ? ":" : ";");
347314564Sdim    packet.PutCString(features[i]);
348314564Sdim  }
349288943Sdim
350314564Sdim  StringExtractorGDBRemote response;
351314564Sdim  if (SendPacketAndWaitForResponse(packet.GetString(), response,
352314564Sdim                                   /*send_async=*/false) ==
353314564Sdim      PacketResult::Success) {
354360784Sdim    const char *response_cstr = response.GetStringRef().data();
355262528Semaste
356314564Sdim    // Hang on to the qSupported packet, so that platforms can do custom
357341825Sdim    // configuration of the transport before attaching/launching the process.
358314564Sdim    m_qSupported_response = response_cstr;
359288943Sdim
360314564Sdim    if (::strstr(response_cstr, "qXfer:auxv:read+"))
361314564Sdim      m_supports_qXfer_auxv_read = eLazyBoolYes;
362314564Sdim    if (::strstr(response_cstr, "qXfer:libraries-svr4:read+"))
363314564Sdim      m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
364314564Sdim    if (::strstr(response_cstr, "augmented-libraries-svr4-read")) {
365314564Sdim      m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
366314564Sdim      m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
367314564Sdim    }
368314564Sdim    if (::strstr(response_cstr, "qXfer:libraries:read+"))
369314564Sdim      m_supports_qXfer_libraries_read = eLazyBoolYes;
370314564Sdim    if (::strstr(response_cstr, "qXfer:features:read+"))
371314564Sdim      m_supports_qXfer_features_read = eLazyBoolYes;
372341825Sdim    if (::strstr(response_cstr, "qXfer:memory-map:read+"))
373341825Sdim      m_supports_qXfer_memory_map_read = eLazyBoolYes;
374288943Sdim
375314564Sdim    // Look for a list of compressions in the features list e.g.
376341825Sdim    // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
377341825Sdim    // deflate,lzma
378314564Sdim    const char *features_list = ::strstr(response_cstr, "qXfer:features:");
379314564Sdim    if (features_list) {
380314564Sdim      const char *compressions =
381314564Sdim          ::strstr(features_list, "SupportedCompressions=");
382314564Sdim      if (compressions) {
383314564Sdim        std::vector<std::string> supported_compressions;
384314564Sdim        compressions += sizeof("SupportedCompressions=") - 1;
385314564Sdim        const char *end_of_compressions = strchr(compressions, ';');
386353358Sdim        if (end_of_compressions == nullptr) {
387314564Sdim          end_of_compressions = strchr(compressions, '\0');
388314564Sdim        }
389314564Sdim        const char *current_compression = compressions;
390314564Sdim        while (current_compression < end_of_compressions) {
391314564Sdim          const char *next_compression_name = strchr(current_compression, ',');
392314564Sdim          const char *end_of_this_word = next_compression_name;
393353358Sdim          if (next_compression_name == nullptr ||
394314564Sdim              end_of_compressions < next_compression_name) {
395314564Sdim            end_of_this_word = end_of_compressions;
396314564Sdim          }
397288943Sdim
398314564Sdim          if (end_of_this_word) {
399314564Sdim            if (end_of_this_word == current_compression) {
400314564Sdim              current_compression++;
401314564Sdim            } else {
402314564Sdim              std::string this_compression(
403314564Sdim                  current_compression, end_of_this_word - current_compression);
404314564Sdim              supported_compressions.push_back(this_compression);
405314564Sdim              current_compression = end_of_this_word + 1;
406288943Sdim            }
407314564Sdim          } else {
408314564Sdim            supported_compressions.push_back(current_compression);
409314564Sdim            current_compression = end_of_compressions;
410314564Sdim          }
411288943Sdim        }
412288943Sdim
413314564Sdim        if (supported_compressions.size() > 0) {
414314564Sdim          MaybeEnableCompression(supported_compressions);
415262528Semaste        }
416314564Sdim      }
417262528Semaste    }
418314564Sdim
419314564Sdim    if (::strstr(response_cstr, "qEcho"))
420314564Sdim      m_supports_qEcho = eLazyBoolYes;
421314564Sdim    else
422314564Sdim      m_supports_qEcho = eLazyBoolNo;
423314564Sdim
424321369Sdim    if (::strstr(response_cstr, "QPassSignals+"))
425321369Sdim      m_supports_QPassSignals = eLazyBoolYes;
426321369Sdim    else
427321369Sdim      m_supports_QPassSignals = eLazyBoolNo;
428321369Sdim
429314564Sdim    const char *packet_size_str = ::strstr(response_cstr, "PacketSize=");
430314564Sdim    if (packet_size_str) {
431314564Sdim      StringExtractorGDBRemote packet_response(packet_size_str +
432314564Sdim                                               strlen("PacketSize="));
433314564Sdim      m_max_packet_size =
434314564Sdim          packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
435314564Sdim      if (m_max_packet_size == 0) {
436314564Sdim        m_max_packet_size = UINT64_MAX; // Must have been a garbled response
437314564Sdim        Log *log(
438314564Sdim            ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
439360784Sdim        LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response");
440314564Sdim      }
441314564Sdim    }
442314564Sdim  }
443262528Semaste}
444262528Semaste
445314564Sdimbool GDBRemoteCommunicationClient::GetThreadSuffixSupported() {
446314564Sdim  if (m_supports_thread_suffix == eLazyBoolCalculate) {
447314564Sdim    StringExtractorGDBRemote response;
448314564Sdim    m_supports_thread_suffix = eLazyBoolNo;
449314564Sdim    if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response,
450314564Sdim                                     false) == PacketResult::Success) {
451314564Sdim      if (response.IsOKResponse())
452314564Sdim        m_supports_thread_suffix = eLazyBoolYes;
453254721Semaste    }
454314564Sdim  }
455314564Sdim  return m_supports_thread_suffix;
456254721Semaste}
457314564Sdimbool GDBRemoteCommunicationClient::GetVContSupported(char flavor) {
458314564Sdim  if (m_supports_vCont_c == eLazyBoolCalculate) {
459314564Sdim    StringExtractorGDBRemote response;
460314564Sdim    m_supports_vCont_any = eLazyBoolNo;
461314564Sdim    m_supports_vCont_all = eLazyBoolNo;
462314564Sdim    m_supports_vCont_c = eLazyBoolNo;
463314564Sdim    m_supports_vCont_C = eLazyBoolNo;
464314564Sdim    m_supports_vCont_s = eLazyBoolNo;
465314564Sdim    m_supports_vCont_S = eLazyBoolNo;
466314564Sdim    if (SendPacketAndWaitForResponse("vCont?", response, false) ==
467314564Sdim        PacketResult::Success) {
468360784Sdim      const char *response_cstr = response.GetStringRef().data();
469314564Sdim      if (::strstr(response_cstr, ";c"))
470314564Sdim        m_supports_vCont_c = eLazyBoolYes;
471254721Semaste
472314564Sdim      if (::strstr(response_cstr, ";C"))
473314564Sdim        m_supports_vCont_C = eLazyBoolYes;
474254721Semaste
475314564Sdim      if (::strstr(response_cstr, ";s"))
476314564Sdim        m_supports_vCont_s = eLazyBoolYes;
477254721Semaste
478314564Sdim      if (::strstr(response_cstr, ";S"))
479314564Sdim        m_supports_vCont_S = eLazyBoolYes;
480254721Semaste
481314564Sdim      if (m_supports_vCont_c == eLazyBoolYes &&
482314564Sdim          m_supports_vCont_C == eLazyBoolYes &&
483314564Sdim          m_supports_vCont_s == eLazyBoolYes &&
484314564Sdim          m_supports_vCont_S == eLazyBoolYes) {
485314564Sdim        m_supports_vCont_all = eLazyBoolYes;
486314564Sdim      }
487314564Sdim
488314564Sdim      if (m_supports_vCont_c == eLazyBoolYes ||
489314564Sdim          m_supports_vCont_C == eLazyBoolYes ||
490314564Sdim          m_supports_vCont_s == eLazyBoolYes ||
491314564Sdim          m_supports_vCont_S == eLazyBoolYes) {
492314564Sdim        m_supports_vCont_any = eLazyBoolYes;
493314564Sdim      }
494254721Semaste    }
495314564Sdim  }
496314564Sdim
497314564Sdim  switch (flavor) {
498314564Sdim  case 'a':
499314564Sdim    return m_supports_vCont_any;
500314564Sdim  case 'A':
501314564Sdim    return m_supports_vCont_all;
502314564Sdim  case 'c':
503314564Sdim    return m_supports_vCont_c;
504314564Sdim  case 'C':
505314564Sdim    return m_supports_vCont_C;
506314564Sdim  case 's':
507314564Sdim    return m_supports_vCont_s;
508314564Sdim  case 'S':
509314564Sdim    return m_supports_vCont_S;
510314564Sdim  default:
511314564Sdim    break;
512314564Sdim  }
513314564Sdim  return false;
514254721Semaste}
515254721Semaste
516314564SdimGDBRemoteCommunication::PacketResult
517314564SdimGDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
518314564Sdim    lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response,
519314564Sdim    bool send_async) {
520314564Sdim  Lock lock(*this, send_async);
521314564Sdim  if (!lock) {
522314564Sdim    if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
523314564Sdim            GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
524360784Sdim      LLDB_LOGF(log,
525360784Sdim                "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex "
526360784Sdim                "for %s packet.",
527360784Sdim                __FUNCTION__, payload.GetData());
528314564Sdim    return PacketResult::ErrorNoSequenceLock;
529314564Sdim  }
530314564Sdim
531314564Sdim  if (GetThreadSuffixSupported())
532314564Sdim    payload.Printf(";thread:%4.4" PRIx64 ";", tid);
533314564Sdim  else {
534314564Sdim    if (!SetCurrentThread(tid))
535314564Sdim      return PacketResult::ErrorSendFailed;
536314564Sdim  }
537314564Sdim
538314564Sdim  return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
539314564Sdim}
540314564Sdim
541341825Sdim// Check if the target supports 'p' packet. It sends out a 'p' packet and
542341825Sdim// checks the response. A normal packet will tell us that support is available.
543258054Semaste//
544258054Semaste// Takes a valid thread ID because p needs to apply to a thread.
545314564Sdimbool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
546360784Sdim  if (m_supports_p == eLazyBoolCalculate)
547360784Sdim    m_supports_p = GetThreadPacketSupported(tid, "p0");
548314564Sdim  return m_supports_p;
549258054Semaste}
550254721Semaste
551360784SdimLazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported(
552360784Sdim    lldb::tid_t tid, llvm::StringRef packetStr) {
553360784Sdim  StreamString payload;
554360784Sdim  payload.PutCString(packetStr);
555360784Sdim  StringExtractorGDBRemote response;
556360784Sdim  if (SendThreadSpecificPacketAndWaitForResponse(
557360784Sdim          tid, std::move(payload), response, false) == PacketResult::Success &&
558360784Sdim      response.IsNormalResponse()) {
559360784Sdim    return eLazyBoolYes;
560360784Sdim  }
561360784Sdim  return eLazyBoolNo;
562360784Sdim}
563360784Sdim
564314564SdimStructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
565314564Sdim  // Get information on all threads at one using the "jThreadsInfo" packet
566314564Sdim  StructuredData::ObjectSP object_sp;
567288943Sdim
568314564Sdim  if (m_supports_jThreadsInfo) {
569314564Sdim    StringExtractorGDBRemote response;
570314564Sdim    response.SetResponseValidatorToJSON();
571314564Sdim    if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) ==
572314564Sdim        PacketResult::Success) {
573314564Sdim      if (response.IsUnsupportedResponse()) {
574314564Sdim        m_supports_jThreadsInfo = false;
575314564Sdim      } else if (!response.Empty()) {
576314564Sdim        object_sp = StructuredData::ParseJSON(response.GetStringRef());
577314564Sdim      }
578288943Sdim    }
579314564Sdim  }
580314564Sdim  return object_sp;
581288943Sdim}
582288943Sdim
583314564Sdimbool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
584314564Sdim  if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) {
585314564Sdim    StringExtractorGDBRemote response;
586314564Sdim    m_supports_jThreadExtendedInfo = eLazyBoolNo;
587314564Sdim    if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) ==
588314564Sdim        PacketResult::Success) {
589314564Sdim      if (response.IsOKResponse()) {
590314564Sdim        m_supports_jThreadExtendedInfo = eLazyBoolYes;
591314564Sdim      }
592276479Sdim    }
593314564Sdim  }
594314564Sdim  return m_supports_jThreadExtendedInfo;
595276479Sdim}
596276479Sdim
597321369Sdimvoid GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
598321369Sdim  if (m_supports_error_string_reply == eLazyBoolCalculate) {
599321369Sdim    StringExtractorGDBRemote response;
600341825Sdim    // We try to enable error strings in remote packets but if we fail, we just
601341825Sdim    // work in the older way.
602321369Sdim    m_supports_error_string_reply = eLazyBoolNo;
603321369Sdim    if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) ==
604321369Sdim        PacketResult::Success) {
605321369Sdim      if (response.IsOKResponse()) {
606321369Sdim        m_supports_error_string_reply = eLazyBoolYes;
607321369Sdim      }
608321369Sdim    }
609321369Sdim  }
610321369Sdim}
611321369Sdim
612314564Sdimbool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() {
613314564Sdim  if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) {
614314564Sdim    StringExtractorGDBRemote response;
615314564Sdim    m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
616314564Sdim    if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:",
617314564Sdim                                     response,
618314564Sdim                                     false) == PacketResult::Success) {
619314564Sdim      if (response.IsOKResponse()) {
620314564Sdim        m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
621314564Sdim      }
622288943Sdim    }
623314564Sdim  }
624314564Sdim  return m_supports_jLoadedDynamicLibrariesInfos;
625288943Sdim}
626288943Sdim
627314564Sdimbool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() {
628314564Sdim  if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) {
629314564Sdim    StringExtractorGDBRemote response;
630314564Sdim    m_supports_jGetSharedCacheInfo = eLazyBoolNo;
631314564Sdim    if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) ==
632314564Sdim        PacketResult::Success) {
633314564Sdim      if (response.IsOKResponse()) {
634314564Sdim        m_supports_jGetSharedCacheInfo = eLazyBoolYes;
635314564Sdim      }
636276479Sdim    }
637314564Sdim  }
638314564Sdim  return m_supports_jGetSharedCacheInfo;
639276479Sdim}
640276479Sdim
641314564Sdimbool GDBRemoteCommunicationClient::GetxPacketSupported() {
642314564Sdim  if (m_supports_x == eLazyBoolCalculate) {
643314564Sdim    StringExtractorGDBRemote response;
644314564Sdim    m_supports_x = eLazyBoolNo;
645314564Sdim    char packet[256];
646314564Sdim    snprintf(packet, sizeof(packet), "x0,0");
647314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
648314564Sdim        PacketResult::Success) {
649314564Sdim      if (response.IsOKResponse())
650314564Sdim        m_supports_x = eLazyBoolYes;
651262528Semaste    }
652314564Sdim  }
653314564Sdim  return m_supports_x;
654262528Semaste}
655262528Semaste
656262528SemasteGDBRemoteCommunicationClient::PacketResult
657314564SdimGDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses(
658314564Sdim    const char *payload_prefix, std::string &response_string) {
659314564Sdim  Lock lock(*this, false);
660314564Sdim  if (!lock) {
661314564Sdim    Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
662314564Sdim                                                           GDBR_LOG_PACKETS));
663360784Sdim    LLDB_LOGF(log,
664360784Sdim              "error: failed to get packet sequence mutex, not sending "
665360784Sdim              "packets with prefix '%s'",
666360784Sdim              payload_prefix);
667314564Sdim    return PacketResult::ErrorNoSequenceLock;
668314564Sdim  }
669254721Semaste
670314564Sdim  response_string = "";
671314564Sdim  std::string payload_prefix_str(payload_prefix);
672314564Sdim  unsigned int response_size = 0x1000;
673314564Sdim  if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet
674314564Sdim    response_size = GetRemoteMaxPacketSize();
675314564Sdim  }
676262528Semaste
677314564Sdim  for (unsigned int offset = 0; true; offset += response_size) {
678314564Sdim    StringExtractorGDBRemote this_response;
679314564Sdim    // Construct payload
680314564Sdim    char sizeDescriptor[128];
681314564Sdim    snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset,
682314564Sdim             response_size);
683314564Sdim    PacketResult result = SendPacketAndWaitForResponseNoLock(
684314564Sdim        payload_prefix_str + sizeDescriptor, this_response);
685314564Sdim    if (result != PacketResult::Success)
686314564Sdim      return result;
687288943Sdim
688314564Sdim    const std::string &this_string = this_response.GetStringRef();
689288943Sdim
690314564Sdim    // Check for m or l as first character; l seems to mean this is the last
691314564Sdim    // chunk
692314564Sdim    char first_char = *this_string.c_str();
693314564Sdim    if (first_char != 'm' && first_char != 'l') {
694314564Sdim      return PacketResult::ErrorReplyInvalid;
695254721Semaste    }
696314564Sdim    // Concatenate the result so far (skipping 'm' or 'l')
697314564Sdim    response_string.append(this_string, 1, std::string::npos);
698314564Sdim    if (first_char == 'l')
699314564Sdim      // We're done
700314564Sdim      return PacketResult::Success;
701314564Sdim  }
702254721Semaste}
703254721Semaste
704314564Sdimlldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
705314564Sdim  if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes)
706314564Sdim    return m_curr_pid;
707254721Semaste
708314564Sdim  // First try to retrieve the pid via the qProcessInfo request.
709314564Sdim  GetCurrentProcessInfo(allow_lazy);
710314564Sdim  if (m_curr_pid_is_valid == eLazyBoolYes) {
711314564Sdim    // We really got it.
712314564Sdim    return m_curr_pid;
713314564Sdim  } else {
714314564Sdim    // If we don't get a response for qProcessInfo, check if $qC gives us a
715341825Sdim    // result. $qC only returns a real process id on older debugserver and
716341825Sdim    // lldb-platform stubs. The gdb remote protocol documents $qC as returning
717341825Sdim    // the thread id, which newer debugserver and lldb-gdbserver stubs return
718341825Sdim    // correctly.
719314564Sdim    StringExtractorGDBRemote response;
720314564Sdim    if (SendPacketAndWaitForResponse("qC", response, false) ==
721314564Sdim        PacketResult::Success) {
722314564Sdim      if (response.GetChar() == 'Q') {
723314564Sdim        if (response.GetChar() == 'C') {
724314564Sdim          m_curr_pid = response.GetHexMaxU32(false, LLDB_INVALID_PROCESS_ID);
725314564Sdim          if (m_curr_pid != LLDB_INVALID_PROCESS_ID) {
726314564Sdim            m_curr_pid_is_valid = eLazyBoolYes;
727314564Sdim            return m_curr_pid;
728314564Sdim          }
729254721Semaste        }
730314564Sdim      }
731254721Semaste    }
732254721Semaste
733314564Sdim    // If we don't get a response for $qC, check if $qfThreadID gives us a
734314564Sdim    // result.
735314564Sdim    if (m_curr_pid == LLDB_INVALID_PROCESS_ID) {
736314564Sdim      std::vector<lldb::tid_t> thread_ids;
737314564Sdim      bool sequence_mutex_unavailable;
738314564Sdim      size_t size;
739314564Sdim      size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable);
740344779Sdim      if (size && !sequence_mutex_unavailable) {
741314564Sdim        m_curr_pid = thread_ids.front();
742314564Sdim        m_curr_pid_is_valid = eLazyBoolYes;
743314564Sdim        return m_curr_pid;
744314564Sdim      }
745288943Sdim    }
746314564Sdim  }
747288943Sdim
748314564Sdim  return LLDB_INVALID_PROCESS_ID;
749288943Sdim}
750288943Sdim
751314564Sdimbool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) {
752314564Sdim  error_str.clear();
753314564Sdim  StringExtractorGDBRemote response;
754314564Sdim  if (SendPacketAndWaitForResponse("qLaunchSuccess", response, false) ==
755314564Sdim      PacketResult::Success) {
756314564Sdim    if (response.IsOKResponse())
757314564Sdim      return true;
758314564Sdim    if (response.GetChar() == 'E') {
759314564Sdim      // A string the describes what failed when launching...
760314564Sdim      error_str = response.GetStringRef().substr(1);
761314564Sdim    } else {
762314564Sdim      error_str.assign("unknown error occurred launching process");
763254721Semaste    }
764314564Sdim  } else {
765314564Sdim    error_str.assign("timed out waiting for app to launch");
766314564Sdim  }
767314564Sdim  return false;
768254721Semaste}
769254721Semaste
770314564Sdimint GDBRemoteCommunicationClient::SendArgumentsPacket(
771314564Sdim    const ProcessLaunchInfo &launch_info) {
772314564Sdim  // Since we don't get the send argv0 separate from the executable path, we
773341825Sdim  // need to make sure to use the actual executable path found in the
774341825Sdim  // launch_info...
775314564Sdim  std::vector<const char *> argv;
776314564Sdim  FileSpec exe_file = launch_info.GetExecutableFile();
777314564Sdim  std::string exe_path;
778353358Sdim  const char *arg = nullptr;
779314564Sdim  const Args &launch_args = launch_info.GetArguments();
780314564Sdim  if (exe_file)
781314564Sdim    exe_path = exe_file.GetPath(false);
782314564Sdim  else {
783314564Sdim    arg = launch_args.GetArgumentAtIndex(0);
784314564Sdim    if (arg)
785314564Sdim      exe_path = arg;
786314564Sdim  }
787314564Sdim  if (!exe_path.empty()) {
788314564Sdim    argv.push_back(exe_path.c_str());
789353358Sdim    for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != nullptr;
790314564Sdim         ++i) {
791314564Sdim      if (arg)
792314564Sdim        argv.push_back(arg);
793254721Semaste    }
794314564Sdim  }
795314564Sdim  if (!argv.empty()) {
796314564Sdim    StreamString packet;
797314564Sdim    packet.PutChar('A');
798314564Sdim    for (size_t i = 0, n = argv.size(); i < n; ++i) {
799314564Sdim      arg = argv[i];
800314564Sdim      const int arg_len = strlen(arg);
801314564Sdim      if (i > 0)
802314564Sdim        packet.PutChar(',');
803314564Sdim      packet.Printf("%i,%i,", arg_len * 2, (int)i);
804314564Sdim      packet.PutBytesAsRawHex8(arg, arg_len);
805254721Semaste    }
806254721Semaste
807254721Semaste    StringExtractorGDBRemote response;
808314564Sdim    if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
809314564Sdim        PacketResult::Success) {
810314564Sdim      if (response.IsOKResponse())
811314564Sdim        return 0;
812314564Sdim      uint8_t error = response.GetError();
813314564Sdim      if (error)
814314564Sdim        return error;
815254721Semaste    }
816314564Sdim  }
817314564Sdim  return -1;
818254721Semaste}
819254721Semaste
820341825Sdimint GDBRemoteCommunicationClient::SendEnvironment(const Environment &env) {
821341825Sdim  for (const auto &KV : env) {
822341825Sdim    int r = SendEnvironmentPacket(Environment::compose(KV).c_str());
823341825Sdim    if (r != 0)
824341825Sdim      return r;
825341825Sdim  }
826341825Sdim  return 0;
827341825Sdim}
828341825Sdim
829314564Sdimint GDBRemoteCommunicationClient::SendEnvironmentPacket(
830314564Sdim    char const *name_equal_value) {
831314564Sdim  if (name_equal_value && name_equal_value[0]) {
832314564Sdim    StreamString packet;
833314564Sdim    bool send_hex_encoding = false;
834344779Sdim    for (const char *p = name_equal_value; *p != '\0' && !send_hex_encoding;
835344779Sdim         ++p) {
836314564Sdim      if (isprint(*p)) {
837314564Sdim        switch (*p) {
838314564Sdim        case '$':
839314564Sdim        case '#':
840314564Sdim        case '*':
841314564Sdim        case '}':
842314564Sdim          send_hex_encoding = true;
843314564Sdim          break;
844314564Sdim        default:
845314564Sdim          break;
846258884Semaste        }
847314564Sdim      } else {
848314564Sdim        // We have non printable characters, lets hex encode this...
849314564Sdim        send_hex_encoding = true;
850314564Sdim      }
851258884Semaste    }
852254721Semaste
853314564Sdim    StringExtractorGDBRemote response;
854314564Sdim    if (send_hex_encoding) {
855314564Sdim      if (m_supports_QEnvironmentHexEncoded) {
856314564Sdim        packet.PutCString("QEnvironmentHexEncoded:");
857314564Sdim        packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value));
858314564Sdim        if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
859314564Sdim            PacketResult::Success) {
860314564Sdim          if (response.IsOKResponse())
861314564Sdim            return 0;
862314564Sdim          uint8_t error = response.GetError();
863314564Sdim          if (error)
864314564Sdim            return error;
865314564Sdim          if (response.IsUnsupportedResponse())
866314564Sdim            m_supports_QEnvironmentHexEncoded = false;
867254721Semaste        }
868314564Sdim      }
869254721Semaste
870314564Sdim    } else if (m_supports_QEnvironment) {
871314564Sdim      packet.Printf("QEnvironment:%s", name_equal_value);
872314564Sdim      if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
873314564Sdim          PacketResult::Success) {
874314564Sdim        if (response.IsOKResponse())
875314564Sdim          return 0;
876314564Sdim        uint8_t error = response.GetError();
877314564Sdim        if (error)
878314564Sdim          return error;
879314564Sdim        if (response.IsUnsupportedResponse())
880314564Sdim          m_supports_QEnvironment = false;
881314564Sdim      }
882254721Semaste    }
883314564Sdim  }
884314564Sdim  return -1;
885254721Semaste}
886254721Semaste
887314564Sdimint GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) {
888314564Sdim  if (arch && arch[0]) {
889314564Sdim    StreamString packet;
890314564Sdim    packet.Printf("QLaunchArch:%s", arch);
891314564Sdim    StringExtractorGDBRemote response;
892314564Sdim    if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
893314564Sdim        PacketResult::Success) {
894314564Sdim      if (response.IsOKResponse())
895314564Sdim        return 0;
896314564Sdim      uint8_t error = response.GetError();
897314564Sdim      if (error)
898314564Sdim        return error;
899254721Semaste    }
900314564Sdim  }
901314564Sdim  return -1;
902254721Semaste}
903254721Semaste
904314564Sdimint GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
905314564Sdim    char const *data, bool *was_supported) {
906314564Sdim  if (data && *data != '\0') {
907314564Sdim    StreamString packet;
908314564Sdim    packet.Printf("QSetProcessEvent:%s", data);
909314564Sdim    StringExtractorGDBRemote response;
910314564Sdim    if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
911314564Sdim        PacketResult::Success) {
912314564Sdim      if (response.IsOKResponse()) {
913314564Sdim        if (was_supported)
914314564Sdim          *was_supported = true;
915314564Sdim        return 0;
916314564Sdim      } else if (response.IsUnsupportedResponse()) {
917314564Sdim        if (was_supported)
918314564Sdim          *was_supported = false;
919314564Sdim        return -1;
920314564Sdim      } else {
921314564Sdim        uint8_t error = response.GetError();
922314564Sdim        if (was_supported)
923314564Sdim          *was_supported = true;
924314564Sdim        if (error)
925314564Sdim          return error;
926314564Sdim      }
927276479Sdim    }
928314564Sdim  }
929314564Sdim  return -1;
930276479Sdim}
931276479Sdim
932341825Sdimllvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() {
933341825Sdim  GetHostInfo();
934341825Sdim  return m_os_version;
935254721Semaste}
936254721Semaste
937360784Sdimllvm::VersionTuple GDBRemoteCommunicationClient::GetMacCatalystVersion() {
938360784Sdim  GetHostInfo();
939360784Sdim  return m_maccatalyst_version;
940360784Sdim}
941360784Sdim
942314564Sdimbool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) {
943314564Sdim  if (GetHostInfo()) {
944314564Sdim    if (!m_os_build.empty()) {
945314564Sdim      s = m_os_build;
946314564Sdim      return true;
947254721Semaste    }
948314564Sdim  }
949314564Sdim  s.clear();
950314564Sdim  return false;
951254721Semaste}
952254721Semaste
953314564Sdimbool GDBRemoteCommunicationClient::GetOSKernelDescription(std::string &s) {
954314564Sdim  if (GetHostInfo()) {
955314564Sdim    if (!m_os_kernel.empty()) {
956314564Sdim      s = m_os_kernel;
957314564Sdim      return true;
958254721Semaste    }
959314564Sdim  }
960314564Sdim  s.clear();
961314564Sdim  return false;
962254721Semaste}
963254721Semaste
964314564Sdimbool GDBRemoteCommunicationClient::GetHostname(std::string &s) {
965314564Sdim  if (GetHostInfo()) {
966314564Sdim    if (!m_hostname.empty()) {
967314564Sdim      s = m_hostname;
968314564Sdim      return true;
969254721Semaste    }
970314564Sdim  }
971314564Sdim  s.clear();
972314564Sdim  return false;
973254721Semaste}
974254721Semaste
975314564SdimArchSpec GDBRemoteCommunicationClient::GetSystemArchitecture() {
976314564Sdim  if (GetHostInfo())
977314564Sdim    return m_host_arch;
978314564Sdim  return ArchSpec();
979254721Semaste}
980254721Semaste
981254721Semasteconst lldb_private::ArchSpec &
982314564SdimGDBRemoteCommunicationClient::GetProcessArchitecture() {
983314564Sdim  if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
984314564Sdim    GetCurrentProcessInfo();
985314564Sdim  return m_process_arch;
986254721Semaste}
987254721Semaste
988314564Sdimbool GDBRemoteCommunicationClient::GetGDBServerVersion() {
989314564Sdim  if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
990314564Sdim    m_gdb_server_name.clear();
991314564Sdim    m_gdb_server_version = 0;
992314564Sdim    m_qGDBServerVersion_is_valid = eLazyBoolNo;
993254721Semaste
994314564Sdim    StringExtractorGDBRemote response;
995314564Sdim    if (SendPacketAndWaitForResponse("qGDBServerVersion", response, false) ==
996314564Sdim        PacketResult::Success) {
997314564Sdim      if (response.IsNormalResponse()) {
998314564Sdim        llvm::StringRef name, value;
999314564Sdim        bool success = false;
1000314564Sdim        while (response.GetNameColonValue(name, value)) {
1001314564Sdim          if (name.equals("name")) {
1002314564Sdim            success = true;
1003314564Sdim            m_gdb_server_name = value;
1004314564Sdim          } else if (name.equals("version")) {
1005314564Sdim            llvm::StringRef major, minor;
1006314564Sdim            std::tie(major, minor) = value.split('.');
1007314564Sdim            if (!major.getAsInteger(0, m_gdb_server_version))
1008314564Sdim              success = true;
1009314564Sdim          }
1010276479Sdim        }
1011314564Sdim        if (success)
1012314564Sdim          m_qGDBServerVersion_is_valid = eLazyBoolYes;
1013314564Sdim      }
1014276479Sdim    }
1015314564Sdim  }
1016314564Sdim  return m_qGDBServerVersion_is_valid == eLazyBoolYes;
1017276479Sdim}
1018276479Sdim
1019314564Sdimvoid GDBRemoteCommunicationClient::MaybeEnableCompression(
1020314564Sdim    std::vector<std::string> supported_compressions) {
1021314564Sdim  CompressionType avail_type = CompressionType::None;
1022314564Sdim  std::string avail_name;
1023288943Sdim
1024314564Sdim#if defined(HAVE_LIBCOMPRESSION)
1025327952Sdim  if (avail_type == CompressionType::None) {
1026314564Sdim    for (auto compression : supported_compressions) {
1027314564Sdim      if (compression == "lzfse") {
1028314564Sdim        avail_type = CompressionType::LZFSE;
1029314564Sdim        avail_name = compression;
1030314564Sdim        break;
1031314564Sdim      }
1032288943Sdim    }
1033314564Sdim  }
1034288943Sdim#endif
1035288943Sdim
1036314564Sdim#if defined(HAVE_LIBCOMPRESSION)
1037327952Sdim  if (avail_type == CompressionType::None) {
1038314564Sdim    for (auto compression : supported_compressions) {
1039314564Sdim      if (compression == "zlib-deflate") {
1040314564Sdim        avail_type = CompressionType::ZlibDeflate;
1041314564Sdim        avail_name = compression;
1042314564Sdim        break;
1043314564Sdim      }
1044288943Sdim    }
1045314564Sdim  }
1046288943Sdim#endif
1047288943Sdim
1048314564Sdim#if defined(HAVE_LIBZ)
1049314564Sdim  if (avail_type == CompressionType::None) {
1050314564Sdim    for (auto compression : supported_compressions) {
1051314564Sdim      if (compression == "zlib-deflate") {
1052314564Sdim        avail_type = CompressionType::ZlibDeflate;
1053314564Sdim        avail_name = compression;
1054314564Sdim        break;
1055314564Sdim      }
1056288943Sdim    }
1057314564Sdim  }
1058288943Sdim#endif
1059288943Sdim
1060314564Sdim#if defined(HAVE_LIBCOMPRESSION)
1061327952Sdim  if (avail_type == CompressionType::None) {
1062314564Sdim    for (auto compression : supported_compressions) {
1063314564Sdim      if (compression == "lz4") {
1064314564Sdim        avail_type = CompressionType::LZ4;
1065314564Sdim        avail_name = compression;
1066314564Sdim        break;
1067314564Sdim      }
1068288943Sdim    }
1069314564Sdim  }
1070288943Sdim#endif
1071288943Sdim
1072314564Sdim#if defined(HAVE_LIBCOMPRESSION)
1073327952Sdim  if (avail_type == CompressionType::None) {
1074314564Sdim    for (auto compression : supported_compressions) {
1075314564Sdim      if (compression == "lzma") {
1076314564Sdim        avail_type = CompressionType::LZMA;
1077314564Sdim        avail_name = compression;
1078314564Sdim        break;
1079314564Sdim      }
1080288943Sdim    }
1081314564Sdim  }
1082288943Sdim#endif
1083288943Sdim
1084314564Sdim  if (avail_type != CompressionType::None) {
1085314564Sdim    StringExtractorGDBRemote response;
1086314564Sdim    std::string packet = "QEnableCompression:type:" + avail_name + ";";
1087314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) !=
1088314564Sdim        PacketResult::Success)
1089314564Sdim      return;
1090314564Sdim
1091314564Sdim    if (response.IsOKResponse()) {
1092314564Sdim      m_compression_type = avail_type;
1093288943Sdim    }
1094314564Sdim  }
1095288943Sdim}
1096288943Sdim
1097314564Sdimconst char *GDBRemoteCommunicationClient::GetGDBServerProgramName() {
1098314564Sdim  if (GetGDBServerVersion()) {
1099314564Sdim    if (!m_gdb_server_name.empty())
1100314564Sdim      return m_gdb_server_name.c_str();
1101314564Sdim  }
1102353358Sdim  return nullptr;
1103276479Sdim}
1104276479Sdim
1105314564Sdimuint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() {
1106314564Sdim  if (GetGDBServerVersion())
1107314564Sdim    return m_gdb_server_version;
1108314564Sdim  return 0;
1109276479Sdim}
1110276479Sdim
1111314564Sdimbool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
1112314564Sdim  StringExtractorGDBRemote response;
1113314564Sdim  if (SendPacketAndWaitForResponse("qC", response, false) !=
1114314564Sdim      PacketResult::Success)
1115314564Sdim    return false;
1116288943Sdim
1117314564Sdim  if (!response.IsNormalResponse())
1118314564Sdim    return false;
1119288943Sdim
1120314564Sdim  if (response.GetChar() == 'Q' && response.GetChar() == 'C')
1121314564Sdim    tid = response.GetHexMaxU32(true, -1);
1122288943Sdim
1123314564Sdim  return true;
1124288943Sdim}
1125288943Sdim
1126314564Sdimbool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
1127314564Sdim  Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS));
1128276479Sdim
1129314564Sdim  if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) {
1130344779Sdim    // host info computation can require DNS traffic and shelling out to external processes.
1131344779Sdim    // Increase the timeout to account for that.
1132344779Sdim    ScopedTimeout timeout(*this, seconds(10));
1133314564Sdim    m_qHostInfo_is_valid = eLazyBoolNo;
1134314564Sdim    StringExtractorGDBRemote response;
1135314564Sdim    if (SendPacketAndWaitForResponse("qHostInfo", response, false) ==
1136314564Sdim        PacketResult::Success) {
1137314564Sdim      if (response.IsNormalResponse()) {
1138314564Sdim        llvm::StringRef name;
1139314564Sdim        llvm::StringRef value;
1140314564Sdim        uint32_t cpu = LLDB_INVALID_CPUTYPE;
1141314564Sdim        uint32_t sub = 0;
1142314564Sdim        std::string arch_name;
1143314564Sdim        std::string os_name;
1144360784Sdim        std::string environment;
1145314564Sdim        std::string vendor_name;
1146314564Sdim        std::string triple;
1147314564Sdim        std::string distribution_id;
1148314564Sdim        uint32_t pointer_byte_size = 0;
1149314564Sdim        ByteOrder byte_order = eByteOrderInvalid;
1150314564Sdim        uint32_t num_keys_decoded = 0;
1151314564Sdim        while (response.GetNameColonValue(name, value)) {
1152314564Sdim          if (name.equals("cputype")) {
1153314564Sdim            // exception type in big endian hex
1154314564Sdim            if (!value.getAsInteger(0, cpu))
1155314564Sdim              ++num_keys_decoded;
1156314564Sdim          } else if (name.equals("cpusubtype")) {
1157314564Sdim            // exception count in big endian hex
1158314564Sdim            if (!value.getAsInteger(0, sub))
1159314564Sdim              ++num_keys_decoded;
1160314564Sdim          } else if (name.equals("arch")) {
1161314564Sdim            arch_name = value;
1162314564Sdim            ++num_keys_decoded;
1163314564Sdim          } else if (name.equals("triple")) {
1164314564Sdim            StringExtractor extractor(value);
1165314564Sdim            extractor.GetHexByteString(triple);
1166314564Sdim            ++num_keys_decoded;
1167314564Sdim          } else if (name.equals("distribution_id")) {
1168314564Sdim            StringExtractor extractor(value);
1169314564Sdim            extractor.GetHexByteString(distribution_id);
1170314564Sdim            ++num_keys_decoded;
1171314564Sdim          } else if (name.equals("os_build")) {
1172314564Sdim            StringExtractor extractor(value);
1173314564Sdim            extractor.GetHexByteString(m_os_build);
1174314564Sdim            ++num_keys_decoded;
1175314564Sdim          } else if (name.equals("hostname")) {
1176314564Sdim            StringExtractor extractor(value);
1177314564Sdim            extractor.GetHexByteString(m_hostname);
1178314564Sdim            ++num_keys_decoded;
1179314564Sdim          } else if (name.equals("os_kernel")) {
1180314564Sdim            StringExtractor extractor(value);
1181314564Sdim            extractor.GetHexByteString(m_os_kernel);
1182314564Sdim            ++num_keys_decoded;
1183314564Sdim          } else if (name.equals("ostype")) {
1184360784Sdim            if (value.equals("maccatalyst")) {
1185360784Sdim              os_name = "ios";
1186360784Sdim              environment = "macabi";
1187360784Sdim            } else
1188360784Sdim              os_name = value;
1189314564Sdim            ++num_keys_decoded;
1190314564Sdim          } else if (name.equals("vendor")) {
1191314564Sdim            vendor_name = value;
1192314564Sdim            ++num_keys_decoded;
1193314564Sdim          } else if (name.equals("endian")) {
1194314564Sdim            byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
1195314564Sdim                             .Case("little", eByteOrderLittle)
1196314564Sdim                             .Case("big", eByteOrderBig)
1197314564Sdim                             .Case("pdp", eByteOrderPDP)
1198314564Sdim                             .Default(eByteOrderInvalid);
1199314564Sdim            if (byte_order != eByteOrderInvalid)
1200314564Sdim              ++num_keys_decoded;
1201314564Sdim          } else if (name.equals("ptrsize")) {
1202314564Sdim            if (!value.getAsInteger(0, pointer_byte_size))
1203314564Sdim              ++num_keys_decoded;
1204314564Sdim          } else if (name.equals("os_version") ||
1205314564Sdim                     name.equals(
1206314564Sdim                         "version")) // Older debugserver binaries used the
1207314564Sdim                                     // "version" key instead of
1208314564Sdim                                     // "os_version"...
1209314564Sdim          {
1210341825Sdim            if (!m_os_version.tryParse(value))
1211314564Sdim              ++num_keys_decoded;
1212360784Sdim          } else if (name.equals("maccatalyst_version")) {
1213360784Sdim            if (!m_maccatalyst_version.tryParse(value))
1214360784Sdim              ++num_keys_decoded;
1215314564Sdim          } else if (name.equals("watchpoint_exceptions_received")) {
1216314564Sdim            m_watchpoints_trigger_after_instruction =
1217314564Sdim                llvm::StringSwitch<LazyBool>(value)
1218314564Sdim                    .Case("before", eLazyBoolNo)
1219314564Sdim                    .Case("after", eLazyBoolYes)
1220314564Sdim                    .Default(eLazyBoolCalculate);
1221314564Sdim            if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate)
1222314564Sdim              ++num_keys_decoded;
1223314564Sdim          } else if (name.equals("default_packet_timeout")) {
1224314564Sdim            uint32_t timeout_seconds;
1225314564Sdim            if (!value.getAsInteger(0, timeout_seconds)) {
1226314564Sdim              m_default_packet_timeout = seconds(timeout_seconds);
1227314564Sdim              SetPacketTimeout(m_default_packet_timeout);
1228314564Sdim              ++num_keys_decoded;
1229314564Sdim            }
1230314564Sdim          }
1231314564Sdim        }
1232254721Semaste
1233314564Sdim        if (num_keys_decoded > 0)
1234314564Sdim          m_qHostInfo_is_valid = eLazyBoolYes;
1235254721Semaste
1236314564Sdim        if (triple.empty()) {
1237314564Sdim          if (arch_name.empty()) {
1238314564Sdim            if (cpu != LLDB_INVALID_CPUTYPE) {
1239314564Sdim              m_host_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
1240314564Sdim              if (pointer_byte_size) {
1241314564Sdim                assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1242314564Sdim              }
1243314564Sdim              if (byte_order != eByteOrderInvalid) {
1244314564Sdim                assert(byte_order == m_host_arch.GetByteOrder());
1245314564Sdim              }
1246254721Semaste
1247314564Sdim              if (!vendor_name.empty())
1248314564Sdim                m_host_arch.GetTriple().setVendorName(
1249314564Sdim                    llvm::StringRef(vendor_name));
1250314564Sdim              if (!os_name.empty())
1251314564Sdim                m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name));
1252360784Sdim              if (!environment.empty())
1253360784Sdim                m_host_arch.GetTriple().setEnvironmentName(environment);
1254314564Sdim            }
1255314564Sdim          } else {
1256314564Sdim            std::string triple;
1257314564Sdim            triple += arch_name;
1258314564Sdim            if (!vendor_name.empty() || !os_name.empty()) {
1259314564Sdim              triple += '-';
1260314564Sdim              if (vendor_name.empty())
1261314564Sdim                triple += "unknown";
1262314564Sdim              else
1263314564Sdim                triple += vendor_name;
1264314564Sdim              triple += '-';
1265314564Sdim              if (os_name.empty())
1266314564Sdim                triple += "unknown";
1267314564Sdim              else
1268314564Sdim                triple += os_name;
1269314564Sdim            }
1270314564Sdim            m_host_arch.SetTriple(triple.c_str());
1271276479Sdim
1272314564Sdim            llvm::Triple &host_triple = m_host_arch.GetTriple();
1273314564Sdim            if (host_triple.getVendor() == llvm::Triple::Apple &&
1274314564Sdim                host_triple.getOS() == llvm::Triple::Darwin) {
1275314564Sdim              switch (m_host_arch.GetMachine()) {
1276314564Sdim              case llvm::Triple::aarch64:
1277360784Sdim              case llvm::Triple::aarch64_32:
1278314564Sdim              case llvm::Triple::arm:
1279314564Sdim              case llvm::Triple::thumb:
1280314564Sdim                host_triple.setOS(llvm::Triple::IOS);
1281314564Sdim                break;
1282314564Sdim              default:
1283314564Sdim                host_triple.setOS(llvm::Triple::MacOSX);
1284314564Sdim                break;
1285314564Sdim              }
1286254721Semaste            }
1287314564Sdim            if (pointer_byte_size) {
1288314564Sdim              assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1289314564Sdim            }
1290314564Sdim            if (byte_order != eByteOrderInvalid) {
1291314564Sdim              assert(byte_order == m_host_arch.GetByteOrder());
1292314564Sdim            }
1293314564Sdim          }
1294314564Sdim        } else {
1295314564Sdim          m_host_arch.SetTriple(triple.c_str());
1296314564Sdim          if (pointer_byte_size) {
1297314564Sdim            assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
1298314564Sdim          }
1299314564Sdim          if (byte_order != eByteOrderInvalid) {
1300314564Sdim            assert(byte_order == m_host_arch.GetByteOrder());
1301314564Sdim          }
1302314564Sdim
1303360784Sdim          LLDB_LOGF(log,
1304360784Sdim                    "GDBRemoteCommunicationClient::%s parsed host "
1305360784Sdim                    "architecture as %s, triple as %s from triple text %s",
1306360784Sdim                    __FUNCTION__,
1307360784Sdim                    m_host_arch.GetArchitectureName()
1308360784Sdim                        ? m_host_arch.GetArchitectureName()
1309360784Sdim                        : "<null-arch-name>",
1310360784Sdim                    m_host_arch.GetTriple().getTriple().c_str(),
1311360784Sdim                    triple.c_str());
1312254721Semaste        }
1313314564Sdim        if (!distribution_id.empty())
1314314564Sdim          m_host_arch.SetDistributionId(distribution_id.c_str());
1315314564Sdim      }
1316254721Semaste    }
1317314564Sdim  }
1318314564Sdim  return m_qHostInfo_is_valid == eLazyBoolYes;
1319254721Semaste}
1320254721Semaste
1321314564Sdimint GDBRemoteCommunicationClient::SendAttach(
1322314564Sdim    lldb::pid_t pid, StringExtractorGDBRemote &response) {
1323314564Sdim  if (pid != LLDB_INVALID_PROCESS_ID) {
1324314564Sdim    char packet[64];
1325314564Sdim    const int packet_len =
1326314564Sdim        ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid);
1327314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
1328314564Sdim    assert(packet_len < (int)sizeof(packet));
1329314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
1330314564Sdim        PacketResult::Success) {
1331314564Sdim      if (response.IsErrorResponse())
1332314564Sdim        return response.GetError();
1333314564Sdim      return 0;
1334254721Semaste    }
1335314564Sdim  }
1336314564Sdim  return -1;
1337254721Semaste}
1338254721Semaste
1339314564Sdimint GDBRemoteCommunicationClient::SendStdinNotification(const char *data,
1340314564Sdim                                                        size_t data_len) {
1341314564Sdim  StreamString packet;
1342314564Sdim  packet.PutCString("I");
1343314564Sdim  packet.PutBytesAsRawHex8(data, data_len);
1344314564Sdim  StringExtractorGDBRemote response;
1345314564Sdim  if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
1346314564Sdim      PacketResult::Success) {
1347314564Sdim    return 0;
1348314564Sdim  }
1349314564Sdim  return response.GetError();
1350288943Sdim}
1351288943Sdim
1352254721Semasteconst lldb_private::ArchSpec &
1353314564SdimGDBRemoteCommunicationClient::GetHostArchitecture() {
1354314564Sdim  if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1355314564Sdim    GetHostInfo();
1356314564Sdim  return m_host_arch;
1357254721Semaste}
1358254721Semaste
1359314564Sdimseconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() {
1360314564Sdim  if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1361314564Sdim    GetHostInfo();
1362314564Sdim  return m_default_packet_timeout;
1363258054Semaste}
1364258054Semaste
1365314564Sdimaddr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size,
1366314564Sdim                                                    uint32_t permissions) {
1367314564Sdim  if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
1368314564Sdim    m_supports_alloc_dealloc_memory = eLazyBoolYes;
1369314564Sdim    char packet[64];
1370314564Sdim    const int packet_len = ::snprintf(
1371314564Sdim        packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s", (uint64_t)size,
1372314564Sdim        permissions & lldb::ePermissionsReadable ? "r" : "",
1373314564Sdim        permissions & lldb::ePermissionsWritable ? "w" : "",
1374314564Sdim        permissions & lldb::ePermissionsExecutable ? "x" : "");
1375314564Sdim    assert(packet_len < (int)sizeof(packet));
1376314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
1377314564Sdim    StringExtractorGDBRemote response;
1378314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
1379314564Sdim        PacketResult::Success) {
1380314564Sdim      if (response.IsUnsupportedResponse())
1381314564Sdim        m_supports_alloc_dealloc_memory = eLazyBoolNo;
1382314564Sdim      else if (!response.IsErrorResponse())
1383314564Sdim        return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
1384314564Sdim    } else {
1385314564Sdim      m_supports_alloc_dealloc_memory = eLazyBoolNo;
1386254721Semaste    }
1387314564Sdim  }
1388314564Sdim  return LLDB_INVALID_ADDRESS;
1389254721Semaste}
1390254721Semaste
1391314564Sdimbool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) {
1392314564Sdim  if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
1393314564Sdim    m_supports_alloc_dealloc_memory = eLazyBoolYes;
1394314564Sdim    char packet[64];
1395314564Sdim    const int packet_len =
1396314564Sdim        ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
1397314564Sdim    assert(packet_len < (int)sizeof(packet));
1398314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
1399314564Sdim    StringExtractorGDBRemote response;
1400314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
1401314564Sdim        PacketResult::Success) {
1402314564Sdim      if (response.IsUnsupportedResponse())
1403314564Sdim        m_supports_alloc_dealloc_memory = eLazyBoolNo;
1404314564Sdim      else if (response.IsOKResponse())
1405314564Sdim        return true;
1406314564Sdim    } else {
1407314564Sdim      m_supports_alloc_dealloc_memory = eLazyBoolNo;
1408254721Semaste    }
1409314564Sdim  }
1410314564Sdim  return false;
1411254721Semaste}
1412254721Semaste
1413321369SdimStatus GDBRemoteCommunicationClient::Detach(bool keep_stopped) {
1414321369Sdim  Status error;
1415254721Semaste
1416314564Sdim  if (keep_stopped) {
1417314564Sdim    if (m_supports_detach_stay_stopped == eLazyBoolCalculate) {
1418314564Sdim      char packet[64];
1419314564Sdim      const int packet_len =
1420314564Sdim          ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
1421314564Sdim      assert(packet_len < (int)sizeof(packet));
1422314564Sdim      UNUSED_IF_ASSERT_DISABLED(packet_len);
1423314564Sdim      StringExtractorGDBRemote response;
1424314564Sdim      if (SendPacketAndWaitForResponse(packet, response, false) ==
1425314564Sdim              PacketResult::Success &&
1426314564Sdim          response.IsOKResponse()) {
1427314564Sdim        m_supports_detach_stay_stopped = eLazyBoolYes;
1428314564Sdim      } else {
1429314564Sdim        m_supports_detach_stay_stopped = eLazyBoolNo;
1430314564Sdim      }
1431254721Semaste    }
1432314564Sdim
1433314564Sdim    if (m_supports_detach_stay_stopped == eLazyBoolNo) {
1434314564Sdim      error.SetErrorString("Stays stopped not supported by this target.");
1435314564Sdim      return error;
1436314564Sdim    } else {
1437314564Sdim      StringExtractorGDBRemote response;
1438314564Sdim      PacketResult packet_result =
1439314564Sdim          SendPacketAndWaitForResponse("D1", response, false);
1440314564Sdim      if (packet_result != PacketResult::Success)
1441314564Sdim        error.SetErrorString("Sending extended disconnect packet failed.");
1442254721Semaste    }
1443314564Sdim  } else {
1444314564Sdim    StringExtractorGDBRemote response;
1445314564Sdim    PacketResult packet_result =
1446314564Sdim        SendPacketAndWaitForResponse("D", response, false);
1447314564Sdim    if (packet_result != PacketResult::Success)
1448314564Sdim      error.SetErrorString("Sending disconnect packet failed.");
1449314564Sdim  }
1450314564Sdim  return error;
1451254721Semaste}
1452254721Semaste
1453321369SdimStatus GDBRemoteCommunicationClient::GetMemoryRegionInfo(
1454314564Sdim    lldb::addr_t addr, lldb_private::MemoryRegionInfo &region_info) {
1455321369Sdim  Status error;
1456314564Sdim  region_info.Clear();
1457254721Semaste
1458314564Sdim  if (m_supports_memory_region_info != eLazyBoolNo) {
1459314564Sdim    m_supports_memory_region_info = eLazyBoolYes;
1460314564Sdim    char packet[64];
1461314564Sdim    const int packet_len = ::snprintf(
1462314564Sdim        packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
1463314564Sdim    assert(packet_len < (int)sizeof(packet));
1464314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
1465314564Sdim    StringExtractorGDBRemote response;
1466314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
1467341825Sdim            PacketResult::Success &&
1468341825Sdim        response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
1469314564Sdim      llvm::StringRef name;
1470314564Sdim      llvm::StringRef value;
1471314564Sdim      addr_t addr_value = LLDB_INVALID_ADDRESS;
1472314564Sdim      bool success = true;
1473314564Sdim      bool saw_permissions = false;
1474314564Sdim      while (success && response.GetNameColonValue(name, value)) {
1475314564Sdim        if (name.equals("start")) {
1476314564Sdim          if (!value.getAsInteger(16, addr_value))
1477314564Sdim            region_info.GetRange().SetRangeBase(addr_value);
1478314564Sdim        } else if (name.equals("size")) {
1479314564Sdim          if (!value.getAsInteger(16, addr_value))
1480314564Sdim            region_info.GetRange().SetByteSize(addr_value);
1481314564Sdim        } else if (name.equals("permissions") &&
1482314564Sdim                   region_info.GetRange().IsValid()) {
1483314564Sdim          saw_permissions = true;
1484314564Sdim          if (region_info.GetRange().Contains(addr)) {
1485314564Sdim            if (value.find('r') != llvm::StringRef::npos)
1486314564Sdim              region_info.SetReadable(MemoryRegionInfo::eYes);
1487314564Sdim            else
1488314564Sdim              region_info.SetReadable(MemoryRegionInfo::eNo);
1489254721Semaste
1490314564Sdim            if (value.find('w') != llvm::StringRef::npos)
1491314564Sdim              region_info.SetWritable(MemoryRegionInfo::eYes);
1492314564Sdim            else
1493314564Sdim              region_info.SetWritable(MemoryRegionInfo::eNo);
1494254721Semaste
1495314564Sdim            if (value.find('x') != llvm::StringRef::npos)
1496314564Sdim              region_info.SetExecutable(MemoryRegionInfo::eYes);
1497314564Sdim            else
1498314564Sdim              region_info.SetExecutable(MemoryRegionInfo::eNo);
1499309124Sdim
1500314564Sdim            region_info.SetMapped(MemoryRegionInfo::eYes);
1501314564Sdim          } else {
1502314564Sdim            // The reported region does not contain this address -- we're
1503314564Sdim            // looking at an unmapped page
1504314564Sdim            region_info.SetReadable(MemoryRegionInfo::eNo);
1505314564Sdim            region_info.SetWritable(MemoryRegionInfo::eNo);
1506314564Sdim            region_info.SetExecutable(MemoryRegionInfo::eNo);
1507314564Sdim            region_info.SetMapped(MemoryRegionInfo::eNo);
1508314564Sdim          }
1509314564Sdim        } else if (name.equals("name")) {
1510314564Sdim          StringExtractorGDBRemote name_extractor(value);
1511314564Sdim          std::string name;
1512314564Sdim          name_extractor.GetHexByteString(name);
1513314564Sdim          region_info.SetName(name.c_str());
1514314564Sdim        } else if (name.equals("error")) {
1515314564Sdim          StringExtractorGDBRemote error_extractor(value);
1516314564Sdim          std::string error_string;
1517314564Sdim          // Now convert the HEX bytes into a string value
1518314564Sdim          error_extractor.GetHexByteString(error_string);
1519314564Sdim          error.SetErrorString(error_string.c_str());
1520254721Semaste        }
1521314564Sdim      }
1522254721Semaste
1523321369Sdim      if (region_info.GetRange().IsValid()) {
1524321369Sdim        // We got a valid address range back but no permissions -- which means
1525321369Sdim        // this is an unmapped page
1526321369Sdim        if (!saw_permissions) {
1527321369Sdim          region_info.SetReadable(MemoryRegionInfo::eNo);
1528321369Sdim          region_info.SetWritable(MemoryRegionInfo::eNo);
1529321369Sdim          region_info.SetExecutable(MemoryRegionInfo::eNo);
1530321369Sdim          region_info.SetMapped(MemoryRegionInfo::eNo);
1531321369Sdim        }
1532321369Sdim      } else {
1533321369Sdim        // We got an invalid address range back
1534321369Sdim        error.SetErrorString("Server returned invalid range");
1535314564Sdim      }
1536314564Sdim    } else {
1537314564Sdim      m_supports_memory_region_info = eLazyBoolNo;
1538254721Semaste    }
1539314564Sdim  }
1540254721Semaste
1541314564Sdim  if (m_supports_memory_region_info == eLazyBoolNo) {
1542314564Sdim    error.SetErrorString("qMemoryRegionInfo is not supported");
1543314564Sdim  }
1544341825Sdim
1545341825Sdim  // Try qXfer:memory-map:read to get region information not included in
1546341825Sdim  // qMemoryRegionInfo
1547341825Sdim  MemoryRegionInfo qXfer_region_info;
1548341825Sdim  Status qXfer_error = GetQXferMemoryMapRegionInfo(addr, qXfer_region_info);
1549341825Sdim
1550341825Sdim  if (error.Fail()) {
1551341825Sdim    // If qMemoryRegionInfo failed, but qXfer:memory-map:read succeeded, use
1552341825Sdim    // the qXfer result as a fallback
1553341825Sdim    if (qXfer_error.Success()) {
1554341825Sdim      region_info = qXfer_region_info;
1555341825Sdim      error.Clear();
1556341825Sdim    } else {
1557341825Sdim      region_info.Clear();
1558341825Sdim    }
1559341825Sdim  } else if (qXfer_error.Success()) {
1560341825Sdim    // If both qMemoryRegionInfo and qXfer:memory-map:read succeeded, and if
1561341825Sdim    // both regions are the same range, update the result to include the flash-
1562341825Sdim    // memory information that is specific to the qXfer result.
1563341825Sdim    if (region_info.GetRange() == qXfer_region_info.GetRange()) {
1564341825Sdim      region_info.SetFlash(qXfer_region_info.GetFlash());
1565341825Sdim      region_info.SetBlocksize(qXfer_region_info.GetBlocksize());
1566341825Sdim    }
1567341825Sdim  }
1568314564Sdim  return error;
1569254721Semaste}
1570254721Semaste
1571341825SdimStatus GDBRemoteCommunicationClient::GetQXferMemoryMapRegionInfo(
1572341825Sdim    lldb::addr_t addr, MemoryRegionInfo &region) {
1573341825Sdim  Status error = LoadQXferMemoryMap();
1574341825Sdim  if (!error.Success())
1575341825Sdim    return error;
1576341825Sdim  for (const auto &map_region : m_qXfer_memory_map) {
1577341825Sdim    if (map_region.GetRange().Contains(addr)) {
1578341825Sdim      region = map_region;
1579341825Sdim      return error;
1580341825Sdim    }
1581341825Sdim  }
1582341825Sdim  error.SetErrorString("Region not found");
1583341825Sdim  return error;
1584341825Sdim}
1585341825Sdim
1586341825SdimStatus GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
1587341825Sdim
1588341825Sdim  Status error;
1589341825Sdim
1590341825Sdim  if (m_qXfer_memory_map_loaded)
1591341825Sdim    // Already loaded, return success
1592341825Sdim    return error;
1593341825Sdim
1594341825Sdim  if (!XMLDocument::XMLEnabled()) {
1595341825Sdim    error.SetErrorString("XML is not supported");
1596341825Sdim    return error;
1597341825Sdim  }
1598341825Sdim
1599341825Sdim  if (!GetQXferMemoryMapReadSupported()) {
1600341825Sdim    error.SetErrorString("Memory map is not supported");
1601341825Sdim    return error;
1602341825Sdim  }
1603341825Sdim
1604341825Sdim  std::string xml;
1605341825Sdim  lldb_private::Status lldberr;
1606341825Sdim  if (!ReadExtFeature(ConstString("memory-map"), ConstString(""), xml,
1607341825Sdim                      lldberr)) {
1608341825Sdim    error.SetErrorString("Failed to read memory map");
1609341825Sdim    return error;
1610341825Sdim  }
1611341825Sdim
1612341825Sdim  XMLDocument xml_document;
1613341825Sdim
1614341825Sdim  if (!xml_document.ParseMemory(xml.c_str(), xml.size())) {
1615341825Sdim    error.SetErrorString("Failed to parse memory map xml");
1616341825Sdim    return error;
1617341825Sdim  }
1618341825Sdim
1619341825Sdim  XMLNode map_node = xml_document.GetRootElement("memory-map");
1620341825Sdim  if (!map_node) {
1621341825Sdim    error.SetErrorString("Invalid root node in memory map xml");
1622341825Sdim    return error;
1623341825Sdim  }
1624341825Sdim
1625341825Sdim  m_qXfer_memory_map.clear();
1626341825Sdim
1627341825Sdim  map_node.ForEachChildElement([this](const XMLNode &memory_node) -> bool {
1628341825Sdim    if (!memory_node.IsElement())
1629341825Sdim      return true;
1630341825Sdim    if (memory_node.GetName() != "memory")
1631341825Sdim      return true;
1632341825Sdim    auto type = memory_node.GetAttributeValue("type", "");
1633341825Sdim    uint64_t start;
1634341825Sdim    uint64_t length;
1635341825Sdim    if (!memory_node.GetAttributeValueAsUnsigned("start", start))
1636341825Sdim      return true;
1637341825Sdim    if (!memory_node.GetAttributeValueAsUnsigned("length", length))
1638341825Sdim      return true;
1639341825Sdim    MemoryRegionInfo region;
1640341825Sdim    region.GetRange().SetRangeBase(start);
1641341825Sdim    region.GetRange().SetByteSize(length);
1642341825Sdim    if (type == "rom") {
1643341825Sdim      region.SetReadable(MemoryRegionInfo::eYes);
1644341825Sdim      this->m_qXfer_memory_map.push_back(region);
1645341825Sdim    } else if (type == "ram") {
1646341825Sdim      region.SetReadable(MemoryRegionInfo::eYes);
1647341825Sdim      region.SetWritable(MemoryRegionInfo::eYes);
1648341825Sdim      this->m_qXfer_memory_map.push_back(region);
1649341825Sdim    } else if (type == "flash") {
1650341825Sdim      region.SetFlash(MemoryRegionInfo::eYes);
1651341825Sdim      memory_node.ForEachChildElement(
1652341825Sdim          [&region](const XMLNode &prop_node) -> bool {
1653341825Sdim            if (!prop_node.IsElement())
1654341825Sdim              return true;
1655341825Sdim            if (prop_node.GetName() != "property")
1656341825Sdim              return true;
1657341825Sdim            auto propname = prop_node.GetAttributeValue("name", "");
1658341825Sdim            if (propname == "blocksize") {
1659341825Sdim              uint64_t blocksize;
1660341825Sdim              if (prop_node.GetElementTextAsUnsigned(blocksize))
1661341825Sdim                region.SetBlocksize(blocksize);
1662341825Sdim            }
1663341825Sdim            return true;
1664341825Sdim          });
1665341825Sdim      this->m_qXfer_memory_map.push_back(region);
1666341825Sdim    }
1667341825Sdim    return true;
1668341825Sdim  });
1669341825Sdim
1670341825Sdim  m_qXfer_memory_map_loaded = true;
1671341825Sdim
1672341825Sdim  return error;
1673341825Sdim}
1674341825Sdim
1675321369SdimStatus GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
1676321369Sdim  Status error;
1677254721Semaste
1678314564Sdim  if (m_supports_watchpoint_support_info == eLazyBoolYes) {
1679314564Sdim    num = m_num_supported_hardware_watchpoints;
1680314564Sdim    return error;
1681314564Sdim  }
1682254721Semaste
1683314564Sdim  // Set num to 0 first.
1684314564Sdim  num = 0;
1685314564Sdim  if (m_supports_watchpoint_support_info != eLazyBoolNo) {
1686314564Sdim    char packet[64];
1687314564Sdim    const int packet_len =
1688314564Sdim        ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:");
1689314564Sdim    assert(packet_len < (int)sizeof(packet));
1690314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
1691314564Sdim    StringExtractorGDBRemote response;
1692314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
1693314564Sdim        PacketResult::Success) {
1694314564Sdim      m_supports_watchpoint_support_info = eLazyBoolYes;
1695314564Sdim      llvm::StringRef name;
1696314564Sdim      llvm::StringRef value;
1697344779Sdim      bool found_num_field = false;
1698314564Sdim      while (response.GetNameColonValue(name, value)) {
1699314564Sdim        if (name.equals("num")) {
1700314564Sdim          value.getAsInteger(0, m_num_supported_hardware_watchpoints);
1701314564Sdim          num = m_num_supported_hardware_watchpoints;
1702344779Sdim          found_num_field = true;
1703254721Semaste        }
1704314564Sdim      }
1705344779Sdim      if (!found_num_field) {
1706344779Sdim        m_supports_watchpoint_support_info = eLazyBoolNo;
1707344779Sdim      }
1708314564Sdim    } else {
1709314564Sdim      m_supports_watchpoint_support_info = eLazyBoolNo;
1710254721Semaste    }
1711314564Sdim  }
1712254721Semaste
1713314564Sdim  if (m_supports_watchpoint_support_info == eLazyBoolNo) {
1714314564Sdim    error.SetErrorString("qWatchpointSupportInfo is not supported");
1715314564Sdim  }
1716314564Sdim  return error;
1717314564Sdim}
1718254721Semaste
1719321369Sdimlldb_private::Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(
1720314564Sdim    uint32_t &num, bool &after, const ArchSpec &arch) {
1721321369Sdim  Status error(GetWatchpointSupportInfo(num));
1722314564Sdim  if (error.Success())
1723314564Sdim    error = GetWatchpointsTriggerAfterInstruction(after, arch);
1724314564Sdim  return error;
1725254721Semaste}
1726254721Semaste
1727321369Sdimlldb_private::Status
1728314564SdimGDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
1729314564Sdim    bool &after, const ArchSpec &arch) {
1730321369Sdim  Status error;
1731353358Sdim  llvm::Triple triple = arch.GetTriple();
1732254721Semaste
1733341825Sdim  // we assume watchpoints will happen after running the relevant opcode and we
1734341825Sdim  // only want to override this behavior if we have explicitly received a
1735341825Sdim  // qHostInfo telling us otherwise
1736314564Sdim  if (m_qHostInfo_is_valid != eLazyBoolYes) {
1737353358Sdim    // On targets like MIPS and ppc64, watchpoint exceptions are always
1738341825Sdim    // generated before the instruction is executed. The connected target may
1739341825Sdim    // not support qHostInfo or qWatchpointSupportInfo packets.
1740353358Sdim    after = !(triple.isMIPS() || triple.isPPC64());
1741314564Sdim  } else {
1742353358Sdim    // For MIPS and ppc64, set m_watchpoints_trigger_after_instruction to
1743327952Sdim    // eLazyBoolNo if it is not calculated before.
1744353358Sdim    if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate &&
1745353358Sdim        (triple.isMIPS() || triple.isPPC64()))
1746314564Sdim      m_watchpoints_trigger_after_instruction = eLazyBoolNo;
1747288943Sdim
1748314564Sdim    after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
1749314564Sdim  }
1750314564Sdim  return error;
1751254721Semaste}
1752254721Semaste
1753314564Sdimint GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) {
1754314564Sdim  if (file_spec) {
1755314564Sdim    std::string path{file_spec.GetPath(false)};
1756314564Sdim    StreamString packet;
1757314564Sdim    packet.PutCString("QSetSTDIN:");
1758353358Sdim    packet.PutStringAsRawHex8(path);
1759254721Semaste
1760314564Sdim    StringExtractorGDBRemote response;
1761314564Sdim    if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
1762314564Sdim        PacketResult::Success) {
1763314564Sdim      if (response.IsOKResponse())
1764314564Sdim        return 0;
1765314564Sdim      uint8_t error = response.GetError();
1766314564Sdim      if (error)
1767314564Sdim        return error;
1768254721Semaste    }
1769314564Sdim  }
1770314564Sdim  return -1;
1771254721Semaste}
1772254721Semaste
1773314564Sdimint GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) {
1774314564Sdim  if (file_spec) {
1775314564Sdim    std::string path{file_spec.GetPath(false)};
1776314564Sdim    StreamString packet;
1777314564Sdim    packet.PutCString("QSetSTDOUT:");
1778353358Sdim    packet.PutStringAsRawHex8(path);
1779288943Sdim
1780314564Sdim    StringExtractorGDBRemote response;
1781314564Sdim    if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
1782314564Sdim        PacketResult::Success) {
1783314564Sdim      if (response.IsOKResponse())
1784314564Sdim        return 0;
1785314564Sdim      uint8_t error = response.GetError();
1786314564Sdim      if (error)
1787314564Sdim        return error;
1788254721Semaste    }
1789314564Sdim  }
1790314564Sdim  return -1;
1791254721Semaste}
1792254721Semaste
1793314564Sdimint GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) {
1794314564Sdim  if (file_spec) {
1795314564Sdim    std::string path{file_spec.GetPath(false)};
1796314564Sdim    StreamString packet;
1797314564Sdim    packet.PutCString("QSetSTDERR:");
1798353358Sdim    packet.PutStringAsRawHex8(path);
1799288943Sdim
1800314564Sdim    StringExtractorGDBRemote response;
1801314564Sdim    if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
1802314564Sdim        PacketResult::Success) {
1803314564Sdim      if (response.IsOKResponse())
1804314564Sdim        return 0;
1805314564Sdim      uint8_t error = response.GetError();
1806314564Sdim      if (error)
1807314564Sdim        return error;
1808254721Semaste    }
1809314564Sdim  }
1810314564Sdim  return -1;
1811254721Semaste}
1812254721Semaste
1813314564Sdimbool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
1814314564Sdim  StringExtractorGDBRemote response;
1815314564Sdim  if (SendPacketAndWaitForResponse("qGetWorkingDir", response, false) ==
1816314564Sdim      PacketResult::Success) {
1817314564Sdim    if (response.IsUnsupportedResponse())
1818314564Sdim      return false;
1819314564Sdim    if (response.IsErrorResponse())
1820314564Sdim      return false;
1821314564Sdim    std::string cwd;
1822314564Sdim    response.GetHexByteString(cwd);
1823344779Sdim    working_dir.SetFile(cwd, GetHostArchitecture().GetTriple());
1824314564Sdim    return !cwd.empty();
1825314564Sdim  }
1826314564Sdim  return false;
1827258884Semaste}
1828258884Semaste
1829314564Sdimint GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) {
1830314564Sdim  if (working_dir) {
1831314564Sdim    std::string path{working_dir.GetPath(false)};
1832314564Sdim    StreamString packet;
1833314564Sdim    packet.PutCString("QSetWorkingDir:");
1834353358Sdim    packet.PutStringAsRawHex8(path);
1835288943Sdim
1836314564Sdim    StringExtractorGDBRemote response;
1837314564Sdim    if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
1838314564Sdim        PacketResult::Success) {
1839314564Sdim      if (response.IsOKResponse())
1840314564Sdim        return 0;
1841314564Sdim      uint8_t error = response.GetError();
1842314564Sdim      if (error)
1843314564Sdim        return error;
1844254721Semaste    }
1845314564Sdim  }
1846314564Sdim  return -1;
1847254721Semaste}
1848254721Semaste
1849314564Sdimint GDBRemoteCommunicationClient::SetDisableASLR(bool enable) {
1850314564Sdim  char packet[32];
1851314564Sdim  const int packet_len =
1852314564Sdim      ::snprintf(packet, sizeof(packet), "QSetDisableASLR:%i", enable ? 1 : 0);
1853314564Sdim  assert(packet_len < (int)sizeof(packet));
1854314564Sdim  UNUSED_IF_ASSERT_DISABLED(packet_len);
1855314564Sdim  StringExtractorGDBRemote response;
1856314564Sdim  if (SendPacketAndWaitForResponse(packet, response, false) ==
1857314564Sdim      PacketResult::Success) {
1858314564Sdim    if (response.IsOKResponse())
1859314564Sdim      return 0;
1860314564Sdim    uint8_t error = response.GetError();
1861314564Sdim    if (error)
1862314564Sdim      return error;
1863314564Sdim  }
1864314564Sdim  return -1;
1865254721Semaste}
1866254721Semaste
1867314564Sdimint GDBRemoteCommunicationClient::SetDetachOnError(bool enable) {
1868314564Sdim  char packet[32];
1869314564Sdim  const int packet_len = ::snprintf(packet, sizeof(packet),
1870314564Sdim                                    "QSetDetachOnError:%i", enable ? 1 : 0);
1871314564Sdim  assert(packet_len < (int)sizeof(packet));
1872314564Sdim  UNUSED_IF_ASSERT_DISABLED(packet_len);
1873314564Sdim  StringExtractorGDBRemote response;
1874314564Sdim  if (SendPacketAndWaitForResponse(packet, response, false) ==
1875314564Sdim      PacketResult::Success) {
1876314564Sdim    if (response.IsOKResponse())
1877314564Sdim      return 0;
1878314564Sdim    uint8_t error = response.GetError();
1879314564Sdim    if (error)
1880314564Sdim      return error;
1881314564Sdim  }
1882314564Sdim  return -1;
1883276479Sdim}
1884276479Sdim
1885314564Sdimbool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
1886314564Sdim    StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) {
1887314564Sdim  if (response.IsNormalResponse()) {
1888314564Sdim    llvm::StringRef name;
1889314564Sdim    llvm::StringRef value;
1890314564Sdim    StringExtractor extractor;
1891276479Sdim
1892314564Sdim    uint32_t cpu = LLDB_INVALID_CPUTYPE;
1893314564Sdim    uint32_t sub = 0;
1894314564Sdim    std::string vendor;
1895314564Sdim    std::string os_type;
1896314564Sdim
1897314564Sdim    while (response.GetNameColonValue(name, value)) {
1898314564Sdim      if (name.equals("pid")) {
1899314564Sdim        lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
1900314564Sdim        value.getAsInteger(0, pid);
1901314564Sdim        process_info.SetProcessID(pid);
1902314564Sdim      } else if (name.equals("ppid")) {
1903314564Sdim        lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
1904314564Sdim        value.getAsInteger(0, pid);
1905314564Sdim        process_info.SetParentProcessID(pid);
1906314564Sdim      } else if (name.equals("uid")) {
1907314564Sdim        uint32_t uid = UINT32_MAX;
1908314564Sdim        value.getAsInteger(0, uid);
1909314564Sdim        process_info.SetUserID(uid);
1910314564Sdim      } else if (name.equals("euid")) {
1911314564Sdim        uint32_t uid = UINT32_MAX;
1912314564Sdim        value.getAsInteger(0, uid);
1913360784Sdim        process_info.SetEffectiveUserID(uid);
1914314564Sdim      } else if (name.equals("gid")) {
1915314564Sdim        uint32_t gid = UINT32_MAX;
1916314564Sdim        value.getAsInteger(0, gid);
1917314564Sdim        process_info.SetGroupID(gid);
1918314564Sdim      } else if (name.equals("egid")) {
1919314564Sdim        uint32_t gid = UINT32_MAX;
1920314564Sdim        value.getAsInteger(0, gid);
1921314564Sdim        process_info.SetEffectiveGroupID(gid);
1922314564Sdim      } else if (name.equals("triple")) {
1923314564Sdim        StringExtractor extractor(value);
1924314564Sdim        std::string triple;
1925314564Sdim        extractor.GetHexByteString(triple);
1926314564Sdim        process_info.GetArchitecture().SetTriple(triple.c_str());
1927314564Sdim      } else if (name.equals("name")) {
1928314564Sdim        StringExtractor extractor(value);
1929341825Sdim        // The process name from ASCII hex bytes since we can't control the
1930341825Sdim        // characters in a process name
1931254721Semaste        std::string name;
1932314564Sdim        extractor.GetHexByteString(name);
1933344779Sdim        process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);
1934360784Sdim      } else if (name.equals("args")) {
1935360784Sdim        llvm::StringRef encoded_args(value), hex_arg;
1936360784Sdim
1937360784Sdim        bool is_arg0 = true;
1938360784Sdim        while (!encoded_args.empty()) {
1939360784Sdim          std::tie(hex_arg, encoded_args) = encoded_args.split('-');
1940360784Sdim          std::string arg;
1941360784Sdim          StringExtractor extractor(hex_arg);
1942360784Sdim          if (extractor.GetHexByteString(arg) * 2 != hex_arg.size()) {
1943360784Sdim            // In case of wrong encoding, we discard all the arguments
1944360784Sdim            process_info.GetArguments().Clear();
1945360784Sdim            process_info.SetArg0("");
1946360784Sdim            break;
1947360784Sdim          }
1948360784Sdim          if (is_arg0)
1949360784Sdim            process_info.SetArg0(arg);
1950360784Sdim          else
1951360784Sdim            process_info.GetArguments().AppendArgument(arg);
1952360784Sdim          is_arg0 = false;
1953360784Sdim        }
1954314564Sdim      } else if (name.equals("cputype")) {
1955314564Sdim        value.getAsInteger(0, cpu);
1956314564Sdim      } else if (name.equals("cpusubtype")) {
1957314564Sdim        value.getAsInteger(0, sub);
1958314564Sdim      } else if (name.equals("vendor")) {
1959314564Sdim        vendor = value;
1960314564Sdim      } else if (name.equals("ostype")) {
1961314564Sdim        os_type = value;
1962314564Sdim      }
1963314564Sdim    }
1964262528Semaste
1965314564Sdim    if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty()) {
1966314564Sdim      if (vendor == "apple") {
1967314564Sdim        process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu,
1968314564Sdim                                                       sub);
1969314564Sdim        process_info.GetArchitecture().GetTriple().setVendorName(
1970314564Sdim            llvm::StringRef(vendor));
1971314564Sdim        process_info.GetArchitecture().GetTriple().setOSName(
1972314564Sdim            llvm::StringRef(os_type));
1973314564Sdim      }
1974314564Sdim    }
1975262528Semaste
1976314564Sdim    if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
1977314564Sdim      return true;
1978314564Sdim  }
1979314564Sdim  return false;
1980254721Semaste}
1981254721Semaste
1982314564Sdimbool GDBRemoteCommunicationClient::GetProcessInfo(
1983314564Sdim    lldb::pid_t pid, ProcessInstanceInfo &process_info) {
1984314564Sdim  process_info.Clear();
1985314564Sdim
1986314564Sdim  if (m_supports_qProcessInfoPID) {
1987314564Sdim    char packet[32];
1988314564Sdim    const int packet_len =
1989314564Sdim        ::snprintf(packet, sizeof(packet), "qProcessInfoPID:%" PRIu64, pid);
1990314564Sdim    assert(packet_len < (int)sizeof(packet));
1991314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
1992314564Sdim    StringExtractorGDBRemote response;
1993314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
1994314564Sdim        PacketResult::Success) {
1995314564Sdim      return DecodeProcessInfoResponse(response, process_info);
1996314564Sdim    } else {
1997314564Sdim      m_supports_qProcessInfoPID = false;
1998314564Sdim      return false;
1999254721Semaste    }
2000314564Sdim  }
2001314564Sdim  return false;
2002254721Semaste}
2003254721Semaste
2004314564Sdimbool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
2005314564Sdim  Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
2006314564Sdim                                                         GDBR_LOG_PACKETS));
2007280031Sdim
2008314564Sdim  if (allow_lazy) {
2009314564Sdim    if (m_qProcessInfo_is_valid == eLazyBoolYes)
2010314564Sdim      return true;
2011314564Sdim    if (m_qProcessInfo_is_valid == eLazyBoolNo)
2012314564Sdim      return false;
2013314564Sdim  }
2014254721Semaste
2015314564Sdim  GetHostInfo();
2016254721Semaste
2017314564Sdim  StringExtractorGDBRemote response;
2018314564Sdim  if (SendPacketAndWaitForResponse("qProcessInfo", response, false) ==
2019314564Sdim      PacketResult::Success) {
2020314564Sdim    if (response.IsNormalResponse()) {
2021314564Sdim      llvm::StringRef name;
2022314564Sdim      llvm::StringRef value;
2023314564Sdim      uint32_t cpu = LLDB_INVALID_CPUTYPE;
2024314564Sdim      uint32_t sub = 0;
2025314564Sdim      std::string arch_name;
2026314564Sdim      std::string os_name;
2027360784Sdim      std::string environment;
2028314564Sdim      std::string vendor_name;
2029314564Sdim      std::string triple;
2030314564Sdim      std::string elf_abi;
2031314564Sdim      uint32_t pointer_byte_size = 0;
2032314564Sdim      StringExtractor extractor;
2033314564Sdim      ByteOrder byte_order = eByteOrderInvalid;
2034314564Sdim      uint32_t num_keys_decoded = 0;
2035314564Sdim      lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
2036314564Sdim      while (response.GetNameColonValue(name, value)) {
2037314564Sdim        if (name.equals("cputype")) {
2038314564Sdim          if (!value.getAsInteger(16, cpu))
2039314564Sdim            ++num_keys_decoded;
2040314564Sdim        } else if (name.equals("cpusubtype")) {
2041314564Sdim          if (!value.getAsInteger(16, sub))
2042314564Sdim            ++num_keys_decoded;
2043314564Sdim        } else if (name.equals("triple")) {
2044314564Sdim          StringExtractor extractor(value);
2045314564Sdim          extractor.GetHexByteString(triple);
2046314564Sdim          ++num_keys_decoded;
2047314564Sdim        } else if (name.equals("ostype")) {
2048360784Sdim          if (value.equals("maccatalyst")) {
2049360784Sdim            os_name = "ios";
2050360784Sdim            environment = "macabi";
2051360784Sdim          } else
2052360784Sdim            os_name = value;
2053314564Sdim          ++num_keys_decoded;
2054314564Sdim        } else if (name.equals("vendor")) {
2055314564Sdim          vendor_name = value;
2056314564Sdim          ++num_keys_decoded;
2057314564Sdim        } else if (name.equals("endian")) {
2058314564Sdim          byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
2059314564Sdim                           .Case("little", eByteOrderLittle)
2060314564Sdim                           .Case("big", eByteOrderBig)
2061314564Sdim                           .Case("pdp", eByteOrderPDP)
2062314564Sdim                           .Default(eByteOrderInvalid);
2063314564Sdim          if (byte_order != eByteOrderInvalid)
2064314564Sdim            ++num_keys_decoded;
2065314564Sdim        } else if (name.equals("ptrsize")) {
2066314564Sdim          if (!value.getAsInteger(16, pointer_byte_size))
2067314564Sdim            ++num_keys_decoded;
2068314564Sdim        } else if (name.equals("pid")) {
2069314564Sdim          if (!value.getAsInteger(16, pid))
2070314564Sdim            ++num_keys_decoded;
2071314564Sdim        } else if (name.equals("elf_abi")) {
2072314564Sdim          elf_abi = value;
2073314564Sdim          ++num_keys_decoded;
2074314564Sdim        }
2075314564Sdim      }
2076314564Sdim      if (num_keys_decoded > 0)
2077314564Sdim        m_qProcessInfo_is_valid = eLazyBoolYes;
2078314564Sdim      if (pid != LLDB_INVALID_PROCESS_ID) {
2079314564Sdim        m_curr_pid_is_valid = eLazyBoolYes;
2080314564Sdim        m_curr_pid = pid;
2081314564Sdim      }
2082276479Sdim
2083314564Sdim      // Set the ArchSpec from the triple if we have it.
2084314564Sdim      if (!triple.empty()) {
2085314564Sdim        m_process_arch.SetTriple(triple.c_str());
2086314564Sdim        m_process_arch.SetFlags(elf_abi);
2087314564Sdim        if (pointer_byte_size) {
2088314564Sdim          assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
2089314564Sdim        }
2090314564Sdim      } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() &&
2091314564Sdim                 !vendor_name.empty()) {
2092314564Sdim        llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name);
2093360784Sdim        if (!environment.empty())
2094360784Sdim            triple.setEnvironmentName(environment);
2095280031Sdim
2096314564Sdim        assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat);
2097321369Sdim        assert(triple.getObjectFormat() != llvm::Triple::Wasm);
2098353358Sdim        assert(triple.getObjectFormat() != llvm::Triple::XCOFF);
2099314564Sdim        switch (triple.getObjectFormat()) {
2100314564Sdim        case llvm::Triple::MachO:
2101314564Sdim          m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
2102314564Sdim          break;
2103314564Sdim        case llvm::Triple::ELF:
2104314564Sdim          m_process_arch.SetArchitecture(eArchTypeELF, cpu, sub);
2105314564Sdim          break;
2106314564Sdim        case llvm::Triple::COFF:
2107314564Sdim          m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub);
2108314564Sdim          break;
2109321369Sdim        case llvm::Triple::Wasm:
2110353358Sdim        case llvm::Triple::XCOFF:
2111360784Sdim          LLDB_LOGF(log, "error: not supported target architecture");
2112321369Sdim          return false;
2113314564Sdim        case llvm::Triple::UnknownObjectFormat:
2114360784Sdim          LLDB_LOGF(log, "error: failed to determine target architecture");
2115314564Sdim          return false;
2116314564Sdim        }
2117280031Sdim
2118314564Sdim        if (pointer_byte_size) {
2119314564Sdim          assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
2120254721Semaste        }
2121314564Sdim        if (byte_order != eByteOrderInvalid) {
2122314564Sdim          assert(byte_order == m_process_arch.GetByteOrder());
2123314564Sdim        }
2124314564Sdim        m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name));
2125314564Sdim        m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name));
2126360784Sdim        m_process_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment));
2127314564Sdim        m_host_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name));
2128314564Sdim        m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name));
2129360784Sdim        m_host_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment));
2130314564Sdim      }
2131314564Sdim      return true;
2132254721Semaste    }
2133314564Sdim  } else {
2134314564Sdim    m_qProcessInfo_is_valid = eLazyBoolNo;
2135314564Sdim  }
2136254721Semaste
2137314564Sdim  return false;
2138254721Semaste}
2139254721Semaste
2140314564Sdimuint32_t GDBRemoteCommunicationClient::FindProcesses(
2141314564Sdim    const ProcessInstanceInfoMatch &match_info,
2142314564Sdim    ProcessInstanceInfoList &process_infos) {
2143314564Sdim  process_infos.Clear();
2144254721Semaste
2145314564Sdim  if (m_supports_qfProcessInfo) {
2146314564Sdim    StreamString packet;
2147314564Sdim    packet.PutCString("qfProcessInfo");
2148314564Sdim    if (!match_info.MatchAllProcesses()) {
2149314564Sdim      packet.PutChar(':');
2150314564Sdim      const char *name = match_info.GetProcessInfo().GetName();
2151314564Sdim      bool has_name_match = false;
2152314564Sdim      if (name && name[0]) {
2153314564Sdim        has_name_match = true;
2154321369Sdim        NameMatch name_match_type = match_info.GetNameMatchType();
2155314564Sdim        switch (name_match_type) {
2156321369Sdim        case NameMatch::Ignore:
2157314564Sdim          has_name_match = false;
2158314564Sdim          break;
2159254721Semaste
2160321369Sdim        case NameMatch::Equals:
2161314564Sdim          packet.PutCString("name_match:equals;");
2162314564Sdim          break;
2163254721Semaste
2164321369Sdim        case NameMatch::Contains:
2165314564Sdim          packet.PutCString("name_match:contains;");
2166314564Sdim          break;
2167254721Semaste
2168321369Sdim        case NameMatch::StartsWith:
2169314564Sdim          packet.PutCString("name_match:starts_with;");
2170314564Sdim          break;
2171314564Sdim
2172321369Sdim        case NameMatch::EndsWith:
2173314564Sdim          packet.PutCString("name_match:ends_with;");
2174314564Sdim          break;
2175314564Sdim
2176321369Sdim        case NameMatch::RegularExpression:
2177314564Sdim          packet.PutCString("name_match:regex;");
2178314564Sdim          break;
2179254721Semaste        }
2180314564Sdim        if (has_name_match) {
2181314564Sdim          packet.PutCString("name:");
2182314564Sdim          packet.PutBytesAsRawHex8(name, ::strlen(name));
2183314564Sdim          packet.PutChar(';');
2184254721Semaste        }
2185314564Sdim      }
2186254721Semaste
2187314564Sdim      if (match_info.GetProcessInfo().ProcessIDIsValid())
2188314564Sdim        packet.Printf("pid:%" PRIu64 ";",
2189314564Sdim                      match_info.GetProcessInfo().GetProcessID());
2190314564Sdim      if (match_info.GetProcessInfo().ParentProcessIDIsValid())
2191314564Sdim        packet.Printf("parent_pid:%" PRIu64 ";",
2192314564Sdim                      match_info.GetProcessInfo().GetParentProcessID());
2193314564Sdim      if (match_info.GetProcessInfo().UserIDIsValid())
2194314564Sdim        packet.Printf("uid:%u;", match_info.GetProcessInfo().GetUserID());
2195314564Sdim      if (match_info.GetProcessInfo().GroupIDIsValid())
2196314564Sdim        packet.Printf("gid:%u;", match_info.GetProcessInfo().GetGroupID());
2197314564Sdim      if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
2198314564Sdim        packet.Printf("euid:%u;",
2199314564Sdim                      match_info.GetProcessInfo().GetEffectiveUserID());
2200314564Sdim      if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
2201314564Sdim        packet.Printf("egid:%u;",
2202314564Sdim                      match_info.GetProcessInfo().GetEffectiveGroupID());
2203360784Sdim      packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0);
2204314564Sdim      if (match_info.GetProcessInfo().GetArchitecture().IsValid()) {
2205314564Sdim        const ArchSpec &match_arch =
2206314564Sdim            match_info.GetProcessInfo().GetArchitecture();
2207314564Sdim        const llvm::Triple &triple = match_arch.GetTriple();
2208314564Sdim        packet.PutCString("triple:");
2209314564Sdim        packet.PutCString(triple.getTriple());
2210314564Sdim        packet.PutChar(';');
2211314564Sdim      }
2212254721Semaste    }
2213314564Sdim    StringExtractorGDBRemote response;
2214341825Sdim    // Increase timeout as the first qfProcessInfo packet takes a long time on
2215341825Sdim    // Android. The value of 1min was arrived at empirically.
2216314564Sdim    ScopedTimeout timeout(*this, minutes(1));
2217314564Sdim    if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
2218314564Sdim        PacketResult::Success) {
2219314564Sdim      do {
2220314564Sdim        ProcessInstanceInfo process_info;
2221314564Sdim        if (!DecodeProcessInfoResponse(response, process_info))
2222314564Sdim          break;
2223314564Sdim        process_infos.Append(process_info);
2224360784Sdim        response = StringExtractorGDBRemote();
2225314564Sdim      } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) ==
2226314564Sdim               PacketResult::Success);
2227314564Sdim    } else {
2228314564Sdim      m_supports_qfProcessInfo = false;
2229314564Sdim      return 0;
2230314564Sdim    }
2231314564Sdim  }
2232314564Sdim  return process_infos.GetSize();
2233254721Semaste}
2234254721Semaste
2235314564Sdimbool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
2236314564Sdim                                               std::string &name) {
2237314564Sdim  if (m_supports_qUserName) {
2238314564Sdim    char packet[32];
2239314564Sdim    const int packet_len =
2240314564Sdim        ::snprintf(packet, sizeof(packet), "qUserName:%i", uid);
2241314564Sdim    assert(packet_len < (int)sizeof(packet));
2242314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
2243314564Sdim    StringExtractorGDBRemote response;
2244314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
2245314564Sdim        PacketResult::Success) {
2246314564Sdim      if (response.IsNormalResponse()) {
2247314564Sdim        // Make sure we parsed the right number of characters. The response is
2248341825Sdim        // the hex encoded user name and should make up the entire packet. If
2249341825Sdim        // there are any non-hex ASCII bytes, the length won't match below..
2250314564Sdim        if (response.GetHexByteString(name) * 2 ==
2251314564Sdim            response.GetStringRef().size())
2252314564Sdim          return true;
2253314564Sdim      }
2254314564Sdim    } else {
2255314564Sdim      m_supports_qUserName = false;
2256314564Sdim      return false;
2257254721Semaste    }
2258314564Sdim  }
2259314564Sdim  return false;
2260254721Semaste}
2261254721Semaste
2262314564Sdimbool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
2263314564Sdim                                                std::string &name) {
2264314564Sdim  if (m_supports_qGroupName) {
2265288943Sdim    char packet[32];
2266314564Sdim    const int packet_len =
2267314564Sdim        ::snprintf(packet, sizeof(packet), "qGroupName:%i", gid);
2268288943Sdim    assert(packet_len < (int)sizeof(packet));
2269314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
2270288943Sdim    StringExtractorGDBRemote response;
2271314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
2272314564Sdim        PacketResult::Success) {
2273314564Sdim      if (response.IsNormalResponse()) {
2274314564Sdim        // Make sure we parsed the right number of characters. The response is
2275341825Sdim        // the hex encoded group name and should make up the entire packet. If
2276341825Sdim        // there are any non-hex ASCII bytes, the length won't match below..
2277314564Sdim        if (response.GetHexByteString(name) * 2 ==
2278314564Sdim            response.GetStringRef().size())
2279314564Sdim          return true;
2280314564Sdim      }
2281314564Sdim    } else {
2282314564Sdim      m_supports_qGroupName = false;
2283314564Sdim      return false;
2284314564Sdim    }
2285314564Sdim  }
2286314564Sdim  return false;
2287314564Sdim}
2288288943Sdim
2289314564Sdimbool GDBRemoteCommunicationClient::SetNonStopMode(const bool enable) {
2290314564Sdim  // Form non-stop packet request
2291314564Sdim  char packet[32];
2292314564Sdim  const int packet_len =
2293314564Sdim      ::snprintf(packet, sizeof(packet), "QNonStop:%1d", (int)enable);
2294314564Sdim  assert(packet_len < (int)sizeof(packet));
2295314564Sdim  UNUSED_IF_ASSERT_DISABLED(packet_len);
2296288943Sdim
2297314564Sdim  StringExtractorGDBRemote response;
2298314564Sdim  // Send to target
2299314564Sdim  if (SendPacketAndWaitForResponse(packet, response, false) ==
2300314564Sdim      PacketResult::Success)
2301314564Sdim    if (response.IsOKResponse())
2302314564Sdim      return true;
2303314564Sdim
2304314564Sdim  // Failed or not supported
2305314564Sdim  return false;
2306288943Sdim}
2307288943Sdim
2308314564Sdimstatic void MakeSpeedTestPacket(StreamString &packet, uint32_t send_size,
2309314564Sdim                                uint32_t recv_size) {
2310314564Sdim  packet.Clear();
2311314564Sdim  packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
2312314564Sdim  uint32_t bytes_left = send_size;
2313314564Sdim  while (bytes_left > 0) {
2314314564Sdim    if (bytes_left >= 26) {
2315314564Sdim      packet.PutCString("abcdefghijklmnopqrstuvwxyz");
2316314564Sdim      bytes_left -= 26;
2317314564Sdim    } else {
2318314564Sdim      packet.Printf("%*.*s;", bytes_left, bytes_left,
2319314564Sdim                    "abcdefghijklmnopqrstuvwxyz");
2320314564Sdim      bytes_left = 0;
2321288943Sdim    }
2322314564Sdim  }
2323288943Sdim}
2324288943Sdim
2325314564Sdimduration<float>
2326314564Sdimcalculate_standard_deviation(const std::vector<duration<float>> &v) {
2327314564Sdim  using Dur = duration<float>;
2328314564Sdim  Dur sum = std::accumulate(std::begin(v), std::end(v), Dur());
2329314564Sdim  Dur mean = sum / v.size();
2330314564Sdim  float accum = 0;
2331314564Sdim  for (auto d : v) {
2332314564Sdim    float delta = (d - mean).count();
2333314564Sdim    accum += delta * delta;
2334314564Sdim  };
2335288943Sdim
2336314564Sdim  return Dur(sqrtf(accum / (v.size() - 1)));
2337288943Sdim}
2338288943Sdim
2339314564Sdimvoid GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
2340314564Sdim                                                   uint32_t max_send,
2341314564Sdim                                                   uint32_t max_recv,
2342314564Sdim                                                   uint64_t recv_amount,
2343314564Sdim                                                   bool json, Stream &strm) {
2344314564Sdim  uint32_t i;
2345314564Sdim  if (SendSpeedTestPacket(0, 0)) {
2346314564Sdim    StreamString packet;
2347314564Sdim    if (json)
2348314564Sdim      strm.Printf("{ \"packet_speeds\" : {\n    \"num_packets\" : %u,\n    "
2349314564Sdim                  "\"results\" : [",
2350314564Sdim                  num_packets);
2351314564Sdim    else
2352314564Sdim      strm.Printf("Testing sending %u packets of various sizes:\n",
2353314564Sdim                  num_packets);
2354314564Sdim    strm.Flush();
2355288943Sdim
2356314564Sdim    uint32_t result_idx = 0;
2357314564Sdim    uint32_t send_size;
2358314564Sdim    std::vector<duration<float>> packet_times;
2359288943Sdim
2360314564Sdim    for (send_size = 0; send_size <= max_send;
2361314564Sdim         send_size ? send_size *= 2 : send_size = 4) {
2362314564Sdim      for (uint32_t recv_size = 0; recv_size <= max_recv;
2363314564Sdim           recv_size ? recv_size *= 2 : recv_size = 4) {
2364314564Sdim        MakeSpeedTestPacket(packet, send_size, recv_size);
2365288943Sdim
2366314564Sdim        packet_times.clear();
2367314564Sdim        // Test how long it takes to send 'num_packets' packets
2368314564Sdim        const auto start_time = steady_clock::now();
2369314564Sdim        for (i = 0; i < num_packets; ++i) {
2370314564Sdim          const auto packet_start_time = steady_clock::now();
2371314564Sdim          StringExtractorGDBRemote response;
2372314564Sdim          SendPacketAndWaitForResponse(packet.GetString(), response, false);
2373314564Sdim          const auto packet_end_time = steady_clock::now();
2374314564Sdim          packet_times.push_back(packet_end_time - packet_start_time);
2375314564Sdim        }
2376314564Sdim        const auto end_time = steady_clock::now();
2377314564Sdim        const auto total_time = end_time - start_time;
2378262528Semaste
2379314564Sdim        float packets_per_second =
2380314564Sdim            ((float)num_packets) / duration<float>(total_time).count();
2381314564Sdim        auto average_per_packet = total_time / num_packets;
2382314564Sdim        const duration<float> standard_deviation =
2383314564Sdim            calculate_standard_deviation(packet_times);
2384314564Sdim        if (json) {
2385321369Sdim          strm.Format("{0}\n     {{\"send_size\" : {1,6}, \"recv_size\" : "
2386321369Sdim                      "{2,6}, \"total_time_nsec\" : {3,12:ns-}, "
2387321369Sdim                      "\"standard_deviation_nsec\" : {4,9:ns-f0}}",
2388314564Sdim                      result_idx > 0 ? "," : "", send_size, recv_size,
2389321369Sdim                      total_time, standard_deviation);
2390314564Sdim          ++result_idx;
2391314564Sdim        } else {
2392321369Sdim          strm.Format("qSpeedTest(send={0,7}, recv={1,7}) in {2:s+f9} for "
2393321369Sdim                      "{3,9:f2} packets/s ({4,10:ms+f6} per packet) with "
2394321369Sdim                      "standard deviation of {5,10:ms+f6}\n",
2395321369Sdim                      send_size, recv_size, duration<float>(total_time),
2396321369Sdim                      packets_per_second, duration<float>(average_per_packet),
2397321369Sdim                      standard_deviation);
2398288943Sdim        }
2399288943Sdim        strm.Flush();
2400314564Sdim      }
2401314564Sdim    }
2402288943Sdim
2403314564Sdim    const float k_recv_amount_mb = (float)recv_amount / (1024.0f * 1024.0f);
2404314564Sdim    if (json)
2405314564Sdim      strm.Printf("\n    ]\n  },\n  \"download_speed\" : {\n    \"byte_size\" "
2406314564Sdim                  ": %" PRIu64 ",\n    \"results\" : [",
2407314564Sdim                  recv_amount);
2408314564Sdim    else
2409314564Sdim      strm.Printf("Testing receiving %2.1fMB of data using varying receive "
2410314564Sdim                  "packet sizes:\n",
2411314564Sdim                  k_recv_amount_mb);
2412314564Sdim    strm.Flush();
2413314564Sdim    send_size = 0;
2414314564Sdim    result_idx = 0;
2415314564Sdim    for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) {
2416314564Sdim      MakeSpeedTestPacket(packet, send_size, recv_size);
2417288943Sdim
2418314564Sdim      // If we have a receive size, test how long it takes to receive 4MB of
2419314564Sdim      // data
2420314564Sdim      if (recv_size > 0) {
2421314564Sdim        const auto start_time = steady_clock::now();
2422314564Sdim        uint32_t bytes_read = 0;
2423314564Sdim        uint32_t packet_count = 0;
2424314564Sdim        while (bytes_read < recv_amount) {
2425314564Sdim          StringExtractorGDBRemote response;
2426314564Sdim          SendPacketAndWaitForResponse(packet.GetString(), response, false);
2427314564Sdim          bytes_read += recv_size;
2428314564Sdim          ++packet_count;
2429254721Semaste        }
2430314564Sdim        const auto end_time = steady_clock::now();
2431314564Sdim        const auto total_time = end_time - start_time;
2432314564Sdim        float mb_second = ((float)recv_amount) /
2433314564Sdim                          duration<float>(total_time).count() /
2434314564Sdim                          (1024.0 * 1024.0);
2435314564Sdim        float packets_per_second =
2436314564Sdim            ((float)packet_count) / duration<float>(total_time).count();
2437314564Sdim        const auto average_per_packet = total_time / packet_count;
2438314564Sdim
2439314564Sdim        if (json) {
2440321369Sdim          strm.Format("{0}\n     {{\"send_size\" : {1,6}, \"recv_size\" : "
2441321369Sdim                      "{2,6}, \"total_time_nsec\" : {3,12:ns-}}",
2442314564Sdim                      result_idx > 0 ? "," : "", send_size, recv_size,
2443321369Sdim                      total_time);
2444314564Sdim          ++result_idx;
2445314564Sdim        } else {
2446321369Sdim          strm.Format("qSpeedTest(send={0,7}, recv={1,7}) {2,6} packets needed "
2447321369Sdim                      "to receive {3:f1}MB in {4:s+f9} for {5} MB/sec for "
2448321369Sdim                      "{6,9:f2} packets/sec ({7,10:ms+f6} per packet)\n",
2449314564Sdim                      send_size, recv_size, packet_count, k_recv_amount_mb,
2450321369Sdim                      duration<float>(total_time), mb_second,
2451321369Sdim                      packets_per_second, duration<float>(average_per_packet));
2452314564Sdim        }
2453314564Sdim        strm.Flush();
2454314564Sdim      }
2455254721Semaste    }
2456314564Sdim    if (json)
2457314564Sdim      strm.Printf("\n    ]\n  }\n}\n");
2458314564Sdim    else
2459314564Sdim      strm.EOL();
2460314564Sdim  }
2461254721Semaste}
2462254721Semaste
2463314564Sdimbool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size,
2464314564Sdim                                                       uint32_t recv_size) {
2465314564Sdim  StreamString packet;
2466314564Sdim  packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
2467314564Sdim  uint32_t bytes_left = send_size;
2468314564Sdim  while (bytes_left > 0) {
2469314564Sdim    if (bytes_left >= 26) {
2470314564Sdim      packet.PutCString("abcdefghijklmnopqrstuvwxyz");
2471314564Sdim      bytes_left -= 26;
2472314564Sdim    } else {
2473314564Sdim      packet.Printf("%*.*s;", bytes_left, bytes_left,
2474314564Sdim                    "abcdefghijklmnopqrstuvwxyz");
2475314564Sdim      bytes_left = 0;
2476254721Semaste    }
2477314564Sdim  }
2478254721Semaste
2479314564Sdim  StringExtractorGDBRemote response;
2480314564Sdim  return SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
2481314564Sdim         PacketResult::Success;
2482254721Semaste}
2483254721Semaste
2484314564Sdimbool GDBRemoteCommunicationClient::LaunchGDBServer(
2485314564Sdim    const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port,
2486314564Sdim    std::string &socket_name) {
2487314564Sdim  pid = LLDB_INVALID_PROCESS_ID;
2488314564Sdim  port = 0;
2489314564Sdim  socket_name.clear();
2490296417Sdim
2491314564Sdim  StringExtractorGDBRemote response;
2492314564Sdim  StreamString stream;
2493314564Sdim  stream.PutCString("qLaunchGDBServer;");
2494314564Sdim  std::string hostname;
2495314564Sdim  if (remote_accept_hostname && remote_accept_hostname[0])
2496314564Sdim    hostname = remote_accept_hostname;
2497314564Sdim  else {
2498314564Sdim    if (HostInfo::GetHostname(hostname)) {
2499314564Sdim      // Make the GDB server we launch only accept connections from this host
2500314564Sdim      stream.Printf("host:%s;", hostname.c_str());
2501314564Sdim    } else {
2502341825Sdim      // Make the GDB server we launch accept connections from any host since
2503341825Sdim      // we can't figure out the hostname
2504314564Sdim      stream.Printf("host:*;");
2505258054Semaste    }
2506314564Sdim  }
2507314564Sdim  // give the process a few seconds to startup
2508314564Sdim  ScopedTimeout timeout(*this, seconds(10));
2509258054Semaste
2510314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
2511314564Sdim      PacketResult::Success) {
2512314564Sdim    llvm::StringRef name;
2513314564Sdim    llvm::StringRef value;
2514314564Sdim    while (response.GetNameColonValue(name, value)) {
2515314564Sdim      if (name.equals("port"))
2516314564Sdim        value.getAsInteger(0, port);
2517314564Sdim      else if (name.equals("pid"))
2518314564Sdim        value.getAsInteger(0, pid);
2519314564Sdim      else if (name.compare("socket_name") == 0) {
2520314564Sdim        StringExtractor extractor(value);
2521314564Sdim        extractor.GetHexByteString(socket_name);
2522314564Sdim      }
2523254721Semaste    }
2524314564Sdim    return true;
2525314564Sdim  }
2526314564Sdim  return false;
2527254721Semaste}
2528254721Semaste
2529314564Sdimsize_t GDBRemoteCommunicationClient::QueryGDBServer(
2530314564Sdim    std::vector<std::pair<uint16_t, std::string>> &connection_urls) {
2531314564Sdim  connection_urls.clear();
2532296417Sdim
2533314564Sdim  StringExtractorGDBRemote response;
2534314564Sdim  if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) !=
2535314564Sdim      PacketResult::Success)
2536314564Sdim    return 0;
2537296417Sdim
2538314564Sdim  StructuredData::ObjectSP data =
2539314564Sdim      StructuredData::ParseJSON(response.GetStringRef());
2540314564Sdim  if (!data)
2541314564Sdim    return 0;
2542296417Sdim
2543314564Sdim  StructuredData::Array *array = data->GetAsArray();
2544314564Sdim  if (!array)
2545314564Sdim    return 0;
2546296417Sdim
2547314564Sdim  for (size_t i = 0, count = array->GetSize(); i < count; ++i) {
2548314564Sdim    StructuredData::Dictionary *element = nullptr;
2549314564Sdim    if (!array->GetItemAtIndexAsDictionary(i, element))
2550314564Sdim      continue;
2551296417Sdim
2552314564Sdim    uint16_t port = 0;
2553314564Sdim    if (StructuredData::ObjectSP port_osp =
2554314564Sdim            element->GetValueForKey(llvm::StringRef("port")))
2555314564Sdim      port = port_osp->GetIntegerValue(0);
2556296417Sdim
2557314564Sdim    std::string socket_name;
2558314564Sdim    if (StructuredData::ObjectSP socket_name_osp =
2559314564Sdim            element->GetValueForKey(llvm::StringRef("socket_name")))
2560314564Sdim      socket_name = socket_name_osp->GetStringValue();
2561296417Sdim
2562314564Sdim    if (port != 0 || !socket_name.empty())
2563314564Sdim      connection_urls.emplace_back(port, socket_name);
2564314564Sdim  }
2565314564Sdim  return connection_urls.size();
2566296417Sdim}
2567296417Sdim
2568314564Sdimbool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) {
2569314564Sdim  StreamString stream;
2570314564Sdim  stream.Printf("qKillSpawnedProcess:%" PRId64, pid);
2571258054Semaste
2572314564Sdim  StringExtractorGDBRemote response;
2573314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
2574314564Sdim      PacketResult::Success) {
2575314564Sdim    if (response.IsOKResponse())
2576314564Sdim      return true;
2577314564Sdim  }
2578314564Sdim  return false;
2579258054Semaste}
2580258054Semaste
2581314564Sdimbool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) {
2582314564Sdim  if (m_curr_tid == tid)
2583314564Sdim    return true;
2584254721Semaste
2585314564Sdim  char packet[32];
2586314564Sdim  int packet_len;
2587314564Sdim  if (tid == UINT64_MAX)
2588314564Sdim    packet_len = ::snprintf(packet, sizeof(packet), "Hg-1");
2589314564Sdim  else
2590314564Sdim    packet_len = ::snprintf(packet, sizeof(packet), "Hg%" PRIx64, tid);
2591314564Sdim  assert(packet_len + 1 < (int)sizeof(packet));
2592314564Sdim  UNUSED_IF_ASSERT_DISABLED(packet_len);
2593314564Sdim  StringExtractorGDBRemote response;
2594314564Sdim  if (SendPacketAndWaitForResponse(packet, response, false) ==
2595314564Sdim      PacketResult::Success) {
2596314564Sdim    if (response.IsOKResponse()) {
2597314564Sdim      m_curr_tid = tid;
2598314564Sdim      return true;
2599314564Sdim    }
2600296417Sdim
2601314564Sdim    /*
2602314564Sdim     * Connected bare-iron target (like YAMON gdb-stub) may not have support for
2603314564Sdim     * Hg packet.
2604314564Sdim     * The reply from '?' packet could be as simple as 'S05'. There is no packet
2605314564Sdim     * which can
2606314564Sdim     * give us pid and/or tid. Assume pid=tid=1 in such cases.
2607314564Sdim    */
2608314564Sdim    if (response.IsUnsupportedResponse() && IsConnected()) {
2609314564Sdim      m_curr_tid = 1;
2610314564Sdim      return true;
2611254721Semaste    }
2612314564Sdim  }
2613314564Sdim  return false;
2614254721Semaste}
2615254721Semaste
2616314564Sdimbool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid) {
2617314564Sdim  if (m_curr_tid_run == tid)
2618314564Sdim    return true;
2619254721Semaste
2620314564Sdim  char packet[32];
2621314564Sdim  int packet_len;
2622314564Sdim  if (tid == UINT64_MAX)
2623314564Sdim    packet_len = ::snprintf(packet, sizeof(packet), "Hc-1");
2624314564Sdim  else
2625314564Sdim    packet_len = ::snprintf(packet, sizeof(packet), "Hc%" PRIx64, tid);
2626254721Semaste
2627314564Sdim  assert(packet_len + 1 < (int)sizeof(packet));
2628314564Sdim  UNUSED_IF_ASSERT_DISABLED(packet_len);
2629314564Sdim  StringExtractorGDBRemote response;
2630314564Sdim  if (SendPacketAndWaitForResponse(packet, response, false) ==
2631314564Sdim      PacketResult::Success) {
2632314564Sdim    if (response.IsOKResponse()) {
2633314564Sdim      m_curr_tid_run = tid;
2634314564Sdim      return true;
2635314564Sdim    }
2636296417Sdim
2637314564Sdim    /*
2638314564Sdim     * Connected bare-iron target (like YAMON gdb-stub) may not have support for
2639314564Sdim     * Hc packet.
2640314564Sdim     * The reply from '?' packet could be as simple as 'S05'. There is no packet
2641314564Sdim     * which can
2642314564Sdim     * give us pid and/or tid. Assume pid=tid=1 in such cases.
2643314564Sdim    */
2644314564Sdim    if (response.IsUnsupportedResponse() && IsConnected()) {
2645314564Sdim      m_curr_tid_run = 1;
2646314564Sdim      return true;
2647254721Semaste    }
2648314564Sdim  }
2649314564Sdim  return false;
2650254721Semaste}
2651254721Semaste
2652314564Sdimbool GDBRemoteCommunicationClient::GetStopReply(
2653314564Sdim    StringExtractorGDBRemote &response) {
2654314564Sdim  if (SendPacketAndWaitForResponse("?", response, false) ==
2655314564Sdim      PacketResult::Success)
2656314564Sdim    return response.IsNormalResponse();
2657314564Sdim  return false;
2658254721Semaste}
2659254721Semaste
2660314564Sdimbool GDBRemoteCommunicationClient::GetThreadStopInfo(
2661314564Sdim    lldb::tid_t tid, StringExtractorGDBRemote &response) {
2662314564Sdim  if (m_supports_qThreadStopInfo) {
2663314564Sdim    char packet[256];
2664314564Sdim    int packet_len =
2665314564Sdim        ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
2666314564Sdim    assert(packet_len < (int)sizeof(packet));
2667314564Sdim    UNUSED_IF_ASSERT_DISABLED(packet_len);
2668314564Sdim    if (SendPacketAndWaitForResponse(packet, response, false) ==
2669314564Sdim        PacketResult::Success) {
2670314564Sdim      if (response.IsUnsupportedResponse())
2671314564Sdim        m_supports_qThreadStopInfo = false;
2672314564Sdim      else if (response.IsNormalResponse())
2673314564Sdim        return true;
2674314564Sdim      else
2675314564Sdim        return false;
2676314564Sdim    } else {
2677314564Sdim      m_supports_qThreadStopInfo = false;
2678254721Semaste    }
2679314564Sdim  }
2680314564Sdim  return false;
2681254721Semaste}
2682254721Semaste
2683314564Sdimuint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
2684314564Sdim    GDBStoppointType type, bool insert, addr_t addr, uint32_t length) {
2685314564Sdim  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
2686360784Sdim  LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
2687360784Sdim            __FUNCTION__, insert ? "add" : "remove", addr);
2688254721Semaste
2689314564Sdim  // Check if the stub is known not to support this breakpoint type
2690314564Sdim  if (!SupportsGDBStoppointPacket(type))
2691314564Sdim    return UINT8_MAX;
2692314564Sdim  // Construct the breakpoint packet
2693314564Sdim  char packet[64];
2694314564Sdim  const int packet_len =
2695314564Sdim      ::snprintf(packet, sizeof(packet), "%c%i,%" PRIx64 ",%x",
2696314564Sdim                 insert ? 'Z' : 'z', type, addr, length);
2697314564Sdim  // Check we haven't overwritten the end of the packet buffer
2698314564Sdim  assert(packet_len + 1 < (int)sizeof(packet));
2699314564Sdim  UNUSED_IF_ASSERT_DISABLED(packet_len);
2700314564Sdim  StringExtractorGDBRemote response;
2701314564Sdim  // Make sure the response is either "OK", "EXX" where XX are two hex digits,
2702314564Sdim  // or "" (unsupported)
2703314564Sdim  response.SetResponseValidatorToOKErrorNotSupported();
2704314564Sdim  // Try to send the breakpoint packet, and check that it was correctly sent
2705314564Sdim  if (SendPacketAndWaitForResponse(packet, response, true) ==
2706314564Sdim      PacketResult::Success) {
2707314564Sdim    // Receive and OK packet when the breakpoint successfully placed
2708314564Sdim    if (response.IsOKResponse())
2709314564Sdim      return 0;
2710280031Sdim
2711321369Sdim    // Status while setting breakpoint, send back specific error
2712314564Sdim    if (response.IsErrorResponse())
2713314564Sdim      return response.GetError();
2714314564Sdim
2715314564Sdim    // Empty packet informs us that breakpoint is not supported
2716314564Sdim    if (response.IsUnsupportedResponse()) {
2717314564Sdim      // Disable this breakpoint type since it is unsupported
2718314564Sdim      switch (type) {
2719314564Sdim      case eBreakpointSoftware:
2720314564Sdim        m_supports_z0 = false;
2721314564Sdim        break;
2722314564Sdim      case eBreakpointHardware:
2723314564Sdim        m_supports_z1 = false;
2724314564Sdim        break;
2725314564Sdim      case eWatchpointWrite:
2726314564Sdim        m_supports_z2 = false;
2727314564Sdim        break;
2728314564Sdim      case eWatchpointRead:
2729314564Sdim        m_supports_z3 = false;
2730314564Sdim        break;
2731314564Sdim      case eWatchpointReadWrite:
2732314564Sdim        m_supports_z4 = false;
2733314564Sdim        break;
2734314564Sdim      case eStoppointInvalid:
2735262528Semaste        return UINT8_MAX;
2736314564Sdim      }
2737314564Sdim    }
2738314564Sdim  }
2739314564Sdim  // Signal generic failure
2740314564Sdim  return UINT8_MAX;
2741314564Sdim}
2742314564Sdim
2743314564Sdimsize_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
2744314564Sdim    std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
2745314564Sdim  thread_ids.clear();
2746314564Sdim
2747314564Sdim  Lock lock(*this, false);
2748314564Sdim  if (lock) {
2749314564Sdim    sequence_mutex_unavailable = false;
2750254721Semaste    StringExtractorGDBRemote response;
2751262528Semaste
2752314564Sdim    PacketResult packet_result;
2753314564Sdim    for (packet_result =
2754314564Sdim             SendPacketAndWaitForResponseNoLock("qfThreadInfo", response);
2755314564Sdim         packet_result == PacketResult::Success && response.IsNormalResponse();
2756314564Sdim         packet_result =
2757314564Sdim             SendPacketAndWaitForResponseNoLock("qsThreadInfo", response)) {
2758314564Sdim      char ch = response.GetChar();
2759314564Sdim      if (ch == 'l')
2760314564Sdim        break;
2761314564Sdim      if (ch == 'm') {
2762314564Sdim        do {
2763314564Sdim          tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
2764262528Semaste
2765314564Sdim          if (tid != LLDB_INVALID_THREAD_ID) {
2766314564Sdim            thread_ids.push_back(tid);
2767314564Sdim          }
2768314564Sdim          ch = response.GetChar(); // Skip the command separator
2769314564Sdim        } while (ch == ',');       // Make sure we got a comma separator
2770314564Sdim      }
2771254721Semaste    }
2772254721Semaste
2773314564Sdim    /*
2774314564Sdim     * Connected bare-iron target (like YAMON gdb-stub) may not have support for
2775314564Sdim     * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet
2776314564Sdim     * could
2777314564Sdim     * be as simple as 'S05'. There is no packet which can give us pid and/or
2778314564Sdim     * tid.
2779314564Sdim     * Assume pid=tid=1 in such cases.
2780314564Sdim    */
2781327952Sdim    if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) &&
2782327952Sdim        thread_ids.size() == 0 && IsConnected()) {
2783314564Sdim      thread_ids.push_back(1);
2784254721Semaste    }
2785314564Sdim  } else {
2786314564Sdim#if !defined(LLDB_CONFIGURATION_DEBUG)
2787314564Sdim    Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
2788314564Sdim                                                           GDBR_LOG_PACKETS));
2789360784Sdim    LLDB_LOGF(log, "error: failed to get packet sequence mutex, not sending "
2790360784Sdim                   "packet 'qfThreadInfo'");
2791254721Semaste#endif
2792314564Sdim    sequence_mutex_unavailable = true;
2793314564Sdim  }
2794314564Sdim  return thread_ids.size();
2795254721Semaste}
2796254721Semaste
2797314564Sdimlldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() {
2798314564Sdim  StringExtractorGDBRemote response;
2799314564Sdim  if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) !=
2800314564Sdim          PacketResult::Success ||
2801314564Sdim      !response.IsNormalResponse())
2802254721Semaste    return LLDB_INVALID_ADDRESS;
2803314564Sdim  return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
2804254721Semaste}
2805254721Semaste
2806321369Sdimlldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
2807314564Sdim    const char *command, // Shouldn't be NULL
2808314564Sdim    const FileSpec &
2809314564Sdim        working_dir, // Pass empty FileSpec to use the current working directory
2810314564Sdim    int *status_ptr, // Pass NULL if you don't want the process exit status
2811314564Sdim    int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
2812314564Sdim                     // process to exit
2813314564Sdim    std::string
2814314564Sdim        *command_output, // Pass NULL if you don't want the command output
2815341825Sdim    const Timeout<std::micro> &timeout) {
2816314564Sdim  lldb_private::StreamString stream;
2817314564Sdim  stream.PutCString("qPlatform_shell:");
2818314564Sdim  stream.PutBytesAsRawHex8(command, strlen(command));
2819314564Sdim  stream.PutChar(',');
2820341825Sdim  uint32_t timeout_sec = UINT32_MAX;
2821341825Sdim  if (timeout) {
2822341825Sdim    // TODO: Use chrono version of std::ceil once c++17 is available.
2823341825Sdim    timeout_sec = std::ceil(std::chrono::duration<double>(*timeout).count());
2824341825Sdim  }
2825314564Sdim  stream.PutHex32(timeout_sec);
2826314564Sdim  if (working_dir) {
2827314564Sdim    std::string path{working_dir.GetPath(false)};
2828258054Semaste    stream.PutChar(',');
2829353358Sdim    stream.PutStringAsRawHex8(path);
2830314564Sdim  }
2831314564Sdim  StringExtractorGDBRemote response;
2832314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
2833314564Sdim      PacketResult::Success) {
2834314564Sdim    if (response.GetChar() != 'F')
2835321369Sdim      return Status("malformed reply");
2836314564Sdim    if (response.GetChar() != ',')
2837321369Sdim      return Status("malformed reply");
2838314564Sdim    uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
2839314564Sdim    if (exitcode == UINT32_MAX)
2840321369Sdim      return Status("unable to run remote process");
2841314564Sdim    else if (status_ptr)
2842314564Sdim      *status_ptr = exitcode;
2843314564Sdim    if (response.GetChar() != ',')
2844321369Sdim      return Status("malformed reply");
2845314564Sdim    uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
2846314564Sdim    if (signo_ptr)
2847314564Sdim      *signo_ptr = signo;
2848314564Sdim    if (response.GetChar() != ',')
2849321369Sdim      return Status("malformed reply");
2850314564Sdim    std::string output;
2851314564Sdim    response.GetEscapedBinaryData(output);
2852314564Sdim    if (command_output)
2853314564Sdim      command_output->assign(output);
2854321369Sdim    return Status();
2855314564Sdim  }
2856321369Sdim  return Status("unable to send packet");
2857258054Semaste}
2858258054Semaste
2859321369SdimStatus GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec,
2860321369Sdim                                                   uint32_t file_permissions) {
2861314564Sdim  std::string path{file_spec.GetPath(false)};
2862314564Sdim  lldb_private::StreamString stream;
2863314564Sdim  stream.PutCString("qPlatform_mkdir:");
2864314564Sdim  stream.PutHex32(file_permissions);
2865314564Sdim  stream.PutChar(',');
2866353358Sdim  stream.PutStringAsRawHex8(path);
2867314564Sdim  llvm::StringRef packet = stream.GetString();
2868314564Sdim  StringExtractorGDBRemote response;
2869258054Semaste
2870314564Sdim  if (SendPacketAndWaitForResponse(packet, response, false) !=
2871314564Sdim      PacketResult::Success)
2872321369Sdim    return Status("failed to send '%s' packet", packet.str().c_str());
2873288943Sdim
2874314564Sdim  if (response.GetChar() != 'F')
2875321369Sdim    return Status("invalid response to '%s' packet", packet.str().c_str());
2876288943Sdim
2877321369Sdim  return Status(response.GetU32(UINT32_MAX), eErrorTypePOSIX);
2878258054Semaste}
2879258054Semaste
2880321369SdimStatus
2881321369SdimGDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec,
2882321369Sdim                                                 uint32_t file_permissions) {
2883314564Sdim  std::string path{file_spec.GetPath(false)};
2884314564Sdim  lldb_private::StreamString stream;
2885314564Sdim  stream.PutCString("qPlatform_chmod:");
2886314564Sdim  stream.PutHex32(file_permissions);
2887314564Sdim  stream.PutChar(',');
2888353358Sdim  stream.PutStringAsRawHex8(path);
2889314564Sdim  llvm::StringRef packet = stream.GetString();
2890314564Sdim  StringExtractorGDBRemote response;
2891288943Sdim
2892314564Sdim  if (SendPacketAndWaitForResponse(packet, response, false) !=
2893314564Sdim      PacketResult::Success)
2894321369Sdim    return Status("failed to send '%s' packet", stream.GetData());
2895288943Sdim
2896314564Sdim  if (response.GetChar() != 'F')
2897321369Sdim    return Status("invalid response to '%s' packet", stream.GetData());
2898288943Sdim
2899321369Sdim  return Status(response.GetU32(UINT32_MAX), eErrorTypePOSIX);
2900258884Semaste}
2901258884Semaste
2902314564Sdimstatic uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response,
2903321369Sdim                                          uint64_t fail_result, Status &error) {
2904314564Sdim  response.SetFilePos(0);
2905314564Sdim  if (response.GetChar() != 'F')
2906314564Sdim    return fail_result;
2907314564Sdim  int32_t result = response.GetS32(-2);
2908314564Sdim  if (result == -2)
2909314564Sdim    return fail_result;
2910314564Sdim  if (response.GetChar() == ',') {
2911314564Sdim    int result_errno = response.GetS32(-2);
2912314564Sdim    if (result_errno != -2)
2913314564Sdim      error.SetError(result_errno, eErrorTypePOSIX);
2914258054Semaste    else
2915314564Sdim      error.SetError(-1, eErrorTypeGeneric);
2916314564Sdim  } else
2917314564Sdim    error.Clear();
2918314564Sdim  return result;
2919258054Semaste}
2920258054Semastelldb::user_id_t
2921314564SdimGDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec,
2922360784Sdim                                       File::OpenOptions flags, mode_t mode,
2923321369Sdim                                       Status &error) {
2924314564Sdim  std::string path(file_spec.GetPath(false));
2925314564Sdim  lldb_private::StreamString stream;
2926314564Sdim  stream.PutCString("vFile:open:");
2927314564Sdim  if (path.empty())
2928258054Semaste    return UINT64_MAX;
2929353358Sdim  stream.PutStringAsRawHex8(path);
2930314564Sdim  stream.PutChar(',');
2931314564Sdim  stream.PutHex32(flags);
2932314564Sdim  stream.PutChar(',');
2933314564Sdim  stream.PutHex32(mode);
2934314564Sdim  StringExtractorGDBRemote response;
2935314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
2936314564Sdim      PacketResult::Success) {
2937314564Sdim    return ParseHostIOPacketResponse(response, UINT64_MAX, error);
2938314564Sdim  }
2939314564Sdim  return UINT64_MAX;
2940258054Semaste}
2941258054Semaste
2942321369Sdimbool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd,
2943321369Sdim                                             Status &error) {
2944314564Sdim  lldb_private::StreamString stream;
2945314564Sdim  stream.Printf("vFile:close:%i", (int)fd);
2946314564Sdim  StringExtractorGDBRemote response;
2947314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
2948314564Sdim      PacketResult::Success) {
2949314564Sdim    return ParseHostIOPacketResponse(response, -1, error) == 0;
2950314564Sdim  }
2951314564Sdim  return false;
2952258054Semaste}
2953258054Semaste
2954258054Semaste// Extension of host I/O packets to get the file size.
2955314564Sdimlldb::user_id_t GDBRemoteCommunicationClient::GetFileSize(
2956314564Sdim    const lldb_private::FileSpec &file_spec) {
2957314564Sdim  std::string path(file_spec.GetPath(false));
2958314564Sdim  lldb_private::StreamString stream;
2959314564Sdim  stream.PutCString("vFile:size:");
2960353358Sdim  stream.PutStringAsRawHex8(path);
2961314564Sdim  StringExtractorGDBRemote response;
2962314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
2963314564Sdim      PacketResult::Success) {
2964314564Sdim    if (response.GetChar() != 'F')
2965314564Sdim      return UINT64_MAX;
2966314564Sdim    uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
2967314564Sdim    return retcode;
2968314564Sdim  }
2969314564Sdim  return UINT64_MAX;
2970258054Semaste}
2971258054Semaste
2972321369SdimStatus
2973321369SdimGDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec,
2974321369Sdim                                                 uint32_t &file_permissions) {
2975314564Sdim  std::string path{file_spec.GetPath(false)};
2976321369Sdim  Status error;
2977314564Sdim  lldb_private::StreamString stream;
2978314564Sdim  stream.PutCString("vFile:mode:");
2979353358Sdim  stream.PutStringAsRawHex8(path);
2980314564Sdim  StringExtractorGDBRemote response;
2981314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
2982314564Sdim      PacketResult::Success) {
2983314564Sdim    if (response.GetChar() != 'F') {
2984314564Sdim      error.SetErrorStringWithFormat("invalid response to '%s' packet",
2985314564Sdim                                     stream.GetData());
2986314564Sdim    } else {
2987314564Sdim      const uint32_t mode = response.GetS32(-1);
2988314564Sdim      if (static_cast<int32_t>(mode) == -1) {
2989314564Sdim        if (response.GetChar() == ',') {
2990314564Sdim          int response_errno = response.GetS32(-1);
2991314564Sdim          if (response_errno > 0)
2992314564Sdim            error.SetError(response_errno, lldb::eErrorTypePOSIX);
2993314564Sdim          else
2994314564Sdim            error.SetErrorToGenericError();
2995314564Sdim        } else
2996314564Sdim          error.SetErrorToGenericError();
2997314564Sdim      } else {
2998314564Sdim        file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO);
2999314564Sdim      }
3000258054Semaste    }
3001314564Sdim  } else {
3002314564Sdim    error.SetErrorStringWithFormat("failed to send '%s' packet",
3003314564Sdim                                   stream.GetData());
3004314564Sdim  }
3005314564Sdim  return error;
3006258054Semaste}
3007258054Semaste
3008314564Sdimuint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd,
3009314564Sdim                                                uint64_t offset, void *dst,
3010314564Sdim                                                uint64_t dst_len,
3011321369Sdim                                                Status &error) {
3012314564Sdim  lldb_private::StreamString stream;
3013314564Sdim  stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len,
3014314564Sdim                offset);
3015314564Sdim  StringExtractorGDBRemote response;
3016314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
3017314564Sdim      PacketResult::Success) {
3018314564Sdim    if (response.GetChar() != 'F')
3019314564Sdim      return 0;
3020314564Sdim    uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
3021314564Sdim    if (retcode == UINT32_MAX)
3022314564Sdim      return retcode;
3023314564Sdim    const char next = (response.Peek() ? *response.Peek() : 0);
3024314564Sdim    if (next == ',')
3025314564Sdim      return 0;
3026314564Sdim    if (next == ';') {
3027314564Sdim      response.GetChar(); // skip the semicolon
3028314564Sdim      std::string buffer;
3029314564Sdim      if (response.GetEscapedBinaryData(buffer)) {
3030314564Sdim        const uint64_t data_to_write =
3031314564Sdim            std::min<uint64_t>(dst_len, buffer.size());
3032314564Sdim        if (data_to_write > 0)
3033314564Sdim          memcpy(dst, &buffer[0], data_to_write);
3034314564Sdim        return data_to_write;
3035314564Sdim      }
3036258054Semaste    }
3037314564Sdim  }
3038314564Sdim  return 0;
3039258054Semaste}
3040258054Semaste
3041314564Sdimuint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd,
3042314564Sdim                                                 uint64_t offset,
3043314564Sdim                                                 const void *src,
3044314564Sdim                                                 uint64_t src_len,
3045321369Sdim                                                 Status &error) {
3046314564Sdim  lldb_private::StreamGDBRemote stream;
3047314564Sdim  stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
3048314564Sdim  stream.PutEscapedBytes(src, src_len);
3049314564Sdim  StringExtractorGDBRemote response;
3050314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
3051314564Sdim      PacketResult::Success) {
3052314564Sdim    if (response.GetChar() != 'F') {
3053314564Sdim      error.SetErrorStringWithFormat("write file failed");
3054314564Sdim      return 0;
3055258054Semaste    }
3056314564Sdim    uint64_t bytes_written = response.GetU64(UINT64_MAX);
3057314564Sdim    if (bytes_written == UINT64_MAX) {
3058314564Sdim      error.SetErrorToGenericError();
3059314564Sdim      if (response.GetChar() == ',') {
3060314564Sdim        int response_errno = response.GetS32(-1);
3061314564Sdim        if (response_errno > 0)
3062314564Sdim          error.SetError(response_errno, lldb::eErrorTypePOSIX);
3063314564Sdim      }
3064314564Sdim      return 0;
3065258054Semaste    }
3066314564Sdim    return bytes_written;
3067314564Sdim  } else {
3068314564Sdim    error.SetErrorString("failed to send vFile:pwrite packet");
3069314564Sdim  }
3070314564Sdim  return 0;
3071258054Semaste}
3072258054Semaste
3073321369SdimStatus GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src,
3074321369Sdim                                                   const FileSpec &dst) {
3075314564Sdim  std::string src_path{src.GetPath(false)}, dst_path{dst.GetPath(false)};
3076321369Sdim  Status error;
3077314564Sdim  lldb_private::StreamGDBRemote stream;
3078314564Sdim  stream.PutCString("vFile:symlink:");
3079314564Sdim  // the unix symlink() command reverses its parameters where the dst if first,
3080314564Sdim  // so we follow suit here
3081353358Sdim  stream.PutStringAsRawHex8(dst_path);
3082314564Sdim  stream.PutChar(',');
3083353358Sdim  stream.PutStringAsRawHex8(src_path);
3084314564Sdim  StringExtractorGDBRemote response;
3085314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
3086314564Sdim      PacketResult::Success) {
3087314564Sdim    if (response.GetChar() == 'F') {
3088314564Sdim      uint32_t result = response.GetU32(UINT32_MAX);
3089314564Sdim      if (result != 0) {
3090314564Sdim        error.SetErrorToGenericError();
3091314564Sdim        if (response.GetChar() == ',') {
3092314564Sdim          int response_errno = response.GetS32(-1);
3093314564Sdim          if (response_errno > 0)
3094314564Sdim            error.SetError(response_errno, lldb::eErrorTypePOSIX);
3095258884Semaste        }
3096314564Sdim      }
3097314564Sdim    } else {
3098314564Sdim      // Should have returned with 'F<result>[,<errno>]'
3099314564Sdim      error.SetErrorStringWithFormat("symlink failed");
3100258884Semaste    }
3101314564Sdim  } else {
3102314564Sdim    error.SetErrorString("failed to send vFile:symlink packet");
3103314564Sdim  }
3104314564Sdim  return error;
3105258884Semaste}
3106258884Semaste
3107321369SdimStatus GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) {
3108314564Sdim  std::string path{file_spec.GetPath(false)};
3109321369Sdim  Status error;
3110314564Sdim  lldb_private::StreamGDBRemote stream;
3111314564Sdim  stream.PutCString("vFile:unlink:");
3112314564Sdim  // the unix symlink() command reverses its parameters where the dst if first,
3113314564Sdim  // so we follow suit here
3114353358Sdim  stream.PutStringAsRawHex8(path);
3115314564Sdim  StringExtractorGDBRemote response;
3116314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
3117314564Sdim      PacketResult::Success) {
3118314564Sdim    if (response.GetChar() == 'F') {
3119314564Sdim      uint32_t result = response.GetU32(UINT32_MAX);
3120314564Sdim      if (result != 0) {
3121314564Sdim        error.SetErrorToGenericError();
3122314564Sdim        if (response.GetChar() == ',') {
3123314564Sdim          int response_errno = response.GetS32(-1);
3124314564Sdim          if (response_errno > 0)
3125314564Sdim            error.SetError(response_errno, lldb::eErrorTypePOSIX);
3126258884Semaste        }
3127314564Sdim      }
3128314564Sdim    } else {
3129314564Sdim      // Should have returned with 'F<result>[,<errno>]'
3130314564Sdim      error.SetErrorStringWithFormat("unlink failed");
3131258884Semaste    }
3132314564Sdim  } else {
3133314564Sdim    error.SetErrorString("failed to send vFile:unlink packet");
3134314564Sdim  }
3135314564Sdim  return error;
3136258884Semaste}
3137258884Semaste
3138258054Semaste// Extension of host I/O packets to get whether a file exists.
3139314564Sdimbool GDBRemoteCommunicationClient::GetFileExists(
3140314564Sdim    const lldb_private::FileSpec &file_spec) {
3141314564Sdim  std::string path(file_spec.GetPath(false));
3142314564Sdim  lldb_private::StreamString stream;
3143314564Sdim  stream.PutCString("vFile:exists:");
3144353358Sdim  stream.PutStringAsRawHex8(path);
3145314564Sdim  StringExtractorGDBRemote response;
3146314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
3147314564Sdim      PacketResult::Success) {
3148314564Sdim    if (response.GetChar() != 'F')
3149314564Sdim      return false;
3150314564Sdim    if (response.GetChar() != ',')
3151314564Sdim      return false;
3152314564Sdim    bool retcode = (response.GetChar() != '0');
3153314564Sdim    return retcode;
3154314564Sdim  }
3155314564Sdim  return false;
3156258054Semaste}
3157258054Semaste
3158314564Sdimbool GDBRemoteCommunicationClient::CalculateMD5(
3159314564Sdim    const lldb_private::FileSpec &file_spec, uint64_t &high, uint64_t &low) {
3160314564Sdim  std::string path(file_spec.GetPath(false));
3161314564Sdim  lldb_private::StreamString stream;
3162314564Sdim  stream.PutCString("vFile:MD5:");
3163353358Sdim  stream.PutStringAsRawHex8(path);
3164314564Sdim  StringExtractorGDBRemote response;
3165314564Sdim  if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
3166314564Sdim      PacketResult::Success) {
3167314564Sdim    if (response.GetChar() != 'F')
3168314564Sdim      return false;
3169314564Sdim    if (response.GetChar() != ',')
3170314564Sdim      return false;
3171314564Sdim    if (response.Peek() && *response.Peek() == 'x')
3172314564Sdim      return false;
3173314564Sdim    low = response.GetHexMaxU64(false, UINT64_MAX);
3174314564Sdim    high = response.GetHexMaxU64(false, UINT64_MAX);
3175314564Sdim    return true;
3176314564Sdim  }
3177314564Sdim  return false;
3178258054Semaste}
3179258884Semaste
3180314564Sdimbool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) {
3181314564Sdim  // Some targets have issues with g/G packets and we need to avoid using them
3182314564Sdim  if (m_avoid_g_packets == eLazyBoolCalculate) {
3183314564Sdim    if (process) {
3184314564Sdim      m_avoid_g_packets = eLazyBoolNo;
3185314564Sdim      const ArchSpec &arch = process->GetTarget().GetArchitecture();
3186314564Sdim      if (arch.IsValid() &&
3187314564Sdim          arch.GetTriple().getVendor() == llvm::Triple::Apple &&
3188314564Sdim          arch.GetTriple().getOS() == llvm::Triple::IOS &&
3189360784Sdim          (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
3190360784Sdim           arch.GetTriple().getArch() == llvm::Triple::aarch64_32)) {
3191314564Sdim        m_avoid_g_packets = eLazyBoolYes;
3192314564Sdim        uint32_t gdb_server_version = GetGDBServerProgramVersion();
3193314564Sdim        if (gdb_server_version != 0) {
3194314564Sdim          const char *gdb_server_name = GetGDBServerProgramName();
3195314564Sdim          if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0) {
3196314564Sdim            if (gdb_server_version >= 310)
3197314564Sdim              m_avoid_g_packets = eLazyBoolNo;
3198314564Sdim          }
3199276479Sdim        }
3200314564Sdim      }
3201276479Sdim    }
3202314564Sdim  }
3203314564Sdim  return m_avoid_g_packets == eLazyBoolYes;
3204276479Sdim}
3205276479Sdim
3206314564SdimDataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid,
3207314564Sdim                                                        uint32_t reg) {
3208314564Sdim  StreamString payload;
3209314564Sdim  payload.Printf("p%x", reg);
3210314564Sdim  StringExtractorGDBRemote response;
3211314564Sdim  if (SendThreadSpecificPacketAndWaitForResponse(
3212314564Sdim          tid, std::move(payload), response, false) != PacketResult::Success ||
3213314564Sdim      !response.IsNormalResponse())
3214314564Sdim    return nullptr;
3215258884Semaste
3216314564Sdim  DataBufferSP buffer_sp(
3217314564Sdim      new DataBufferHeap(response.GetStringRef().size() / 2, 0));
3218314564Sdim  response.GetHexBytes(buffer_sp->GetData(), '\xcc');
3219314564Sdim  return buffer_sp;
3220258884Semaste}
3221258884Semaste
3222314564SdimDataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) {
3223314564Sdim  StreamString payload;
3224314564Sdim  payload.PutChar('g');
3225314564Sdim  StringExtractorGDBRemote response;
3226314564Sdim  if (SendThreadSpecificPacketAndWaitForResponse(
3227314564Sdim          tid, std::move(payload), response, false) != PacketResult::Success ||
3228314564Sdim      !response.IsNormalResponse())
3229314564Sdim    return nullptr;
3230258884Semaste
3231314564Sdim  DataBufferSP buffer_sp(
3232314564Sdim      new DataBufferHeap(response.GetStringRef().size() / 2, 0));
3233314564Sdim  response.GetHexBytes(buffer_sp->GetData(), '\xcc');
3234314564Sdim  return buffer_sp;
3235314564Sdim}
3236258884Semaste
3237314564Sdimbool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid,
3238314564Sdim                                                 uint32_t reg_num,
3239314564Sdim                                                 llvm::ArrayRef<uint8_t> data) {
3240314564Sdim  StreamString payload;
3241314564Sdim  payload.Printf("P%x=", reg_num);
3242314564Sdim  payload.PutBytesAsRawHex8(data.data(), data.size(),
3243314564Sdim                            endian::InlHostByteOrder(),
3244314564Sdim                            endian::InlHostByteOrder());
3245314564Sdim  StringExtractorGDBRemote response;
3246314564Sdim  return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
3247314564Sdim                                                    response, false) ==
3248314564Sdim             PacketResult::Success &&
3249314564Sdim         response.IsOKResponse();
3250314564Sdim}
3251314564Sdim
3252314564Sdimbool GDBRemoteCommunicationClient::WriteAllRegisters(
3253314564Sdim    lldb::tid_t tid, llvm::ArrayRef<uint8_t> data) {
3254314564Sdim  StreamString payload;
3255314564Sdim  payload.PutChar('G');
3256314564Sdim  payload.PutBytesAsRawHex8(data.data(), data.size(),
3257314564Sdim                            endian::InlHostByteOrder(),
3258314564Sdim                            endian::InlHostByteOrder());
3259314564Sdim  StringExtractorGDBRemote response;
3260314564Sdim  return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
3261314564Sdim                                                    response, false) ==
3262314564Sdim             PacketResult::Success &&
3263314564Sdim         response.IsOKResponse();
3264314564Sdim}
3265314564Sdim
3266314564Sdimbool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
3267314564Sdim                                                     uint32_t &save_id) {
3268314564Sdim  save_id = 0; // Set to invalid save ID
3269314564Sdim  if (m_supports_QSaveRegisterState == eLazyBoolNo)
3270258884Semaste    return false;
3271314564Sdim
3272314564Sdim  m_supports_QSaveRegisterState = eLazyBoolYes;
3273314564Sdim  StreamString payload;
3274314564Sdim  payload.PutCString("QSaveRegisterState");
3275314564Sdim  StringExtractorGDBRemote response;
3276314564Sdim  if (SendThreadSpecificPacketAndWaitForResponse(
3277314564Sdim          tid, std::move(payload), response, false) != PacketResult::Success)
3278314564Sdim    return false;
3279314564Sdim
3280314564Sdim  if (response.IsUnsupportedResponse())
3281314564Sdim    m_supports_QSaveRegisterState = eLazyBoolNo;
3282314564Sdim
3283314564Sdim  const uint32_t response_save_id = response.GetU32(0);
3284314564Sdim  if (response_save_id == 0)
3285314564Sdim    return false;
3286314564Sdim
3287314564Sdim  save_id = response_save_id;
3288314564Sdim  return true;
3289258884Semaste}
3290258884Semaste
3291314564Sdimbool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
3292314564Sdim                                                        uint32_t save_id) {
3293314564Sdim  // We use the "m_supports_QSaveRegisterState" variable here because the
3294341825Sdim  // QSaveRegisterState and QRestoreRegisterState packets must both be
3295341825Sdim  // supported in order to be useful
3296314564Sdim  if (m_supports_QSaveRegisterState == eLazyBoolNo)
3297258884Semaste    return false;
3298314564Sdim
3299314564Sdim  StreamString payload;
3300314564Sdim  payload.Printf("QRestoreRegisterState:%u", save_id);
3301314564Sdim  StringExtractorGDBRemote response;
3302314564Sdim  if (SendThreadSpecificPacketAndWaitForResponse(
3303314564Sdim          tid, std::move(payload), response, false) != PacketResult::Success)
3304314564Sdim    return false;
3305314564Sdim
3306314564Sdim  if (response.IsOKResponse())
3307314564Sdim    return true;
3308314564Sdim
3309314564Sdim  if (response.IsUnsupportedResponse())
3310314564Sdim    m_supports_QSaveRegisterState = eLazyBoolNo;
3311314564Sdim  return false;
3312258884Semaste}
3313258884Semaste
3314314564Sdimbool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) {
3315314564Sdim  if (!GetSyncThreadStateSupported())
3316258884Semaste    return false;
3317314564Sdim
3318314564Sdim  StreamString packet;
3319314564Sdim  StringExtractorGDBRemote response;
3320314564Sdim  packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid);
3321314564Sdim  return SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
3322314564Sdim             GDBRemoteCommunication::PacketResult::Success &&
3323314564Sdim         response.IsOKResponse();
3324258884Semaste}
3325288943Sdim
3326321369Sdimlldb::user_id_t
3327321369SdimGDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options,
3328321369Sdim                                                   Status &error) {
3329321369Sdim  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3330321369Sdim  lldb::user_id_t ret_uid = LLDB_INVALID_UID;
3331321369Sdim
3332321369Sdim  StreamGDBRemote escaped_packet;
3333321369Sdim  escaped_packet.PutCString("jTraceStart:");
3334321369Sdim
3335321369Sdim  StructuredData::Dictionary json_packet;
3336321369Sdim  json_packet.AddIntegerItem("type", options.getType());
3337321369Sdim  json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
3338321369Sdim  json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
3339321369Sdim
3340321369Sdim  if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
3341321369Sdim    json_packet.AddIntegerItem("threadid", options.getThreadID());
3342321369Sdim
3343321369Sdim  StructuredData::DictionarySP custom_params = options.getTraceParams();
3344321369Sdim  if (custom_params)
3345321369Sdim    json_packet.AddItem("params", custom_params);
3346321369Sdim
3347321369Sdim  StreamString json_string;
3348321369Sdim  json_packet.Dump(json_string, false);
3349321369Sdim  escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
3350321369Sdim
3351321369Sdim  StringExtractorGDBRemote response;
3352321369Sdim  if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3353321369Sdim                                   true) ==
3354321369Sdim      GDBRemoteCommunication::PacketResult::Success) {
3355321369Sdim    if (!response.IsNormalResponse()) {
3356321369Sdim      error = response.GetStatus();
3357321369Sdim      LLDB_LOG(log, "Target does not support Tracing , error {0}", error);
3358321369Sdim    } else {
3359321369Sdim      ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID);
3360321369Sdim    }
3361321369Sdim  } else {
3362321369Sdim    LLDB_LOG(log, "failed to send packet");
3363321369Sdim    error.SetErrorStringWithFormat("failed to send packet: '%s'",
3364321369Sdim                                   escaped_packet.GetData());
3365321369Sdim  }
3366321369Sdim  return ret_uid;
3367321369Sdim}
3368321369Sdim
3369321369SdimStatus
3370321369SdimGDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid,
3371321369Sdim                                                  lldb::tid_t thread_id) {
3372321369Sdim  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3373321369Sdim  StringExtractorGDBRemote response;
3374321369Sdim  Status error;
3375321369Sdim
3376321369Sdim  StructuredData::Dictionary json_packet;
3377321369Sdim  StreamGDBRemote escaped_packet;
3378321369Sdim  StreamString json_string;
3379321369Sdim  escaped_packet.PutCString("jTraceStop:");
3380321369Sdim
3381321369Sdim  json_packet.AddIntegerItem("traceid", uid);
3382321369Sdim
3383321369Sdim  if (thread_id != LLDB_INVALID_THREAD_ID)
3384321369Sdim    json_packet.AddIntegerItem("threadid", thread_id);
3385321369Sdim
3386321369Sdim  json_packet.Dump(json_string, false);
3387321369Sdim
3388321369Sdim  escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
3389321369Sdim
3390321369Sdim  if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3391321369Sdim                                   true) ==
3392321369Sdim      GDBRemoteCommunication::PacketResult::Success) {
3393321369Sdim    if (!response.IsOKResponse()) {
3394321369Sdim      error = response.GetStatus();
3395321369Sdim      LLDB_LOG(log, "stop tracing failed");
3396321369Sdim    }
3397321369Sdim  } else {
3398321369Sdim    LLDB_LOG(log, "failed to send packet");
3399321369Sdim    error.SetErrorStringWithFormat(
3400321369Sdim        "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(),
3401321369Sdim        response.GetError());
3402321369Sdim  }
3403321369Sdim  return error;
3404321369Sdim}
3405321369Sdim
3406321369SdimStatus GDBRemoteCommunicationClient::SendGetDataPacket(
3407321369Sdim    lldb::user_id_t uid, lldb::tid_t thread_id,
3408321369Sdim    llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
3409321369Sdim
3410321369Sdim  StreamGDBRemote escaped_packet;
3411321369Sdim  escaped_packet.PutCString("jTraceBufferRead:");
3412321369Sdim  return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
3413321369Sdim}
3414321369Sdim
3415321369SdimStatus GDBRemoteCommunicationClient::SendGetMetaDataPacket(
3416321369Sdim    lldb::user_id_t uid, lldb::tid_t thread_id,
3417321369Sdim    llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
3418321369Sdim
3419321369Sdim  StreamGDBRemote escaped_packet;
3420321369Sdim  escaped_packet.PutCString("jTraceMetaRead:");
3421321369Sdim  return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
3422321369Sdim}
3423321369Sdim
3424321369SdimStatus
3425321369SdimGDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid,
3426321369Sdim                                                       TraceOptions &options) {
3427321369Sdim  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3428321369Sdim  StringExtractorGDBRemote response;
3429321369Sdim  Status error;
3430321369Sdim
3431321369Sdim  StreamString json_string;
3432321369Sdim  StreamGDBRemote escaped_packet;
3433321369Sdim  escaped_packet.PutCString("jTraceConfigRead:");
3434321369Sdim
3435321369Sdim  StructuredData::Dictionary json_packet;
3436321369Sdim  json_packet.AddIntegerItem("traceid", uid);
3437321369Sdim
3438321369Sdim  if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
3439321369Sdim    json_packet.AddIntegerItem("threadid", options.getThreadID());
3440321369Sdim
3441321369Sdim  json_packet.Dump(json_string, false);
3442321369Sdim  escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
3443321369Sdim
3444321369Sdim  if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3445321369Sdim                                   true) ==
3446321369Sdim      GDBRemoteCommunication::PacketResult::Success) {
3447321369Sdim    if (response.IsNormalResponse()) {
3448321369Sdim      uint64_t type = std::numeric_limits<uint64_t>::max();
3449321369Sdim      uint64_t buffersize = std::numeric_limits<uint64_t>::max();
3450321369Sdim      uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
3451321369Sdim
3452321369Sdim      auto json_object = StructuredData::ParseJSON(response.Peek());
3453321369Sdim
3454321369Sdim      if (!json_object ||
3455321369Sdim          json_object->GetType() != lldb::eStructuredDataTypeDictionary) {
3456321369Sdim        error.SetErrorString("Invalid Configuration obtained");
3457321369Sdim        return error;
3458321369Sdim      }
3459321369Sdim
3460321369Sdim      auto json_dict = json_object->GetAsDictionary();
3461321369Sdim
3462321369Sdim      json_dict->GetValueForKeyAsInteger<uint64_t>("metabuffersize",
3463321369Sdim                                                   metabuffersize);
3464321369Sdim      options.setMetaDataBufferSize(metabuffersize);
3465321369Sdim
3466321369Sdim      json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", buffersize);
3467321369Sdim      options.setTraceBufferSize(buffersize);
3468321369Sdim
3469321369Sdim      json_dict->GetValueForKeyAsInteger<uint64_t>("type", type);
3470321369Sdim      options.setType(static_cast<lldb::TraceType>(type));
3471321369Sdim
3472321369Sdim      StructuredData::ObjectSP custom_params_sp =
3473321369Sdim          json_dict->GetValueForKey("params");
3474321369Sdim      if (custom_params_sp) {
3475321369Sdim        if (custom_params_sp->GetType() !=
3476321369Sdim            lldb::eStructuredDataTypeDictionary) {
3477321369Sdim          error.SetErrorString("Invalid Configuration obtained");
3478321369Sdim          return error;
3479321369Sdim        } else
3480321369Sdim          options.setTraceParams(
3481321369Sdim              static_pointer_cast<StructuredData::Dictionary>(
3482321369Sdim                  custom_params_sp));
3483321369Sdim      }
3484321369Sdim    } else {
3485321369Sdim      error = response.GetStatus();
3486321369Sdim    }
3487321369Sdim  } else {
3488321369Sdim    LLDB_LOG(log, "failed to send packet");
3489321369Sdim    error.SetErrorStringWithFormat("failed to send packet: '%s'",
3490321369Sdim                                   escaped_packet.GetData());
3491321369Sdim  }
3492321369Sdim  return error;
3493321369Sdim}
3494321369Sdim
3495321369SdimStatus GDBRemoteCommunicationClient::SendGetTraceDataPacket(
3496321369Sdim    StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id,
3497321369Sdim    llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
3498321369Sdim  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3499321369Sdim  Status error;
3500321369Sdim
3501321369Sdim  StructuredData::Dictionary json_packet;
3502321369Sdim
3503321369Sdim  json_packet.AddIntegerItem("traceid", uid);
3504321369Sdim  json_packet.AddIntegerItem("offset", offset);
3505321369Sdim  json_packet.AddIntegerItem("buffersize", buffer.size());
3506321369Sdim
3507321369Sdim  if (thread_id != LLDB_INVALID_THREAD_ID)
3508321369Sdim    json_packet.AddIntegerItem("threadid", thread_id);
3509321369Sdim
3510321369Sdim  StreamString json_string;
3511321369Sdim  json_packet.Dump(json_string, false);
3512321369Sdim
3513321369Sdim  packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
3514321369Sdim  StringExtractorGDBRemote response;
3515321369Sdim  if (SendPacketAndWaitForResponse(packet.GetString(), response, true) ==
3516321369Sdim      GDBRemoteCommunication::PacketResult::Success) {
3517321369Sdim    if (response.IsNormalResponse()) {
3518321369Sdim      size_t filled_size = response.GetHexBytesAvail(buffer);
3519321369Sdim      buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size);
3520321369Sdim    } else {
3521321369Sdim      error = response.GetStatus();
3522321369Sdim      buffer = buffer.slice(buffer.size());
3523321369Sdim    }
3524321369Sdim  } else {
3525321369Sdim    LLDB_LOG(log, "failed to send packet");
3526321369Sdim    error.SetErrorStringWithFormat("failed to send packet: '%s'",
3527321369Sdim                                   packet.GetData());
3528321369Sdim    buffer = buffer.slice(buffer.size());
3529321369Sdim  }
3530321369Sdim  return error;
3531321369Sdim}
3532321369Sdim
3533314564Sdimbool GDBRemoteCommunicationClient::GetModuleInfo(
3534314564Sdim    const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec,
3535314564Sdim    ModuleSpec &module_spec) {
3536314564Sdim  if (!m_supports_qModuleInfo)
3537314564Sdim    return false;
3538296417Sdim
3539314564Sdim  std::string module_path = module_file_spec.GetPath(false);
3540314564Sdim  if (module_path.empty())
3541314564Sdim    return false;
3542288943Sdim
3543314564Sdim  StreamString packet;
3544314564Sdim  packet.PutCString("qModuleInfo:");
3545353358Sdim  packet.PutStringAsRawHex8(module_path);
3546314564Sdim  packet.PutCString(";");
3547314564Sdim  const auto &triple = arch_spec.GetTriple().getTriple();
3548353358Sdim  packet.PutStringAsRawHex8(triple);
3549288943Sdim
3550314564Sdim  StringExtractorGDBRemote response;
3551314564Sdim  if (SendPacketAndWaitForResponse(packet.GetString(), response, false) !=
3552314564Sdim      PacketResult::Success)
3553314564Sdim    return false;
3554288943Sdim
3555314564Sdim  if (response.IsErrorResponse())
3556314564Sdim    return false;
3557288943Sdim
3558314564Sdim  if (response.IsUnsupportedResponse()) {
3559314564Sdim    m_supports_qModuleInfo = false;
3560314564Sdim    return false;
3561314564Sdim  }
3562296417Sdim
3563314564Sdim  llvm::StringRef name;
3564314564Sdim  llvm::StringRef value;
3565288943Sdim
3566314564Sdim  module_spec.Clear();
3567314564Sdim  module_spec.GetFileSpec() = module_file_spec;
3568288943Sdim
3569314564Sdim  while (response.GetNameColonValue(name, value)) {
3570314564Sdim    if (name == "uuid" || name == "md5") {
3571314564Sdim      StringExtractor extractor(value);
3572314564Sdim      std::string uuid;
3573314564Sdim      extractor.GetHexByteString(uuid);
3574341825Sdim      module_spec.GetUUID().SetFromStringRef(uuid, uuid.size() / 2);
3575314564Sdim    } else if (name == "triple") {
3576314564Sdim      StringExtractor extractor(value);
3577314564Sdim      std::string triple;
3578314564Sdim      extractor.GetHexByteString(triple);
3579314564Sdim      module_spec.GetArchitecture().SetTriple(triple.c_str());
3580314564Sdim    } else if (name == "file_offset") {
3581314564Sdim      uint64_t ival = 0;
3582314564Sdim      if (!value.getAsInteger(16, ival))
3583314564Sdim        module_spec.SetObjectOffset(ival);
3584314564Sdim    } else if (name == "file_size") {
3585314564Sdim      uint64_t ival = 0;
3586314564Sdim      if (!value.getAsInteger(16, ival))
3587314564Sdim        module_spec.SetObjectSize(ival);
3588314564Sdim    } else if (name == "file_path") {
3589314564Sdim      StringExtractor extractor(value);
3590314564Sdim      std::string path;
3591314564Sdim      extractor.GetHexByteString(path);
3592344779Sdim      module_spec.GetFileSpec() = FileSpec(path, arch_spec.GetTriple());
3593288943Sdim    }
3594314564Sdim  }
3595288943Sdim
3596314564Sdim  return true;
3597288943Sdim}
3598288943Sdim
3599314564Sdimstatic llvm::Optional<ModuleSpec>
3600314564SdimParseModuleSpec(StructuredData::Dictionary *dict) {
3601314564Sdim  ModuleSpec result;
3602314564Sdim  if (!dict)
3603314564Sdim    return llvm::None;
3604314564Sdim
3605321369Sdim  llvm::StringRef string;
3606314564Sdim  uint64_t integer;
3607314564Sdim
3608314564Sdim  if (!dict->GetValueForKeyAsString("uuid", string))
3609314564Sdim    return llvm::None;
3610327952Sdim  if (result.GetUUID().SetFromStringRef(string, string.size() / 2) !=
3611327952Sdim      string.size())
3612327952Sdim    return llvm::None;
3613314564Sdim
3614314564Sdim  if (!dict->GetValueForKeyAsInteger("file_offset", integer))
3615314564Sdim    return llvm::None;
3616314564Sdim  result.SetObjectOffset(integer);
3617314564Sdim
3618314564Sdim  if (!dict->GetValueForKeyAsInteger("file_size", integer))
3619314564Sdim    return llvm::None;
3620314564Sdim  result.SetObjectSize(integer);
3621314564Sdim
3622314564Sdim  if (!dict->GetValueForKeyAsString("triple", string))
3623314564Sdim    return llvm::None;
3624321369Sdim  result.GetArchitecture().SetTriple(string);
3625314564Sdim
3626314564Sdim  if (!dict->GetValueForKeyAsString("file_path", string))
3627314564Sdim    return llvm::None;
3628344779Sdim  result.GetFileSpec() = FileSpec(string, result.GetArchitecture().GetTriple());
3629314564Sdim
3630314564Sdim  return result;
3631314564Sdim}
3632314564Sdim
3633314564Sdimllvm::Optional<std::vector<ModuleSpec>>
3634314564SdimGDBRemoteCommunicationClient::GetModulesInfo(
3635314564Sdim    llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) {
3636360784Sdim  namespace json = llvm::json;
3637360784Sdim
3638314564Sdim  if (!m_supports_jModulesInfo)
3639314564Sdim    return llvm::None;
3640314564Sdim
3641360784Sdim  json::Array module_array;
3642314564Sdim  for (const FileSpec &module_file_spec : module_file_specs) {
3643360784Sdim    module_array.push_back(
3644360784Sdim        json::Object{{"file", module_file_spec.GetPath(false)},
3645360784Sdim                     {"triple", triple.getTriple()}});
3646314564Sdim  }
3647314564Sdim  StreamString unescaped_payload;
3648314564Sdim  unescaped_payload.PutCString("jModulesInfo:");
3649360784Sdim  unescaped_payload.AsRawOstream() << std::move(module_array);
3650360784Sdim
3651314564Sdim  StreamGDBRemote payload;
3652314564Sdim  payload.PutEscapedBytes(unescaped_payload.GetString().data(),
3653314564Sdim                          unescaped_payload.GetSize());
3654314564Sdim
3655321369Sdim  // Increase the timeout for jModulesInfo since this packet can take longer.
3656321369Sdim  ScopedTimeout timeout(*this, std::chrono::seconds(10));
3657321369Sdim
3658314564Sdim  StringExtractorGDBRemote response;
3659314564Sdim  if (SendPacketAndWaitForResponse(payload.GetString(), response, false) !=
3660314564Sdim          PacketResult::Success ||
3661314564Sdim      response.IsErrorResponse())
3662314564Sdim    return llvm::None;
3663314564Sdim
3664314564Sdim  if (response.IsUnsupportedResponse()) {
3665314564Sdim    m_supports_jModulesInfo = false;
3666314564Sdim    return llvm::None;
3667314564Sdim  }
3668314564Sdim
3669314564Sdim  StructuredData::ObjectSP response_object_sp =
3670314564Sdim      StructuredData::ParseJSON(response.GetStringRef());
3671314564Sdim  if (!response_object_sp)
3672314564Sdim    return llvm::None;
3673314564Sdim
3674314564Sdim  StructuredData::Array *response_array = response_object_sp->GetAsArray();
3675314564Sdim  if (!response_array)
3676314564Sdim    return llvm::None;
3677314564Sdim
3678314564Sdim  std::vector<ModuleSpec> result;
3679314564Sdim  for (size_t i = 0; i < response_array->GetSize(); ++i) {
3680314564Sdim    if (llvm::Optional<ModuleSpec> module_spec = ParseModuleSpec(
3681314564Sdim            response_array->GetItemAtIndex(i)->GetAsDictionary()))
3682314564Sdim      result.push_back(*module_spec);
3683314564Sdim  }
3684314564Sdim
3685314564Sdim  return result;
3686314564Sdim}
3687314564Sdim
3688288943Sdim// query the target remote for extended information using the qXfer packet
3689288943Sdim//
3690341825Sdim// example: object='features', annex='target.xml', out=<xml output> return:
3691341825Sdim// 'true'  on success
3692288943Sdim//          'false' on failure (err set)
3693314564Sdimbool GDBRemoteCommunicationClient::ReadExtFeature(
3694314564Sdim    const lldb_private::ConstString object,
3695314564Sdim    const lldb_private::ConstString annex, std::string &out,
3696321369Sdim    lldb_private::Status &err) {
3697288943Sdim
3698314564Sdim  std::stringstream output;
3699314564Sdim  StringExtractorGDBRemote chunk;
3700288943Sdim
3701314564Sdim  uint64_t size = GetRemoteMaxPacketSize();
3702314564Sdim  if (size == 0)
3703314564Sdim    size = 0x1000;
3704314564Sdim  size = size - 1; // Leave space for the 'm' or 'l' character in the response
3705314564Sdim  int offset = 0;
3706314564Sdim  bool active = true;
3707288943Sdim
3708314564Sdim  // loop until all data has been read
3709314564Sdim  while (active) {
3710288943Sdim
3711314564Sdim    // send query extended feature packet
3712314564Sdim    std::stringstream packet;
3713314564Sdim    packet << "qXfer:" << object.AsCString("")
3714314564Sdim           << ":read:" << annex.AsCString("") << ":" << std::hex << offset
3715314564Sdim           << "," << std::hex << size;
3716288943Sdim
3717314564Sdim    GDBRemoteCommunication::PacketResult res =
3718314564Sdim        SendPacketAndWaitForResponse(packet.str(), chunk, false);
3719288943Sdim
3720314564Sdim    if (res != GDBRemoteCommunication::PacketResult::Success) {
3721314564Sdim      err.SetErrorString("Error sending $qXfer packet");
3722314564Sdim      return false;
3723314564Sdim    }
3724288943Sdim
3725314564Sdim    const std::string &str = chunk.GetStringRef();
3726314564Sdim    if (str.length() == 0) {
3727314564Sdim      // should have some data in chunk
3728314564Sdim      err.SetErrorString("Empty response from $qXfer packet");
3729314564Sdim      return false;
3730314564Sdim    }
3731288943Sdim
3732314564Sdim    // check packet code
3733314564Sdim    switch (str[0]) {
3734314564Sdim    // last chunk
3735314564Sdim    case ('l'):
3736314564Sdim      active = false;
3737314564Sdim      LLVM_FALLTHROUGH;
3738288943Sdim
3739314564Sdim    // more chunks
3740314564Sdim    case ('m'):
3741314564Sdim      if (str.length() > 1)
3742314564Sdim        output << &str[1];
3743360784Sdim      offset += str.length() - 1;
3744314564Sdim      break;
3745288943Sdim
3746314564Sdim    // unknown chunk
3747314564Sdim    default:
3748314564Sdim      err.SetErrorString("Invalid continuation code from $qXfer packet");
3749314564Sdim      return false;
3750288943Sdim    }
3751314564Sdim  }
3752288943Sdim
3753314564Sdim  out = output.str();
3754314564Sdim  err.Success();
3755314564Sdim  return true;
3756288943Sdim}
3757288943Sdim
3758288943Sdim// Notify the target that gdb is prepared to serve symbol lookup requests.
3759288943Sdim//  packet: "qSymbol::"
3760288943Sdim//  reply:
3761288943Sdim//  OK                  The target does not need to look up any (more) symbols.
3762314564Sdim//  qSymbol:<sym_name>  The target requests the value of symbol sym_name (hex
3763314564Sdim//  encoded).
3764314564Sdim//                      LLDB may provide the value by sending another qSymbol
3765314564Sdim//                      packet
3766288943Sdim//                      in the form of"qSymbol:<sym_value>:<sym_name>".
3767296417Sdim//
3768296417Sdim//  Three examples:
3769296417Sdim//
3770296417Sdim//  lldb sends:    qSymbol::
3771296417Sdim//  lldb receives: OK
3772314564Sdim//     Remote gdb stub does not need to know the addresses of any symbols, lldb
3773314564Sdim//     does not
3774296417Sdim//     need to ask again in this session.
3775296417Sdim//
3776296417Sdim//  lldb sends:    qSymbol::
3777296417Sdim//  lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
3778296417Sdim//  lldb sends:    qSymbol::64697370617463685f71756575655f6f666673657473
3779296417Sdim//  lldb receives: OK
3780314564Sdim//     Remote gdb stub asks for address of 'dispatch_queue_offsets'.  lldb does
3781314564Sdim//     not know
3782314564Sdim//     the address at this time.  lldb needs to send qSymbol:: again when it has
3783314564Sdim//     more
3784296417Sdim//     solibs loaded.
3785296417Sdim//
3786296417Sdim//  lldb sends:    qSymbol::
3787296417Sdim//  lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
3788296417Sdim//  lldb sends:    qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473
3789296417Sdim//  lldb receives: OK
3790314564Sdim//     Remote gdb stub asks for address of 'dispatch_queue_offsets'.  lldb says
3791314564Sdim//     that it
3792314564Sdim//     is at address 0x2bc97554.  Remote gdb stub sends 'OK' indicating that it
3793314564Sdim//     does not
3794296417Sdim//     need any more symbols.  lldb does not need to ask again in this session.
3795288943Sdim
3796314564Sdimvoid GDBRemoteCommunicationClient::ServeSymbolLookups(
3797314564Sdim    lldb_private::Process *process) {
3798341825Sdim  // Set to true once we've resolved a symbol to an address for the remote
3799341825Sdim  // stub. If we get an 'OK' response after this, the remote stub doesn't need
3800341825Sdim  // any more symbols and we can stop asking.
3801314564Sdim  bool symbol_response_provided = false;
3802296417Sdim
3803314564Sdim  // Is this the initial qSymbol:: packet?
3804314564Sdim  bool first_qsymbol_query = true;
3805296417Sdim
3806344779Sdim  if (m_supports_qSymbol && !m_qSymbol_requests_done) {
3807314564Sdim    Lock lock(*this, false);
3808314564Sdim    if (lock) {
3809314564Sdim      StreamString packet;
3810314564Sdim      packet.PutCString("qSymbol::");
3811314564Sdim      StringExtractorGDBRemote response;
3812314564Sdim      while (SendPacketAndWaitForResponseNoLock(packet.GetString(), response) ==
3813314564Sdim             PacketResult::Success) {
3814314564Sdim        if (response.IsOKResponse()) {
3815314564Sdim          if (symbol_response_provided || first_qsymbol_query) {
3816314564Sdim            m_qSymbol_requests_done = true;
3817314564Sdim          }
3818288943Sdim
3819314564Sdim          // We are done serving symbols requests
3820314564Sdim          return;
3821314564Sdim        }
3822314564Sdim        first_qsymbol_query = false;
3823296417Sdim
3824314564Sdim        if (response.IsUnsupportedResponse()) {
3825341825Sdim          // qSymbol is not supported by the current GDB server we are
3826341825Sdim          // connected to
3827314564Sdim          m_supports_qSymbol = false;
3828314564Sdim          return;
3829314564Sdim        } else {
3830314564Sdim          llvm::StringRef response_str(response.GetStringRef());
3831314564Sdim          if (response_str.startswith("qSymbol:")) {
3832314564Sdim            response.SetFilePos(strlen("qSymbol:"));
3833314564Sdim            std::string symbol_name;
3834314564Sdim            if (response.GetHexByteString(symbol_name)) {
3835314564Sdim              if (symbol_name.empty())
3836314564Sdim                return;
3837296417Sdim
3838314564Sdim              addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
3839314564Sdim              lldb_private::SymbolContextList sc_list;
3840360784Sdim              process->GetTarget().GetImages().FindSymbolsWithNameAndType(
3841360784Sdim                  ConstString(symbol_name), eSymbolTypeAny, sc_list);
3842360784Sdim              if (!sc_list.IsEmpty()) {
3843314564Sdim                const size_t num_scs = sc_list.GetSize();
3844314564Sdim                for (size_t sc_idx = 0;
3845314564Sdim                     sc_idx < num_scs &&
3846314564Sdim                     symbol_load_addr == LLDB_INVALID_ADDRESS;
3847314564Sdim                     ++sc_idx) {
3848314564Sdim                  SymbolContext sc;
3849314564Sdim                  if (sc_list.GetContextAtIndex(sc_idx, sc)) {
3850314564Sdim                    if (sc.symbol) {
3851314564Sdim                      switch (sc.symbol->GetType()) {
3852314564Sdim                      case eSymbolTypeInvalid:
3853314564Sdim                      case eSymbolTypeAbsolute:
3854314564Sdim                      case eSymbolTypeUndefined:
3855314564Sdim                      case eSymbolTypeSourceFile:
3856314564Sdim                      case eSymbolTypeHeaderFile:
3857314564Sdim                      case eSymbolTypeObjectFile:
3858314564Sdim                      case eSymbolTypeCommonBlock:
3859314564Sdim                      case eSymbolTypeBlock:
3860314564Sdim                      case eSymbolTypeLocal:
3861314564Sdim                      case eSymbolTypeParam:
3862314564Sdim                      case eSymbolTypeVariable:
3863314564Sdim                      case eSymbolTypeVariableType:
3864314564Sdim                      case eSymbolTypeLineEntry:
3865314564Sdim                      case eSymbolTypeLineHeader:
3866314564Sdim                      case eSymbolTypeScopeBegin:
3867314564Sdim                      case eSymbolTypeScopeEnd:
3868314564Sdim                      case eSymbolTypeAdditional:
3869314564Sdim                      case eSymbolTypeCompiler:
3870314564Sdim                      case eSymbolTypeInstrumentation:
3871314564Sdim                      case eSymbolTypeTrampoline:
3872314564Sdim                        break;
3873288943Sdim
3874314564Sdim                      case eSymbolTypeCode:
3875314564Sdim                      case eSymbolTypeResolver:
3876314564Sdim                      case eSymbolTypeData:
3877314564Sdim                      case eSymbolTypeRuntime:
3878314564Sdim                      case eSymbolTypeException:
3879314564Sdim                      case eSymbolTypeObjCClass:
3880314564Sdim                      case eSymbolTypeObjCMetaClass:
3881314564Sdim                      case eSymbolTypeObjCIVar:
3882314564Sdim                      case eSymbolTypeReExported:
3883314564Sdim                        symbol_load_addr =
3884314564Sdim                            sc.symbol->GetLoadAddress(&process->GetTarget());
3885314564Sdim                        break;
3886314564Sdim                      }
3887288943Sdim                    }
3888314564Sdim                  }
3889288943Sdim                }
3890314564Sdim              }
3891314564Sdim              // This is the normal path where our symbol lookup was successful
3892341825Sdim              // and we want to send a packet with the new symbol value and see
3893341825Sdim              // if another lookup needs to be done.
3894314564Sdim
3895314564Sdim              // Change "packet" to contain the requested symbol value and name
3896314564Sdim              packet.Clear();
3897314564Sdim              packet.PutCString("qSymbol:");
3898314564Sdim              if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
3899314564Sdim                packet.Printf("%" PRIx64, symbol_load_addr);
3900314564Sdim                symbol_response_provided = true;
3901314564Sdim              } else {
3902314564Sdim                symbol_response_provided = false;
3903314564Sdim              }
3904314564Sdim              packet.PutCString(":");
3905314564Sdim              packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
3906314564Sdim              continue; // go back to the while loop and send "packet" and wait
3907314564Sdim                        // for another response
3908288943Sdim            }
3909314564Sdim          }
3910314564Sdim        }
3911314564Sdim      }
3912314564Sdim      // If we make it here, the symbol request packet response wasn't valid or
3913314564Sdim      // our symbol lookup failed so we must abort
3914314564Sdim      return;
3915288943Sdim
3916314564Sdim    } else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
3917314564Sdim                   GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) {
3918360784Sdim      LLDB_LOGF(log,
3919360784Sdim                "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.",
3920360784Sdim                __FUNCTION__);
3921288943Sdim    }
3922314564Sdim  }
3923288943Sdim}
3924288943Sdim
3925314564SdimStructuredData::Array *
3926314564SdimGDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
3927314564Sdim  if (!m_supported_async_json_packets_is_valid) {
3928341825Sdim    // Query the server for the array of supported asynchronous JSON packets.
3929314564Sdim    m_supported_async_json_packets_is_valid = true;
3930314564Sdim
3931314564Sdim    Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
3932314564Sdim
3933314564Sdim    // Poll it now.
3934314564Sdim    StringExtractorGDBRemote response;
3935314564Sdim    const bool send_async = false;
3936314564Sdim    if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response,
3937314564Sdim                                     send_async) == PacketResult::Success) {
3938314564Sdim      m_supported_async_json_packets_sp =
3939314564Sdim          StructuredData::ParseJSON(response.GetStringRef());
3940314564Sdim      if (m_supported_async_json_packets_sp &&
3941314564Sdim          !m_supported_async_json_packets_sp->GetAsArray()) {
3942341825Sdim        // We were returned something other than a JSON array.  This is
3943341825Sdim        // invalid.  Clear it out.
3944360784Sdim        LLDB_LOGF(log,
3945360784Sdim                  "GDBRemoteCommunicationClient::%s(): "
3946360784Sdim                  "QSupportedAsyncJSONPackets returned invalid "
3947360784Sdim                  "result: %s",
3948360784Sdim                  __FUNCTION__, response.GetStringRef().data());
3949314564Sdim        m_supported_async_json_packets_sp.reset();
3950314564Sdim      }
3951314564Sdim    } else {
3952360784Sdim      LLDB_LOGF(log,
3953360784Sdim                "GDBRemoteCommunicationClient::%s(): "
3954360784Sdim                "QSupportedAsyncJSONPackets unsupported",
3955360784Sdim                __FUNCTION__);
3956314564Sdim    }
3957314564Sdim
3958314564Sdim    if (log && m_supported_async_json_packets_sp) {
3959314564Sdim      StreamString stream;
3960314564Sdim      m_supported_async_json_packets_sp->Dump(stream);
3961360784Sdim      LLDB_LOGF(log,
3962360784Sdim                "GDBRemoteCommunicationClient::%s(): supported async "
3963360784Sdim                "JSON packets: %s",
3964360784Sdim                __FUNCTION__, stream.GetData());
3965314564Sdim    }
3966314564Sdim  }
3967314564Sdim
3968314564Sdim  return m_supported_async_json_packets_sp
3969314564Sdim             ? m_supported_async_json_packets_sp->GetAsArray()
3970314564Sdim             : nullptr;
3971314564Sdim}
3972314564Sdim
3973321369SdimStatus GDBRemoteCommunicationClient::SendSignalsToIgnore(
3974321369Sdim    llvm::ArrayRef<int32_t> signals) {
3975321369Sdim  // Format packet:
3976321369Sdim  // QPassSignals:<hex_sig1>;<hex_sig2>...;<hex_sigN>
3977321369Sdim  auto range = llvm::make_range(signals.begin(), signals.end());
3978321369Sdim  std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str();
3979321369Sdim
3980321369Sdim  StringExtractorGDBRemote response;
3981321369Sdim  auto send_status = SendPacketAndWaitForResponse(packet, response, false);
3982321369Sdim
3983321369Sdim  if (send_status != GDBRemoteCommunication::PacketResult::Success)
3984321369Sdim    return Status("Sending QPassSignals packet failed");
3985321369Sdim
3986321369Sdim  if (response.IsOKResponse()) {
3987321369Sdim    return Status();
3988321369Sdim  } else {
3989321369Sdim    return Status("Unknown error happened during sending QPassSignals packet.");
3990321369Sdim  }
3991321369Sdim}
3992321369Sdim
3993321369SdimStatus GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
3994353358Sdim    ConstString type_name, const StructuredData::ObjectSP &config_sp) {
3995321369Sdim  Status error;
3996314564Sdim
3997314564Sdim  if (type_name.GetLength() == 0) {
3998314564Sdim    error.SetErrorString("invalid type_name argument");
3999314564Sdim    return error;
4000314564Sdim  }
4001314564Sdim
4002341825Sdim  // Build command: Configure{type_name}: serialized config data.
4003314564Sdim  StreamGDBRemote stream;
4004314564Sdim  stream.PutCString("QConfigure");
4005314564Sdim  stream.PutCString(type_name.AsCString());
4006314564Sdim  stream.PutChar(':');
4007314564Sdim  if (config_sp) {
4008314564Sdim    // Gather the plain-text version of the configuration data.
4009314564Sdim    StreamString unescaped_stream;
4010314564Sdim    config_sp->Dump(unescaped_stream);
4011314564Sdim    unescaped_stream.Flush();
4012314564Sdim
4013314564Sdim    // Add it to the stream in escaped fashion.
4014314564Sdim    stream.PutEscapedBytes(unescaped_stream.GetString().data(),
4015314564Sdim                           unescaped_stream.GetSize());
4016314564Sdim  }
4017314564Sdim  stream.Flush();
4018314564Sdim
4019314564Sdim  // Send the packet.
4020314564Sdim  const bool send_async = false;
4021314564Sdim  StringExtractorGDBRemote response;
4022314564Sdim  auto result =
4023314564Sdim      SendPacketAndWaitForResponse(stream.GetString(), response, send_async);
4024314564Sdim  if (result == PacketResult::Success) {
4025314564Sdim    // We failed if the config result comes back other than OK.
4026360784Sdim    if (strcmp(response.GetStringRef().data(), "OK") == 0) {
4027314564Sdim      // Okay!
4028314564Sdim      error.Clear();
4029314564Sdim    } else {
4030314564Sdim      error.SetErrorStringWithFormat("configuring StructuredData feature "
4031314564Sdim                                     "%s failed with error %s",
4032314564Sdim                                     type_name.AsCString(),
4033360784Sdim                                     response.GetStringRef().data());
4034314564Sdim    }
4035314564Sdim  } else {
4036314564Sdim    // Can we get more data here on the failure?
4037314564Sdim    error.SetErrorStringWithFormat("configuring StructuredData feature %s "
4038314564Sdim                                   "failed when sending packet: "
4039314564Sdim                                   "PacketResult=%d",
4040314564Sdim                                   type_name.AsCString(), (int)result);
4041314564Sdim  }
4042314564Sdim  return error;
4043314564Sdim}
4044314564Sdim
4045314564Sdimvoid GDBRemoteCommunicationClient::OnRunPacketSent(bool first) {
4046314564Sdim  GDBRemoteClientBase::OnRunPacketSent(first);
4047314564Sdim  m_curr_tid = LLDB_INVALID_THREAD_ID;
4048314564Sdim}
4049