15ffd83dbSDimitry Andric //===-- GDBRemoteCommunicationClient.cpp ----------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "GDBRemoteCommunicationClient.h"
100b57cec5SDimitry Andric 
11fe6060f1SDimitry Andric #include <cmath>
120b57cec5SDimitry Andric #include <sys/stat.h>
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include <numeric>
15bdd1243dSDimitry Andric #include <optional>
160b57cec5SDimitry Andric #include <sstream>
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h"
190b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h"
20*0fca6ea1SDimitry Andric #include "lldb/Host/SafeMachO.h"
210b57cec5SDimitry Andric #include "lldb/Host/XML.h"
220b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h"
230b57cec5SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h"
240b57cec5SDimitry Andric #include "lldb/Target/Target.h"
250b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h"
260b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
270b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
280b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
2981ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
300b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
310b57cec5SDimitry Andric #include "lldb/Utility/State.h"
320b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #include "ProcessGDBRemote.h"
350b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h"
360b57cec5SDimitry Andric #include "lldb/Host/Config.h"
370b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
380b57cec5SDimitry Andric 
3906c3fb27SDimitry Andric #include "llvm/ADT/STLExtras.h"
400b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
419dba64beSDimitry Andric #include "llvm/Support/JSON.h"
420b57cec5SDimitry Andric 
439dba64beSDimitry Andric #if defined(HAVE_LIBCOMPRESSION)
440b57cec5SDimitry Andric #include <compression.h>
450b57cec5SDimitry Andric #endif
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric using namespace lldb;
480b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote;
499dba64beSDimitry Andric using namespace lldb_private;
500b57cec5SDimitry Andric using namespace std::chrono;
510b57cec5SDimitry Andric 
525ffd83dbSDimitry Andric llvm::raw_ostream &process_gdb_remote::operator<<(llvm::raw_ostream &os,
535ffd83dbSDimitry Andric                                                   const QOffsets &offsets) {
545ffd83dbSDimitry Andric   return os << llvm::formatv(
555ffd83dbSDimitry Andric              "QOffsets({0}, [{1:@[x]}])", offsets.segments,
565ffd83dbSDimitry Andric              llvm::make_range(offsets.offsets.begin(), offsets.offsets.end()));
575ffd83dbSDimitry Andric }
585ffd83dbSDimitry Andric 
590b57cec5SDimitry Andric // GDBRemoteCommunicationClient constructor
600b57cec5SDimitry Andric GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
61bdd1243dSDimitry Andric     : GDBRemoteClientBase("gdb-remote.client"),
62fe6060f1SDimitry Andric 
630b57cec5SDimitry Andric       m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
640b57cec5SDimitry Andric       m_supports_qUserName(true), m_supports_qGroupName(true),
650b57cec5SDimitry Andric       m_supports_qThreadStopInfo(true), m_supports_z0(true),
660b57cec5SDimitry Andric       m_supports_z1(true), m_supports_z2(true), m_supports_z3(true),
670b57cec5SDimitry Andric       m_supports_z4(true), m_supports_QEnvironment(true),
680b57cec5SDimitry Andric       m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true),
690b57cec5SDimitry Andric       m_qSymbol_requests_done(false), m_supports_qModuleInfo(true),
700b57cec5SDimitry Andric       m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true),
71349cc55cSDimitry Andric       m_supports_vFileSize(true), m_supports_vFileMode(true),
72349cc55cSDimitry Andric       m_supports_vFileExists(true), m_supports_vRun(true),
73fe6060f1SDimitry Andric 
7406c3fb27SDimitry Andric       m_host_arch(), m_host_distribution_id(), m_process_arch(), m_os_build(),
7506c3fb27SDimitry Andric       m_os_kernel(), m_hostname(), m_gdb_server_name(),
7606c3fb27SDimitry Andric       m_default_packet_timeout(0), m_qSupported_response(),
7706c3fb27SDimitry Andric       m_supported_async_json_packets_sp(), m_qXfer_memory_map() {}
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric // Destructor
800b57cec5SDimitry Andric GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
810b57cec5SDimitry Andric   if (IsConnected())
820b57cec5SDimitry Andric     Disconnect();
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
860b57cec5SDimitry Andric   ResetDiscoverableSettings(false);
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   // Start the read thread after we send the handshake ack since if we fail to
890b57cec5SDimitry Andric   // send the handshake ack, there is no reason to continue...
90349cc55cSDimitry Andric   std::chrono::steady_clock::time_point start_of_handshake =
91349cc55cSDimitry Andric       std::chrono::steady_clock::now();
920b57cec5SDimitry Andric   if (SendAck()) {
930b57cec5SDimitry Andric     // The return value from QueryNoAckModeSupported() is true if the packet
940b57cec5SDimitry Andric     // was sent and _any_ response (including UNIMPLEMENTED) was received), or
950b57cec5SDimitry Andric     // false if no response was received. This quickly tells us if we have a
960b57cec5SDimitry Andric     // live connection to a remote GDB server...
970b57cec5SDimitry Andric     if (QueryNoAckModeSupported()) {
980b57cec5SDimitry Andric       return true;
990b57cec5SDimitry Andric     } else {
100349cc55cSDimitry Andric       std::chrono::steady_clock::time_point end_of_handshake =
101349cc55cSDimitry Andric           std::chrono::steady_clock::now();
102349cc55cSDimitry Andric       auto handshake_timeout =
103349cc55cSDimitry Andric           std::chrono::duration<double>(end_of_handshake - start_of_handshake)
104349cc55cSDimitry Andric               .count();
105349cc55cSDimitry Andric       if (error_ptr) {
1064824e7fdSDimitry Andric         if (!IsConnected())
107349cc55cSDimitry Andric           error_ptr->SetErrorString("Connection shut down by remote side "
108349cc55cSDimitry Andric                                     "while waiting for reply to initial "
109349cc55cSDimitry Andric                                     "handshake packet");
1104824e7fdSDimitry Andric         else
111349cc55cSDimitry Andric           error_ptr->SetErrorStringWithFormat(
112349cc55cSDimitry Andric               "failed to get reply to handshake packet within timeout of "
113349cc55cSDimitry Andric               "%.1f seconds",
114349cc55cSDimitry Andric               handshake_timeout);
1150b57cec5SDimitry Andric       }
116349cc55cSDimitry Andric     }
1170b57cec5SDimitry Andric   } else {
1180b57cec5SDimitry Andric     if (error_ptr)
1190b57cec5SDimitry Andric       error_ptr->SetErrorString("failed to send the handshake ack");
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric   return false;
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetEchoSupported() {
1250b57cec5SDimitry Andric   if (m_supports_qEcho == eLazyBoolCalculate) {
1260b57cec5SDimitry Andric     GetRemoteQSupported();
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric   return m_supports_qEcho == eLazyBoolYes;
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetQPassSignalsSupported() {
1320b57cec5SDimitry Andric   if (m_supports_QPassSignals == eLazyBoolCalculate) {
1330b57cec5SDimitry Andric     GetRemoteQSupported();
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric   return m_supports_QPassSignals == eLazyBoolYes;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() {
1390b57cec5SDimitry Andric   if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) {
1400b57cec5SDimitry Andric     GetRemoteQSupported();
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric   return m_supports_augmented_libraries_svr4_read == eLazyBoolYes;
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported() {
1460b57cec5SDimitry Andric   if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) {
1470b57cec5SDimitry Andric     GetRemoteQSupported();
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric   return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes;
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported() {
1530b57cec5SDimitry Andric   if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) {
1540b57cec5SDimitry Andric     GetRemoteQSupported();
1550b57cec5SDimitry Andric   }
1560b57cec5SDimitry Andric   return m_supports_qXfer_libraries_read == eLazyBoolYes;
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetQXferAuxvReadSupported() {
1600b57cec5SDimitry Andric   if (m_supports_qXfer_auxv_read == eLazyBoolCalculate) {
1610b57cec5SDimitry Andric     GetRemoteQSupported();
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric   return m_supports_qXfer_auxv_read == eLazyBoolYes;
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() {
1670b57cec5SDimitry Andric   if (m_supports_qXfer_features_read == eLazyBoolCalculate) {
1680b57cec5SDimitry Andric     GetRemoteQSupported();
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric   return m_supports_qXfer_features_read == eLazyBoolYes;
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
1740b57cec5SDimitry Andric   if (m_supports_qXfer_memory_map_read == eLazyBoolCalculate) {
1750b57cec5SDimitry Andric     GetRemoteQSupported();
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric   return m_supports_qXfer_memory_map_read == eLazyBoolYes;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
18004eeddc0SDimitry Andric bool GDBRemoteCommunicationClient::GetQXferSigInfoReadSupported() {
18104eeddc0SDimitry Andric   if (m_supports_qXfer_siginfo_read == eLazyBoolCalculate) {
18204eeddc0SDimitry Andric     GetRemoteQSupported();
18304eeddc0SDimitry Andric   }
18404eeddc0SDimitry Andric   return m_supports_qXfer_siginfo_read == eLazyBoolYes;
18504eeddc0SDimitry Andric }
18604eeddc0SDimitry Andric 
187bdd1243dSDimitry Andric bool GDBRemoteCommunicationClient::GetMultiprocessSupported() {
188bdd1243dSDimitry Andric   if (m_supports_memory_tagging == eLazyBoolCalculate)
189bdd1243dSDimitry Andric     GetRemoteQSupported();
190bdd1243dSDimitry Andric   return m_supports_multiprocess == eLazyBoolYes;
191bdd1243dSDimitry Andric }
192bdd1243dSDimitry Andric 
1930b57cec5SDimitry Andric uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
1940b57cec5SDimitry Andric   if (m_max_packet_size == 0) {
1950b57cec5SDimitry Andric     GetRemoteQSupported();
1960b57cec5SDimitry Andric   }
1970b57cec5SDimitry Andric   return m_max_packet_size;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
2010b57cec5SDimitry Andric   if (m_supports_not_sending_acks == eLazyBoolCalculate) {
2020b57cec5SDimitry Andric     m_send_acks = true;
2030b57cec5SDimitry Andric     m_supports_not_sending_acks = eLazyBoolNo;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric     // This is the first real packet that we'll send in a debug session and it
2060b57cec5SDimitry Andric     // may take a little longer than normal to receive a reply.  Wait at least
2070b57cec5SDimitry Andric     // 6 seconds for a reply to this packet.
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric     StringExtractorGDBRemote response;
212fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("QStartNoAckMode", response) ==
2130b57cec5SDimitry Andric         PacketResult::Success) {
2140b57cec5SDimitry Andric       if (response.IsOKResponse()) {
2150b57cec5SDimitry Andric         m_send_acks = false;
2160b57cec5SDimitry Andric         m_supports_not_sending_acks = eLazyBoolYes;
2170b57cec5SDimitry Andric       }
2180b57cec5SDimitry Andric       return true;
2190b57cec5SDimitry Andric     }
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric   return false;
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() {
2250b57cec5SDimitry Andric   if (m_supports_threads_in_stop_reply == eLazyBoolCalculate) {
2260b57cec5SDimitry Andric     m_supports_threads_in_stop_reply = eLazyBoolNo;
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric     StringExtractorGDBRemote response;
229fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response) ==
230fe6060f1SDimitry Andric         PacketResult::Success) {
2310b57cec5SDimitry Andric       if (response.IsOKResponse())
2320b57cec5SDimitry Andric         m_supports_threads_in_stop_reply = eLazyBoolYes;
2330b57cec5SDimitry Andric     }
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() {
2380b57cec5SDimitry Andric   if (m_attach_or_wait_reply == eLazyBoolCalculate) {
2390b57cec5SDimitry Andric     m_attach_or_wait_reply = eLazyBoolNo;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric     StringExtractorGDBRemote response;
242fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response) ==
243fe6060f1SDimitry Andric         PacketResult::Success) {
2440b57cec5SDimitry Andric       if (response.IsOKResponse())
2450b57cec5SDimitry Andric         m_attach_or_wait_reply = eLazyBoolYes;
2460b57cec5SDimitry Andric     }
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric   return m_attach_or_wait_reply == eLazyBoolYes;
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
2520b57cec5SDimitry Andric   if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) {
2530b57cec5SDimitry Andric     m_prepare_for_reg_writing_reply = eLazyBoolNo;
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric     StringExtractorGDBRemote response;
256fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response) ==
257fe6060f1SDimitry Andric         PacketResult::Success) {
2580b57cec5SDimitry Andric       if (response.IsOKResponse())
2590b57cec5SDimitry Andric         m_prepare_for_reg_writing_reply = eLazyBoolYes;
2600b57cec5SDimitry Andric     }
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric   return m_prepare_for_reg_writing_reply == eLazyBoolYes;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
2660b57cec5SDimitry Andric   if (!did_exec) {
2670b57cec5SDimitry Andric     // Hard reset everything, this is when we first connect to a GDB server
2680b57cec5SDimitry Andric     m_supports_not_sending_acks = eLazyBoolCalculate;
2690b57cec5SDimitry Andric     m_supports_thread_suffix = eLazyBoolCalculate;
2700b57cec5SDimitry Andric     m_supports_threads_in_stop_reply = eLazyBoolCalculate;
2710b57cec5SDimitry Andric     m_supports_vCont_c = eLazyBoolCalculate;
2720b57cec5SDimitry Andric     m_supports_vCont_C = eLazyBoolCalculate;
2730b57cec5SDimitry Andric     m_supports_vCont_s = eLazyBoolCalculate;
2740b57cec5SDimitry Andric     m_supports_vCont_S = eLazyBoolCalculate;
2750b57cec5SDimitry Andric     m_supports_p = eLazyBoolCalculate;
2760b57cec5SDimitry Andric     m_supports_x = eLazyBoolCalculate;
2770b57cec5SDimitry Andric     m_supports_QSaveRegisterState = eLazyBoolCalculate;
2780b57cec5SDimitry Andric     m_qHostInfo_is_valid = eLazyBoolCalculate;
2790b57cec5SDimitry Andric     m_curr_pid_is_valid = eLazyBoolCalculate;
2800b57cec5SDimitry Andric     m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
2810b57cec5SDimitry Andric     m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
2820b57cec5SDimitry Andric     m_supports_memory_region_info = eLazyBoolCalculate;
2830b57cec5SDimitry Andric     m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
2840b57cec5SDimitry Andric     m_attach_or_wait_reply = eLazyBoolCalculate;
2850b57cec5SDimitry Andric     m_avoid_g_packets = eLazyBoolCalculate;
286fe6060f1SDimitry Andric     m_supports_multiprocess = eLazyBoolCalculate;
287349cc55cSDimitry Andric     m_supports_qSaveCore = eLazyBoolCalculate;
2880b57cec5SDimitry Andric     m_supports_qXfer_auxv_read = eLazyBoolCalculate;
2890b57cec5SDimitry Andric     m_supports_qXfer_libraries_read = eLazyBoolCalculate;
2900b57cec5SDimitry Andric     m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
2910b57cec5SDimitry Andric     m_supports_qXfer_features_read = eLazyBoolCalculate;
2920b57cec5SDimitry Andric     m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
29304eeddc0SDimitry Andric     m_supports_qXfer_siginfo_read = eLazyBoolCalculate;
2940b57cec5SDimitry Andric     m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
295349cc55cSDimitry Andric     m_uses_native_signals = eLazyBoolCalculate;
2960b57cec5SDimitry Andric     m_supports_qProcessInfoPID = true;
2970b57cec5SDimitry Andric     m_supports_qfProcessInfo = true;
2980b57cec5SDimitry Andric     m_supports_qUserName = true;
2990b57cec5SDimitry Andric     m_supports_qGroupName = true;
3000b57cec5SDimitry Andric     m_supports_qThreadStopInfo = true;
3010b57cec5SDimitry Andric     m_supports_z0 = true;
3020b57cec5SDimitry Andric     m_supports_z1 = true;
3030b57cec5SDimitry Andric     m_supports_z2 = true;
3040b57cec5SDimitry Andric     m_supports_z3 = true;
3050b57cec5SDimitry Andric     m_supports_z4 = true;
3060b57cec5SDimitry Andric     m_supports_QEnvironment = true;
3070b57cec5SDimitry Andric     m_supports_QEnvironmentHexEncoded = true;
3080b57cec5SDimitry Andric     m_supports_qSymbol = true;
3090b57cec5SDimitry Andric     m_qSymbol_requests_done = false;
3100b57cec5SDimitry Andric     m_supports_qModuleInfo = true;
3110b57cec5SDimitry Andric     m_host_arch.Clear();
31206c3fb27SDimitry Andric     m_host_distribution_id.clear();
3130b57cec5SDimitry Andric     m_os_version = llvm::VersionTuple();
3140b57cec5SDimitry Andric     m_os_build.clear();
3150b57cec5SDimitry Andric     m_os_kernel.clear();
3160b57cec5SDimitry Andric     m_hostname.clear();
3170b57cec5SDimitry Andric     m_gdb_server_name.clear();
3180b57cec5SDimitry Andric     m_gdb_server_version = UINT32_MAX;
3190b57cec5SDimitry Andric     m_default_packet_timeout = seconds(0);
320fe6060f1SDimitry Andric     m_target_vm_page_size = 0;
3210b57cec5SDimitry Andric     m_max_packet_size = 0;
3220b57cec5SDimitry Andric     m_qSupported_response.clear();
3230b57cec5SDimitry Andric     m_supported_async_json_packets_is_valid = false;
3240b57cec5SDimitry Andric     m_supported_async_json_packets_sp.reset();
3250b57cec5SDimitry Andric     m_supports_jModulesInfo = true;
3260b57cec5SDimitry Andric   }
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   // These flags should be reset when we first connect to a GDB server and when
3290b57cec5SDimitry Andric   // our inferior process execs
3300b57cec5SDimitry Andric   m_qProcessInfo_is_valid = eLazyBoolCalculate;
3310b57cec5SDimitry Andric   m_process_arch.Clear();
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric void GDBRemoteCommunicationClient::GetRemoteQSupported() {
3350b57cec5SDimitry Andric   // Clear out any capabilities we expect to see in the qSupported response
3360b57cec5SDimitry Andric   m_supports_qXfer_auxv_read = eLazyBoolNo;
3370b57cec5SDimitry Andric   m_supports_qXfer_libraries_read = eLazyBoolNo;
3380b57cec5SDimitry Andric   m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
3390b57cec5SDimitry Andric   m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
3400b57cec5SDimitry Andric   m_supports_qXfer_features_read = eLazyBoolNo;
3410b57cec5SDimitry Andric   m_supports_qXfer_memory_map_read = eLazyBoolNo;
34204eeddc0SDimitry Andric   m_supports_qXfer_siginfo_read = eLazyBoolNo;
343fe6060f1SDimitry Andric   m_supports_multiprocess = eLazyBoolNo;
344fe6060f1SDimitry Andric   m_supports_qEcho = eLazyBoolNo;
345fe6060f1SDimitry Andric   m_supports_QPassSignals = eLazyBoolNo;
346fe6060f1SDimitry Andric   m_supports_memory_tagging = eLazyBoolNo;
347349cc55cSDimitry Andric   m_supports_qSaveCore = eLazyBoolNo;
348349cc55cSDimitry Andric   m_uses_native_signals = eLazyBoolNo;
349fe6060f1SDimitry Andric 
3500b57cec5SDimitry Andric   m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
3510b57cec5SDimitry Andric                                   // not, we assume no limit
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   // build the qSupported packet
354fe6060f1SDimitry Andric   std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc",
355349cc55cSDimitry Andric                                        "multiprocess+", "fork-events+",
356349cc55cSDimitry Andric                                        "vfork-events+"};
3570b57cec5SDimitry Andric   StreamString packet;
3580b57cec5SDimitry Andric   packet.PutCString("qSupported");
3590b57cec5SDimitry Andric   for (uint32_t i = 0; i < features.size(); ++i) {
3600b57cec5SDimitry Andric     packet.PutCString(i == 0 ? ":" : ";");
3610b57cec5SDimitry Andric     packet.PutCString(features[i]);
3620b57cec5SDimitry Andric   }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   StringExtractorGDBRemote response;
365fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
3660b57cec5SDimitry Andric       PacketResult::Success) {
3670b57cec5SDimitry Andric     // Hang on to the qSupported packet, so that platforms can do custom
3680b57cec5SDimitry Andric     // configuration of the transport before attaching/launching the process.
369fe6060f1SDimitry Andric     m_qSupported_response = response.GetStringRef().str();
3700b57cec5SDimitry Andric 
371349cc55cSDimitry Andric     for (llvm::StringRef x : llvm::split(response.GetStringRef(), ';')) {
372fe6060f1SDimitry Andric       if (x == "qXfer:auxv:read+")
3730b57cec5SDimitry Andric         m_supports_qXfer_auxv_read = eLazyBoolYes;
374fe6060f1SDimitry Andric       else if (x == "qXfer:libraries-svr4:read+")
3750b57cec5SDimitry Andric         m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
376fe6060f1SDimitry Andric       else if (x == "augmented-libraries-svr4-read") {
3770b57cec5SDimitry Andric         m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
3780b57cec5SDimitry Andric         m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
379fe6060f1SDimitry Andric       } else if (x == "qXfer:libraries:read+")
3800b57cec5SDimitry Andric         m_supports_qXfer_libraries_read = eLazyBoolYes;
381fe6060f1SDimitry Andric       else if (x == "qXfer:features:read+")
3820b57cec5SDimitry Andric         m_supports_qXfer_features_read = eLazyBoolYes;
383fe6060f1SDimitry Andric       else if (x == "qXfer:memory-map:read+")
3840b57cec5SDimitry Andric         m_supports_qXfer_memory_map_read = eLazyBoolYes;
38504eeddc0SDimitry Andric       else if (x == "qXfer:siginfo:read+")
38604eeddc0SDimitry Andric         m_supports_qXfer_siginfo_read = eLazyBoolYes;
387fe6060f1SDimitry Andric       else if (x == "qEcho")
388fe6060f1SDimitry Andric         m_supports_qEcho = eLazyBoolYes;
389fe6060f1SDimitry Andric       else if (x == "QPassSignals+")
390fe6060f1SDimitry Andric         m_supports_QPassSignals = eLazyBoolYes;
391fe6060f1SDimitry Andric       else if (x == "multiprocess+")
392fe6060f1SDimitry Andric         m_supports_multiprocess = eLazyBoolYes;
393fe6060f1SDimitry Andric       else if (x == "memory-tagging+")
394fe6060f1SDimitry Andric         m_supports_memory_tagging = eLazyBoolYes;
395349cc55cSDimitry Andric       else if (x == "qSaveCore+")
396349cc55cSDimitry Andric         m_supports_qSaveCore = eLazyBoolYes;
397349cc55cSDimitry Andric       else if (x == "native-signals+")
398349cc55cSDimitry Andric         m_uses_native_signals = eLazyBoolYes;
3990b57cec5SDimitry Andric       // Look for a list of compressions in the features list e.g.
4000b57cec5SDimitry Andric       // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
4010b57cec5SDimitry Andric       // deflate,lzma
402fe6060f1SDimitry Andric       else if (x.consume_front("SupportedCompressions=")) {
403fe6060f1SDimitry Andric         llvm::SmallVector<llvm::StringRef, 4> compressions;
404fe6060f1SDimitry Andric         x.split(compressions, ',');
405fe6060f1SDimitry Andric         if (!compressions.empty())
406fe6060f1SDimitry Andric           MaybeEnableCompression(compressions);
407*0fca6ea1SDimitry Andric       } else if (x.consume_front("SupportedWatchpointTypes=")) {
408*0fca6ea1SDimitry Andric         llvm::SmallVector<llvm::StringRef, 4> watchpoint_types;
409*0fca6ea1SDimitry Andric         x.split(watchpoint_types, ',');
410*0fca6ea1SDimitry Andric         m_watchpoint_types = eWatchpointHardwareFeatureUnknown;
411*0fca6ea1SDimitry Andric         for (auto wp_type : watchpoint_types) {
412*0fca6ea1SDimitry Andric           if (wp_type == "x86_64")
413*0fca6ea1SDimitry Andric             m_watchpoint_types |= eWatchpointHardwareX86;
414*0fca6ea1SDimitry Andric           if (wp_type == "aarch64-mask")
415*0fca6ea1SDimitry Andric             m_watchpoint_types |= eWatchpointHardwareArmMASK;
416*0fca6ea1SDimitry Andric           if (wp_type == "aarch64-bas")
417*0fca6ea1SDimitry Andric             m_watchpoint_types |= eWatchpointHardwareArmBAS;
418*0fca6ea1SDimitry Andric         }
419fe6060f1SDimitry Andric       } else if (x.consume_front("PacketSize=")) {
420fe6060f1SDimitry Andric         StringExtractorGDBRemote packet_response(x);
4210b57cec5SDimitry Andric         m_max_packet_size =
4220b57cec5SDimitry Andric             packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
4230b57cec5SDimitry Andric         if (m_max_packet_size == 0) {
4240b57cec5SDimitry Andric           m_max_packet_size = UINT64_MAX; // Must have been a garbled response
4251fd87a68SDimitry Andric           Log *log(GetLog(GDBRLog::Process));
4269dba64beSDimitry Andric           LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response");
4270b57cec5SDimitry Andric         }
4280b57cec5SDimitry Andric       }
4290b57cec5SDimitry Andric     }
4300b57cec5SDimitry Andric   }
431fe6060f1SDimitry Andric }
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() {
4340b57cec5SDimitry Andric   if (m_supports_thread_suffix == eLazyBoolCalculate) {
4350b57cec5SDimitry Andric     StringExtractorGDBRemote response;
4360b57cec5SDimitry Andric     m_supports_thread_suffix = eLazyBoolNo;
437fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response) ==
438fe6060f1SDimitry Andric         PacketResult::Success) {
4390b57cec5SDimitry Andric       if (response.IsOKResponse())
4400b57cec5SDimitry Andric         m_supports_thread_suffix = eLazyBoolYes;
4410b57cec5SDimitry Andric     }
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric   return m_supports_thread_suffix;
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) {
4460b57cec5SDimitry Andric   if (m_supports_vCont_c == eLazyBoolCalculate) {
4470b57cec5SDimitry Andric     StringExtractorGDBRemote response;
4480b57cec5SDimitry Andric     m_supports_vCont_any = eLazyBoolNo;
4490b57cec5SDimitry Andric     m_supports_vCont_all = eLazyBoolNo;
4500b57cec5SDimitry Andric     m_supports_vCont_c = eLazyBoolNo;
4510b57cec5SDimitry Andric     m_supports_vCont_C = eLazyBoolNo;
4520b57cec5SDimitry Andric     m_supports_vCont_s = eLazyBoolNo;
4530b57cec5SDimitry Andric     m_supports_vCont_S = eLazyBoolNo;
454fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("vCont?", response) ==
4550b57cec5SDimitry Andric         PacketResult::Success) {
4569dba64beSDimitry Andric       const char *response_cstr = response.GetStringRef().data();
4570b57cec5SDimitry Andric       if (::strstr(response_cstr, ";c"))
4580b57cec5SDimitry Andric         m_supports_vCont_c = eLazyBoolYes;
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric       if (::strstr(response_cstr, ";C"))
4610b57cec5SDimitry Andric         m_supports_vCont_C = eLazyBoolYes;
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric       if (::strstr(response_cstr, ";s"))
4640b57cec5SDimitry Andric         m_supports_vCont_s = eLazyBoolYes;
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric       if (::strstr(response_cstr, ";S"))
4670b57cec5SDimitry Andric         m_supports_vCont_S = eLazyBoolYes;
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric       if (m_supports_vCont_c == eLazyBoolYes &&
4700b57cec5SDimitry Andric           m_supports_vCont_C == eLazyBoolYes &&
4710b57cec5SDimitry Andric           m_supports_vCont_s == eLazyBoolYes &&
4720b57cec5SDimitry Andric           m_supports_vCont_S == eLazyBoolYes) {
4730b57cec5SDimitry Andric         m_supports_vCont_all = eLazyBoolYes;
4740b57cec5SDimitry Andric       }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric       if (m_supports_vCont_c == eLazyBoolYes ||
4770b57cec5SDimitry Andric           m_supports_vCont_C == eLazyBoolYes ||
4780b57cec5SDimitry Andric           m_supports_vCont_s == eLazyBoolYes ||
4790b57cec5SDimitry Andric           m_supports_vCont_S == eLazyBoolYes) {
4800b57cec5SDimitry Andric         m_supports_vCont_any = eLazyBoolYes;
4810b57cec5SDimitry Andric       }
4820b57cec5SDimitry Andric     }
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   switch (flavor) {
4860b57cec5SDimitry Andric   case 'a':
4870b57cec5SDimitry Andric     return m_supports_vCont_any;
4880b57cec5SDimitry Andric   case 'A':
4890b57cec5SDimitry Andric     return m_supports_vCont_all;
4900b57cec5SDimitry Andric   case 'c':
4910b57cec5SDimitry Andric     return m_supports_vCont_c;
4920b57cec5SDimitry Andric   case 'C':
4930b57cec5SDimitry Andric     return m_supports_vCont_C;
4940b57cec5SDimitry Andric   case 's':
4950b57cec5SDimitry Andric     return m_supports_vCont_s;
4960b57cec5SDimitry Andric   case 'S':
4970b57cec5SDimitry Andric     return m_supports_vCont_S;
4980b57cec5SDimitry Andric   default:
4990b57cec5SDimitry Andric     break;
5000b57cec5SDimitry Andric   }
5010b57cec5SDimitry Andric   return false;
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
5050b57cec5SDimitry Andric GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
506fe6060f1SDimitry Andric     lldb::tid_t tid, StreamString &&payload,
507fe6060f1SDimitry Andric     StringExtractorGDBRemote &response) {
508fe6060f1SDimitry Andric   Lock lock(*this);
5090b57cec5SDimitry Andric   if (!lock) {
5101fd87a68SDimitry Andric     if (Log *log = GetLog(GDBRLog::Process | GDBRLog::Packets))
5119dba64beSDimitry Andric       LLDB_LOGF(log,
5129dba64beSDimitry Andric                 "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex "
5130b57cec5SDimitry Andric                 "for %s packet.",
5140b57cec5SDimitry Andric                 __FUNCTION__, payload.GetData());
5150b57cec5SDimitry Andric     return PacketResult::ErrorNoSequenceLock;
5160b57cec5SDimitry Andric   }
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric   if (GetThreadSuffixSupported())
5190b57cec5SDimitry Andric     payload.Printf(";thread:%4.4" PRIx64 ";", tid);
5200b57cec5SDimitry Andric   else {
5210b57cec5SDimitry Andric     if (!SetCurrentThread(tid))
5220b57cec5SDimitry Andric       return PacketResult::ErrorSendFailed;
5230b57cec5SDimitry Andric   }
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric // Check if the target supports 'p' packet. It sends out a 'p' packet and
5290b57cec5SDimitry Andric // checks the response. A normal packet will tell us that support is available.
5300b57cec5SDimitry Andric //
5310b57cec5SDimitry Andric // Takes a valid thread ID because p needs to apply to a thread.
5320b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
533480093f4SDimitry Andric   if (m_supports_p == eLazyBoolCalculate)
534480093f4SDimitry Andric     m_supports_p = GetThreadPacketSupported(tid, "p0");
5350b57cec5SDimitry Andric   return m_supports_p;
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
538480093f4SDimitry Andric LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported(
539480093f4SDimitry Andric     lldb::tid_t tid, llvm::StringRef packetStr) {
540480093f4SDimitry Andric   StreamString payload;
541480093f4SDimitry Andric   payload.PutCString(packetStr);
542480093f4SDimitry Andric   StringExtractorGDBRemote response;
543480093f4SDimitry Andric   if (SendThreadSpecificPacketAndWaitForResponse(
544fe6060f1SDimitry Andric           tid, std::move(payload), response) == PacketResult::Success &&
545480093f4SDimitry Andric       response.IsNormalResponse()) {
546480093f4SDimitry Andric     return eLazyBoolYes;
547480093f4SDimitry Andric   }
548480093f4SDimitry Andric   return eLazyBoolNo;
549480093f4SDimitry Andric }
550480093f4SDimitry Andric 
551349cc55cSDimitry Andric bool GDBRemoteCommunicationClient::GetSaveCoreSupported() const {
552349cc55cSDimitry Andric   return m_supports_qSaveCore == eLazyBoolYes;
553349cc55cSDimitry Andric }
554349cc55cSDimitry Andric 
5550b57cec5SDimitry Andric StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
5560b57cec5SDimitry Andric   // Get information on all threads at one using the "jThreadsInfo" packet
5570b57cec5SDimitry Andric   StructuredData::ObjectSP object_sp;
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   if (m_supports_jThreadsInfo) {
5600b57cec5SDimitry Andric     StringExtractorGDBRemote response;
5610b57cec5SDimitry Andric     response.SetResponseValidatorToJSON();
562fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("jThreadsInfo", response) ==
5630b57cec5SDimitry Andric         PacketResult::Success) {
5640b57cec5SDimitry Andric       if (response.IsUnsupportedResponse()) {
5650b57cec5SDimitry Andric         m_supports_jThreadsInfo = false;
5660b57cec5SDimitry Andric       } else if (!response.Empty()) {
56706c3fb27SDimitry Andric         object_sp = StructuredData::ParseJSON(response.GetStringRef());
5680b57cec5SDimitry Andric       }
5690b57cec5SDimitry Andric     }
5700b57cec5SDimitry Andric   }
5710b57cec5SDimitry Andric   return object_sp;
5720b57cec5SDimitry Andric }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
5750b57cec5SDimitry Andric   if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) {
5760b57cec5SDimitry Andric     StringExtractorGDBRemote response;
5770b57cec5SDimitry Andric     m_supports_jThreadExtendedInfo = eLazyBoolNo;
578fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response) ==
5790b57cec5SDimitry Andric         PacketResult::Success) {
5800b57cec5SDimitry Andric       if (response.IsOKResponse()) {
5810b57cec5SDimitry Andric         m_supports_jThreadExtendedInfo = eLazyBoolYes;
5820b57cec5SDimitry Andric       }
5830b57cec5SDimitry Andric     }
5840b57cec5SDimitry Andric   }
5850b57cec5SDimitry Andric   return m_supports_jThreadExtendedInfo;
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric void GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
5890b57cec5SDimitry Andric   if (m_supports_error_string_reply == eLazyBoolCalculate) {
5900b57cec5SDimitry Andric     StringExtractorGDBRemote response;
5910b57cec5SDimitry Andric     // We try to enable error strings in remote packets but if we fail, we just
5920b57cec5SDimitry Andric     // work in the older way.
5930b57cec5SDimitry Andric     m_supports_error_string_reply = eLazyBoolNo;
594fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("QEnableErrorStrings", response) ==
5950b57cec5SDimitry Andric         PacketResult::Success) {
5960b57cec5SDimitry Andric       if (response.IsOKResponse()) {
5970b57cec5SDimitry Andric         m_supports_error_string_reply = eLazyBoolYes;
5980b57cec5SDimitry Andric       }
5990b57cec5SDimitry Andric     }
6000b57cec5SDimitry Andric   }
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() {
6040b57cec5SDimitry Andric   if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) {
6050b57cec5SDimitry Andric     StringExtractorGDBRemote response;
6060b57cec5SDimitry Andric     m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
6070b57cec5SDimitry Andric     if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:",
608fe6060f1SDimitry Andric                                      response) == PacketResult::Success) {
6090b57cec5SDimitry Andric       if (response.IsOKResponse()) {
6100b57cec5SDimitry Andric         m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
6110b57cec5SDimitry Andric       }
6120b57cec5SDimitry Andric     }
6130b57cec5SDimitry Andric   }
6140b57cec5SDimitry Andric   return m_supports_jLoadedDynamicLibrariesInfos;
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() {
6180b57cec5SDimitry Andric   if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) {
6190b57cec5SDimitry Andric     StringExtractorGDBRemote response;
6200b57cec5SDimitry Andric     m_supports_jGetSharedCacheInfo = eLazyBoolNo;
621fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response) ==
6220b57cec5SDimitry Andric         PacketResult::Success) {
6230b57cec5SDimitry Andric       if (response.IsOKResponse()) {
6240b57cec5SDimitry Andric         m_supports_jGetSharedCacheInfo = eLazyBoolYes;
6250b57cec5SDimitry Andric       }
6260b57cec5SDimitry Andric     }
6270b57cec5SDimitry Andric   }
6280b57cec5SDimitry Andric   return m_supports_jGetSharedCacheInfo;
6290b57cec5SDimitry Andric }
6300b57cec5SDimitry Andric 
631bdd1243dSDimitry Andric bool GDBRemoteCommunicationClient::GetDynamicLoaderProcessStateSupported() {
632bdd1243dSDimitry Andric   if (m_supports_jGetDyldProcessState == eLazyBoolCalculate) {
633bdd1243dSDimitry Andric     StringExtractorGDBRemote response;
634bdd1243dSDimitry Andric     m_supports_jGetDyldProcessState = eLazyBoolNo;
635bdd1243dSDimitry Andric     if (SendPacketAndWaitForResponse("jGetDyldProcessState", response) ==
636bdd1243dSDimitry Andric         PacketResult::Success) {
637bdd1243dSDimitry Andric       if (!response.IsUnsupportedResponse())
638bdd1243dSDimitry Andric         m_supports_jGetDyldProcessState = eLazyBoolYes;
639bdd1243dSDimitry Andric     }
640bdd1243dSDimitry Andric   }
641bdd1243dSDimitry Andric   return m_supports_jGetDyldProcessState;
642bdd1243dSDimitry Andric }
643bdd1243dSDimitry Andric 
644fe6060f1SDimitry Andric bool GDBRemoteCommunicationClient::GetMemoryTaggingSupported() {
645fe6060f1SDimitry Andric   if (m_supports_memory_tagging == eLazyBoolCalculate) {
646fe6060f1SDimitry Andric     GetRemoteQSupported();
647fe6060f1SDimitry Andric   }
648fe6060f1SDimitry Andric   return m_supports_memory_tagging == eLazyBoolYes;
649fe6060f1SDimitry Andric }
650fe6060f1SDimitry Andric 
651fe6060f1SDimitry Andric DataBufferSP GDBRemoteCommunicationClient::ReadMemoryTags(lldb::addr_t addr,
652fe6060f1SDimitry Andric                                                           size_t len,
653fe6060f1SDimitry Andric                                                           int32_t type) {
654fe6060f1SDimitry Andric   StreamString packet;
655fe6060f1SDimitry Andric   packet.Printf("qMemTags:%" PRIx64 ",%zx:%" PRIx32, addr, len, type);
656fe6060f1SDimitry Andric   StringExtractorGDBRemote response;
657fe6060f1SDimitry Andric 
6581fd87a68SDimitry Andric   Log *log = GetLog(GDBRLog::Memory);
659fe6060f1SDimitry Andric 
660fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
661fe6060f1SDimitry Andric           PacketResult::Success ||
662fe6060f1SDimitry Andric       !response.IsNormalResponse()) {
663fe6060f1SDimitry Andric     LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s: qMemTags packet failed",
664fe6060f1SDimitry Andric               __FUNCTION__);
665fe6060f1SDimitry Andric     return nullptr;
666fe6060f1SDimitry Andric   }
667fe6060f1SDimitry Andric 
668fe6060f1SDimitry Andric   // We are expecting
669fe6060f1SDimitry Andric   // m<hex encoded bytes>
670fe6060f1SDimitry Andric 
671fe6060f1SDimitry Andric   if (response.GetChar() != 'm') {
672fe6060f1SDimitry Andric     LLDB_LOGF(log,
673fe6060f1SDimitry Andric               "GDBRemoteCommunicationClient::%s: qMemTags response did not "
674fe6060f1SDimitry Andric               "begin with \"m\"",
675fe6060f1SDimitry Andric               __FUNCTION__);
676fe6060f1SDimitry Andric     return nullptr;
677fe6060f1SDimitry Andric   }
678fe6060f1SDimitry Andric 
679fe6060f1SDimitry Andric   size_t expected_bytes = response.GetBytesLeft() / 2;
68081ad6265SDimitry Andric   WritableDataBufferSP buffer_sp(new DataBufferHeap(expected_bytes, 0));
681fe6060f1SDimitry Andric   size_t got_bytes = response.GetHexBytesAvail(buffer_sp->GetData());
682fe6060f1SDimitry Andric   // Check both because in some situations chars are consumed even
683fe6060f1SDimitry Andric   // if the decoding fails.
684fe6060f1SDimitry Andric   if (response.GetBytesLeft() || (expected_bytes != got_bytes)) {
685fe6060f1SDimitry Andric     LLDB_LOGF(
686fe6060f1SDimitry Andric         log,
687fe6060f1SDimitry Andric         "GDBRemoteCommunicationClient::%s: Invalid data in qMemTags response",
688fe6060f1SDimitry Andric         __FUNCTION__);
689fe6060f1SDimitry Andric     return nullptr;
690fe6060f1SDimitry Andric   }
691fe6060f1SDimitry Andric 
692fe6060f1SDimitry Andric   return buffer_sp;
693fe6060f1SDimitry Andric }
694fe6060f1SDimitry Andric 
695fe6060f1SDimitry Andric Status GDBRemoteCommunicationClient::WriteMemoryTags(
696fe6060f1SDimitry Andric     lldb::addr_t addr, size_t len, int32_t type,
697fe6060f1SDimitry Andric     const std::vector<uint8_t> &tags) {
698fe6060f1SDimitry Andric   // Format QMemTags:address,length:type:tags
699fe6060f1SDimitry Andric   StreamString packet;
700fe6060f1SDimitry Andric   packet.Printf("QMemTags:%" PRIx64 ",%zx:%" PRIx32 ":", addr, len, type);
701fe6060f1SDimitry Andric   packet.PutBytesAsRawHex8(tags.data(), tags.size());
702fe6060f1SDimitry Andric 
703fe6060f1SDimitry Andric   Status status;
704fe6060f1SDimitry Andric   StringExtractorGDBRemote response;
705fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
706fe6060f1SDimitry Andric           PacketResult::Success ||
707fe6060f1SDimitry Andric       !response.IsOKResponse()) {
708fe6060f1SDimitry Andric     status.SetErrorString("QMemTags packet failed");
709fe6060f1SDimitry Andric   }
710fe6060f1SDimitry Andric   return status;
711fe6060f1SDimitry Andric }
712fe6060f1SDimitry Andric 
7130b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetxPacketSupported() {
7140b57cec5SDimitry Andric   if (m_supports_x == eLazyBoolCalculate) {
7150b57cec5SDimitry Andric     StringExtractorGDBRemote response;
7160b57cec5SDimitry Andric     m_supports_x = eLazyBoolNo;
7170b57cec5SDimitry Andric     char packet[256];
7180b57cec5SDimitry Andric     snprintf(packet, sizeof(packet), "x0,0");
719fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) ==
7200b57cec5SDimitry Andric         PacketResult::Success) {
7210b57cec5SDimitry Andric       if (response.IsOKResponse())
7220b57cec5SDimitry Andric         m_supports_x = eLazyBoolYes;
7230b57cec5SDimitry Andric     }
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric   return m_supports_x;
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
7290b57cec5SDimitry Andric   if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes)
7300b57cec5SDimitry Andric     return m_curr_pid;
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric   // First try to retrieve the pid via the qProcessInfo request.
7330b57cec5SDimitry Andric   GetCurrentProcessInfo(allow_lazy);
7340b57cec5SDimitry Andric   if (m_curr_pid_is_valid == eLazyBoolYes) {
7350b57cec5SDimitry Andric     // We really got it.
7360b57cec5SDimitry Andric     return m_curr_pid;
7370b57cec5SDimitry Andric   } else {
7380b57cec5SDimitry Andric     // If we don't get a response for qProcessInfo, check if $qC gives us a
7390b57cec5SDimitry Andric     // result. $qC only returns a real process id on older debugserver and
7400b57cec5SDimitry Andric     // lldb-platform stubs. The gdb remote protocol documents $qC as returning
7410b57cec5SDimitry Andric     // the thread id, which newer debugserver and lldb-gdbserver stubs return
7420b57cec5SDimitry Andric     // correctly.
7430b57cec5SDimitry Andric     StringExtractorGDBRemote response;
744fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("qC", response) == PacketResult::Success) {
7450b57cec5SDimitry Andric       if (response.GetChar() == 'Q') {
7460b57cec5SDimitry Andric         if (response.GetChar() == 'C') {
747fe6060f1SDimitry Andric           m_curr_pid_run = m_curr_pid =
748fe6060f1SDimitry Andric               response.GetHexMaxU64(false, LLDB_INVALID_PROCESS_ID);
7490b57cec5SDimitry Andric           if (m_curr_pid != LLDB_INVALID_PROCESS_ID) {
7500b57cec5SDimitry Andric             m_curr_pid_is_valid = eLazyBoolYes;
7510b57cec5SDimitry Andric             return m_curr_pid;
7520b57cec5SDimitry Andric           }
7530b57cec5SDimitry Andric         }
7540b57cec5SDimitry Andric       }
7550b57cec5SDimitry Andric     }
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric     // If we don't get a response for $qC, check if $qfThreadID gives us a
7580b57cec5SDimitry Andric     // result.
7590b57cec5SDimitry Andric     if (m_curr_pid == LLDB_INVALID_PROCESS_ID) {
7600b57cec5SDimitry Andric       bool sequence_mutex_unavailable;
761fe6060f1SDimitry Andric       auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
762fe6060f1SDimitry Andric       if (!ids.empty() && !sequence_mutex_unavailable) {
763fe6060f1SDimitry Andric         // If server returned an explicit PID, use that.
764fe6060f1SDimitry Andric         m_curr_pid_run = m_curr_pid = ids.front().first;
765fe6060f1SDimitry Andric         // Otherwise, use the TID of the first thread (Linux hack).
766fe6060f1SDimitry Andric         if (m_curr_pid == LLDB_INVALID_PROCESS_ID)
767fe6060f1SDimitry Andric           m_curr_pid_run = m_curr_pid = ids.front().second;
7680b57cec5SDimitry Andric         m_curr_pid_is_valid = eLazyBoolYes;
7690b57cec5SDimitry Andric         return m_curr_pid;
7700b57cec5SDimitry Andric       }
7710b57cec5SDimitry Andric     }
7720b57cec5SDimitry Andric   }
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric   return LLDB_INVALID_PROCESS_ID;
7750b57cec5SDimitry Andric }
7760b57cec5SDimitry Andric 
777bdd1243dSDimitry Andric llvm::Error GDBRemoteCommunicationClient::LaunchProcess(const Args &args) {
778bdd1243dSDimitry Andric   if (!args.GetArgumentAtIndex(0))
779bdd1243dSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
780bdd1243dSDimitry Andric                                    "Nothing to launch");
781349cc55cSDimitry Andric   // try vRun first
782349cc55cSDimitry Andric   if (m_supports_vRun) {
783349cc55cSDimitry Andric     StreamString packet;
784349cc55cSDimitry Andric     packet.PutCString("vRun");
785bdd1243dSDimitry Andric     for (const Args::ArgEntry &arg : args) {
786349cc55cSDimitry Andric       packet.PutChar(';');
787bdd1243dSDimitry Andric       packet.PutStringAsRawHex8(arg.ref());
788349cc55cSDimitry Andric     }
789349cc55cSDimitry Andric 
790349cc55cSDimitry Andric     StringExtractorGDBRemote response;
791349cc55cSDimitry Andric     if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
792349cc55cSDimitry Andric         PacketResult::Success)
793bdd1243dSDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
794bdd1243dSDimitry Andric                                      "Sending vRun packet failed");
795349cc55cSDimitry Andric 
796bdd1243dSDimitry Andric     if (response.IsErrorResponse())
797bdd1243dSDimitry Andric       return response.GetStatus().ToError();
798bdd1243dSDimitry Andric 
799349cc55cSDimitry Andric     // vRun replies with a stop reason packet
800349cc55cSDimitry Andric     // FIXME: right now we just discard the packet and LLDB queries
801349cc55cSDimitry Andric     // for stop reason again
802349cc55cSDimitry Andric     if (!response.IsUnsupportedResponse())
803bdd1243dSDimitry Andric       return llvm::Error::success();
804349cc55cSDimitry Andric 
805349cc55cSDimitry Andric     m_supports_vRun = false;
806349cc55cSDimitry Andric   }
807349cc55cSDimitry Andric 
808349cc55cSDimitry Andric   // fallback to A
8090b57cec5SDimitry Andric   StreamString packet;
8100b57cec5SDimitry Andric   packet.PutChar('A');
811bdd1243dSDimitry Andric   llvm::ListSeparator LS(",");
812bdd1243dSDimitry Andric   for (const auto &arg : llvm::enumerate(args)) {
813bdd1243dSDimitry Andric     packet << LS;
814bdd1243dSDimitry Andric     packet.Format("{0},{1},", arg.value().ref().size() * 2, arg.index());
815bdd1243dSDimitry Andric     packet.PutStringAsRawHex8(arg.value().ref());
8160b57cec5SDimitry Andric   }
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   StringExtractorGDBRemote response;
819bdd1243dSDimitry Andric   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
8200b57cec5SDimitry Andric       PacketResult::Success) {
821bdd1243dSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
822bdd1243dSDimitry Andric                                    "Sending A packet failed");
823bdd1243dSDimitry Andric   }
824bdd1243dSDimitry Andric   if (!response.IsOKResponse())
825bdd1243dSDimitry Andric     return response.GetStatus().ToError();
826bdd1243dSDimitry Andric 
827bdd1243dSDimitry Andric   if (SendPacketAndWaitForResponse("qLaunchSuccess", response) !=
828bdd1243dSDimitry Andric       PacketResult::Success) {
829bdd1243dSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
830bdd1243dSDimitry Andric                                    "Sending qLaunchSuccess packet failed");
831bdd1243dSDimitry Andric   }
8320b57cec5SDimitry Andric   if (response.IsOKResponse())
833bdd1243dSDimitry Andric     return llvm::Error::success();
834bdd1243dSDimitry Andric   if (response.GetChar() == 'E') {
835bdd1243dSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
836bdd1243dSDimitry Andric                                    response.GetStringRef().substr(1));
8370b57cec5SDimitry Andric   }
838bdd1243dSDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
839bdd1243dSDimitry Andric                                  "unknown error occurred launching process");
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SendEnvironment(const Environment &env) {
84306c3fb27SDimitry Andric   llvm::SmallVector<std::pair<llvm::StringRef, llvm::StringRef>, 0> vec;
84406c3fb27SDimitry Andric   for (const auto &kv : env)
84506c3fb27SDimitry Andric     vec.emplace_back(kv.first(), kv.second);
84606c3fb27SDimitry Andric   llvm::sort(vec, llvm::less_first());
84706c3fb27SDimitry Andric   for (const auto &[k, v] : vec) {
84806c3fb27SDimitry Andric     int r = SendEnvironmentPacket((k + "=" + v).str().c_str());
8490b57cec5SDimitry Andric     if (r != 0)
8500b57cec5SDimitry Andric       return r;
8510b57cec5SDimitry Andric   }
8520b57cec5SDimitry Andric   return 0;
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SendEnvironmentPacket(
8560b57cec5SDimitry Andric     char const *name_equal_value) {
8570b57cec5SDimitry Andric   if (name_equal_value && name_equal_value[0]) {
8580b57cec5SDimitry Andric     bool send_hex_encoding = false;
8590b57cec5SDimitry Andric     for (const char *p = name_equal_value; *p != '\0' && !send_hex_encoding;
8600b57cec5SDimitry Andric          ++p) {
8615ffd83dbSDimitry Andric       if (llvm::isPrint(*p)) {
8620b57cec5SDimitry Andric         switch (*p) {
8630b57cec5SDimitry Andric         case '$':
8640b57cec5SDimitry Andric         case '#':
8650b57cec5SDimitry Andric         case '*':
8660b57cec5SDimitry Andric         case '}':
8670b57cec5SDimitry Andric           send_hex_encoding = true;
8680b57cec5SDimitry Andric           break;
8690b57cec5SDimitry Andric         default:
8700b57cec5SDimitry Andric           break;
8710b57cec5SDimitry Andric         }
8720b57cec5SDimitry Andric       } else {
8730b57cec5SDimitry Andric         // We have non printable characters, lets hex encode this...
8740b57cec5SDimitry Andric         send_hex_encoding = true;
8750b57cec5SDimitry Andric       }
8760b57cec5SDimitry Andric     }
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric     StringExtractorGDBRemote response;
879349cc55cSDimitry Andric     // Prefer sending unencoded, if possible and the server supports it.
880349cc55cSDimitry Andric     if (!send_hex_encoding && m_supports_QEnvironment) {
881349cc55cSDimitry Andric       StreamString packet;
882349cc55cSDimitry Andric       packet.Printf("QEnvironment:%s", name_equal_value);
883349cc55cSDimitry Andric       if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
884349cc55cSDimitry Andric           PacketResult::Success)
885349cc55cSDimitry Andric         return -1;
886349cc55cSDimitry Andric 
8870b57cec5SDimitry Andric       if (response.IsOKResponse())
8880b57cec5SDimitry Andric         return 0;
889349cc55cSDimitry Andric       if (response.IsUnsupportedResponse())
890349cc55cSDimitry Andric         m_supports_QEnvironment = false;
891349cc55cSDimitry Andric       else {
8920b57cec5SDimitry Andric         uint8_t error = response.GetError();
8930b57cec5SDimitry Andric         if (error)
8940b57cec5SDimitry Andric           return error;
895349cc55cSDimitry Andric         return -1;
8960b57cec5SDimitry Andric       }
8970b57cec5SDimitry Andric     }
8980b57cec5SDimitry Andric 
899349cc55cSDimitry Andric     if (m_supports_QEnvironmentHexEncoded) {
900349cc55cSDimitry Andric       StreamString packet;
901349cc55cSDimitry Andric       packet.PutCString("QEnvironmentHexEncoded:");
902349cc55cSDimitry Andric       packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value));
903349cc55cSDimitry Andric       if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
904349cc55cSDimitry Andric           PacketResult::Success)
905349cc55cSDimitry Andric         return -1;
906349cc55cSDimitry Andric 
9070b57cec5SDimitry Andric       if (response.IsOKResponse())
9080b57cec5SDimitry Andric         return 0;
909349cc55cSDimitry Andric       if (response.IsUnsupportedResponse())
910349cc55cSDimitry Andric         m_supports_QEnvironmentHexEncoded = false;
911349cc55cSDimitry Andric       else {
9120b57cec5SDimitry Andric         uint8_t error = response.GetError();
9130b57cec5SDimitry Andric         if (error)
9140b57cec5SDimitry Andric           return error;
915349cc55cSDimitry Andric         return -1;
9160b57cec5SDimitry Andric       }
9170b57cec5SDimitry Andric     }
9180b57cec5SDimitry Andric   }
9190b57cec5SDimitry Andric   return -1;
9200b57cec5SDimitry Andric }
9210b57cec5SDimitry Andric 
9220b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) {
9230b57cec5SDimitry Andric   if (arch && arch[0]) {
9240b57cec5SDimitry Andric     StreamString packet;
9250b57cec5SDimitry Andric     packet.Printf("QLaunchArch:%s", arch);
9260b57cec5SDimitry Andric     StringExtractorGDBRemote response;
927fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
9280b57cec5SDimitry Andric         PacketResult::Success) {
9290b57cec5SDimitry Andric       if (response.IsOKResponse())
9300b57cec5SDimitry Andric         return 0;
9310b57cec5SDimitry Andric       uint8_t error = response.GetError();
9320b57cec5SDimitry Andric       if (error)
9330b57cec5SDimitry Andric         return error;
9340b57cec5SDimitry Andric     }
9350b57cec5SDimitry Andric   }
9360b57cec5SDimitry Andric   return -1;
9370b57cec5SDimitry Andric }
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
9400b57cec5SDimitry Andric     char const *data, bool *was_supported) {
9410b57cec5SDimitry Andric   if (data && *data != '\0') {
9420b57cec5SDimitry Andric     StreamString packet;
9430b57cec5SDimitry Andric     packet.Printf("QSetProcessEvent:%s", data);
9440b57cec5SDimitry Andric     StringExtractorGDBRemote response;
945fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
9460b57cec5SDimitry Andric         PacketResult::Success) {
9470b57cec5SDimitry Andric       if (response.IsOKResponse()) {
9480b57cec5SDimitry Andric         if (was_supported)
9490b57cec5SDimitry Andric           *was_supported = true;
9500b57cec5SDimitry Andric         return 0;
9510b57cec5SDimitry Andric       } else if (response.IsUnsupportedResponse()) {
9520b57cec5SDimitry Andric         if (was_supported)
9530b57cec5SDimitry Andric           *was_supported = false;
9540b57cec5SDimitry Andric         return -1;
9550b57cec5SDimitry Andric       } else {
9560b57cec5SDimitry Andric         uint8_t error = response.GetError();
9570b57cec5SDimitry Andric         if (was_supported)
9580b57cec5SDimitry Andric           *was_supported = true;
9590b57cec5SDimitry Andric         if (error)
9600b57cec5SDimitry Andric           return error;
9610b57cec5SDimitry Andric       }
9620b57cec5SDimitry Andric     }
9630b57cec5SDimitry Andric   }
9640b57cec5SDimitry Andric   return -1;
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() {
9680b57cec5SDimitry Andric   GetHostInfo();
9690b57cec5SDimitry Andric   return m_os_version;
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
9729dba64beSDimitry Andric llvm::VersionTuple GDBRemoteCommunicationClient::GetMacCatalystVersion() {
9739dba64beSDimitry Andric   GetHostInfo();
9749dba64beSDimitry Andric   return m_maccatalyst_version;
9759dba64beSDimitry Andric }
9769dba64beSDimitry Andric 
977bdd1243dSDimitry Andric std::optional<std::string> GDBRemoteCommunicationClient::GetOSBuildString() {
9780b57cec5SDimitry Andric   if (GetHostInfo()) {
979349cc55cSDimitry Andric     if (!m_os_build.empty())
980349cc55cSDimitry Andric       return m_os_build;
9810b57cec5SDimitry Andric   }
982bdd1243dSDimitry Andric   return std::nullopt;
9830b57cec5SDimitry Andric }
9840b57cec5SDimitry Andric 
985bdd1243dSDimitry Andric std::optional<std::string>
986349cc55cSDimitry Andric GDBRemoteCommunicationClient::GetOSKernelDescription() {
9870b57cec5SDimitry Andric   if (GetHostInfo()) {
988349cc55cSDimitry Andric     if (!m_os_kernel.empty())
989349cc55cSDimitry Andric       return m_os_kernel;
9900b57cec5SDimitry Andric   }
991bdd1243dSDimitry Andric   return std::nullopt;
9920b57cec5SDimitry Andric }
9930b57cec5SDimitry Andric 
9940b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetHostname(std::string &s) {
9950b57cec5SDimitry Andric   if (GetHostInfo()) {
9960b57cec5SDimitry Andric     if (!m_hostname.empty()) {
9970b57cec5SDimitry Andric       s = m_hostname;
9980b57cec5SDimitry Andric       return true;
9990b57cec5SDimitry Andric     }
10000b57cec5SDimitry Andric   }
10010b57cec5SDimitry Andric   s.clear();
10020b57cec5SDimitry Andric   return false;
10030b57cec5SDimitry Andric }
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric ArchSpec GDBRemoteCommunicationClient::GetSystemArchitecture() {
10060b57cec5SDimitry Andric   if (GetHostInfo())
10070b57cec5SDimitry Andric     return m_host_arch;
10080b57cec5SDimitry Andric   return ArchSpec();
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric const lldb_private::ArchSpec &
10120b57cec5SDimitry Andric GDBRemoteCommunicationClient::GetProcessArchitecture() {
10130b57cec5SDimitry Andric   if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
10140b57cec5SDimitry Andric     GetCurrentProcessInfo();
10150b57cec5SDimitry Andric   return m_process_arch;
10160b57cec5SDimitry Andric }
10170b57cec5SDimitry Andric 
10180eae32dcSDimitry Andric bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary(
10190eae32dcSDimitry Andric     UUID &uuid, addr_t &value, bool &value_is_offset) {
10200eae32dcSDimitry Andric   if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
10210eae32dcSDimitry Andric     GetCurrentProcessInfo();
10220eae32dcSDimitry Andric 
10230eae32dcSDimitry Andric   // Return true if we have a UUID or an address/offset of the
10240eae32dcSDimitry Andric   // main standalone / firmware binary being used.
10250eae32dcSDimitry Andric   if (!m_process_standalone_uuid.IsValid() &&
10260eae32dcSDimitry Andric       m_process_standalone_value == LLDB_INVALID_ADDRESS)
10270eae32dcSDimitry Andric     return false;
10280eae32dcSDimitry Andric 
10290eae32dcSDimitry Andric   uuid = m_process_standalone_uuid;
10300eae32dcSDimitry Andric   value = m_process_standalone_value;
10310eae32dcSDimitry Andric   value_is_offset = m_process_standalone_value_is_offset;
10320eae32dcSDimitry Andric   return true;
10330eae32dcSDimitry Andric }
10340eae32dcSDimitry Andric 
1035bdd1243dSDimitry Andric std::vector<addr_t>
1036bdd1243dSDimitry Andric GDBRemoteCommunicationClient::GetProcessStandaloneBinaries() {
1037bdd1243dSDimitry Andric   if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
1038bdd1243dSDimitry Andric     GetCurrentProcessInfo();
1039bdd1243dSDimitry Andric   return m_binary_addresses;
1040bdd1243dSDimitry Andric }
1041bdd1243dSDimitry Andric 
10420b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
10430b57cec5SDimitry Andric   if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
10440b57cec5SDimitry Andric     m_gdb_server_name.clear();
10450b57cec5SDimitry Andric     m_gdb_server_version = 0;
10460b57cec5SDimitry Andric     m_qGDBServerVersion_is_valid = eLazyBoolNo;
10470b57cec5SDimitry Andric 
10480b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1049fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("qGDBServerVersion", response) ==
10500b57cec5SDimitry Andric         PacketResult::Success) {
10510b57cec5SDimitry Andric       if (response.IsNormalResponse()) {
10520b57cec5SDimitry Andric         llvm::StringRef name, value;
10530b57cec5SDimitry Andric         bool success = false;
10540b57cec5SDimitry Andric         while (response.GetNameColonValue(name, value)) {
1055*0fca6ea1SDimitry Andric           if (name == "name") {
10560b57cec5SDimitry Andric             success = true;
10575ffd83dbSDimitry Andric             m_gdb_server_name = std::string(value);
1058*0fca6ea1SDimitry Andric           } else if (name == "version") {
10590b57cec5SDimitry Andric             llvm::StringRef major, minor;
10600b57cec5SDimitry Andric             std::tie(major, minor) = value.split('.');
10610b57cec5SDimitry Andric             if (!major.getAsInteger(0, m_gdb_server_version))
10620b57cec5SDimitry Andric               success = true;
10630b57cec5SDimitry Andric           }
10640b57cec5SDimitry Andric         }
10650b57cec5SDimitry Andric         if (success)
10660b57cec5SDimitry Andric           m_qGDBServerVersion_is_valid = eLazyBoolYes;
10670b57cec5SDimitry Andric       }
10680b57cec5SDimitry Andric     }
10690b57cec5SDimitry Andric   }
10700b57cec5SDimitry Andric   return m_qGDBServerVersion_is_valid == eLazyBoolYes;
10710b57cec5SDimitry Andric }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric void GDBRemoteCommunicationClient::MaybeEnableCompression(
1074fe6060f1SDimitry Andric     llvm::ArrayRef<llvm::StringRef> supported_compressions) {
10750b57cec5SDimitry Andric   CompressionType avail_type = CompressionType::None;
1076fe6060f1SDimitry Andric   llvm::StringRef avail_name;
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric #if defined(HAVE_LIBCOMPRESSION)
10790b57cec5SDimitry Andric   if (avail_type == CompressionType::None) {
10800b57cec5SDimitry Andric     for (auto compression : supported_compressions) {
10810b57cec5SDimitry Andric       if (compression == "lzfse") {
10820b57cec5SDimitry Andric         avail_type = CompressionType::LZFSE;
10830b57cec5SDimitry Andric         avail_name = compression;
10840b57cec5SDimitry Andric         break;
10850b57cec5SDimitry Andric       }
10860b57cec5SDimitry Andric     }
10870b57cec5SDimitry Andric   }
10880b57cec5SDimitry Andric #endif
10890b57cec5SDimitry Andric 
10900b57cec5SDimitry Andric #if defined(HAVE_LIBCOMPRESSION)
10910b57cec5SDimitry Andric   if (avail_type == CompressionType::None) {
10920b57cec5SDimitry Andric     for (auto compression : supported_compressions) {
10930b57cec5SDimitry Andric       if (compression == "zlib-deflate") {
10940b57cec5SDimitry Andric         avail_type = CompressionType::ZlibDeflate;
10950b57cec5SDimitry Andric         avail_name = compression;
10960b57cec5SDimitry Andric         break;
10970b57cec5SDimitry Andric       }
10980b57cec5SDimitry Andric     }
10990b57cec5SDimitry Andric   }
11000b57cec5SDimitry Andric #endif
11010b57cec5SDimitry Andric 
1102e8d8bef9SDimitry Andric #if LLVM_ENABLE_ZLIB
11030b57cec5SDimitry Andric   if (avail_type == CompressionType::None) {
11040b57cec5SDimitry Andric     for (auto compression : supported_compressions) {
11050b57cec5SDimitry Andric       if (compression == "zlib-deflate") {
11060b57cec5SDimitry Andric         avail_type = CompressionType::ZlibDeflate;
11070b57cec5SDimitry Andric         avail_name = compression;
11080b57cec5SDimitry Andric         break;
11090b57cec5SDimitry Andric       }
11100b57cec5SDimitry Andric     }
11110b57cec5SDimitry Andric   }
11120b57cec5SDimitry Andric #endif
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric #if defined(HAVE_LIBCOMPRESSION)
11150b57cec5SDimitry Andric   if (avail_type == CompressionType::None) {
11160b57cec5SDimitry Andric     for (auto compression : supported_compressions) {
11170b57cec5SDimitry Andric       if (compression == "lz4") {
11180b57cec5SDimitry Andric         avail_type = CompressionType::LZ4;
11190b57cec5SDimitry Andric         avail_name = compression;
11200b57cec5SDimitry Andric         break;
11210b57cec5SDimitry Andric       }
11220b57cec5SDimitry Andric     }
11230b57cec5SDimitry Andric   }
11240b57cec5SDimitry Andric #endif
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric #if defined(HAVE_LIBCOMPRESSION)
11270b57cec5SDimitry Andric   if (avail_type == CompressionType::None) {
11280b57cec5SDimitry Andric     for (auto compression : supported_compressions) {
11290b57cec5SDimitry Andric       if (compression == "lzma") {
11300b57cec5SDimitry Andric         avail_type = CompressionType::LZMA;
11310b57cec5SDimitry Andric         avail_name = compression;
11320b57cec5SDimitry Andric         break;
11330b57cec5SDimitry Andric       }
11340b57cec5SDimitry Andric     }
11350b57cec5SDimitry Andric   }
11360b57cec5SDimitry Andric #endif
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric   if (avail_type != CompressionType::None) {
11390b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1140349cc55cSDimitry Andric     std::string packet = "QEnableCompression:type:" + avail_name.str() + ";";
1141349cc55cSDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
11420b57cec5SDimitry Andric       return;
11430b57cec5SDimitry Andric 
11440b57cec5SDimitry Andric     if (response.IsOKResponse()) {
11450b57cec5SDimitry Andric       m_compression_type = avail_type;
11460b57cec5SDimitry Andric     }
11470b57cec5SDimitry Andric   }
11480b57cec5SDimitry Andric }
11490b57cec5SDimitry Andric 
11500b57cec5SDimitry Andric const char *GDBRemoteCommunicationClient::GetGDBServerProgramName() {
11510b57cec5SDimitry Andric   if (GetGDBServerVersion()) {
11520b57cec5SDimitry Andric     if (!m_gdb_server_name.empty())
11530b57cec5SDimitry Andric       return m_gdb_server_name.c_str();
11540b57cec5SDimitry Andric   }
11550b57cec5SDimitry Andric   return nullptr;
11560b57cec5SDimitry Andric }
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() {
11590b57cec5SDimitry Andric   if (GetGDBServerVersion())
11600b57cec5SDimitry Andric     return m_gdb_server_version;
11610b57cec5SDimitry Andric   return 0;
11620b57cec5SDimitry Andric }
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
11650b57cec5SDimitry Andric   StringExtractorGDBRemote response;
1166fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse("qC", response) != PacketResult::Success)
11670b57cec5SDimitry Andric     return false;
11680b57cec5SDimitry Andric 
11690b57cec5SDimitry Andric   if (!response.IsNormalResponse())
11700b57cec5SDimitry Andric     return false;
11710b57cec5SDimitry Andric 
1172fe6060f1SDimitry Andric   if (response.GetChar() == 'Q' && response.GetChar() == 'C') {
1173fe6060f1SDimitry Andric     auto pid_tid = response.GetPidTid(0);
1174fe6060f1SDimitry Andric     if (!pid_tid)
1175fe6060f1SDimitry Andric       return false;
1176fe6060f1SDimitry Andric 
1177fe6060f1SDimitry Andric     lldb::pid_t pid = pid_tid->first;
1178fe6060f1SDimitry Andric     // invalid
1179fe6060f1SDimitry Andric     if (pid == StringExtractorGDBRemote::AllProcesses)
1180fe6060f1SDimitry Andric       return false;
1181fe6060f1SDimitry Andric 
1182fe6060f1SDimitry Andric     // if we get pid as well, update m_curr_pid
1183fe6060f1SDimitry Andric     if (pid != 0) {
1184fe6060f1SDimitry Andric       m_curr_pid_run = m_curr_pid = pid;
1185fe6060f1SDimitry Andric       m_curr_pid_is_valid = eLazyBoolYes;
1186fe6060f1SDimitry Andric     }
1187fe6060f1SDimitry Andric     tid = pid_tid->second;
1188fe6060f1SDimitry Andric   }
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric   return true;
11910b57cec5SDimitry Andric }
11920b57cec5SDimitry Andric 
11935ffd83dbSDimitry Andric static void ParseOSType(llvm::StringRef value, std::string &os_name,
11945ffd83dbSDimitry Andric                         std::string &environment) {
1195*0fca6ea1SDimitry Andric   if (value == "iossimulator" || value == "tvossimulator" ||
1196*0fca6ea1SDimitry Andric       value == "watchossimulator" || value == "xrossimulator" ||
1197*0fca6ea1SDimitry Andric       value == "visionossimulator") {
11985ffd83dbSDimitry Andric     environment = "simulator";
11995ffd83dbSDimitry Andric     os_name = value.drop_back(environment.size()).str();
1200*0fca6ea1SDimitry Andric   } else if (value == "maccatalyst") {
12015ffd83dbSDimitry Andric     os_name = "ios";
12025ffd83dbSDimitry Andric     environment = "macabi";
12035ffd83dbSDimitry Andric   } else {
12045ffd83dbSDimitry Andric     os_name = value.str();
12055ffd83dbSDimitry Andric   }
12065ffd83dbSDimitry Andric }
12075ffd83dbSDimitry Andric 
12080b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
12091fd87a68SDimitry Andric   Log *log = GetLog(GDBRLog::Process);
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric   if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) {
12120b57cec5SDimitry Andric     // host info computation can require DNS traffic and shelling out to external processes.
12130b57cec5SDimitry Andric     // Increase the timeout to account for that.
12140b57cec5SDimitry Andric     ScopedTimeout timeout(*this, seconds(10));
12150b57cec5SDimitry Andric     m_qHostInfo_is_valid = eLazyBoolNo;
12160b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1217fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("qHostInfo", response) ==
12180b57cec5SDimitry Andric         PacketResult::Success) {
12190b57cec5SDimitry Andric       if (response.IsNormalResponse()) {
12200b57cec5SDimitry Andric         llvm::StringRef name;
12210b57cec5SDimitry Andric         llvm::StringRef value;
12220b57cec5SDimitry Andric         uint32_t cpu = LLDB_INVALID_CPUTYPE;
12230b57cec5SDimitry Andric         uint32_t sub = 0;
12240b57cec5SDimitry Andric         std::string arch_name;
12250b57cec5SDimitry Andric         std::string os_name;
12269dba64beSDimitry Andric         std::string environment;
12270b57cec5SDimitry Andric         std::string vendor_name;
12280b57cec5SDimitry Andric         std::string triple;
12290b57cec5SDimitry Andric         uint32_t pointer_byte_size = 0;
12300b57cec5SDimitry Andric         ByteOrder byte_order = eByteOrderInvalid;
12310b57cec5SDimitry Andric         uint32_t num_keys_decoded = 0;
12320b57cec5SDimitry Andric         while (response.GetNameColonValue(name, value)) {
1233*0fca6ea1SDimitry Andric           if (name == "cputype") {
12340b57cec5SDimitry Andric             // exception type in big endian hex
12350b57cec5SDimitry Andric             if (!value.getAsInteger(0, cpu))
12360b57cec5SDimitry Andric               ++num_keys_decoded;
1237*0fca6ea1SDimitry Andric           } else if (name == "cpusubtype") {
12380b57cec5SDimitry Andric             // exception count in big endian hex
12390b57cec5SDimitry Andric             if (!value.getAsInteger(0, sub))
12400b57cec5SDimitry Andric               ++num_keys_decoded;
1241*0fca6ea1SDimitry Andric           } else if (name == "arch") {
12425ffd83dbSDimitry Andric             arch_name = std::string(value);
12430b57cec5SDimitry Andric             ++num_keys_decoded;
1244*0fca6ea1SDimitry Andric           } else if (name == "triple") {
12450b57cec5SDimitry Andric             StringExtractor extractor(value);
12460b57cec5SDimitry Andric             extractor.GetHexByteString(triple);
12470b57cec5SDimitry Andric             ++num_keys_decoded;
1248*0fca6ea1SDimitry Andric           } else if (name == "distribution_id") {
12490b57cec5SDimitry Andric             StringExtractor extractor(value);
125006c3fb27SDimitry Andric             extractor.GetHexByteString(m_host_distribution_id);
12510b57cec5SDimitry Andric             ++num_keys_decoded;
1252*0fca6ea1SDimitry Andric           } else if (name == "os_build") {
12530b57cec5SDimitry Andric             StringExtractor extractor(value);
12540b57cec5SDimitry Andric             extractor.GetHexByteString(m_os_build);
12550b57cec5SDimitry Andric             ++num_keys_decoded;
1256*0fca6ea1SDimitry Andric           } else if (name == "hostname") {
12570b57cec5SDimitry Andric             StringExtractor extractor(value);
12580b57cec5SDimitry Andric             extractor.GetHexByteString(m_hostname);
12590b57cec5SDimitry Andric             ++num_keys_decoded;
1260*0fca6ea1SDimitry Andric           } else if (name == "os_kernel") {
12610b57cec5SDimitry Andric             StringExtractor extractor(value);
12620b57cec5SDimitry Andric             extractor.GetHexByteString(m_os_kernel);
12630b57cec5SDimitry Andric             ++num_keys_decoded;
1264*0fca6ea1SDimitry Andric           } else if (name == "ostype") {
12655ffd83dbSDimitry Andric             ParseOSType(value, os_name, environment);
12660b57cec5SDimitry Andric             ++num_keys_decoded;
1267*0fca6ea1SDimitry Andric           } else if (name == "vendor") {
12685ffd83dbSDimitry Andric             vendor_name = std::string(value);
12690b57cec5SDimitry Andric             ++num_keys_decoded;
1270*0fca6ea1SDimitry Andric           } else if (name == "endian") {
12710b57cec5SDimitry Andric             byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
12720b57cec5SDimitry Andric                              .Case("little", eByteOrderLittle)
12730b57cec5SDimitry Andric                              .Case("big", eByteOrderBig)
12740b57cec5SDimitry Andric                              .Case("pdp", eByteOrderPDP)
12750b57cec5SDimitry Andric                              .Default(eByteOrderInvalid);
12760b57cec5SDimitry Andric             if (byte_order != eByteOrderInvalid)
12770b57cec5SDimitry Andric               ++num_keys_decoded;
1278*0fca6ea1SDimitry Andric           } else if (name == "ptrsize") {
12790b57cec5SDimitry Andric             if (!value.getAsInteger(0, pointer_byte_size))
12800b57cec5SDimitry Andric               ++num_keys_decoded;
1281*0fca6ea1SDimitry Andric           } else if (name == "addressing_bits") {
12825f757f3fSDimitry Andric             if (!value.getAsInteger(0, m_low_mem_addressing_bits)) {
12835f757f3fSDimitry Andric               ++num_keys_decoded;
12845f757f3fSDimitry Andric             }
1285*0fca6ea1SDimitry Andric           } else if (name == "high_mem_addressing_bits") {
12865f757f3fSDimitry Andric             if (!value.getAsInteger(0, m_high_mem_addressing_bits))
12875f757f3fSDimitry Andric               ++num_keys_decoded;
1288*0fca6ea1SDimitry Andric           } else if (name == "low_mem_addressing_bits") {
12895f757f3fSDimitry Andric             if (!value.getAsInteger(0, m_low_mem_addressing_bits))
1290fe6060f1SDimitry Andric               ++num_keys_decoded;
1291*0fca6ea1SDimitry Andric           } else if (name == "os_version" ||
1292*0fca6ea1SDimitry Andric                      name == "version") // Older debugserver binaries used
1293fe6060f1SDimitry Andric                                         // the "version" key instead of
12940b57cec5SDimitry Andric                                         // "os_version"...
12950b57cec5SDimitry Andric           {
12960b57cec5SDimitry Andric             if (!m_os_version.tryParse(value))
12970b57cec5SDimitry Andric               ++num_keys_decoded;
1298*0fca6ea1SDimitry Andric           } else if (name == "maccatalyst_version") {
12999dba64beSDimitry Andric             if (!m_maccatalyst_version.tryParse(value))
13009dba64beSDimitry Andric               ++num_keys_decoded;
1301*0fca6ea1SDimitry Andric           } else if (name == "watchpoint_exceptions_received") {
13020b57cec5SDimitry Andric             m_watchpoints_trigger_after_instruction =
13030b57cec5SDimitry Andric                 llvm::StringSwitch<LazyBool>(value)
13040b57cec5SDimitry Andric                     .Case("before", eLazyBoolNo)
13050b57cec5SDimitry Andric                     .Case("after", eLazyBoolYes)
13060b57cec5SDimitry Andric                     .Default(eLazyBoolCalculate);
13070b57cec5SDimitry Andric             if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate)
13080b57cec5SDimitry Andric               ++num_keys_decoded;
1309*0fca6ea1SDimitry Andric           } else if (name == "default_packet_timeout") {
13100b57cec5SDimitry Andric             uint32_t timeout_seconds;
13110b57cec5SDimitry Andric             if (!value.getAsInteger(0, timeout_seconds)) {
13120b57cec5SDimitry Andric               m_default_packet_timeout = seconds(timeout_seconds);
13130b57cec5SDimitry Andric               SetPacketTimeout(m_default_packet_timeout);
13140b57cec5SDimitry Andric               ++num_keys_decoded;
13150b57cec5SDimitry Andric             }
1316*0fca6ea1SDimitry Andric           } else if (name == "vm-page-size") {
1317fe6060f1SDimitry Andric             int page_size;
1318fe6060f1SDimitry Andric             if (!value.getAsInteger(0, page_size)) {
1319fe6060f1SDimitry Andric               m_target_vm_page_size = page_size;
1320fe6060f1SDimitry Andric               ++num_keys_decoded;
1321fe6060f1SDimitry Andric             }
13220b57cec5SDimitry Andric           }
13230b57cec5SDimitry Andric         }
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric         if (num_keys_decoded > 0)
13260b57cec5SDimitry Andric           m_qHostInfo_is_valid = eLazyBoolYes;
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric         if (triple.empty()) {
13290b57cec5SDimitry Andric           if (arch_name.empty()) {
13300b57cec5SDimitry Andric             if (cpu != LLDB_INVALID_CPUTYPE) {
13310b57cec5SDimitry Andric               m_host_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
13320b57cec5SDimitry Andric               if (pointer_byte_size) {
13330b57cec5SDimitry Andric                 assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
13340b57cec5SDimitry Andric               }
13350b57cec5SDimitry Andric               if (byte_order != eByteOrderInvalid) {
13360b57cec5SDimitry Andric                 assert(byte_order == m_host_arch.GetByteOrder());
13370b57cec5SDimitry Andric               }
13380b57cec5SDimitry Andric 
13390b57cec5SDimitry Andric               if (!vendor_name.empty())
13400b57cec5SDimitry Andric                 m_host_arch.GetTriple().setVendorName(
13410b57cec5SDimitry Andric                     llvm::StringRef(vendor_name));
13420b57cec5SDimitry Andric               if (!os_name.empty())
13430b57cec5SDimitry Andric                 m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name));
13449dba64beSDimitry Andric               if (!environment.empty())
13459dba64beSDimitry Andric                 m_host_arch.GetTriple().setEnvironmentName(environment);
13460b57cec5SDimitry Andric             }
13470b57cec5SDimitry Andric           } else {
13480b57cec5SDimitry Andric             std::string triple;
13490b57cec5SDimitry Andric             triple += arch_name;
13500b57cec5SDimitry Andric             if (!vendor_name.empty() || !os_name.empty()) {
13510b57cec5SDimitry Andric               triple += '-';
13520b57cec5SDimitry Andric               if (vendor_name.empty())
13530b57cec5SDimitry Andric                 triple += "unknown";
13540b57cec5SDimitry Andric               else
13550b57cec5SDimitry Andric                 triple += vendor_name;
13560b57cec5SDimitry Andric               triple += '-';
13570b57cec5SDimitry Andric               if (os_name.empty())
13580b57cec5SDimitry Andric                 triple += "unknown";
13590b57cec5SDimitry Andric               else
13600b57cec5SDimitry Andric                 triple += os_name;
13610b57cec5SDimitry Andric             }
13620b57cec5SDimitry Andric             m_host_arch.SetTriple(triple.c_str());
13630b57cec5SDimitry Andric 
13640b57cec5SDimitry Andric             llvm::Triple &host_triple = m_host_arch.GetTriple();
13650b57cec5SDimitry Andric             if (host_triple.getVendor() == llvm::Triple::Apple &&
13660b57cec5SDimitry Andric                 host_triple.getOS() == llvm::Triple::Darwin) {
13670b57cec5SDimitry Andric               switch (m_host_arch.GetMachine()) {
13680b57cec5SDimitry Andric               case llvm::Triple::aarch64:
13699dba64beSDimitry Andric               case llvm::Triple::aarch64_32:
13700b57cec5SDimitry Andric               case llvm::Triple::arm:
13710b57cec5SDimitry Andric               case llvm::Triple::thumb:
13720b57cec5SDimitry Andric                 host_triple.setOS(llvm::Triple::IOS);
13730b57cec5SDimitry Andric                 break;
13740b57cec5SDimitry Andric               default:
13750b57cec5SDimitry Andric                 host_triple.setOS(llvm::Triple::MacOSX);
13760b57cec5SDimitry Andric                 break;
13770b57cec5SDimitry Andric               }
13780b57cec5SDimitry Andric             }
13790b57cec5SDimitry Andric             if (pointer_byte_size) {
13800b57cec5SDimitry Andric               assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
13810b57cec5SDimitry Andric             }
13820b57cec5SDimitry Andric             if (byte_order != eByteOrderInvalid) {
13830b57cec5SDimitry Andric               assert(byte_order == m_host_arch.GetByteOrder());
13840b57cec5SDimitry Andric             }
13850b57cec5SDimitry Andric           }
13860b57cec5SDimitry Andric         } else {
13870b57cec5SDimitry Andric           m_host_arch.SetTriple(triple.c_str());
13880b57cec5SDimitry Andric           if (pointer_byte_size) {
13890b57cec5SDimitry Andric             assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
13900b57cec5SDimitry Andric           }
13910b57cec5SDimitry Andric           if (byte_order != eByteOrderInvalid) {
13920b57cec5SDimitry Andric             assert(byte_order == m_host_arch.GetByteOrder());
13930b57cec5SDimitry Andric           }
13940b57cec5SDimitry Andric 
13959dba64beSDimitry Andric           LLDB_LOGF(log,
13969dba64beSDimitry Andric                     "GDBRemoteCommunicationClient::%s parsed host "
13970b57cec5SDimitry Andric                     "architecture as %s, triple as %s from triple text %s",
13989dba64beSDimitry Andric                     __FUNCTION__,
13999dba64beSDimitry Andric                     m_host_arch.GetArchitectureName()
14000b57cec5SDimitry Andric                         ? m_host_arch.GetArchitectureName()
14010b57cec5SDimitry Andric                         : "<null-arch-name>",
14020b57cec5SDimitry Andric                     m_host_arch.GetTriple().getTriple().c_str(),
14030b57cec5SDimitry Andric                     triple.c_str());
14040b57cec5SDimitry Andric         }
14050b57cec5SDimitry Andric       }
14060b57cec5SDimitry Andric     }
14070b57cec5SDimitry Andric   }
14080b57cec5SDimitry Andric   return m_qHostInfo_is_valid == eLazyBoolYes;
14090b57cec5SDimitry Andric }
14100b57cec5SDimitry Andric 
14110b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SendStdinNotification(const char *data,
14120b57cec5SDimitry Andric                                                         size_t data_len) {
14130b57cec5SDimitry Andric   StreamString packet;
14140b57cec5SDimitry Andric   packet.PutCString("I");
14150b57cec5SDimitry Andric   packet.PutBytesAsRawHex8(data, data_len);
14160b57cec5SDimitry Andric   StringExtractorGDBRemote response;
1417fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
14180b57cec5SDimitry Andric       PacketResult::Success) {
14190b57cec5SDimitry Andric     return 0;
14200b57cec5SDimitry Andric   }
14210b57cec5SDimitry Andric   return response.GetError();
14220b57cec5SDimitry Andric }
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric const lldb_private::ArchSpec &
14250b57cec5SDimitry Andric GDBRemoteCommunicationClient::GetHostArchitecture() {
14260b57cec5SDimitry Andric   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
14270b57cec5SDimitry Andric     GetHostInfo();
14280b57cec5SDimitry Andric   return m_host_arch;
14290b57cec5SDimitry Andric }
14300b57cec5SDimitry Andric 
14315f757f3fSDimitry Andric AddressableBits GDBRemoteCommunicationClient::GetAddressableBits() {
14325f757f3fSDimitry Andric   AddressableBits addressable_bits;
1433fe6060f1SDimitry Andric   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1434fe6060f1SDimitry Andric     GetHostInfo();
14355f757f3fSDimitry Andric 
14365f757f3fSDimitry Andric   if (m_low_mem_addressing_bits == m_high_mem_addressing_bits)
14375f757f3fSDimitry Andric     addressable_bits.SetAddressableBits(m_low_mem_addressing_bits);
14385f757f3fSDimitry Andric   else
14395f757f3fSDimitry Andric     addressable_bits.SetAddressableBits(m_low_mem_addressing_bits,
14405f757f3fSDimitry Andric                                         m_high_mem_addressing_bits);
14415f757f3fSDimitry Andric   return addressable_bits;
1442fe6060f1SDimitry Andric }
14435f757f3fSDimitry Andric 
14440b57cec5SDimitry Andric seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() {
14450b57cec5SDimitry Andric   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
14460b57cec5SDimitry Andric     GetHostInfo();
14470b57cec5SDimitry Andric   return m_default_packet_timeout;
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size,
14510b57cec5SDimitry Andric                                                     uint32_t permissions) {
14520b57cec5SDimitry Andric   if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
14530b57cec5SDimitry Andric     m_supports_alloc_dealloc_memory = eLazyBoolYes;
14540b57cec5SDimitry Andric     char packet[64];
14550b57cec5SDimitry Andric     const int packet_len = ::snprintf(
14560b57cec5SDimitry Andric         packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s", (uint64_t)size,
14570b57cec5SDimitry Andric         permissions & lldb::ePermissionsReadable ? "r" : "",
14580b57cec5SDimitry Andric         permissions & lldb::ePermissionsWritable ? "w" : "",
14590b57cec5SDimitry Andric         permissions & lldb::ePermissionsExecutable ? "x" : "");
14600b57cec5SDimitry Andric     assert(packet_len < (int)sizeof(packet));
14610b57cec5SDimitry Andric     UNUSED_IF_ASSERT_DISABLED(packet_len);
14620b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1463fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) ==
14640b57cec5SDimitry Andric         PacketResult::Success) {
14650b57cec5SDimitry Andric       if (response.IsUnsupportedResponse())
14660b57cec5SDimitry Andric         m_supports_alloc_dealloc_memory = eLazyBoolNo;
14670b57cec5SDimitry Andric       else if (!response.IsErrorResponse())
14680b57cec5SDimitry Andric         return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
14690b57cec5SDimitry Andric     } else {
14700b57cec5SDimitry Andric       m_supports_alloc_dealloc_memory = eLazyBoolNo;
14710b57cec5SDimitry Andric     }
14720b57cec5SDimitry Andric   }
14730b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
14740b57cec5SDimitry Andric }
14750b57cec5SDimitry Andric 
14760b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) {
14770b57cec5SDimitry Andric   if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
14780b57cec5SDimitry Andric     m_supports_alloc_dealloc_memory = eLazyBoolYes;
14790b57cec5SDimitry Andric     char packet[64];
14800b57cec5SDimitry Andric     const int packet_len =
14810b57cec5SDimitry Andric         ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
14820b57cec5SDimitry Andric     assert(packet_len < (int)sizeof(packet));
14830b57cec5SDimitry Andric     UNUSED_IF_ASSERT_DISABLED(packet_len);
14840b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1485fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) ==
14860b57cec5SDimitry Andric         PacketResult::Success) {
14870b57cec5SDimitry Andric       if (response.IsUnsupportedResponse())
14880b57cec5SDimitry Andric         m_supports_alloc_dealloc_memory = eLazyBoolNo;
14890b57cec5SDimitry Andric       else if (response.IsOKResponse())
14900b57cec5SDimitry Andric         return true;
14910b57cec5SDimitry Andric     } else {
14920b57cec5SDimitry Andric       m_supports_alloc_dealloc_memory = eLazyBoolNo;
14930b57cec5SDimitry Andric     }
14940b57cec5SDimitry Andric   }
14950b57cec5SDimitry Andric   return false;
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric 
1498349cc55cSDimitry Andric Status GDBRemoteCommunicationClient::Detach(bool keep_stopped,
1499349cc55cSDimitry Andric                                             lldb::pid_t pid) {
15000b57cec5SDimitry Andric   Status error;
1501349cc55cSDimitry Andric   lldb_private::StreamString packet;
15020b57cec5SDimitry Andric 
1503349cc55cSDimitry Andric   packet.PutChar('D');
15040b57cec5SDimitry Andric   if (keep_stopped) {
15050b57cec5SDimitry Andric     if (m_supports_detach_stay_stopped == eLazyBoolCalculate) {
15060b57cec5SDimitry Andric       char packet[64];
15070b57cec5SDimitry Andric       const int packet_len =
15080b57cec5SDimitry Andric           ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
15090b57cec5SDimitry Andric       assert(packet_len < (int)sizeof(packet));
15100b57cec5SDimitry Andric       UNUSED_IF_ASSERT_DISABLED(packet_len);
15110b57cec5SDimitry Andric       StringExtractorGDBRemote response;
1512fe6060f1SDimitry Andric       if (SendPacketAndWaitForResponse(packet, response) ==
15130b57cec5SDimitry Andric               PacketResult::Success &&
15140b57cec5SDimitry Andric           response.IsOKResponse()) {
15150b57cec5SDimitry Andric         m_supports_detach_stay_stopped = eLazyBoolYes;
15160b57cec5SDimitry Andric       } else {
15170b57cec5SDimitry Andric         m_supports_detach_stay_stopped = eLazyBoolNo;
15180b57cec5SDimitry Andric       }
15190b57cec5SDimitry Andric     }
15200b57cec5SDimitry Andric 
15210b57cec5SDimitry Andric     if (m_supports_detach_stay_stopped == eLazyBoolNo) {
15220b57cec5SDimitry Andric       error.SetErrorString("Stays stopped not supported by this target.");
15230b57cec5SDimitry Andric       return error;
15240b57cec5SDimitry Andric     } else {
1525349cc55cSDimitry Andric       packet.PutChar('1');
15260b57cec5SDimitry Andric     }
15270b57cec5SDimitry Andric   }
1528349cc55cSDimitry Andric 
1529bdd1243dSDimitry Andric   if (GetMultiprocessSupported()) {
1530349cc55cSDimitry Andric     // Some servers (e.g. qemu) require specifying the PID even if only a single
1531349cc55cSDimitry Andric     // process is running.
1532349cc55cSDimitry Andric     if (pid == LLDB_INVALID_PROCESS_ID)
1533349cc55cSDimitry Andric       pid = GetCurrentProcessID();
1534349cc55cSDimitry Andric     packet.PutChar(';');
1535349cc55cSDimitry Andric     packet.PutHex64(pid);
1536349cc55cSDimitry Andric   } else if (pid != LLDB_INVALID_PROCESS_ID) {
1537349cc55cSDimitry Andric     error.SetErrorString("Multiprocess extension not supported by the server.");
1538349cc55cSDimitry Andric     return error;
1539349cc55cSDimitry Andric   }
1540349cc55cSDimitry Andric 
1541349cc55cSDimitry Andric   StringExtractorGDBRemote response;
1542349cc55cSDimitry Andric   PacketResult packet_result =
1543349cc55cSDimitry Andric       SendPacketAndWaitForResponse(packet.GetString(), response);
1544349cc55cSDimitry Andric   if (packet_result != PacketResult::Success)
1545349cc55cSDimitry Andric     error.SetErrorString("Sending isconnect packet failed.");
15460b57cec5SDimitry Andric   return error;
15470b57cec5SDimitry Andric }
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
15500b57cec5SDimitry Andric     lldb::addr_t addr, lldb_private::MemoryRegionInfo &region_info) {
15510b57cec5SDimitry Andric   Status error;
15520b57cec5SDimitry Andric   region_info.Clear();
15530b57cec5SDimitry Andric 
15540b57cec5SDimitry Andric   if (m_supports_memory_region_info != eLazyBoolNo) {
15550b57cec5SDimitry Andric     m_supports_memory_region_info = eLazyBoolYes;
15560b57cec5SDimitry Andric     char packet[64];
15570b57cec5SDimitry Andric     const int packet_len = ::snprintf(
15580b57cec5SDimitry Andric         packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
15590b57cec5SDimitry Andric     assert(packet_len < (int)sizeof(packet));
15600b57cec5SDimitry Andric     UNUSED_IF_ASSERT_DISABLED(packet_len);
15610b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1562fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) ==
15630b57cec5SDimitry Andric             PacketResult::Success &&
15640b57cec5SDimitry Andric         response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
15650b57cec5SDimitry Andric       llvm::StringRef name;
15660b57cec5SDimitry Andric       llvm::StringRef value;
15670b57cec5SDimitry Andric       addr_t addr_value = LLDB_INVALID_ADDRESS;
15680b57cec5SDimitry Andric       bool success = true;
15690b57cec5SDimitry Andric       bool saw_permissions = false;
15700b57cec5SDimitry Andric       while (success && response.GetNameColonValue(name, value)) {
1571*0fca6ea1SDimitry Andric         if (name == "start") {
15720b57cec5SDimitry Andric           if (!value.getAsInteger(16, addr_value))
15730b57cec5SDimitry Andric             region_info.GetRange().SetRangeBase(addr_value);
1574*0fca6ea1SDimitry Andric         } else if (name == "size") {
1575bdd1243dSDimitry Andric           if (!value.getAsInteger(16, addr_value)) {
15760b57cec5SDimitry Andric             region_info.GetRange().SetByteSize(addr_value);
1577bdd1243dSDimitry Andric             if (region_info.GetRange().GetRangeEnd() <
1578bdd1243dSDimitry Andric                 region_info.GetRange().GetRangeBase()) {
1579bdd1243dSDimitry Andric               // Range size overflowed, truncate it.
1580bdd1243dSDimitry Andric               region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
1581bdd1243dSDimitry Andric             }
1582bdd1243dSDimitry Andric           }
1583*0fca6ea1SDimitry Andric         } else if (name == "permissions" && region_info.GetRange().IsValid()) {
15840b57cec5SDimitry Andric           saw_permissions = true;
15850b57cec5SDimitry Andric           if (region_info.GetRange().Contains(addr)) {
1586349cc55cSDimitry Andric             if (value.contains('r'))
15870b57cec5SDimitry Andric               region_info.SetReadable(MemoryRegionInfo::eYes);
15880b57cec5SDimitry Andric             else
15890b57cec5SDimitry Andric               region_info.SetReadable(MemoryRegionInfo::eNo);
15900b57cec5SDimitry Andric 
1591349cc55cSDimitry Andric             if (value.contains('w'))
15920b57cec5SDimitry Andric               region_info.SetWritable(MemoryRegionInfo::eYes);
15930b57cec5SDimitry Andric             else
15940b57cec5SDimitry Andric               region_info.SetWritable(MemoryRegionInfo::eNo);
15950b57cec5SDimitry Andric 
1596349cc55cSDimitry Andric             if (value.contains('x'))
15970b57cec5SDimitry Andric               region_info.SetExecutable(MemoryRegionInfo::eYes);
15980b57cec5SDimitry Andric             else
15990b57cec5SDimitry Andric               region_info.SetExecutable(MemoryRegionInfo::eNo);
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric             region_info.SetMapped(MemoryRegionInfo::eYes);
16020b57cec5SDimitry Andric           } else {
16030b57cec5SDimitry Andric             // The reported region does not contain this address -- we're
16040b57cec5SDimitry Andric             // looking at an unmapped page
16050b57cec5SDimitry Andric             region_info.SetReadable(MemoryRegionInfo::eNo);
16060b57cec5SDimitry Andric             region_info.SetWritable(MemoryRegionInfo::eNo);
16070b57cec5SDimitry Andric             region_info.SetExecutable(MemoryRegionInfo::eNo);
16080b57cec5SDimitry Andric             region_info.SetMapped(MemoryRegionInfo::eNo);
16090b57cec5SDimitry Andric           }
1610*0fca6ea1SDimitry Andric         } else if (name == "name") {
16110b57cec5SDimitry Andric           StringExtractorGDBRemote name_extractor(value);
16120b57cec5SDimitry Andric           std::string name;
16130b57cec5SDimitry Andric           name_extractor.GetHexByteString(name);
16140b57cec5SDimitry Andric           region_info.SetName(name.c_str());
1615*0fca6ea1SDimitry Andric         } else if (name == "flags") {
1616e8d8bef9SDimitry Andric           region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
1617e8d8bef9SDimitry Andric 
1618e8d8bef9SDimitry Andric           llvm::StringRef flags = value;
1619e8d8bef9SDimitry Andric           llvm::StringRef flag;
1620e8d8bef9SDimitry Andric           while (flags.size()) {
1621e8d8bef9SDimitry Andric             flags = flags.ltrim();
1622e8d8bef9SDimitry Andric             std::tie(flag, flags) = flags.split(' ');
1623e8d8bef9SDimitry Andric             // To account for trailing whitespace
1624e8d8bef9SDimitry Andric             if (flag.size()) {
1625e8d8bef9SDimitry Andric               if (flag == "mt") {
1626e8d8bef9SDimitry Andric                 region_info.SetMemoryTagged(MemoryRegionInfo::eYes);
1627e8d8bef9SDimitry Andric                 break;
1628e8d8bef9SDimitry Andric               }
1629e8d8bef9SDimitry Andric             }
1630e8d8bef9SDimitry Andric           }
1631*0fca6ea1SDimitry Andric         } else if (name == "type") {
1632349cc55cSDimitry Andric           std::string comma_sep_str = value.str();
1633349cc55cSDimitry Andric           size_t comma_pos;
1634349cc55cSDimitry Andric           while ((comma_pos = comma_sep_str.find(',')) != std::string::npos) {
1635349cc55cSDimitry Andric             comma_sep_str[comma_pos] = '\0';
1636349cc55cSDimitry Andric             if (comma_sep_str == "stack") {
1637349cc55cSDimitry Andric               region_info.SetIsStackMemory(MemoryRegionInfo::eYes);
1638349cc55cSDimitry Andric             }
1639349cc55cSDimitry Andric           }
1640349cc55cSDimitry Andric           // handle final (or only) type of "stack"
1641349cc55cSDimitry Andric           if (comma_sep_str == "stack") {
1642349cc55cSDimitry Andric             region_info.SetIsStackMemory(MemoryRegionInfo::eYes);
1643349cc55cSDimitry Andric           }
1644*0fca6ea1SDimitry Andric         } else if (name == "error") {
16450b57cec5SDimitry Andric           StringExtractorGDBRemote error_extractor(value);
16460b57cec5SDimitry Andric           std::string error_string;
16470b57cec5SDimitry Andric           // Now convert the HEX bytes into a string value
16480b57cec5SDimitry Andric           error_extractor.GetHexByteString(error_string);
16490b57cec5SDimitry Andric           error.SetErrorString(error_string.c_str());
1650*0fca6ea1SDimitry Andric         } else if (name == "dirty-pages") {
1651fe6060f1SDimitry Andric           std::vector<addr_t> dirty_page_list;
1652349cc55cSDimitry Andric           for (llvm::StringRef x : llvm::split(value, ',')) {
1653fe6060f1SDimitry Andric             addr_t page;
1654349cc55cSDimitry Andric             x.consume_front("0x");
1655349cc55cSDimitry Andric             if (llvm::to_integer(x, page, 16))
1656fe6060f1SDimitry Andric               dirty_page_list.push_back(page);
1657fe6060f1SDimitry Andric           }
1658fe6060f1SDimitry Andric           region_info.SetDirtyPageList(dirty_page_list);
16590b57cec5SDimitry Andric         }
16600b57cec5SDimitry Andric       }
16610b57cec5SDimitry Andric 
1662fe6060f1SDimitry Andric       if (m_target_vm_page_size != 0)
1663fe6060f1SDimitry Andric         region_info.SetPageSize(m_target_vm_page_size);
1664fe6060f1SDimitry Andric 
16650b57cec5SDimitry Andric       if (region_info.GetRange().IsValid()) {
16660b57cec5SDimitry Andric         // We got a valid address range back but no permissions -- which means
16670b57cec5SDimitry Andric         // this is an unmapped page
16680b57cec5SDimitry Andric         if (!saw_permissions) {
16690b57cec5SDimitry Andric           region_info.SetReadable(MemoryRegionInfo::eNo);
16700b57cec5SDimitry Andric           region_info.SetWritable(MemoryRegionInfo::eNo);
16710b57cec5SDimitry Andric           region_info.SetExecutable(MemoryRegionInfo::eNo);
16720b57cec5SDimitry Andric           region_info.SetMapped(MemoryRegionInfo::eNo);
16730b57cec5SDimitry Andric         }
16740b57cec5SDimitry Andric       } else {
16750b57cec5SDimitry Andric         // We got an invalid address range back
16760b57cec5SDimitry Andric         error.SetErrorString("Server returned invalid range");
16770b57cec5SDimitry Andric       }
16780b57cec5SDimitry Andric     } else {
16790b57cec5SDimitry Andric       m_supports_memory_region_info = eLazyBoolNo;
16800b57cec5SDimitry Andric     }
16810b57cec5SDimitry Andric   }
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric   if (m_supports_memory_region_info == eLazyBoolNo) {
16840b57cec5SDimitry Andric     error.SetErrorString("qMemoryRegionInfo is not supported");
16850b57cec5SDimitry Andric   }
16860b57cec5SDimitry Andric 
16870b57cec5SDimitry Andric   // Try qXfer:memory-map:read to get region information not included in
16880b57cec5SDimitry Andric   // qMemoryRegionInfo
16890b57cec5SDimitry Andric   MemoryRegionInfo qXfer_region_info;
16900b57cec5SDimitry Andric   Status qXfer_error = GetQXferMemoryMapRegionInfo(addr, qXfer_region_info);
16910b57cec5SDimitry Andric 
16920b57cec5SDimitry Andric   if (error.Fail()) {
16930b57cec5SDimitry Andric     // If qMemoryRegionInfo failed, but qXfer:memory-map:read succeeded, use
16940b57cec5SDimitry Andric     // the qXfer result as a fallback
16950b57cec5SDimitry Andric     if (qXfer_error.Success()) {
16960b57cec5SDimitry Andric       region_info = qXfer_region_info;
16970b57cec5SDimitry Andric       error.Clear();
16980b57cec5SDimitry Andric     } else {
16990b57cec5SDimitry Andric       region_info.Clear();
17000b57cec5SDimitry Andric     }
17010b57cec5SDimitry Andric   } else if (qXfer_error.Success()) {
17020b57cec5SDimitry Andric     // If both qMemoryRegionInfo and qXfer:memory-map:read succeeded, and if
17030b57cec5SDimitry Andric     // both regions are the same range, update the result to include the flash-
17040b57cec5SDimitry Andric     // memory information that is specific to the qXfer result.
17050b57cec5SDimitry Andric     if (region_info.GetRange() == qXfer_region_info.GetRange()) {
17060b57cec5SDimitry Andric       region_info.SetFlash(qXfer_region_info.GetFlash());
17070b57cec5SDimitry Andric       region_info.SetBlocksize(qXfer_region_info.GetBlocksize());
17080b57cec5SDimitry Andric     }
17090b57cec5SDimitry Andric   }
17100b57cec5SDimitry Andric   return error;
17110b57cec5SDimitry Andric }
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric Status GDBRemoteCommunicationClient::GetQXferMemoryMapRegionInfo(
17140b57cec5SDimitry Andric     lldb::addr_t addr, MemoryRegionInfo &region) {
17150b57cec5SDimitry Andric   Status error = LoadQXferMemoryMap();
17160b57cec5SDimitry Andric   if (!error.Success())
17170b57cec5SDimitry Andric     return error;
17180b57cec5SDimitry Andric   for (const auto &map_region : m_qXfer_memory_map) {
17190b57cec5SDimitry Andric     if (map_region.GetRange().Contains(addr)) {
17200b57cec5SDimitry Andric       region = map_region;
17210b57cec5SDimitry Andric       return error;
17220b57cec5SDimitry Andric     }
17230b57cec5SDimitry Andric   }
17240b57cec5SDimitry Andric   error.SetErrorString("Region not found");
17250b57cec5SDimitry Andric   return error;
17260b57cec5SDimitry Andric }
17270b57cec5SDimitry Andric 
17280b57cec5SDimitry Andric Status GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
17290b57cec5SDimitry Andric 
17300b57cec5SDimitry Andric   Status error;
17310b57cec5SDimitry Andric 
17320b57cec5SDimitry Andric   if (m_qXfer_memory_map_loaded)
17330b57cec5SDimitry Andric     // Already loaded, return success
17340b57cec5SDimitry Andric     return error;
17350b57cec5SDimitry Andric 
17360b57cec5SDimitry Andric   if (!XMLDocument::XMLEnabled()) {
17370b57cec5SDimitry Andric     error.SetErrorString("XML is not supported");
17380b57cec5SDimitry Andric     return error;
17390b57cec5SDimitry Andric   }
17400b57cec5SDimitry Andric 
17410b57cec5SDimitry Andric   if (!GetQXferMemoryMapReadSupported()) {
17420b57cec5SDimitry Andric     error.SetErrorString("Memory map is not supported");
17430b57cec5SDimitry Andric     return error;
17440b57cec5SDimitry Andric   }
17450b57cec5SDimitry Andric 
1746349cc55cSDimitry Andric   llvm::Expected<std::string> xml = ReadExtFeature("memory-map", "");
1747349cc55cSDimitry Andric   if (!xml)
1748349cc55cSDimitry Andric     return Status(xml.takeError());
17490b57cec5SDimitry Andric 
17500b57cec5SDimitry Andric   XMLDocument xml_document;
17510b57cec5SDimitry Andric 
1752349cc55cSDimitry Andric   if (!xml_document.ParseMemory(xml->c_str(), xml->size())) {
17530b57cec5SDimitry Andric     error.SetErrorString("Failed to parse memory map xml");
17540b57cec5SDimitry Andric     return error;
17550b57cec5SDimitry Andric   }
17560b57cec5SDimitry Andric 
17570b57cec5SDimitry Andric   XMLNode map_node = xml_document.GetRootElement("memory-map");
17580b57cec5SDimitry Andric   if (!map_node) {
17590b57cec5SDimitry Andric     error.SetErrorString("Invalid root node in memory map xml");
17600b57cec5SDimitry Andric     return error;
17610b57cec5SDimitry Andric   }
17620b57cec5SDimitry Andric 
17630b57cec5SDimitry Andric   m_qXfer_memory_map.clear();
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric   map_node.ForEachChildElement([this](const XMLNode &memory_node) -> bool {
17660b57cec5SDimitry Andric     if (!memory_node.IsElement())
17670b57cec5SDimitry Andric       return true;
17680b57cec5SDimitry Andric     if (memory_node.GetName() != "memory")
17690b57cec5SDimitry Andric       return true;
17700b57cec5SDimitry Andric     auto type = memory_node.GetAttributeValue("type", "");
17710b57cec5SDimitry Andric     uint64_t start;
17720b57cec5SDimitry Andric     uint64_t length;
17730b57cec5SDimitry Andric     if (!memory_node.GetAttributeValueAsUnsigned("start", start))
17740b57cec5SDimitry Andric       return true;
17750b57cec5SDimitry Andric     if (!memory_node.GetAttributeValueAsUnsigned("length", length))
17760b57cec5SDimitry Andric       return true;
17770b57cec5SDimitry Andric     MemoryRegionInfo region;
17780b57cec5SDimitry Andric     region.GetRange().SetRangeBase(start);
17790b57cec5SDimitry Andric     region.GetRange().SetByteSize(length);
17800b57cec5SDimitry Andric     if (type == "rom") {
17810b57cec5SDimitry Andric       region.SetReadable(MemoryRegionInfo::eYes);
17820b57cec5SDimitry Andric       this->m_qXfer_memory_map.push_back(region);
17830b57cec5SDimitry Andric     } else if (type == "ram") {
17840b57cec5SDimitry Andric       region.SetReadable(MemoryRegionInfo::eYes);
17850b57cec5SDimitry Andric       region.SetWritable(MemoryRegionInfo::eYes);
17860b57cec5SDimitry Andric       this->m_qXfer_memory_map.push_back(region);
17870b57cec5SDimitry Andric     } else if (type == "flash") {
17880b57cec5SDimitry Andric       region.SetFlash(MemoryRegionInfo::eYes);
17890b57cec5SDimitry Andric       memory_node.ForEachChildElement(
17900b57cec5SDimitry Andric           [&region](const XMLNode &prop_node) -> bool {
17910b57cec5SDimitry Andric             if (!prop_node.IsElement())
17920b57cec5SDimitry Andric               return true;
17930b57cec5SDimitry Andric             if (prop_node.GetName() != "property")
17940b57cec5SDimitry Andric               return true;
17950b57cec5SDimitry Andric             auto propname = prop_node.GetAttributeValue("name", "");
17960b57cec5SDimitry Andric             if (propname == "blocksize") {
17970b57cec5SDimitry Andric               uint64_t blocksize;
17980b57cec5SDimitry Andric               if (prop_node.GetElementTextAsUnsigned(blocksize))
17990b57cec5SDimitry Andric                 region.SetBlocksize(blocksize);
18000b57cec5SDimitry Andric             }
18010b57cec5SDimitry Andric             return true;
18020b57cec5SDimitry Andric           });
18030b57cec5SDimitry Andric       this->m_qXfer_memory_map.push_back(region);
18040b57cec5SDimitry Andric     }
18050b57cec5SDimitry Andric     return true;
18060b57cec5SDimitry Andric   });
18070b57cec5SDimitry Andric 
18080b57cec5SDimitry Andric   m_qXfer_memory_map_loaded = true;
18090b57cec5SDimitry Andric 
18100b57cec5SDimitry Andric   return error;
18110b57cec5SDimitry Andric }
18120b57cec5SDimitry Andric 
181306c3fb27SDimitry Andric std::optional<uint32_t> GDBRemoteCommunicationClient::GetWatchpointSlotCount() {
18140b57cec5SDimitry Andric   if (m_supports_watchpoint_support_info == eLazyBoolYes) {
181506c3fb27SDimitry Andric     return m_num_supported_hardware_watchpoints;
18160b57cec5SDimitry Andric   }
18170b57cec5SDimitry Andric 
181806c3fb27SDimitry Andric   std::optional<uint32_t> num;
18190b57cec5SDimitry Andric   if (m_supports_watchpoint_support_info != eLazyBoolNo) {
18200b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1821fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) ==
1822fe6060f1SDimitry Andric         PacketResult::Success) {
18230b57cec5SDimitry Andric       m_supports_watchpoint_support_info = eLazyBoolYes;
18240b57cec5SDimitry Andric       llvm::StringRef name;
18250b57cec5SDimitry Andric       llvm::StringRef value;
18260b57cec5SDimitry Andric       while (response.GetNameColonValue(name, value)) {
1827*0fca6ea1SDimitry Andric         if (name == "num") {
18280b57cec5SDimitry Andric           value.getAsInteger(0, m_num_supported_hardware_watchpoints);
18290b57cec5SDimitry Andric           num = m_num_supported_hardware_watchpoints;
18300b57cec5SDimitry Andric         }
18310b57cec5SDimitry Andric       }
183206c3fb27SDimitry Andric       if (!num) {
18330b57cec5SDimitry Andric         m_supports_watchpoint_support_info = eLazyBoolNo;
18340b57cec5SDimitry Andric       }
18350b57cec5SDimitry Andric     } else {
18360b57cec5SDimitry Andric       m_supports_watchpoint_support_info = eLazyBoolNo;
18370b57cec5SDimitry Andric     }
18380b57cec5SDimitry Andric   }
18390b57cec5SDimitry Andric 
184006c3fb27SDimitry Andric   return num;
18410b57cec5SDimitry Andric }
18420b57cec5SDimitry Andric 
1843*0fca6ea1SDimitry Andric WatchpointHardwareFeature
1844*0fca6ea1SDimitry Andric GDBRemoteCommunicationClient::GetSupportedWatchpointTypes() {
1845*0fca6ea1SDimitry Andric   return m_watchpoint_types;
1846*0fca6ea1SDimitry Andric }
1847*0fca6ea1SDimitry Andric 
184806c3fb27SDimitry Andric std::optional<bool> GDBRemoteCommunicationClient::GetWatchpointReportedAfter() {
184906c3fb27SDimitry Andric   if (m_qHostInfo_is_valid == eLazyBoolCalculate)
185006c3fb27SDimitry Andric     GetHostInfo();
185106c3fb27SDimitry Andric 
185206c3fb27SDimitry Andric   // Process determines this by target CPU, but allow for the
185306c3fb27SDimitry Andric   // remote stub to override it via the qHostInfo
185406c3fb27SDimitry Andric   // watchpoint_exceptions_received key, if it is present.
185506c3fb27SDimitry Andric   if (m_qHostInfo_is_valid == eLazyBoolYes) {
185606c3fb27SDimitry Andric     if (m_watchpoints_trigger_after_instruction == eLazyBoolNo)
185706c3fb27SDimitry Andric       return false;
185806c3fb27SDimitry Andric     if (m_watchpoints_trigger_after_instruction == eLazyBoolYes)
185906c3fb27SDimitry Andric       return true;
18600b57cec5SDimitry Andric   }
18610b57cec5SDimitry Andric 
186206c3fb27SDimitry Andric   return std::nullopt;
18630b57cec5SDimitry Andric }
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) {
18660b57cec5SDimitry Andric   if (file_spec) {
18670b57cec5SDimitry Andric     std::string path{file_spec.GetPath(false)};
18680b57cec5SDimitry Andric     StreamString packet;
18690b57cec5SDimitry Andric     packet.PutCString("QSetSTDIN:");
18700b57cec5SDimitry Andric     packet.PutStringAsRawHex8(path);
18710b57cec5SDimitry Andric 
18720b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1873fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
18740b57cec5SDimitry Andric         PacketResult::Success) {
18750b57cec5SDimitry Andric       if (response.IsOKResponse())
18760b57cec5SDimitry Andric         return 0;
18770b57cec5SDimitry Andric       uint8_t error = response.GetError();
18780b57cec5SDimitry Andric       if (error)
18790b57cec5SDimitry Andric         return error;
18800b57cec5SDimitry Andric     }
18810b57cec5SDimitry Andric   }
18820b57cec5SDimitry Andric   return -1;
18830b57cec5SDimitry Andric }
18840b57cec5SDimitry Andric 
18850b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) {
18860b57cec5SDimitry Andric   if (file_spec) {
18870b57cec5SDimitry Andric     std::string path{file_spec.GetPath(false)};
18880b57cec5SDimitry Andric     StreamString packet;
18890b57cec5SDimitry Andric     packet.PutCString("QSetSTDOUT:");
18900b57cec5SDimitry Andric     packet.PutStringAsRawHex8(path);
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1893fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
18940b57cec5SDimitry Andric         PacketResult::Success) {
18950b57cec5SDimitry Andric       if (response.IsOKResponse())
18960b57cec5SDimitry Andric         return 0;
18970b57cec5SDimitry Andric       uint8_t error = response.GetError();
18980b57cec5SDimitry Andric       if (error)
18990b57cec5SDimitry Andric         return error;
19000b57cec5SDimitry Andric     }
19010b57cec5SDimitry Andric   }
19020b57cec5SDimitry Andric   return -1;
19030b57cec5SDimitry Andric }
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) {
19060b57cec5SDimitry Andric   if (file_spec) {
19070b57cec5SDimitry Andric     std::string path{file_spec.GetPath(false)};
19080b57cec5SDimitry Andric     StreamString packet;
19090b57cec5SDimitry Andric     packet.PutCString("QSetSTDERR:");
19100b57cec5SDimitry Andric     packet.PutStringAsRawHex8(path);
19110b57cec5SDimitry Andric 
19120b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1913fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
19140b57cec5SDimitry Andric         PacketResult::Success) {
19150b57cec5SDimitry Andric       if (response.IsOKResponse())
19160b57cec5SDimitry Andric         return 0;
19170b57cec5SDimitry Andric       uint8_t error = response.GetError();
19180b57cec5SDimitry Andric       if (error)
19190b57cec5SDimitry Andric         return error;
19200b57cec5SDimitry Andric     }
19210b57cec5SDimitry Andric   }
19220b57cec5SDimitry Andric   return -1;
19230b57cec5SDimitry Andric }
19240b57cec5SDimitry Andric 
19250b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
19260b57cec5SDimitry Andric   StringExtractorGDBRemote response;
1927fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse("qGetWorkingDir", response) ==
19280b57cec5SDimitry Andric       PacketResult::Success) {
19290b57cec5SDimitry Andric     if (response.IsUnsupportedResponse())
19300b57cec5SDimitry Andric       return false;
19310b57cec5SDimitry Andric     if (response.IsErrorResponse())
19320b57cec5SDimitry Andric       return false;
19330b57cec5SDimitry Andric     std::string cwd;
19340b57cec5SDimitry Andric     response.GetHexByteString(cwd);
19350b57cec5SDimitry Andric     working_dir.SetFile(cwd, GetHostArchitecture().GetTriple());
19360b57cec5SDimitry Andric     return !cwd.empty();
19370b57cec5SDimitry Andric   }
19380b57cec5SDimitry Andric   return false;
19390b57cec5SDimitry Andric }
19400b57cec5SDimitry Andric 
19410b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) {
19420b57cec5SDimitry Andric   if (working_dir) {
19430b57cec5SDimitry Andric     std::string path{working_dir.GetPath(false)};
19440b57cec5SDimitry Andric     StreamString packet;
19450b57cec5SDimitry Andric     packet.PutCString("QSetWorkingDir:");
19460b57cec5SDimitry Andric     packet.PutStringAsRawHex8(path);
19470b57cec5SDimitry Andric 
19480b57cec5SDimitry Andric     StringExtractorGDBRemote response;
1949fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
19500b57cec5SDimitry Andric         PacketResult::Success) {
19510b57cec5SDimitry Andric       if (response.IsOKResponse())
19520b57cec5SDimitry Andric         return 0;
19530b57cec5SDimitry Andric       uint8_t error = response.GetError();
19540b57cec5SDimitry Andric       if (error)
19550b57cec5SDimitry Andric         return error;
19560b57cec5SDimitry Andric     }
19570b57cec5SDimitry Andric   }
19580b57cec5SDimitry Andric   return -1;
19590b57cec5SDimitry Andric }
19600b57cec5SDimitry Andric 
19610b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) {
19620b57cec5SDimitry Andric   char packet[32];
19630b57cec5SDimitry Andric   const int packet_len =
19640b57cec5SDimitry Andric       ::snprintf(packet, sizeof(packet), "QSetDisableASLR:%i", enable ? 1 : 0);
19650b57cec5SDimitry Andric   assert(packet_len < (int)sizeof(packet));
19660b57cec5SDimitry Andric   UNUSED_IF_ASSERT_DISABLED(packet_len);
19670b57cec5SDimitry Andric   StringExtractorGDBRemote response;
1968fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
19690b57cec5SDimitry Andric     if (response.IsOKResponse())
19700b57cec5SDimitry Andric       return 0;
19710b57cec5SDimitry Andric     uint8_t error = response.GetError();
19720b57cec5SDimitry Andric     if (error)
19730b57cec5SDimitry Andric       return error;
19740b57cec5SDimitry Andric   }
19750b57cec5SDimitry Andric   return -1;
19760b57cec5SDimitry Andric }
19770b57cec5SDimitry Andric 
19780b57cec5SDimitry Andric int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) {
19790b57cec5SDimitry Andric   char packet[32];
19800b57cec5SDimitry Andric   const int packet_len = ::snprintf(packet, sizeof(packet),
19810b57cec5SDimitry Andric                                     "QSetDetachOnError:%i", enable ? 1 : 0);
19820b57cec5SDimitry Andric   assert(packet_len < (int)sizeof(packet));
19830b57cec5SDimitry Andric   UNUSED_IF_ASSERT_DISABLED(packet_len);
19840b57cec5SDimitry Andric   StringExtractorGDBRemote response;
1985fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) {
19860b57cec5SDimitry Andric     if (response.IsOKResponse())
19870b57cec5SDimitry Andric       return 0;
19880b57cec5SDimitry Andric     uint8_t error = response.GetError();
19890b57cec5SDimitry Andric     if (error)
19900b57cec5SDimitry Andric       return error;
19910b57cec5SDimitry Andric   }
19920b57cec5SDimitry Andric   return -1;
19930b57cec5SDimitry Andric }
19940b57cec5SDimitry Andric 
19950b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
19960b57cec5SDimitry Andric     StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) {
19970b57cec5SDimitry Andric   if (response.IsNormalResponse()) {
19980b57cec5SDimitry Andric     llvm::StringRef name;
19990b57cec5SDimitry Andric     llvm::StringRef value;
20000b57cec5SDimitry Andric     StringExtractor extractor;
20010b57cec5SDimitry Andric 
20020b57cec5SDimitry Andric     uint32_t cpu = LLDB_INVALID_CPUTYPE;
20030b57cec5SDimitry Andric     uint32_t sub = 0;
20040b57cec5SDimitry Andric     std::string vendor;
20050b57cec5SDimitry Andric     std::string os_type;
20060b57cec5SDimitry Andric 
20070b57cec5SDimitry Andric     while (response.GetNameColonValue(name, value)) {
2008*0fca6ea1SDimitry Andric       if (name == "pid") {
20090b57cec5SDimitry Andric         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
20100b57cec5SDimitry Andric         value.getAsInteger(0, pid);
20110b57cec5SDimitry Andric         process_info.SetProcessID(pid);
2012*0fca6ea1SDimitry Andric       } else if (name == "ppid") {
20130b57cec5SDimitry Andric         lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
20140b57cec5SDimitry Andric         value.getAsInteger(0, pid);
20150b57cec5SDimitry Andric         process_info.SetParentProcessID(pid);
2016*0fca6ea1SDimitry Andric       } else if (name == "uid") {
20170b57cec5SDimitry Andric         uint32_t uid = UINT32_MAX;
20180b57cec5SDimitry Andric         value.getAsInteger(0, uid);
20190b57cec5SDimitry Andric         process_info.SetUserID(uid);
2020*0fca6ea1SDimitry Andric       } else if (name == "euid") {
20210b57cec5SDimitry Andric         uint32_t uid = UINT32_MAX;
20220b57cec5SDimitry Andric         value.getAsInteger(0, uid);
20239dba64beSDimitry Andric         process_info.SetEffectiveUserID(uid);
2024*0fca6ea1SDimitry Andric       } else if (name == "gid") {
20250b57cec5SDimitry Andric         uint32_t gid = UINT32_MAX;
20260b57cec5SDimitry Andric         value.getAsInteger(0, gid);
20270b57cec5SDimitry Andric         process_info.SetGroupID(gid);
2028*0fca6ea1SDimitry Andric       } else if (name == "egid") {
20290b57cec5SDimitry Andric         uint32_t gid = UINT32_MAX;
20300b57cec5SDimitry Andric         value.getAsInteger(0, gid);
20310b57cec5SDimitry Andric         process_info.SetEffectiveGroupID(gid);
2032*0fca6ea1SDimitry Andric       } else if (name == "triple") {
20330b57cec5SDimitry Andric         StringExtractor extractor(value);
20340b57cec5SDimitry Andric         std::string triple;
20350b57cec5SDimitry Andric         extractor.GetHexByteString(triple);
20360b57cec5SDimitry Andric         process_info.GetArchitecture().SetTriple(triple.c_str());
2037*0fca6ea1SDimitry Andric       } else if (name == "name") {
20380b57cec5SDimitry Andric         StringExtractor extractor(value);
20390b57cec5SDimitry Andric         // The process name from ASCII hex bytes since we can't control the
20400b57cec5SDimitry Andric         // characters in a process name
20410b57cec5SDimitry Andric         std::string name;
20420b57cec5SDimitry Andric         extractor.GetHexByteString(name);
20430b57cec5SDimitry Andric         process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);
2044*0fca6ea1SDimitry Andric       } else if (name == "args") {
20459dba64beSDimitry Andric         llvm::StringRef encoded_args(value), hex_arg;
20469dba64beSDimitry Andric 
20479dba64beSDimitry Andric         bool is_arg0 = true;
20489dba64beSDimitry Andric         while (!encoded_args.empty()) {
20499dba64beSDimitry Andric           std::tie(hex_arg, encoded_args) = encoded_args.split('-');
20509dba64beSDimitry Andric           std::string arg;
20519dba64beSDimitry Andric           StringExtractor extractor(hex_arg);
20529dba64beSDimitry Andric           if (extractor.GetHexByteString(arg) * 2 != hex_arg.size()) {
20539dba64beSDimitry Andric             // In case of wrong encoding, we discard all the arguments
20549dba64beSDimitry Andric             process_info.GetArguments().Clear();
20559dba64beSDimitry Andric             process_info.SetArg0("");
20569dba64beSDimitry Andric             break;
20579dba64beSDimitry Andric           }
20589dba64beSDimitry Andric           if (is_arg0)
20599dba64beSDimitry Andric             process_info.SetArg0(arg);
20609dba64beSDimitry Andric           else
20619dba64beSDimitry Andric             process_info.GetArguments().AppendArgument(arg);
20629dba64beSDimitry Andric           is_arg0 = false;
20639dba64beSDimitry Andric         }
2064*0fca6ea1SDimitry Andric       } else if (name == "cputype") {
20650b57cec5SDimitry Andric         value.getAsInteger(0, cpu);
2066*0fca6ea1SDimitry Andric       } else if (name == "cpusubtype") {
20670b57cec5SDimitry Andric         value.getAsInteger(0, sub);
2068*0fca6ea1SDimitry Andric       } else if (name == "vendor") {
20695ffd83dbSDimitry Andric         vendor = std::string(value);
2070*0fca6ea1SDimitry Andric       } else if (name == "ostype") {
20715ffd83dbSDimitry Andric         os_type = std::string(value);
20720b57cec5SDimitry Andric       }
20730b57cec5SDimitry Andric     }
20740b57cec5SDimitry Andric 
20750b57cec5SDimitry Andric     if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty()) {
20760b57cec5SDimitry Andric       if (vendor == "apple") {
20770b57cec5SDimitry Andric         process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu,
20780b57cec5SDimitry Andric                                                        sub);
20790b57cec5SDimitry Andric         process_info.GetArchitecture().GetTriple().setVendorName(
20800b57cec5SDimitry Andric             llvm::StringRef(vendor));
20810b57cec5SDimitry Andric         process_info.GetArchitecture().GetTriple().setOSName(
20820b57cec5SDimitry Andric             llvm::StringRef(os_type));
20830b57cec5SDimitry Andric       }
20840b57cec5SDimitry Andric     }
20850b57cec5SDimitry Andric 
20860b57cec5SDimitry Andric     if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
20870b57cec5SDimitry Andric       return true;
20880b57cec5SDimitry Andric   }
20890b57cec5SDimitry Andric   return false;
20900b57cec5SDimitry Andric }
20910b57cec5SDimitry Andric 
20920b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetProcessInfo(
20930b57cec5SDimitry Andric     lldb::pid_t pid, ProcessInstanceInfo &process_info) {
20940b57cec5SDimitry Andric   process_info.Clear();
20950b57cec5SDimitry Andric 
20960b57cec5SDimitry Andric   if (m_supports_qProcessInfoPID) {
20970b57cec5SDimitry Andric     char packet[32];
20980b57cec5SDimitry Andric     const int packet_len =
20990b57cec5SDimitry Andric         ::snprintf(packet, sizeof(packet), "qProcessInfoPID:%" PRIu64, pid);
21000b57cec5SDimitry Andric     assert(packet_len < (int)sizeof(packet));
21010b57cec5SDimitry Andric     UNUSED_IF_ASSERT_DISABLED(packet_len);
21020b57cec5SDimitry Andric     StringExtractorGDBRemote response;
2103fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) ==
21040b57cec5SDimitry Andric         PacketResult::Success) {
21050b57cec5SDimitry Andric       return DecodeProcessInfoResponse(response, process_info);
21060b57cec5SDimitry Andric     } else {
21070b57cec5SDimitry Andric       m_supports_qProcessInfoPID = false;
21080b57cec5SDimitry Andric       return false;
21090b57cec5SDimitry Andric     }
21100b57cec5SDimitry Andric   }
21110b57cec5SDimitry Andric   return false;
21120b57cec5SDimitry Andric }
21130b57cec5SDimitry Andric 
21140b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
21151fd87a68SDimitry Andric   Log *log(GetLog(GDBRLog::Process | GDBRLog::Packets));
21160b57cec5SDimitry Andric 
21170b57cec5SDimitry Andric   if (allow_lazy) {
21180b57cec5SDimitry Andric     if (m_qProcessInfo_is_valid == eLazyBoolYes)
21190b57cec5SDimitry Andric       return true;
21200b57cec5SDimitry Andric     if (m_qProcessInfo_is_valid == eLazyBoolNo)
21210b57cec5SDimitry Andric       return false;
21220b57cec5SDimitry Andric   }
21230b57cec5SDimitry Andric 
21240b57cec5SDimitry Andric   GetHostInfo();
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric   StringExtractorGDBRemote response;
2127fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse("qProcessInfo", response) ==
21280b57cec5SDimitry Andric       PacketResult::Success) {
21290b57cec5SDimitry Andric     if (response.IsNormalResponse()) {
21300b57cec5SDimitry Andric       llvm::StringRef name;
21310b57cec5SDimitry Andric       llvm::StringRef value;
21320b57cec5SDimitry Andric       uint32_t cpu = LLDB_INVALID_CPUTYPE;
21330b57cec5SDimitry Andric       uint32_t sub = 0;
21340b57cec5SDimitry Andric       std::string arch_name;
21350b57cec5SDimitry Andric       std::string os_name;
21369dba64beSDimitry Andric       std::string environment;
21370b57cec5SDimitry Andric       std::string vendor_name;
21380b57cec5SDimitry Andric       std::string triple;
21390b57cec5SDimitry Andric       std::string elf_abi;
21400b57cec5SDimitry Andric       uint32_t pointer_byte_size = 0;
21410b57cec5SDimitry Andric       StringExtractor extractor;
21420b57cec5SDimitry Andric       ByteOrder byte_order = eByteOrderInvalid;
21430b57cec5SDimitry Andric       uint32_t num_keys_decoded = 0;
21440b57cec5SDimitry Andric       lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
21450b57cec5SDimitry Andric       while (response.GetNameColonValue(name, value)) {
2146*0fca6ea1SDimitry Andric         if (name == "cputype") {
21470b57cec5SDimitry Andric           if (!value.getAsInteger(16, cpu))
21480b57cec5SDimitry Andric             ++num_keys_decoded;
2149*0fca6ea1SDimitry Andric         } else if (name == "cpusubtype") {
2150*0fca6ea1SDimitry Andric           if (!value.getAsInteger(16, sub)) {
21510b57cec5SDimitry Andric             ++num_keys_decoded;
2152*0fca6ea1SDimitry Andric             // Workaround for pre-2024 Apple debugserver, which always
2153*0fca6ea1SDimitry Andric             // returns arm64e on arm64e-capable hardware regardless of
2154*0fca6ea1SDimitry Andric             // what the process is. This can be deleted at some point
2155*0fca6ea1SDimitry Andric             // in the future.
2156*0fca6ea1SDimitry Andric             if (cpu == llvm::MachO::CPU_TYPE_ARM64 &&
2157*0fca6ea1SDimitry Andric                 sub == llvm::MachO::CPU_SUBTYPE_ARM64E) {
2158*0fca6ea1SDimitry Andric               if (GetGDBServerVersion())
2159*0fca6ea1SDimitry Andric                 if (m_gdb_server_version >= 1000 &&
2160*0fca6ea1SDimitry Andric                     m_gdb_server_version <= 1504)
2161*0fca6ea1SDimitry Andric                   sub = 0;
2162*0fca6ea1SDimitry Andric             }
2163*0fca6ea1SDimitry Andric           }
2164*0fca6ea1SDimitry Andric         } else if (name == "triple") {
21650b57cec5SDimitry Andric           StringExtractor extractor(value);
21660b57cec5SDimitry Andric           extractor.GetHexByteString(triple);
21670b57cec5SDimitry Andric           ++num_keys_decoded;
2168*0fca6ea1SDimitry Andric         } else if (name == "ostype") {
21695ffd83dbSDimitry Andric           ParseOSType(value, os_name, environment);
21700b57cec5SDimitry Andric           ++num_keys_decoded;
2171*0fca6ea1SDimitry Andric         } else if (name == "vendor") {
21725ffd83dbSDimitry Andric           vendor_name = std::string(value);
21730b57cec5SDimitry Andric           ++num_keys_decoded;
2174*0fca6ea1SDimitry Andric         } else if (name == "endian") {
21750b57cec5SDimitry Andric           byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
21760b57cec5SDimitry Andric                            .Case("little", eByteOrderLittle)
21770b57cec5SDimitry Andric                            .Case("big", eByteOrderBig)
21780b57cec5SDimitry Andric                            .Case("pdp", eByteOrderPDP)
21790b57cec5SDimitry Andric                            .Default(eByteOrderInvalid);
21800b57cec5SDimitry Andric           if (byte_order != eByteOrderInvalid)
21810b57cec5SDimitry Andric             ++num_keys_decoded;
2182*0fca6ea1SDimitry Andric         } else if (name == "ptrsize") {
21830b57cec5SDimitry Andric           if (!value.getAsInteger(16, pointer_byte_size))
21840b57cec5SDimitry Andric             ++num_keys_decoded;
2185*0fca6ea1SDimitry Andric         } else if (name == "pid") {
21860b57cec5SDimitry Andric           if (!value.getAsInteger(16, pid))
21870b57cec5SDimitry Andric             ++num_keys_decoded;
2188*0fca6ea1SDimitry Andric         } else if (name == "elf_abi") {
21895ffd83dbSDimitry Andric           elf_abi = std::string(value);
21900b57cec5SDimitry Andric           ++num_keys_decoded;
2191*0fca6ea1SDimitry Andric         } else if (name == "main-binary-uuid") {
21920eae32dcSDimitry Andric           m_process_standalone_uuid.SetFromStringRef(value);
21930eae32dcSDimitry Andric           ++num_keys_decoded;
2194*0fca6ea1SDimitry Andric         } else if (name == "main-binary-slide") {
21950eae32dcSDimitry Andric           StringExtractor extractor(value);
21960eae32dcSDimitry Andric           m_process_standalone_value =
21970eae32dcSDimitry Andric               extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
21980eae32dcSDimitry Andric           if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
21990eae32dcSDimitry Andric             m_process_standalone_value_is_offset = true;
22000eae32dcSDimitry Andric             ++num_keys_decoded;
22010eae32dcSDimitry Andric           }
2202*0fca6ea1SDimitry Andric         } else if (name == "main-binary-address") {
22030eae32dcSDimitry Andric           StringExtractor extractor(value);
22040eae32dcSDimitry Andric           m_process_standalone_value =
22050eae32dcSDimitry Andric               extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
22060eae32dcSDimitry Andric           if (m_process_standalone_value != LLDB_INVALID_ADDRESS) {
22070eae32dcSDimitry Andric             m_process_standalone_value_is_offset = false;
22080eae32dcSDimitry Andric             ++num_keys_decoded;
22090eae32dcSDimitry Andric           }
2210*0fca6ea1SDimitry Andric         } else if (name == "binary-addresses") {
2211bdd1243dSDimitry Andric           m_binary_addresses.clear();
2212bdd1243dSDimitry Andric           ++num_keys_decoded;
2213bdd1243dSDimitry Andric           for (llvm::StringRef x : llvm::split(value, ',')) {
2214bdd1243dSDimitry Andric             addr_t vmaddr;
2215bdd1243dSDimitry Andric             x.consume_front("0x");
2216bdd1243dSDimitry Andric             if (llvm::to_integer(x, vmaddr, 16))
2217bdd1243dSDimitry Andric               m_binary_addresses.push_back(vmaddr);
2218bdd1243dSDimitry Andric           }
22190b57cec5SDimitry Andric         }
22200b57cec5SDimitry Andric       }
22210b57cec5SDimitry Andric       if (num_keys_decoded > 0)
22220b57cec5SDimitry Andric         m_qProcessInfo_is_valid = eLazyBoolYes;
22230b57cec5SDimitry Andric       if (pid != LLDB_INVALID_PROCESS_ID) {
22240b57cec5SDimitry Andric         m_curr_pid_is_valid = eLazyBoolYes;
2225fe6060f1SDimitry Andric         m_curr_pid_run = m_curr_pid = pid;
22260b57cec5SDimitry Andric       }
22270b57cec5SDimitry Andric 
22280b57cec5SDimitry Andric       // Set the ArchSpec from the triple if we have it.
22290b57cec5SDimitry Andric       if (!triple.empty()) {
22300b57cec5SDimitry Andric         m_process_arch.SetTriple(triple.c_str());
22310b57cec5SDimitry Andric         m_process_arch.SetFlags(elf_abi);
22320b57cec5SDimitry Andric         if (pointer_byte_size) {
22330b57cec5SDimitry Andric           assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
22340b57cec5SDimitry Andric         }
22350b57cec5SDimitry Andric       } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() &&
22360b57cec5SDimitry Andric                  !vendor_name.empty()) {
22370b57cec5SDimitry Andric         llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name);
22389dba64beSDimitry Andric         if (!environment.empty())
22399dba64beSDimitry Andric             triple.setEnvironmentName(environment);
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric         assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat);
22420b57cec5SDimitry Andric         assert(triple.getObjectFormat() != llvm::Triple::Wasm);
22430b57cec5SDimitry Andric         assert(triple.getObjectFormat() != llvm::Triple::XCOFF);
22440b57cec5SDimitry Andric         switch (triple.getObjectFormat()) {
22450b57cec5SDimitry Andric         case llvm::Triple::MachO:
22460b57cec5SDimitry Andric           m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
22470b57cec5SDimitry Andric           break;
22480b57cec5SDimitry Andric         case llvm::Triple::ELF:
22490b57cec5SDimitry Andric           m_process_arch.SetArchitecture(eArchTypeELF, cpu, sub);
22500b57cec5SDimitry Andric           break;
22510b57cec5SDimitry Andric         case llvm::Triple::COFF:
22520b57cec5SDimitry Andric           m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub);
22530b57cec5SDimitry Andric           break;
2254e8d8bef9SDimitry Andric         case llvm::Triple::GOFF:
225581ad6265SDimitry Andric         case llvm::Triple::SPIRV:
22560b57cec5SDimitry Andric         case llvm::Triple::Wasm:
22570b57cec5SDimitry Andric         case llvm::Triple::XCOFF:
225881ad6265SDimitry Andric         case llvm::Triple::DXContainer:
22599dba64beSDimitry Andric           LLDB_LOGF(log, "error: not supported target architecture");
22600b57cec5SDimitry Andric           return false;
22610b57cec5SDimitry Andric         case llvm::Triple::UnknownObjectFormat:
22629dba64beSDimitry Andric           LLDB_LOGF(log, "error: failed to determine target architecture");
22630b57cec5SDimitry Andric           return false;
22640b57cec5SDimitry Andric         }
22650b57cec5SDimitry Andric 
22660b57cec5SDimitry Andric         if (pointer_byte_size) {
22670b57cec5SDimitry Andric           assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
22680b57cec5SDimitry Andric         }
22690b57cec5SDimitry Andric         if (byte_order != eByteOrderInvalid) {
22700b57cec5SDimitry Andric           assert(byte_order == m_process_arch.GetByteOrder());
22710b57cec5SDimitry Andric         }
22720b57cec5SDimitry Andric         m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name));
22730b57cec5SDimitry Andric         m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name));
22749dba64beSDimitry Andric         m_process_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment));
22750b57cec5SDimitry Andric       }
22760b57cec5SDimitry Andric       return true;
22770b57cec5SDimitry Andric     }
22780b57cec5SDimitry Andric   } else {
22790b57cec5SDimitry Andric     m_qProcessInfo_is_valid = eLazyBoolNo;
22800b57cec5SDimitry Andric   }
22810b57cec5SDimitry Andric 
22820b57cec5SDimitry Andric   return false;
22830b57cec5SDimitry Andric }
22840b57cec5SDimitry Andric 
22850b57cec5SDimitry Andric uint32_t GDBRemoteCommunicationClient::FindProcesses(
22860b57cec5SDimitry Andric     const ProcessInstanceInfoMatch &match_info,
22870b57cec5SDimitry Andric     ProcessInstanceInfoList &process_infos) {
22885ffd83dbSDimitry Andric   process_infos.clear();
22890b57cec5SDimitry Andric 
22900b57cec5SDimitry Andric   if (m_supports_qfProcessInfo) {
22910b57cec5SDimitry Andric     StreamString packet;
22920b57cec5SDimitry Andric     packet.PutCString("qfProcessInfo");
22930b57cec5SDimitry Andric     if (!match_info.MatchAllProcesses()) {
22940b57cec5SDimitry Andric       packet.PutChar(':');
22950b57cec5SDimitry Andric       const char *name = match_info.GetProcessInfo().GetName();
22960b57cec5SDimitry Andric       bool has_name_match = false;
22970b57cec5SDimitry Andric       if (name && name[0]) {
22980b57cec5SDimitry Andric         has_name_match = true;
22990b57cec5SDimitry Andric         NameMatch name_match_type = match_info.GetNameMatchType();
23000b57cec5SDimitry Andric         switch (name_match_type) {
23010b57cec5SDimitry Andric         case NameMatch::Ignore:
23020b57cec5SDimitry Andric           has_name_match = false;
23030b57cec5SDimitry Andric           break;
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric         case NameMatch::Equals:
23060b57cec5SDimitry Andric           packet.PutCString("name_match:equals;");
23070b57cec5SDimitry Andric           break;
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric         case NameMatch::Contains:
23100b57cec5SDimitry Andric           packet.PutCString("name_match:contains;");
23110b57cec5SDimitry Andric           break;
23120b57cec5SDimitry Andric 
23130b57cec5SDimitry Andric         case NameMatch::StartsWith:
23140b57cec5SDimitry Andric           packet.PutCString("name_match:starts_with;");
23150b57cec5SDimitry Andric           break;
23160b57cec5SDimitry Andric 
23170b57cec5SDimitry Andric         case NameMatch::EndsWith:
23180b57cec5SDimitry Andric           packet.PutCString("name_match:ends_with;");
23190b57cec5SDimitry Andric           break;
23200b57cec5SDimitry Andric 
23210b57cec5SDimitry Andric         case NameMatch::RegularExpression:
23220b57cec5SDimitry Andric           packet.PutCString("name_match:regex;");
23230b57cec5SDimitry Andric           break;
23240b57cec5SDimitry Andric         }
23250b57cec5SDimitry Andric         if (has_name_match) {
23260b57cec5SDimitry Andric           packet.PutCString("name:");
23270b57cec5SDimitry Andric           packet.PutBytesAsRawHex8(name, ::strlen(name));
23280b57cec5SDimitry Andric           packet.PutChar(';');
23290b57cec5SDimitry Andric         }
23300b57cec5SDimitry Andric       }
23310b57cec5SDimitry Andric 
23320b57cec5SDimitry Andric       if (match_info.GetProcessInfo().ProcessIDIsValid())
23330b57cec5SDimitry Andric         packet.Printf("pid:%" PRIu64 ";",
23340b57cec5SDimitry Andric                       match_info.GetProcessInfo().GetProcessID());
23350b57cec5SDimitry Andric       if (match_info.GetProcessInfo().ParentProcessIDIsValid())
23360b57cec5SDimitry Andric         packet.Printf("parent_pid:%" PRIu64 ";",
23370b57cec5SDimitry Andric                       match_info.GetProcessInfo().GetParentProcessID());
23380b57cec5SDimitry Andric       if (match_info.GetProcessInfo().UserIDIsValid())
23390b57cec5SDimitry Andric         packet.Printf("uid:%u;", match_info.GetProcessInfo().GetUserID());
23400b57cec5SDimitry Andric       if (match_info.GetProcessInfo().GroupIDIsValid())
23410b57cec5SDimitry Andric         packet.Printf("gid:%u;", match_info.GetProcessInfo().GetGroupID());
23420b57cec5SDimitry Andric       if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
23430b57cec5SDimitry Andric         packet.Printf("euid:%u;",
23440b57cec5SDimitry Andric                       match_info.GetProcessInfo().GetEffectiveUserID());
23450b57cec5SDimitry Andric       if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
23460b57cec5SDimitry Andric         packet.Printf("egid:%u;",
23470b57cec5SDimitry Andric                       match_info.GetProcessInfo().GetEffectiveGroupID());
23480b57cec5SDimitry Andric       packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0);
23490b57cec5SDimitry Andric       if (match_info.GetProcessInfo().GetArchitecture().IsValid()) {
23500b57cec5SDimitry Andric         const ArchSpec &match_arch =
23510b57cec5SDimitry Andric             match_info.GetProcessInfo().GetArchitecture();
23520b57cec5SDimitry Andric         const llvm::Triple &triple = match_arch.GetTriple();
23530b57cec5SDimitry Andric         packet.PutCString("triple:");
23540b57cec5SDimitry Andric         packet.PutCString(triple.getTriple());
23550b57cec5SDimitry Andric         packet.PutChar(';');
23560b57cec5SDimitry Andric       }
23570b57cec5SDimitry Andric     }
23580b57cec5SDimitry Andric     StringExtractorGDBRemote response;
23590b57cec5SDimitry Andric     // Increase timeout as the first qfProcessInfo packet takes a long time on
23600b57cec5SDimitry Andric     // Android. The value of 1min was arrived at empirically.
23610b57cec5SDimitry Andric     ScopedTimeout timeout(*this, minutes(1));
2362fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
23630b57cec5SDimitry Andric         PacketResult::Success) {
23640b57cec5SDimitry Andric       do {
23650b57cec5SDimitry Andric         ProcessInstanceInfo process_info;
23660b57cec5SDimitry Andric         if (!DecodeProcessInfoResponse(response, process_info))
23670b57cec5SDimitry Andric           break;
23685ffd83dbSDimitry Andric         process_infos.push_back(process_info);
23699dba64beSDimitry Andric         response = StringExtractorGDBRemote();
2370fe6060f1SDimitry Andric       } while (SendPacketAndWaitForResponse("qsProcessInfo", response) ==
23710b57cec5SDimitry Andric                PacketResult::Success);
23720b57cec5SDimitry Andric     } else {
23730b57cec5SDimitry Andric       m_supports_qfProcessInfo = false;
23740b57cec5SDimitry Andric       return 0;
23750b57cec5SDimitry Andric     }
23760b57cec5SDimitry Andric   }
23775ffd83dbSDimitry Andric   return process_infos.size();
23780b57cec5SDimitry Andric }
23790b57cec5SDimitry Andric 
23800b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
23810b57cec5SDimitry Andric                                                std::string &name) {
23820b57cec5SDimitry Andric   if (m_supports_qUserName) {
23830b57cec5SDimitry Andric     char packet[32];
23840b57cec5SDimitry Andric     const int packet_len =
23850b57cec5SDimitry Andric         ::snprintf(packet, sizeof(packet), "qUserName:%i", uid);
23860b57cec5SDimitry Andric     assert(packet_len < (int)sizeof(packet));
23870b57cec5SDimitry Andric     UNUSED_IF_ASSERT_DISABLED(packet_len);
23880b57cec5SDimitry Andric     StringExtractorGDBRemote response;
2389fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) ==
23900b57cec5SDimitry Andric         PacketResult::Success) {
23910b57cec5SDimitry Andric       if (response.IsNormalResponse()) {
23920b57cec5SDimitry Andric         // Make sure we parsed the right number of characters. The response is
23930b57cec5SDimitry Andric         // the hex encoded user name and should make up the entire packet. If
23940b57cec5SDimitry Andric         // there are any non-hex ASCII bytes, the length won't match below..
23950b57cec5SDimitry Andric         if (response.GetHexByteString(name) * 2 ==
23960b57cec5SDimitry Andric             response.GetStringRef().size())
23970b57cec5SDimitry Andric           return true;
23980b57cec5SDimitry Andric       }
23990b57cec5SDimitry Andric     } else {
24000b57cec5SDimitry Andric       m_supports_qUserName = false;
24010b57cec5SDimitry Andric       return false;
24020b57cec5SDimitry Andric     }
24030b57cec5SDimitry Andric   }
24040b57cec5SDimitry Andric   return false;
24050b57cec5SDimitry Andric }
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
24080b57cec5SDimitry Andric                                                 std::string &name) {
24090b57cec5SDimitry Andric   if (m_supports_qGroupName) {
24100b57cec5SDimitry Andric     char packet[32];
24110b57cec5SDimitry Andric     const int packet_len =
24120b57cec5SDimitry Andric         ::snprintf(packet, sizeof(packet), "qGroupName:%i", gid);
24130b57cec5SDimitry Andric     assert(packet_len < (int)sizeof(packet));
24140b57cec5SDimitry Andric     UNUSED_IF_ASSERT_DISABLED(packet_len);
24150b57cec5SDimitry Andric     StringExtractorGDBRemote response;
2416fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) ==
24170b57cec5SDimitry Andric         PacketResult::Success) {
24180b57cec5SDimitry Andric       if (response.IsNormalResponse()) {
24190b57cec5SDimitry Andric         // Make sure we parsed the right number of characters. The response is
24200b57cec5SDimitry Andric         // the hex encoded group name and should make up the entire packet. If
24210b57cec5SDimitry Andric         // there are any non-hex ASCII bytes, the length won't match below..
24220b57cec5SDimitry Andric         if (response.GetHexByteString(name) * 2 ==
24230b57cec5SDimitry Andric             response.GetStringRef().size())
24240b57cec5SDimitry Andric           return true;
24250b57cec5SDimitry Andric       }
24260b57cec5SDimitry Andric     } else {
24270b57cec5SDimitry Andric       m_supports_qGroupName = false;
24280b57cec5SDimitry Andric       return false;
24290b57cec5SDimitry Andric     }
24300b57cec5SDimitry Andric   }
24310b57cec5SDimitry Andric   return false;
24320b57cec5SDimitry Andric }
24330b57cec5SDimitry Andric 
24340b57cec5SDimitry Andric static void MakeSpeedTestPacket(StreamString &packet, uint32_t send_size,
24350b57cec5SDimitry Andric                                 uint32_t recv_size) {
24360b57cec5SDimitry Andric   packet.Clear();
24370b57cec5SDimitry Andric   packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
24380b57cec5SDimitry Andric   uint32_t bytes_left = send_size;
24390b57cec5SDimitry Andric   while (bytes_left > 0) {
24400b57cec5SDimitry Andric     if (bytes_left >= 26) {
24410b57cec5SDimitry Andric       packet.PutCString("abcdefghijklmnopqrstuvwxyz");
24420b57cec5SDimitry Andric       bytes_left -= 26;
24430b57cec5SDimitry Andric     } else {
24440b57cec5SDimitry Andric       packet.Printf("%*.*s;", bytes_left, bytes_left,
24450b57cec5SDimitry Andric                     "abcdefghijklmnopqrstuvwxyz");
24460b57cec5SDimitry Andric       bytes_left = 0;
24470b57cec5SDimitry Andric     }
24480b57cec5SDimitry Andric   }
24490b57cec5SDimitry Andric }
24500b57cec5SDimitry Andric 
24510b57cec5SDimitry Andric duration<float>
24520b57cec5SDimitry Andric calculate_standard_deviation(const std::vector<duration<float>> &v) {
2453bdd1243dSDimitry Andric   if (v.size() == 0)
2454bdd1243dSDimitry Andric     return duration<float>::zero();
24550b57cec5SDimitry Andric   using Dur = duration<float>;
24560b57cec5SDimitry Andric   Dur sum = std::accumulate(std::begin(v), std::end(v), Dur());
24570b57cec5SDimitry Andric   Dur mean = sum / v.size();
24580b57cec5SDimitry Andric   float accum = 0;
24590b57cec5SDimitry Andric   for (auto d : v) {
24600b57cec5SDimitry Andric     float delta = (d - mean).count();
24610b57cec5SDimitry Andric     accum += delta * delta;
24620b57cec5SDimitry Andric   };
24630b57cec5SDimitry Andric 
24640b57cec5SDimitry Andric   return Dur(sqrtf(accum / (v.size() - 1)));
24650b57cec5SDimitry Andric }
24660b57cec5SDimitry Andric 
24670b57cec5SDimitry Andric void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
24680b57cec5SDimitry Andric                                                    uint32_t max_send,
24690b57cec5SDimitry Andric                                                    uint32_t max_recv,
24700b57cec5SDimitry Andric                                                    uint64_t recv_amount,
24710b57cec5SDimitry Andric                                                    bool json, Stream &strm) {
2472bdd1243dSDimitry Andric 
24730b57cec5SDimitry Andric   if (SendSpeedTestPacket(0, 0)) {
24740b57cec5SDimitry Andric     StreamString packet;
24750b57cec5SDimitry Andric     if (json)
24760b57cec5SDimitry Andric       strm.Printf("{ \"packet_speeds\" : {\n    \"num_packets\" : %u,\n    "
24770b57cec5SDimitry Andric                   "\"results\" : [",
24780b57cec5SDimitry Andric                   num_packets);
24790b57cec5SDimitry Andric     else
24800b57cec5SDimitry Andric       strm.Printf("Testing sending %u packets of various sizes:\n",
24810b57cec5SDimitry Andric                   num_packets);
24820b57cec5SDimitry Andric     strm.Flush();
24830b57cec5SDimitry Andric 
24840b57cec5SDimitry Andric     uint32_t result_idx = 0;
24850b57cec5SDimitry Andric     uint32_t send_size;
24860b57cec5SDimitry Andric     std::vector<duration<float>> packet_times;
24870b57cec5SDimitry Andric 
24880b57cec5SDimitry Andric     for (send_size = 0; send_size <= max_send;
24890b57cec5SDimitry Andric          send_size ? send_size *= 2 : send_size = 4) {
24900b57cec5SDimitry Andric       for (uint32_t recv_size = 0; recv_size <= max_recv;
24910b57cec5SDimitry Andric            recv_size ? recv_size *= 2 : recv_size = 4) {
24920b57cec5SDimitry Andric         MakeSpeedTestPacket(packet, send_size, recv_size);
24930b57cec5SDimitry Andric 
24940b57cec5SDimitry Andric         packet_times.clear();
24950b57cec5SDimitry Andric         // Test how long it takes to send 'num_packets' packets
24960b57cec5SDimitry Andric         const auto start_time = steady_clock::now();
2497bdd1243dSDimitry Andric         for (uint32_t i = 0; i < num_packets; ++i) {
24980b57cec5SDimitry Andric           const auto packet_start_time = steady_clock::now();
24990b57cec5SDimitry Andric           StringExtractorGDBRemote response;
2500fe6060f1SDimitry Andric           SendPacketAndWaitForResponse(packet.GetString(), response);
25010b57cec5SDimitry Andric           const auto packet_end_time = steady_clock::now();
25020b57cec5SDimitry Andric           packet_times.push_back(packet_end_time - packet_start_time);
25030b57cec5SDimitry Andric         }
25040b57cec5SDimitry Andric         const auto end_time = steady_clock::now();
25050b57cec5SDimitry Andric         const auto total_time = end_time - start_time;
25060b57cec5SDimitry Andric 
25070b57cec5SDimitry Andric         float packets_per_second =
25080b57cec5SDimitry Andric             ((float)num_packets) / duration<float>(total_time).count();
2509bdd1243dSDimitry Andric         auto average_per_packet = num_packets > 0 ? total_time / num_packets
2510bdd1243dSDimitry Andric                                                   : duration<float>::zero();
25110b57cec5SDimitry Andric         const duration<float> standard_deviation =
25120b57cec5SDimitry Andric             calculate_standard_deviation(packet_times);
25130b57cec5SDimitry Andric         if (json) {
25140b57cec5SDimitry Andric           strm.Format("{0}\n     {{\"send_size\" : {1,6}, \"recv_size\" : "
25150b57cec5SDimitry Andric                       "{2,6}, \"total_time_nsec\" : {3,12:ns-}, "
25160b57cec5SDimitry Andric                       "\"standard_deviation_nsec\" : {4,9:ns-f0}}",
25170b57cec5SDimitry Andric                       result_idx > 0 ? "," : "", send_size, recv_size,
25180b57cec5SDimitry Andric                       total_time, standard_deviation);
25190b57cec5SDimitry Andric           ++result_idx;
25200b57cec5SDimitry Andric         } else {
25210b57cec5SDimitry Andric           strm.Format("qSpeedTest(send={0,7}, recv={1,7}) in {2:s+f9} for "
25220b57cec5SDimitry Andric                       "{3,9:f2} packets/s ({4,10:ms+f6} per packet) with "
25230b57cec5SDimitry Andric                       "standard deviation of {5,10:ms+f6}\n",
25240b57cec5SDimitry Andric                       send_size, recv_size, duration<float>(total_time),
25250b57cec5SDimitry Andric                       packets_per_second, duration<float>(average_per_packet),
25260b57cec5SDimitry Andric                       standard_deviation);
25270b57cec5SDimitry Andric         }
25280b57cec5SDimitry Andric         strm.Flush();
25290b57cec5SDimitry Andric       }
25300b57cec5SDimitry Andric     }
25310b57cec5SDimitry Andric 
25320b57cec5SDimitry Andric     const float k_recv_amount_mb = (float)recv_amount / (1024.0f * 1024.0f);
25330b57cec5SDimitry Andric     if (json)
25340b57cec5SDimitry Andric       strm.Printf("\n    ]\n  },\n  \"download_speed\" : {\n    \"byte_size\" "
25350b57cec5SDimitry Andric                   ": %" PRIu64 ",\n    \"results\" : [",
25360b57cec5SDimitry Andric                   recv_amount);
25370b57cec5SDimitry Andric     else
25380b57cec5SDimitry Andric       strm.Printf("Testing receiving %2.1fMB of data using varying receive "
25390b57cec5SDimitry Andric                   "packet sizes:\n",
25400b57cec5SDimitry Andric                   k_recv_amount_mb);
25410b57cec5SDimitry Andric     strm.Flush();
25420b57cec5SDimitry Andric     send_size = 0;
25430b57cec5SDimitry Andric     result_idx = 0;
25440b57cec5SDimitry Andric     for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) {
25450b57cec5SDimitry Andric       MakeSpeedTestPacket(packet, send_size, recv_size);
25460b57cec5SDimitry Andric 
25470b57cec5SDimitry Andric       // If we have a receive size, test how long it takes to receive 4MB of
25480b57cec5SDimitry Andric       // data
25490b57cec5SDimitry Andric       if (recv_size > 0) {
25500b57cec5SDimitry Andric         const auto start_time = steady_clock::now();
25510b57cec5SDimitry Andric         uint32_t bytes_read = 0;
25520b57cec5SDimitry Andric         uint32_t packet_count = 0;
25530b57cec5SDimitry Andric         while (bytes_read < recv_amount) {
25540b57cec5SDimitry Andric           StringExtractorGDBRemote response;
2555fe6060f1SDimitry Andric           SendPacketAndWaitForResponse(packet.GetString(), response);
25560b57cec5SDimitry Andric           bytes_read += recv_size;
25570b57cec5SDimitry Andric           ++packet_count;
25580b57cec5SDimitry Andric         }
25590b57cec5SDimitry Andric         const auto end_time = steady_clock::now();
25600b57cec5SDimitry Andric         const auto total_time = end_time - start_time;
25610b57cec5SDimitry Andric         float mb_second = ((float)recv_amount) /
25620b57cec5SDimitry Andric                           duration<float>(total_time).count() /
25630b57cec5SDimitry Andric                           (1024.0 * 1024.0);
25640b57cec5SDimitry Andric         float packets_per_second =
25650b57cec5SDimitry Andric             ((float)packet_count) / duration<float>(total_time).count();
2566bdd1243dSDimitry Andric         const auto average_per_packet = packet_count > 0
2567bdd1243dSDimitry Andric                                             ? total_time / packet_count
2568bdd1243dSDimitry Andric                                             : duration<float>::zero();
25690b57cec5SDimitry Andric 
25700b57cec5SDimitry Andric         if (json) {
25710b57cec5SDimitry Andric           strm.Format("{0}\n     {{\"send_size\" : {1,6}, \"recv_size\" : "
25720b57cec5SDimitry Andric                       "{2,6}, \"total_time_nsec\" : {3,12:ns-}}",
25730b57cec5SDimitry Andric                       result_idx > 0 ? "," : "", send_size, recv_size,
25740b57cec5SDimitry Andric                       total_time);
25750b57cec5SDimitry Andric           ++result_idx;
25760b57cec5SDimitry Andric         } else {
25770b57cec5SDimitry Andric           strm.Format("qSpeedTest(send={0,7}, recv={1,7}) {2,6} packets needed "
25780b57cec5SDimitry Andric                       "to receive {3:f1}MB in {4:s+f9} for {5} MB/sec for "
25790b57cec5SDimitry Andric                       "{6,9:f2} packets/sec ({7,10:ms+f6} per packet)\n",
25800b57cec5SDimitry Andric                       send_size, recv_size, packet_count, k_recv_amount_mb,
25810b57cec5SDimitry Andric                       duration<float>(total_time), mb_second,
25820b57cec5SDimitry Andric                       packets_per_second, duration<float>(average_per_packet));
25830b57cec5SDimitry Andric         }
25840b57cec5SDimitry Andric         strm.Flush();
25850b57cec5SDimitry Andric       }
25860b57cec5SDimitry Andric     }
25870b57cec5SDimitry Andric     if (json)
25880b57cec5SDimitry Andric       strm.Printf("\n    ]\n  }\n}\n");
25890b57cec5SDimitry Andric     else
25900b57cec5SDimitry Andric       strm.EOL();
25910b57cec5SDimitry Andric   }
25920b57cec5SDimitry Andric }
25930b57cec5SDimitry Andric 
25940b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size,
25950b57cec5SDimitry Andric                                                        uint32_t recv_size) {
25960b57cec5SDimitry Andric   StreamString packet;
25970b57cec5SDimitry Andric   packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
25980b57cec5SDimitry Andric   uint32_t bytes_left = send_size;
25990b57cec5SDimitry Andric   while (bytes_left > 0) {
26000b57cec5SDimitry Andric     if (bytes_left >= 26) {
26010b57cec5SDimitry Andric       packet.PutCString("abcdefghijklmnopqrstuvwxyz");
26020b57cec5SDimitry Andric       bytes_left -= 26;
26030b57cec5SDimitry Andric     } else {
26040b57cec5SDimitry Andric       packet.Printf("%*.*s;", bytes_left, bytes_left,
26050b57cec5SDimitry Andric                     "abcdefghijklmnopqrstuvwxyz");
26060b57cec5SDimitry Andric       bytes_left = 0;
26070b57cec5SDimitry Andric     }
26080b57cec5SDimitry Andric   }
26090b57cec5SDimitry Andric 
26100b57cec5SDimitry Andric   StringExtractorGDBRemote response;
2611fe6060f1SDimitry Andric   return SendPacketAndWaitForResponse(packet.GetString(), response) ==
26120b57cec5SDimitry Andric          PacketResult::Success;
26130b57cec5SDimitry Andric }
26140b57cec5SDimitry Andric 
26150b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::LaunchGDBServer(
26160b57cec5SDimitry Andric     const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port,
26170b57cec5SDimitry Andric     std::string &socket_name) {
26180b57cec5SDimitry Andric   pid = LLDB_INVALID_PROCESS_ID;
26190b57cec5SDimitry Andric   port = 0;
26200b57cec5SDimitry Andric   socket_name.clear();
26210b57cec5SDimitry Andric 
26220b57cec5SDimitry Andric   StringExtractorGDBRemote response;
26230b57cec5SDimitry Andric   StreamString stream;
26240b57cec5SDimitry Andric   stream.PutCString("qLaunchGDBServer;");
26250b57cec5SDimitry Andric   std::string hostname;
26260b57cec5SDimitry Andric   if (remote_accept_hostname && remote_accept_hostname[0])
26270b57cec5SDimitry Andric     hostname = remote_accept_hostname;
26280b57cec5SDimitry Andric   else {
26290b57cec5SDimitry Andric     if (HostInfo::GetHostname(hostname)) {
26300b57cec5SDimitry Andric       // Make the GDB server we launch only accept connections from this host
26310b57cec5SDimitry Andric       stream.Printf("host:%s;", hostname.c_str());
26320b57cec5SDimitry Andric     } else {
26330b57cec5SDimitry Andric       // Make the GDB server we launch accept connections from any host since
26340b57cec5SDimitry Andric       // we can't figure out the hostname
26350b57cec5SDimitry Andric       stream.Printf("host:*;");
26360b57cec5SDimitry Andric     }
26370b57cec5SDimitry Andric   }
26380b57cec5SDimitry Andric   // give the process a few seconds to startup
26390b57cec5SDimitry Andric   ScopedTimeout timeout(*this, seconds(10));
26400b57cec5SDimitry Andric 
2641fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
26420b57cec5SDimitry Andric       PacketResult::Success) {
264306c3fb27SDimitry Andric     if (response.IsErrorResponse())
264406c3fb27SDimitry Andric       return false;
264506c3fb27SDimitry Andric 
26460b57cec5SDimitry Andric     llvm::StringRef name;
26470b57cec5SDimitry Andric     llvm::StringRef value;
26480b57cec5SDimitry Andric     while (response.GetNameColonValue(name, value)) {
2649*0fca6ea1SDimitry Andric       if (name == "port")
26500b57cec5SDimitry Andric         value.getAsInteger(0, port);
2651*0fca6ea1SDimitry Andric       else if (name == "pid")
26520b57cec5SDimitry Andric         value.getAsInteger(0, pid);
26530b57cec5SDimitry Andric       else if (name.compare("socket_name") == 0) {
26540b57cec5SDimitry Andric         StringExtractor extractor(value);
26550b57cec5SDimitry Andric         extractor.GetHexByteString(socket_name);
26560b57cec5SDimitry Andric       }
26570b57cec5SDimitry Andric     }
26580b57cec5SDimitry Andric     return true;
26590b57cec5SDimitry Andric   }
26600b57cec5SDimitry Andric   return false;
26610b57cec5SDimitry Andric }
26620b57cec5SDimitry Andric 
26630b57cec5SDimitry Andric size_t GDBRemoteCommunicationClient::QueryGDBServer(
26640b57cec5SDimitry Andric     std::vector<std::pair<uint16_t, std::string>> &connection_urls) {
26650b57cec5SDimitry Andric   connection_urls.clear();
26660b57cec5SDimitry Andric 
26670b57cec5SDimitry Andric   StringExtractorGDBRemote response;
2668fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse("qQueryGDBServer", response) !=
26690b57cec5SDimitry Andric       PacketResult::Success)
26700b57cec5SDimitry Andric     return 0;
26710b57cec5SDimitry Andric 
26720b57cec5SDimitry Andric   StructuredData::ObjectSP data =
267306c3fb27SDimitry Andric       StructuredData::ParseJSON(response.GetStringRef());
26740b57cec5SDimitry Andric   if (!data)
26750b57cec5SDimitry Andric     return 0;
26760b57cec5SDimitry Andric 
26770b57cec5SDimitry Andric   StructuredData::Array *array = data->GetAsArray();
26780b57cec5SDimitry Andric   if (!array)
26790b57cec5SDimitry Andric     return 0;
26800b57cec5SDimitry Andric 
26810b57cec5SDimitry Andric   for (size_t i = 0, count = array->GetSize(); i < count; ++i) {
26825f757f3fSDimitry Andric     std::optional<StructuredData::Dictionary *> maybe_element =
26835f757f3fSDimitry Andric         array->GetItemAtIndexAsDictionary(i);
26845f757f3fSDimitry Andric     if (!maybe_element)
26850b57cec5SDimitry Andric       continue;
26860b57cec5SDimitry Andric 
26875f757f3fSDimitry Andric     StructuredData::Dictionary *element = *maybe_element;
26880b57cec5SDimitry Andric     uint16_t port = 0;
26890b57cec5SDimitry Andric     if (StructuredData::ObjectSP port_osp =
26900b57cec5SDimitry Andric             element->GetValueForKey(llvm::StringRef("port")))
269106c3fb27SDimitry Andric       port = port_osp->GetUnsignedIntegerValue(0);
26920b57cec5SDimitry Andric 
26930b57cec5SDimitry Andric     std::string socket_name;
26940b57cec5SDimitry Andric     if (StructuredData::ObjectSP socket_name_osp =
26950b57cec5SDimitry Andric             element->GetValueForKey(llvm::StringRef("socket_name")))
26965ffd83dbSDimitry Andric       socket_name = std::string(socket_name_osp->GetStringValue());
26970b57cec5SDimitry Andric 
26980b57cec5SDimitry Andric     if (port != 0 || !socket_name.empty())
26990b57cec5SDimitry Andric       connection_urls.emplace_back(port, socket_name);
27000b57cec5SDimitry Andric   }
27010b57cec5SDimitry Andric   return connection_urls.size();
27020b57cec5SDimitry Andric }
27030b57cec5SDimitry Andric 
27040b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) {
27050b57cec5SDimitry Andric   StreamString stream;
27060b57cec5SDimitry Andric   stream.Printf("qKillSpawnedProcess:%" PRId64, pid);
27070b57cec5SDimitry Andric 
27080b57cec5SDimitry Andric   StringExtractorGDBRemote response;
2709fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
27100b57cec5SDimitry Andric       PacketResult::Success) {
27110b57cec5SDimitry Andric     if (response.IsOKResponse())
27120b57cec5SDimitry Andric       return true;
27130b57cec5SDimitry Andric   }
27140b57cec5SDimitry Andric   return false;
27150b57cec5SDimitry Andric }
27160b57cec5SDimitry Andric 
2717bdd1243dSDimitry Andric std::optional<PidTid> GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(
2718bdd1243dSDimitry Andric     uint64_t tid, uint64_t pid, char op) {
2719fe6060f1SDimitry Andric   lldb_private::StreamString packet;
2720fe6060f1SDimitry Andric   packet.PutChar('H');
2721fe6060f1SDimitry Andric   packet.PutChar(op);
27220b57cec5SDimitry Andric 
2723fe6060f1SDimitry Andric   if (pid != LLDB_INVALID_PROCESS_ID)
2724fe6060f1SDimitry Andric     packet.Printf("p%" PRIx64 ".", pid);
2725fe6060f1SDimitry Andric 
27260b57cec5SDimitry Andric   if (tid == UINT64_MAX)
2727fe6060f1SDimitry Andric     packet.PutCString("-1");
27280b57cec5SDimitry Andric   else
2729fe6060f1SDimitry Andric     packet.Printf("%" PRIx64, tid);
2730fe6060f1SDimitry Andric 
27310b57cec5SDimitry Andric   StringExtractorGDBRemote response;
273281ad6265SDimitry Andric   if (SendPacketAndWaitForResponse(packet.GetString(), response) ==
273381ad6265SDimitry Andric       PacketResult::Success) {
2734fe6060f1SDimitry Andric     if (response.IsOKResponse())
2735fe6060f1SDimitry Andric       return {{pid, tid}};
27360b57cec5SDimitry Andric 
27370b57cec5SDimitry Andric     /*
27380b57cec5SDimitry Andric      * Connected bare-iron target (like YAMON gdb-stub) may not have support for
27390b57cec5SDimitry Andric      * Hg packet.
27400b57cec5SDimitry Andric      * The reply from '?' packet could be as simple as 'S05'. There is no packet
27410b57cec5SDimitry Andric      * which can
27420b57cec5SDimitry Andric      * give us pid and/or tid. Assume pid=tid=1 in such cases.
27430b57cec5SDimitry Andric      */
2744fe6060f1SDimitry Andric     if (response.IsUnsupportedResponse() && IsConnected())
2745fe6060f1SDimitry Andric       return {{1, 1}};
27460b57cec5SDimitry Andric   }
2747bdd1243dSDimitry Andric   return std::nullopt;
27480b57cec5SDimitry Andric }
27490b57cec5SDimitry Andric 
2750fe6060f1SDimitry Andric bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid,
2751fe6060f1SDimitry Andric                                                     uint64_t pid) {
2752fe6060f1SDimitry Andric   if (m_curr_tid == tid &&
2753fe6060f1SDimitry Andric       (m_curr_pid == pid || LLDB_INVALID_PROCESS_ID == pid))
27540b57cec5SDimitry Andric     return true;
27550b57cec5SDimitry Andric 
2756bdd1243dSDimitry Andric   std::optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'g');
275781ad6265SDimitry Andric   if (ret) {
2758fe6060f1SDimitry Andric     if (ret->pid != LLDB_INVALID_PROCESS_ID)
2759fe6060f1SDimitry Andric       m_curr_pid = ret->pid;
2760fe6060f1SDimitry Andric     m_curr_tid = ret->tid;
2761fe6060f1SDimitry Andric   }
2762753f127fSDimitry Andric   return ret.has_value();
27630b57cec5SDimitry Andric }
27640b57cec5SDimitry Andric 
2765fe6060f1SDimitry Andric bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid,
2766fe6060f1SDimitry Andric                                                           uint64_t pid) {
2767fe6060f1SDimitry Andric   if (m_curr_tid_run == tid &&
2768fe6060f1SDimitry Andric       (m_curr_pid_run == pid || LLDB_INVALID_PROCESS_ID == pid))
27690b57cec5SDimitry Andric     return true;
2770fe6060f1SDimitry Andric 
2771bdd1243dSDimitry Andric   std::optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'c');
277281ad6265SDimitry Andric   if (ret) {
2773fe6060f1SDimitry Andric     if (ret->pid != LLDB_INVALID_PROCESS_ID)
2774fe6060f1SDimitry Andric       m_curr_pid_run = ret->pid;
2775fe6060f1SDimitry Andric     m_curr_tid_run = ret->tid;
27760b57cec5SDimitry Andric   }
2777753f127fSDimitry Andric   return ret.has_value();
27780b57cec5SDimitry Andric }
27790b57cec5SDimitry Andric 
27800b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetStopReply(
27810b57cec5SDimitry Andric     StringExtractorGDBRemote &response) {
2782fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success)
27830b57cec5SDimitry Andric     return response.IsNormalResponse();
27840b57cec5SDimitry Andric   return false;
27850b57cec5SDimitry Andric }
27860b57cec5SDimitry Andric 
27870b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetThreadStopInfo(
27880b57cec5SDimitry Andric     lldb::tid_t tid, StringExtractorGDBRemote &response) {
27890b57cec5SDimitry Andric   if (m_supports_qThreadStopInfo) {
27900b57cec5SDimitry Andric     char packet[256];
27910b57cec5SDimitry Andric     int packet_len =
27920b57cec5SDimitry Andric         ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
27930b57cec5SDimitry Andric     assert(packet_len < (int)sizeof(packet));
27940b57cec5SDimitry Andric     UNUSED_IF_ASSERT_DISABLED(packet_len);
2795fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse(packet, response) ==
27960b57cec5SDimitry Andric         PacketResult::Success) {
27970b57cec5SDimitry Andric       if (response.IsUnsupportedResponse())
27980b57cec5SDimitry Andric         m_supports_qThreadStopInfo = false;
27990b57cec5SDimitry Andric       else if (response.IsNormalResponse())
28000b57cec5SDimitry Andric         return true;
28010b57cec5SDimitry Andric       else
28020b57cec5SDimitry Andric         return false;
28030b57cec5SDimitry Andric     } else {
28040b57cec5SDimitry Andric       m_supports_qThreadStopInfo = false;
28050b57cec5SDimitry Andric     }
28060b57cec5SDimitry Andric   }
28070b57cec5SDimitry Andric   return false;
28080b57cec5SDimitry Andric }
28090b57cec5SDimitry Andric 
28100b57cec5SDimitry Andric uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
2811fe6060f1SDimitry Andric     GDBStoppointType type, bool insert, addr_t addr, uint32_t length,
2812fe6060f1SDimitry Andric     std::chrono::seconds timeout) {
281381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Breakpoints);
28149dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
28150b57cec5SDimitry Andric             __FUNCTION__, insert ? "add" : "remove", addr);
28160b57cec5SDimitry Andric 
28170b57cec5SDimitry Andric   // Check if the stub is known not to support this breakpoint type
28180b57cec5SDimitry Andric   if (!SupportsGDBStoppointPacket(type))
28190b57cec5SDimitry Andric     return UINT8_MAX;
28200b57cec5SDimitry Andric   // Construct the breakpoint packet
28210b57cec5SDimitry Andric   char packet[64];
28220b57cec5SDimitry Andric   const int packet_len =
28230b57cec5SDimitry Andric       ::snprintf(packet, sizeof(packet), "%c%i,%" PRIx64 ",%x",
28240b57cec5SDimitry Andric                  insert ? 'Z' : 'z', type, addr, length);
28250b57cec5SDimitry Andric   // Check we haven't overwritten the end of the packet buffer
28260b57cec5SDimitry Andric   assert(packet_len + 1 < (int)sizeof(packet));
28270b57cec5SDimitry Andric   UNUSED_IF_ASSERT_DISABLED(packet_len);
28280b57cec5SDimitry Andric   StringExtractorGDBRemote response;
28290b57cec5SDimitry Andric   // Make sure the response is either "OK", "EXX" where XX are two hex digits,
28300b57cec5SDimitry Andric   // or "" (unsupported)
28310b57cec5SDimitry Andric   response.SetResponseValidatorToOKErrorNotSupported();
28320b57cec5SDimitry Andric   // Try to send the breakpoint packet, and check that it was correctly sent
2833fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet, response, timeout) ==
28340b57cec5SDimitry Andric       PacketResult::Success) {
28350b57cec5SDimitry Andric     // Receive and OK packet when the breakpoint successfully placed
28360b57cec5SDimitry Andric     if (response.IsOKResponse())
28370b57cec5SDimitry Andric       return 0;
28380b57cec5SDimitry Andric 
28390b57cec5SDimitry Andric     // Status while setting breakpoint, send back specific error
28400b57cec5SDimitry Andric     if (response.IsErrorResponse())
28410b57cec5SDimitry Andric       return response.GetError();
28420b57cec5SDimitry Andric 
28430b57cec5SDimitry Andric     // Empty packet informs us that breakpoint is not supported
28440b57cec5SDimitry Andric     if (response.IsUnsupportedResponse()) {
28450b57cec5SDimitry Andric       // Disable this breakpoint type since it is unsupported
28460b57cec5SDimitry Andric       switch (type) {
28470b57cec5SDimitry Andric       case eBreakpointSoftware:
28480b57cec5SDimitry Andric         m_supports_z0 = false;
28490b57cec5SDimitry Andric         break;
28500b57cec5SDimitry Andric       case eBreakpointHardware:
28510b57cec5SDimitry Andric         m_supports_z1 = false;
28520b57cec5SDimitry Andric         break;
28530b57cec5SDimitry Andric       case eWatchpointWrite:
28540b57cec5SDimitry Andric         m_supports_z2 = false;
28550b57cec5SDimitry Andric         break;
28560b57cec5SDimitry Andric       case eWatchpointRead:
28570b57cec5SDimitry Andric         m_supports_z3 = false;
28580b57cec5SDimitry Andric         break;
28590b57cec5SDimitry Andric       case eWatchpointReadWrite:
28600b57cec5SDimitry Andric         m_supports_z4 = false;
28610b57cec5SDimitry Andric         break;
28620b57cec5SDimitry Andric       case eStoppointInvalid:
28630b57cec5SDimitry Andric         return UINT8_MAX;
28640b57cec5SDimitry Andric       }
28650b57cec5SDimitry Andric     }
28660b57cec5SDimitry Andric   }
28670b57cec5SDimitry Andric   // Signal generic failure
28680b57cec5SDimitry Andric   return UINT8_MAX;
28690b57cec5SDimitry Andric }
28700b57cec5SDimitry Andric 
2871fe6060f1SDimitry Andric std::vector<std::pair<lldb::pid_t, lldb::tid_t>>
2872fe6060f1SDimitry Andric GDBRemoteCommunicationClient::GetCurrentProcessAndThreadIDs(
2873fe6060f1SDimitry Andric     bool &sequence_mutex_unavailable) {
2874fe6060f1SDimitry Andric   std::vector<std::pair<lldb::pid_t, lldb::tid_t>> ids;
28750b57cec5SDimitry Andric 
2876fe6060f1SDimitry Andric   Lock lock(*this);
28770b57cec5SDimitry Andric   if (lock) {
28780b57cec5SDimitry Andric     sequence_mutex_unavailable = false;
28790b57cec5SDimitry Andric     StringExtractorGDBRemote response;
28800b57cec5SDimitry Andric 
28810b57cec5SDimitry Andric     PacketResult packet_result;
28820b57cec5SDimitry Andric     for (packet_result =
28830b57cec5SDimitry Andric              SendPacketAndWaitForResponseNoLock("qfThreadInfo", response);
28840b57cec5SDimitry Andric          packet_result == PacketResult::Success && response.IsNormalResponse();
28850b57cec5SDimitry Andric          packet_result =
28860b57cec5SDimitry Andric              SendPacketAndWaitForResponseNoLock("qsThreadInfo", response)) {
28870b57cec5SDimitry Andric       char ch = response.GetChar();
28880b57cec5SDimitry Andric       if (ch == 'l')
28890b57cec5SDimitry Andric         break;
28900b57cec5SDimitry Andric       if (ch == 'm') {
28910b57cec5SDimitry Andric         do {
2892fe6060f1SDimitry Andric           auto pid_tid = response.GetPidTid(LLDB_INVALID_PROCESS_ID);
2893349cc55cSDimitry Andric           // If we get an invalid response, break out of the loop.
2894349cc55cSDimitry Andric           // If there are valid tids, they have been added to ids.
2895349cc55cSDimitry Andric           // If there are no valid tids, we'll fall through to the
2896349cc55cSDimitry Andric           // bare-iron target handling below.
2897fe6060f1SDimitry Andric           if (!pid_tid)
2898349cc55cSDimitry Andric             break;
28990b57cec5SDimitry Andric 
290081ad6265SDimitry Andric           ids.push_back(*pid_tid);
29010b57cec5SDimitry Andric           ch = response.GetChar(); // Skip the command separator
29020b57cec5SDimitry Andric         } while (ch == ',');       // Make sure we got a comma separator
29030b57cec5SDimitry Andric       }
29040b57cec5SDimitry Andric     }
29050b57cec5SDimitry Andric 
29060b57cec5SDimitry Andric     /*
29070b57cec5SDimitry Andric      * Connected bare-iron target (like YAMON gdb-stub) may not have support for
29080b57cec5SDimitry Andric      * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet
29090b57cec5SDimitry Andric      * could
29100b57cec5SDimitry Andric      * be as simple as 'S05'. There is no packet which can give us pid and/or
29110b57cec5SDimitry Andric      * tid.
29120b57cec5SDimitry Andric      * Assume pid=tid=1 in such cases.
29130b57cec5SDimitry Andric      */
29140b57cec5SDimitry Andric     if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) &&
2915fe6060f1SDimitry Andric         ids.size() == 0 && IsConnected()) {
2916fe6060f1SDimitry Andric       ids.emplace_back(1, 1);
29170b57cec5SDimitry Andric     }
29180b57cec5SDimitry Andric   } else {
29191fd87a68SDimitry Andric     Log *log(GetLog(GDBRLog::Process | GDBRLog::Packets));
29205ffd83dbSDimitry Andric     LLDB_LOG(log, "error: failed to get packet sequence mutex, not sending "
29210b57cec5SDimitry Andric                   "packet 'qfThreadInfo'");
29220b57cec5SDimitry Andric     sequence_mutex_unavailable = true;
29230b57cec5SDimitry Andric   }
2924fe6060f1SDimitry Andric 
2925fe6060f1SDimitry Andric   return ids;
2926fe6060f1SDimitry Andric }
2927fe6060f1SDimitry Andric 
2928fe6060f1SDimitry Andric size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
2929fe6060f1SDimitry Andric     std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
2930fe6060f1SDimitry Andric   lldb::pid_t pid = GetCurrentProcessID();
2931fe6060f1SDimitry Andric   thread_ids.clear();
2932fe6060f1SDimitry Andric 
2933fe6060f1SDimitry Andric   auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable);
2934fe6060f1SDimitry Andric   if (ids.empty() || sequence_mutex_unavailable)
2935fe6060f1SDimitry Andric     return 0;
2936fe6060f1SDimitry Andric 
2937fe6060f1SDimitry Andric   for (auto id : ids) {
2938fe6060f1SDimitry Andric     // skip threads that do not belong to the current process
2939fe6060f1SDimitry Andric     if (id.first != LLDB_INVALID_PROCESS_ID && id.first != pid)
2940fe6060f1SDimitry Andric       continue;
2941fe6060f1SDimitry Andric     if (id.second != LLDB_INVALID_THREAD_ID &&
2942fe6060f1SDimitry Andric         id.second != StringExtractorGDBRemote::AllThreads)
2943fe6060f1SDimitry Andric       thread_ids.push_back(id.second);
2944fe6060f1SDimitry Andric   }
2945fe6060f1SDimitry Andric 
29460b57cec5SDimitry Andric   return thread_ids.size();
29470b57cec5SDimitry Andric }
29480b57cec5SDimitry Andric 
29490b57cec5SDimitry Andric lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() {
29500b57cec5SDimitry Andric   StringExtractorGDBRemote response;
2951fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse("qShlibInfoAddr", response) !=
29520b57cec5SDimitry Andric           PacketResult::Success ||
29530b57cec5SDimitry Andric       !response.IsNormalResponse())
29540b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
29550b57cec5SDimitry Andric   return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
29560b57cec5SDimitry Andric }
29570b57cec5SDimitry Andric 
29580b57cec5SDimitry Andric lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
2959e8d8bef9SDimitry Andric     llvm::StringRef command,
29600b57cec5SDimitry Andric     const FileSpec &
29610b57cec5SDimitry Andric         working_dir, // Pass empty FileSpec to use the current working directory
29620b57cec5SDimitry Andric     int *status_ptr, // Pass NULL if you don't want the process exit status
29630b57cec5SDimitry Andric     int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
29640b57cec5SDimitry Andric                      // process to exit
29650b57cec5SDimitry Andric     std::string
29660b57cec5SDimitry Andric         *command_output, // Pass NULL if you don't want the command output
29670b57cec5SDimitry Andric     const Timeout<std::micro> &timeout) {
29680b57cec5SDimitry Andric   lldb_private::StreamString stream;
29690b57cec5SDimitry Andric   stream.PutCString("qPlatform_shell:");
2970e8d8bef9SDimitry Andric   stream.PutBytesAsRawHex8(command.data(), command.size());
29710b57cec5SDimitry Andric   stream.PutChar(',');
29720b57cec5SDimitry Andric   uint32_t timeout_sec = UINT32_MAX;
29730b57cec5SDimitry Andric   if (timeout) {
29740b57cec5SDimitry Andric     // TODO: Use chrono version of std::ceil once c++17 is available.
29750b57cec5SDimitry Andric     timeout_sec = std::ceil(std::chrono::duration<double>(*timeout).count());
29760b57cec5SDimitry Andric   }
29770b57cec5SDimitry Andric   stream.PutHex32(timeout_sec);
29780b57cec5SDimitry Andric   if (working_dir) {
29790b57cec5SDimitry Andric     std::string path{working_dir.GetPath(false)};
29800b57cec5SDimitry Andric     stream.PutChar(',');
29810b57cec5SDimitry Andric     stream.PutStringAsRawHex8(path);
29820b57cec5SDimitry Andric   }
29830b57cec5SDimitry Andric   StringExtractorGDBRemote response;
2984fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
29850b57cec5SDimitry Andric       PacketResult::Success) {
29860b57cec5SDimitry Andric     if (response.GetChar() != 'F')
29870b57cec5SDimitry Andric       return Status("malformed reply");
29880b57cec5SDimitry Andric     if (response.GetChar() != ',')
29890b57cec5SDimitry Andric       return Status("malformed reply");
29900b57cec5SDimitry Andric     uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
29910b57cec5SDimitry Andric     if (exitcode == UINT32_MAX)
29920b57cec5SDimitry Andric       return Status("unable to run remote process");
29930b57cec5SDimitry Andric     else if (status_ptr)
29940b57cec5SDimitry Andric       *status_ptr = exitcode;
29950b57cec5SDimitry Andric     if (response.GetChar() != ',')
29960b57cec5SDimitry Andric       return Status("malformed reply");
29970b57cec5SDimitry Andric     uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
29980b57cec5SDimitry Andric     if (signo_ptr)
29990b57cec5SDimitry Andric       *signo_ptr = signo;
30000b57cec5SDimitry Andric     if (response.GetChar() != ',')
30010b57cec5SDimitry Andric       return Status("malformed reply");
30020b57cec5SDimitry Andric     std::string output;
30030b57cec5SDimitry Andric     response.GetEscapedBinaryData(output);
30040b57cec5SDimitry Andric     if (command_output)
30050b57cec5SDimitry Andric       command_output->assign(output);
30060b57cec5SDimitry Andric     return Status();
30070b57cec5SDimitry Andric   }
30080b57cec5SDimitry Andric   return Status("unable to send packet");
30090b57cec5SDimitry Andric }
30100b57cec5SDimitry Andric 
30110b57cec5SDimitry Andric Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec,
30120b57cec5SDimitry Andric                                                    uint32_t file_permissions) {
30130b57cec5SDimitry Andric   std::string path{file_spec.GetPath(false)};
30140b57cec5SDimitry Andric   lldb_private::StreamString stream;
30150b57cec5SDimitry Andric   stream.PutCString("qPlatform_mkdir:");
30160b57cec5SDimitry Andric   stream.PutHex32(file_permissions);
30170b57cec5SDimitry Andric   stream.PutChar(',');
30180b57cec5SDimitry Andric   stream.PutStringAsRawHex8(path);
30190b57cec5SDimitry Andric   llvm::StringRef packet = stream.GetString();
30200b57cec5SDimitry Andric   StringExtractorGDBRemote response;
30210b57cec5SDimitry Andric 
3022fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
30230b57cec5SDimitry Andric     return Status("failed to send '%s' packet", packet.str().c_str());
30240b57cec5SDimitry Andric 
30250b57cec5SDimitry Andric   if (response.GetChar() != 'F')
30260b57cec5SDimitry Andric     return Status("invalid response to '%s' packet", packet.str().c_str());
30270b57cec5SDimitry Andric 
3028349cc55cSDimitry Andric   return Status(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX);
30290b57cec5SDimitry Andric }
30300b57cec5SDimitry Andric 
30310b57cec5SDimitry Andric Status
30320b57cec5SDimitry Andric GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec,
30330b57cec5SDimitry Andric                                                  uint32_t file_permissions) {
30340b57cec5SDimitry Andric   std::string path{file_spec.GetPath(false)};
30350b57cec5SDimitry Andric   lldb_private::StreamString stream;
30360b57cec5SDimitry Andric   stream.PutCString("qPlatform_chmod:");
30370b57cec5SDimitry Andric   stream.PutHex32(file_permissions);
30380b57cec5SDimitry Andric   stream.PutChar(',');
30390b57cec5SDimitry Andric   stream.PutStringAsRawHex8(path);
30400b57cec5SDimitry Andric   llvm::StringRef packet = stream.GetString();
30410b57cec5SDimitry Andric   StringExtractorGDBRemote response;
30420b57cec5SDimitry Andric 
3043fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success)
30440b57cec5SDimitry Andric     return Status("failed to send '%s' packet", stream.GetData());
30450b57cec5SDimitry Andric 
30460b57cec5SDimitry Andric   if (response.GetChar() != 'F')
30470b57cec5SDimitry Andric     return Status("invalid response to '%s' packet", stream.GetData());
30480b57cec5SDimitry Andric 
3049349cc55cSDimitry Andric   return Status(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX);
3050349cc55cSDimitry Andric }
3051349cc55cSDimitry Andric 
3052349cc55cSDimitry Andric static int gdb_errno_to_system(int err) {
3053349cc55cSDimitry Andric   switch (err) {
3054349cc55cSDimitry Andric #define HANDLE_ERRNO(name, value)                                              \
3055349cc55cSDimitry Andric   case GDB_##name:                                                             \
3056349cc55cSDimitry Andric     return name;
3057349cc55cSDimitry Andric #include "Plugins/Process/gdb-remote/GDBRemoteErrno.def"
3058349cc55cSDimitry Andric   default:
3059349cc55cSDimitry Andric     return -1;
3060349cc55cSDimitry Andric   }
30610b57cec5SDimitry Andric }
30620b57cec5SDimitry Andric 
30630b57cec5SDimitry Andric static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response,
30640b57cec5SDimitry Andric                                           uint64_t fail_result, Status &error) {
30650b57cec5SDimitry Andric   response.SetFilePos(0);
30660b57cec5SDimitry Andric   if (response.GetChar() != 'F')
30670b57cec5SDimitry Andric     return fail_result;
3068349cc55cSDimitry Andric   int32_t result = response.GetS32(-2, 16);
30690b57cec5SDimitry Andric   if (result == -2)
30700b57cec5SDimitry Andric     return fail_result;
30710b57cec5SDimitry Andric   if (response.GetChar() == ',') {
3072349cc55cSDimitry Andric     int result_errno = gdb_errno_to_system(response.GetS32(-1, 16));
3073349cc55cSDimitry Andric     if (result_errno != -1)
30740b57cec5SDimitry Andric       error.SetError(result_errno, eErrorTypePOSIX);
30750b57cec5SDimitry Andric     else
30760b57cec5SDimitry Andric       error.SetError(-1, eErrorTypeGeneric);
30770b57cec5SDimitry Andric   } else
30780b57cec5SDimitry Andric     error.Clear();
30790b57cec5SDimitry Andric   return result;
30800b57cec5SDimitry Andric }
30810b57cec5SDimitry Andric lldb::user_id_t
30820b57cec5SDimitry Andric GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec,
30839dba64beSDimitry Andric                                        File::OpenOptions flags, mode_t mode,
30840b57cec5SDimitry Andric                                        Status &error) {
30850b57cec5SDimitry Andric   std::string path(file_spec.GetPath(false));
30860b57cec5SDimitry Andric   lldb_private::StreamString stream;
30870b57cec5SDimitry Andric   stream.PutCString("vFile:open:");
30880b57cec5SDimitry Andric   if (path.empty())
30890b57cec5SDimitry Andric     return UINT64_MAX;
30900b57cec5SDimitry Andric   stream.PutStringAsRawHex8(path);
30910b57cec5SDimitry Andric   stream.PutChar(',');
30920b57cec5SDimitry Andric   stream.PutHex32(flags);
30930b57cec5SDimitry Andric   stream.PutChar(',');
30940b57cec5SDimitry Andric   stream.PutHex32(mode);
30950b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3096fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
30970b57cec5SDimitry Andric       PacketResult::Success) {
30980b57cec5SDimitry Andric     return ParseHostIOPacketResponse(response, UINT64_MAX, error);
30990b57cec5SDimitry Andric   }
31000b57cec5SDimitry Andric   return UINT64_MAX;
31010b57cec5SDimitry Andric }
31020b57cec5SDimitry Andric 
31030b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd,
31040b57cec5SDimitry Andric                                              Status &error) {
31050b57cec5SDimitry Andric   lldb_private::StreamString stream;
3106349cc55cSDimitry Andric   stream.Printf("vFile:close:%x", (int)fd);
31070b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3108fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
31090b57cec5SDimitry Andric       PacketResult::Success) {
31100b57cec5SDimitry Andric     return ParseHostIOPacketResponse(response, -1, error) == 0;
31110b57cec5SDimitry Andric   }
31120b57cec5SDimitry Andric   return false;
31130b57cec5SDimitry Andric }
31140b57cec5SDimitry Andric 
3115bdd1243dSDimitry Andric std::optional<GDBRemoteFStatData>
3116349cc55cSDimitry Andric GDBRemoteCommunicationClient::FStat(lldb::user_id_t fd) {
3117349cc55cSDimitry Andric   lldb_private::StreamString stream;
3118349cc55cSDimitry Andric   stream.Printf("vFile:fstat:%" PRIx64, fd);
3119349cc55cSDimitry Andric   StringExtractorGDBRemote response;
3120349cc55cSDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3121349cc55cSDimitry Andric       PacketResult::Success) {
3122349cc55cSDimitry Andric     if (response.GetChar() != 'F')
3123bdd1243dSDimitry Andric       return std::nullopt;
3124349cc55cSDimitry Andric     int64_t size = response.GetS64(-1, 16);
3125349cc55cSDimitry Andric     if (size > 0 && response.GetChar() == ';') {
3126349cc55cSDimitry Andric       std::string buffer;
3127349cc55cSDimitry Andric       if (response.GetEscapedBinaryData(buffer)) {
3128349cc55cSDimitry Andric         GDBRemoteFStatData out;
3129349cc55cSDimitry Andric         if (buffer.size() != sizeof(out))
3130bdd1243dSDimitry Andric           return std::nullopt;
3131349cc55cSDimitry Andric         memcpy(&out, buffer.data(), sizeof(out));
3132349cc55cSDimitry Andric         return out;
3133349cc55cSDimitry Andric       }
3134349cc55cSDimitry Andric     }
3135349cc55cSDimitry Andric   }
3136bdd1243dSDimitry Andric   return std::nullopt;
3137349cc55cSDimitry Andric }
3138349cc55cSDimitry Andric 
3139bdd1243dSDimitry Andric std::optional<GDBRemoteFStatData>
3140349cc55cSDimitry Andric GDBRemoteCommunicationClient::Stat(const lldb_private::FileSpec &file_spec) {
3141349cc55cSDimitry Andric   Status error;
3142349cc55cSDimitry Andric   lldb::user_id_t fd = OpenFile(file_spec, File::eOpenOptionReadOnly, 0, error);
3143349cc55cSDimitry Andric   if (fd == UINT64_MAX)
3144bdd1243dSDimitry Andric     return std::nullopt;
3145bdd1243dSDimitry Andric   std::optional<GDBRemoteFStatData> st = FStat(fd);
3146349cc55cSDimitry Andric   CloseFile(fd, error);
3147349cc55cSDimitry Andric   return st;
3148349cc55cSDimitry Andric }
3149349cc55cSDimitry Andric 
31500b57cec5SDimitry Andric // Extension of host I/O packets to get the file size.
31510b57cec5SDimitry Andric lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize(
31520b57cec5SDimitry Andric     const lldb_private::FileSpec &file_spec) {
3153349cc55cSDimitry Andric   if (m_supports_vFileSize) {
31540b57cec5SDimitry Andric     std::string path(file_spec.GetPath(false));
31550b57cec5SDimitry Andric     lldb_private::StreamString stream;
31560b57cec5SDimitry Andric     stream.PutCString("vFile:size:");
31570b57cec5SDimitry Andric     stream.PutStringAsRawHex8(path);
31580b57cec5SDimitry Andric     StringExtractorGDBRemote response;
3159349cc55cSDimitry Andric     if (SendPacketAndWaitForResponse(stream.GetString(), response) !=
3160349cc55cSDimitry Andric         PacketResult::Success)
3161349cc55cSDimitry Andric       return UINT64_MAX;
3162349cc55cSDimitry Andric 
3163349cc55cSDimitry Andric     if (!response.IsUnsupportedResponse()) {
31640b57cec5SDimitry Andric       if (response.GetChar() != 'F')
31650b57cec5SDimitry Andric         return UINT64_MAX;
31660b57cec5SDimitry Andric       uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
31670b57cec5SDimitry Andric       return retcode;
31680b57cec5SDimitry Andric     }
3169349cc55cSDimitry Andric     m_supports_vFileSize = false;
3170349cc55cSDimitry Andric   }
3171349cc55cSDimitry Andric 
3172349cc55cSDimitry Andric   // Fallback to fstat.
3173bdd1243dSDimitry Andric   std::optional<GDBRemoteFStatData> st = Stat(file_spec);
3174349cc55cSDimitry Andric   return st ? st->gdb_st_size : UINT64_MAX;
31750b57cec5SDimitry Andric }
31760b57cec5SDimitry Andric 
3177e8d8bef9SDimitry Andric void GDBRemoteCommunicationClient::AutoCompleteDiskFileOrDirectory(
3178e8d8bef9SDimitry Andric     CompletionRequest &request, bool only_dir) {
3179e8d8bef9SDimitry Andric   lldb_private::StreamString stream;
3180e8d8bef9SDimitry Andric   stream.PutCString("qPathComplete:");
3181e8d8bef9SDimitry Andric   stream.PutHex32(only_dir ? 1 : 0);
3182e8d8bef9SDimitry Andric   stream.PutChar(',');
3183e8d8bef9SDimitry Andric   stream.PutStringAsRawHex8(request.GetCursorArgumentPrefix());
3184e8d8bef9SDimitry Andric   StringExtractorGDBRemote response;
3185fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
3186e8d8bef9SDimitry Andric       PacketResult::Success) {
3187e8d8bef9SDimitry Andric     StreamString strm;
3188e8d8bef9SDimitry Andric     char ch = response.GetChar();
3189e8d8bef9SDimitry Andric     if (ch != 'M')
3190e8d8bef9SDimitry Andric       return;
3191e8d8bef9SDimitry Andric     while (response.Peek()) {
3192e8d8bef9SDimitry Andric       strm.Clear();
3193e8d8bef9SDimitry Andric       while ((ch = response.GetHexU8(0, false)) != '\0')
3194e8d8bef9SDimitry Andric         strm.PutChar(ch);
3195e8d8bef9SDimitry Andric       request.AddCompletion(strm.GetString());
3196e8d8bef9SDimitry Andric       if (response.GetChar() != ',')
3197e8d8bef9SDimitry Andric         break;
3198e8d8bef9SDimitry Andric     }
3199e8d8bef9SDimitry Andric   }
3200e8d8bef9SDimitry Andric }
3201e8d8bef9SDimitry Andric 
32020b57cec5SDimitry Andric Status
32030b57cec5SDimitry Andric GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec,
32040b57cec5SDimitry Andric                                                  uint32_t &file_permissions) {
3205349cc55cSDimitry Andric   if (m_supports_vFileMode) {
32060b57cec5SDimitry Andric     std::string path{file_spec.GetPath(false)};
32070b57cec5SDimitry Andric     Status error;
32080b57cec5SDimitry Andric     lldb_private::StreamString stream;
32090b57cec5SDimitry Andric     stream.PutCString("vFile:mode:");
32100b57cec5SDimitry Andric     stream.PutStringAsRawHex8(path);
32110b57cec5SDimitry Andric     StringExtractorGDBRemote response;
3212349cc55cSDimitry Andric     if (SendPacketAndWaitForResponse(stream.GetString(), response) !=
32130b57cec5SDimitry Andric         PacketResult::Success) {
3214349cc55cSDimitry Andric       error.SetErrorStringWithFormat("failed to send '%s' packet",
3215349cc55cSDimitry Andric                                      stream.GetData());
3216349cc55cSDimitry Andric       return error;
3217349cc55cSDimitry Andric     }
3218349cc55cSDimitry Andric     if (!response.IsUnsupportedResponse()) {
32190b57cec5SDimitry Andric       if (response.GetChar() != 'F') {
32200b57cec5SDimitry Andric         error.SetErrorStringWithFormat("invalid response to '%s' packet",
32210b57cec5SDimitry Andric                                        stream.GetData());
32220b57cec5SDimitry Andric       } else {
3223349cc55cSDimitry Andric         const uint32_t mode = response.GetS32(-1, 16);
32240b57cec5SDimitry Andric         if (static_cast<int32_t>(mode) == -1) {
32250b57cec5SDimitry Andric           if (response.GetChar() == ',') {
3226349cc55cSDimitry Andric             int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
32270b57cec5SDimitry Andric             if (response_errno > 0)
32280b57cec5SDimitry Andric               error.SetError(response_errno, lldb::eErrorTypePOSIX);
32290b57cec5SDimitry Andric             else
32300b57cec5SDimitry Andric               error.SetErrorToGenericError();
32310b57cec5SDimitry Andric           } else
32320b57cec5SDimitry Andric             error.SetErrorToGenericError();
32330b57cec5SDimitry Andric         } else {
32340b57cec5SDimitry Andric           file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO);
32350b57cec5SDimitry Andric         }
32360b57cec5SDimitry Andric       }
32370b57cec5SDimitry Andric       return error;
3238349cc55cSDimitry Andric     } else { // response.IsUnsupportedResponse()
3239349cc55cSDimitry Andric       m_supports_vFileMode = false;
3240349cc55cSDimitry Andric     }
3241349cc55cSDimitry Andric   }
3242349cc55cSDimitry Andric 
3243349cc55cSDimitry Andric   // Fallback to fstat.
3244bdd1243dSDimitry Andric   if (std::optional<GDBRemoteFStatData> st = Stat(file_spec)) {
3245349cc55cSDimitry Andric     file_permissions = st->gdb_st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
3246349cc55cSDimitry Andric     return Status();
3247349cc55cSDimitry Andric   }
3248349cc55cSDimitry Andric   return Status("fstat failed");
32490b57cec5SDimitry Andric }
32500b57cec5SDimitry Andric 
32510b57cec5SDimitry Andric uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd,
32520b57cec5SDimitry Andric                                                 uint64_t offset, void *dst,
32530b57cec5SDimitry Andric                                                 uint64_t dst_len,
32540b57cec5SDimitry Andric                                                 Status &error) {
32550b57cec5SDimitry Andric   lldb_private::StreamString stream;
3256349cc55cSDimitry Andric   stream.Printf("vFile:pread:%x,%" PRIx64 ",%" PRIx64, (int)fd, dst_len,
32570b57cec5SDimitry Andric                 offset);
32580b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3259fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
32600b57cec5SDimitry Andric       PacketResult::Success) {
32610b57cec5SDimitry Andric     if (response.GetChar() != 'F')
32620b57cec5SDimitry Andric       return 0;
3263349cc55cSDimitry Andric     int64_t retcode = response.GetS64(-1, 16);
3264349cc55cSDimitry Andric     if (retcode == -1) {
3265349cc55cSDimitry Andric       error.SetErrorToGenericError();
3266349cc55cSDimitry Andric       if (response.GetChar() == ',') {
3267349cc55cSDimitry Andric         int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
3268349cc55cSDimitry Andric         if (response_errno > 0)
3269349cc55cSDimitry Andric           error.SetError(response_errno, lldb::eErrorTypePOSIX);
3270349cc55cSDimitry Andric       }
3271349cc55cSDimitry Andric       return -1;
3272349cc55cSDimitry Andric     }
32730b57cec5SDimitry Andric     const char next = (response.Peek() ? *response.Peek() : 0);
32740b57cec5SDimitry Andric     if (next == ',')
32750b57cec5SDimitry Andric       return 0;
32760b57cec5SDimitry Andric     if (next == ';') {
32770b57cec5SDimitry Andric       response.GetChar(); // skip the semicolon
32780b57cec5SDimitry Andric       std::string buffer;
32790b57cec5SDimitry Andric       if (response.GetEscapedBinaryData(buffer)) {
32800b57cec5SDimitry Andric         const uint64_t data_to_write =
32810b57cec5SDimitry Andric             std::min<uint64_t>(dst_len, buffer.size());
32820b57cec5SDimitry Andric         if (data_to_write > 0)
32830b57cec5SDimitry Andric           memcpy(dst, &buffer[0], data_to_write);
32840b57cec5SDimitry Andric         return data_to_write;
32850b57cec5SDimitry Andric       }
32860b57cec5SDimitry Andric     }
32870b57cec5SDimitry Andric   }
32880b57cec5SDimitry Andric   return 0;
32890b57cec5SDimitry Andric }
32900b57cec5SDimitry Andric 
32910b57cec5SDimitry Andric uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd,
32920b57cec5SDimitry Andric                                                  uint64_t offset,
32930b57cec5SDimitry Andric                                                  const void *src,
32940b57cec5SDimitry Andric                                                  uint64_t src_len,
32950b57cec5SDimitry Andric                                                  Status &error) {
32960b57cec5SDimitry Andric   lldb_private::StreamGDBRemote stream;
3297349cc55cSDimitry Andric   stream.Printf("vFile:pwrite:%x,%" PRIx64 ",", (int)fd, offset);
32980b57cec5SDimitry Andric   stream.PutEscapedBytes(src, src_len);
32990b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3300fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
33010b57cec5SDimitry Andric       PacketResult::Success) {
33020b57cec5SDimitry Andric     if (response.GetChar() != 'F') {
33030b57cec5SDimitry Andric       error.SetErrorStringWithFormat("write file failed");
33040b57cec5SDimitry Andric       return 0;
33050b57cec5SDimitry Andric     }
3306349cc55cSDimitry Andric     int64_t bytes_written = response.GetS64(-1, 16);
3307349cc55cSDimitry Andric     if (bytes_written == -1) {
33080b57cec5SDimitry Andric       error.SetErrorToGenericError();
33090b57cec5SDimitry Andric       if (response.GetChar() == ',') {
3310349cc55cSDimitry Andric         int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
33110b57cec5SDimitry Andric         if (response_errno > 0)
33120b57cec5SDimitry Andric           error.SetError(response_errno, lldb::eErrorTypePOSIX);
33130b57cec5SDimitry Andric       }
3314349cc55cSDimitry Andric       return -1;
33150b57cec5SDimitry Andric     }
33160b57cec5SDimitry Andric     return bytes_written;
33170b57cec5SDimitry Andric   } else {
33180b57cec5SDimitry Andric     error.SetErrorString("failed to send vFile:pwrite packet");
33190b57cec5SDimitry Andric   }
33200b57cec5SDimitry Andric   return 0;
33210b57cec5SDimitry Andric }
33220b57cec5SDimitry Andric 
33230b57cec5SDimitry Andric Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src,
33240b57cec5SDimitry Andric                                                    const FileSpec &dst) {
33250b57cec5SDimitry Andric   std::string src_path{src.GetPath(false)}, dst_path{dst.GetPath(false)};
33260b57cec5SDimitry Andric   Status error;
33270b57cec5SDimitry Andric   lldb_private::StreamGDBRemote stream;
33280b57cec5SDimitry Andric   stream.PutCString("vFile:symlink:");
33290b57cec5SDimitry Andric   // the unix symlink() command reverses its parameters where the dst if first,
33300b57cec5SDimitry Andric   // so we follow suit here
33310b57cec5SDimitry Andric   stream.PutStringAsRawHex8(dst_path);
33320b57cec5SDimitry Andric   stream.PutChar(',');
33330b57cec5SDimitry Andric   stream.PutStringAsRawHex8(src_path);
33340b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3335fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
33360b57cec5SDimitry Andric       PacketResult::Success) {
33370b57cec5SDimitry Andric     if (response.GetChar() == 'F') {
3338349cc55cSDimitry Andric       uint32_t result = response.GetHexMaxU32(false, UINT32_MAX);
33390b57cec5SDimitry Andric       if (result != 0) {
33400b57cec5SDimitry Andric         error.SetErrorToGenericError();
33410b57cec5SDimitry Andric         if (response.GetChar() == ',') {
3342349cc55cSDimitry Andric           int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
33430b57cec5SDimitry Andric           if (response_errno > 0)
33440b57cec5SDimitry Andric             error.SetError(response_errno, lldb::eErrorTypePOSIX);
33450b57cec5SDimitry Andric         }
33460b57cec5SDimitry Andric       }
33470b57cec5SDimitry Andric     } else {
33480b57cec5SDimitry Andric       // Should have returned with 'F<result>[,<errno>]'
33490b57cec5SDimitry Andric       error.SetErrorStringWithFormat("symlink failed");
33500b57cec5SDimitry Andric     }
33510b57cec5SDimitry Andric   } else {
33520b57cec5SDimitry Andric     error.SetErrorString("failed to send vFile:symlink packet");
33530b57cec5SDimitry Andric   }
33540b57cec5SDimitry Andric   return error;
33550b57cec5SDimitry Andric }
33560b57cec5SDimitry Andric 
33570b57cec5SDimitry Andric Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) {
33580b57cec5SDimitry Andric   std::string path{file_spec.GetPath(false)};
33590b57cec5SDimitry Andric   Status error;
33600b57cec5SDimitry Andric   lldb_private::StreamGDBRemote stream;
33610b57cec5SDimitry Andric   stream.PutCString("vFile:unlink:");
33620b57cec5SDimitry Andric   // the unix symlink() command reverses its parameters where the dst if first,
33630b57cec5SDimitry Andric   // so we follow suit here
33640b57cec5SDimitry Andric   stream.PutStringAsRawHex8(path);
33650b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3366fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
33670b57cec5SDimitry Andric       PacketResult::Success) {
33680b57cec5SDimitry Andric     if (response.GetChar() == 'F') {
3369349cc55cSDimitry Andric       uint32_t result = response.GetHexMaxU32(false, UINT32_MAX);
33700b57cec5SDimitry Andric       if (result != 0) {
33710b57cec5SDimitry Andric         error.SetErrorToGenericError();
33720b57cec5SDimitry Andric         if (response.GetChar() == ',') {
3373349cc55cSDimitry Andric           int response_errno = gdb_errno_to_system(response.GetS32(-1, 16));
33740b57cec5SDimitry Andric           if (response_errno > 0)
33750b57cec5SDimitry Andric             error.SetError(response_errno, lldb::eErrorTypePOSIX);
33760b57cec5SDimitry Andric         }
33770b57cec5SDimitry Andric       }
33780b57cec5SDimitry Andric     } else {
33790b57cec5SDimitry Andric       // Should have returned with 'F<result>[,<errno>]'
33800b57cec5SDimitry Andric       error.SetErrorStringWithFormat("unlink failed");
33810b57cec5SDimitry Andric     }
33820b57cec5SDimitry Andric   } else {
33830b57cec5SDimitry Andric     error.SetErrorString("failed to send vFile:unlink packet");
33840b57cec5SDimitry Andric   }
33850b57cec5SDimitry Andric   return error;
33860b57cec5SDimitry Andric }
33870b57cec5SDimitry Andric 
33880b57cec5SDimitry Andric // Extension of host I/O packets to get whether a file exists.
33890b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetFileExists(
33900b57cec5SDimitry Andric     const lldb_private::FileSpec &file_spec) {
3391349cc55cSDimitry Andric   if (m_supports_vFileExists) {
33920b57cec5SDimitry Andric     std::string path(file_spec.GetPath(false));
33930b57cec5SDimitry Andric     lldb_private::StreamString stream;
33940b57cec5SDimitry Andric     stream.PutCString("vFile:exists:");
33950b57cec5SDimitry Andric     stream.PutStringAsRawHex8(path);
33960b57cec5SDimitry Andric     StringExtractorGDBRemote response;
3397349cc55cSDimitry Andric     if (SendPacketAndWaitForResponse(stream.GetString(), response) !=
3398349cc55cSDimitry Andric         PacketResult::Success)
3399349cc55cSDimitry Andric       return false;
3400349cc55cSDimitry Andric     if (!response.IsUnsupportedResponse()) {
34010b57cec5SDimitry Andric       if (response.GetChar() != 'F')
34020b57cec5SDimitry Andric         return false;
34030b57cec5SDimitry Andric       if (response.GetChar() != ',')
34040b57cec5SDimitry Andric         return false;
34050b57cec5SDimitry Andric       bool retcode = (response.GetChar() != '0');
34060b57cec5SDimitry Andric       return retcode;
3407349cc55cSDimitry Andric     } else
3408349cc55cSDimitry Andric       m_supports_vFileExists = false;
34090b57cec5SDimitry Andric   }
3410349cc55cSDimitry Andric 
3411349cc55cSDimitry Andric   // Fallback to open.
3412349cc55cSDimitry Andric   Status error;
3413349cc55cSDimitry Andric   lldb::user_id_t fd = OpenFile(file_spec, File::eOpenOptionReadOnly, 0, error);
3414349cc55cSDimitry Andric   if (fd == UINT64_MAX)
34150b57cec5SDimitry Andric     return false;
3416349cc55cSDimitry Andric   CloseFile(fd, error);
3417349cc55cSDimitry Andric   return true;
34180b57cec5SDimitry Andric }
34190b57cec5SDimitry Andric 
3420*0fca6ea1SDimitry Andric llvm::ErrorOr<llvm::MD5::MD5Result> GDBRemoteCommunicationClient::CalculateMD5(
3421*0fca6ea1SDimitry Andric     const lldb_private::FileSpec &file_spec) {
34220b57cec5SDimitry Andric   std::string path(file_spec.GetPath(false));
34230b57cec5SDimitry Andric   lldb_private::StreamString stream;
34240b57cec5SDimitry Andric   stream.PutCString("vFile:MD5:");
34250b57cec5SDimitry Andric   stream.PutStringAsRawHex8(path);
34260b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3427fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
34280b57cec5SDimitry Andric       PacketResult::Success) {
34290b57cec5SDimitry Andric     if (response.GetChar() != 'F')
3430*0fca6ea1SDimitry Andric       return std::make_error_code(std::errc::illegal_byte_sequence);
34310b57cec5SDimitry Andric     if (response.GetChar() != ',')
3432*0fca6ea1SDimitry Andric       return std::make_error_code(std::errc::illegal_byte_sequence);
34330b57cec5SDimitry Andric     if (response.Peek() && *response.Peek() == 'x')
3434*0fca6ea1SDimitry Andric       return std::make_error_code(std::errc::no_such_file_or_directory);
3435*0fca6ea1SDimitry Andric 
3436*0fca6ea1SDimitry Andric     // GDBRemoteCommunicationServerCommon::Handle_vFile_MD5 concatenates low and
3437*0fca6ea1SDimitry Andric     // high hex strings. We can't use response.GetHexMaxU64 because that can't
3438*0fca6ea1SDimitry Andric     // handle the concatenated hex string. What would happen is parsing the low
3439*0fca6ea1SDimitry Andric     // would consume the whole response packet which would give incorrect
3440*0fca6ea1SDimitry Andric     // results. Instead, we get the byte string for each low and high hex
3441*0fca6ea1SDimitry Andric     // separately, and parse them.
3442*0fca6ea1SDimitry Andric     //
3443*0fca6ea1SDimitry Andric     // An alternate way to handle this is to change the server to put a
3444*0fca6ea1SDimitry Andric     // delimiter between the low/high parts, and change the client to parse the
3445*0fca6ea1SDimitry Andric     // delimiter. However, we choose not to do this so existing lldb-servers
3446*0fca6ea1SDimitry Andric     // don't have to be patched
3447*0fca6ea1SDimitry Andric 
3448*0fca6ea1SDimitry Andric     // The checksum is 128 bits encoded as hex
3449*0fca6ea1SDimitry Andric     // This means low/high are halves of 64 bits each, in otherwords, 8 bytes.
3450*0fca6ea1SDimitry Andric     // Each byte takes 2 hex characters in the response.
3451*0fca6ea1SDimitry Andric     const size_t MD5_HALF_LENGTH = sizeof(uint64_t) * 2;
3452*0fca6ea1SDimitry Andric 
3453*0fca6ea1SDimitry Andric     // Get low part
3454*0fca6ea1SDimitry Andric     auto part =
3455*0fca6ea1SDimitry Andric         response.GetStringRef().substr(response.GetFilePos(), MD5_HALF_LENGTH);
3456*0fca6ea1SDimitry Andric     if (part.size() != MD5_HALF_LENGTH)
3457*0fca6ea1SDimitry Andric       return std::make_error_code(std::errc::illegal_byte_sequence);
3458*0fca6ea1SDimitry Andric     response.SetFilePos(response.GetFilePos() + part.size());
3459*0fca6ea1SDimitry Andric 
3460*0fca6ea1SDimitry Andric     uint64_t low;
3461*0fca6ea1SDimitry Andric     if (part.getAsInteger(/*radix=*/16, low))
3462*0fca6ea1SDimitry Andric       return std::make_error_code(std::errc::illegal_byte_sequence);
3463*0fca6ea1SDimitry Andric 
3464*0fca6ea1SDimitry Andric     // Get high part
3465*0fca6ea1SDimitry Andric     part =
3466*0fca6ea1SDimitry Andric         response.GetStringRef().substr(response.GetFilePos(), MD5_HALF_LENGTH);
3467*0fca6ea1SDimitry Andric     if (part.size() != MD5_HALF_LENGTH)
3468*0fca6ea1SDimitry Andric       return std::make_error_code(std::errc::illegal_byte_sequence);
3469*0fca6ea1SDimitry Andric     response.SetFilePos(response.GetFilePos() + part.size());
3470*0fca6ea1SDimitry Andric 
3471*0fca6ea1SDimitry Andric     uint64_t high;
3472*0fca6ea1SDimitry Andric     if (part.getAsInteger(/*radix=*/16, high))
3473*0fca6ea1SDimitry Andric       return std::make_error_code(std::errc::illegal_byte_sequence);
3474*0fca6ea1SDimitry Andric 
3475*0fca6ea1SDimitry Andric     llvm::MD5::MD5Result result;
3476*0fca6ea1SDimitry Andric     llvm::support::endian::write<uint64_t, llvm::endianness::little>(
3477*0fca6ea1SDimitry Andric         result.data(), low);
3478*0fca6ea1SDimitry Andric     llvm::support::endian::write<uint64_t, llvm::endianness::little>(
3479*0fca6ea1SDimitry Andric         result.data() + 8, high);
3480*0fca6ea1SDimitry Andric 
3481*0fca6ea1SDimitry Andric     return result;
34820b57cec5SDimitry Andric   }
3483*0fca6ea1SDimitry Andric   return std::make_error_code(std::errc::operation_canceled);
34840b57cec5SDimitry Andric }
34850b57cec5SDimitry Andric 
34860b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) {
34870b57cec5SDimitry Andric   // Some targets have issues with g/G packets and we need to avoid using them
34880b57cec5SDimitry Andric   if (m_avoid_g_packets == eLazyBoolCalculate) {
34890b57cec5SDimitry Andric     if (process) {
34900b57cec5SDimitry Andric       m_avoid_g_packets = eLazyBoolNo;
34910b57cec5SDimitry Andric       const ArchSpec &arch = process->GetTarget().GetArchitecture();
34920b57cec5SDimitry Andric       if (arch.IsValid() &&
34930b57cec5SDimitry Andric           arch.GetTriple().getVendor() == llvm::Triple::Apple &&
34940b57cec5SDimitry Andric           arch.GetTriple().getOS() == llvm::Triple::IOS &&
34959dba64beSDimitry Andric           (arch.GetTriple().getArch() == llvm::Triple::aarch64 ||
34969dba64beSDimitry Andric            arch.GetTriple().getArch() == llvm::Triple::aarch64_32)) {
34970b57cec5SDimitry Andric         m_avoid_g_packets = eLazyBoolYes;
34980b57cec5SDimitry Andric         uint32_t gdb_server_version = GetGDBServerProgramVersion();
34990b57cec5SDimitry Andric         if (gdb_server_version != 0) {
35000b57cec5SDimitry Andric           const char *gdb_server_name = GetGDBServerProgramName();
35010b57cec5SDimitry Andric           if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0) {
35020b57cec5SDimitry Andric             if (gdb_server_version >= 310)
35030b57cec5SDimitry Andric               m_avoid_g_packets = eLazyBoolNo;
35040b57cec5SDimitry Andric           }
35050b57cec5SDimitry Andric         }
35060b57cec5SDimitry Andric       }
35070b57cec5SDimitry Andric     }
35080b57cec5SDimitry Andric   }
35090b57cec5SDimitry Andric   return m_avoid_g_packets == eLazyBoolYes;
35100b57cec5SDimitry Andric }
35110b57cec5SDimitry Andric 
35120b57cec5SDimitry Andric DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid,
35130b57cec5SDimitry Andric                                                         uint32_t reg) {
35140b57cec5SDimitry Andric   StreamString payload;
35150b57cec5SDimitry Andric   payload.Printf("p%x", reg);
35160b57cec5SDimitry Andric   StringExtractorGDBRemote response;
35170b57cec5SDimitry Andric   if (SendThreadSpecificPacketAndWaitForResponse(
3518fe6060f1SDimitry Andric           tid, std::move(payload), response) != PacketResult::Success ||
35190b57cec5SDimitry Andric       !response.IsNormalResponse())
35200b57cec5SDimitry Andric     return nullptr;
35210b57cec5SDimitry Andric 
352281ad6265SDimitry Andric   WritableDataBufferSP buffer_sp(
35230b57cec5SDimitry Andric       new DataBufferHeap(response.GetStringRef().size() / 2, 0));
35240b57cec5SDimitry Andric   response.GetHexBytes(buffer_sp->GetData(), '\xcc');
35250b57cec5SDimitry Andric   return buffer_sp;
35260b57cec5SDimitry Andric }
35270b57cec5SDimitry Andric 
35280b57cec5SDimitry Andric DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) {
35290b57cec5SDimitry Andric   StreamString payload;
35300b57cec5SDimitry Andric   payload.PutChar('g');
35310b57cec5SDimitry Andric   StringExtractorGDBRemote response;
35320b57cec5SDimitry Andric   if (SendThreadSpecificPacketAndWaitForResponse(
3533fe6060f1SDimitry Andric           tid, std::move(payload), response) != PacketResult::Success ||
35340b57cec5SDimitry Andric       !response.IsNormalResponse())
35350b57cec5SDimitry Andric     return nullptr;
35360b57cec5SDimitry Andric 
353781ad6265SDimitry Andric   WritableDataBufferSP buffer_sp(
35380b57cec5SDimitry Andric       new DataBufferHeap(response.GetStringRef().size() / 2, 0));
35390b57cec5SDimitry Andric   response.GetHexBytes(buffer_sp->GetData(), '\xcc');
35400b57cec5SDimitry Andric   return buffer_sp;
35410b57cec5SDimitry Andric }
35420b57cec5SDimitry Andric 
35430b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid,
35440b57cec5SDimitry Andric                                                  uint32_t reg_num,
35450b57cec5SDimitry Andric                                                  llvm::ArrayRef<uint8_t> data) {
35460b57cec5SDimitry Andric   StreamString payload;
35470b57cec5SDimitry Andric   payload.Printf("P%x=", reg_num);
35480b57cec5SDimitry Andric   payload.PutBytesAsRawHex8(data.data(), data.size(),
35490b57cec5SDimitry Andric                             endian::InlHostByteOrder(),
35500b57cec5SDimitry Andric                             endian::InlHostByteOrder());
35510b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3552fe6060f1SDimitry Andric   return SendThreadSpecificPacketAndWaitForResponse(
3553fe6060f1SDimitry Andric              tid, std::move(payload), response) == PacketResult::Success &&
35540b57cec5SDimitry Andric          response.IsOKResponse();
35550b57cec5SDimitry Andric }
35560b57cec5SDimitry Andric 
35570b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::WriteAllRegisters(
35580b57cec5SDimitry Andric     lldb::tid_t tid, llvm::ArrayRef<uint8_t> data) {
35590b57cec5SDimitry Andric   StreamString payload;
35600b57cec5SDimitry Andric   payload.PutChar('G');
35610b57cec5SDimitry Andric   payload.PutBytesAsRawHex8(data.data(), data.size(),
35620b57cec5SDimitry Andric                             endian::InlHostByteOrder(),
35630b57cec5SDimitry Andric                             endian::InlHostByteOrder());
35640b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3565fe6060f1SDimitry Andric   return SendThreadSpecificPacketAndWaitForResponse(
3566fe6060f1SDimitry Andric              tid, std::move(payload), response) == PacketResult::Success &&
35670b57cec5SDimitry Andric          response.IsOKResponse();
35680b57cec5SDimitry Andric }
35690b57cec5SDimitry Andric 
35700b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
35710b57cec5SDimitry Andric                                                      uint32_t &save_id) {
35720b57cec5SDimitry Andric   save_id = 0; // Set to invalid save ID
35730b57cec5SDimitry Andric   if (m_supports_QSaveRegisterState == eLazyBoolNo)
35740b57cec5SDimitry Andric     return false;
35750b57cec5SDimitry Andric 
35760b57cec5SDimitry Andric   m_supports_QSaveRegisterState = eLazyBoolYes;
35770b57cec5SDimitry Andric   StreamString payload;
35780b57cec5SDimitry Andric   payload.PutCString("QSaveRegisterState");
35790b57cec5SDimitry Andric   StringExtractorGDBRemote response;
35800b57cec5SDimitry Andric   if (SendThreadSpecificPacketAndWaitForResponse(
3581fe6060f1SDimitry Andric           tid, std::move(payload), response) != PacketResult::Success)
35820b57cec5SDimitry Andric     return false;
35830b57cec5SDimitry Andric 
35840b57cec5SDimitry Andric   if (response.IsUnsupportedResponse())
35850b57cec5SDimitry Andric     m_supports_QSaveRegisterState = eLazyBoolNo;
35860b57cec5SDimitry Andric 
35870b57cec5SDimitry Andric   const uint32_t response_save_id = response.GetU32(0);
35880b57cec5SDimitry Andric   if (response_save_id == 0)
35890b57cec5SDimitry Andric     return false;
35900b57cec5SDimitry Andric 
35910b57cec5SDimitry Andric   save_id = response_save_id;
35920b57cec5SDimitry Andric   return true;
35930b57cec5SDimitry Andric }
35940b57cec5SDimitry Andric 
35950b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
35960b57cec5SDimitry Andric                                                         uint32_t save_id) {
35970b57cec5SDimitry Andric   // We use the "m_supports_QSaveRegisterState" variable here because the
35980b57cec5SDimitry Andric   // QSaveRegisterState and QRestoreRegisterState packets must both be
35990b57cec5SDimitry Andric   // supported in order to be useful
36000b57cec5SDimitry Andric   if (m_supports_QSaveRegisterState == eLazyBoolNo)
36010b57cec5SDimitry Andric     return false;
36020b57cec5SDimitry Andric 
36030b57cec5SDimitry Andric   StreamString payload;
36040b57cec5SDimitry Andric   payload.Printf("QRestoreRegisterState:%u", save_id);
36050b57cec5SDimitry Andric   StringExtractorGDBRemote response;
36060b57cec5SDimitry Andric   if (SendThreadSpecificPacketAndWaitForResponse(
3607fe6060f1SDimitry Andric           tid, std::move(payload), response) != PacketResult::Success)
36080b57cec5SDimitry Andric     return false;
36090b57cec5SDimitry Andric 
36100b57cec5SDimitry Andric   if (response.IsOKResponse())
36110b57cec5SDimitry Andric     return true;
36120b57cec5SDimitry Andric 
36130b57cec5SDimitry Andric   if (response.IsUnsupportedResponse())
36140b57cec5SDimitry Andric     m_supports_QSaveRegisterState = eLazyBoolNo;
36150b57cec5SDimitry Andric   return false;
36160b57cec5SDimitry Andric }
36170b57cec5SDimitry Andric 
36180b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) {
36190b57cec5SDimitry Andric   if (!GetSyncThreadStateSupported())
36200b57cec5SDimitry Andric     return false;
36210b57cec5SDimitry Andric 
36220b57cec5SDimitry Andric   StreamString packet;
36230b57cec5SDimitry Andric   StringExtractorGDBRemote response;
36240b57cec5SDimitry Andric   packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid);
3625fe6060f1SDimitry Andric   return SendPacketAndWaitForResponse(packet.GetString(), response) ==
36260b57cec5SDimitry Andric              GDBRemoteCommunication::PacketResult::Success &&
36270b57cec5SDimitry Andric          response.IsOKResponse();
36280b57cec5SDimitry Andric }
36290b57cec5SDimitry Andric 
3630fe6060f1SDimitry Andric llvm::Expected<TraceSupportedResponse>
3631fe6060f1SDimitry Andric GDBRemoteCommunicationClient::SendTraceSupported(std::chrono::seconds timeout) {
36321fd87a68SDimitry Andric   Log *log = GetLog(GDBRLog::Process);
3633e8d8bef9SDimitry Andric 
3634e8d8bef9SDimitry Andric   StreamGDBRemote escaped_packet;
3635fe6060f1SDimitry Andric   escaped_packet.PutCString("jLLDBTraceSupported");
3636e8d8bef9SDimitry Andric 
3637e8d8bef9SDimitry Andric   StringExtractorGDBRemote response;
3638e8d8bef9SDimitry Andric   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3639fe6060f1SDimitry Andric                                    timeout) ==
3640e8d8bef9SDimitry Andric       GDBRemoteCommunication::PacketResult::Success) {
3641e8d8bef9SDimitry Andric     if (response.IsErrorResponse())
3642e8d8bef9SDimitry Andric       return response.GetStatus().ToError();
3643e8d8bef9SDimitry Andric     if (response.IsUnsupportedResponse())
3644e8d8bef9SDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3645fe6060f1SDimitry Andric                                      "jLLDBTraceSupported is unsupported");
3646e8d8bef9SDimitry Andric 
3647fe6060f1SDimitry Andric     return llvm::json::parse<TraceSupportedResponse>(response.Peek(),
3648fe6060f1SDimitry Andric                                                      "TraceSupportedResponse");
3649e8d8bef9SDimitry Andric   }
3650fe6060f1SDimitry Andric   LLDB_LOG(log, "failed to send packet: jLLDBTraceSupported");
3651fe6060f1SDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3652fe6060f1SDimitry Andric                                  "failed to send packet: jLLDBTraceSupported");
3653e8d8bef9SDimitry Andric }
3654e8d8bef9SDimitry Andric 
3655fe6060f1SDimitry Andric llvm::Error
3656fe6060f1SDimitry Andric GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request,
3657fe6060f1SDimitry Andric                                             std::chrono::seconds timeout) {
36581fd87a68SDimitry Andric   Log *log = GetLog(GDBRLog::Process);
36590b57cec5SDimitry Andric 
36600b57cec5SDimitry Andric   StreamGDBRemote escaped_packet;
3661fe6060f1SDimitry Andric   escaped_packet.PutCString("jLLDBTraceStop:");
36620b57cec5SDimitry Andric 
3663fe6060f1SDimitry Andric   std::string json_string;
3664fe6060f1SDimitry Andric   llvm::raw_string_ostream os(json_string);
3665fe6060f1SDimitry Andric   os << toJSON(request);
3666fe6060f1SDimitry Andric   os.flush();
36670b57cec5SDimitry Andric 
3668fe6060f1SDimitry Andric   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
36690b57cec5SDimitry Andric 
3670fe6060f1SDimitry Andric   StringExtractorGDBRemote response;
36710b57cec5SDimitry Andric   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3672fe6060f1SDimitry Andric                                    timeout) ==
36730b57cec5SDimitry Andric       GDBRemoteCommunication::PacketResult::Success) {
3674fe6060f1SDimitry Andric     if (response.IsErrorResponse())
3675fe6060f1SDimitry Andric       return response.GetStatus().ToError();
3676fe6060f1SDimitry Andric     if (response.IsUnsupportedResponse())
3677fe6060f1SDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3678fe6060f1SDimitry Andric                                      "jLLDBTraceStop is unsupported");
3679fe6060f1SDimitry Andric     if (response.IsOKResponse())
3680fe6060f1SDimitry Andric       return llvm::Error::success();
3681fe6060f1SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
3682fe6060f1SDimitry Andric                                    "Invalid jLLDBTraceStart response");
36830b57cec5SDimitry Andric   }
3684fe6060f1SDimitry Andric   LLDB_LOG(log, "failed to send packet: jLLDBTraceStop");
3685fe6060f1SDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3686fe6060f1SDimitry Andric                                  "failed to send packet: jLLDBTraceStop '%s'",
36870b57cec5SDimitry Andric                                  escaped_packet.GetData());
36880b57cec5SDimitry Andric }
36890b57cec5SDimitry Andric 
3690fe6060f1SDimitry Andric llvm::Error
3691fe6060f1SDimitry Andric GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value &params,
3692fe6060f1SDimitry Andric                                              std::chrono::seconds timeout) {
36931fd87a68SDimitry Andric   Log *log = GetLog(GDBRLog::Process);
36940b57cec5SDimitry Andric 
3695fe6060f1SDimitry Andric   StreamGDBRemote escaped_packet;
3696fe6060f1SDimitry Andric   escaped_packet.PutCString("jLLDBTraceStart:");
36970b57cec5SDimitry Andric 
3698fe6060f1SDimitry Andric   std::string json_string;
3699fe6060f1SDimitry Andric   llvm::raw_string_ostream os(json_string);
3700fe6060f1SDimitry Andric   os << params;
3701fe6060f1SDimitry Andric   os.flush();
37020b57cec5SDimitry Andric 
3703fe6060f1SDimitry Andric   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
37040b57cec5SDimitry Andric 
37050b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3706fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3707fe6060f1SDimitry Andric                                    timeout) ==
37080b57cec5SDimitry Andric       GDBRemoteCommunication::PacketResult::Success) {
3709fe6060f1SDimitry Andric     if (response.IsErrorResponse())
3710fe6060f1SDimitry Andric       return response.GetStatus().ToError();
3711fe6060f1SDimitry Andric     if (response.IsUnsupportedResponse())
3712fe6060f1SDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3713fe6060f1SDimitry Andric                                      "jLLDBTraceStart is unsupported");
3714fe6060f1SDimitry Andric     if (response.IsOKResponse())
3715fe6060f1SDimitry Andric       return llvm::Error::success();
3716fe6060f1SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
3717fe6060f1SDimitry Andric                                    "Invalid jLLDBTraceStart response");
37180b57cec5SDimitry Andric   }
3719fe6060f1SDimitry Andric   LLDB_LOG(log, "failed to send packet: jLLDBTraceStart");
3720fe6060f1SDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
3721fe6060f1SDimitry Andric                                  "failed to send packet: jLLDBTraceStart '%s'",
3722fe6060f1SDimitry Andric                                  escaped_packet.GetData());
37230b57cec5SDimitry Andric }
3724fe6060f1SDimitry Andric 
3725fe6060f1SDimitry Andric llvm::Expected<std::string>
3726fe6060f1SDimitry Andric GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type,
3727fe6060f1SDimitry Andric                                                 std::chrono::seconds timeout) {
37281fd87a68SDimitry Andric   Log *log = GetLog(GDBRLog::Process);
3729fe6060f1SDimitry Andric 
3730fe6060f1SDimitry Andric   StreamGDBRemote escaped_packet;
3731fe6060f1SDimitry Andric   escaped_packet.PutCString("jLLDBTraceGetState:");
3732fe6060f1SDimitry Andric 
3733fe6060f1SDimitry Andric   std::string json_string;
3734fe6060f1SDimitry Andric   llvm::raw_string_ostream os(json_string);
3735fe6060f1SDimitry Andric   os << toJSON(TraceGetStateRequest{type.str()});
3736fe6060f1SDimitry Andric   os.flush();
3737fe6060f1SDimitry Andric 
3738fe6060f1SDimitry Andric   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3739fe6060f1SDimitry Andric 
3740fe6060f1SDimitry Andric   StringExtractorGDBRemote response;
3741fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3742fe6060f1SDimitry Andric                                    timeout) ==
3743fe6060f1SDimitry Andric       GDBRemoteCommunication::PacketResult::Success) {
3744fe6060f1SDimitry Andric     if (response.IsErrorResponse())
3745fe6060f1SDimitry Andric       return response.GetStatus().ToError();
3746fe6060f1SDimitry Andric     if (response.IsUnsupportedResponse())
3747fe6060f1SDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
3748fe6060f1SDimitry Andric                                      "jLLDBTraceGetState is unsupported");
3749fe6060f1SDimitry Andric     return std::string(response.Peek());
3750fe6060f1SDimitry Andric   }
3751fe6060f1SDimitry Andric 
3752fe6060f1SDimitry Andric   LLDB_LOG(log, "failed to send packet: jLLDBTraceGetState");
3753fe6060f1SDimitry Andric   return llvm::createStringError(
3754fe6060f1SDimitry Andric       llvm::inconvertibleErrorCode(),
3755fe6060f1SDimitry Andric       "failed to send packet: jLLDBTraceGetState '%s'",
3756fe6060f1SDimitry Andric       escaped_packet.GetData());
3757fe6060f1SDimitry Andric }
3758fe6060f1SDimitry Andric 
3759fe6060f1SDimitry Andric llvm::Expected<std::vector<uint8_t>>
3760fe6060f1SDimitry Andric GDBRemoteCommunicationClient::SendTraceGetBinaryData(
3761fe6060f1SDimitry Andric     const TraceGetBinaryDataRequest &request, std::chrono::seconds timeout) {
37621fd87a68SDimitry Andric   Log *log = GetLog(GDBRLog::Process);
3763fe6060f1SDimitry Andric 
3764fe6060f1SDimitry Andric   StreamGDBRemote escaped_packet;
3765fe6060f1SDimitry Andric   escaped_packet.PutCString("jLLDBTraceGetBinaryData:");
3766fe6060f1SDimitry Andric 
3767fe6060f1SDimitry Andric   std::string json_string;
3768fe6060f1SDimitry Andric   llvm::raw_string_ostream os(json_string);
3769fe6060f1SDimitry Andric   os << toJSON(request);
3770fe6060f1SDimitry Andric   os.flush();
3771fe6060f1SDimitry Andric 
3772fe6060f1SDimitry Andric   escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size());
3773fe6060f1SDimitry Andric 
3774fe6060f1SDimitry Andric   StringExtractorGDBRemote response;
3775fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
3776fe6060f1SDimitry Andric                                    timeout) ==
3777fe6060f1SDimitry Andric       GDBRemoteCommunication::PacketResult::Success) {
3778fe6060f1SDimitry Andric     if (response.IsErrorResponse())
3779fe6060f1SDimitry Andric       return response.GetStatus().ToError();
3780fe6060f1SDimitry Andric     std::string data;
3781fe6060f1SDimitry Andric     response.GetEscapedBinaryData(data);
3782fe6060f1SDimitry Andric     return std::vector<uint8_t>(data.begin(), data.end());
3783fe6060f1SDimitry Andric   }
3784fe6060f1SDimitry Andric   LLDB_LOG(log, "failed to send packet: jLLDBTraceGetBinaryData");
3785fe6060f1SDimitry Andric   return llvm::createStringError(
3786fe6060f1SDimitry Andric       llvm::inconvertibleErrorCode(),
3787fe6060f1SDimitry Andric       "failed to send packet: jLLDBTraceGetBinaryData '%s'",
3788fe6060f1SDimitry Andric       escaped_packet.GetData());
37890b57cec5SDimitry Andric }
37900b57cec5SDimitry Andric 
3791bdd1243dSDimitry Andric std::optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() {
37925ffd83dbSDimitry Andric   StringExtractorGDBRemote response;
3793fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse("qOffsets", response) !=
3794fe6060f1SDimitry Andric       PacketResult::Success)
3795bdd1243dSDimitry Andric     return std::nullopt;
37965ffd83dbSDimitry Andric   if (!response.IsNormalResponse())
3797bdd1243dSDimitry Andric     return std::nullopt;
37985ffd83dbSDimitry Andric 
37995ffd83dbSDimitry Andric   QOffsets result;
38005ffd83dbSDimitry Andric   llvm::StringRef ref = response.GetStringRef();
38015ffd83dbSDimitry Andric   const auto &GetOffset = [&] {
38025ffd83dbSDimitry Andric     addr_t offset;
38035ffd83dbSDimitry Andric     if (ref.consumeInteger(16, offset))
38045ffd83dbSDimitry Andric       return false;
38055ffd83dbSDimitry Andric     result.offsets.push_back(offset);
38065ffd83dbSDimitry Andric     return true;
38075ffd83dbSDimitry Andric   };
38085ffd83dbSDimitry Andric 
38095ffd83dbSDimitry Andric   if (ref.consume_front("Text=")) {
38105ffd83dbSDimitry Andric     result.segments = false;
38115ffd83dbSDimitry Andric     if (!GetOffset())
3812bdd1243dSDimitry Andric       return std::nullopt;
38135ffd83dbSDimitry Andric     if (!ref.consume_front(";Data=") || !GetOffset())
3814bdd1243dSDimitry Andric       return std::nullopt;
38155ffd83dbSDimitry Andric     if (ref.empty())
38165ffd83dbSDimitry Andric       return result;
38175ffd83dbSDimitry Andric     if (ref.consume_front(";Bss=") && GetOffset() && ref.empty())
38185ffd83dbSDimitry Andric       return result;
38195ffd83dbSDimitry Andric   } else if (ref.consume_front("TextSeg=")) {
38205ffd83dbSDimitry Andric     result.segments = true;
38215ffd83dbSDimitry Andric     if (!GetOffset())
3822bdd1243dSDimitry Andric       return std::nullopt;
38235ffd83dbSDimitry Andric     if (ref.empty())
38245ffd83dbSDimitry Andric       return result;
38255ffd83dbSDimitry Andric     if (ref.consume_front(";DataSeg=") && GetOffset() && ref.empty())
38265ffd83dbSDimitry Andric       return result;
38275ffd83dbSDimitry Andric   }
3828bdd1243dSDimitry Andric   return std::nullopt;
38295ffd83dbSDimitry Andric }
38305ffd83dbSDimitry Andric 
38310b57cec5SDimitry Andric bool GDBRemoteCommunicationClient::GetModuleInfo(
38320b57cec5SDimitry Andric     const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec,
38330b57cec5SDimitry Andric     ModuleSpec &module_spec) {
38340b57cec5SDimitry Andric   if (!m_supports_qModuleInfo)
38350b57cec5SDimitry Andric     return false;
38360b57cec5SDimitry Andric 
38370b57cec5SDimitry Andric   std::string module_path = module_file_spec.GetPath(false);
38380b57cec5SDimitry Andric   if (module_path.empty())
38390b57cec5SDimitry Andric     return false;
38400b57cec5SDimitry Andric 
38410b57cec5SDimitry Andric   StreamString packet;
38420b57cec5SDimitry Andric   packet.PutCString("qModuleInfo:");
38430b57cec5SDimitry Andric   packet.PutStringAsRawHex8(module_path);
38440b57cec5SDimitry Andric   packet.PutCString(";");
38450b57cec5SDimitry Andric   const auto &triple = arch_spec.GetTriple().getTriple();
38460b57cec5SDimitry Andric   packet.PutStringAsRawHex8(triple);
38470b57cec5SDimitry Andric 
38480b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3849fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(packet.GetString(), response) !=
38500b57cec5SDimitry Andric       PacketResult::Success)
38510b57cec5SDimitry Andric     return false;
38520b57cec5SDimitry Andric 
38530b57cec5SDimitry Andric   if (response.IsErrorResponse())
38540b57cec5SDimitry Andric     return false;
38550b57cec5SDimitry Andric 
38560b57cec5SDimitry Andric   if (response.IsUnsupportedResponse()) {
38570b57cec5SDimitry Andric     m_supports_qModuleInfo = false;
38580b57cec5SDimitry Andric     return false;
38590b57cec5SDimitry Andric   }
38600b57cec5SDimitry Andric 
38610b57cec5SDimitry Andric   llvm::StringRef name;
38620b57cec5SDimitry Andric   llvm::StringRef value;
38630b57cec5SDimitry Andric 
38640b57cec5SDimitry Andric   module_spec.Clear();
38650b57cec5SDimitry Andric   module_spec.GetFileSpec() = module_file_spec;
38660b57cec5SDimitry Andric 
38670b57cec5SDimitry Andric   while (response.GetNameColonValue(name, value)) {
38680b57cec5SDimitry Andric     if (name == "uuid" || name == "md5") {
38690b57cec5SDimitry Andric       StringExtractor extractor(value);
38700b57cec5SDimitry Andric       std::string uuid;
38710b57cec5SDimitry Andric       extractor.GetHexByteString(uuid);
38725ffd83dbSDimitry Andric       module_spec.GetUUID().SetFromStringRef(uuid);
38730b57cec5SDimitry Andric     } else if (name == "triple") {
38740b57cec5SDimitry Andric       StringExtractor extractor(value);
38750b57cec5SDimitry Andric       std::string triple;
38760b57cec5SDimitry Andric       extractor.GetHexByteString(triple);
38770b57cec5SDimitry Andric       module_spec.GetArchitecture().SetTriple(triple.c_str());
38780b57cec5SDimitry Andric     } else if (name == "file_offset") {
38790b57cec5SDimitry Andric       uint64_t ival = 0;
38800b57cec5SDimitry Andric       if (!value.getAsInteger(16, ival))
38810b57cec5SDimitry Andric         module_spec.SetObjectOffset(ival);
38820b57cec5SDimitry Andric     } else if (name == "file_size") {
38830b57cec5SDimitry Andric       uint64_t ival = 0;
38840b57cec5SDimitry Andric       if (!value.getAsInteger(16, ival))
38850b57cec5SDimitry Andric         module_spec.SetObjectSize(ival);
38860b57cec5SDimitry Andric     } else if (name == "file_path") {
38870b57cec5SDimitry Andric       StringExtractor extractor(value);
38880b57cec5SDimitry Andric       std::string path;
38890b57cec5SDimitry Andric       extractor.GetHexByteString(path);
38900b57cec5SDimitry Andric       module_spec.GetFileSpec() = FileSpec(path, arch_spec.GetTriple());
38910b57cec5SDimitry Andric     }
38920b57cec5SDimitry Andric   }
38930b57cec5SDimitry Andric 
38940b57cec5SDimitry Andric   return true;
38950b57cec5SDimitry Andric }
38960b57cec5SDimitry Andric 
3897bdd1243dSDimitry Andric static std::optional<ModuleSpec>
38980b57cec5SDimitry Andric ParseModuleSpec(StructuredData::Dictionary *dict) {
38990b57cec5SDimitry Andric   ModuleSpec result;
39000b57cec5SDimitry Andric   if (!dict)
3901bdd1243dSDimitry Andric     return std::nullopt;
39020b57cec5SDimitry Andric 
39030b57cec5SDimitry Andric   llvm::StringRef string;
39040b57cec5SDimitry Andric   uint64_t integer;
39050b57cec5SDimitry Andric 
39060b57cec5SDimitry Andric   if (!dict->GetValueForKeyAsString("uuid", string))
3907bdd1243dSDimitry Andric     return std::nullopt;
39085ffd83dbSDimitry Andric   if (!result.GetUUID().SetFromStringRef(string))
3909bdd1243dSDimitry Andric     return std::nullopt;
39100b57cec5SDimitry Andric 
39110b57cec5SDimitry Andric   if (!dict->GetValueForKeyAsInteger("file_offset", integer))
3912bdd1243dSDimitry Andric     return std::nullopt;
39130b57cec5SDimitry Andric   result.SetObjectOffset(integer);
39140b57cec5SDimitry Andric 
39150b57cec5SDimitry Andric   if (!dict->GetValueForKeyAsInteger("file_size", integer))
3916bdd1243dSDimitry Andric     return std::nullopt;
39170b57cec5SDimitry Andric   result.SetObjectSize(integer);
39180b57cec5SDimitry Andric 
39190b57cec5SDimitry Andric   if (!dict->GetValueForKeyAsString("triple", string))
3920bdd1243dSDimitry Andric     return std::nullopt;
39210b57cec5SDimitry Andric   result.GetArchitecture().SetTriple(string);
39220b57cec5SDimitry Andric 
39230b57cec5SDimitry Andric   if (!dict->GetValueForKeyAsString("file_path", string))
3924bdd1243dSDimitry Andric     return std::nullopt;
39250b57cec5SDimitry Andric   result.GetFileSpec() = FileSpec(string, result.GetArchitecture().GetTriple());
39260b57cec5SDimitry Andric 
39270b57cec5SDimitry Andric   return result;
39280b57cec5SDimitry Andric }
39290b57cec5SDimitry Andric 
3930bdd1243dSDimitry Andric std::optional<std::vector<ModuleSpec>>
39310b57cec5SDimitry Andric GDBRemoteCommunicationClient::GetModulesInfo(
39320b57cec5SDimitry Andric     llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) {
39339dba64beSDimitry Andric   namespace json = llvm::json;
39349dba64beSDimitry Andric 
39350b57cec5SDimitry Andric   if (!m_supports_jModulesInfo)
3936bdd1243dSDimitry Andric     return std::nullopt;
39370b57cec5SDimitry Andric 
39389dba64beSDimitry Andric   json::Array module_array;
39390b57cec5SDimitry Andric   for (const FileSpec &module_file_spec : module_file_specs) {
39409dba64beSDimitry Andric     module_array.push_back(
39419dba64beSDimitry Andric         json::Object{{"file", module_file_spec.GetPath(false)},
39429dba64beSDimitry Andric                      {"triple", triple.getTriple()}});
39430b57cec5SDimitry Andric   }
39440b57cec5SDimitry Andric   StreamString unescaped_payload;
39450b57cec5SDimitry Andric   unescaped_payload.PutCString("jModulesInfo:");
39469dba64beSDimitry Andric   unescaped_payload.AsRawOstream() << std::move(module_array);
39479dba64beSDimitry Andric 
39480b57cec5SDimitry Andric   StreamGDBRemote payload;
39490b57cec5SDimitry Andric   payload.PutEscapedBytes(unescaped_payload.GetString().data(),
39500b57cec5SDimitry Andric                           unescaped_payload.GetSize());
39510b57cec5SDimitry Andric 
39520b57cec5SDimitry Andric   // Increase the timeout for jModulesInfo since this packet can take longer.
39530b57cec5SDimitry Andric   ScopedTimeout timeout(*this, std::chrono::seconds(10));
39540b57cec5SDimitry Andric 
39550b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3956fe6060f1SDimitry Andric   if (SendPacketAndWaitForResponse(payload.GetString(), response) !=
39570b57cec5SDimitry Andric           PacketResult::Success ||
39580b57cec5SDimitry Andric       response.IsErrorResponse())
3959bdd1243dSDimitry Andric     return std::nullopt;
39600b57cec5SDimitry Andric 
39610b57cec5SDimitry Andric   if (response.IsUnsupportedResponse()) {
39620b57cec5SDimitry Andric     m_supports_jModulesInfo = false;
3963bdd1243dSDimitry Andric     return std::nullopt;
39640b57cec5SDimitry Andric   }
39650b57cec5SDimitry Andric 
39660b57cec5SDimitry Andric   StructuredData::ObjectSP response_object_sp =
396706c3fb27SDimitry Andric       StructuredData::ParseJSON(response.GetStringRef());
39680b57cec5SDimitry Andric   if (!response_object_sp)
3969bdd1243dSDimitry Andric     return std::nullopt;
39700b57cec5SDimitry Andric 
39710b57cec5SDimitry Andric   StructuredData::Array *response_array = response_object_sp->GetAsArray();
39720b57cec5SDimitry Andric   if (!response_array)
3973bdd1243dSDimitry Andric     return std::nullopt;
39740b57cec5SDimitry Andric 
39750b57cec5SDimitry Andric   std::vector<ModuleSpec> result;
39760b57cec5SDimitry Andric   for (size_t i = 0; i < response_array->GetSize(); ++i) {
3977bdd1243dSDimitry Andric     if (std::optional<ModuleSpec> module_spec = ParseModuleSpec(
39780b57cec5SDimitry Andric             response_array->GetItemAtIndex(i)->GetAsDictionary()))
39790b57cec5SDimitry Andric       result.push_back(*module_spec);
39800b57cec5SDimitry Andric   }
39810b57cec5SDimitry Andric 
39820b57cec5SDimitry Andric   return result;
39830b57cec5SDimitry Andric }
39840b57cec5SDimitry Andric 
39850b57cec5SDimitry Andric // query the target remote for extended information using the qXfer packet
39860b57cec5SDimitry Andric //
3987349cc55cSDimitry Andric // example: object='features', annex='target.xml'
3988349cc55cSDimitry Andric // return: <xml output> or error
3989349cc55cSDimitry Andric llvm::Expected<std::string>
3990349cc55cSDimitry Andric GDBRemoteCommunicationClient::ReadExtFeature(llvm::StringRef object,
3991349cc55cSDimitry Andric                                              llvm::StringRef annex) {
39920b57cec5SDimitry Andric 
3993349cc55cSDimitry Andric   std::string output;
3994349cc55cSDimitry Andric   llvm::raw_string_ostream output_stream(output);
39950b57cec5SDimitry Andric   StringExtractorGDBRemote chunk;
39960b57cec5SDimitry Andric 
39970b57cec5SDimitry Andric   uint64_t size = GetRemoteMaxPacketSize();
39980b57cec5SDimitry Andric   if (size == 0)
39990b57cec5SDimitry Andric     size = 0x1000;
40000b57cec5SDimitry Andric   size = size - 1; // Leave space for the 'm' or 'l' character in the response
40010b57cec5SDimitry Andric   int offset = 0;
40020b57cec5SDimitry Andric   bool active = true;
40030b57cec5SDimitry Andric 
40040b57cec5SDimitry Andric   // loop until all data has been read
40050b57cec5SDimitry Andric   while (active) {
40060b57cec5SDimitry Andric 
40070b57cec5SDimitry Andric     // send query extended feature packet
4008349cc55cSDimitry Andric     std::string packet =
4009349cc55cSDimitry Andric         ("qXfer:" + object + ":read:" + annex + ":" +
4010349cc55cSDimitry Andric          llvm::Twine::utohexstr(offset) + "," + llvm::Twine::utohexstr(size))
4011349cc55cSDimitry Andric             .str();
40120b57cec5SDimitry Andric 
40130b57cec5SDimitry Andric     GDBRemoteCommunication::PacketResult res =
4014349cc55cSDimitry Andric         SendPacketAndWaitForResponse(packet, chunk);
40150b57cec5SDimitry Andric 
4016349cc55cSDimitry Andric     if (res != GDBRemoteCommunication::PacketResult::Success ||
4017349cc55cSDimitry Andric         chunk.GetStringRef().empty()) {
4018349cc55cSDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
4019349cc55cSDimitry Andric                                      "Error sending $qXfer packet");
40200b57cec5SDimitry Andric     }
40210b57cec5SDimitry Andric 
40220b57cec5SDimitry Andric     // check packet code
4023349cc55cSDimitry Andric     switch (chunk.GetStringRef()[0]) {
40240b57cec5SDimitry Andric     // last chunk
40250b57cec5SDimitry Andric     case ('l'):
40260b57cec5SDimitry Andric       active = false;
4027bdd1243dSDimitry Andric       [[fallthrough]];
40280b57cec5SDimitry Andric 
40290b57cec5SDimitry Andric     // more chunks
40300b57cec5SDimitry Andric     case ('m'):
4031349cc55cSDimitry Andric       output_stream << chunk.GetStringRef().drop_front();
4032349cc55cSDimitry Andric       offset += chunk.GetStringRef().size() - 1;
40330b57cec5SDimitry Andric       break;
40340b57cec5SDimitry Andric 
40350b57cec5SDimitry Andric     // unknown chunk
40360b57cec5SDimitry Andric     default:
4037349cc55cSDimitry Andric       return llvm::createStringError(
4038349cc55cSDimitry Andric           llvm::inconvertibleErrorCode(),
4039349cc55cSDimitry Andric           "Invalid continuation code from $qXfer packet");
40400b57cec5SDimitry Andric     }
40410b57cec5SDimitry Andric   }
40420b57cec5SDimitry Andric 
4043349cc55cSDimitry Andric   return output_stream.str();
40440b57cec5SDimitry Andric }
40450b57cec5SDimitry Andric 
40460b57cec5SDimitry Andric // Notify the target that gdb is prepared to serve symbol lookup requests.
40470b57cec5SDimitry Andric //  packet: "qSymbol::"
40480b57cec5SDimitry Andric //  reply:
40490b57cec5SDimitry Andric //  OK                  The target does not need to look up any (more) symbols.
40500b57cec5SDimitry Andric //  qSymbol:<sym_name>  The target requests the value of symbol sym_name (hex
40510b57cec5SDimitry Andric //  encoded).
40520b57cec5SDimitry Andric //                      LLDB may provide the value by sending another qSymbol
40530b57cec5SDimitry Andric //                      packet
40540b57cec5SDimitry Andric //                      in the form of"qSymbol:<sym_value>:<sym_name>".
40550b57cec5SDimitry Andric //
40560b57cec5SDimitry Andric //  Three examples:
40570b57cec5SDimitry Andric //
40580b57cec5SDimitry Andric //  lldb sends:    qSymbol::
40590b57cec5SDimitry Andric //  lldb receives: OK
40600b57cec5SDimitry Andric //     Remote gdb stub does not need to know the addresses of any symbols, lldb
40610b57cec5SDimitry Andric //     does not
40620b57cec5SDimitry Andric //     need to ask again in this session.
40630b57cec5SDimitry Andric //
40640b57cec5SDimitry Andric //  lldb sends:    qSymbol::
40650b57cec5SDimitry Andric //  lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
40660b57cec5SDimitry Andric //  lldb sends:    qSymbol::64697370617463685f71756575655f6f666673657473
40670b57cec5SDimitry Andric //  lldb receives: OK
40680b57cec5SDimitry Andric //     Remote gdb stub asks for address of 'dispatch_queue_offsets'.  lldb does
40690b57cec5SDimitry Andric //     not know
40700b57cec5SDimitry Andric //     the address at this time.  lldb needs to send qSymbol:: again when it has
40710b57cec5SDimitry Andric //     more
40720b57cec5SDimitry Andric //     solibs loaded.
40730b57cec5SDimitry Andric //
40740b57cec5SDimitry Andric //  lldb sends:    qSymbol::
40750b57cec5SDimitry Andric //  lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
40760b57cec5SDimitry Andric //  lldb sends:    qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473
40770b57cec5SDimitry Andric //  lldb receives: OK
40780b57cec5SDimitry Andric //     Remote gdb stub asks for address of 'dispatch_queue_offsets'.  lldb says
40790b57cec5SDimitry Andric //     that it
40800b57cec5SDimitry Andric //     is at address 0x2bc97554.  Remote gdb stub sends 'OK' indicating that it
40810b57cec5SDimitry Andric //     does not
40820b57cec5SDimitry Andric //     need any more symbols.  lldb does not need to ask again in this session.
40830b57cec5SDimitry Andric 
40840b57cec5SDimitry Andric void GDBRemoteCommunicationClient::ServeSymbolLookups(
40850b57cec5SDimitry Andric     lldb_private::Process *process) {
40860b57cec5SDimitry Andric   // Set to true once we've resolved a symbol to an address for the remote
40870b57cec5SDimitry Andric   // stub. If we get an 'OK' response after this, the remote stub doesn't need
40880b57cec5SDimitry Andric   // any more symbols and we can stop asking.
40890b57cec5SDimitry Andric   bool symbol_response_provided = false;
40900b57cec5SDimitry Andric 
40910b57cec5SDimitry Andric   // Is this the initial qSymbol:: packet?
40920b57cec5SDimitry Andric   bool first_qsymbol_query = true;
40930b57cec5SDimitry Andric 
40940b57cec5SDimitry Andric   if (m_supports_qSymbol && !m_qSymbol_requests_done) {
4095fe6060f1SDimitry Andric     Lock lock(*this);
40960b57cec5SDimitry Andric     if (lock) {
40970b57cec5SDimitry Andric       StreamString packet;
40980b57cec5SDimitry Andric       packet.PutCString("qSymbol::");
40990b57cec5SDimitry Andric       StringExtractorGDBRemote response;
41000b57cec5SDimitry Andric       while (SendPacketAndWaitForResponseNoLock(packet.GetString(), response) ==
41010b57cec5SDimitry Andric              PacketResult::Success) {
41020b57cec5SDimitry Andric         if (response.IsOKResponse()) {
41030b57cec5SDimitry Andric           if (symbol_response_provided || first_qsymbol_query) {
41040b57cec5SDimitry Andric             m_qSymbol_requests_done = true;
41050b57cec5SDimitry Andric           }
41060b57cec5SDimitry Andric 
41070b57cec5SDimitry Andric           // We are done serving symbols requests
41080b57cec5SDimitry Andric           return;
41090b57cec5SDimitry Andric         }
41100b57cec5SDimitry Andric         first_qsymbol_query = false;
41110b57cec5SDimitry Andric 
41120b57cec5SDimitry Andric         if (response.IsUnsupportedResponse()) {
41130b57cec5SDimitry Andric           // qSymbol is not supported by the current GDB server we are
41140b57cec5SDimitry Andric           // connected to
41150b57cec5SDimitry Andric           m_supports_qSymbol = false;
41160b57cec5SDimitry Andric           return;
41170b57cec5SDimitry Andric         } else {
41180b57cec5SDimitry Andric           llvm::StringRef response_str(response.GetStringRef());
41195f757f3fSDimitry Andric           if (response_str.starts_with("qSymbol:")) {
41200b57cec5SDimitry Andric             response.SetFilePos(strlen("qSymbol:"));
41210b57cec5SDimitry Andric             std::string symbol_name;
41220b57cec5SDimitry Andric             if (response.GetHexByteString(symbol_name)) {
41230b57cec5SDimitry Andric               if (symbol_name.empty())
41240b57cec5SDimitry Andric                 return;
41250b57cec5SDimitry Andric 
41260b57cec5SDimitry Andric               addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
41270b57cec5SDimitry Andric               lldb_private::SymbolContextList sc_list;
41289dba64beSDimitry Andric               process->GetTarget().GetImages().FindSymbolsWithNameAndType(
41299dba64beSDimitry Andric                   ConstString(symbol_name), eSymbolTypeAny, sc_list);
413006c3fb27SDimitry Andric               for (const SymbolContext &sc : sc_list) {
413106c3fb27SDimitry Andric                 if (symbol_load_addr != LLDB_INVALID_ADDRESS)
413206c3fb27SDimitry Andric                   break;
41330b57cec5SDimitry Andric                 if (sc.symbol) {
41340b57cec5SDimitry Andric                   switch (sc.symbol->GetType()) {
41350b57cec5SDimitry Andric                   case eSymbolTypeInvalid:
41360b57cec5SDimitry Andric                   case eSymbolTypeAbsolute:
41370b57cec5SDimitry Andric                   case eSymbolTypeUndefined:
41380b57cec5SDimitry Andric                   case eSymbolTypeSourceFile:
41390b57cec5SDimitry Andric                   case eSymbolTypeHeaderFile:
41400b57cec5SDimitry Andric                   case eSymbolTypeObjectFile:
41410b57cec5SDimitry Andric                   case eSymbolTypeCommonBlock:
41420b57cec5SDimitry Andric                   case eSymbolTypeBlock:
41430b57cec5SDimitry Andric                   case eSymbolTypeLocal:
41440b57cec5SDimitry Andric                   case eSymbolTypeParam:
41450b57cec5SDimitry Andric                   case eSymbolTypeVariable:
41460b57cec5SDimitry Andric                   case eSymbolTypeVariableType:
41470b57cec5SDimitry Andric                   case eSymbolTypeLineEntry:
41480b57cec5SDimitry Andric                   case eSymbolTypeLineHeader:
41490b57cec5SDimitry Andric                   case eSymbolTypeScopeBegin:
41500b57cec5SDimitry Andric                   case eSymbolTypeScopeEnd:
41510b57cec5SDimitry Andric                   case eSymbolTypeAdditional:
41520b57cec5SDimitry Andric                   case eSymbolTypeCompiler:
41530b57cec5SDimitry Andric                   case eSymbolTypeInstrumentation:
41540b57cec5SDimitry Andric                   case eSymbolTypeTrampoline:
41550b57cec5SDimitry Andric                     break;
41560b57cec5SDimitry Andric 
41570b57cec5SDimitry Andric                   case eSymbolTypeCode:
41580b57cec5SDimitry Andric                   case eSymbolTypeResolver:
41590b57cec5SDimitry Andric                   case eSymbolTypeData:
41600b57cec5SDimitry Andric                   case eSymbolTypeRuntime:
41610b57cec5SDimitry Andric                   case eSymbolTypeException:
41620b57cec5SDimitry Andric                   case eSymbolTypeObjCClass:
41630b57cec5SDimitry Andric                   case eSymbolTypeObjCMetaClass:
41640b57cec5SDimitry Andric                   case eSymbolTypeObjCIVar:
41650b57cec5SDimitry Andric                   case eSymbolTypeReExported:
41660b57cec5SDimitry Andric                     symbol_load_addr =
41670b57cec5SDimitry Andric                         sc.symbol->GetLoadAddress(&process->GetTarget());
41680b57cec5SDimitry Andric                     break;
41690b57cec5SDimitry Andric                   }
41700b57cec5SDimitry Andric                 }
41710b57cec5SDimitry Andric               }
41720b57cec5SDimitry Andric               // This is the normal path where our symbol lookup was successful
41730b57cec5SDimitry Andric               // and we want to send a packet with the new symbol value and see
41740b57cec5SDimitry Andric               // if another lookup needs to be done.
41750b57cec5SDimitry Andric 
41760b57cec5SDimitry Andric               // Change "packet" to contain the requested symbol value and name
41770b57cec5SDimitry Andric               packet.Clear();
41780b57cec5SDimitry Andric               packet.PutCString("qSymbol:");
41790b57cec5SDimitry Andric               if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
41800b57cec5SDimitry Andric                 packet.Printf("%" PRIx64, symbol_load_addr);
41810b57cec5SDimitry Andric                 symbol_response_provided = true;
41820b57cec5SDimitry Andric               } else {
41830b57cec5SDimitry Andric                 symbol_response_provided = false;
41840b57cec5SDimitry Andric               }
41850b57cec5SDimitry Andric               packet.PutCString(":");
41860b57cec5SDimitry Andric               packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
41870b57cec5SDimitry Andric               continue; // go back to the while loop and send "packet" and wait
41880b57cec5SDimitry Andric                         // for another response
41890b57cec5SDimitry Andric             }
41900b57cec5SDimitry Andric           }
41910b57cec5SDimitry Andric         }
41920b57cec5SDimitry Andric       }
41930b57cec5SDimitry Andric       // If we make it here, the symbol request packet response wasn't valid or
41940b57cec5SDimitry Andric       // our symbol lookup failed so we must abort
41950b57cec5SDimitry Andric       return;
41960b57cec5SDimitry Andric 
41971fd87a68SDimitry Andric     } else if (Log *log = GetLog(GDBRLog::Process | GDBRLog::Packets)) {
41989dba64beSDimitry Andric       LLDB_LOGF(log,
41990b57cec5SDimitry Andric                 "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.",
42000b57cec5SDimitry Andric                 __FUNCTION__);
42010b57cec5SDimitry Andric     }
42020b57cec5SDimitry Andric   }
42030b57cec5SDimitry Andric }
42040b57cec5SDimitry Andric 
42050b57cec5SDimitry Andric StructuredData::Array *
42060b57cec5SDimitry Andric GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
42070b57cec5SDimitry Andric   if (!m_supported_async_json_packets_is_valid) {
42080b57cec5SDimitry Andric     // Query the server for the array of supported asynchronous JSON packets.
42090b57cec5SDimitry Andric     m_supported_async_json_packets_is_valid = true;
42100b57cec5SDimitry Andric 
42111fd87a68SDimitry Andric     Log *log = GetLog(GDBRLog::Process);
42120b57cec5SDimitry Andric 
42130b57cec5SDimitry Andric     // Poll it now.
42140b57cec5SDimitry Andric     StringExtractorGDBRemote response;
4215fe6060f1SDimitry Andric     if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response) ==
4216fe6060f1SDimitry Andric         PacketResult::Success) {
42170b57cec5SDimitry Andric       m_supported_async_json_packets_sp =
421806c3fb27SDimitry Andric           StructuredData::ParseJSON(response.GetStringRef());
42190b57cec5SDimitry Andric       if (m_supported_async_json_packets_sp &&
42200b57cec5SDimitry Andric           !m_supported_async_json_packets_sp->GetAsArray()) {
42210b57cec5SDimitry Andric         // We were returned something other than a JSON array.  This is
42220b57cec5SDimitry Andric         // invalid.  Clear it out.
42239dba64beSDimitry Andric         LLDB_LOGF(log,
42249dba64beSDimitry Andric                   "GDBRemoteCommunicationClient::%s(): "
42250b57cec5SDimitry Andric                   "QSupportedAsyncJSONPackets returned invalid "
42260b57cec5SDimitry Andric                   "result: %s",
42279dba64beSDimitry Andric                   __FUNCTION__, response.GetStringRef().data());
42280b57cec5SDimitry Andric         m_supported_async_json_packets_sp.reset();
42290b57cec5SDimitry Andric       }
42300b57cec5SDimitry Andric     } else {
42319dba64beSDimitry Andric       LLDB_LOGF(log,
42329dba64beSDimitry Andric                 "GDBRemoteCommunicationClient::%s(): "
42330b57cec5SDimitry Andric                 "QSupportedAsyncJSONPackets unsupported",
42340b57cec5SDimitry Andric                 __FUNCTION__);
42350b57cec5SDimitry Andric     }
42360b57cec5SDimitry Andric 
42370b57cec5SDimitry Andric     if (log && m_supported_async_json_packets_sp) {
42380b57cec5SDimitry Andric       StreamString stream;
42390b57cec5SDimitry Andric       m_supported_async_json_packets_sp->Dump(stream);
42409dba64beSDimitry Andric       LLDB_LOGF(log,
42419dba64beSDimitry Andric                 "GDBRemoteCommunicationClient::%s(): supported async "
42420b57cec5SDimitry Andric                 "JSON packets: %s",
42430b57cec5SDimitry Andric                 __FUNCTION__, stream.GetData());
42440b57cec5SDimitry Andric     }
42450b57cec5SDimitry Andric   }
42460b57cec5SDimitry Andric 
42470b57cec5SDimitry Andric   return m_supported_async_json_packets_sp
42480b57cec5SDimitry Andric              ? m_supported_async_json_packets_sp->GetAsArray()
42490b57cec5SDimitry Andric              : nullptr;
42500b57cec5SDimitry Andric }
42510b57cec5SDimitry Andric 
42520b57cec5SDimitry Andric Status GDBRemoteCommunicationClient::SendSignalsToIgnore(
42530b57cec5SDimitry Andric     llvm::ArrayRef<int32_t> signals) {
42540b57cec5SDimitry Andric   // Format packet:
42550b57cec5SDimitry Andric   // QPassSignals:<hex_sig1>;<hex_sig2>...;<hex_sigN>
42560b57cec5SDimitry Andric   auto range = llvm::make_range(signals.begin(), signals.end());
42570b57cec5SDimitry Andric   std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str();
42580b57cec5SDimitry Andric 
42590b57cec5SDimitry Andric   StringExtractorGDBRemote response;
4260fe6060f1SDimitry Andric   auto send_status = SendPacketAndWaitForResponse(packet, response);
42610b57cec5SDimitry Andric 
42620b57cec5SDimitry Andric   if (send_status != GDBRemoteCommunication::PacketResult::Success)
42630b57cec5SDimitry Andric     return Status("Sending QPassSignals packet failed");
42640b57cec5SDimitry Andric 
42650b57cec5SDimitry Andric   if (response.IsOKResponse()) {
42660b57cec5SDimitry Andric     return Status();
42670b57cec5SDimitry Andric   } else {
42680b57cec5SDimitry Andric     return Status("Unknown error happened during sending QPassSignals packet.");
42690b57cec5SDimitry Andric   }
42700b57cec5SDimitry Andric }
42710b57cec5SDimitry Andric 
42720b57cec5SDimitry Andric Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
427306c3fb27SDimitry Andric     llvm::StringRef type_name, const StructuredData::ObjectSP &config_sp) {
42740b57cec5SDimitry Andric   Status error;
42750b57cec5SDimitry Andric 
427606c3fb27SDimitry Andric   if (type_name.empty()) {
42770b57cec5SDimitry Andric     error.SetErrorString("invalid type_name argument");
42780b57cec5SDimitry Andric     return error;
42790b57cec5SDimitry Andric   }
42800b57cec5SDimitry Andric 
42810b57cec5SDimitry Andric   // Build command: Configure{type_name}: serialized config data.
42820b57cec5SDimitry Andric   StreamGDBRemote stream;
42830b57cec5SDimitry Andric   stream.PutCString("QConfigure");
428406c3fb27SDimitry Andric   stream.PutCString(type_name);
42850b57cec5SDimitry Andric   stream.PutChar(':');
42860b57cec5SDimitry Andric   if (config_sp) {
42870b57cec5SDimitry Andric     // Gather the plain-text version of the configuration data.
42880b57cec5SDimitry Andric     StreamString unescaped_stream;
42890b57cec5SDimitry Andric     config_sp->Dump(unescaped_stream);
42900b57cec5SDimitry Andric     unescaped_stream.Flush();
42910b57cec5SDimitry Andric 
42920b57cec5SDimitry Andric     // Add it to the stream in escaped fashion.
42930b57cec5SDimitry Andric     stream.PutEscapedBytes(unescaped_stream.GetString().data(),
42940b57cec5SDimitry Andric                            unescaped_stream.GetSize());
42950b57cec5SDimitry Andric   }
42960b57cec5SDimitry Andric   stream.Flush();
42970b57cec5SDimitry Andric 
42980b57cec5SDimitry Andric   // Send the packet.
42990b57cec5SDimitry Andric   StringExtractorGDBRemote response;
4300fe6060f1SDimitry Andric   auto result = SendPacketAndWaitForResponse(stream.GetString(), response);
43010b57cec5SDimitry Andric   if (result == PacketResult::Success) {
43020b57cec5SDimitry Andric     // We failed if the config result comes back other than OK.
430306c3fb27SDimitry Andric     if (response.GetStringRef() == "OK") {
43040b57cec5SDimitry Andric       // Okay!
43050b57cec5SDimitry Andric       error.Clear();
43060b57cec5SDimitry Andric     } else {
430706c3fb27SDimitry Andric       error.SetErrorStringWithFormatv(
430806c3fb27SDimitry Andric           "configuring StructuredData feature {0} failed with error {1}",
430906c3fb27SDimitry Andric           type_name, response.GetStringRef());
43100b57cec5SDimitry Andric     }
43110b57cec5SDimitry Andric   } else {
43120b57cec5SDimitry Andric     // Can we get more data here on the failure?
431306c3fb27SDimitry Andric     error.SetErrorStringWithFormatv(
431406c3fb27SDimitry Andric         "configuring StructuredData feature {0} failed when sending packet: "
431506c3fb27SDimitry Andric         "PacketResult={1}",
431606c3fb27SDimitry Andric         type_name, (int)result);
43170b57cec5SDimitry Andric   }
43180b57cec5SDimitry Andric   return error;
43190b57cec5SDimitry Andric }
43200b57cec5SDimitry Andric 
43210b57cec5SDimitry Andric void GDBRemoteCommunicationClient::OnRunPacketSent(bool first) {
43220b57cec5SDimitry Andric   GDBRemoteClientBase::OnRunPacketSent(first);
43230b57cec5SDimitry Andric   m_curr_tid = LLDB_INVALID_THREAD_ID;
43240b57cec5SDimitry Andric }
4325349cc55cSDimitry Andric 
4326349cc55cSDimitry Andric bool GDBRemoteCommunicationClient::UsesNativeSignals() {
4327349cc55cSDimitry Andric   if (m_uses_native_signals == eLazyBoolCalculate)
4328349cc55cSDimitry Andric     GetRemoteQSupported();
4329349cc55cSDimitry Andric   if (m_uses_native_signals == eLazyBoolYes)
4330349cc55cSDimitry Andric     return true;
4331349cc55cSDimitry Andric 
4332349cc55cSDimitry Andric   // If the remote didn't indicate native-signal support explicitly,
4333349cc55cSDimitry Andric   // check whether it is an old version of lldb-server.
4334349cc55cSDimitry Andric   return GetThreadSuffixSupported();
4335349cc55cSDimitry Andric }
4336972a253aSDimitry Andric 
4337972a253aSDimitry Andric llvm::Expected<int> GDBRemoteCommunicationClient::KillProcess(lldb::pid_t pid) {
4338972a253aSDimitry Andric   StringExtractorGDBRemote response;
4339972a253aSDimitry Andric   GDBRemoteCommunication::ScopedTimeout(*this, seconds(3));
4340972a253aSDimitry Andric 
4341972a253aSDimitry Andric   if (SendPacketAndWaitForResponse("k", response, GetPacketTimeout()) !=
4342972a253aSDimitry Andric       PacketResult::Success)
4343972a253aSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
4344972a253aSDimitry Andric                                    "failed to send k packet");
4345972a253aSDimitry Andric 
4346972a253aSDimitry Andric   char packet_cmd = response.GetChar(0);
4347972a253aSDimitry Andric   if (packet_cmd == 'W' || packet_cmd == 'X')
4348972a253aSDimitry Andric     return response.GetHexU8();
4349972a253aSDimitry Andric 
4350972a253aSDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
4351972a253aSDimitry Andric                                  "unexpected response to k packet: %s",
4352972a253aSDimitry Andric                                  response.GetStringRef().str().c_str());
4353972a253aSDimitry Andric }
4354