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