15ffd83dbSDimitry Andric //===-- GDBRemoteCommunicationServerLLGS.cpp ------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9fe6060f1SDimitry Andric #include <cerrno> 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Host/Config.h" 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include <chrono> 140b57cec5SDimitry Andric #include <cstring> 15fe6060f1SDimitry Andric #include <limits> 16bdd1243dSDimitry Andric #include <optional> 170b57cec5SDimitry Andric #include <thread> 180b57cec5SDimitry Andric 19e8d8bef9SDimitry Andric #include "GDBRemoteCommunicationServerLLGS.h" 200b57cec5SDimitry Andric #include "lldb/Host/ConnectionFileDescriptor.h" 210b57cec5SDimitry Andric #include "lldb/Host/Debug.h" 220b57cec5SDimitry Andric #include "lldb/Host/File.h" 230b57cec5SDimitry Andric #include "lldb/Host/FileAction.h" 240b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h" 250b57cec5SDimitry Andric #include "lldb/Host/Host.h" 260b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h" 270b57cec5SDimitry Andric #include "lldb/Host/PosixApi.h" 28349cc55cSDimitry Andric #include "lldb/Host/Socket.h" 290b57cec5SDimitry Andric #include "lldb/Host/common/NativeProcessProtocol.h" 300b57cec5SDimitry Andric #include "lldb/Host/common/NativeRegisterContext.h" 310b57cec5SDimitry Andric #include "lldb/Host/common/NativeThreadProtocol.h" 320b57cec5SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h" 330b57cec5SDimitry Andric #include "lldb/Utility/Args.h" 340b57cec5SDimitry Andric #include "lldb/Utility/DataBuffer.h" 350b57cec5SDimitry Andric #include "lldb/Utility/Endian.h" 36e8d8bef9SDimitry Andric #include "lldb/Utility/GDBRemote.h" 370b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h" 3881ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 390b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 400b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h" 410b57cec5SDimitry Andric #include "lldb/Utility/State.h" 420b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 43e8d8bef9SDimitry Andric #include "lldb/Utility/UnimplementedError.h" 440b57cec5SDimitry Andric #include "lldb/Utility/UriParser.h" 450b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 469dba64beSDimitry Andric #include "llvm/Support/JSON.h" 470b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric #include "ProcessGDBRemote.h" 500b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h" 510b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h" 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric using namespace lldb; 540b57cec5SDimitry Andric using namespace lldb_private; 550b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote; 560b57cec5SDimitry Andric using namespace llvm; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric // GDBRemote Errors 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric namespace { 610b57cec5SDimitry Andric enum GDBRemoteServerError { 620b57cec5SDimitry Andric // Set to the first unused error number in literal form below 630b57cec5SDimitry Andric eErrorFirst = 29, 640b57cec5SDimitry Andric eErrorNoProcess = eErrorFirst, 650b57cec5SDimitry Andric eErrorResume, 660b57cec5SDimitry Andric eErrorExitStatus 670b57cec5SDimitry Andric }; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric // GDBRemoteCommunicationServerLLGS constructor 710b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( 720b57cec5SDimitry Andric MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory) 73bdd1243dSDimitry Andric : GDBRemoteCommunicationServerCommon(), m_mainloop(mainloop), 74bdd1243dSDimitry Andric m_process_factory(process_factory), m_current_process(nullptr), 75bdd1243dSDimitry Andric m_continue_process(nullptr), m_stdio_communication() { 760b57cec5SDimitry Andric RegisterPacketHandlers(); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { 800b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C, 810b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_C); 820b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c, 830b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_c); 840b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D, 850b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_D); 860b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H, 870b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_H); 880b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I, 890b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_I); 900b57cec5SDimitry Andric RegisterMemberFunctionHandler( 910b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_interrupt, 920b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_interrupt); 930b57cec5SDimitry Andric RegisterMemberFunctionHandler( 940b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_m, 950b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_memory_read); 960b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M, 970b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_M); 98e8d8bef9SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType__M, 99e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle__M); 100e8d8bef9SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType__m, 101e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle__m); 1020b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, 1030b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_p); 1040b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P, 1050b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_P); 1060b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC, 1070b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qC); 10881ad6265SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_T, 10981ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_T); 1100b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1110b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qfThreadInfo, 1120b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo); 1130b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1140b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress, 1150b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress); 1160b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1170b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, 1180b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir); 1190b57cec5SDimitry Andric RegisterMemberFunctionHandler( 120fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported, 121fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported); 122fe6060f1SDimitry Andric RegisterMemberFunctionHandler( 123fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply, 124fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply); 125fe6060f1SDimitry Andric RegisterMemberFunctionHandler( 1260b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo, 1270b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo); 1280b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1290b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported, 1300b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported); 1310b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1320b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qProcessInfo, 1330b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo); 1340b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1350b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qRegisterInfo, 1360b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo); 1370b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1380b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState, 1390b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState); 1400b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1410b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState, 1420b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState); 1430b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1440b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR, 1450b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR); 1460b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1470b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, 1480b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir); 1490b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1500b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qsThreadInfo, 1510b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo); 1520b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1530b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo, 1540b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo); 1550b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1560b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jThreadsInfo, 1570b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo); 1580b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1590b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo, 1600b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo); 1610b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1620b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qXfer, 1630b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qXfer); 1640b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s, 1650b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_s); 1660b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1670b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_stop_reason, 1680b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ? 1690b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1700b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vAttach, 1710b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vAttach); 1720b57cec5SDimitry Andric RegisterMemberFunctionHandler( 173e8d8bef9SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vAttachWait, 174e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vAttachWait); 175e8d8bef9SDimitry Andric RegisterMemberFunctionHandler( 176e8d8bef9SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qVAttachOrWaitSupported, 177e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported); 178e8d8bef9SDimitry Andric RegisterMemberFunctionHandler( 179e8d8bef9SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vAttachOrWait, 180e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait); 181e8d8bef9SDimitry Andric RegisterMemberFunctionHandler( 1820b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vCont, 1830b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vCont); 1840b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1850b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vCont_actions, 1860b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); 1870b57cec5SDimitry Andric RegisterMemberFunctionHandler( 188349cc55cSDimitry Andric StringExtractorGDBRemote::eServerPacketType_vRun, 189349cc55cSDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vRun); 190349cc55cSDimitry Andric RegisterMemberFunctionHandler( 1910b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_x, 1920b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_memory_read); 1930b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z, 1940b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_Z); 1950b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, 1960b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_z); 1970b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1980b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QPassSignals, 1990b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric RegisterMemberFunctionHandler( 202fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupported, 203fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported); 2040b57cec5SDimitry Andric RegisterMemberFunctionHandler( 205fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStart, 206fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart); 2070b57cec5SDimitry Andric RegisterMemberFunctionHandler( 208fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStop, 209fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop); 2100b57cec5SDimitry Andric RegisterMemberFunctionHandler( 211fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetState, 212fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState); 2130b57cec5SDimitry Andric RegisterMemberFunctionHandler( 214fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetBinaryData, 215fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g, 2180b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_g); 2190b57cec5SDimitry Andric 220fe6060f1SDimitry Andric RegisterMemberFunctionHandler( 221fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qMemTags, 222fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qMemTags); 223fe6060f1SDimitry Andric 224fe6060f1SDimitry Andric RegisterMemberFunctionHandler( 225fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QMemTags, 226fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QMemTags); 227fe6060f1SDimitry Andric 2280b57cec5SDimitry Andric RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, 2290b57cec5SDimitry Andric [this](StringExtractorGDBRemote packet, Status &error, 2300b57cec5SDimitry Andric bool &interrupt, bool &quit) { 2310b57cec5SDimitry Andric quit = true; 2320b57cec5SDimitry Andric return this->Handle_k(packet); 2330b57cec5SDimitry Andric }); 234349cc55cSDimitry Andric 235349cc55cSDimitry Andric RegisterMemberFunctionHandler( 23681ad6265SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vKill, 23781ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vKill); 23881ad6265SDimitry Andric 23981ad6265SDimitry Andric RegisterMemberFunctionHandler( 240349cc55cSDimitry Andric StringExtractorGDBRemote::eServerPacketType_qLLDBSaveCore, 241349cc55cSDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qSaveCore); 24281ad6265SDimitry Andric 24381ad6265SDimitry Andric RegisterMemberFunctionHandler( 24481ad6265SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QNonStop, 24581ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QNonStop); 24681ad6265SDimitry Andric RegisterMemberFunctionHandler( 247fcaf7f86SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vStdio, 248fcaf7f86SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vStdio); 249fcaf7f86SDimitry Andric RegisterMemberFunctionHandler( 25081ad6265SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vStopped, 25181ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vStopped); 25281ad6265SDimitry Andric RegisterMemberFunctionHandler( 25381ad6265SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vCtrlC, 25481ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vCtrlC); 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) { 2580b57cec5SDimitry Andric m_process_launch_info = info; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { 26281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric if (!m_process_launch_info.GetArguments().GetArgumentCount()) 2650b57cec5SDimitry Andric return Status("%s: no process command line specified to launch", 2660b57cec5SDimitry Andric __FUNCTION__); 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric const bool should_forward_stdio = 2690b57cec5SDimitry Andric m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr || 2700b57cec5SDimitry Andric m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr || 2710b57cec5SDimitry Andric m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr; 2720b57cec5SDimitry Andric m_process_launch_info.SetLaunchInSeparateProcessGroup(true); 2730b57cec5SDimitry Andric m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric if (should_forward_stdio) { 2769dba64beSDimitry Andric // Temporarily relax the following for Windows until we can take advantage 2779dba64beSDimitry Andric // of the recently added pty support. This doesn't really affect the use of 2789dba64beSDimitry Andric // lldb-server on Windows. 2799dba64beSDimitry Andric #if !defined(_WIN32) 2800b57cec5SDimitry Andric if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection()) 2810b57cec5SDimitry Andric return Status(std::move(Err)); 2829dba64beSDimitry Andric #endif 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric { 2860b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); 287fe6060f1SDimitry Andric assert(m_debugged_processes.empty() && "lldb-server creating debugged " 2880b57cec5SDimitry Andric "process but one already exists"); 2890b57cec5SDimitry Andric auto process_or = 2900b57cec5SDimitry Andric m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); 2910b57cec5SDimitry Andric if (!process_or) 2920b57cec5SDimitry Andric return Status(process_or.takeError()); 293fe6060f1SDimitry Andric m_continue_process = m_current_process = process_or->get(); 294fcaf7f86SDimitry Andric m_debugged_processes.emplace( 295fcaf7f86SDimitry Andric m_current_process->GetID(), 296fcaf7f86SDimitry Andric DebuggedProcess{std::move(*process_or), DebuggedProcess::Flag{}}); 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 299fe6060f1SDimitry Andric SetEnabledExtensions(*m_current_process); 300fe6060f1SDimitry Andric 3010b57cec5SDimitry Andric // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as 3020b57cec5SDimitry Andric // needed. llgs local-process debugging may specify PTY paths, which will 3030b57cec5SDimitry Andric // make these file actions non-null process launch -i/e/o will also make 3040b57cec5SDimitry Andric // these file actions non-null nullptr means that the traffic is expected to 3050b57cec5SDimitry Andric // flow over gdb-remote protocol 3060b57cec5SDimitry Andric if (should_forward_stdio) { 3070b57cec5SDimitry Andric // nullptr means it's not redirected to file or pty (in case of LLGS local) 3080b57cec5SDimitry Andric // at least one of stdio will be transferred pty<->gdb-remote we need to 309349cc55cSDimitry Andric // give the pty primary handle to this object to read and/or write 3100b57cec5SDimitry Andric LLDB_LOG(log, 3110b57cec5SDimitry Andric "pid = {0}: setting up stdout/stderr redirection via $O " 3120b57cec5SDimitry Andric "gdb-remote commands", 313fe6060f1SDimitry Andric m_current_process->GetID()); 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric // Setup stdout/stderr mapping from inferior to $O 316fe6060f1SDimitry Andric auto terminal_fd = m_current_process->GetTerminalFileDescriptor(); 3170b57cec5SDimitry Andric if (terminal_fd >= 0) { 3189dba64beSDimitry Andric LLDB_LOGF(log, 3199dba64beSDimitry Andric "ProcessGDBRemoteCommunicationServerLLGS::%s setting " 3200b57cec5SDimitry Andric "inferior STDIO fd to %d", 3210b57cec5SDimitry Andric __FUNCTION__, terminal_fd); 3220b57cec5SDimitry Andric Status status = SetSTDIOFileDescriptor(terminal_fd); 3230b57cec5SDimitry Andric if (status.Fail()) 3240b57cec5SDimitry Andric return status; 3250b57cec5SDimitry Andric } else { 3269dba64beSDimitry Andric LLDB_LOGF(log, 3279dba64beSDimitry Andric "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " 3280b57cec5SDimitry Andric "inferior STDIO since terminal fd reported as %d", 3290b57cec5SDimitry Andric __FUNCTION__, terminal_fd); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric } else { 3320b57cec5SDimitry Andric LLDB_LOG(log, 3330b57cec5SDimitry Andric "pid = {0} skipping stdout/stderr redirection via $O: inferior " 3340b57cec5SDimitry Andric "will communicate over client-provided file descriptors", 335fe6060f1SDimitry Andric m_current_process->GetID()); 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric printf("Launched '%s' as process %" PRIu64 "...\n", 3390b57cec5SDimitry Andric m_process_launch_info.GetArguments().GetArgumentAtIndex(0), 340fe6060f1SDimitry Andric m_current_process->GetID()); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric return Status(); 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { 34681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3479dba64beSDimitry Andric LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, 3480b57cec5SDimitry Andric __FUNCTION__, pid); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric // Before we try to attach, make sure we aren't already monitoring something 3510b57cec5SDimitry Andric // else. 352fe6060f1SDimitry Andric if (!m_debugged_processes.empty()) 3530b57cec5SDimitry Andric return Status("cannot attach to process %" PRIu64 3540b57cec5SDimitry Andric " when another process with pid %" PRIu64 3550b57cec5SDimitry Andric " is being debugged.", 356fe6060f1SDimitry Andric pid, m_current_process->GetID()); 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric // Try to attach. 3590b57cec5SDimitry Andric auto process_or = m_process_factory.Attach(pid, *this, m_mainloop); 3600b57cec5SDimitry Andric if (!process_or) { 3610b57cec5SDimitry Andric Status status(process_or.takeError()); 362349cc55cSDimitry Andric llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}\n", pid, 3630b57cec5SDimitry Andric status); 3640b57cec5SDimitry Andric return status; 3650b57cec5SDimitry Andric } 366fe6060f1SDimitry Andric m_continue_process = m_current_process = process_or->get(); 367fcaf7f86SDimitry Andric m_debugged_processes.emplace( 368fcaf7f86SDimitry Andric m_current_process->GetID(), 369fcaf7f86SDimitry Andric DebuggedProcess{std::move(*process_or), DebuggedProcess::Flag{}}); 370fe6060f1SDimitry Andric SetEnabledExtensions(*m_current_process); 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric // Setup stdout/stderr mapping from inferior. 373fe6060f1SDimitry Andric auto terminal_fd = m_current_process->GetTerminalFileDescriptor(); 3740b57cec5SDimitry Andric if (terminal_fd >= 0) { 3759dba64beSDimitry Andric LLDB_LOGF(log, 3769dba64beSDimitry Andric "ProcessGDBRemoteCommunicationServerLLGS::%s setting " 3770b57cec5SDimitry Andric "inferior STDIO fd to %d", 3780b57cec5SDimitry Andric __FUNCTION__, terminal_fd); 3790b57cec5SDimitry Andric Status status = SetSTDIOFileDescriptor(terminal_fd); 3800b57cec5SDimitry Andric if (status.Fail()) 3810b57cec5SDimitry Andric return status; 3820b57cec5SDimitry Andric } else { 3839dba64beSDimitry Andric LLDB_LOGF(log, 3849dba64beSDimitry Andric "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " 3850b57cec5SDimitry Andric "inferior STDIO since terminal fd reported as %d", 3860b57cec5SDimitry Andric __FUNCTION__, terminal_fd); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric printf("Attached to process %" PRIu64 "...\n", pid); 3900b57cec5SDimitry Andric return Status(); 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 393e8d8bef9SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess( 394e8d8bef9SDimitry Andric llvm::StringRef process_name, bool include_existing) { 39581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 396e8d8bef9SDimitry Andric 397e8d8bef9SDimitry Andric std::chrono::milliseconds polling_interval = std::chrono::milliseconds(1); 398e8d8bef9SDimitry Andric 399e8d8bef9SDimitry Andric // Create the matcher used to search the process list. 400e8d8bef9SDimitry Andric ProcessInstanceInfoList exclusion_list; 401e8d8bef9SDimitry Andric ProcessInstanceInfoMatch match_info; 402e8d8bef9SDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile( 403e8d8bef9SDimitry Andric process_name, llvm::sys::path::Style::native); 404e8d8bef9SDimitry Andric match_info.SetNameMatchType(NameMatch::Equals); 405e8d8bef9SDimitry Andric 406e8d8bef9SDimitry Andric if (include_existing) { 407e8d8bef9SDimitry Andric LLDB_LOG(log, "including existing processes in search"); 408e8d8bef9SDimitry Andric } else { 409e8d8bef9SDimitry Andric // Create the excluded process list before polling begins. 410e8d8bef9SDimitry Andric Host::FindProcesses(match_info, exclusion_list); 411e8d8bef9SDimitry Andric LLDB_LOG(log, "placed '{0}' processes in the exclusion list.", 412e8d8bef9SDimitry Andric exclusion_list.size()); 413e8d8bef9SDimitry Andric } 414e8d8bef9SDimitry Andric 415e8d8bef9SDimitry Andric LLDB_LOG(log, "waiting for '{0}' to appear", process_name); 416e8d8bef9SDimitry Andric 417e8d8bef9SDimitry Andric auto is_in_exclusion_list = 418e8d8bef9SDimitry Andric [&exclusion_list](const ProcessInstanceInfo &info) { 419e8d8bef9SDimitry Andric for (auto &excluded : exclusion_list) { 420e8d8bef9SDimitry Andric if (excluded.GetProcessID() == info.GetProcessID()) 421e8d8bef9SDimitry Andric return true; 422e8d8bef9SDimitry Andric } 423e8d8bef9SDimitry Andric return false; 424e8d8bef9SDimitry Andric }; 425e8d8bef9SDimitry Andric 426e8d8bef9SDimitry Andric ProcessInstanceInfoList loop_process_list; 427e8d8bef9SDimitry Andric while (true) { 428e8d8bef9SDimitry Andric loop_process_list.clear(); 429e8d8bef9SDimitry Andric if (Host::FindProcesses(match_info, loop_process_list)) { 430e8d8bef9SDimitry Andric // Remove all the elements that are in the exclusion list. 431e8d8bef9SDimitry Andric llvm::erase_if(loop_process_list, is_in_exclusion_list); 432e8d8bef9SDimitry Andric 433e8d8bef9SDimitry Andric // One match! We found the desired process. 434e8d8bef9SDimitry Andric if (loop_process_list.size() == 1) { 435e8d8bef9SDimitry Andric auto matching_process_pid = loop_process_list[0].GetProcessID(); 436e8d8bef9SDimitry Andric LLDB_LOG(log, "found pid {0}", matching_process_pid); 437e8d8bef9SDimitry Andric return AttachToProcess(matching_process_pid); 438e8d8bef9SDimitry Andric } 439e8d8bef9SDimitry Andric 440e8d8bef9SDimitry Andric // Multiple matches! Return an error reporting the PIDs we found. 441e8d8bef9SDimitry Andric if (loop_process_list.size() > 1) { 442e8d8bef9SDimitry Andric StreamString error_stream; 443e8d8bef9SDimitry Andric error_stream.Format( 444e8d8bef9SDimitry Andric "Multiple executables with name: '{0}' found. Pids: ", 445e8d8bef9SDimitry Andric process_name); 446e8d8bef9SDimitry Andric for (size_t i = 0; i < loop_process_list.size() - 1; ++i) { 447e8d8bef9SDimitry Andric error_stream.Format("{0}, ", loop_process_list[i].GetProcessID()); 448e8d8bef9SDimitry Andric } 449e8d8bef9SDimitry Andric error_stream.Format("{0}.", loop_process_list.back().GetProcessID()); 450e8d8bef9SDimitry Andric 451e8d8bef9SDimitry Andric Status error; 452e8d8bef9SDimitry Andric error.SetErrorString(error_stream.GetString()); 453e8d8bef9SDimitry Andric return error; 454e8d8bef9SDimitry Andric } 455e8d8bef9SDimitry Andric } 456e8d8bef9SDimitry Andric // No matches, we have not found the process. Sleep until next poll. 457e8d8bef9SDimitry Andric LLDB_LOG(log, "sleep {0} seconds", polling_interval); 458e8d8bef9SDimitry Andric std::this_thread::sleep_for(polling_interval); 459e8d8bef9SDimitry Andric } 460e8d8bef9SDimitry Andric } 461e8d8bef9SDimitry Andric 4620b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::InitializeDelegate( 4630b57cec5SDimitry Andric NativeProcessProtocol *process) { 4640b57cec5SDimitry Andric assert(process && "process cannot be NULL"); 46581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 4660b57cec5SDimitry Andric if (log) { 4679dba64beSDimitry Andric LLDB_LOGF(log, 4689dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s called with " 4690b57cec5SDimitry Andric "NativeProcessProtocol pid %" PRIu64 ", current state: %s", 4700b57cec5SDimitry Andric __FUNCTION__, process->GetID(), 4710b57cec5SDimitry Andric StateAsCString(process->GetState())); 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 4760b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendWResponse( 4770b57cec5SDimitry Andric NativeProcessProtocol *process) { 4780b57cec5SDimitry Andric assert(process && "process cannot be NULL"); 47981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric // send W notification 4820b57cec5SDimitry Andric auto wait_status = process->GetExitStatus(); 4830b57cec5SDimitry Andric if (!wait_status) { 4840b57cec5SDimitry Andric LLDB_LOG(log, "pid = {0}, failed to retrieve process exit status", 4850b57cec5SDimitry Andric process->GetID()); 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric StreamGDBRemote response; 4880b57cec5SDimitry Andric response.PutChar('E'); 4890b57cec5SDimitry Andric response.PutHex8(GDBRemoteServerError::eErrorExitStatus); 4900b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(), 4940b57cec5SDimitry Andric *wait_status); 4950b57cec5SDimitry Andric 49681ad6265SDimitry Andric // If the process was killed through vKill, return "OK". 497fcaf7f86SDimitry Andric if (bool(m_debugged_processes.at(process->GetID()).flags & 498fcaf7f86SDimitry Andric DebuggedProcess::Flag::vkilled)) 49981ad6265SDimitry Andric return SendOKResponse(); 50081ad6265SDimitry Andric 5010b57cec5SDimitry Andric StreamGDBRemote response; 5020b57cec5SDimitry Andric response.Format("{0:g}", *wait_status); 503fcaf7f86SDimitry Andric if (bool(m_extensions_supported & 504fcaf7f86SDimitry Andric NativeProcessProtocol::Extension::multiprocess)) 50581ad6265SDimitry Andric response.Format(";process:{0:x-}", process->GetID()); 50681ad6265SDimitry Andric if (m_non_stop) 50781ad6265SDimitry Andric return SendNotificationPacketNoLock("Stop", m_stop_notification_queue, 50881ad6265SDimitry Andric response.GetString()); 5090b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric static void AppendHexValue(StreamString &response, const uint8_t *buf, 5130b57cec5SDimitry Andric uint32_t buf_size, bool swap) { 5140b57cec5SDimitry Andric int64_t i; 5150b57cec5SDimitry Andric if (swap) { 5160b57cec5SDimitry Andric for (i = buf_size - 1; i >= 0; i--) 5170b57cec5SDimitry Andric response.PutHex8(buf[i]); 5180b57cec5SDimitry Andric } else { 5190b57cec5SDimitry Andric for (i = 0; i < buf_size; i++) 5200b57cec5SDimitry Andric response.PutHex8(buf[i]); 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 5245ffd83dbSDimitry Andric static llvm::StringRef GetEncodingNameOrEmpty(const RegisterInfo ®_info) { 5255ffd83dbSDimitry Andric switch (reg_info.encoding) { 5265ffd83dbSDimitry Andric case eEncodingUint: 5275ffd83dbSDimitry Andric return "uint"; 5285ffd83dbSDimitry Andric case eEncodingSint: 5295ffd83dbSDimitry Andric return "sint"; 5305ffd83dbSDimitry Andric case eEncodingIEEE754: 5315ffd83dbSDimitry Andric return "ieee754"; 5325ffd83dbSDimitry Andric case eEncodingVector: 5335ffd83dbSDimitry Andric return "vector"; 5345ffd83dbSDimitry Andric default: 5355ffd83dbSDimitry Andric return ""; 5365ffd83dbSDimitry Andric } 5375ffd83dbSDimitry Andric } 5385ffd83dbSDimitry Andric 5395ffd83dbSDimitry Andric static llvm::StringRef GetFormatNameOrEmpty(const RegisterInfo ®_info) { 5405ffd83dbSDimitry Andric switch (reg_info.format) { 5415ffd83dbSDimitry Andric case eFormatBinary: 5425ffd83dbSDimitry Andric return "binary"; 5435ffd83dbSDimitry Andric case eFormatDecimal: 5445ffd83dbSDimitry Andric return "decimal"; 5455ffd83dbSDimitry Andric case eFormatHex: 5465ffd83dbSDimitry Andric return "hex"; 5475ffd83dbSDimitry Andric case eFormatFloat: 5485ffd83dbSDimitry Andric return "float"; 5495ffd83dbSDimitry Andric case eFormatVectorOfSInt8: 5505ffd83dbSDimitry Andric return "vector-sint8"; 5515ffd83dbSDimitry Andric case eFormatVectorOfUInt8: 5525ffd83dbSDimitry Andric return "vector-uint8"; 5535ffd83dbSDimitry Andric case eFormatVectorOfSInt16: 5545ffd83dbSDimitry Andric return "vector-sint16"; 5555ffd83dbSDimitry Andric case eFormatVectorOfUInt16: 5565ffd83dbSDimitry Andric return "vector-uint16"; 5575ffd83dbSDimitry Andric case eFormatVectorOfSInt32: 5585ffd83dbSDimitry Andric return "vector-sint32"; 5595ffd83dbSDimitry Andric case eFormatVectorOfUInt32: 5605ffd83dbSDimitry Andric return "vector-uint32"; 5615ffd83dbSDimitry Andric case eFormatVectorOfFloat32: 5625ffd83dbSDimitry Andric return "vector-float32"; 5635ffd83dbSDimitry Andric case eFormatVectorOfUInt64: 5645ffd83dbSDimitry Andric return "vector-uint64"; 5655ffd83dbSDimitry Andric case eFormatVectorOfUInt128: 5665ffd83dbSDimitry Andric return "vector-uint128"; 5675ffd83dbSDimitry Andric default: 5685ffd83dbSDimitry Andric return ""; 5695ffd83dbSDimitry Andric }; 5705ffd83dbSDimitry Andric } 5715ffd83dbSDimitry Andric 5725ffd83dbSDimitry Andric static llvm::StringRef GetKindGenericOrEmpty(const RegisterInfo ®_info) { 5735ffd83dbSDimitry Andric switch (reg_info.kinds[RegisterKind::eRegisterKindGeneric]) { 5745ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_PC: 5755ffd83dbSDimitry Andric return "pc"; 5765ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_SP: 5775ffd83dbSDimitry Andric return "sp"; 5785ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_FP: 5795ffd83dbSDimitry Andric return "fp"; 5805ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_RA: 5815ffd83dbSDimitry Andric return "ra"; 5825ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_FLAGS: 5835ffd83dbSDimitry Andric return "flags"; 5845ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG1: 5855ffd83dbSDimitry Andric return "arg1"; 5865ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG2: 5875ffd83dbSDimitry Andric return "arg2"; 5885ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG3: 5895ffd83dbSDimitry Andric return "arg3"; 5905ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG4: 5915ffd83dbSDimitry Andric return "arg4"; 5925ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG5: 5935ffd83dbSDimitry Andric return "arg5"; 5945ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG6: 5955ffd83dbSDimitry Andric return "arg6"; 5965ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG7: 5975ffd83dbSDimitry Andric return "arg7"; 5985ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG8: 5995ffd83dbSDimitry Andric return "arg8"; 6005ffd83dbSDimitry Andric default: 6015ffd83dbSDimitry Andric return ""; 6025ffd83dbSDimitry Andric } 6035ffd83dbSDimitry Andric } 6045ffd83dbSDimitry Andric 6055ffd83dbSDimitry Andric static void CollectRegNums(const uint32_t *reg_num, StreamString &response, 6065ffd83dbSDimitry Andric bool usehex) { 6075ffd83dbSDimitry Andric for (int i = 0; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) { 6085ffd83dbSDimitry Andric if (i > 0) 6095ffd83dbSDimitry Andric response.PutChar(','); 6105ffd83dbSDimitry Andric if (usehex) 6115ffd83dbSDimitry Andric response.Printf("%" PRIx32, *reg_num); 6125ffd83dbSDimitry Andric else 6135ffd83dbSDimitry Andric response.Printf("%" PRIu32, *reg_num); 6145ffd83dbSDimitry Andric } 6155ffd83dbSDimitry Andric } 6165ffd83dbSDimitry Andric 6170b57cec5SDimitry Andric static void WriteRegisterValueInHexFixedWidth( 6180b57cec5SDimitry Andric StreamString &response, NativeRegisterContext ®_ctx, 6190b57cec5SDimitry Andric const RegisterInfo ®_info, const RegisterValue *reg_value_p, 6200b57cec5SDimitry Andric lldb::ByteOrder byte_order) { 6210b57cec5SDimitry Andric RegisterValue reg_value; 6220b57cec5SDimitry Andric if (!reg_value_p) { 6230b57cec5SDimitry Andric Status error = reg_ctx.ReadRegister(®_info, reg_value); 6240b57cec5SDimitry Andric if (error.Success()) 6250b57cec5SDimitry Andric reg_value_p = ®_value; 6260b57cec5SDimitry Andric // else log. 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric if (reg_value_p) { 6300b57cec5SDimitry Andric AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(), 6310b57cec5SDimitry Andric reg_value_p->GetByteSize(), 6320b57cec5SDimitry Andric byte_order == lldb::eByteOrderLittle); 6330b57cec5SDimitry Andric } else { 6340b57cec5SDimitry Andric // Zero-out any unreadable values. 6350b57cec5SDimitry Andric if (reg_info.byte_size > 0) { 6360b57cec5SDimitry Andric std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0'); 6370b57cec5SDimitry Andric AppendHexValue(response, zeros.data(), zeros.size(), false); 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 642bdd1243dSDimitry Andric static std::optional<json::Object> 6439dba64beSDimitry Andric GetRegistersAsJSON(NativeThreadProtocol &thread) { 64481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric NativeRegisterContext& reg_ctx = thread.GetRegisterContext(); 6470b57cec5SDimitry Andric 6489dba64beSDimitry Andric json::Object register_object; 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET 651e8d8bef9SDimitry Andric const auto expedited_regs = 652e8d8bef9SDimitry Andric reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Full); 6530b57cec5SDimitry Andric #else 654e8d8bef9SDimitry Andric const auto expedited_regs = 655e8d8bef9SDimitry Andric reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Minimal); 6560b57cec5SDimitry Andric #endif 657e8d8bef9SDimitry Andric if (expedited_regs.empty()) 658bdd1243dSDimitry Andric return std::nullopt; 6590b57cec5SDimitry Andric 660e8d8bef9SDimitry Andric for (auto ®_num : expedited_regs) { 6610b57cec5SDimitry Andric const RegisterInfo *const reg_info_p = 6620b57cec5SDimitry Andric reg_ctx.GetRegisterInfoAtIndex(reg_num); 6630b57cec5SDimitry Andric if (reg_info_p == nullptr) { 6649dba64beSDimitry Andric LLDB_LOGF(log, 6650b57cec5SDimitry Andric "%s failed to get register info for register index %" PRIu32, 6660b57cec5SDimitry Andric __FUNCTION__, reg_num); 6670b57cec5SDimitry Andric continue; 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric if (reg_info_p->value_regs != nullptr) 6710b57cec5SDimitry Andric continue; // Only expedite registers that are not contained in other 6720b57cec5SDimitry Andric // registers. 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric RegisterValue reg_value; 6750b57cec5SDimitry Andric Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); 6760b57cec5SDimitry Andric if (error.Fail()) { 6779dba64beSDimitry Andric LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s", 6780b57cec5SDimitry Andric __FUNCTION__, 6790b57cec5SDimitry Andric reg_info_p->name ? reg_info_p->name : "<unnamed-register>", 6800b57cec5SDimitry Andric reg_num, error.AsCString()); 6810b57cec5SDimitry Andric continue; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric StreamString stream; 6850b57cec5SDimitry Andric WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p, 6860b57cec5SDimitry Andric ®_value, lldb::eByteOrderBig); 6870b57cec5SDimitry Andric 6889dba64beSDimitry Andric register_object.try_emplace(llvm::to_string(reg_num), 6899dba64beSDimitry Andric stream.GetString().str()); 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric 6929dba64beSDimitry Andric return register_object; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric static const char *GetStopReasonString(StopReason stop_reason) { 6960b57cec5SDimitry Andric switch (stop_reason) { 6970b57cec5SDimitry Andric case eStopReasonTrace: 6980b57cec5SDimitry Andric return "trace"; 6990b57cec5SDimitry Andric case eStopReasonBreakpoint: 7000b57cec5SDimitry Andric return "breakpoint"; 7010b57cec5SDimitry Andric case eStopReasonWatchpoint: 7020b57cec5SDimitry Andric return "watchpoint"; 7030b57cec5SDimitry Andric case eStopReasonSignal: 7040b57cec5SDimitry Andric return "signal"; 7050b57cec5SDimitry Andric case eStopReasonException: 7060b57cec5SDimitry Andric return "exception"; 7070b57cec5SDimitry Andric case eStopReasonExec: 7080b57cec5SDimitry Andric return "exec"; 709fe6060f1SDimitry Andric case eStopReasonProcessorTrace: 710fe6060f1SDimitry Andric return "processor trace"; 711fe6060f1SDimitry Andric case eStopReasonFork: 712fe6060f1SDimitry Andric return "fork"; 713fe6060f1SDimitry Andric case eStopReasonVFork: 714fe6060f1SDimitry Andric return "vfork"; 715fe6060f1SDimitry Andric case eStopReasonVForkDone: 716fe6060f1SDimitry Andric return "vforkdone"; 7170b57cec5SDimitry Andric case eStopReasonInstrumentation: 7180b57cec5SDimitry Andric case eStopReasonInvalid: 7190b57cec5SDimitry Andric case eStopReasonPlanComplete: 7200b57cec5SDimitry Andric case eStopReasonThreadExiting: 7210b57cec5SDimitry Andric case eStopReasonNone: 7220b57cec5SDimitry Andric break; // ignored 7230b57cec5SDimitry Andric } 7240b57cec5SDimitry Andric return nullptr; 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric 7279dba64beSDimitry Andric static llvm::Expected<json::Array> 7289dba64beSDimitry Andric GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) { 72981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 7300b57cec5SDimitry Andric 7319dba64beSDimitry Andric json::Array threads_array; 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric // Ensure we can get info on the given thread. 73481ad6265SDimitry Andric for (NativeThreadProtocol &thread : process.Threads()) { 73581ad6265SDimitry Andric lldb::tid_t tid = thread.GetID(); 7360b57cec5SDimitry Andric // Grab the reason this thread stopped. 7370b57cec5SDimitry Andric struct ThreadStopInfo tid_stop_info; 7380b57cec5SDimitry Andric std::string description; 73981ad6265SDimitry Andric if (!thread.GetStopReason(tid_stop_info, description)) 7409dba64beSDimitry Andric return llvm::make_error<llvm::StringError>( 7419dba64beSDimitry Andric "failed to get stop reason", llvm::inconvertibleErrorCode()); 7420b57cec5SDimitry Andric 74381ad6265SDimitry Andric const int signum = tid_stop_info.signo; 7440b57cec5SDimitry Andric if (log) { 7459dba64beSDimitry Andric LLDB_LOGF(log, 7469dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 7470b57cec5SDimitry Andric " tid %" PRIu64 7480b57cec5SDimitry Andric " got signal signo = %d, reason = %d, exc_type = %" PRIu64, 7490b57cec5SDimitry Andric __FUNCTION__, process.GetID(), tid, signum, 7500b57cec5SDimitry Andric tid_stop_info.reason, tid_stop_info.details.exception.type); 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric 7539dba64beSDimitry Andric json::Object thread_obj; 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric if (!abridged) { 756bdd1243dSDimitry Andric if (std::optional<json::Object> registers = GetRegistersAsJSON(thread)) 7579dba64beSDimitry Andric thread_obj.try_emplace("registers", std::move(*registers)); 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric 7609dba64beSDimitry Andric thread_obj.try_emplace("tid", static_cast<int64_t>(tid)); 7619dba64beSDimitry Andric 7620b57cec5SDimitry Andric if (signum != 0) 7639dba64beSDimitry Andric thread_obj.try_emplace("signal", signum); 7640b57cec5SDimitry Andric 76581ad6265SDimitry Andric const std::string thread_name = thread.GetName(); 7660b57cec5SDimitry Andric if (!thread_name.empty()) 7679dba64beSDimitry Andric thread_obj.try_emplace("name", thread_name); 7680b57cec5SDimitry Andric 7699dba64beSDimitry Andric const char *stop_reason = GetStopReasonString(tid_stop_info.reason); 7709dba64beSDimitry Andric if (stop_reason) 7719dba64beSDimitry Andric thread_obj.try_emplace("reason", stop_reason); 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric if (!description.empty()) 7749dba64beSDimitry Andric thread_obj.try_emplace("description", description); 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric if ((tid_stop_info.reason == eStopReasonException) && 7770b57cec5SDimitry Andric tid_stop_info.details.exception.type) { 7789dba64beSDimitry Andric thread_obj.try_emplace( 7799dba64beSDimitry Andric "metype", static_cast<int64_t>(tid_stop_info.details.exception.type)); 7800b57cec5SDimitry Andric 7819dba64beSDimitry Andric json::Array medata_array; 7820b57cec5SDimitry Andric for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; 7830b57cec5SDimitry Andric ++i) { 7849dba64beSDimitry Andric medata_array.push_back( 7859dba64beSDimitry Andric static_cast<int64_t>(tid_stop_info.details.exception.data[i])); 7860b57cec5SDimitry Andric } 7879dba64beSDimitry Andric thread_obj.try_emplace("medata", std::move(medata_array)); 7880b57cec5SDimitry Andric } 7899dba64beSDimitry Andric threads_array.push_back(std::move(thread_obj)); 7900b57cec5SDimitry Andric } 7919dba64beSDimitry Andric return threads_array; 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric 79481ad6265SDimitry Andric StreamString 79581ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::PrepareStopReplyPacketForThread( 79681ad6265SDimitry Andric NativeThreadProtocol &thread) { 79781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 7980b57cec5SDimitry Andric 79981ad6265SDimitry Andric NativeProcessProtocol &process = thread.GetProcess(); 8000b57cec5SDimitry Andric 80181ad6265SDimitry Andric LLDB_LOG(log, "preparing packet for pid {0} tid {1}", process.GetID(), 80281ad6265SDimitry Andric thread.GetID()); 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric // Grab the reason this thread stopped. 80581ad6265SDimitry Andric StreamString response; 8060b57cec5SDimitry Andric struct ThreadStopInfo tid_stop_info; 8070b57cec5SDimitry Andric std::string description; 80881ad6265SDimitry Andric if (!thread.GetStopReason(tid_stop_info, description)) 80981ad6265SDimitry Andric return response; 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric // FIXME implement register handling for exec'd inferiors. 8120b57cec5SDimitry Andric // if (tid_stop_info.reason == eStopReasonExec) { 8130b57cec5SDimitry Andric // const bool force = true; 8140b57cec5SDimitry Andric // InitializeRegisters(force); 8150b57cec5SDimitry Andric // } 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric // Output the T packet with the thread 8180b57cec5SDimitry Andric response.PutChar('T'); 81981ad6265SDimitry Andric int signum = tid_stop_info.signo; 8200b57cec5SDimitry Andric LLDB_LOG( 8210b57cec5SDimitry Andric log, 8220b57cec5SDimitry Andric "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}", 82381ad6265SDimitry Andric process.GetID(), thread.GetID(), signum, int(tid_stop_info.reason), 8240b57cec5SDimitry Andric tid_stop_info.details.exception.type); 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric // Print the signal number. 8270b57cec5SDimitry Andric response.PutHex8(signum & 0xff); 8280b57cec5SDimitry Andric 82981ad6265SDimitry Andric // Include the (pid and) tid. 83081ad6265SDimitry Andric response.PutCString("thread:"); 83181ad6265SDimitry Andric AppendThreadIDToResponse(response, process.GetID(), thread.GetID()); 83281ad6265SDimitry Andric response.PutChar(';'); 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric // Include the thread name if there is one. 83581ad6265SDimitry Andric const std::string thread_name = thread.GetName(); 8360b57cec5SDimitry Andric if (!thread_name.empty()) { 8370b57cec5SDimitry Andric size_t thread_name_len = thread_name.length(); 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) { 8400b57cec5SDimitry Andric response.PutCString("name:"); 8410b57cec5SDimitry Andric response.PutCString(thread_name); 8420b57cec5SDimitry Andric } else { 8430b57cec5SDimitry Andric // The thread name contains special chars, send as hex bytes. 8440b57cec5SDimitry Andric response.PutCString("hexname:"); 8450b57cec5SDimitry Andric response.PutStringAsRawHex8(thread_name); 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric response.PutChar(';'); 8480b57cec5SDimitry Andric } 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric // If a 'QListThreadsInStopReply' was sent to enable this feature, we will 8510b57cec5SDimitry Andric // send all thread IDs back in the "threads" key whose value is a list of hex 8520b57cec5SDimitry Andric // thread IDs separated by commas: 8530b57cec5SDimitry Andric // "threads:10a,10b,10c;" 8540b57cec5SDimitry Andric // This will save the debugger from having to send a pair of qfThreadInfo and 8550b57cec5SDimitry Andric // qsThreadInfo packets, but it also might take a lot of room in the stop 8560b57cec5SDimitry Andric // reply packet, so it must be enabled only on systems where there are no 8570b57cec5SDimitry Andric // limits on packet lengths. 8580b57cec5SDimitry Andric if (m_list_threads_in_stop_reply) { 8590b57cec5SDimitry Andric response.PutCString("threads:"); 8600b57cec5SDimitry Andric 86181ad6265SDimitry Andric uint32_t thread_num = 0; 86281ad6265SDimitry Andric for (NativeThreadProtocol &listed_thread : process.Threads()) { 86381ad6265SDimitry Andric if (thread_num > 0) 8640b57cec5SDimitry Andric response.PutChar(','); 86581ad6265SDimitry Andric response.Printf("%" PRIx64, listed_thread.GetID()); 86681ad6265SDimitry Andric ++thread_num; 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric response.PutChar(';'); 8690b57cec5SDimitry Andric 8700b57cec5SDimitry Andric // Include JSON info that describes the stop reason for any threads that 8710b57cec5SDimitry Andric // actually have stop reasons. We use the new "jstopinfo" key whose values 8720b57cec5SDimitry Andric // is hex ascii JSON that contains the thread IDs thread stop info only for 8730b57cec5SDimitry Andric // threads that have stop reasons. Only send this if we have more than one 8740b57cec5SDimitry Andric // thread otherwise this packet has all the info it needs. 87581ad6265SDimitry Andric if (thread_num > 1) { 8760b57cec5SDimitry Andric const bool threads_with_valid_stop_info_only = true; 8779dba64beSDimitry Andric llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo( 878fe6060f1SDimitry Andric *m_current_process, threads_with_valid_stop_info_only); 8799dba64beSDimitry Andric if (threads_info) { 8800b57cec5SDimitry Andric response.PutCString("jstopinfo:"); 8810b57cec5SDimitry Andric StreamString unescaped_response; 8829dba64beSDimitry Andric unescaped_response.AsRawOstream() << std::move(*threads_info); 8830b57cec5SDimitry Andric response.PutStringAsRawHex8(unescaped_response.GetData()); 8840b57cec5SDimitry Andric response.PutChar(';'); 8859dba64beSDimitry Andric } else { 886480093f4SDimitry Andric LLDB_LOG_ERROR(log, threads_info.takeError(), 887480093f4SDimitry Andric "failed to prepare a jstopinfo field for pid {1}: {0}", 88881ad6265SDimitry Andric process.GetID()); 8899dba64beSDimitry Andric } 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric response.PutCString("thread-pcs"); 8930b57cec5SDimitry Andric char delimiter = ':'; 89481ad6265SDimitry Andric for (NativeThreadProtocol &thread : process.Threads()) { 89581ad6265SDimitry Andric NativeRegisterContext ®_ctx = thread.GetRegisterContext(); 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber( 8980b57cec5SDimitry Andric eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 8990b57cec5SDimitry Andric const RegisterInfo *const reg_info_p = 9000b57cec5SDimitry Andric reg_ctx.GetRegisterInfoAtIndex(reg_to_read); 9010b57cec5SDimitry Andric 9020b57cec5SDimitry Andric RegisterValue reg_value; 9030b57cec5SDimitry Andric Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); 9040b57cec5SDimitry Andric if (error.Fail()) { 9059dba64beSDimitry Andric LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s", 9060b57cec5SDimitry Andric __FUNCTION__, 9079dba64beSDimitry Andric reg_info_p->name ? reg_info_p->name : "<unnamed-register>", 9080b57cec5SDimitry Andric reg_to_read, error.AsCString()); 9090b57cec5SDimitry Andric continue; 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric response.PutChar(delimiter); 9130b57cec5SDimitry Andric delimiter = ','; 9140b57cec5SDimitry Andric WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p, 9150b57cec5SDimitry Andric ®_value, endian::InlHostByteOrder()); 9160b57cec5SDimitry Andric } 9170b57cec5SDimitry Andric 9180b57cec5SDimitry Andric response.PutChar(';'); 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric // 9220b57cec5SDimitry Andric // Expedite registers. 9230b57cec5SDimitry Andric // 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric // Grab the register context. 92681ad6265SDimitry Andric NativeRegisterContext ®_ctx = thread.GetRegisterContext(); 927e8d8bef9SDimitry Andric const auto expedited_regs = 928e8d8bef9SDimitry Andric reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Full); 9290b57cec5SDimitry Andric 930e8d8bef9SDimitry Andric for (auto ®_num : expedited_regs) { 9310b57cec5SDimitry Andric const RegisterInfo *const reg_info_p = 932e8d8bef9SDimitry Andric reg_ctx.GetRegisterInfoAtIndex(reg_num); 9330b57cec5SDimitry Andric // Only expediate registers that are not contained in other registers. 934e8d8bef9SDimitry Andric if (reg_info_p != nullptr && reg_info_p->value_regs == nullptr) { 9350b57cec5SDimitry Andric RegisterValue reg_value; 9360b57cec5SDimitry Andric Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); 9370b57cec5SDimitry Andric if (error.Success()) { 938e8d8bef9SDimitry Andric response.Printf("%.02x:", reg_num); 9390b57cec5SDimitry Andric WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p, 9400b57cec5SDimitry Andric ®_value, lldb::eByteOrderBig); 9410b57cec5SDimitry Andric response.PutChar(';'); 9420b57cec5SDimitry Andric } else { 94381ad6265SDimitry Andric LLDB_LOGF(log, 94481ad6265SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed to read " 9450b57cec5SDimitry Andric "register '%s' index %" PRIu32 ": %s", 9460b57cec5SDimitry Andric __FUNCTION__, 9479dba64beSDimitry Andric reg_info_p->name ? reg_info_p->name : "<unnamed-register>", 948e8d8bef9SDimitry Andric reg_num, error.AsCString()); 9490b57cec5SDimitry Andric } 9500b57cec5SDimitry Andric } 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric const char *reason_str = GetStopReasonString(tid_stop_info.reason); 9540b57cec5SDimitry Andric if (reason_str != nullptr) { 9550b57cec5SDimitry Andric response.Printf("reason:%s;", reason_str); 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric if (!description.empty()) { 9590b57cec5SDimitry Andric // Description may contains special chars, send as hex bytes. 9600b57cec5SDimitry Andric response.PutCString("description:"); 9610b57cec5SDimitry Andric response.PutStringAsRawHex8(description); 9620b57cec5SDimitry Andric response.PutChar(';'); 9630b57cec5SDimitry Andric } else if ((tid_stop_info.reason == eStopReasonException) && 9640b57cec5SDimitry Andric tid_stop_info.details.exception.type) { 9650b57cec5SDimitry Andric response.PutCString("metype:"); 9660b57cec5SDimitry Andric response.PutHex64(tid_stop_info.details.exception.type); 9670b57cec5SDimitry Andric response.PutCString(";mecount:"); 9680b57cec5SDimitry Andric response.PutHex32(tid_stop_info.details.exception.data_count); 9690b57cec5SDimitry Andric response.PutChar(';'); 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) { 9720b57cec5SDimitry Andric response.PutCString("medata:"); 9730b57cec5SDimitry Andric response.PutHex64(tid_stop_info.details.exception.data[i]); 9740b57cec5SDimitry Andric response.PutChar(';'); 9750b57cec5SDimitry Andric } 9760b57cec5SDimitry Andric } 9770b57cec5SDimitry Andric 978fe6060f1SDimitry Andric // Include child process PID/TID for forks. 979fe6060f1SDimitry Andric if (tid_stop_info.reason == eStopReasonFork || 980fe6060f1SDimitry Andric tid_stop_info.reason == eStopReasonVFork) { 981fe6060f1SDimitry Andric assert(bool(m_extensions_supported & 982fe6060f1SDimitry Andric NativeProcessProtocol::Extension::multiprocess)); 983fe6060f1SDimitry Andric if (tid_stop_info.reason == eStopReasonFork) 984fe6060f1SDimitry Andric assert(bool(m_extensions_supported & 985fe6060f1SDimitry Andric NativeProcessProtocol::Extension::fork)); 986fe6060f1SDimitry Andric if (tid_stop_info.reason == eStopReasonVFork) 987fe6060f1SDimitry Andric assert(bool(m_extensions_supported & 988fe6060f1SDimitry Andric NativeProcessProtocol::Extension::vfork)); 989fe6060f1SDimitry Andric response.Printf("%s:p%" PRIx64 ".%" PRIx64 ";", reason_str, 990fe6060f1SDimitry Andric tid_stop_info.details.fork.child_pid, 991fe6060f1SDimitry Andric tid_stop_info.details.fork.child_tid); 992fe6060f1SDimitry Andric } 993fe6060f1SDimitry Andric 99481ad6265SDimitry Andric return response; 99581ad6265SDimitry Andric } 99681ad6265SDimitry Andric 99781ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 99881ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( 99981ad6265SDimitry Andric NativeProcessProtocol &process, lldb::tid_t tid, bool force_synchronous) { 100081ad6265SDimitry Andric // Ensure we can get info on the given thread. 100181ad6265SDimitry Andric NativeThreadProtocol *thread = process.GetThreadByID(tid); 100281ad6265SDimitry Andric if (!thread) 100381ad6265SDimitry Andric return SendErrorResponse(51); 100481ad6265SDimitry Andric 100581ad6265SDimitry Andric StreamString response = PrepareStopReplyPacketForThread(*thread); 100681ad6265SDimitry Andric if (response.Empty()) 100781ad6265SDimitry Andric return SendErrorResponse(42); 100881ad6265SDimitry Andric 100981ad6265SDimitry Andric if (m_non_stop && !force_synchronous) { 101081ad6265SDimitry Andric PacketResult ret = SendNotificationPacketNoLock( 101181ad6265SDimitry Andric "Stop", m_stop_notification_queue, response.GetString()); 101281ad6265SDimitry Andric // Queue notification events for the remaining threads. 101381ad6265SDimitry Andric EnqueueStopReplyPackets(tid); 101481ad6265SDimitry Andric return ret; 101581ad6265SDimitry Andric } 101681ad6265SDimitry Andric 10170b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric 102081ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::EnqueueStopReplyPackets( 102181ad6265SDimitry Andric lldb::tid_t thread_to_skip) { 102281ad6265SDimitry Andric if (!m_non_stop) 102381ad6265SDimitry Andric return; 102481ad6265SDimitry Andric 102581ad6265SDimitry Andric for (NativeThreadProtocol &listed_thread : m_current_process->Threads()) { 1026fcaf7f86SDimitry Andric if (listed_thread.GetID() != thread_to_skip) { 1027fcaf7f86SDimitry Andric StreamString stop_reply = PrepareStopReplyPacketForThread(listed_thread); 1028fcaf7f86SDimitry Andric if (!stop_reply.Empty()) 1029fcaf7f86SDimitry Andric m_stop_notification_queue.push_back(stop_reply.GetString().str()); 1030fcaf7f86SDimitry Andric } 103181ad6265SDimitry Andric } 103281ad6265SDimitry Andric } 103381ad6265SDimitry Andric 10340b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( 10350b57cec5SDimitry Andric NativeProcessProtocol *process) { 10360b57cec5SDimitry Andric assert(process && "process cannot be NULL"); 10370b57cec5SDimitry Andric 103881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 10399dba64beSDimitry Andric LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); 10400b57cec5SDimitry Andric 104181ad6265SDimitry Andric PacketResult result = SendStopReasonForState( 104281ad6265SDimitry Andric *process, StateType::eStateExited, /*force_synchronous=*/false); 10430b57cec5SDimitry Andric if (result != PacketResult::Success) { 10449dba64beSDimitry Andric LLDB_LOGF(log, 10459dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed to send stop " 10460b57cec5SDimitry Andric "notification for PID %" PRIu64 ", state: eStateExited", 10470b57cec5SDimitry Andric __FUNCTION__, process->GetID()); 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric 105081ad6265SDimitry Andric if (m_current_process == process) 105181ad6265SDimitry Andric m_current_process = nullptr; 105281ad6265SDimitry Andric if (m_continue_process == process) 105381ad6265SDimitry Andric m_continue_process = nullptr; 105481ad6265SDimitry Andric 105581ad6265SDimitry Andric lldb::pid_t pid = process->GetID(); 105681ad6265SDimitry Andric m_mainloop.AddPendingCallback([this, pid](MainLoopBase &loop) { 1057fcaf7f86SDimitry Andric auto find_it = m_debugged_processes.find(pid); 1058fcaf7f86SDimitry Andric assert(find_it != m_debugged_processes.end()); 1059fcaf7f86SDimitry Andric bool vkilled = bool(find_it->second.flags & DebuggedProcess::Flag::vkilled); 1060fcaf7f86SDimitry Andric m_debugged_processes.erase(find_it); 106181ad6265SDimitry Andric // Terminate the main loop only if vKill has not been used. 106281ad6265SDimitry Andric // When running in non-stop mode, wait for the vStopped to clear 106381ad6265SDimitry Andric // the notification queue. 1064fcaf7f86SDimitry Andric if (m_debugged_processes.empty() && !m_non_stop && !vkilled) { 106581ad6265SDimitry Andric // Close the pipe to the inferior terminal i/o if we launched it and set 106681ad6265SDimitry Andric // one up. 10670b57cec5SDimitry Andric MaybeCloseInferiorTerminalConnection(); 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric // We are ready to exit the debug monitor. 10700b57cec5SDimitry Andric m_exit_now = true; 107181ad6265SDimitry Andric loop.RequestTermination(); 107281ad6265SDimitry Andric } 107381ad6265SDimitry Andric }); 10740b57cec5SDimitry Andric } 10750b57cec5SDimitry Andric 10760b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( 10770b57cec5SDimitry Andric NativeProcessProtocol *process) { 10780b57cec5SDimitry Andric assert(process && "process cannot be NULL"); 10790b57cec5SDimitry Andric 108081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 10819dba64beSDimitry Andric LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); 10820b57cec5SDimitry Andric 108381ad6265SDimitry Andric PacketResult result = SendStopReasonForState( 108481ad6265SDimitry Andric *process, StateType::eStateStopped, /*force_synchronous=*/false); 10850b57cec5SDimitry Andric if (result != PacketResult::Success) { 10869dba64beSDimitry Andric LLDB_LOGF(log, 10879dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed to send stop " 10880b57cec5SDimitry Andric "notification for PID %" PRIu64 ", state: eStateExited", 10890b57cec5SDimitry Andric __FUNCTION__, process->GetID()); 10900b57cec5SDimitry Andric } 10910b57cec5SDimitry Andric } 10920b57cec5SDimitry Andric 10930b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( 10940b57cec5SDimitry Andric NativeProcessProtocol *process, lldb::StateType state) { 10950b57cec5SDimitry Andric assert(process && "process cannot be NULL"); 109681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 10970b57cec5SDimitry Andric if (log) { 10989dba64beSDimitry Andric LLDB_LOGF(log, 10999dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s called with " 11000b57cec5SDimitry Andric "NativeProcessProtocol pid %" PRIu64 ", state: %s", 11010b57cec5SDimitry Andric __FUNCTION__, process->GetID(), StateAsCString(state)); 11020b57cec5SDimitry Andric } 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric switch (state) { 11050b57cec5SDimitry Andric case StateType::eStateRunning: 11060b57cec5SDimitry Andric break; 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric case StateType::eStateStopped: 11090b57cec5SDimitry Andric // Make sure we get all of the pending stdout/stderr from the inferior and 11100b57cec5SDimitry Andric // send it to the lldb host before we send the state change notification 11110b57cec5SDimitry Andric SendProcessOutput(); 11120b57cec5SDimitry Andric // Then stop the forwarding, so that any late output (see llvm.org/pr25652) 11130b57cec5SDimitry Andric // does not interfere with our protocol. 1114fcaf7f86SDimitry Andric if (!m_non_stop) 11150b57cec5SDimitry Andric StopSTDIOForwarding(); 11160b57cec5SDimitry Andric HandleInferiorState_Stopped(process); 11170b57cec5SDimitry Andric break; 11180b57cec5SDimitry Andric 11190b57cec5SDimitry Andric case StateType::eStateExited: 11200b57cec5SDimitry Andric // Same as above 11210b57cec5SDimitry Andric SendProcessOutput(); 1122fcaf7f86SDimitry Andric if (!m_non_stop) 11230b57cec5SDimitry Andric StopSTDIOForwarding(); 11240b57cec5SDimitry Andric HandleInferiorState_Exited(process); 11250b57cec5SDimitry Andric break; 11260b57cec5SDimitry Andric 11270b57cec5SDimitry Andric default: 11280b57cec5SDimitry Andric if (log) { 11299dba64beSDimitry Andric LLDB_LOGF(log, 11309dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s didn't handle state " 11310b57cec5SDimitry Andric "change for pid %" PRIu64 ", new state: %s", 11320b57cec5SDimitry Andric __FUNCTION__, process->GetID(), StateAsCString(state)); 11330b57cec5SDimitry Andric } 11340b57cec5SDimitry Andric break; 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) { 11390b57cec5SDimitry Andric ClearProcessSpecificData(); 11400b57cec5SDimitry Andric } 11410b57cec5SDimitry Andric 1142fe6060f1SDimitry Andric void GDBRemoteCommunicationServerLLGS::NewSubprocess( 1143fe6060f1SDimitry Andric NativeProcessProtocol *parent_process, 1144fe6060f1SDimitry Andric std::unique_ptr<NativeProcessProtocol> child_process) { 1145fe6060f1SDimitry Andric lldb::pid_t child_pid = child_process->GetID(); 1146fe6060f1SDimitry Andric assert(child_pid != LLDB_INVALID_PROCESS_ID); 1147fe6060f1SDimitry Andric assert(m_debugged_processes.find(child_pid) == m_debugged_processes.end()); 1148fcaf7f86SDimitry Andric m_debugged_processes.emplace( 1149fcaf7f86SDimitry Andric child_pid, 1150fcaf7f86SDimitry Andric DebuggedProcess{std::move(child_process), DebuggedProcess::Flag{}}); 1151fe6060f1SDimitry Andric } 1152fe6060f1SDimitry Andric 11530b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { 115404eeddc0SDimitry Andric Log *log = GetLog(GDBRLog::Comm); 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric bool interrupt = false; 11570b57cec5SDimitry Andric bool done = false; 11580b57cec5SDimitry Andric Status error; 11590b57cec5SDimitry Andric while (true) { 11600b57cec5SDimitry Andric const PacketResult result = GetPacketAndSendResponse( 11610b57cec5SDimitry Andric std::chrono::microseconds(0), error, interrupt, done); 11620b57cec5SDimitry Andric if (result == PacketResult::ErrorReplyTimeout) 11630b57cec5SDimitry Andric break; // No more packets in the queue 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric if ((result != PacketResult::Success)) { 11669dba64beSDimitry Andric LLDB_LOGF(log, 11679dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s processing a packet " 11680b57cec5SDimitry Andric "failed: %s", 11690b57cec5SDimitry Andric __FUNCTION__, error.AsCString()); 11700b57cec5SDimitry Andric m_mainloop.RequestTermination(); 11710b57cec5SDimitry Andric break; 11720b57cec5SDimitry Andric } 11730b57cec5SDimitry Andric } 11740b57cec5SDimitry Andric } 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::InitializeConnection( 11775ffd83dbSDimitry Andric std::unique_ptr<Connection> connection) { 11780b57cec5SDimitry Andric IOObjectSP read_object_sp = connection->GetReadObject(); 11795ffd83dbSDimitry Andric GDBRemoteCommunicationServer::SetConnection(std::move(connection)); 11800b57cec5SDimitry Andric 11810b57cec5SDimitry Andric Status error; 11820b57cec5SDimitry Andric m_network_handle_up = m_mainloop.RegisterReadObject( 11830b57cec5SDimitry Andric read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); }, 11840b57cec5SDimitry Andric error); 11850b57cec5SDimitry Andric return error; 11860b57cec5SDimitry Andric } 11870b57cec5SDimitry Andric 11880b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 11890b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer, 11900b57cec5SDimitry Andric uint32_t len) { 11910b57cec5SDimitry Andric if ((buffer == nullptr) || (len == 0)) { 11920b57cec5SDimitry Andric // Nothing to send. 11930b57cec5SDimitry Andric return PacketResult::Success; 11940b57cec5SDimitry Andric } 11950b57cec5SDimitry Andric 11960b57cec5SDimitry Andric StreamString response; 11970b57cec5SDimitry Andric response.PutChar('O'); 11980b57cec5SDimitry Andric response.PutBytesAsRawHex8(buffer, len); 11990b57cec5SDimitry Andric 1200fcaf7f86SDimitry Andric if (m_non_stop) 1201fcaf7f86SDimitry Andric return SendNotificationPacketNoLock("Stdio", m_stdio_notification_queue, 1202fcaf7f86SDimitry Andric response.GetString()); 12030b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 12040b57cec5SDimitry Andric } 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) { 12070b57cec5SDimitry Andric Status error; 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric // Set up the reading/handling of process I/O 12100b57cec5SDimitry Andric std::unique_ptr<ConnectionFileDescriptor> conn_up( 12110b57cec5SDimitry Andric new ConnectionFileDescriptor(fd, true)); 12120b57cec5SDimitry Andric if (!conn_up) { 12130b57cec5SDimitry Andric error.SetErrorString("failed to create ConnectionFileDescriptor"); 12140b57cec5SDimitry Andric return error; 12150b57cec5SDimitry Andric } 12160b57cec5SDimitry Andric 12170b57cec5SDimitry Andric m_stdio_communication.SetCloseOnEOF(false); 12185ffd83dbSDimitry Andric m_stdio_communication.SetConnection(std::move(conn_up)); 12190b57cec5SDimitry Andric if (!m_stdio_communication.IsConnected()) { 12200b57cec5SDimitry Andric error.SetErrorString( 12210b57cec5SDimitry Andric "failed to set connection for inferior I/O communication"); 12220b57cec5SDimitry Andric return error; 12230b57cec5SDimitry Andric } 12240b57cec5SDimitry Andric 12250b57cec5SDimitry Andric return Status(); 12260b57cec5SDimitry Andric } 12270b57cec5SDimitry Andric 12280b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() { 12290b57cec5SDimitry Andric // Don't forward if not connected (e.g. when attaching). 12300b57cec5SDimitry Andric if (!m_stdio_communication.IsConnected()) 12310b57cec5SDimitry Andric return; 12320b57cec5SDimitry Andric 12330b57cec5SDimitry Andric Status error; 123481ad6265SDimitry Andric assert(!m_stdio_handle_up); 12350b57cec5SDimitry Andric m_stdio_handle_up = m_mainloop.RegisterReadObject( 12360b57cec5SDimitry Andric m_stdio_communication.GetConnection()->GetReadObject(), 12370b57cec5SDimitry Andric [this](MainLoopBase &) { SendProcessOutput(); }, error); 12380b57cec5SDimitry Andric 12390b57cec5SDimitry Andric if (!m_stdio_handle_up) { 12400b57cec5SDimitry Andric // Not much we can do about the failure. Log it and continue without 12410b57cec5SDimitry Andric // forwarding. 124281ad6265SDimitry Andric if (Log *log = GetLog(LLDBLog::Process)) 124381ad6265SDimitry Andric LLDB_LOG(log, "Failed to set up stdio forwarding: {0}", error); 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() { 12480b57cec5SDimitry Andric m_stdio_handle_up.reset(); 12490b57cec5SDimitry Andric } 12500b57cec5SDimitry Andric 12510b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { 12520b57cec5SDimitry Andric char buffer[1024]; 12530b57cec5SDimitry Andric ConnectionStatus status; 12540b57cec5SDimitry Andric Status error; 12550b57cec5SDimitry Andric while (true) { 12560b57cec5SDimitry Andric size_t bytes_read = m_stdio_communication.Read( 12570b57cec5SDimitry Andric buffer, sizeof buffer, std::chrono::microseconds(0), status, &error); 12580b57cec5SDimitry Andric switch (status) { 12590b57cec5SDimitry Andric case eConnectionStatusSuccess: 12600b57cec5SDimitry Andric SendONotification(buffer, bytes_read); 12610b57cec5SDimitry Andric break; 12620b57cec5SDimitry Andric case eConnectionStatusLostConnection: 12630b57cec5SDimitry Andric case eConnectionStatusEndOfFile: 12640b57cec5SDimitry Andric case eConnectionStatusError: 12650b57cec5SDimitry Andric case eConnectionStatusNoConnection: 126681ad6265SDimitry Andric if (Log *log = GetLog(LLDBLog::Process)) 12679dba64beSDimitry Andric LLDB_LOGF(log, 12689dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s Stopping stdio " 12690b57cec5SDimitry Andric "forwarding as communication returned status %d (error: " 12700b57cec5SDimitry Andric "%s)", 12710b57cec5SDimitry Andric __FUNCTION__, status, error.AsCString()); 12720b57cec5SDimitry Andric m_stdio_handle_up.reset(); 12730b57cec5SDimitry Andric return; 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric case eConnectionStatusInterrupted: 12760b57cec5SDimitry Andric case eConnectionStatusTimedOut: 12770b57cec5SDimitry Andric return; 12780b57cec5SDimitry Andric } 12790b57cec5SDimitry Andric } 12800b57cec5SDimitry Andric } 12810b57cec5SDimitry Andric 12820b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 1283fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported( 12840b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 1285fe6060f1SDimitry Andric 12860b57cec5SDimitry Andric // Fail if we don't have a current process. 1287fe6060f1SDimitry Andric if (!m_current_process || 1288fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 1289fe6060f1SDimitry Andric return SendErrorResponse(Status("Process not running.")); 12900b57cec5SDimitry Andric 1291fe6060f1SDimitry Andric return SendJSONResponse(m_current_process->TraceSupported()); 12920b57cec5SDimitry Andric } 12930b57cec5SDimitry Andric 12940b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 1295fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop( 12960b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 12970b57cec5SDimitry Andric // Fail if we don't have a current process. 1298fe6060f1SDimitry Andric if (!m_current_process || 1299fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 1300fe6060f1SDimitry Andric return SendErrorResponse(Status("Process not running.")); 13010b57cec5SDimitry Andric 1302fe6060f1SDimitry Andric packet.ConsumeFront("jLLDBTraceStop:"); 1303fe6060f1SDimitry Andric Expected<TraceStopRequest> stop_request = 1304fe6060f1SDimitry Andric json::parse<TraceStopRequest>(packet.Peek(), "TraceStopRequest"); 1305fe6060f1SDimitry Andric if (!stop_request) 1306fe6060f1SDimitry Andric return SendErrorResponse(stop_request.takeError()); 13070b57cec5SDimitry Andric 1308fe6060f1SDimitry Andric if (Error err = m_current_process->TraceStop(*stop_request)) 1309fe6060f1SDimitry Andric return SendErrorResponse(std::move(err)); 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric return SendOKResponse(); 13120b57cec5SDimitry Andric } 13130b57cec5SDimitry Andric 13140b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 1315fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart( 1316e8d8bef9SDimitry Andric StringExtractorGDBRemote &packet) { 1317e8d8bef9SDimitry Andric 1318e8d8bef9SDimitry Andric // Fail if we don't have a current process. 1319fe6060f1SDimitry Andric if (!m_current_process || 1320fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 1321e8d8bef9SDimitry Andric return SendErrorResponse(Status("Process not running.")); 1322e8d8bef9SDimitry Andric 1323fe6060f1SDimitry Andric packet.ConsumeFront("jLLDBTraceStart:"); 1324fe6060f1SDimitry Andric Expected<TraceStartRequest> request = 1325fe6060f1SDimitry Andric json::parse<TraceStartRequest>(packet.Peek(), "TraceStartRequest"); 1326fe6060f1SDimitry Andric if (!request) 1327fe6060f1SDimitry Andric return SendErrorResponse(request.takeError()); 1328e8d8bef9SDimitry Andric 1329fe6060f1SDimitry Andric if (Error err = m_current_process->TraceStart(packet.Peek(), request->type)) 1330fe6060f1SDimitry Andric return SendErrorResponse(std::move(err)); 1331e8d8bef9SDimitry Andric 1332fe6060f1SDimitry Andric return SendOKResponse(); 1333e8d8bef9SDimitry Andric } 1334e8d8bef9SDimitry Andric 1335e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 1336fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState( 13370b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 13380b57cec5SDimitry Andric 13390b57cec5SDimitry Andric // Fail if we don't have a current process. 1340fe6060f1SDimitry Andric if (!m_current_process || 1341fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 1342fe6060f1SDimitry Andric return SendErrorResponse(Status("Process not running.")); 13430b57cec5SDimitry Andric 1344fe6060f1SDimitry Andric packet.ConsumeFront("jLLDBTraceGetState:"); 1345fe6060f1SDimitry Andric Expected<TraceGetStateRequest> request = 1346fe6060f1SDimitry Andric json::parse<TraceGetStateRequest>(packet.Peek(), "TraceGetStateRequest"); 1347fe6060f1SDimitry Andric if (!request) 1348fe6060f1SDimitry Andric return SendErrorResponse(request.takeError()); 13490b57cec5SDimitry Andric 1350fe6060f1SDimitry Andric return SendJSONResponse(m_current_process->TraceGetState(request->type)); 13510b57cec5SDimitry Andric } 13520b57cec5SDimitry Andric 13530b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 1354fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData( 13550b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 13560b57cec5SDimitry Andric 13570b57cec5SDimitry Andric // Fail if we don't have a current process. 1358fe6060f1SDimitry Andric if (!m_current_process || 1359fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 1360fe6060f1SDimitry Andric return SendErrorResponse(Status("Process not running.")); 13610b57cec5SDimitry Andric 1362fe6060f1SDimitry Andric packet.ConsumeFront("jLLDBTraceGetBinaryData:"); 1363fe6060f1SDimitry Andric llvm::Expected<TraceGetBinaryDataRequest> request = 1364fe6060f1SDimitry Andric llvm::json::parse<TraceGetBinaryDataRequest>(packet.Peek(), 1365fe6060f1SDimitry Andric "TraceGetBinaryDataRequest"); 1366fe6060f1SDimitry Andric if (!request) 1367fe6060f1SDimitry Andric return SendErrorResponse(Status(request.takeError())); 13680b57cec5SDimitry Andric 1369fe6060f1SDimitry Andric if (Expected<std::vector<uint8_t>> bytes = 1370fe6060f1SDimitry Andric m_current_process->TraceGetBinaryData(*request)) { 13710b57cec5SDimitry Andric StreamGDBRemote response; 1372fe6060f1SDimitry Andric response.PutEscapedBytes(bytes->data(), bytes->size()); 1373fe6060f1SDimitry Andric return SendPacketNoLock(response.GetString()); 1374fe6060f1SDimitry Andric } else 1375fe6060f1SDimitry Andric return SendErrorResponse(bytes.takeError()); 13760b57cec5SDimitry Andric } 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 13790b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( 13800b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 13810b57cec5SDimitry Andric // Fail if we don't have a current process. 1382fe6060f1SDimitry Andric if (!m_current_process || 1383fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 13840b57cec5SDimitry Andric return SendErrorResponse(68); 13850b57cec5SDimitry Andric 1386fe6060f1SDimitry Andric lldb::pid_t pid = m_current_process->GetID(); 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 13890b57cec5SDimitry Andric return SendErrorResponse(1); 13900b57cec5SDimitry Andric 13910b57cec5SDimitry Andric ProcessInstanceInfo proc_info; 13920b57cec5SDimitry Andric if (!Host::GetProcessInfo(pid, proc_info)) 13930b57cec5SDimitry Andric return SendErrorResponse(1); 13940b57cec5SDimitry Andric 13950b57cec5SDimitry Andric StreamString response; 13960b57cec5SDimitry Andric CreateProcessInfoResponse_DebugServerStyle(proc_info, response); 13970b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric 14000b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 14010b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) { 14020b57cec5SDimitry Andric // Fail if we don't have a current process. 1403fe6060f1SDimitry Andric if (!m_current_process || 1404fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 14050b57cec5SDimitry Andric return SendErrorResponse(68); 14060b57cec5SDimitry Andric 14070b57cec5SDimitry Andric // Make sure we set the current thread so g and p packets return the data the 14080b57cec5SDimitry Andric // gdb will expect. 1409fe6060f1SDimitry Andric lldb::tid_t tid = m_current_process->GetCurrentThreadID(); 14100b57cec5SDimitry Andric SetCurrentThreadID(tid); 14110b57cec5SDimitry Andric 1412fe6060f1SDimitry Andric NativeThreadProtocol *thread = m_current_process->GetCurrentThread(); 14130b57cec5SDimitry Andric if (!thread) 14140b57cec5SDimitry Andric return SendErrorResponse(69); 14150b57cec5SDimitry Andric 14160b57cec5SDimitry Andric StreamString response; 141781ad6265SDimitry Andric response.PutCString("QC"); 141881ad6265SDimitry Andric AppendThreadIDToResponse(response, m_current_process->GetID(), 141981ad6265SDimitry Andric thread->GetID()); 14200b57cec5SDimitry Andric 14210b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 14220b57cec5SDimitry Andric } 14230b57cec5SDimitry Andric 14240b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 14250b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { 142681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 14270b57cec5SDimitry Andric 1428fcaf7f86SDimitry Andric if (!m_non_stop) 14290b57cec5SDimitry Andric StopSTDIOForwarding(); 14300b57cec5SDimitry Andric 143181ad6265SDimitry Andric if (m_debugged_processes.empty()) { 14320b57cec5SDimitry Andric LLDB_LOG(log, "No debugged process found."); 14330b57cec5SDimitry Andric return PacketResult::Success; 14340b57cec5SDimitry Andric } 14350b57cec5SDimitry Andric 143681ad6265SDimitry Andric for (auto it = m_debugged_processes.begin(); it != m_debugged_processes.end(); 143781ad6265SDimitry Andric ++it) { 143881ad6265SDimitry Andric LLDB_LOG(log, "Killing process {0}", it->first); 1439fcaf7f86SDimitry Andric Status error = it->second.process_up->Kill(); 14400b57cec5SDimitry Andric if (error.Fail()) 144181ad6265SDimitry Andric LLDB_LOG(log, "Failed to kill debugged process {0}: {1}", it->first, 144281ad6265SDimitry Andric error); 144381ad6265SDimitry Andric } 14440b57cec5SDimitry Andric 144581ad6265SDimitry Andric // The response to kill packet is undefined per the spec. LLDB 144681ad6265SDimitry Andric // follows the same rules as for continue packets, i.e. no response 144781ad6265SDimitry Andric // in all-stop mode, and "OK" in non-stop mode; in both cases this 144881ad6265SDimitry Andric // is followed by the actual stop reason. 144981ad6265SDimitry Andric return SendContinueSuccessResponse(); 145081ad6265SDimitry Andric } 145181ad6265SDimitry Andric 145281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 145381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vKill( 145481ad6265SDimitry Andric StringExtractorGDBRemote &packet) { 1455fcaf7f86SDimitry Andric if (!m_non_stop) 145681ad6265SDimitry Andric StopSTDIOForwarding(); 145781ad6265SDimitry Andric 145881ad6265SDimitry Andric packet.SetFilePos(6); // vKill; 145981ad6265SDimitry Andric uint32_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); 146081ad6265SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 146181ad6265SDimitry Andric return SendIllFormedResponse(packet, 146281ad6265SDimitry Andric "vKill failed to parse the process id"); 146381ad6265SDimitry Andric 146481ad6265SDimitry Andric auto it = m_debugged_processes.find(pid); 146581ad6265SDimitry Andric if (it == m_debugged_processes.end()) 146681ad6265SDimitry Andric return SendErrorResponse(42); 146781ad6265SDimitry Andric 1468fcaf7f86SDimitry Andric Status error = it->second.process_up->Kill(); 146981ad6265SDimitry Andric if (error.Fail()) 147081ad6265SDimitry Andric return SendErrorResponse(error.ToError()); 147181ad6265SDimitry Andric 147281ad6265SDimitry Andric // OK response is sent when the process dies. 1473fcaf7f86SDimitry Andric it->second.flags |= DebuggedProcess::Flag::vkilled; 14740b57cec5SDimitry Andric return PacketResult::Success; 14750b57cec5SDimitry Andric } 14760b57cec5SDimitry Andric 14770b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 14780b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR( 14790b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 14800b57cec5SDimitry Andric packet.SetFilePos(::strlen("QSetDisableASLR:")); 14810b57cec5SDimitry Andric if (packet.GetU32(0)) 14820b57cec5SDimitry Andric m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR); 14830b57cec5SDimitry Andric else 14840b57cec5SDimitry Andric m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); 14850b57cec5SDimitry Andric return SendOKResponse(); 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric 14880b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 14890b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir( 14900b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 14910b57cec5SDimitry Andric packet.SetFilePos(::strlen("QSetWorkingDir:")); 14920b57cec5SDimitry Andric std::string path; 14930b57cec5SDimitry Andric packet.GetHexByteString(path); 14940b57cec5SDimitry Andric m_process_launch_info.SetWorkingDirectory(FileSpec(path)); 14950b57cec5SDimitry Andric return SendOKResponse(); 14960b57cec5SDimitry Andric } 14970b57cec5SDimitry Andric 14980b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 14990b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( 15000b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 15010b57cec5SDimitry Andric FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()}; 15020b57cec5SDimitry Andric if (working_dir) { 15030b57cec5SDimitry Andric StreamString response; 1504bdd1243dSDimitry Andric response.PutStringAsRawHex8(working_dir.GetPath().c_str()); 15050b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 15060b57cec5SDimitry Andric } 15070b57cec5SDimitry Andric 15080b57cec5SDimitry Andric return SendErrorResponse(14); 15090b57cec5SDimitry Andric } 15100b57cec5SDimitry Andric 15110b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 1512fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported( 1513fe6060f1SDimitry Andric StringExtractorGDBRemote &packet) { 1514fe6060f1SDimitry Andric m_thread_suffix_supported = true; 1515fe6060f1SDimitry Andric return SendOKResponse(); 1516fe6060f1SDimitry Andric } 1517fe6060f1SDimitry Andric 1518fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult 1519fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply( 1520fe6060f1SDimitry Andric StringExtractorGDBRemote &packet) { 1521fe6060f1SDimitry Andric m_list_threads_in_stop_reply = true; 1522fe6060f1SDimitry Andric return SendOKResponse(); 1523fe6060f1SDimitry Andric } 1524fe6060f1SDimitry Andric 1525fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult 1526fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::ResumeProcess( 1527fcaf7f86SDimitry Andric NativeProcessProtocol &process, const ResumeActionList &actions) { 1528fcaf7f86SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 1529fcaf7f86SDimitry Andric 1530fcaf7f86SDimitry Andric // In non-stop protocol mode, the process could be running already. 1531fcaf7f86SDimitry Andric // We do not support resuming threads independently, so just error out. 1532fcaf7f86SDimitry Andric if (!process.CanResume()) { 1533fcaf7f86SDimitry Andric LLDB_LOG(log, "process {0} cannot be resumed (state={1})", process.GetID(), 1534fcaf7f86SDimitry Andric process.GetState()); 1535fcaf7f86SDimitry Andric return SendErrorResponse(0x37); 1536fcaf7f86SDimitry Andric } 1537fcaf7f86SDimitry Andric 1538fcaf7f86SDimitry Andric Status error = process.Resume(actions); 1539fcaf7f86SDimitry Andric if (error.Fail()) { 1540fcaf7f86SDimitry Andric LLDB_LOG(log, "process {0} failed to resume: {1}", process.GetID(), error); 1541fcaf7f86SDimitry Andric return SendErrorResponse(GDBRemoteServerError::eErrorResume); 1542fcaf7f86SDimitry Andric } 1543fcaf7f86SDimitry Andric 1544fcaf7f86SDimitry Andric LLDB_LOG(log, "process {0} resumed", process.GetID()); 1545fcaf7f86SDimitry Andric 1546fcaf7f86SDimitry Andric return PacketResult::Success; 1547fcaf7f86SDimitry Andric } 1548fcaf7f86SDimitry Andric 1549fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult 15500b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { 155181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 15529dba64beSDimitry Andric LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); 15530b57cec5SDimitry Andric 15540b57cec5SDimitry Andric // Ensure we have a native process. 1555fe6060f1SDimitry Andric if (!m_continue_process) { 15569dba64beSDimitry Andric LLDB_LOGF(log, 15579dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s no debugged process " 15580b57cec5SDimitry Andric "shared pointer", 15590b57cec5SDimitry Andric __FUNCTION__); 15600b57cec5SDimitry Andric return SendErrorResponse(0x36); 15610b57cec5SDimitry Andric } 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric // Pull out the signal number. 15640b57cec5SDimitry Andric packet.SetFilePos(::strlen("C")); 15650b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) { 15660b57cec5SDimitry Andric // Shouldn't be using a C without a signal. 15670b57cec5SDimitry Andric return SendIllFormedResponse(packet, "C packet specified without signal."); 15680b57cec5SDimitry Andric } 15690b57cec5SDimitry Andric const uint32_t signo = 15700b57cec5SDimitry Andric packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); 15710b57cec5SDimitry Andric if (signo == std::numeric_limits<uint32_t>::max()) 15720b57cec5SDimitry Andric return SendIllFormedResponse(packet, "failed to parse signal number"); 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andric // Handle optional continue address. 15750b57cec5SDimitry Andric if (packet.GetBytesLeft() > 0) { 15760b57cec5SDimitry Andric // FIXME add continue at address support for $C{signo}[;{continue-address}]. 15770b57cec5SDimitry Andric if (*packet.Peek() == ';') 15789dba64beSDimitry Andric return SendUnimplementedResponse(packet.GetStringRef().data()); 15790b57cec5SDimitry Andric else 15800b57cec5SDimitry Andric return SendIllFormedResponse( 15810b57cec5SDimitry Andric packet, "unexpected content after $C{signal-number}"); 15820b57cec5SDimitry Andric } 15830b57cec5SDimitry Andric 1584fcaf7f86SDimitry Andric // In non-stop protocol mode, the process could be running already. 1585fcaf7f86SDimitry Andric // We do not support resuming threads independently, so just error out. 1586fcaf7f86SDimitry Andric if (!m_continue_process->CanResume()) { 1587fcaf7f86SDimitry Andric LLDB_LOG(log, "process cannot be resumed (state={0})", 1588fcaf7f86SDimitry Andric m_continue_process->GetState()); 1589fcaf7f86SDimitry Andric return SendErrorResponse(0x37); 1590fcaf7f86SDimitry Andric } 1591fcaf7f86SDimitry Andric 15929dba64beSDimitry Andric ResumeActionList resume_actions(StateType::eStateRunning, 15939dba64beSDimitry Andric LLDB_INVALID_SIGNAL_NUMBER); 15940b57cec5SDimitry Andric Status error; 15950b57cec5SDimitry Andric 15960b57cec5SDimitry Andric // We have two branches: what to do if a continue thread is specified (in 15970b57cec5SDimitry Andric // which case we target sending the signal to that thread), or when we don't 15980b57cec5SDimitry Andric // have a continue thread set (in which case we send a signal to the 15990b57cec5SDimitry Andric // process). 16000b57cec5SDimitry Andric 16010b57cec5SDimitry Andric // TODO discuss with Greg Clayton, make sure this makes sense. 16020b57cec5SDimitry Andric 16030b57cec5SDimitry Andric lldb::tid_t signal_tid = GetContinueThreadID(); 16040b57cec5SDimitry Andric if (signal_tid != LLDB_INVALID_THREAD_ID) { 16050b57cec5SDimitry Andric // The resume action for the continue thread (or all threads if a continue 16060b57cec5SDimitry Andric // thread is not set). 16070b57cec5SDimitry Andric ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning, 16080b57cec5SDimitry Andric static_cast<int>(signo)}; 16090b57cec5SDimitry Andric 16100b57cec5SDimitry Andric // Add the action for the continue thread (or all threads when the continue 16110b57cec5SDimitry Andric // thread isn't present). 16120b57cec5SDimitry Andric resume_actions.Append(action); 16130b57cec5SDimitry Andric } else { 16140b57cec5SDimitry Andric // Send the signal to the process since we weren't targeting a specific 16150b57cec5SDimitry Andric // continue thread with the signal. 1616fe6060f1SDimitry Andric error = m_continue_process->Signal(signo); 16170b57cec5SDimitry Andric if (error.Fail()) { 16180b57cec5SDimitry Andric LLDB_LOG(log, "failed to send signal for process {0}: {1}", 1619fe6060f1SDimitry Andric m_continue_process->GetID(), error); 16200b57cec5SDimitry Andric 16210b57cec5SDimitry Andric return SendErrorResponse(0x52); 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric } 16240b57cec5SDimitry Andric 1625fcaf7f86SDimitry Andric // NB: this checks CanResume() twice but using a single code path for 1626fcaf7f86SDimitry Andric // resuming still seems worth it. 1627fcaf7f86SDimitry Andric PacketResult resume_res = ResumeProcess(*m_continue_process, resume_actions); 1628fcaf7f86SDimitry Andric if (resume_res != PacketResult::Success) 1629fcaf7f86SDimitry Andric return resume_res; 16300b57cec5SDimitry Andric 163181ad6265SDimitry Andric // Don't send an "OK" packet, except in non-stop mode; 163281ad6265SDimitry Andric // otherwise, the response is the stopped/exited message. 163381ad6265SDimitry Andric return SendContinueSuccessResponse(); 16340b57cec5SDimitry Andric } 16350b57cec5SDimitry Andric 16360b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 16370b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { 163881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 16399dba64beSDimitry Andric LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric packet.SetFilePos(packet.GetFilePos() + ::strlen("c")); 16420b57cec5SDimitry Andric 16430b57cec5SDimitry Andric // For now just support all continue. 16440b57cec5SDimitry Andric const bool has_continue_address = (packet.GetBytesLeft() > 0); 16450b57cec5SDimitry Andric if (has_continue_address) { 16460b57cec5SDimitry Andric LLDB_LOG(log, "not implemented for c[address] variant [{0} remains]", 16470b57cec5SDimitry Andric packet.Peek()); 16489dba64beSDimitry Andric return SendUnimplementedResponse(packet.GetStringRef().data()); 16490b57cec5SDimitry Andric } 16500b57cec5SDimitry Andric 16510b57cec5SDimitry Andric // Ensure we have a native process. 1652fe6060f1SDimitry Andric if (!m_continue_process) { 16539dba64beSDimitry Andric LLDB_LOGF(log, 16549dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s no debugged process " 16550b57cec5SDimitry Andric "shared pointer", 16560b57cec5SDimitry Andric __FUNCTION__); 16570b57cec5SDimitry Andric return SendErrorResponse(0x36); 16580b57cec5SDimitry Andric } 16590b57cec5SDimitry Andric 16600b57cec5SDimitry Andric // Build the ResumeActionList 16619dba64beSDimitry Andric ResumeActionList actions(StateType::eStateRunning, 16629dba64beSDimitry Andric LLDB_INVALID_SIGNAL_NUMBER); 16630b57cec5SDimitry Andric 1664fcaf7f86SDimitry Andric PacketResult resume_res = ResumeProcess(*m_continue_process, actions); 1665fcaf7f86SDimitry Andric if (resume_res != PacketResult::Success) 1666fcaf7f86SDimitry Andric return resume_res; 166781ad6265SDimitry Andric 166881ad6265SDimitry Andric return SendContinueSuccessResponse(); 16690b57cec5SDimitry Andric } 16700b57cec5SDimitry Andric 16710b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 16720b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCont_actions( 16730b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 16740b57cec5SDimitry Andric StreamString response; 167581ad6265SDimitry Andric response.Printf("vCont;c;C;s;S;t"); 16760b57cec5SDimitry Andric 16770b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 16780b57cec5SDimitry Andric } 16790b57cec5SDimitry Andric 1680fcaf7f86SDimitry Andric static bool ResumeActionListStopsAllThreads(ResumeActionList &actions) { 1681fcaf7f86SDimitry Andric // We're doing a stop-all if and only if our only action is a "t" for all 1682fcaf7f86SDimitry Andric // threads. 1683fcaf7f86SDimitry Andric if (const ResumeAction *default_action = 1684fcaf7f86SDimitry Andric actions.GetActionForThread(LLDB_INVALID_THREAD_ID, false)) { 1685fcaf7f86SDimitry Andric if (default_action->state == eStateSuspended && actions.GetSize() == 1) 1686fcaf7f86SDimitry Andric return true; 1687fcaf7f86SDimitry Andric } 1688fcaf7f86SDimitry Andric 1689fcaf7f86SDimitry Andric return false; 1690fcaf7f86SDimitry Andric } 1691fcaf7f86SDimitry Andric 16920b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 16930b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCont( 16940b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 169581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 16969dba64beSDimitry Andric LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s handling vCont packet", 16970b57cec5SDimitry Andric __FUNCTION__); 16980b57cec5SDimitry Andric 16990b57cec5SDimitry Andric packet.SetFilePos(::strlen("vCont")); 17000b57cec5SDimitry Andric 17010b57cec5SDimitry Andric if (packet.GetBytesLeft() == 0) { 17029dba64beSDimitry Andric LLDB_LOGF(log, 17039dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s missing action from " 17040b57cec5SDimitry Andric "vCont package", 17050b57cec5SDimitry Andric __FUNCTION__); 17060b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Missing action from vCont package"); 17070b57cec5SDimitry Andric } 17080b57cec5SDimitry Andric 170981ad6265SDimitry Andric if (::strcmp(packet.Peek(), ";s") == 0) { 17100b57cec5SDimitry Andric // Move past the ';', then do a simple 's'. 17110b57cec5SDimitry Andric packet.SetFilePos(packet.GetFilePos() + 1); 17120b57cec5SDimitry Andric return Handle_s(packet); 17130b57cec5SDimitry Andric } 17140b57cec5SDimitry Andric 171581ad6265SDimitry Andric std::unordered_map<lldb::pid_t, ResumeActionList> thread_actions; 17160b57cec5SDimitry Andric 17170b57cec5SDimitry Andric while (packet.GetBytesLeft() && *packet.Peek() == ';') { 17180b57cec5SDimitry Andric // Skip the semi-colon. 17190b57cec5SDimitry Andric packet.GetChar(); 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric // Build up the thread action. 17220b57cec5SDimitry Andric ResumeAction thread_action; 17230b57cec5SDimitry Andric thread_action.tid = LLDB_INVALID_THREAD_ID; 17240b57cec5SDimitry Andric thread_action.state = eStateInvalid; 17259dba64beSDimitry Andric thread_action.signal = LLDB_INVALID_SIGNAL_NUMBER; 17260b57cec5SDimitry Andric 17270b57cec5SDimitry Andric const char action = packet.GetChar(); 17280b57cec5SDimitry Andric switch (action) { 17290b57cec5SDimitry Andric case 'C': 17300b57cec5SDimitry Andric thread_action.signal = packet.GetHexMaxU32(false, 0); 17310b57cec5SDimitry Andric if (thread_action.signal == 0) 17320b57cec5SDimitry Andric return SendIllFormedResponse( 17330b57cec5SDimitry Andric packet, "Could not parse signal in vCont packet C action"); 1734bdd1243dSDimitry Andric [[fallthrough]]; 17350b57cec5SDimitry Andric 17360b57cec5SDimitry Andric case 'c': 17370b57cec5SDimitry Andric // Continue 17380b57cec5SDimitry Andric thread_action.state = eStateRunning; 17390b57cec5SDimitry Andric break; 17400b57cec5SDimitry Andric 17410b57cec5SDimitry Andric case 'S': 17420b57cec5SDimitry Andric thread_action.signal = packet.GetHexMaxU32(false, 0); 17430b57cec5SDimitry Andric if (thread_action.signal == 0) 17440b57cec5SDimitry Andric return SendIllFormedResponse( 17450b57cec5SDimitry Andric packet, "Could not parse signal in vCont packet S action"); 1746bdd1243dSDimitry Andric [[fallthrough]]; 17470b57cec5SDimitry Andric 17480b57cec5SDimitry Andric case 's': 17490b57cec5SDimitry Andric // Step 17500b57cec5SDimitry Andric thread_action.state = eStateStepping; 17510b57cec5SDimitry Andric break; 17520b57cec5SDimitry Andric 175381ad6265SDimitry Andric case 't': 175481ad6265SDimitry Andric // Stop 175581ad6265SDimitry Andric thread_action.state = eStateSuspended; 175681ad6265SDimitry Andric break; 175781ad6265SDimitry Andric 17580b57cec5SDimitry Andric default: 17590b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Unsupported vCont action"); 17600b57cec5SDimitry Andric break; 17610b57cec5SDimitry Andric } 17620b57cec5SDimitry Andric 1763bdd1243dSDimitry Andric // If there's no thread-id (e.g. "vCont;c"), it's "p-1.-1". 176481ad6265SDimitry Andric lldb::pid_t pid = StringExtractorGDBRemote::AllProcesses; 176581ad6265SDimitry Andric lldb::tid_t tid = StringExtractorGDBRemote::AllThreads; 176681ad6265SDimitry Andric 17670b57cec5SDimitry Andric // Parse out optional :{thread-id} value. 17680b57cec5SDimitry Andric if (packet.GetBytesLeft() && (*packet.Peek() == ':')) { 17690b57cec5SDimitry Andric // Consume the separator. 17700b57cec5SDimitry Andric packet.GetChar(); 17710b57cec5SDimitry Andric 1772bdd1243dSDimitry Andric auto pid_tid = packet.GetPidTid(LLDB_INVALID_PROCESS_ID); 177381ad6265SDimitry Andric if (!pid_tid) 177481ad6265SDimitry Andric return SendIllFormedResponse(packet, "Malformed thread-id"); 1775fe6060f1SDimitry Andric 177681ad6265SDimitry Andric pid = pid_tid->first; 177781ad6265SDimitry Andric tid = pid_tid->second; 17780b57cec5SDimitry Andric } 17790b57cec5SDimitry Andric 1780fcaf7f86SDimitry Andric if (thread_action.state == eStateSuspended && 1781fcaf7f86SDimitry Andric tid != StringExtractorGDBRemote::AllThreads) { 1782fcaf7f86SDimitry Andric return SendIllFormedResponse( 1783fcaf7f86SDimitry Andric packet, "'t' action not supported for individual threads"); 1784fcaf7f86SDimitry Andric } 1785fcaf7f86SDimitry Andric 1786bdd1243dSDimitry Andric // If we get TID without PID, it's the current process. 1787bdd1243dSDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) { 178881ad6265SDimitry Andric if (!m_continue_process) { 1789bdd1243dSDimitry Andric LLDB_LOG(log, "no process selected via Hc"); 179081ad6265SDimitry Andric return SendErrorResponse(0x36); 179181ad6265SDimitry Andric } 179281ad6265SDimitry Andric pid = m_continue_process->GetID(); 17930b57cec5SDimitry Andric } 17940b57cec5SDimitry Andric 1795bdd1243dSDimitry Andric assert(pid != LLDB_INVALID_PROCESS_ID); 179681ad6265SDimitry Andric if (tid == StringExtractorGDBRemote::AllThreads) 179781ad6265SDimitry Andric tid = LLDB_INVALID_THREAD_ID; 179881ad6265SDimitry Andric thread_action.tid = tid; 179981ad6265SDimitry Andric 1800bdd1243dSDimitry Andric if (pid == StringExtractorGDBRemote::AllProcesses) { 1801bdd1243dSDimitry Andric if (tid != LLDB_INVALID_THREAD_ID) 1802bdd1243dSDimitry Andric return SendIllFormedResponse( 1803bdd1243dSDimitry Andric packet, "vCont: p-1 is not valid with a specific tid"); 1804bdd1243dSDimitry Andric for (auto &process_it : m_debugged_processes) 1805bdd1243dSDimitry Andric thread_actions[process_it.first].Append(thread_action); 1806bdd1243dSDimitry Andric } else 180781ad6265SDimitry Andric thread_actions[pid].Append(thread_action); 180881ad6265SDimitry Andric } 180981ad6265SDimitry Andric 181081ad6265SDimitry Andric assert(thread_actions.size() >= 1); 1811bdd1243dSDimitry Andric if (thread_actions.size() > 1 && !m_non_stop) 181281ad6265SDimitry Andric return SendIllFormedResponse( 1813bdd1243dSDimitry Andric packet, 1814bdd1243dSDimitry Andric "Resuming multiple processes is supported in non-stop mode only"); 181581ad6265SDimitry Andric 181681ad6265SDimitry Andric for (std::pair<lldb::pid_t, ResumeActionList> x : thread_actions) { 181781ad6265SDimitry Andric auto process_it = m_debugged_processes.find(x.first); 181881ad6265SDimitry Andric if (process_it == m_debugged_processes.end()) { 181981ad6265SDimitry Andric LLDB_LOG(log, "vCont failed for process {0}: process not debugged", 182081ad6265SDimitry Andric x.first); 18210b57cec5SDimitry Andric return SendErrorResponse(GDBRemoteServerError::eErrorResume); 18220b57cec5SDimitry Andric } 18230b57cec5SDimitry Andric 1824fcaf7f86SDimitry Andric // There are four possible scenarios here. These are: 1825fcaf7f86SDimitry Andric // 1. vCont on a stopped process that resumes at least one thread. 1826fcaf7f86SDimitry Andric // In this case, we call Resume(). 1827fcaf7f86SDimitry Andric // 2. vCont on a stopped process that leaves all threads suspended. 1828fcaf7f86SDimitry Andric // A no-op. 1829fcaf7f86SDimitry Andric // 3. vCont on a running process that requests suspending all 1830fcaf7f86SDimitry Andric // running threads. In this case, we call Interrupt(). 1831fcaf7f86SDimitry Andric // 4. vCont on a running process that requests suspending a subset 1832fcaf7f86SDimitry Andric // of running threads or resuming a subset of suspended threads. 1833fcaf7f86SDimitry Andric // Since we do not support full nonstop mode, this is unsupported 1834fcaf7f86SDimitry Andric // and we return an error. 1835fcaf7f86SDimitry Andric 1836fcaf7f86SDimitry Andric assert(process_it->second.process_up); 1837fcaf7f86SDimitry Andric if (ResumeActionListStopsAllThreads(x.second)) { 1838fcaf7f86SDimitry Andric if (process_it->second.process_up->IsRunning()) { 1839fcaf7f86SDimitry Andric assert(m_non_stop); 1840fcaf7f86SDimitry Andric 1841fcaf7f86SDimitry Andric Status error = process_it->second.process_up->Interrupt(); 184281ad6265SDimitry Andric if (error.Fail()) { 1843fcaf7f86SDimitry Andric LLDB_LOG(log, "vCont failed to halt process {0}: {1}", x.first, 1844fcaf7f86SDimitry Andric error); 184581ad6265SDimitry Andric return SendErrorResponse(GDBRemoteServerError::eErrorResume); 184681ad6265SDimitry Andric } 184781ad6265SDimitry Andric 1848fcaf7f86SDimitry Andric LLDB_LOG(log, "halted process {0}", x.first); 1849fcaf7f86SDimitry Andric 1850fcaf7f86SDimitry Andric // hack to avoid enabling stdio forwarding after stop 1851fcaf7f86SDimitry Andric // TODO: remove this when we improve stdio forwarding for nonstop 1852fcaf7f86SDimitry Andric assert(thread_actions.size() == 1); 1853fcaf7f86SDimitry Andric return SendOKResponse(); 1854fcaf7f86SDimitry Andric } 1855fcaf7f86SDimitry Andric } else { 1856fcaf7f86SDimitry Andric PacketResult resume_res = 1857fcaf7f86SDimitry Andric ResumeProcess(*process_it->second.process_up, x.second); 1858fcaf7f86SDimitry Andric if (resume_res != PacketResult::Success) 1859fcaf7f86SDimitry Andric return resume_res; 1860fcaf7f86SDimitry Andric } 186181ad6265SDimitry Andric } 186281ad6265SDimitry Andric 186381ad6265SDimitry Andric return SendContinueSuccessResponse(); 18640b57cec5SDimitry Andric } 18650b57cec5SDimitry Andric 18660b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) { 186781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 18680b57cec5SDimitry Andric LLDB_LOG(log, "setting current thread id to {0}", tid); 18690b57cec5SDimitry Andric 18700b57cec5SDimitry Andric m_current_tid = tid; 1871fe6060f1SDimitry Andric if (m_current_process) 1872fe6060f1SDimitry Andric m_current_process->SetCurrentThreadID(m_current_tid); 18730b57cec5SDimitry Andric } 18740b57cec5SDimitry Andric 18750b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) { 187681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 18770b57cec5SDimitry Andric LLDB_LOG(log, "setting continue thread id to {0}", tid); 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric m_continue_tid = tid; 18800b57cec5SDimitry Andric } 18810b57cec5SDimitry Andric 18820b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 18830b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_stop_reason( 18840b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 18850b57cec5SDimitry Andric // Handle the $? gdbremote command. 18860b57cec5SDimitry Andric 188781ad6265SDimitry Andric if (m_non_stop) { 188881ad6265SDimitry Andric // Clear the notification queue first, except for pending exit 188981ad6265SDimitry Andric // notifications. 189081ad6265SDimitry Andric llvm::erase_if(m_stop_notification_queue, [](const std::string &x) { 189181ad6265SDimitry Andric return x.front() != 'W' && x.front() != 'X'; 189281ad6265SDimitry Andric }); 189381ad6265SDimitry Andric 189481ad6265SDimitry Andric if (m_current_process) { 189581ad6265SDimitry Andric // Queue stop reply packets for all active threads. Start with 189681ad6265SDimitry Andric // the current thread (for clients that don't actually support multiple 189781ad6265SDimitry Andric // stop reasons). 189881ad6265SDimitry Andric NativeThreadProtocol *thread = m_current_process->GetCurrentThread(); 1899fcaf7f86SDimitry Andric if (thread) { 1900fcaf7f86SDimitry Andric StreamString stop_reply = PrepareStopReplyPacketForThread(*thread); 1901fcaf7f86SDimitry Andric if (!stop_reply.Empty()) 1902fcaf7f86SDimitry Andric m_stop_notification_queue.push_back(stop_reply.GetString().str()); 1903fcaf7f86SDimitry Andric } 190481ad6265SDimitry Andric EnqueueStopReplyPackets(thread ? thread->GetID() 190581ad6265SDimitry Andric : LLDB_INVALID_THREAD_ID); 190681ad6265SDimitry Andric } 190781ad6265SDimitry Andric 190881ad6265SDimitry Andric // If the notification queue is empty (i.e. everything is running), send OK. 190981ad6265SDimitry Andric if (m_stop_notification_queue.empty()) 191081ad6265SDimitry Andric return SendOKResponse(); 191181ad6265SDimitry Andric 191281ad6265SDimitry Andric // Send the first item from the new notification queue synchronously. 191381ad6265SDimitry Andric return SendPacketNoLock(m_stop_notification_queue.front()); 191481ad6265SDimitry Andric } 191581ad6265SDimitry Andric 19160b57cec5SDimitry Andric // If no process, indicate error 1917fe6060f1SDimitry Andric if (!m_current_process) 19180b57cec5SDimitry Andric return SendErrorResponse(02); 19190b57cec5SDimitry Andric 192081ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 192181ad6265SDimitry Andric m_current_process->GetState(), 192281ad6265SDimitry Andric /*force_synchronous=*/true); 19230b57cec5SDimitry Andric } 19240b57cec5SDimitry Andric 19250b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 19260b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendStopReasonForState( 192781ad6265SDimitry Andric NativeProcessProtocol &process, lldb::StateType process_state, 192881ad6265SDimitry Andric bool force_synchronous) { 192981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 19300b57cec5SDimitry Andric 1931fcaf7f86SDimitry Andric if (m_disabling_non_stop) { 1932fcaf7f86SDimitry Andric // Check if we are waiting for any more processes to stop. If we are, 1933fcaf7f86SDimitry Andric // do not send the OK response yet. 1934fcaf7f86SDimitry Andric for (const auto &it : m_debugged_processes) { 1935fcaf7f86SDimitry Andric if (it.second.process_up->IsRunning()) 1936fcaf7f86SDimitry Andric return PacketResult::Success; 1937fcaf7f86SDimitry Andric } 1938fcaf7f86SDimitry Andric 1939fcaf7f86SDimitry Andric // If all expected processes were stopped after a QNonStop:0 request, 1940fcaf7f86SDimitry Andric // send the OK response. 1941fcaf7f86SDimitry Andric m_disabling_non_stop = false; 1942fcaf7f86SDimitry Andric return SendOKResponse(); 1943fcaf7f86SDimitry Andric } 1944fcaf7f86SDimitry Andric 19450b57cec5SDimitry Andric switch (process_state) { 19460b57cec5SDimitry Andric case eStateAttaching: 19470b57cec5SDimitry Andric case eStateLaunching: 19480b57cec5SDimitry Andric case eStateRunning: 19490b57cec5SDimitry Andric case eStateStepping: 19500b57cec5SDimitry Andric case eStateDetached: 19510b57cec5SDimitry Andric // NOTE: gdb protocol doc looks like it should return $OK 19520b57cec5SDimitry Andric // when everything is running (i.e. no stopped result). 19530b57cec5SDimitry Andric return PacketResult::Success; // Ignore 19540b57cec5SDimitry Andric 19550b57cec5SDimitry Andric case eStateSuspended: 19560b57cec5SDimitry Andric case eStateStopped: 19570b57cec5SDimitry Andric case eStateCrashed: { 195881ad6265SDimitry Andric lldb::tid_t tid = process.GetCurrentThreadID(); 19590b57cec5SDimitry Andric // Make sure we set the current thread so g and p packets return the data 19600b57cec5SDimitry Andric // the gdb will expect. 19610b57cec5SDimitry Andric SetCurrentThreadID(tid); 196281ad6265SDimitry Andric return SendStopReplyPacketForThread(process, tid, force_synchronous); 19630b57cec5SDimitry Andric } 19640b57cec5SDimitry Andric 19650b57cec5SDimitry Andric case eStateInvalid: 19660b57cec5SDimitry Andric case eStateUnloaded: 19670b57cec5SDimitry Andric case eStateExited: 196881ad6265SDimitry Andric return SendWResponse(&process); 19690b57cec5SDimitry Andric 19700b57cec5SDimitry Andric default: 19710b57cec5SDimitry Andric LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}", 197281ad6265SDimitry Andric process.GetID(), process_state); 19730b57cec5SDimitry Andric break; 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric 19760b57cec5SDimitry Andric return SendErrorResponse(0); 19770b57cec5SDimitry Andric } 19780b57cec5SDimitry Andric 19790b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 19800b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( 19810b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 19820b57cec5SDimitry Andric // Fail if we don't have a current process. 1983fe6060f1SDimitry Andric if (!m_current_process || 1984fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 19850b57cec5SDimitry Andric return SendErrorResponse(68); 19860b57cec5SDimitry Andric 19870b57cec5SDimitry Andric // Ensure we have a thread. 1988fe6060f1SDimitry Andric NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0); 19890b57cec5SDimitry Andric if (!thread) 19900b57cec5SDimitry Andric return SendErrorResponse(69); 19910b57cec5SDimitry Andric 19920b57cec5SDimitry Andric // Get the register context for the first thread. 19930b57cec5SDimitry Andric NativeRegisterContext ®_context = thread->GetRegisterContext(); 19940b57cec5SDimitry Andric 19950b57cec5SDimitry Andric // Parse out the register number from the request. 19960b57cec5SDimitry Andric packet.SetFilePos(strlen("qRegisterInfo")); 19970b57cec5SDimitry Andric const uint32_t reg_index = 19980b57cec5SDimitry Andric packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); 19990b57cec5SDimitry Andric if (reg_index == std::numeric_limits<uint32_t>::max()) 20000b57cec5SDimitry Andric return SendErrorResponse(69); 20010b57cec5SDimitry Andric 20020b57cec5SDimitry Andric // Return the end of registers response if we've iterated one past the end of 20030b57cec5SDimitry Andric // the register set. 20040b57cec5SDimitry Andric if (reg_index >= reg_context.GetUserRegisterCount()) 20050b57cec5SDimitry Andric return SendErrorResponse(69); 20060b57cec5SDimitry Andric 20070b57cec5SDimitry Andric const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); 20080b57cec5SDimitry Andric if (!reg_info) 20090b57cec5SDimitry Andric return SendErrorResponse(69); 20100b57cec5SDimitry Andric 20110b57cec5SDimitry Andric // Build the reginfos response. 20120b57cec5SDimitry Andric StreamGDBRemote response; 20130b57cec5SDimitry Andric 20140b57cec5SDimitry Andric response.PutCString("name:"); 20150b57cec5SDimitry Andric response.PutCString(reg_info->name); 20160b57cec5SDimitry Andric response.PutChar(';'); 20170b57cec5SDimitry Andric 20180b57cec5SDimitry Andric if (reg_info->alt_name && reg_info->alt_name[0]) { 20190b57cec5SDimitry Andric response.PutCString("alt-name:"); 20200b57cec5SDimitry Andric response.PutCString(reg_info->alt_name); 20210b57cec5SDimitry Andric response.PutChar(';'); 20220b57cec5SDimitry Andric } 20230b57cec5SDimitry Andric 2024e8d8bef9SDimitry Andric response.Printf("bitsize:%" PRIu32 ";", reg_info->byte_size * 8); 2025e8d8bef9SDimitry Andric 2026e8d8bef9SDimitry Andric if (!reg_context.RegisterOffsetIsDynamic()) 2027e8d8bef9SDimitry Andric response.Printf("offset:%" PRIu32 ";", reg_info->byte_offset); 20280b57cec5SDimitry Andric 20295ffd83dbSDimitry Andric llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info); 20305ffd83dbSDimitry Andric if (!encoding.empty()) 20315ffd83dbSDimitry Andric response << "encoding:" << encoding << ';'; 20320b57cec5SDimitry Andric 20335ffd83dbSDimitry Andric llvm::StringRef format = GetFormatNameOrEmpty(*reg_info); 20345ffd83dbSDimitry Andric if (!format.empty()) 20355ffd83dbSDimitry Andric response << "format:" << format << ';'; 20360b57cec5SDimitry Andric 20370b57cec5SDimitry Andric const char *const register_set_name = 20380b57cec5SDimitry Andric reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); 20395ffd83dbSDimitry Andric if (register_set_name) 20405ffd83dbSDimitry Andric response << "set:" << register_set_name << ';'; 20410b57cec5SDimitry Andric 20420b57cec5SDimitry Andric if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != 20430b57cec5SDimitry Andric LLDB_INVALID_REGNUM) 20440b57cec5SDimitry Andric response.Printf("ehframe:%" PRIu32 ";", 20450b57cec5SDimitry Andric reg_info->kinds[RegisterKind::eRegisterKindEHFrame]); 20460b57cec5SDimitry Andric 20470b57cec5SDimitry Andric if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM) 20480b57cec5SDimitry Andric response.Printf("dwarf:%" PRIu32 ";", 20490b57cec5SDimitry Andric reg_info->kinds[RegisterKind::eRegisterKindDWARF]); 20500b57cec5SDimitry Andric 20515ffd83dbSDimitry Andric llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info); 20525ffd83dbSDimitry Andric if (!kind_generic.empty()) 20535ffd83dbSDimitry Andric response << "generic:" << kind_generic << ';'; 20540b57cec5SDimitry Andric 20550b57cec5SDimitry Andric if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) { 20560b57cec5SDimitry Andric response.PutCString("container-regs:"); 20575ffd83dbSDimitry Andric CollectRegNums(reg_info->value_regs, response, true); 20580b57cec5SDimitry Andric response.PutChar(';'); 20590b57cec5SDimitry Andric } 20600b57cec5SDimitry Andric 20610b57cec5SDimitry Andric if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) { 20620b57cec5SDimitry Andric response.PutCString("invalidate-regs:"); 20635ffd83dbSDimitry Andric CollectRegNums(reg_info->invalidate_regs, response, true); 20640b57cec5SDimitry Andric response.PutChar(';'); 20650b57cec5SDimitry Andric } 20660b57cec5SDimitry Andric 20670b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 20680b57cec5SDimitry Andric } 20690b57cec5SDimitry Andric 207081ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::AddProcessThreads( 207181ad6265SDimitry Andric StreamGDBRemote &response, NativeProcessProtocol &process, bool &had_any) { 207281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 207381ad6265SDimitry Andric 207481ad6265SDimitry Andric lldb::pid_t pid = process.GetID(); 207581ad6265SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 207681ad6265SDimitry Andric return; 207781ad6265SDimitry Andric 207881ad6265SDimitry Andric LLDB_LOG(log, "iterating over threads of process {0}", process.GetID()); 207981ad6265SDimitry Andric for (NativeThreadProtocol &thread : process.Threads()) { 208081ad6265SDimitry Andric LLDB_LOG(log, "iterated thread tid={0}", thread.GetID()); 208181ad6265SDimitry Andric response.PutChar(had_any ? ',' : 'm'); 208281ad6265SDimitry Andric AppendThreadIDToResponse(response, pid, thread.GetID()); 208381ad6265SDimitry Andric had_any = true; 208481ad6265SDimitry Andric } 208581ad6265SDimitry Andric } 208681ad6265SDimitry Andric 20870b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 20880b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( 20890b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 209081ad6265SDimitry Andric assert(m_debugged_processes.size() == 1 || 209181ad6265SDimitry Andric bool(m_extensions_supported & 209281ad6265SDimitry Andric NativeProcessProtocol::Extension::multiprocess)); 20930b57cec5SDimitry Andric 209481ad6265SDimitry Andric bool had_any = false; 20950b57cec5SDimitry Andric StreamGDBRemote response; 20960b57cec5SDimitry Andric 209781ad6265SDimitry Andric for (auto &pid_ptr : m_debugged_processes) 2098fcaf7f86SDimitry Andric AddProcessThreads(response, *pid_ptr.second.process_up, had_any); 20990b57cec5SDimitry Andric 210081ad6265SDimitry Andric if (!had_any) 210181ad6265SDimitry Andric return SendOKResponse(); 21020b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 21030b57cec5SDimitry Andric } 21040b57cec5SDimitry Andric 21050b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 21060b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo( 21070b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 21080b57cec5SDimitry Andric // FIXME for now we return the full thread list in the initial packet and 21090b57cec5SDimitry Andric // always do nothing here. 21100b57cec5SDimitry Andric return SendPacketNoLock("l"); 21110b57cec5SDimitry Andric } 21120b57cec5SDimitry Andric 21130b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 21140b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) { 211581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 21160b57cec5SDimitry Andric 21170b57cec5SDimitry Andric // Move past packet name. 21180b57cec5SDimitry Andric packet.SetFilePos(strlen("g")); 21190b57cec5SDimitry Andric 21200b57cec5SDimitry Andric // Get the thread to use. 21210b57cec5SDimitry Andric NativeThreadProtocol *thread = GetThreadFromSuffix(packet); 21220b57cec5SDimitry Andric if (!thread) { 21230b57cec5SDimitry Andric LLDB_LOG(log, "failed, no thread available"); 21240b57cec5SDimitry Andric return SendErrorResponse(0x15); 21250b57cec5SDimitry Andric } 21260b57cec5SDimitry Andric 21270b57cec5SDimitry Andric // Get the thread's register context. 21280b57cec5SDimitry Andric NativeRegisterContext ®_ctx = thread->GetRegisterContext(); 21290b57cec5SDimitry Andric 21300b57cec5SDimitry Andric std::vector<uint8_t> regs_buffer; 21310b57cec5SDimitry Andric for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount(); 21320b57cec5SDimitry Andric ++reg_num) { 21330b57cec5SDimitry Andric const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num); 21340b57cec5SDimitry Andric 21350b57cec5SDimitry Andric if (reg_info == nullptr) { 21360b57cec5SDimitry Andric LLDB_LOG(log, "failed to get register info for register index {0}", 21370b57cec5SDimitry Andric reg_num); 21380b57cec5SDimitry Andric return SendErrorResponse(0x15); 21390b57cec5SDimitry Andric } 21400b57cec5SDimitry Andric 21410b57cec5SDimitry Andric if (reg_info->value_regs != nullptr) 21420b57cec5SDimitry Andric continue; // skip registers that are contained in other registers 21430b57cec5SDimitry Andric 21440b57cec5SDimitry Andric RegisterValue reg_value; 21450b57cec5SDimitry Andric Status error = reg_ctx.ReadRegister(reg_info, reg_value); 21460b57cec5SDimitry Andric if (error.Fail()) { 21470b57cec5SDimitry Andric LLDB_LOG(log, "failed to read register at index {0}", reg_num); 21480b57cec5SDimitry Andric return SendErrorResponse(0x15); 21490b57cec5SDimitry Andric } 21500b57cec5SDimitry Andric 21510b57cec5SDimitry Andric if (reg_info->byte_offset + reg_info->byte_size >= regs_buffer.size()) 21520b57cec5SDimitry Andric // Resize the buffer to guarantee it can store the register offsetted 21530b57cec5SDimitry Andric // data. 21540b57cec5SDimitry Andric regs_buffer.resize(reg_info->byte_offset + reg_info->byte_size); 21550b57cec5SDimitry Andric 21560b57cec5SDimitry Andric // Copy the register offsetted data to the buffer. 21570b57cec5SDimitry Andric memcpy(regs_buffer.data() + reg_info->byte_offset, reg_value.GetBytes(), 21580b57cec5SDimitry Andric reg_info->byte_size); 21590b57cec5SDimitry Andric } 21600b57cec5SDimitry Andric 21610b57cec5SDimitry Andric // Write the response. 21620b57cec5SDimitry Andric StreamGDBRemote response; 21630b57cec5SDimitry Andric response.PutBytesAsRawHex8(regs_buffer.data(), regs_buffer.size()); 21640b57cec5SDimitry Andric 21650b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 21660b57cec5SDimitry Andric } 21670b57cec5SDimitry Andric 21680b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 21690b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { 217081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 21710b57cec5SDimitry Andric 21720b57cec5SDimitry Andric // Parse out the register number from the request. 21730b57cec5SDimitry Andric packet.SetFilePos(strlen("p")); 21740b57cec5SDimitry Andric const uint32_t reg_index = 21750b57cec5SDimitry Andric packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); 21760b57cec5SDimitry Andric if (reg_index == std::numeric_limits<uint32_t>::max()) { 21779dba64beSDimitry Andric LLDB_LOGF(log, 21789dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, could not " 21790b57cec5SDimitry Andric "parse register number from request \"%s\"", 21809dba64beSDimitry Andric __FUNCTION__, packet.GetStringRef().data()); 21810b57cec5SDimitry Andric return SendErrorResponse(0x15); 21820b57cec5SDimitry Andric } 21830b57cec5SDimitry Andric 21840b57cec5SDimitry Andric // Get the thread to use. 21850b57cec5SDimitry Andric NativeThreadProtocol *thread = GetThreadFromSuffix(packet); 21860b57cec5SDimitry Andric if (!thread) { 21870b57cec5SDimitry Andric LLDB_LOG(log, "failed, no thread available"); 21880b57cec5SDimitry Andric return SendErrorResponse(0x15); 21890b57cec5SDimitry Andric } 21900b57cec5SDimitry Andric 21910b57cec5SDimitry Andric // Get the thread's register context. 21920b57cec5SDimitry Andric NativeRegisterContext ®_context = thread->GetRegisterContext(); 21930b57cec5SDimitry Andric 21940b57cec5SDimitry Andric // Return the end of registers response if we've iterated one past the end of 21950b57cec5SDimitry Andric // the register set. 21960b57cec5SDimitry Andric if (reg_index >= reg_context.GetUserRegisterCount()) { 21979dba64beSDimitry Andric LLDB_LOGF(log, 21989dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, requested " 21990b57cec5SDimitry Andric "register %" PRIu32 " beyond register count %" PRIu32, 22009dba64beSDimitry Andric __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); 22010b57cec5SDimitry Andric return SendErrorResponse(0x15); 22020b57cec5SDimitry Andric } 22030b57cec5SDimitry Andric 22040b57cec5SDimitry Andric const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); 22050b57cec5SDimitry Andric if (!reg_info) { 22069dba64beSDimitry Andric LLDB_LOGF(log, 22079dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, requested " 22080b57cec5SDimitry Andric "register %" PRIu32 " returned NULL", 22090b57cec5SDimitry Andric __FUNCTION__, reg_index); 22100b57cec5SDimitry Andric return SendErrorResponse(0x15); 22110b57cec5SDimitry Andric } 22120b57cec5SDimitry Andric 22130b57cec5SDimitry Andric // Build the reginfos response. 22140b57cec5SDimitry Andric StreamGDBRemote response; 22150b57cec5SDimitry Andric 22160b57cec5SDimitry Andric // Retrieve the value 22170b57cec5SDimitry Andric RegisterValue reg_value; 22180b57cec5SDimitry Andric Status error = reg_context.ReadRegister(reg_info, reg_value); 22190b57cec5SDimitry Andric if (error.Fail()) { 22209dba64beSDimitry Andric LLDB_LOGF(log, 22219dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, read of " 22220b57cec5SDimitry Andric "requested register %" PRIu32 " (%s) failed: %s", 22230b57cec5SDimitry Andric __FUNCTION__, reg_index, reg_info->name, error.AsCString()); 22240b57cec5SDimitry Andric return SendErrorResponse(0x15); 22250b57cec5SDimitry Andric } 22260b57cec5SDimitry Andric 22270b57cec5SDimitry Andric const uint8_t *const data = 2228480093f4SDimitry Andric static_cast<const uint8_t *>(reg_value.GetBytes()); 22290b57cec5SDimitry Andric if (!data) { 22309dba64beSDimitry Andric LLDB_LOGF(log, 22319dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed to get data " 22320b57cec5SDimitry Andric "bytes from requested register %" PRIu32, 22330b57cec5SDimitry Andric __FUNCTION__, reg_index); 22340b57cec5SDimitry Andric return SendErrorResponse(0x15); 22350b57cec5SDimitry Andric } 22360b57cec5SDimitry Andric 22370b57cec5SDimitry Andric // FIXME flip as needed to get data in big/little endian format for this host. 22380b57cec5SDimitry Andric for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i) 22390b57cec5SDimitry Andric response.PutHex8(data[i]); 22400b57cec5SDimitry Andric 22410b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 22420b57cec5SDimitry Andric } 22430b57cec5SDimitry Andric 22440b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 22450b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { 224681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 22470b57cec5SDimitry Andric 22480b57cec5SDimitry Andric // Ensure there is more content. 22490b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 22500b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Empty P packet"); 22510b57cec5SDimitry Andric 22520b57cec5SDimitry Andric // Parse out the register number from the request. 22530b57cec5SDimitry Andric packet.SetFilePos(strlen("P")); 22540b57cec5SDimitry Andric const uint32_t reg_index = 22550b57cec5SDimitry Andric packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); 22560b57cec5SDimitry Andric if (reg_index == std::numeric_limits<uint32_t>::max()) { 22579dba64beSDimitry Andric LLDB_LOGF(log, 22589dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, could not " 22590b57cec5SDimitry Andric "parse register number from request \"%s\"", 22609dba64beSDimitry Andric __FUNCTION__, packet.GetStringRef().data()); 22610b57cec5SDimitry Andric return SendErrorResponse(0x29); 22620b57cec5SDimitry Andric } 22630b57cec5SDimitry Andric 22640b57cec5SDimitry Andric // Note debugserver would send an E30 here. 22650b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '=')) 22660b57cec5SDimitry Andric return SendIllFormedResponse( 22670b57cec5SDimitry Andric packet, "P packet missing '=' char after register number"); 22680b57cec5SDimitry Andric 22690b57cec5SDimitry Andric // Parse out the value. 22705ffd83dbSDimitry Andric uint8_t reg_bytes[RegisterValue::kMaxRegisterByteSize]; 22710b57cec5SDimitry Andric size_t reg_size = packet.GetHexBytesAvail(reg_bytes); 22720b57cec5SDimitry Andric 22730b57cec5SDimitry Andric // Get the thread to use. 22740b57cec5SDimitry Andric NativeThreadProtocol *thread = GetThreadFromSuffix(packet); 22750b57cec5SDimitry Andric if (!thread) { 22769dba64beSDimitry Andric LLDB_LOGF(log, 22779dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no thread " 22780b57cec5SDimitry Andric "available (thread index 0)", 22790b57cec5SDimitry Andric __FUNCTION__); 22800b57cec5SDimitry Andric return SendErrorResponse(0x28); 22810b57cec5SDimitry Andric } 22820b57cec5SDimitry Andric 22830b57cec5SDimitry Andric // Get the thread's register context. 22840b57cec5SDimitry Andric NativeRegisterContext ®_context = thread->GetRegisterContext(); 22850b57cec5SDimitry Andric const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); 22860b57cec5SDimitry Andric if (!reg_info) { 22879dba64beSDimitry Andric LLDB_LOGF(log, 22889dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, requested " 22890b57cec5SDimitry Andric "register %" PRIu32 " returned NULL", 22900b57cec5SDimitry Andric __FUNCTION__, reg_index); 22910b57cec5SDimitry Andric return SendErrorResponse(0x48); 22920b57cec5SDimitry Andric } 22930b57cec5SDimitry Andric 22940b57cec5SDimitry Andric // Return the end of registers response if we've iterated one past the end of 22950b57cec5SDimitry Andric // the register set. 22960b57cec5SDimitry Andric if (reg_index >= reg_context.GetUserRegisterCount()) { 22979dba64beSDimitry Andric LLDB_LOGF(log, 22989dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, requested " 22990b57cec5SDimitry Andric "register %" PRIu32 " beyond register count %" PRIu32, 23000b57cec5SDimitry Andric __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); 23010b57cec5SDimitry Andric return SendErrorResponse(0x47); 23020b57cec5SDimitry Andric } 23030b57cec5SDimitry Andric 2304349cc55cSDimitry Andric if (reg_size != reg_info->byte_size) 23050b57cec5SDimitry Andric return SendIllFormedResponse(packet, "P packet register size is incorrect"); 23060b57cec5SDimitry Andric 23070b57cec5SDimitry Andric // Build the reginfos response. 23080b57cec5SDimitry Andric StreamGDBRemote response; 23090b57cec5SDimitry Andric 2310bdd1243dSDimitry Andric RegisterValue reg_value(ArrayRef(reg_bytes, reg_size), 2311fe6060f1SDimitry Andric m_current_process->GetArchitecture().GetByteOrder()); 23120b57cec5SDimitry Andric Status error = reg_context.WriteRegister(reg_info, reg_value); 23130b57cec5SDimitry Andric if (error.Fail()) { 23149dba64beSDimitry Andric LLDB_LOGF(log, 23159dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, write of " 23160b57cec5SDimitry Andric "requested register %" PRIu32 " (%s) failed: %s", 23170b57cec5SDimitry Andric __FUNCTION__, reg_index, reg_info->name, error.AsCString()); 23180b57cec5SDimitry Andric return SendErrorResponse(0x32); 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric 23210b57cec5SDimitry Andric return SendOKResponse(); 23220b57cec5SDimitry Andric } 23230b57cec5SDimitry Andric 23240b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 23250b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { 232681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 23270b57cec5SDimitry Andric 23280b57cec5SDimitry Andric // Parse out which variant of $H is requested. 23290b57cec5SDimitry Andric packet.SetFilePos(strlen("H")); 23300b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) { 23319dba64beSDimitry Andric LLDB_LOGF(log, 23329dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, H command " 23330b57cec5SDimitry Andric "missing {g,c} variant", 23340b57cec5SDimitry Andric __FUNCTION__); 23350b57cec5SDimitry Andric return SendIllFormedResponse(packet, "H command missing {g,c} variant"); 23360b57cec5SDimitry Andric } 23370b57cec5SDimitry Andric 23380b57cec5SDimitry Andric const char h_variant = packet.GetChar(); 2339fe6060f1SDimitry Andric NativeProcessProtocol *default_process; 23400b57cec5SDimitry Andric switch (h_variant) { 23410b57cec5SDimitry Andric case 'g': 2342fe6060f1SDimitry Andric default_process = m_current_process; 23430b57cec5SDimitry Andric break; 23440b57cec5SDimitry Andric 23450b57cec5SDimitry Andric case 'c': 2346fe6060f1SDimitry Andric default_process = m_continue_process; 23470b57cec5SDimitry Andric break; 23480b57cec5SDimitry Andric 23490b57cec5SDimitry Andric default: 23509dba64beSDimitry Andric LLDB_LOGF( 23519dba64beSDimitry Andric log, 23520b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", 23530b57cec5SDimitry Andric __FUNCTION__, h_variant); 23540b57cec5SDimitry Andric return SendIllFormedResponse(packet, 23550b57cec5SDimitry Andric "H variant unsupported, should be c or g"); 23560b57cec5SDimitry Andric } 23570b57cec5SDimitry Andric 23580b57cec5SDimitry Andric // Parse out the thread number. 2359fe6060f1SDimitry Andric auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID() 2360fe6060f1SDimitry Andric : LLDB_INVALID_PROCESS_ID); 2361fe6060f1SDimitry Andric if (!pid_tid) 2362fe6060f1SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 2363fe6060f1SDimitry Andric inconvertibleErrorCode(), "Malformed thread-id")); 2364fe6060f1SDimitry Andric 2365fe6060f1SDimitry Andric lldb::pid_t pid = pid_tid->first; 2366fe6060f1SDimitry Andric lldb::tid_t tid = pid_tid->second; 2367fe6060f1SDimitry Andric 2368fe6060f1SDimitry Andric if (pid == StringExtractorGDBRemote::AllProcesses) 2369fe6060f1SDimitry Andric return SendUnimplementedResponse("Selecting all processes not supported"); 2370fe6060f1SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 2371fe6060f1SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 2372fe6060f1SDimitry Andric inconvertibleErrorCode(), "No current process and no PID provided")); 2373fe6060f1SDimitry Andric 2374fe6060f1SDimitry Andric // Check the process ID and find respective process instance. 2375fe6060f1SDimitry Andric auto new_process_it = m_debugged_processes.find(pid); 2376fe6060f1SDimitry Andric if (new_process_it == m_debugged_processes.end()) 2377fe6060f1SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 2378fe6060f1SDimitry Andric inconvertibleErrorCode(), 2379fe6060f1SDimitry Andric llvm::formatv("No process with PID {0} debugged", pid))); 23800b57cec5SDimitry Andric 23810b57cec5SDimitry Andric // Ensure we have the given thread when not specifying -1 (all threads) or 0 23820b57cec5SDimitry Andric // (any thread). 23830b57cec5SDimitry Andric if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { 2384fcaf7f86SDimitry Andric NativeThreadProtocol *thread = 2385fcaf7f86SDimitry Andric new_process_it->second.process_up->GetThreadByID(tid); 23860b57cec5SDimitry Andric if (!thread) { 23879dba64beSDimitry Andric LLDB_LOGF(log, 23889dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 23890b57cec5SDimitry Andric " not found", 23900b57cec5SDimitry Andric __FUNCTION__, tid); 23910b57cec5SDimitry Andric return SendErrorResponse(0x15); 23920b57cec5SDimitry Andric } 23930b57cec5SDimitry Andric } 23940b57cec5SDimitry Andric 2395fe6060f1SDimitry Andric // Now switch the given process and thread type. 23960b57cec5SDimitry Andric switch (h_variant) { 23970b57cec5SDimitry Andric case 'g': 2398fcaf7f86SDimitry Andric m_current_process = new_process_it->second.process_up.get(); 23990b57cec5SDimitry Andric SetCurrentThreadID(tid); 24000b57cec5SDimitry Andric break; 24010b57cec5SDimitry Andric 24020b57cec5SDimitry Andric case 'c': 2403fcaf7f86SDimitry Andric m_continue_process = new_process_it->second.process_up.get(); 24040b57cec5SDimitry Andric SetContinueThreadID(tid); 24050b57cec5SDimitry Andric break; 24060b57cec5SDimitry Andric 24070b57cec5SDimitry Andric default: 24080b57cec5SDimitry Andric assert(false && "unsupported $H variant - shouldn't get here"); 24090b57cec5SDimitry Andric return SendIllFormedResponse(packet, 24100b57cec5SDimitry Andric "H variant unsupported, should be c or g"); 24110b57cec5SDimitry Andric } 24120b57cec5SDimitry Andric 24130b57cec5SDimitry Andric return SendOKResponse(); 24140b57cec5SDimitry Andric } 24150b57cec5SDimitry Andric 24160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 24170b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { 241881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 24190b57cec5SDimitry Andric 24200b57cec5SDimitry Andric // Fail if we don't have a current process. 2421fe6060f1SDimitry Andric if (!m_current_process || 2422fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 24239dba64beSDimitry Andric LLDB_LOGF( 24249dba64beSDimitry Andric log, 24250b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 24260b57cec5SDimitry Andric __FUNCTION__); 24270b57cec5SDimitry Andric return SendErrorResponse(0x15); 24280b57cec5SDimitry Andric } 24290b57cec5SDimitry Andric 24300b57cec5SDimitry Andric packet.SetFilePos(::strlen("I")); 24310b57cec5SDimitry Andric uint8_t tmp[4096]; 24320b57cec5SDimitry Andric for (;;) { 24330b57cec5SDimitry Andric size_t read = packet.GetHexBytesAvail(tmp); 24340b57cec5SDimitry Andric if (read == 0) { 24350b57cec5SDimitry Andric break; 24360b57cec5SDimitry Andric } 24370b57cec5SDimitry Andric // write directly to stdin *this might block if stdin buffer is full* 24380b57cec5SDimitry Andric // TODO: enqueue this block in circular buffer and send window size to 24390b57cec5SDimitry Andric // remote host 24400b57cec5SDimitry Andric ConnectionStatus status; 24410b57cec5SDimitry Andric Status error; 2442bdd1243dSDimitry Andric m_stdio_communication.WriteAll(tmp, read, status, &error); 24430b57cec5SDimitry Andric if (error.Fail()) { 24440b57cec5SDimitry Andric return SendErrorResponse(0x15); 24450b57cec5SDimitry Andric } 24460b57cec5SDimitry Andric } 24470b57cec5SDimitry Andric 24480b57cec5SDimitry Andric return SendOKResponse(); 24490b57cec5SDimitry Andric } 24500b57cec5SDimitry Andric 24510b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 24520b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_interrupt( 24530b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 245481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 24550b57cec5SDimitry Andric 24560b57cec5SDimitry Andric // Fail if we don't have a current process. 2457fe6060f1SDimitry Andric if (!m_current_process || 2458fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 24590b57cec5SDimitry Andric LLDB_LOG(log, "failed, no process available"); 24600b57cec5SDimitry Andric return SendErrorResponse(0x15); 24610b57cec5SDimitry Andric } 24620b57cec5SDimitry Andric 24630b57cec5SDimitry Andric // Interrupt the process. 2464fe6060f1SDimitry Andric Status error = m_current_process->Interrupt(); 24650b57cec5SDimitry Andric if (error.Fail()) { 2466fe6060f1SDimitry Andric LLDB_LOG(log, "failed for process {0}: {1}", m_current_process->GetID(), 24670b57cec5SDimitry Andric error); 24680b57cec5SDimitry Andric return SendErrorResponse(GDBRemoteServerError::eErrorResume); 24690b57cec5SDimitry Andric } 24700b57cec5SDimitry Andric 2471fe6060f1SDimitry Andric LLDB_LOG(log, "stopped process {0}", m_current_process->GetID()); 24720b57cec5SDimitry Andric 24730b57cec5SDimitry Andric // No response required from stop all. 24740b57cec5SDimitry Andric return PacketResult::Success; 24750b57cec5SDimitry Andric } 24760b57cec5SDimitry Andric 24770b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 24780b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_memory_read( 24790b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 248081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 24810b57cec5SDimitry Andric 2482fe6060f1SDimitry Andric if (!m_current_process || 2483fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 24849dba64beSDimitry Andric LLDB_LOGF( 24859dba64beSDimitry Andric log, 24860b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 24870b57cec5SDimitry Andric __FUNCTION__); 24880b57cec5SDimitry Andric return SendErrorResponse(0x15); 24890b57cec5SDimitry Andric } 24900b57cec5SDimitry Andric 24910b57cec5SDimitry Andric // Parse out the memory address. 24920b57cec5SDimitry Andric packet.SetFilePos(strlen("m")); 24930b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 24940b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short m packet"); 24950b57cec5SDimitry Andric 24960b57cec5SDimitry Andric // Read the address. Punting on validation. 24970b57cec5SDimitry Andric // FIXME replace with Hex U64 read with no default value that fails on failed 24980b57cec5SDimitry Andric // read. 24990b57cec5SDimitry Andric const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); 25000b57cec5SDimitry Andric 25010b57cec5SDimitry Andric // Validate comma. 25020b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) 25030b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Comma sep missing in m packet"); 25040b57cec5SDimitry Andric 25050b57cec5SDimitry Andric // Get # bytes to read. 25060b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 25070b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Length missing in m packet"); 25080b57cec5SDimitry Andric 25090b57cec5SDimitry Andric const uint64_t byte_count = packet.GetHexMaxU64(false, 0); 25100b57cec5SDimitry Andric if (byte_count == 0) { 25119dba64beSDimitry Andric LLDB_LOGF(log, 25129dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s nothing to read: " 25130b57cec5SDimitry Andric "zero-length packet", 25140b57cec5SDimitry Andric __FUNCTION__); 25150b57cec5SDimitry Andric return SendOKResponse(); 25160b57cec5SDimitry Andric } 25170b57cec5SDimitry Andric 25180b57cec5SDimitry Andric // Allocate the response buffer. 25190b57cec5SDimitry Andric std::string buf(byte_count, '\0'); 25200b57cec5SDimitry Andric if (buf.empty()) 25210b57cec5SDimitry Andric return SendErrorResponse(0x78); 25220b57cec5SDimitry Andric 25230b57cec5SDimitry Andric // Retrieve the process memory. 25240b57cec5SDimitry Andric size_t bytes_read = 0; 2525fe6060f1SDimitry Andric Status error = m_current_process->ReadMemoryWithoutTrap( 25260b57cec5SDimitry Andric read_addr, &buf[0], byte_count, bytes_read); 25270b57cec5SDimitry Andric if (error.Fail()) { 25289dba64beSDimitry Andric LLDB_LOGF(log, 25299dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 25300b57cec5SDimitry Andric " mem 0x%" PRIx64 ": failed to read. Error: %s", 2531fe6060f1SDimitry Andric __FUNCTION__, m_current_process->GetID(), read_addr, 25320b57cec5SDimitry Andric error.AsCString()); 25330b57cec5SDimitry Andric return SendErrorResponse(0x08); 25340b57cec5SDimitry Andric } 25350b57cec5SDimitry Andric 25360b57cec5SDimitry Andric if (bytes_read == 0) { 25379dba64beSDimitry Andric LLDB_LOGF(log, 25389dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 25390b57cec5SDimitry Andric " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", 2540fe6060f1SDimitry Andric __FUNCTION__, m_current_process->GetID(), read_addr, byte_count); 25410b57cec5SDimitry Andric return SendErrorResponse(0x08); 25420b57cec5SDimitry Andric } 25430b57cec5SDimitry Andric 25440b57cec5SDimitry Andric StreamGDBRemote response; 25450b57cec5SDimitry Andric packet.SetFilePos(0); 25460b57cec5SDimitry Andric char kind = packet.GetChar('?'); 25470b57cec5SDimitry Andric if (kind == 'x') 25480b57cec5SDimitry Andric response.PutEscapedBytes(buf.data(), byte_count); 25490b57cec5SDimitry Andric else { 25500b57cec5SDimitry Andric assert(kind == 'm'); 25510b57cec5SDimitry Andric for (size_t i = 0; i < bytes_read; ++i) 25520b57cec5SDimitry Andric response.PutHex8(buf[i]); 25530b57cec5SDimitry Andric } 25540b57cec5SDimitry Andric 25550b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 25560b57cec5SDimitry Andric } 25570b57cec5SDimitry Andric 25580b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 2559e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) { 256081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 2561e8d8bef9SDimitry Andric 2562fe6060f1SDimitry Andric if (!m_current_process || 2563fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 2564e8d8bef9SDimitry Andric LLDB_LOGF( 2565e8d8bef9SDimitry Andric log, 2566e8d8bef9SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 2567e8d8bef9SDimitry Andric __FUNCTION__); 2568e8d8bef9SDimitry Andric return SendErrorResponse(0x15); 2569e8d8bef9SDimitry Andric } 2570e8d8bef9SDimitry Andric 2571e8d8bef9SDimitry Andric // Parse out the memory address. 2572e8d8bef9SDimitry Andric packet.SetFilePos(strlen("_M")); 2573e8d8bef9SDimitry Andric if (packet.GetBytesLeft() < 1) 2574e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Too short _M packet"); 2575e8d8bef9SDimitry Andric 2576e8d8bef9SDimitry Andric const lldb::addr_t size = packet.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 2577e8d8bef9SDimitry Andric if (size == LLDB_INVALID_ADDRESS) 2578e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Address not valid"); 2579e8d8bef9SDimitry Andric if (packet.GetChar() != ',') 2580e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Bad packet"); 2581e8d8bef9SDimitry Andric Permissions perms = {}; 2582e8d8bef9SDimitry Andric while (packet.GetBytesLeft() > 0) { 2583e8d8bef9SDimitry Andric switch (packet.GetChar()) { 2584e8d8bef9SDimitry Andric case 'r': 2585e8d8bef9SDimitry Andric perms |= ePermissionsReadable; 2586e8d8bef9SDimitry Andric break; 2587e8d8bef9SDimitry Andric case 'w': 2588e8d8bef9SDimitry Andric perms |= ePermissionsWritable; 2589e8d8bef9SDimitry Andric break; 2590e8d8bef9SDimitry Andric case 'x': 2591e8d8bef9SDimitry Andric perms |= ePermissionsExecutable; 2592e8d8bef9SDimitry Andric break; 2593e8d8bef9SDimitry Andric default: 2594e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Bad permissions"); 2595e8d8bef9SDimitry Andric } 2596e8d8bef9SDimitry Andric } 2597e8d8bef9SDimitry Andric 2598fe6060f1SDimitry Andric llvm::Expected<addr_t> addr = m_current_process->AllocateMemory(size, perms); 2599e8d8bef9SDimitry Andric if (!addr) 2600e8d8bef9SDimitry Andric return SendErrorResponse(addr.takeError()); 2601e8d8bef9SDimitry Andric 2602e8d8bef9SDimitry Andric StreamGDBRemote response; 2603e8d8bef9SDimitry Andric response.PutHex64(*addr); 2604e8d8bef9SDimitry Andric return SendPacketNoLock(response.GetString()); 2605e8d8bef9SDimitry Andric } 2606e8d8bef9SDimitry Andric 2607e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 2608e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) { 260981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 2610e8d8bef9SDimitry Andric 2611fe6060f1SDimitry Andric if (!m_current_process || 2612fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 2613e8d8bef9SDimitry Andric LLDB_LOGF( 2614e8d8bef9SDimitry Andric log, 2615e8d8bef9SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 2616e8d8bef9SDimitry Andric __FUNCTION__); 2617e8d8bef9SDimitry Andric return SendErrorResponse(0x15); 2618e8d8bef9SDimitry Andric } 2619e8d8bef9SDimitry Andric 2620e8d8bef9SDimitry Andric // Parse out the memory address. 2621e8d8bef9SDimitry Andric packet.SetFilePos(strlen("_m")); 2622e8d8bef9SDimitry Andric if (packet.GetBytesLeft() < 1) 2623e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Too short m packet"); 2624e8d8bef9SDimitry Andric 2625e8d8bef9SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 2626e8d8bef9SDimitry Andric if (addr == LLDB_INVALID_ADDRESS) 2627e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Address not valid"); 2628e8d8bef9SDimitry Andric 2629fe6060f1SDimitry Andric if (llvm::Error Err = m_current_process->DeallocateMemory(addr)) 2630e8d8bef9SDimitry Andric return SendErrorResponse(std::move(Err)); 2631e8d8bef9SDimitry Andric 2632e8d8bef9SDimitry Andric return SendOKResponse(); 2633e8d8bef9SDimitry Andric } 2634e8d8bef9SDimitry Andric 2635e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 26360b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { 263781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 26380b57cec5SDimitry Andric 2639fe6060f1SDimitry Andric if (!m_current_process || 2640fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 26419dba64beSDimitry Andric LLDB_LOGF( 26429dba64beSDimitry Andric log, 26430b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 26440b57cec5SDimitry Andric __FUNCTION__); 26450b57cec5SDimitry Andric return SendErrorResponse(0x15); 26460b57cec5SDimitry Andric } 26470b57cec5SDimitry Andric 26480b57cec5SDimitry Andric // Parse out the memory address. 26490b57cec5SDimitry Andric packet.SetFilePos(strlen("M")); 26500b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 26510b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short M packet"); 26520b57cec5SDimitry Andric 26530b57cec5SDimitry Andric // Read the address. Punting on validation. 26540b57cec5SDimitry Andric // FIXME replace with Hex U64 read with no default value that fails on failed 26550b57cec5SDimitry Andric // read. 26560b57cec5SDimitry Andric const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0); 26570b57cec5SDimitry Andric 26580b57cec5SDimitry Andric // Validate comma. 26590b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) 26600b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Comma sep missing in M packet"); 26610b57cec5SDimitry Andric 26620b57cec5SDimitry Andric // Get # bytes to read. 26630b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 26640b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Length missing in M packet"); 26650b57cec5SDimitry Andric 26660b57cec5SDimitry Andric const uint64_t byte_count = packet.GetHexMaxU64(false, 0); 26670b57cec5SDimitry Andric if (byte_count == 0) { 26680b57cec5SDimitry Andric LLDB_LOG(log, "nothing to write: zero-length packet"); 26690b57cec5SDimitry Andric return PacketResult::Success; 26700b57cec5SDimitry Andric } 26710b57cec5SDimitry Andric 26720b57cec5SDimitry Andric // Validate colon. 26730b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':')) 26740b57cec5SDimitry Andric return SendIllFormedResponse( 26750b57cec5SDimitry Andric packet, "Comma sep missing in M packet after byte length"); 26760b57cec5SDimitry Andric 26770b57cec5SDimitry Andric // Allocate the conversion buffer. 26780b57cec5SDimitry Andric std::vector<uint8_t> buf(byte_count, 0); 26790b57cec5SDimitry Andric if (buf.empty()) 26800b57cec5SDimitry Andric return SendErrorResponse(0x78); 26810b57cec5SDimitry Andric 26820b57cec5SDimitry Andric // Convert the hex memory write contents to bytes. 26830b57cec5SDimitry Andric StreamGDBRemote response; 26840b57cec5SDimitry Andric const uint64_t convert_count = packet.GetHexBytes(buf, 0); 26850b57cec5SDimitry Andric if (convert_count != byte_count) { 26860b57cec5SDimitry Andric LLDB_LOG(log, 26870b57cec5SDimitry Andric "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " 26880b57cec5SDimitry Andric "to convert.", 2689fe6060f1SDimitry Andric m_current_process->GetID(), write_addr, byte_count, convert_count); 26900b57cec5SDimitry Andric return SendIllFormedResponse(packet, "M content byte length specified did " 26910b57cec5SDimitry Andric "not match hex-encoded content " 26920b57cec5SDimitry Andric "length"); 26930b57cec5SDimitry Andric } 26940b57cec5SDimitry Andric 26950b57cec5SDimitry Andric // Write the process memory. 26960b57cec5SDimitry Andric size_t bytes_written = 0; 2697fe6060f1SDimitry Andric Status error = m_current_process->WriteMemory(write_addr, &buf[0], byte_count, 2698fe6060f1SDimitry Andric bytes_written); 26990b57cec5SDimitry Andric if (error.Fail()) { 27000b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}", 2701fe6060f1SDimitry Andric m_current_process->GetID(), write_addr, error); 27020b57cec5SDimitry Andric return SendErrorResponse(0x09); 27030b57cec5SDimitry Andric } 27040b57cec5SDimitry Andric 27050b57cec5SDimitry Andric if (bytes_written == 0) { 27060b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes", 2707fe6060f1SDimitry Andric m_current_process->GetID(), write_addr, byte_count); 27080b57cec5SDimitry Andric return SendErrorResponse(0x09); 27090b57cec5SDimitry Andric } 27100b57cec5SDimitry Andric 27110b57cec5SDimitry Andric return SendOKResponse(); 27120b57cec5SDimitry Andric } 27130b57cec5SDimitry Andric 27140b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 27150b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( 27160b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 271781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 27180b57cec5SDimitry Andric 27190b57cec5SDimitry Andric // Currently only the NativeProcessProtocol knows if it can handle a 27200b57cec5SDimitry Andric // qMemoryRegionInfoSupported request, but we're not guaranteed to be 27210b57cec5SDimitry Andric // attached to a process. For now we'll assume the client only asks this 27220b57cec5SDimitry Andric // when a process is being debugged. 27230b57cec5SDimitry Andric 27240b57cec5SDimitry Andric // Ensure we have a process running; otherwise, we can't figure this out 27250b57cec5SDimitry Andric // since we won't have a NativeProcessProtocol. 2726fe6060f1SDimitry Andric if (!m_current_process || 2727fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 27289dba64beSDimitry Andric LLDB_LOGF( 27299dba64beSDimitry Andric log, 27300b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 27310b57cec5SDimitry Andric __FUNCTION__); 27320b57cec5SDimitry Andric return SendErrorResponse(0x15); 27330b57cec5SDimitry Andric } 27340b57cec5SDimitry Andric 27350b57cec5SDimitry Andric // Test if we can get any region back when asking for the region around NULL. 27360b57cec5SDimitry Andric MemoryRegionInfo region_info; 2737fe6060f1SDimitry Andric const Status error = m_current_process->GetMemoryRegionInfo(0, region_info); 27380b57cec5SDimitry Andric if (error.Fail()) { 27390b57cec5SDimitry Andric // We don't support memory region info collection for this 27400b57cec5SDimitry Andric // NativeProcessProtocol. 27410b57cec5SDimitry Andric return SendUnimplementedResponse(""); 27420b57cec5SDimitry Andric } 27430b57cec5SDimitry Andric 27440b57cec5SDimitry Andric return SendOKResponse(); 27450b57cec5SDimitry Andric } 27460b57cec5SDimitry Andric 27470b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 27480b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( 27490b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 275081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 27510b57cec5SDimitry Andric 27520b57cec5SDimitry Andric // Ensure we have a process. 2753fe6060f1SDimitry Andric if (!m_current_process || 2754fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 27559dba64beSDimitry Andric LLDB_LOGF( 27569dba64beSDimitry Andric log, 27570b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 27580b57cec5SDimitry Andric __FUNCTION__); 27590b57cec5SDimitry Andric return SendErrorResponse(0x15); 27600b57cec5SDimitry Andric } 27610b57cec5SDimitry Andric 27620b57cec5SDimitry Andric // Parse out the memory address. 27630b57cec5SDimitry Andric packet.SetFilePos(strlen("qMemoryRegionInfo:")); 27640b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 27650b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet"); 27660b57cec5SDimitry Andric 27670b57cec5SDimitry Andric // Read the address. Punting on validation. 27680b57cec5SDimitry Andric const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); 27690b57cec5SDimitry Andric 27700b57cec5SDimitry Andric StreamGDBRemote response; 27710b57cec5SDimitry Andric 27720b57cec5SDimitry Andric // Get the memory region info for the target address. 27730b57cec5SDimitry Andric MemoryRegionInfo region_info; 27740b57cec5SDimitry Andric const Status error = 2775fe6060f1SDimitry Andric m_current_process->GetMemoryRegionInfo(read_addr, region_info); 27760b57cec5SDimitry Andric if (error.Fail()) { 27770b57cec5SDimitry Andric // Return the error message. 27780b57cec5SDimitry Andric 27790b57cec5SDimitry Andric response.PutCString("error:"); 27800b57cec5SDimitry Andric response.PutStringAsRawHex8(error.AsCString()); 27810b57cec5SDimitry Andric response.PutChar(';'); 27820b57cec5SDimitry Andric } else { 27830b57cec5SDimitry Andric // Range start and size. 27840b57cec5SDimitry Andric response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";", 27850b57cec5SDimitry Andric region_info.GetRange().GetRangeBase(), 27860b57cec5SDimitry Andric region_info.GetRange().GetByteSize()); 27870b57cec5SDimitry Andric 27880b57cec5SDimitry Andric // Permissions. 27890b57cec5SDimitry Andric if (region_info.GetReadable() || region_info.GetWritable() || 27900b57cec5SDimitry Andric region_info.GetExecutable()) { 27910b57cec5SDimitry Andric // Write permissions info. 27920b57cec5SDimitry Andric response.PutCString("permissions:"); 27930b57cec5SDimitry Andric 27940b57cec5SDimitry Andric if (region_info.GetReadable()) 27950b57cec5SDimitry Andric response.PutChar('r'); 27960b57cec5SDimitry Andric if (region_info.GetWritable()) 27970b57cec5SDimitry Andric response.PutChar('w'); 27980b57cec5SDimitry Andric if (region_info.GetExecutable()) 27990b57cec5SDimitry Andric response.PutChar('x'); 28000b57cec5SDimitry Andric 28010b57cec5SDimitry Andric response.PutChar(';'); 28020b57cec5SDimitry Andric } 28030b57cec5SDimitry Andric 2804e8d8bef9SDimitry Andric // Flags 2805e8d8bef9SDimitry Andric MemoryRegionInfo::OptionalBool memory_tagged = 2806e8d8bef9SDimitry Andric region_info.GetMemoryTagged(); 2807e8d8bef9SDimitry Andric if (memory_tagged != MemoryRegionInfo::eDontKnow) { 2808e8d8bef9SDimitry Andric response.PutCString("flags:"); 2809e8d8bef9SDimitry Andric if (memory_tagged == MemoryRegionInfo::eYes) { 2810e8d8bef9SDimitry Andric response.PutCString("mt"); 2811e8d8bef9SDimitry Andric } 2812e8d8bef9SDimitry Andric response.PutChar(';'); 2813e8d8bef9SDimitry Andric } 2814e8d8bef9SDimitry Andric 28150b57cec5SDimitry Andric // Name 28160b57cec5SDimitry Andric ConstString name = region_info.GetName(); 28170b57cec5SDimitry Andric if (name) { 28180b57cec5SDimitry Andric response.PutCString("name:"); 28195ffd83dbSDimitry Andric response.PutStringAsRawHex8(name.GetStringRef()); 28200b57cec5SDimitry Andric response.PutChar(';'); 28210b57cec5SDimitry Andric } 28220b57cec5SDimitry Andric } 28230b57cec5SDimitry Andric 28240b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 28250b57cec5SDimitry Andric } 28260b57cec5SDimitry Andric 28270b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 28280b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { 28290b57cec5SDimitry Andric // Ensure we have a process. 2830fe6060f1SDimitry Andric if (!m_current_process || 2831fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 283281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 28330b57cec5SDimitry Andric LLDB_LOG(log, "failed, no process available"); 28340b57cec5SDimitry Andric return SendErrorResponse(0x15); 28350b57cec5SDimitry Andric } 28360b57cec5SDimitry Andric 28370b57cec5SDimitry Andric // Parse out software or hardware breakpoint or watchpoint requested. 28380b57cec5SDimitry Andric packet.SetFilePos(strlen("Z")); 28390b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 28400b57cec5SDimitry Andric return SendIllFormedResponse( 28410b57cec5SDimitry Andric packet, "Too short Z packet, missing software/hardware specifier"); 28420b57cec5SDimitry Andric 28430b57cec5SDimitry Andric bool want_breakpoint = true; 28440b57cec5SDimitry Andric bool want_hardware = false; 28450b57cec5SDimitry Andric uint32_t watch_flags = 0; 28460b57cec5SDimitry Andric 28470b57cec5SDimitry Andric const GDBStoppointType stoppoint_type = 28480b57cec5SDimitry Andric GDBStoppointType(packet.GetS32(eStoppointInvalid)); 28490b57cec5SDimitry Andric switch (stoppoint_type) { 28500b57cec5SDimitry Andric case eBreakpointSoftware: 28510b57cec5SDimitry Andric want_hardware = false; 28520b57cec5SDimitry Andric want_breakpoint = true; 28530b57cec5SDimitry Andric break; 28540b57cec5SDimitry Andric case eBreakpointHardware: 28550b57cec5SDimitry Andric want_hardware = true; 28560b57cec5SDimitry Andric want_breakpoint = true; 28570b57cec5SDimitry Andric break; 28580b57cec5SDimitry Andric case eWatchpointWrite: 28590b57cec5SDimitry Andric watch_flags = 1; 28600b57cec5SDimitry Andric want_hardware = true; 28610b57cec5SDimitry Andric want_breakpoint = false; 28620b57cec5SDimitry Andric break; 28630b57cec5SDimitry Andric case eWatchpointRead: 28640b57cec5SDimitry Andric watch_flags = 2; 28650b57cec5SDimitry Andric want_hardware = true; 28660b57cec5SDimitry Andric want_breakpoint = false; 28670b57cec5SDimitry Andric break; 28680b57cec5SDimitry Andric case eWatchpointReadWrite: 28690b57cec5SDimitry Andric watch_flags = 3; 28700b57cec5SDimitry Andric want_hardware = true; 28710b57cec5SDimitry Andric want_breakpoint = false; 28720b57cec5SDimitry Andric break; 28730b57cec5SDimitry Andric case eStoppointInvalid: 28740b57cec5SDimitry Andric return SendIllFormedResponse( 28750b57cec5SDimitry Andric packet, "Z packet had invalid software/hardware specifier"); 28760b57cec5SDimitry Andric } 28770b57cec5SDimitry Andric 28780b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') 28790b57cec5SDimitry Andric return SendIllFormedResponse( 28800b57cec5SDimitry Andric packet, "Malformed Z packet, expecting comma after stoppoint type"); 28810b57cec5SDimitry Andric 28820b57cec5SDimitry Andric // Parse out the stoppoint address. 28830b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 28840b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short Z packet, missing address"); 28850b57cec5SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); 28860b57cec5SDimitry Andric 28870b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') 28880b57cec5SDimitry Andric return SendIllFormedResponse( 28890b57cec5SDimitry Andric packet, "Malformed Z packet, expecting comma after address"); 28900b57cec5SDimitry Andric 28910b57cec5SDimitry Andric // Parse out the stoppoint size (i.e. size hint for opcode size). 28920b57cec5SDimitry Andric const uint32_t size = 28930b57cec5SDimitry Andric packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); 28940b57cec5SDimitry Andric if (size == std::numeric_limits<uint32_t>::max()) 28950b57cec5SDimitry Andric return SendIllFormedResponse( 28960b57cec5SDimitry Andric packet, "Malformed Z packet, failed to parse size argument"); 28970b57cec5SDimitry Andric 28980b57cec5SDimitry Andric if (want_breakpoint) { 28990b57cec5SDimitry Andric // Try to set the breakpoint. 29000b57cec5SDimitry Andric const Status error = 2901fe6060f1SDimitry Andric m_current_process->SetBreakpoint(addr, size, want_hardware); 29020b57cec5SDimitry Andric if (error.Success()) 29030b57cec5SDimitry Andric return SendOKResponse(); 290481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Breakpoints); 29050b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}", 2906fe6060f1SDimitry Andric m_current_process->GetID(), error); 29070b57cec5SDimitry Andric return SendErrorResponse(0x09); 29080b57cec5SDimitry Andric } else { 29090b57cec5SDimitry Andric // Try to set the watchpoint. 2910fe6060f1SDimitry Andric const Status error = m_current_process->SetWatchpoint( 29110b57cec5SDimitry Andric addr, size, watch_flags, want_hardware); 29120b57cec5SDimitry Andric if (error.Success()) 29130b57cec5SDimitry Andric return SendOKResponse(); 291481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Watchpoints); 29150b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}", 2916fe6060f1SDimitry Andric m_current_process->GetID(), error); 29170b57cec5SDimitry Andric return SendErrorResponse(0x09); 29180b57cec5SDimitry Andric } 29190b57cec5SDimitry Andric } 29200b57cec5SDimitry Andric 29210b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 29220b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { 29230b57cec5SDimitry Andric // Ensure we have a process. 2924fe6060f1SDimitry Andric if (!m_current_process || 2925fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 292681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 29270b57cec5SDimitry Andric LLDB_LOG(log, "failed, no process available"); 29280b57cec5SDimitry Andric return SendErrorResponse(0x15); 29290b57cec5SDimitry Andric } 29300b57cec5SDimitry Andric 29310b57cec5SDimitry Andric // Parse out software or hardware breakpoint or watchpoint requested. 29320b57cec5SDimitry Andric packet.SetFilePos(strlen("z")); 29330b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 29340b57cec5SDimitry Andric return SendIllFormedResponse( 29350b57cec5SDimitry Andric packet, "Too short z packet, missing software/hardware specifier"); 29360b57cec5SDimitry Andric 29370b57cec5SDimitry Andric bool want_breakpoint = true; 29380b57cec5SDimitry Andric bool want_hardware = false; 29390b57cec5SDimitry Andric 29400b57cec5SDimitry Andric const GDBStoppointType stoppoint_type = 29410b57cec5SDimitry Andric GDBStoppointType(packet.GetS32(eStoppointInvalid)); 29420b57cec5SDimitry Andric switch (stoppoint_type) { 29430b57cec5SDimitry Andric case eBreakpointHardware: 29440b57cec5SDimitry Andric want_breakpoint = true; 29450b57cec5SDimitry Andric want_hardware = true; 29460b57cec5SDimitry Andric break; 29470b57cec5SDimitry Andric case eBreakpointSoftware: 29480b57cec5SDimitry Andric want_breakpoint = true; 29490b57cec5SDimitry Andric break; 29500b57cec5SDimitry Andric case eWatchpointWrite: 29510b57cec5SDimitry Andric want_breakpoint = false; 29520b57cec5SDimitry Andric break; 29530b57cec5SDimitry Andric case eWatchpointRead: 29540b57cec5SDimitry Andric want_breakpoint = false; 29550b57cec5SDimitry Andric break; 29560b57cec5SDimitry Andric case eWatchpointReadWrite: 29570b57cec5SDimitry Andric want_breakpoint = false; 29580b57cec5SDimitry Andric break; 29590b57cec5SDimitry Andric default: 29600b57cec5SDimitry Andric return SendIllFormedResponse( 29610b57cec5SDimitry Andric packet, "z packet had invalid software/hardware specifier"); 29620b57cec5SDimitry Andric } 29630b57cec5SDimitry Andric 29640b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') 29650b57cec5SDimitry Andric return SendIllFormedResponse( 29660b57cec5SDimitry Andric packet, "Malformed z packet, expecting comma after stoppoint type"); 29670b57cec5SDimitry Andric 29680b57cec5SDimitry Andric // Parse out the stoppoint address. 29690b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 29700b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short z packet, missing address"); 29710b57cec5SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); 29720b57cec5SDimitry Andric 29730b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') 29740b57cec5SDimitry Andric return SendIllFormedResponse( 29750b57cec5SDimitry Andric packet, "Malformed z packet, expecting comma after address"); 29760b57cec5SDimitry Andric 29770b57cec5SDimitry Andric /* 29780b57cec5SDimitry Andric // Parse out the stoppoint size (i.e. size hint for opcode size). 29790b57cec5SDimitry Andric const uint32_t size = packet.GetHexMaxU32 (false, 29800b57cec5SDimitry Andric std::numeric_limits<uint32_t>::max ()); 29810b57cec5SDimitry Andric if (size == std::numeric_limits<uint32_t>::max ()) 29820b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Malformed z packet, failed to parse 29830b57cec5SDimitry Andric size argument"); 29840b57cec5SDimitry Andric */ 29850b57cec5SDimitry Andric 29860b57cec5SDimitry Andric if (want_breakpoint) { 29870b57cec5SDimitry Andric // Try to clear the breakpoint. 29880b57cec5SDimitry Andric const Status error = 2989fe6060f1SDimitry Andric m_current_process->RemoveBreakpoint(addr, want_hardware); 29900b57cec5SDimitry Andric if (error.Success()) 29910b57cec5SDimitry Andric return SendOKResponse(); 299281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Breakpoints); 29930b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}", 2994fe6060f1SDimitry Andric m_current_process->GetID(), error); 29950b57cec5SDimitry Andric return SendErrorResponse(0x09); 29960b57cec5SDimitry Andric } else { 29970b57cec5SDimitry Andric // Try to clear the watchpoint. 2998fe6060f1SDimitry Andric const Status error = m_current_process->RemoveWatchpoint(addr); 29990b57cec5SDimitry Andric if (error.Success()) 30000b57cec5SDimitry Andric return SendOKResponse(); 300181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Watchpoints); 30020b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}", 3003fe6060f1SDimitry Andric m_current_process->GetID(), error); 30040b57cec5SDimitry Andric return SendErrorResponse(0x09); 30050b57cec5SDimitry Andric } 30060b57cec5SDimitry Andric } 30070b57cec5SDimitry Andric 30080b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 30090b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { 301081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 30110b57cec5SDimitry Andric 30120b57cec5SDimitry Andric // Ensure we have a process. 3013fe6060f1SDimitry Andric if (!m_continue_process || 3014fe6060f1SDimitry Andric (m_continue_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 30159dba64beSDimitry Andric LLDB_LOGF( 30169dba64beSDimitry Andric log, 30170b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 30180b57cec5SDimitry Andric __FUNCTION__); 30190b57cec5SDimitry Andric return SendErrorResponse(0x32); 30200b57cec5SDimitry Andric } 30210b57cec5SDimitry Andric 30220b57cec5SDimitry Andric // We first try to use a continue thread id. If any one or any all set, use 30230b57cec5SDimitry Andric // the current thread. Bail out if we don't have a thread id. 30240b57cec5SDimitry Andric lldb::tid_t tid = GetContinueThreadID(); 30250b57cec5SDimitry Andric if (tid == 0 || tid == LLDB_INVALID_THREAD_ID) 30260b57cec5SDimitry Andric tid = GetCurrentThreadID(); 30270b57cec5SDimitry Andric if (tid == LLDB_INVALID_THREAD_ID) 30280b57cec5SDimitry Andric return SendErrorResponse(0x33); 30290b57cec5SDimitry Andric 30300b57cec5SDimitry Andric // Double check that we have such a thread. 30310b57cec5SDimitry Andric // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. 3032fe6060f1SDimitry Andric NativeThreadProtocol *thread = m_continue_process->GetThreadByID(tid); 30330b57cec5SDimitry Andric if (!thread) 30340b57cec5SDimitry Andric return SendErrorResponse(0x33); 30350b57cec5SDimitry Andric 30360b57cec5SDimitry Andric // Create the step action for the given thread. 30379dba64beSDimitry Andric ResumeAction action = {tid, eStateStepping, LLDB_INVALID_SIGNAL_NUMBER}; 30380b57cec5SDimitry Andric 30390b57cec5SDimitry Andric // Setup the actions list. 30400b57cec5SDimitry Andric ResumeActionList actions; 30410b57cec5SDimitry Andric actions.Append(action); 30420b57cec5SDimitry Andric 30430b57cec5SDimitry Andric // All other threads stop while we're single stepping a thread. 30440b57cec5SDimitry Andric actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); 3045fcaf7f86SDimitry Andric 3046fcaf7f86SDimitry Andric PacketResult resume_res = ResumeProcess(*m_continue_process, actions); 3047fcaf7f86SDimitry Andric if (resume_res != PacketResult::Success) 3048fcaf7f86SDimitry Andric return resume_res; 30490b57cec5SDimitry Andric 305081ad6265SDimitry Andric // No response here, unless in non-stop mode. 305181ad6265SDimitry Andric // Otherwise, the stop or exit will come from the resulting action. 305281ad6265SDimitry Andric return SendContinueSuccessResponse(); 30530b57cec5SDimitry Andric } 30540b57cec5SDimitry Andric 30550b57cec5SDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> 30565ffd83dbSDimitry Andric GDBRemoteCommunicationServerLLGS::BuildTargetXml() { 30575ffd83dbSDimitry Andric // Ensure we have a thread. 3058fe6060f1SDimitry Andric NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0); 30595ffd83dbSDimitry Andric if (!thread) 30605ffd83dbSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 30615ffd83dbSDimitry Andric "No thread available"); 30625ffd83dbSDimitry Andric 306381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 30645ffd83dbSDimitry Andric // Get the register context for the first thread. 30655ffd83dbSDimitry Andric NativeRegisterContext ®_context = thread->GetRegisterContext(); 30665ffd83dbSDimitry Andric 30675ffd83dbSDimitry Andric StreamString response; 30685ffd83dbSDimitry Andric 3069bdd1243dSDimitry Andric response.Printf("<?xml version=\"1.0\"?>\n"); 3070bdd1243dSDimitry Andric response.Printf("<target version=\"1.0\">\n"); 3071bdd1243dSDimitry Andric response.IndentMore(); 30725ffd83dbSDimitry Andric 3073bdd1243dSDimitry Andric response.Indent(); 3074bdd1243dSDimitry Andric response.Printf("<architecture>%s</architecture>\n", 3075fe6060f1SDimitry Andric m_current_process->GetArchitecture() 30765ffd83dbSDimitry Andric .GetTriple() 30775ffd83dbSDimitry Andric .getArchName() 30785ffd83dbSDimitry Andric .str() 30795ffd83dbSDimitry Andric .c_str()); 30805ffd83dbSDimitry Andric 3081bdd1243dSDimitry Andric response.Indent("<feature>\n"); 30825ffd83dbSDimitry Andric 30835ffd83dbSDimitry Andric const int registers_count = reg_context.GetUserRegisterCount(); 3084bdd1243dSDimitry Andric if (registers_count) 3085bdd1243dSDimitry Andric response.IndentMore(); 3086bdd1243dSDimitry Andric 30875ffd83dbSDimitry Andric for (int reg_index = 0; reg_index < registers_count; reg_index++) { 30885ffd83dbSDimitry Andric const RegisterInfo *reg_info = 30895ffd83dbSDimitry Andric reg_context.GetRegisterInfoAtIndex(reg_index); 30905ffd83dbSDimitry Andric 30915ffd83dbSDimitry Andric if (!reg_info) { 30925ffd83dbSDimitry Andric LLDB_LOGF(log, 30935ffd83dbSDimitry Andric "%s failed to get register info for register index %" PRIu32, 30945ffd83dbSDimitry Andric "target.xml", reg_index); 30955ffd83dbSDimitry Andric continue; 30965ffd83dbSDimitry Andric } 30975ffd83dbSDimitry Andric 3098bdd1243dSDimitry Andric response.Indent(); 3099bdd1243dSDimitry Andric response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 3100bdd1243dSDimitry Andric "\" regnum=\"%d\" ", 3101e8d8bef9SDimitry Andric reg_info->name, reg_info->byte_size * 8, reg_index); 3102e8d8bef9SDimitry Andric 3103e8d8bef9SDimitry Andric if (!reg_context.RegisterOffsetIsDynamic()) 3104e8d8bef9SDimitry Andric response.Printf("offset=\"%" PRIu32 "\" ", reg_info->byte_offset); 31055ffd83dbSDimitry Andric 31065ffd83dbSDimitry Andric if (reg_info->alt_name && reg_info->alt_name[0]) 31075ffd83dbSDimitry Andric response.Printf("altname=\"%s\" ", reg_info->alt_name); 31085ffd83dbSDimitry Andric 31095ffd83dbSDimitry Andric llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info); 31105ffd83dbSDimitry Andric if (!encoding.empty()) 31115ffd83dbSDimitry Andric response << "encoding=\"" << encoding << "\" "; 31125ffd83dbSDimitry Andric 31135ffd83dbSDimitry Andric llvm::StringRef format = GetFormatNameOrEmpty(*reg_info); 31145ffd83dbSDimitry Andric if (!format.empty()) 31155ffd83dbSDimitry Andric response << "format=\"" << format << "\" "; 31165ffd83dbSDimitry Andric 31175ffd83dbSDimitry Andric const char *const register_set_name = 31185ffd83dbSDimitry Andric reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); 31195ffd83dbSDimitry Andric if (register_set_name) 31205ffd83dbSDimitry Andric response << "group=\"" << register_set_name << "\" "; 31215ffd83dbSDimitry Andric 31225ffd83dbSDimitry Andric if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != 31235ffd83dbSDimitry Andric LLDB_INVALID_REGNUM) 31245ffd83dbSDimitry Andric response.Printf("ehframe_regnum=\"%" PRIu32 "\" ", 31255ffd83dbSDimitry Andric reg_info->kinds[RegisterKind::eRegisterKindEHFrame]); 31265ffd83dbSDimitry Andric 31275ffd83dbSDimitry Andric if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != 31285ffd83dbSDimitry Andric LLDB_INVALID_REGNUM) 31295ffd83dbSDimitry Andric response.Printf("dwarf_regnum=\"%" PRIu32 "\" ", 31305ffd83dbSDimitry Andric reg_info->kinds[RegisterKind::eRegisterKindDWARF]); 31315ffd83dbSDimitry Andric 31325ffd83dbSDimitry Andric llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info); 31335ffd83dbSDimitry Andric if (!kind_generic.empty()) 31345ffd83dbSDimitry Andric response << "generic=\"" << kind_generic << "\" "; 31355ffd83dbSDimitry Andric 31365ffd83dbSDimitry Andric if (reg_info->value_regs && 31375ffd83dbSDimitry Andric reg_info->value_regs[0] != LLDB_INVALID_REGNUM) { 31385ffd83dbSDimitry Andric response.PutCString("value_regnums=\""); 31395ffd83dbSDimitry Andric CollectRegNums(reg_info->value_regs, response, false); 31405ffd83dbSDimitry Andric response.Printf("\" "); 31415ffd83dbSDimitry Andric } 31425ffd83dbSDimitry Andric 31435ffd83dbSDimitry Andric if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) { 31445ffd83dbSDimitry Andric response.PutCString("invalidate_regnums=\""); 31455ffd83dbSDimitry Andric CollectRegNums(reg_info->invalidate_regs, response, false); 31465ffd83dbSDimitry Andric response.Printf("\" "); 31475ffd83dbSDimitry Andric } 31485ffd83dbSDimitry Andric 3149bdd1243dSDimitry Andric response.Printf("/>\n"); 31505ffd83dbSDimitry Andric } 31515ffd83dbSDimitry Andric 3152bdd1243dSDimitry Andric if (registers_count) 3153bdd1243dSDimitry Andric response.IndentLess(); 3154bdd1243dSDimitry Andric 3155bdd1243dSDimitry Andric response.Indent("</feature>\n"); 3156bdd1243dSDimitry Andric response.IndentLess(); 3157bdd1243dSDimitry Andric response.Indent("</target>\n"); 31585ffd83dbSDimitry Andric return MemoryBuffer::getMemBufferCopy(response.GetString(), "target.xml"); 31595ffd83dbSDimitry Andric } 31605ffd83dbSDimitry Andric 31615ffd83dbSDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> 31620b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, 31630b57cec5SDimitry Andric llvm::StringRef annex) { 31640b57cec5SDimitry Andric // Make sure we have a valid process. 3165fe6060f1SDimitry Andric if (!m_current_process || 3166fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 31670b57cec5SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 31680b57cec5SDimitry Andric "No process available"); 31690b57cec5SDimitry Andric } 31700b57cec5SDimitry Andric 31715ffd83dbSDimitry Andric if (object == "auxv") { 31720b57cec5SDimitry Andric // Grab the auxv data. 3173fe6060f1SDimitry Andric auto buffer_or_error = m_current_process->GetAuxvData(); 31740b57cec5SDimitry Andric if (!buffer_or_error) 31750b57cec5SDimitry Andric return llvm::errorCodeToError(buffer_or_error.getError()); 31760b57cec5SDimitry Andric return std::move(*buffer_or_error); 31770b57cec5SDimitry Andric } 31780b57cec5SDimitry Andric 317904eeddc0SDimitry Andric if (object == "siginfo") { 318004eeddc0SDimitry Andric NativeThreadProtocol *thread = m_current_process->GetCurrentThread(); 318104eeddc0SDimitry Andric if (!thread) 318204eeddc0SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 318304eeddc0SDimitry Andric "no current thread"); 318404eeddc0SDimitry Andric 318504eeddc0SDimitry Andric auto buffer_or_error = thread->GetSiginfo(); 318604eeddc0SDimitry Andric if (!buffer_or_error) 318704eeddc0SDimitry Andric return buffer_or_error.takeError(); 318804eeddc0SDimitry Andric return std::move(*buffer_or_error); 318904eeddc0SDimitry Andric } 319004eeddc0SDimitry Andric 31919dba64beSDimitry Andric if (object == "libraries-svr4") { 3192fe6060f1SDimitry Andric auto library_list = m_current_process->GetLoadedSVR4Libraries(); 31939dba64beSDimitry Andric if (!library_list) 31949dba64beSDimitry Andric return library_list.takeError(); 31959dba64beSDimitry Andric 31969dba64beSDimitry Andric StreamString response; 31979dba64beSDimitry Andric response.Printf("<library-list-svr4 version=\"1.0\">"); 31989dba64beSDimitry Andric for (auto const &library : *library_list) { 31999dba64beSDimitry Andric response.Printf("<library name=\"%s\" ", 32009dba64beSDimitry Andric XMLEncodeAttributeValue(library.name.c_str()).c_str()); 32019dba64beSDimitry Andric response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map); 32029dba64beSDimitry Andric response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr); 32039dba64beSDimitry Andric response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr); 32049dba64beSDimitry Andric } 32059dba64beSDimitry Andric response.Printf("</library-list-svr4>"); 32069dba64beSDimitry Andric return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__); 32079dba64beSDimitry Andric } 32089dba64beSDimitry Andric 32095ffd83dbSDimitry Andric if (object == "features" && annex == "target.xml") 32105ffd83dbSDimitry Andric return BuildTargetXml(); 32115ffd83dbSDimitry Andric 3212e8d8bef9SDimitry Andric return llvm::make_error<UnimplementedError>(); 32130b57cec5SDimitry Andric } 32140b57cec5SDimitry Andric 32150b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 32160b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qXfer( 32170b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 32180b57cec5SDimitry Andric SmallVector<StringRef, 5> fields; 32190b57cec5SDimitry Andric // The packet format is "qXfer:<object>:<action>:<annex>:offset,length" 32200b57cec5SDimitry Andric StringRef(packet.GetStringRef()).split(fields, ':', 4); 32210b57cec5SDimitry Andric if (fields.size() != 5) 32220b57cec5SDimitry Andric return SendIllFormedResponse(packet, "malformed qXfer packet"); 32230b57cec5SDimitry Andric StringRef &xfer_object = fields[1]; 32240b57cec5SDimitry Andric StringRef &xfer_action = fields[2]; 32250b57cec5SDimitry Andric StringRef &xfer_annex = fields[3]; 32260b57cec5SDimitry Andric StringExtractor offset_data(fields[4]); 32270b57cec5SDimitry Andric if (xfer_action != "read") 32280b57cec5SDimitry Andric return SendUnimplementedResponse("qXfer action not supported"); 32290b57cec5SDimitry Andric // Parse offset. 32300b57cec5SDimitry Andric const uint64_t xfer_offset = 32310b57cec5SDimitry Andric offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); 32320b57cec5SDimitry Andric if (xfer_offset == std::numeric_limits<uint64_t>::max()) 32330b57cec5SDimitry Andric return SendIllFormedResponse(packet, "qXfer packet missing offset"); 32340b57cec5SDimitry Andric // Parse out comma. 32350b57cec5SDimitry Andric if (offset_data.GetChar() != ',') 32360b57cec5SDimitry Andric return SendIllFormedResponse(packet, 32370b57cec5SDimitry Andric "qXfer packet missing comma after offset"); 32380b57cec5SDimitry Andric // Parse out the length. 32390b57cec5SDimitry Andric const uint64_t xfer_length = 32400b57cec5SDimitry Andric offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); 32410b57cec5SDimitry Andric if (xfer_length == std::numeric_limits<uint64_t>::max()) 32420b57cec5SDimitry Andric return SendIllFormedResponse(packet, "qXfer packet missing length"); 32430b57cec5SDimitry Andric 32440b57cec5SDimitry Andric // Get a previously constructed buffer if it exists or create it now. 32450b57cec5SDimitry Andric std::string buffer_key = (xfer_object + xfer_action + xfer_annex).str(); 32460b57cec5SDimitry Andric auto buffer_it = m_xfer_buffer_map.find(buffer_key); 32470b57cec5SDimitry Andric if (buffer_it == m_xfer_buffer_map.end()) { 32480b57cec5SDimitry Andric auto buffer_up = ReadXferObject(xfer_object, xfer_annex); 32490b57cec5SDimitry Andric if (!buffer_up) 32500b57cec5SDimitry Andric return SendErrorResponse(buffer_up.takeError()); 32510b57cec5SDimitry Andric buffer_it = m_xfer_buffer_map 32520b57cec5SDimitry Andric .insert(std::make_pair(buffer_key, std::move(*buffer_up))) 32530b57cec5SDimitry Andric .first; 32540b57cec5SDimitry Andric } 32550b57cec5SDimitry Andric 32560b57cec5SDimitry Andric // Send back the response 32570b57cec5SDimitry Andric StreamGDBRemote response; 32580b57cec5SDimitry Andric bool done_with_buffer = false; 32590b57cec5SDimitry Andric llvm::StringRef buffer = buffer_it->second->getBuffer(); 32600b57cec5SDimitry Andric if (xfer_offset >= buffer.size()) { 32610b57cec5SDimitry Andric // We have nothing left to send. Mark the buffer as complete. 32620b57cec5SDimitry Andric response.PutChar('l'); 32630b57cec5SDimitry Andric done_with_buffer = true; 32640b57cec5SDimitry Andric } else { 32650b57cec5SDimitry Andric // Figure out how many bytes are available starting at the given offset. 32660b57cec5SDimitry Andric buffer = buffer.drop_front(xfer_offset); 32670b57cec5SDimitry Andric // Mark the response type according to whether we're reading the remainder 32680b57cec5SDimitry Andric // of the data. 32690b57cec5SDimitry Andric if (xfer_length >= buffer.size()) { 32700b57cec5SDimitry Andric // There will be nothing left to read after this 32710b57cec5SDimitry Andric response.PutChar('l'); 32720b57cec5SDimitry Andric done_with_buffer = true; 32730b57cec5SDimitry Andric } else { 32740b57cec5SDimitry Andric // There will still be bytes to read after this request. 32750b57cec5SDimitry Andric response.PutChar('m'); 32760b57cec5SDimitry Andric buffer = buffer.take_front(xfer_length); 32770b57cec5SDimitry Andric } 32780b57cec5SDimitry Andric // Now write the data in encoded binary form. 32790b57cec5SDimitry Andric response.PutEscapedBytes(buffer.data(), buffer.size()); 32800b57cec5SDimitry Andric } 32810b57cec5SDimitry Andric 32820b57cec5SDimitry Andric if (done_with_buffer) 32830b57cec5SDimitry Andric m_xfer_buffer_map.erase(buffer_it); 32840b57cec5SDimitry Andric 32850b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 32860b57cec5SDimitry Andric } 32870b57cec5SDimitry Andric 32880b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 32890b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( 32900b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 329181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 32920b57cec5SDimitry Andric 32930b57cec5SDimitry Andric // Move past packet name. 32940b57cec5SDimitry Andric packet.SetFilePos(strlen("QSaveRegisterState")); 32950b57cec5SDimitry Andric 32960b57cec5SDimitry Andric // Get the thread to use. 32970b57cec5SDimitry Andric NativeThreadProtocol *thread = GetThreadFromSuffix(packet); 32980b57cec5SDimitry Andric if (!thread) { 32990b57cec5SDimitry Andric if (m_thread_suffix_supported) 33000b57cec5SDimitry Andric return SendIllFormedResponse( 33010b57cec5SDimitry Andric packet, "No thread specified in QSaveRegisterState packet"); 33020b57cec5SDimitry Andric else 33030b57cec5SDimitry Andric return SendIllFormedResponse(packet, 33040b57cec5SDimitry Andric "No thread was is set with the Hg packet"); 33050b57cec5SDimitry Andric } 33060b57cec5SDimitry Andric 33070b57cec5SDimitry Andric // Grab the register context for the thread. 33080b57cec5SDimitry Andric NativeRegisterContext& reg_context = thread->GetRegisterContext(); 33090b57cec5SDimitry Andric 33100b57cec5SDimitry Andric // Save registers to a buffer. 331181ad6265SDimitry Andric WritableDataBufferSP register_data_sp; 33120b57cec5SDimitry Andric Status error = reg_context.ReadAllRegisterValues(register_data_sp); 33130b57cec5SDimitry Andric if (error.Fail()) { 33140b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to save all register values: {1}", 3315fe6060f1SDimitry Andric m_current_process->GetID(), error); 33160b57cec5SDimitry Andric return SendErrorResponse(0x75); 33170b57cec5SDimitry Andric } 33180b57cec5SDimitry Andric 33190b57cec5SDimitry Andric // Allocate a new save id. 33200b57cec5SDimitry Andric const uint32_t save_id = GetNextSavedRegistersID(); 33210b57cec5SDimitry Andric assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) && 33220b57cec5SDimitry Andric "GetNextRegisterSaveID() returned an existing register save id"); 33230b57cec5SDimitry Andric 33240b57cec5SDimitry Andric // Save the register data buffer under the save id. 33250b57cec5SDimitry Andric { 33260b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_saved_registers_mutex); 33270b57cec5SDimitry Andric m_saved_registers_map[save_id] = register_data_sp; 33280b57cec5SDimitry Andric } 33290b57cec5SDimitry Andric 33300b57cec5SDimitry Andric // Write the response. 33310b57cec5SDimitry Andric StreamGDBRemote response; 33320b57cec5SDimitry Andric response.Printf("%" PRIu32, save_id); 33330b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 33340b57cec5SDimitry Andric } 33350b57cec5SDimitry Andric 33360b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 33370b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( 33380b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 333981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 33400b57cec5SDimitry Andric 33410b57cec5SDimitry Andric // Parse out save id. 33420b57cec5SDimitry Andric packet.SetFilePos(strlen("QRestoreRegisterState:")); 33430b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 33440b57cec5SDimitry Andric return SendIllFormedResponse( 33450b57cec5SDimitry Andric packet, "QRestoreRegisterState packet missing register save id"); 33460b57cec5SDimitry Andric 33470b57cec5SDimitry Andric const uint32_t save_id = packet.GetU32(0); 33480b57cec5SDimitry Andric if (save_id == 0) { 33490b57cec5SDimitry Andric LLDB_LOG(log, "QRestoreRegisterState packet has malformed save id, " 33500b57cec5SDimitry Andric "expecting decimal uint32_t"); 33510b57cec5SDimitry Andric return SendErrorResponse(0x76); 33520b57cec5SDimitry Andric } 33530b57cec5SDimitry Andric 33540b57cec5SDimitry Andric // Get the thread to use. 33550b57cec5SDimitry Andric NativeThreadProtocol *thread = GetThreadFromSuffix(packet); 33560b57cec5SDimitry Andric if (!thread) { 33570b57cec5SDimitry Andric if (m_thread_suffix_supported) 33580b57cec5SDimitry Andric return SendIllFormedResponse( 33590b57cec5SDimitry Andric packet, "No thread specified in QRestoreRegisterState packet"); 33600b57cec5SDimitry Andric else 33610b57cec5SDimitry Andric return SendIllFormedResponse(packet, 33620b57cec5SDimitry Andric "No thread was is set with the Hg packet"); 33630b57cec5SDimitry Andric } 33640b57cec5SDimitry Andric 33650b57cec5SDimitry Andric // Grab the register context for the thread. 33660b57cec5SDimitry Andric NativeRegisterContext ®_context = thread->GetRegisterContext(); 33670b57cec5SDimitry Andric 33680b57cec5SDimitry Andric // Retrieve register state buffer, then remove from the list. 33690b57cec5SDimitry Andric DataBufferSP register_data_sp; 33700b57cec5SDimitry Andric { 33710b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_saved_registers_mutex); 33720b57cec5SDimitry Andric 33730b57cec5SDimitry Andric // Find the register set buffer for the given save id. 33740b57cec5SDimitry Andric auto it = m_saved_registers_map.find(save_id); 33750b57cec5SDimitry Andric if (it == m_saved_registers_map.end()) { 33760b57cec5SDimitry Andric LLDB_LOG(log, 33770b57cec5SDimitry Andric "pid {0} does not have a register set save buffer for id {1}", 3378fe6060f1SDimitry Andric m_current_process->GetID(), save_id); 33790b57cec5SDimitry Andric return SendErrorResponse(0x77); 33800b57cec5SDimitry Andric } 33810b57cec5SDimitry Andric register_data_sp = it->second; 33820b57cec5SDimitry Andric 33830b57cec5SDimitry Andric // Remove it from the map. 33840b57cec5SDimitry Andric m_saved_registers_map.erase(it); 33850b57cec5SDimitry Andric } 33860b57cec5SDimitry Andric 33870b57cec5SDimitry Andric Status error = reg_context.WriteAllRegisterValues(register_data_sp); 33880b57cec5SDimitry Andric if (error.Fail()) { 33890b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to restore all register values: {1}", 3390fe6060f1SDimitry Andric m_current_process->GetID(), error); 33910b57cec5SDimitry Andric return SendErrorResponse(0x77); 33920b57cec5SDimitry Andric } 33930b57cec5SDimitry Andric 33940b57cec5SDimitry Andric return SendOKResponse(); 33950b57cec5SDimitry Andric } 33960b57cec5SDimitry Andric 33970b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 33980b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttach( 33990b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 340081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 34010b57cec5SDimitry Andric 34020b57cec5SDimitry Andric // Consume the ';' after vAttach. 34030b57cec5SDimitry Andric packet.SetFilePos(strlen("vAttach")); 34040b57cec5SDimitry Andric if (!packet.GetBytesLeft() || packet.GetChar() != ';') 34050b57cec5SDimitry Andric return SendIllFormedResponse(packet, "vAttach missing expected ';'"); 34060b57cec5SDimitry Andric 34070b57cec5SDimitry Andric // Grab the PID to which we will attach (assume hex encoding). 34080b57cec5SDimitry Andric lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); 34090b57cec5SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 34100b57cec5SDimitry Andric return SendIllFormedResponse(packet, 34110b57cec5SDimitry Andric "vAttach failed to parse the process id"); 34120b57cec5SDimitry Andric 34130b57cec5SDimitry Andric // Attempt to attach. 34149dba64beSDimitry Andric LLDB_LOGF(log, 34159dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s attempting to attach to " 34160b57cec5SDimitry Andric "pid %" PRIu64, 34170b57cec5SDimitry Andric __FUNCTION__, pid); 34180b57cec5SDimitry Andric 34190b57cec5SDimitry Andric Status error = AttachToProcess(pid); 34200b57cec5SDimitry Andric 34210b57cec5SDimitry Andric if (error.Fail()) { 34229dba64beSDimitry Andric LLDB_LOGF(log, 34239dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed to attach to " 34240b57cec5SDimitry Andric "pid %" PRIu64 ": %s\n", 34250b57cec5SDimitry Andric __FUNCTION__, pid, error.AsCString()); 34260b57cec5SDimitry Andric return SendErrorResponse(error); 34270b57cec5SDimitry Andric } 34280b57cec5SDimitry Andric 34290b57cec5SDimitry Andric // Notify we attached by sending a stop packet. 343081ad6265SDimitry Andric assert(m_current_process); 343181ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 343281ad6265SDimitry Andric m_current_process->GetState(), 343381ad6265SDimitry Andric /*force_synchronous=*/false); 34340b57cec5SDimitry Andric } 34350b57cec5SDimitry Andric 34360b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 3437e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachWait( 3438e8d8bef9SDimitry Andric StringExtractorGDBRemote &packet) { 343981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3440e8d8bef9SDimitry Andric 3441e8d8bef9SDimitry Andric // Consume the ';' after the identifier. 3442e8d8bef9SDimitry Andric packet.SetFilePos(strlen("vAttachWait")); 3443e8d8bef9SDimitry Andric 3444e8d8bef9SDimitry Andric if (!packet.GetBytesLeft() || packet.GetChar() != ';') 3445e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "vAttachWait missing expected ';'"); 3446e8d8bef9SDimitry Andric 3447e8d8bef9SDimitry Andric // Allocate the buffer for the process name from vAttachWait. 3448e8d8bef9SDimitry Andric std::string process_name; 3449e8d8bef9SDimitry Andric if (!packet.GetHexByteString(process_name)) 3450e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, 3451e8d8bef9SDimitry Andric "vAttachWait failed to parse process name"); 3452e8d8bef9SDimitry Andric 3453e8d8bef9SDimitry Andric LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name); 3454e8d8bef9SDimitry Andric 3455e8d8bef9SDimitry Andric Status error = AttachWaitProcess(process_name, false); 3456e8d8bef9SDimitry Andric if (error.Fail()) { 3457e8d8bef9SDimitry Andric LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name, 3458e8d8bef9SDimitry Andric error); 3459e8d8bef9SDimitry Andric return SendErrorResponse(error); 3460e8d8bef9SDimitry Andric } 3461e8d8bef9SDimitry Andric 3462e8d8bef9SDimitry Andric // Notify we attached by sending a stop packet. 346381ad6265SDimitry Andric assert(m_current_process); 346481ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 346581ad6265SDimitry Andric m_current_process->GetState(), 346681ad6265SDimitry Andric /*force_synchronous=*/false); 3467e8d8bef9SDimitry Andric } 3468e8d8bef9SDimitry Andric 3469e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 3470e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported( 3471e8d8bef9SDimitry Andric StringExtractorGDBRemote &packet) { 3472e8d8bef9SDimitry Andric return SendOKResponse(); 3473e8d8bef9SDimitry Andric } 3474e8d8bef9SDimitry Andric 3475e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 3476e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait( 3477e8d8bef9SDimitry Andric StringExtractorGDBRemote &packet) { 347881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3479e8d8bef9SDimitry Andric 3480e8d8bef9SDimitry Andric // Consume the ';' after the identifier. 3481e8d8bef9SDimitry Andric packet.SetFilePos(strlen("vAttachOrWait")); 3482e8d8bef9SDimitry Andric 3483e8d8bef9SDimitry Andric if (!packet.GetBytesLeft() || packet.GetChar() != ';') 3484e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "vAttachOrWait missing expected ';'"); 3485e8d8bef9SDimitry Andric 3486e8d8bef9SDimitry Andric // Allocate the buffer for the process name from vAttachWait. 3487e8d8bef9SDimitry Andric std::string process_name; 3488e8d8bef9SDimitry Andric if (!packet.GetHexByteString(process_name)) 3489e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, 3490e8d8bef9SDimitry Andric "vAttachOrWait failed to parse process name"); 3491e8d8bef9SDimitry Andric 3492e8d8bef9SDimitry Andric LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name); 3493e8d8bef9SDimitry Andric 3494e8d8bef9SDimitry Andric Status error = AttachWaitProcess(process_name, true); 3495e8d8bef9SDimitry Andric if (error.Fail()) { 3496e8d8bef9SDimitry Andric LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name, 3497e8d8bef9SDimitry Andric error); 3498e8d8bef9SDimitry Andric return SendErrorResponse(error); 3499e8d8bef9SDimitry Andric } 3500e8d8bef9SDimitry Andric 3501e8d8bef9SDimitry Andric // Notify we attached by sending a stop packet. 350281ad6265SDimitry Andric assert(m_current_process); 350381ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 350481ad6265SDimitry Andric m_current_process->GetState(), 350581ad6265SDimitry Andric /*force_synchronous=*/false); 3506e8d8bef9SDimitry Andric } 3507e8d8bef9SDimitry Andric 3508e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 3509349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vRun( 3510349cc55cSDimitry Andric StringExtractorGDBRemote &packet) { 351181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3512349cc55cSDimitry Andric 3513349cc55cSDimitry Andric llvm::StringRef s = packet.GetStringRef(); 3514349cc55cSDimitry Andric if (!s.consume_front("vRun;")) 3515349cc55cSDimitry Andric return SendErrorResponse(8); 3516349cc55cSDimitry Andric 3517349cc55cSDimitry Andric llvm::SmallVector<llvm::StringRef, 16> argv; 3518349cc55cSDimitry Andric s.split(argv, ';'); 3519349cc55cSDimitry Andric 3520349cc55cSDimitry Andric for (llvm::StringRef hex_arg : argv) { 3521349cc55cSDimitry Andric StringExtractor arg_ext{hex_arg}; 3522349cc55cSDimitry Andric std::string arg; 3523349cc55cSDimitry Andric arg_ext.GetHexByteString(arg); 3524349cc55cSDimitry Andric m_process_launch_info.GetArguments().AppendArgument(arg); 3525349cc55cSDimitry Andric LLDB_LOGF(log, "LLGSPacketHandler::%s added arg: \"%s\"", __FUNCTION__, 3526349cc55cSDimitry Andric arg.c_str()); 3527349cc55cSDimitry Andric } 3528349cc55cSDimitry Andric 3529bdd1243dSDimitry Andric if (argv.empty()) 3530bdd1243dSDimitry Andric return SendErrorResponse(Status("No arguments")); 3531349cc55cSDimitry Andric m_process_launch_info.GetExecutableFile().SetFile( 3532349cc55cSDimitry Andric m_process_launch_info.GetArguments()[0].ref(), FileSpec::Style::native); 3533349cc55cSDimitry Andric m_process_launch_error = LaunchProcess(); 3534bdd1243dSDimitry Andric if (m_process_launch_error.Fail()) 3535bdd1243dSDimitry Andric return SendErrorResponse(m_process_launch_error); 353681ad6265SDimitry Andric assert(m_current_process); 353781ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 353881ad6265SDimitry Andric m_current_process->GetState(), 353981ad6265SDimitry Andric /*force_synchronous=*/true); 354081ad6265SDimitry Andric } 3541349cc55cSDimitry Andric 3542349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult 35430b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { 354481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3545fcaf7f86SDimitry Andric if (!m_non_stop) 35460b57cec5SDimitry Andric StopSTDIOForwarding(); 35470b57cec5SDimitry Andric 35480b57cec5SDimitry Andric lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 35490b57cec5SDimitry Andric 35500b57cec5SDimitry Andric // Consume the ';' after D. 35510b57cec5SDimitry Andric packet.SetFilePos(1); 35520b57cec5SDimitry Andric if (packet.GetBytesLeft()) { 35530b57cec5SDimitry Andric if (packet.GetChar() != ';') 35540b57cec5SDimitry Andric return SendIllFormedResponse(packet, "D missing expected ';'"); 35550b57cec5SDimitry Andric 35560b57cec5SDimitry Andric // Grab the PID from which we will detach (assume hex encoding). 35570b57cec5SDimitry Andric pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); 35580b57cec5SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 35590b57cec5SDimitry Andric return SendIllFormedResponse(packet, "D failed to parse the process id"); 35600b57cec5SDimitry Andric } 35610b57cec5SDimitry Andric 3562fe6060f1SDimitry Andric // Detach forked children if their PID was specified *or* no PID was requested 3563fe6060f1SDimitry Andric // (i.e. detach-all packet). 3564fe6060f1SDimitry Andric llvm::Error detach_error = llvm::Error::success(); 3565fe6060f1SDimitry Andric bool detached = false; 3566fe6060f1SDimitry Andric for (auto it = m_debugged_processes.begin(); 3567fe6060f1SDimitry Andric it != m_debugged_processes.end();) { 3568fe6060f1SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) { 356981ad6265SDimitry Andric LLDB_LOGF(log, 357081ad6265SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s detaching %" PRId64, 357181ad6265SDimitry Andric __FUNCTION__, it->first); 3572fcaf7f86SDimitry Andric if (llvm::Error e = it->second.process_up->Detach().ToError()) 3573fe6060f1SDimitry Andric detach_error = llvm::joinErrors(std::move(detach_error), std::move(e)); 3574fe6060f1SDimitry Andric else { 3575fcaf7f86SDimitry Andric if (it->second.process_up.get() == m_current_process) 3576fe6060f1SDimitry Andric m_current_process = nullptr; 3577fcaf7f86SDimitry Andric if (it->second.process_up.get() == m_continue_process) 3578fe6060f1SDimitry Andric m_continue_process = nullptr; 3579fe6060f1SDimitry Andric it = m_debugged_processes.erase(it); 3580fe6060f1SDimitry Andric detached = true; 3581fe6060f1SDimitry Andric continue; 3582fe6060f1SDimitry Andric } 3583fe6060f1SDimitry Andric } 3584fe6060f1SDimitry Andric ++it; 35850b57cec5SDimitry Andric } 35860b57cec5SDimitry Andric 3587fe6060f1SDimitry Andric if (detach_error) 3588fe6060f1SDimitry Andric return SendErrorResponse(std::move(detach_error)); 3589fe6060f1SDimitry Andric if (!detached) 3590fe6060f1SDimitry Andric return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid)); 35910b57cec5SDimitry Andric return SendOKResponse(); 35920b57cec5SDimitry Andric } 35930b57cec5SDimitry Andric 35940b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 35950b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo( 35960b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 359781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 359881ad6265SDimitry Andric 359981ad6265SDimitry Andric if (!m_current_process || 360081ad6265SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 360181ad6265SDimitry Andric return SendErrorResponse(50); 36020b57cec5SDimitry Andric 36030b57cec5SDimitry Andric packet.SetFilePos(strlen("qThreadStopInfo")); 3604fe6060f1SDimitry Andric const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID); 36050b57cec5SDimitry Andric if (tid == LLDB_INVALID_THREAD_ID) { 36069dba64beSDimitry Andric LLDB_LOGF(log, 36079dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, could not " 36080b57cec5SDimitry Andric "parse thread id from request \"%s\"", 36099dba64beSDimitry Andric __FUNCTION__, packet.GetStringRef().data()); 36100b57cec5SDimitry Andric return SendErrorResponse(0x15); 36110b57cec5SDimitry Andric } 361281ad6265SDimitry Andric return SendStopReplyPacketForThread(*m_current_process, tid, 361381ad6265SDimitry Andric /*force_synchronous=*/true); 36140b57cec5SDimitry Andric } 36150b57cec5SDimitry Andric 36160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 36170b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( 36180b57cec5SDimitry Andric StringExtractorGDBRemote &) { 361981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 36200b57cec5SDimitry Andric 36210b57cec5SDimitry Andric // Ensure we have a debugged process. 3622fe6060f1SDimitry Andric if (!m_current_process || 3623fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 36240b57cec5SDimitry Andric return SendErrorResponse(50); 3625fe6060f1SDimitry Andric LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID()); 36260b57cec5SDimitry Andric 36270b57cec5SDimitry Andric StreamString response; 36280b57cec5SDimitry Andric const bool threads_with_valid_stop_info_only = false; 3629fe6060f1SDimitry Andric llvm::Expected<json::Value> threads_info = 3630fe6060f1SDimitry Andric GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only); 36319dba64beSDimitry Andric if (!threads_info) { 3632480093f4SDimitry Andric LLDB_LOG_ERROR(log, threads_info.takeError(), 3633480093f4SDimitry Andric "failed to prepare a packet for pid {1}: {0}", 3634fe6060f1SDimitry Andric m_current_process->GetID()); 36350b57cec5SDimitry Andric return SendErrorResponse(52); 36360b57cec5SDimitry Andric } 36370b57cec5SDimitry Andric 36389dba64beSDimitry Andric response.AsRawOstream() << *threads_info; 36390b57cec5SDimitry Andric StreamGDBRemote escaped_response; 36400b57cec5SDimitry Andric escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); 36410b57cec5SDimitry Andric return SendPacketNoLock(escaped_response.GetString()); 36420b57cec5SDimitry Andric } 36430b57cec5SDimitry Andric 36440b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 36450b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( 36460b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 36470b57cec5SDimitry Andric // Fail if we don't have a current process. 3648fe6060f1SDimitry Andric if (!m_current_process || 3649fe6060f1SDimitry Andric m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) 36500b57cec5SDimitry Andric return SendErrorResponse(68); 36510b57cec5SDimitry Andric 36520b57cec5SDimitry Andric packet.SetFilePos(strlen("qWatchpointSupportInfo")); 36530b57cec5SDimitry Andric if (packet.GetBytesLeft() == 0) 36540b57cec5SDimitry Andric return SendOKResponse(); 36550b57cec5SDimitry Andric if (packet.GetChar() != ':') 36560b57cec5SDimitry Andric return SendErrorResponse(67); 36570b57cec5SDimitry Andric 3658fe6060f1SDimitry Andric auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo(); 36590b57cec5SDimitry Andric 36600b57cec5SDimitry Andric StreamGDBRemote response; 3661bdd1243dSDimitry Andric if (hw_debug_cap == std::nullopt) 36620b57cec5SDimitry Andric response.Printf("num:0;"); 36630b57cec5SDimitry Andric else 36640b57cec5SDimitry Andric response.Printf("num:%d;", hw_debug_cap->second); 36650b57cec5SDimitry Andric 36660b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 36670b57cec5SDimitry Andric } 36680b57cec5SDimitry Andric 36690b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 36700b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( 36710b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 36720b57cec5SDimitry Andric // Fail if we don't have a current process. 3673fe6060f1SDimitry Andric if (!m_current_process || 3674fe6060f1SDimitry Andric m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) 36750b57cec5SDimitry Andric return SendErrorResponse(67); 36760b57cec5SDimitry Andric 36770b57cec5SDimitry Andric packet.SetFilePos(strlen("qFileLoadAddress:")); 36780b57cec5SDimitry Andric if (packet.GetBytesLeft() == 0) 36790b57cec5SDimitry Andric return SendErrorResponse(68); 36800b57cec5SDimitry Andric 36810b57cec5SDimitry Andric std::string file_name; 36820b57cec5SDimitry Andric packet.GetHexByteString(file_name); 36830b57cec5SDimitry Andric 36840b57cec5SDimitry Andric lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS; 36850b57cec5SDimitry Andric Status error = 3686fe6060f1SDimitry Andric m_current_process->GetFileLoadAddress(file_name, file_load_address); 36870b57cec5SDimitry Andric if (error.Fail()) 36880b57cec5SDimitry Andric return SendErrorResponse(69); 36890b57cec5SDimitry Andric 36900b57cec5SDimitry Andric if (file_load_address == LLDB_INVALID_ADDRESS) 36910b57cec5SDimitry Andric return SendErrorResponse(1); // File not loaded 36920b57cec5SDimitry Andric 36930b57cec5SDimitry Andric StreamGDBRemote response; 36940b57cec5SDimitry Andric response.PutHex64(file_load_address); 36950b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 36960b57cec5SDimitry Andric } 36970b57cec5SDimitry Andric 36980b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 36990b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QPassSignals( 37000b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 37010b57cec5SDimitry Andric std::vector<int> signals; 37020b57cec5SDimitry Andric packet.SetFilePos(strlen("QPassSignals:")); 37030b57cec5SDimitry Andric 37040b57cec5SDimitry Andric // Read sequence of hex signal numbers divided by a semicolon and optionally 37050b57cec5SDimitry Andric // spaces. 37060b57cec5SDimitry Andric while (packet.GetBytesLeft() > 0) { 37070b57cec5SDimitry Andric int signal = packet.GetS32(-1, 16); 37080b57cec5SDimitry Andric if (signal < 0) 37090b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Failed to parse signal number."); 37100b57cec5SDimitry Andric signals.push_back(signal); 37110b57cec5SDimitry Andric 37120b57cec5SDimitry Andric packet.SkipSpaces(); 37130b57cec5SDimitry Andric char separator = packet.GetChar(); 37140b57cec5SDimitry Andric if (separator == '\0') 37150b57cec5SDimitry Andric break; // End of string 37160b57cec5SDimitry Andric if (separator != ';') 37170b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Invalid separator," 37180b57cec5SDimitry Andric " expected semicolon."); 37190b57cec5SDimitry Andric } 37200b57cec5SDimitry Andric 37210b57cec5SDimitry Andric // Fail if we don't have a current process. 3722fe6060f1SDimitry Andric if (!m_current_process) 37230b57cec5SDimitry Andric return SendErrorResponse(68); 37240b57cec5SDimitry Andric 3725fe6060f1SDimitry Andric Status error = m_current_process->IgnoreSignals(signals); 37260b57cec5SDimitry Andric if (error.Fail()) 37270b57cec5SDimitry Andric return SendErrorResponse(69); 37280b57cec5SDimitry Andric 37290b57cec5SDimitry Andric return SendOKResponse(); 37300b57cec5SDimitry Andric } 37310b57cec5SDimitry Andric 3732fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult 3733fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemTags( 3734fe6060f1SDimitry Andric StringExtractorGDBRemote &packet) { 373581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3736fe6060f1SDimitry Andric 3737fe6060f1SDimitry Andric // Ensure we have a process. 3738fe6060f1SDimitry Andric if (!m_current_process || 3739fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 3740fe6060f1SDimitry Andric LLDB_LOGF( 3741fe6060f1SDimitry Andric log, 3742fe6060f1SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 3743fe6060f1SDimitry Andric __FUNCTION__); 3744fe6060f1SDimitry Andric return SendErrorResponse(1); 3745fe6060f1SDimitry Andric } 3746fe6060f1SDimitry Andric 3747fe6060f1SDimitry Andric // We are expecting 3748fe6060f1SDimitry Andric // qMemTags:<hex address>,<hex length>:<hex type> 3749fe6060f1SDimitry Andric 3750fe6060f1SDimitry Andric // Address 3751fe6060f1SDimitry Andric packet.SetFilePos(strlen("qMemTags:")); 3752fe6060f1SDimitry Andric const char *current_char = packet.Peek(); 3753fe6060f1SDimitry Andric if (!current_char || *current_char == ',') 3754fe6060f1SDimitry Andric return SendIllFormedResponse(packet, "Missing address in qMemTags packet"); 3755fe6060f1SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0); 3756fe6060f1SDimitry Andric 3757fe6060f1SDimitry Andric // Length 3758fe6060f1SDimitry Andric char previous_char = packet.GetChar(); 3759fe6060f1SDimitry Andric current_char = packet.Peek(); 3760fe6060f1SDimitry Andric // If we don't have a separator or the length field is empty 3761fe6060f1SDimitry Andric if (previous_char != ',' || (current_char && *current_char == ':')) 3762fe6060f1SDimitry Andric return SendIllFormedResponse(packet, 3763fe6060f1SDimitry Andric "Invalid addr,length pair in qMemTags packet"); 3764fe6060f1SDimitry Andric 3765fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1) 3766fe6060f1SDimitry Andric return SendIllFormedResponse( 3767fe6060f1SDimitry Andric packet, "Too short qMemtags: packet (looking for length)"); 3768fe6060f1SDimitry Andric const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0); 3769fe6060f1SDimitry Andric 3770fe6060f1SDimitry Andric // Type 3771fe6060f1SDimitry Andric const char *invalid_type_err = "Invalid type field in qMemTags: packet"; 3772fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') 3773fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 3774fe6060f1SDimitry Andric 37756e75b2fbSDimitry Andric // Type is a signed integer but packed into the packet as its raw bytes. 37766e75b2fbSDimitry Andric // However, our GetU64 uses strtoull which allows +/-. We do not want this. 37776e75b2fbSDimitry Andric const char *first_type_char = packet.Peek(); 37786e75b2fbSDimitry Andric if (first_type_char && (*first_type_char == '+' || *first_type_char == '-')) 37796e75b2fbSDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 37806e75b2fbSDimitry Andric 37816e75b2fbSDimitry Andric // Extract type as unsigned then cast to signed. 37826e75b2fbSDimitry Andric // Using a uint64_t here so that we have some value outside of the 32 bit 37836e75b2fbSDimitry Andric // range to use as the invalid return value. 37846e75b2fbSDimitry Andric uint64_t raw_type = 37856e75b2fbSDimitry Andric packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16); 37866e75b2fbSDimitry Andric 37876e75b2fbSDimitry Andric if ( // Make sure the cast below would be valid 37886e75b2fbSDimitry Andric raw_type > std::numeric_limits<uint32_t>::max() || 3789fe6060f1SDimitry Andric // To catch inputs like "123aardvark" that will parse but clearly aren't 3790fe6060f1SDimitry Andric // valid in this case. 3791fe6060f1SDimitry Andric packet.GetBytesLeft()) { 3792fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 3793fe6060f1SDimitry Andric } 3794fe6060f1SDimitry Andric 37956e75b2fbSDimitry Andric // First narrow to 32 bits otherwise the copy into type would take 37966e75b2fbSDimitry Andric // the wrong 4 bytes on big endian. 37976e75b2fbSDimitry Andric uint32_t raw_type_32 = raw_type; 37986e75b2fbSDimitry Andric int32_t type = reinterpret_cast<int32_t &>(raw_type_32); 37996e75b2fbSDimitry Andric 3800fe6060f1SDimitry Andric StreamGDBRemote response; 3801fe6060f1SDimitry Andric std::vector<uint8_t> tags; 3802fe6060f1SDimitry Andric Status error = m_current_process->ReadMemoryTags(type, addr, length, tags); 3803fe6060f1SDimitry Andric if (error.Fail()) 3804fe6060f1SDimitry Andric return SendErrorResponse(1); 3805fe6060f1SDimitry Andric 3806fe6060f1SDimitry Andric // This m is here in case we want to support multi part replies in the future. 3807fe6060f1SDimitry Andric // In the same manner as qfThreadInfo/qsThreadInfo. 3808fe6060f1SDimitry Andric response.PutChar('m'); 3809fe6060f1SDimitry Andric response.PutBytesAsRawHex8(tags.data(), tags.size()); 3810fe6060f1SDimitry Andric return SendPacketNoLock(response.GetString()); 3811fe6060f1SDimitry Andric } 3812fe6060f1SDimitry Andric 3813fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult 3814fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QMemTags( 3815fe6060f1SDimitry Andric StringExtractorGDBRemote &packet) { 381681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3817fe6060f1SDimitry Andric 3818fe6060f1SDimitry Andric // Ensure we have a process. 3819fe6060f1SDimitry Andric if (!m_current_process || 3820fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 3821fe6060f1SDimitry Andric LLDB_LOGF( 3822fe6060f1SDimitry Andric log, 3823fe6060f1SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 3824fe6060f1SDimitry Andric __FUNCTION__); 3825fe6060f1SDimitry Andric return SendErrorResponse(1); 3826fe6060f1SDimitry Andric } 3827fe6060f1SDimitry Andric 3828fe6060f1SDimitry Andric // We are expecting 3829fe6060f1SDimitry Andric // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes> 3830fe6060f1SDimitry Andric 3831fe6060f1SDimitry Andric // Address 3832fe6060f1SDimitry Andric packet.SetFilePos(strlen("QMemTags:")); 3833fe6060f1SDimitry Andric const char *current_char = packet.Peek(); 3834fe6060f1SDimitry Andric if (!current_char || *current_char == ',') 3835fe6060f1SDimitry Andric return SendIllFormedResponse(packet, "Missing address in QMemTags packet"); 3836fe6060f1SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0); 3837fe6060f1SDimitry Andric 3838fe6060f1SDimitry Andric // Length 3839fe6060f1SDimitry Andric char previous_char = packet.GetChar(); 3840fe6060f1SDimitry Andric current_char = packet.Peek(); 3841fe6060f1SDimitry Andric // If we don't have a separator or the length field is empty 3842fe6060f1SDimitry Andric if (previous_char != ',' || (current_char && *current_char == ':')) 3843fe6060f1SDimitry Andric return SendIllFormedResponse(packet, 3844fe6060f1SDimitry Andric "Invalid addr,length pair in QMemTags packet"); 3845fe6060f1SDimitry Andric 3846fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1) 3847fe6060f1SDimitry Andric return SendIllFormedResponse( 3848fe6060f1SDimitry Andric packet, "Too short QMemtags: packet (looking for length)"); 3849fe6060f1SDimitry Andric const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0); 3850fe6060f1SDimitry Andric 3851fe6060f1SDimitry Andric // Type 3852fe6060f1SDimitry Andric const char *invalid_type_err = "Invalid type field in QMemTags: packet"; 3853fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') 3854fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 3855fe6060f1SDimitry Andric 3856fe6060f1SDimitry Andric // Our GetU64 uses strtoull which allows leading +/-, we don't want that. 3857fe6060f1SDimitry Andric const char *first_type_char = packet.Peek(); 3858fe6060f1SDimitry Andric if (first_type_char && (*first_type_char == '+' || *first_type_char == '-')) 3859fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 3860fe6060f1SDimitry Andric 3861fe6060f1SDimitry Andric // The type is a signed integer but is in the packet as its raw bytes. 3862fe6060f1SDimitry Andric // So parse first as unsigned then cast to signed later. 3863fe6060f1SDimitry Andric // We extract to 64 bit, even though we only expect 32, so that we've 3864fe6060f1SDimitry Andric // got some invalid value we can check for. 3865fe6060f1SDimitry Andric uint64_t raw_type = 3866fe6060f1SDimitry Andric packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16); 3867fe6060f1SDimitry Andric if (raw_type > std::numeric_limits<uint32_t>::max()) 3868fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 38696e75b2fbSDimitry Andric 38706e75b2fbSDimitry Andric // First narrow to 32 bits. Otherwise the copy below would get the wrong 38716e75b2fbSDimitry Andric // 4 bytes on big endian. 38726e75b2fbSDimitry Andric uint32_t raw_type_32 = raw_type; 38736e75b2fbSDimitry Andric int32_t type = reinterpret_cast<int32_t &>(raw_type_32); 3874fe6060f1SDimitry Andric 3875fe6060f1SDimitry Andric // Tag data 3876fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') 3877fe6060f1SDimitry Andric return SendIllFormedResponse(packet, 3878fe6060f1SDimitry Andric "Missing tag data in QMemTags: packet"); 3879fe6060f1SDimitry Andric 3880fe6060f1SDimitry Andric // Must be 2 chars per byte 3881fe6060f1SDimitry Andric const char *invalid_data_err = "Invalid tag data in QMemTags: packet"; 3882fe6060f1SDimitry Andric if (packet.GetBytesLeft() % 2) 3883fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_data_err); 3884fe6060f1SDimitry Andric 3885fe6060f1SDimitry Andric // This is bytes here and is unpacked into target specific tags later 3886fe6060f1SDimitry Andric // We cannot assume that number of bytes == length here because the server 3887fe6060f1SDimitry Andric // can repeat tags to fill a given range. 3888fe6060f1SDimitry Andric std::vector<uint8_t> tag_data; 3889fe6060f1SDimitry Andric // Zero length writes will not have any tag data 3890fe6060f1SDimitry Andric // (but we pass them on because it will still check that tagging is enabled) 3891fe6060f1SDimitry Andric if (packet.GetBytesLeft()) { 3892fe6060f1SDimitry Andric size_t byte_count = packet.GetBytesLeft() / 2; 3893fe6060f1SDimitry Andric tag_data.resize(byte_count); 3894fe6060f1SDimitry Andric size_t converted_bytes = packet.GetHexBytes(tag_data, 0); 3895fe6060f1SDimitry Andric if (converted_bytes != byte_count) { 3896fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_data_err); 3897fe6060f1SDimitry Andric } 3898fe6060f1SDimitry Andric } 3899fe6060f1SDimitry Andric 3900fe6060f1SDimitry Andric Status status = 3901fe6060f1SDimitry Andric m_current_process->WriteMemoryTags(type, addr, length, tag_data); 3902fe6060f1SDimitry Andric return status.Success() ? SendOKResponse() : SendErrorResponse(1); 3903fe6060f1SDimitry Andric } 3904fe6060f1SDimitry Andric 3905349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult 3906349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qSaveCore( 3907349cc55cSDimitry Andric StringExtractorGDBRemote &packet) { 3908349cc55cSDimitry Andric // Fail if we don't have a current process. 3909349cc55cSDimitry Andric if (!m_current_process || 3910349cc55cSDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 3911349cc55cSDimitry Andric return SendErrorResponse(Status("Process not running.")); 3912349cc55cSDimitry Andric 3913349cc55cSDimitry Andric std::string path_hint; 3914349cc55cSDimitry Andric 3915349cc55cSDimitry Andric StringRef packet_str{packet.GetStringRef()}; 3916349cc55cSDimitry Andric assert(packet_str.startswith("qSaveCore")); 3917349cc55cSDimitry Andric if (packet_str.consume_front("qSaveCore;")) { 3918349cc55cSDimitry Andric for (auto x : llvm::split(packet_str, ';')) { 3919349cc55cSDimitry Andric if (x.consume_front("path-hint:")) 3920349cc55cSDimitry Andric StringExtractor(x).GetHexByteString(path_hint); 3921349cc55cSDimitry Andric else 3922349cc55cSDimitry Andric return SendErrorResponse(Status("Unsupported qSaveCore option")); 3923349cc55cSDimitry Andric } 3924349cc55cSDimitry Andric } 3925349cc55cSDimitry Andric 3926349cc55cSDimitry Andric llvm::Expected<std::string> ret = m_current_process->SaveCore(path_hint); 3927349cc55cSDimitry Andric if (!ret) 3928349cc55cSDimitry Andric return SendErrorResponse(ret.takeError()); 3929349cc55cSDimitry Andric 3930349cc55cSDimitry Andric StreamString response; 3931349cc55cSDimitry Andric response.PutCString("core-path:"); 3932349cc55cSDimitry Andric response.PutStringAsRawHex8(ret.get()); 3933349cc55cSDimitry Andric return SendPacketNoLock(response.GetString()); 3934349cc55cSDimitry Andric } 3935349cc55cSDimitry Andric 393681ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 393781ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QNonStop( 393881ad6265SDimitry Andric StringExtractorGDBRemote &packet) { 3939fcaf7f86SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3940fcaf7f86SDimitry Andric 394181ad6265SDimitry Andric StringRef packet_str{packet.GetStringRef()}; 394281ad6265SDimitry Andric assert(packet_str.startswith("QNonStop:")); 394381ad6265SDimitry Andric packet_str.consume_front("QNonStop:"); 394481ad6265SDimitry Andric if (packet_str == "0") { 3945fcaf7f86SDimitry Andric if (m_non_stop) 3946fcaf7f86SDimitry Andric StopSTDIOForwarding(); 3947fcaf7f86SDimitry Andric for (auto &process_it : m_debugged_processes) { 3948fcaf7f86SDimitry Andric if (process_it.second.process_up->IsRunning()) { 3949fcaf7f86SDimitry Andric assert(m_non_stop); 3950fcaf7f86SDimitry Andric Status error = process_it.second.process_up->Interrupt(); 3951fcaf7f86SDimitry Andric if (error.Fail()) { 3952fcaf7f86SDimitry Andric LLDB_LOG(log, 3953fcaf7f86SDimitry Andric "while disabling nonstop, failed to halt process {0}: {1}", 3954fcaf7f86SDimitry Andric process_it.first, error); 3955fcaf7f86SDimitry Andric return SendErrorResponse(0x41); 3956fcaf7f86SDimitry Andric } 3957fcaf7f86SDimitry Andric // we must not send stop reasons after QNonStop 3958fcaf7f86SDimitry Andric m_disabling_non_stop = true; 3959fcaf7f86SDimitry Andric } 3960fcaf7f86SDimitry Andric } 3961fcaf7f86SDimitry Andric m_stdio_notification_queue.clear(); 3962fcaf7f86SDimitry Andric m_stop_notification_queue.clear(); 396381ad6265SDimitry Andric m_non_stop = false; 3964fcaf7f86SDimitry Andric // If we are stopping anything, defer sending the OK response until we're 3965fcaf7f86SDimitry Andric // done. 3966fcaf7f86SDimitry Andric if (m_disabling_non_stop) 3967fcaf7f86SDimitry Andric return PacketResult::Success; 396881ad6265SDimitry Andric } else if (packet_str == "1") { 3969fcaf7f86SDimitry Andric if (!m_non_stop) 3970fcaf7f86SDimitry Andric StartSTDIOForwarding(); 397181ad6265SDimitry Andric m_non_stop = true; 397281ad6265SDimitry Andric } else 397381ad6265SDimitry Andric return SendErrorResponse(Status("Invalid QNonStop packet")); 397481ad6265SDimitry Andric return SendOKResponse(); 397581ad6265SDimitry Andric } 397681ad6265SDimitry Andric 397781ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 3978fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::HandleNotificationAck( 3979fcaf7f86SDimitry Andric std::deque<std::string> &queue) { 3980fcaf7f86SDimitry Andric // Per the protocol, the first message put into the queue is sent 3981fcaf7f86SDimitry Andric // immediately. However, it remains the queue until the client ACKs it -- 3982fcaf7f86SDimitry Andric // then we pop it and send the next message. The process repeats until 3983fcaf7f86SDimitry Andric // the last message in the queue is ACK-ed, in which case the packet sends 3984fcaf7f86SDimitry Andric // an OK response. 3985fcaf7f86SDimitry Andric if (queue.empty()) 3986fcaf7f86SDimitry Andric return SendErrorResponse(Status("No pending notification to ack")); 3987fcaf7f86SDimitry Andric queue.pop_front(); 3988fcaf7f86SDimitry Andric if (!queue.empty()) 3989fcaf7f86SDimitry Andric return SendPacketNoLock(queue.front()); 3990fcaf7f86SDimitry Andric return SendOKResponse(); 3991fcaf7f86SDimitry Andric } 3992fcaf7f86SDimitry Andric 3993fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult 3994fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStdio( 3995fcaf7f86SDimitry Andric StringExtractorGDBRemote &packet) { 3996fcaf7f86SDimitry Andric return HandleNotificationAck(m_stdio_notification_queue); 3997fcaf7f86SDimitry Andric } 3998fcaf7f86SDimitry Andric 3999fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult 400081ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStopped( 400181ad6265SDimitry Andric StringExtractorGDBRemote &packet) { 4002fcaf7f86SDimitry Andric PacketResult ret = HandleNotificationAck(m_stop_notification_queue); 400381ad6265SDimitry Andric // If this was the last notification and all the processes exited, 400481ad6265SDimitry Andric // terminate the server. 4005fcaf7f86SDimitry Andric if (m_stop_notification_queue.empty() && m_debugged_processes.empty()) { 400681ad6265SDimitry Andric m_exit_now = true; 400781ad6265SDimitry Andric m_mainloop.RequestTermination(); 400881ad6265SDimitry Andric } 4009fcaf7f86SDimitry Andric return ret; 401081ad6265SDimitry Andric } 401181ad6265SDimitry Andric 401281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 401381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCtrlC( 401481ad6265SDimitry Andric StringExtractorGDBRemote &packet) { 401581ad6265SDimitry Andric if (!m_non_stop) 401681ad6265SDimitry Andric return SendErrorResponse(Status("vCtrl is only valid in non-stop mode")); 401781ad6265SDimitry Andric 401881ad6265SDimitry Andric PacketResult interrupt_res = Handle_interrupt(packet); 401981ad6265SDimitry Andric // If interrupting the process failed, pass the result through. 402081ad6265SDimitry Andric if (interrupt_res != PacketResult::Success) 402181ad6265SDimitry Andric return interrupt_res; 402281ad6265SDimitry Andric // Otherwise, vCtrlC should issue an OK response (normal interrupts do not). 402381ad6265SDimitry Andric return SendOKResponse(); 402481ad6265SDimitry Andric } 402581ad6265SDimitry Andric 402681ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 402781ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_T(StringExtractorGDBRemote &packet) { 402881ad6265SDimitry Andric packet.SetFilePos(strlen("T")); 402981ad6265SDimitry Andric auto pid_tid = packet.GetPidTid(m_current_process ? m_current_process->GetID() 403081ad6265SDimitry Andric : LLDB_INVALID_PROCESS_ID); 403181ad6265SDimitry Andric if (!pid_tid) 403281ad6265SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 403381ad6265SDimitry Andric inconvertibleErrorCode(), "Malformed thread-id")); 403481ad6265SDimitry Andric 403581ad6265SDimitry Andric lldb::pid_t pid = pid_tid->first; 403681ad6265SDimitry Andric lldb::tid_t tid = pid_tid->second; 403781ad6265SDimitry Andric 403881ad6265SDimitry Andric // Technically, this would also be caught by the PID check but let's be more 403981ad6265SDimitry Andric // explicit about the error. 404081ad6265SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 404181ad6265SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 404281ad6265SDimitry Andric inconvertibleErrorCode(), "No current process and no PID provided")); 404381ad6265SDimitry Andric 404481ad6265SDimitry Andric // Check the process ID and find respective process instance. 404581ad6265SDimitry Andric auto new_process_it = m_debugged_processes.find(pid); 404681ad6265SDimitry Andric if (new_process_it == m_debugged_processes.end()) 404781ad6265SDimitry Andric return SendErrorResponse(1); 404881ad6265SDimitry Andric 404981ad6265SDimitry Andric // Check the thread ID 4050fcaf7f86SDimitry Andric if (!new_process_it->second.process_up->GetThreadByID(tid)) 405181ad6265SDimitry Andric return SendErrorResponse(2); 405281ad6265SDimitry Andric 405381ad6265SDimitry Andric return SendOKResponse(); 405481ad6265SDimitry Andric } 405581ad6265SDimitry Andric 40560b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { 405781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 40580b57cec5SDimitry Andric 40590b57cec5SDimitry Andric // Tell the stdio connection to shut down. 40600b57cec5SDimitry Andric if (m_stdio_communication.IsConnected()) { 40610b57cec5SDimitry Andric auto connection = m_stdio_communication.GetConnection(); 40620b57cec5SDimitry Andric if (connection) { 40630b57cec5SDimitry Andric Status error; 40640b57cec5SDimitry Andric connection->Disconnect(&error); 40650b57cec5SDimitry Andric 40660b57cec5SDimitry Andric if (error.Success()) { 40679dba64beSDimitry Andric LLDB_LOGF(log, 40689dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s disconnect process " 40690b57cec5SDimitry Andric "terminal stdio - SUCCESS", 40700b57cec5SDimitry Andric __FUNCTION__); 40710b57cec5SDimitry Andric } else { 40729dba64beSDimitry Andric LLDB_LOGF(log, 40739dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s disconnect process " 40740b57cec5SDimitry Andric "terminal stdio - FAIL: %s", 40750b57cec5SDimitry Andric __FUNCTION__, error.AsCString()); 40760b57cec5SDimitry Andric } 40770b57cec5SDimitry Andric } 40780b57cec5SDimitry Andric } 40790b57cec5SDimitry Andric } 40800b57cec5SDimitry Andric 40810b57cec5SDimitry Andric NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( 40820b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 40830b57cec5SDimitry Andric // We have no thread if we don't have a process. 4084fe6060f1SDimitry Andric if (!m_current_process || 4085fe6060f1SDimitry Andric m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) 40860b57cec5SDimitry Andric return nullptr; 40870b57cec5SDimitry Andric 40880b57cec5SDimitry Andric // If the client hasn't asked for thread suffix support, there will not be a 40890b57cec5SDimitry Andric // thread suffix. Use the current thread in that case. 40900b57cec5SDimitry Andric if (!m_thread_suffix_supported) { 40910b57cec5SDimitry Andric const lldb::tid_t current_tid = GetCurrentThreadID(); 40920b57cec5SDimitry Andric if (current_tid == LLDB_INVALID_THREAD_ID) 40930b57cec5SDimitry Andric return nullptr; 40940b57cec5SDimitry Andric else if (current_tid == 0) { 40950b57cec5SDimitry Andric // Pick a thread. 4096fe6060f1SDimitry Andric return m_current_process->GetThreadAtIndex(0); 40970b57cec5SDimitry Andric } else 4098fe6060f1SDimitry Andric return m_current_process->GetThreadByID(current_tid); 40990b57cec5SDimitry Andric } 41000b57cec5SDimitry Andric 410181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 41020b57cec5SDimitry Andric 41030b57cec5SDimitry Andric // Parse out the ';'. 41040b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') { 41059dba64beSDimitry Andric LLDB_LOGF(log, 41069dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " 41070b57cec5SDimitry Andric "error: expected ';' prior to start of thread suffix: packet " 41080b57cec5SDimitry Andric "contents = '%s'", 41099dba64beSDimitry Andric __FUNCTION__, packet.GetStringRef().data()); 41100b57cec5SDimitry Andric return nullptr; 41110b57cec5SDimitry Andric } 41120b57cec5SDimitry Andric 41130b57cec5SDimitry Andric if (!packet.GetBytesLeft()) 41140b57cec5SDimitry Andric return nullptr; 41150b57cec5SDimitry Andric 41160b57cec5SDimitry Andric // Parse out thread: portion. 41170b57cec5SDimitry Andric if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { 41189dba64beSDimitry Andric LLDB_LOGF(log, 41199dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " 41200b57cec5SDimitry Andric "error: expected 'thread:' but not found, packet contents = " 41210b57cec5SDimitry Andric "'%s'", 41229dba64beSDimitry Andric __FUNCTION__, packet.GetStringRef().data()); 41230b57cec5SDimitry Andric return nullptr; 41240b57cec5SDimitry Andric } 41250b57cec5SDimitry Andric packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); 41260b57cec5SDimitry Andric const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); 41270b57cec5SDimitry Andric if (tid != 0) 4128fe6060f1SDimitry Andric return m_current_process->GetThreadByID(tid); 41290b57cec5SDimitry Andric 41300b57cec5SDimitry Andric return nullptr; 41310b57cec5SDimitry Andric } 41320b57cec5SDimitry Andric 41330b57cec5SDimitry Andric lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { 41340b57cec5SDimitry Andric if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) { 41350b57cec5SDimitry Andric // Use whatever the debug process says is the current thread id since the 41360b57cec5SDimitry Andric // protocol either didn't specify or specified we want any/all threads 41370b57cec5SDimitry Andric // marked as the current thread. 4138fe6060f1SDimitry Andric if (!m_current_process) 41390b57cec5SDimitry Andric return LLDB_INVALID_THREAD_ID; 4140fe6060f1SDimitry Andric return m_current_process->GetCurrentThreadID(); 41410b57cec5SDimitry Andric } 41420b57cec5SDimitry Andric // Use the specific current thread id set by the gdb remote protocol. 41430b57cec5SDimitry Andric return m_current_tid; 41440b57cec5SDimitry Andric } 41450b57cec5SDimitry Andric 41460b57cec5SDimitry Andric uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() { 41470b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_saved_registers_mutex); 41480b57cec5SDimitry Andric return m_next_saved_registers_id++; 41490b57cec5SDimitry Andric } 41500b57cec5SDimitry Andric 41510b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() { 415281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 41530b57cec5SDimitry Andric 41540b57cec5SDimitry Andric LLDB_LOG(log, "clearing {0} xfer buffers", m_xfer_buffer_map.size()); 41550b57cec5SDimitry Andric m_xfer_buffer_map.clear(); 41560b57cec5SDimitry Andric } 41570b57cec5SDimitry Andric 41580b57cec5SDimitry Andric FileSpec 41590b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, 41600b57cec5SDimitry Andric const ArchSpec &arch) { 4161fe6060f1SDimitry Andric if (m_current_process) { 41620b57cec5SDimitry Andric FileSpec file_spec; 4163fe6060f1SDimitry Andric if (m_current_process 41640b57cec5SDimitry Andric ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec) 41650b57cec5SDimitry Andric .Success()) { 41660b57cec5SDimitry Andric if (FileSystem::Instance().Exists(file_spec)) 41670b57cec5SDimitry Andric return file_spec; 41680b57cec5SDimitry Andric } 41690b57cec5SDimitry Andric } 41700b57cec5SDimitry Andric 41710b57cec5SDimitry Andric return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch); 41720b57cec5SDimitry Andric } 41739dba64beSDimitry Andric 41749dba64beSDimitry Andric std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue( 41759dba64beSDimitry Andric llvm::StringRef value) { 41769dba64beSDimitry Andric std::string result; 41779dba64beSDimitry Andric for (const char &c : value) { 41789dba64beSDimitry Andric switch (c) { 41799dba64beSDimitry Andric case '\'': 41809dba64beSDimitry Andric result += "'"; 41819dba64beSDimitry Andric break; 41829dba64beSDimitry Andric case '"': 41839dba64beSDimitry Andric result += """; 41849dba64beSDimitry Andric break; 41859dba64beSDimitry Andric case '<': 41869dba64beSDimitry Andric result += "<"; 41879dba64beSDimitry Andric break; 41889dba64beSDimitry Andric case '>': 41899dba64beSDimitry Andric result += ">"; 41909dba64beSDimitry Andric break; 41919dba64beSDimitry Andric default: 41929dba64beSDimitry Andric result += c; 41939dba64beSDimitry Andric break; 41949dba64beSDimitry Andric } 41959dba64beSDimitry Andric } 41969dba64beSDimitry Andric return result; 41979dba64beSDimitry Andric } 4198fe6060f1SDimitry Andric 4199fe6060f1SDimitry Andric std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures( 4200fe6060f1SDimitry Andric const llvm::ArrayRef<llvm::StringRef> client_features) { 4201fe6060f1SDimitry Andric std::vector<std::string> ret = 4202fe6060f1SDimitry Andric GDBRemoteCommunicationServerCommon::HandleFeatures(client_features); 4203fe6060f1SDimitry Andric ret.insert(ret.end(), { 4204fe6060f1SDimitry Andric "QThreadSuffixSupported+", 4205fe6060f1SDimitry Andric "QListThreadsInStopReply+", 4206fe6060f1SDimitry Andric "qXfer:features:read+", 420781ad6265SDimitry Andric "QNonStop+", 4208fe6060f1SDimitry Andric }); 4209fe6060f1SDimitry Andric 4210fe6060f1SDimitry Andric // report server-only features 4211fe6060f1SDimitry Andric using Extension = NativeProcessProtocol::Extension; 4212fe6060f1SDimitry Andric Extension plugin_features = m_process_factory.GetSupportedExtensions(); 4213fe6060f1SDimitry Andric if (bool(plugin_features & Extension::pass_signals)) 4214fe6060f1SDimitry Andric ret.push_back("QPassSignals+"); 4215fe6060f1SDimitry Andric if (bool(plugin_features & Extension::auxv)) 4216fe6060f1SDimitry Andric ret.push_back("qXfer:auxv:read+"); 4217fe6060f1SDimitry Andric if (bool(plugin_features & Extension::libraries_svr4)) 4218fe6060f1SDimitry Andric ret.push_back("qXfer:libraries-svr4:read+"); 421904eeddc0SDimitry Andric if (bool(plugin_features & Extension::siginfo_read)) 422004eeddc0SDimitry Andric ret.push_back("qXfer:siginfo:read+"); 4221fe6060f1SDimitry Andric if (bool(plugin_features & Extension::memory_tagging)) 4222fe6060f1SDimitry Andric ret.push_back("memory-tagging+"); 4223349cc55cSDimitry Andric if (bool(plugin_features & Extension::savecore)) 4224349cc55cSDimitry Andric ret.push_back("qSaveCore+"); 4225fe6060f1SDimitry Andric 4226fe6060f1SDimitry Andric // check for client features 4227fe6060f1SDimitry Andric m_extensions_supported = {}; 4228fe6060f1SDimitry Andric for (llvm::StringRef x : client_features) 4229fe6060f1SDimitry Andric m_extensions_supported |= 4230fe6060f1SDimitry Andric llvm::StringSwitch<Extension>(x) 4231fe6060f1SDimitry Andric .Case("multiprocess+", Extension::multiprocess) 4232fe6060f1SDimitry Andric .Case("fork-events+", Extension::fork) 4233fe6060f1SDimitry Andric .Case("vfork-events+", Extension::vfork) 4234fe6060f1SDimitry Andric .Default({}); 4235fe6060f1SDimitry Andric 4236fe6060f1SDimitry Andric m_extensions_supported &= plugin_features; 4237fe6060f1SDimitry Andric 4238fe6060f1SDimitry Andric // fork & vfork require multiprocess 4239fe6060f1SDimitry Andric if (!bool(m_extensions_supported & Extension::multiprocess)) 4240fe6060f1SDimitry Andric m_extensions_supported &= ~(Extension::fork | Extension::vfork); 4241fe6060f1SDimitry Andric 4242fe6060f1SDimitry Andric // report only if actually supported 4243fe6060f1SDimitry Andric if (bool(m_extensions_supported & Extension::multiprocess)) 4244fe6060f1SDimitry Andric ret.push_back("multiprocess+"); 4245fe6060f1SDimitry Andric if (bool(m_extensions_supported & Extension::fork)) 4246fe6060f1SDimitry Andric ret.push_back("fork-events+"); 4247fe6060f1SDimitry Andric if (bool(m_extensions_supported & Extension::vfork)) 4248fe6060f1SDimitry Andric ret.push_back("vfork-events+"); 4249fe6060f1SDimitry Andric 4250fe6060f1SDimitry Andric for (auto &x : m_debugged_processes) 4251fcaf7f86SDimitry Andric SetEnabledExtensions(*x.second.process_up); 4252fe6060f1SDimitry Andric return ret; 4253fe6060f1SDimitry Andric } 4254fe6060f1SDimitry Andric 4255fe6060f1SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions( 4256fe6060f1SDimitry Andric NativeProcessProtocol &process) { 4257fe6060f1SDimitry Andric NativeProcessProtocol::Extension flags = m_extensions_supported; 4258fe6060f1SDimitry Andric assert(!bool(flags & ~m_process_factory.GetSupportedExtensions())); 4259fe6060f1SDimitry Andric process.SetEnabledExtensions(flags); 4260fe6060f1SDimitry Andric } 4261349cc55cSDimitry Andric 426281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 426381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() { 4264fcaf7f86SDimitry Andric if (m_non_stop) 4265fcaf7f86SDimitry Andric return SendOKResponse(); 426681ad6265SDimitry Andric StartSTDIOForwarding(); 4267fcaf7f86SDimitry Andric return PacketResult::Success; 426881ad6265SDimitry Andric } 426981ad6265SDimitry Andric 427081ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse( 427181ad6265SDimitry Andric Stream &response, lldb::pid_t pid, lldb::tid_t tid) { 427281ad6265SDimitry Andric if (bool(m_extensions_supported & 427381ad6265SDimitry Andric NativeProcessProtocol::Extension::multiprocess)) 427481ad6265SDimitry Andric response.Format("p{0:x-}.", pid); 427581ad6265SDimitry Andric response.Format("{0:x-}", tid); 427681ad6265SDimitry Andric } 427781ad6265SDimitry Andric 4278349cc55cSDimitry Andric std::string 4279349cc55cSDimitry Andric lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg, 4280349cc55cSDimitry Andric bool reverse_connect) { 4281349cc55cSDimitry Andric // Try parsing the argument as URL. 4282bdd1243dSDimitry Andric if (std::optional<URI> url = URI::Parse(url_arg)) { 4283349cc55cSDimitry Andric if (reverse_connect) 4284349cc55cSDimitry Andric return url_arg.str(); 4285349cc55cSDimitry Andric 4286349cc55cSDimitry Andric // Translate the scheme from LLGS notation to ConnectionFileDescriptor. 4287349cc55cSDimitry Andric // If the scheme doesn't match any, pass it through to support using CFD 4288349cc55cSDimitry Andric // schemes directly. 4289349cc55cSDimitry Andric std::string new_url = llvm::StringSwitch<std::string>(url->scheme) 4290349cc55cSDimitry Andric .Case("tcp", "listen") 4291349cc55cSDimitry Andric .Case("unix", "unix-accept") 4292349cc55cSDimitry Andric .Case("unix-abstract", "unix-abstract-accept") 4293349cc55cSDimitry Andric .Default(url->scheme.str()); 4294349cc55cSDimitry Andric llvm::append_range(new_url, url_arg.substr(url->scheme.size())); 4295349cc55cSDimitry Andric return new_url; 4296349cc55cSDimitry Andric } 4297349cc55cSDimitry Andric 4298349cc55cSDimitry Andric std::string host_port = url_arg.str(); 4299349cc55cSDimitry Andric // If host_and_port starts with ':', default the host to be "localhost" and 4300349cc55cSDimitry Andric // expect the remainder to be the port. 4301349cc55cSDimitry Andric if (url_arg.startswith(":")) 4302349cc55cSDimitry Andric host_port.insert(0, "localhost"); 4303349cc55cSDimitry Andric 4304349cc55cSDimitry Andric // Try parsing the (preprocessed) argument as host:port pair. 4305349cc55cSDimitry Andric if (!llvm::errorToBool(Socket::DecodeHostAndPort(host_port).takeError())) 4306349cc55cSDimitry Andric return (reverse_connect ? "connect://" : "listen://") + host_port; 4307349cc55cSDimitry Andric 4308349cc55cSDimitry Andric // If none of the above applied, interpret the argument as UNIX socket path. 4309349cc55cSDimitry Andric return (reverse_connect ? "unix-connect://" : "unix-accept://") + 4310349cc55cSDimitry Andric url_arg.str(); 4311349cc55cSDimitry Andric } 4312