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 ®ion_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 ®ion) { 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 [®ion](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 ¶ms, 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