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/State.h" 410b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 42e8d8bef9SDimitry Andric #include "lldb/Utility/UnimplementedError.h" 430b57cec5SDimitry Andric #include "lldb/Utility/UriParser.h" 449dba64beSDimitry Andric #include "llvm/Support/JSON.h" 450b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 4606c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric #include "ProcessGDBRemote.h" 490b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h" 500b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h" 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric using namespace lldb; 530b57cec5SDimitry Andric using namespace lldb_private; 540b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote; 550b57cec5SDimitry Andric using namespace llvm; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // GDBRemote Errors 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric namespace { 600b57cec5SDimitry Andric enum GDBRemoteServerError { 610b57cec5SDimitry Andric // Set to the first unused error number in literal form below 620b57cec5SDimitry Andric eErrorFirst = 29, 630b57cec5SDimitry Andric eErrorNoProcess = eErrorFirst, 640b57cec5SDimitry Andric eErrorResume, 650b57cec5SDimitry Andric eErrorExitStatus 660b57cec5SDimitry Andric }; 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric // GDBRemoteCommunicationServerLLGS constructor 700b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( 7106c3fb27SDimitry Andric MainLoop &mainloop, NativeProcessProtocol::Manager &process_manager) 72bdd1243dSDimitry Andric : GDBRemoteCommunicationServerCommon(), m_mainloop(mainloop), 7306c3fb27SDimitry Andric m_process_manager(process_manager), m_current_process(nullptr), 74bdd1243dSDimitry Andric m_continue_process(nullptr), m_stdio_communication() { 750b57cec5SDimitry Andric RegisterPacketHandlers(); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { 790b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C, 800b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_C); 810b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c, 820b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_c); 830b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D, 840b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_D); 850b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H, 860b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_H); 870b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I, 880b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_I); 890b57cec5SDimitry Andric RegisterMemberFunctionHandler( 900b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_interrupt, 910b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_interrupt); 920b57cec5SDimitry Andric RegisterMemberFunctionHandler( 930b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_m, 940b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_memory_read); 950b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M, 960b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_M); 97e8d8bef9SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType__M, 98e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle__M); 99e8d8bef9SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType__m, 100e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle__m); 1010b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, 1020b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_p); 1030b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P, 1040b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_P); 1050b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC, 1060b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qC); 10781ad6265SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_T, 10881ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_T); 1090b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1100b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qfThreadInfo, 1110b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo); 1120b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1130b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress, 1140b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress); 1150b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1160b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, 1170b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir); 1180b57cec5SDimitry Andric RegisterMemberFunctionHandler( 119fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported, 120fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported); 121fe6060f1SDimitry Andric RegisterMemberFunctionHandler( 122fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply, 123fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply); 124fe6060f1SDimitry Andric RegisterMemberFunctionHandler( 1250b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo, 1260b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo); 1270b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1280b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported, 1290b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported); 1300b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1310b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qProcessInfo, 1320b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo); 1330b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1340b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qRegisterInfo, 1350b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo); 1360b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1370b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState, 1380b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState); 1390b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1400b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState, 1410b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState); 1420b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1430b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR, 1440b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR); 1450b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1460b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, 1470b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir); 1480b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1490b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qsThreadInfo, 1500b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo); 1510b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1520b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo, 1530b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo); 1540b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1550b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jThreadsInfo, 1560b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo); 1570b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1580b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo, 1590b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo); 1600b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1610b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qXfer, 1620b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qXfer); 1630b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s, 1640b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_s); 1650b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1660b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_stop_reason, 1670b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ? 1680b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1690b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vAttach, 1700b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vAttach); 1710b57cec5SDimitry Andric RegisterMemberFunctionHandler( 172e8d8bef9SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vAttachWait, 173e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vAttachWait); 174e8d8bef9SDimitry Andric RegisterMemberFunctionHandler( 175e8d8bef9SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qVAttachOrWaitSupported, 176e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported); 177e8d8bef9SDimitry Andric RegisterMemberFunctionHandler( 178e8d8bef9SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vAttachOrWait, 179e8d8bef9SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait); 180e8d8bef9SDimitry Andric RegisterMemberFunctionHandler( 1810b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vCont, 1820b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vCont); 1830b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1840b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vCont_actions, 1850b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); 1860b57cec5SDimitry Andric RegisterMemberFunctionHandler( 187349cc55cSDimitry Andric StringExtractorGDBRemote::eServerPacketType_vRun, 188349cc55cSDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vRun); 189349cc55cSDimitry Andric RegisterMemberFunctionHandler( 1900b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_x, 1910b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_memory_read); 1920b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z, 1930b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_Z); 1940b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, 1950b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_z); 1960b57cec5SDimitry Andric RegisterMemberFunctionHandler( 1970b57cec5SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QPassSignals, 1980b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric RegisterMemberFunctionHandler( 201fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupported, 202fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported); 2030b57cec5SDimitry Andric RegisterMemberFunctionHandler( 204fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStart, 205fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart); 2060b57cec5SDimitry Andric RegisterMemberFunctionHandler( 207fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStop, 208fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop); 2090b57cec5SDimitry Andric RegisterMemberFunctionHandler( 210fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetState, 211fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState); 2120b57cec5SDimitry Andric RegisterMemberFunctionHandler( 213fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetBinaryData, 214fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g, 2170b57cec5SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_g); 2180b57cec5SDimitry Andric 219fe6060f1SDimitry Andric RegisterMemberFunctionHandler( 220fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_qMemTags, 221fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qMemTags); 222fe6060f1SDimitry Andric 223fe6060f1SDimitry Andric RegisterMemberFunctionHandler( 224fe6060f1SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QMemTags, 225fe6060f1SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QMemTags); 226fe6060f1SDimitry Andric 2270b57cec5SDimitry Andric RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, 2280b57cec5SDimitry Andric [this](StringExtractorGDBRemote packet, Status &error, 2290b57cec5SDimitry Andric bool &interrupt, bool &quit) { 2300b57cec5SDimitry Andric quit = true; 2310b57cec5SDimitry Andric return this->Handle_k(packet); 2320b57cec5SDimitry Andric }); 233349cc55cSDimitry Andric 234349cc55cSDimitry Andric RegisterMemberFunctionHandler( 23581ad6265SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vKill, 23681ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vKill); 23781ad6265SDimitry Andric 23881ad6265SDimitry Andric RegisterMemberFunctionHandler( 239349cc55cSDimitry Andric StringExtractorGDBRemote::eServerPacketType_qLLDBSaveCore, 240349cc55cSDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_qSaveCore); 24181ad6265SDimitry Andric 24281ad6265SDimitry Andric RegisterMemberFunctionHandler( 24381ad6265SDimitry Andric StringExtractorGDBRemote::eServerPacketType_QNonStop, 24481ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_QNonStop); 24581ad6265SDimitry Andric RegisterMemberFunctionHandler( 246fcaf7f86SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vStdio, 247fcaf7f86SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vStdio); 248fcaf7f86SDimitry Andric RegisterMemberFunctionHandler( 24981ad6265SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vStopped, 25081ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vStopped); 25181ad6265SDimitry Andric RegisterMemberFunctionHandler( 25281ad6265SDimitry Andric StringExtractorGDBRemote::eServerPacketType_vCtrlC, 25381ad6265SDimitry Andric &GDBRemoteCommunicationServerLLGS::Handle_vCtrlC); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) { 2570b57cec5SDimitry Andric m_process_launch_info = info; 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { 26181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric if (!m_process_launch_info.GetArguments().GetArgumentCount()) 2640b57cec5SDimitry Andric return Status("%s: no process command line specified to launch", 2650b57cec5SDimitry Andric __FUNCTION__); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric const bool should_forward_stdio = 2680b57cec5SDimitry Andric m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr || 2690b57cec5SDimitry Andric m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr || 2700b57cec5SDimitry Andric m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr; 2710b57cec5SDimitry Andric m_process_launch_info.SetLaunchInSeparateProcessGroup(true); 2720b57cec5SDimitry Andric m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric if (should_forward_stdio) { 2759dba64beSDimitry Andric // Temporarily relax the following for Windows until we can take advantage 2769dba64beSDimitry Andric // of the recently added pty support. This doesn't really affect the use of 2779dba64beSDimitry Andric // lldb-server on Windows. 2789dba64beSDimitry Andric #if !defined(_WIN32) 2790b57cec5SDimitry Andric if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection()) 2800b57cec5SDimitry Andric return Status(std::move(Err)); 2819dba64beSDimitry Andric #endif 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric { 2850b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); 286fe6060f1SDimitry Andric assert(m_debugged_processes.empty() && "lldb-server creating debugged " 2870b57cec5SDimitry Andric "process but one already exists"); 28806c3fb27SDimitry Andric auto process_or = m_process_manager.Launch(m_process_launch_info, *this); 2890b57cec5SDimitry Andric if (!process_or) 2900b57cec5SDimitry Andric return Status(process_or.takeError()); 291fe6060f1SDimitry Andric m_continue_process = m_current_process = process_or->get(); 292fcaf7f86SDimitry Andric m_debugged_processes.emplace( 293fcaf7f86SDimitry Andric m_current_process->GetID(), 294fcaf7f86SDimitry Andric DebuggedProcess{std::move(*process_or), DebuggedProcess::Flag{}}); 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 297fe6060f1SDimitry Andric SetEnabledExtensions(*m_current_process); 298fe6060f1SDimitry Andric 2990b57cec5SDimitry Andric // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as 3000b57cec5SDimitry Andric // needed. llgs local-process debugging may specify PTY paths, which will 3010b57cec5SDimitry Andric // make these file actions non-null process launch -i/e/o will also make 3020b57cec5SDimitry Andric // these file actions non-null nullptr means that the traffic is expected to 3030b57cec5SDimitry Andric // flow over gdb-remote protocol 3040b57cec5SDimitry Andric if (should_forward_stdio) { 3050b57cec5SDimitry Andric // nullptr means it's not redirected to file or pty (in case of LLGS local) 3060b57cec5SDimitry Andric // at least one of stdio will be transferred pty<->gdb-remote we need to 307349cc55cSDimitry Andric // give the pty primary handle to this object to read and/or write 3080b57cec5SDimitry Andric LLDB_LOG(log, 3090b57cec5SDimitry Andric "pid = {0}: setting up stdout/stderr redirection via $O " 3100b57cec5SDimitry Andric "gdb-remote commands", 311fe6060f1SDimitry Andric m_current_process->GetID()); 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // Setup stdout/stderr mapping from inferior to $O 314fe6060f1SDimitry Andric auto terminal_fd = m_current_process->GetTerminalFileDescriptor(); 3150b57cec5SDimitry Andric if (terminal_fd >= 0) { 3169dba64beSDimitry Andric LLDB_LOGF(log, 3179dba64beSDimitry Andric "ProcessGDBRemoteCommunicationServerLLGS::%s setting " 3180b57cec5SDimitry Andric "inferior STDIO fd to %d", 3190b57cec5SDimitry Andric __FUNCTION__, terminal_fd); 3200b57cec5SDimitry Andric Status status = SetSTDIOFileDescriptor(terminal_fd); 3210b57cec5SDimitry Andric if (status.Fail()) 3220b57cec5SDimitry Andric return status; 3230b57cec5SDimitry Andric } else { 3249dba64beSDimitry Andric LLDB_LOGF(log, 3259dba64beSDimitry Andric "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " 3260b57cec5SDimitry Andric "inferior STDIO since terminal fd reported as %d", 3270b57cec5SDimitry Andric __FUNCTION__, terminal_fd); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric } else { 3300b57cec5SDimitry Andric LLDB_LOG(log, 3310b57cec5SDimitry Andric "pid = {0} skipping stdout/stderr redirection via $O: inferior " 3320b57cec5SDimitry Andric "will communicate over client-provided file descriptors", 333fe6060f1SDimitry Andric m_current_process->GetID()); 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric printf("Launched '%s' as process %" PRIu64 "...\n", 3370b57cec5SDimitry Andric m_process_launch_info.GetArguments().GetArgumentAtIndex(0), 338fe6060f1SDimitry Andric m_current_process->GetID()); 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric return Status(); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { 34481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3459dba64beSDimitry Andric LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, 3460b57cec5SDimitry Andric __FUNCTION__, pid); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric // Before we try to attach, make sure we aren't already monitoring something 3490b57cec5SDimitry Andric // else. 350fe6060f1SDimitry Andric if (!m_debugged_processes.empty()) 3510b57cec5SDimitry Andric return Status("cannot attach to process %" PRIu64 3520b57cec5SDimitry Andric " when another process with pid %" PRIu64 3530b57cec5SDimitry Andric " is being debugged.", 354fe6060f1SDimitry Andric pid, m_current_process->GetID()); 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric // Try to attach. 35706c3fb27SDimitry Andric auto process_or = m_process_manager.Attach(pid, *this); 3580b57cec5SDimitry Andric if (!process_or) { 3590b57cec5SDimitry Andric Status status(process_or.takeError()); 360349cc55cSDimitry Andric llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}\n", pid, 3610b57cec5SDimitry Andric status); 3620b57cec5SDimitry Andric return status; 3630b57cec5SDimitry Andric } 364fe6060f1SDimitry Andric m_continue_process = m_current_process = process_or->get(); 365fcaf7f86SDimitry Andric m_debugged_processes.emplace( 366fcaf7f86SDimitry Andric m_current_process->GetID(), 367fcaf7f86SDimitry Andric DebuggedProcess{std::move(*process_or), DebuggedProcess::Flag{}}); 368fe6060f1SDimitry Andric SetEnabledExtensions(*m_current_process); 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric // Setup stdout/stderr mapping from inferior. 371fe6060f1SDimitry Andric auto terminal_fd = m_current_process->GetTerminalFileDescriptor(); 3720b57cec5SDimitry Andric if (terminal_fd >= 0) { 3739dba64beSDimitry Andric LLDB_LOGF(log, 3749dba64beSDimitry Andric "ProcessGDBRemoteCommunicationServerLLGS::%s setting " 3750b57cec5SDimitry Andric "inferior STDIO fd to %d", 3760b57cec5SDimitry Andric __FUNCTION__, terminal_fd); 3770b57cec5SDimitry Andric Status status = SetSTDIOFileDescriptor(terminal_fd); 3780b57cec5SDimitry Andric if (status.Fail()) 3790b57cec5SDimitry Andric return status; 3800b57cec5SDimitry Andric } else { 3819dba64beSDimitry Andric LLDB_LOGF(log, 3829dba64beSDimitry Andric "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " 3830b57cec5SDimitry Andric "inferior STDIO since terminal fd reported as %d", 3840b57cec5SDimitry Andric __FUNCTION__, terminal_fd); 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric printf("Attached to process %" PRIu64 "...\n", pid); 3880b57cec5SDimitry Andric return Status(); 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 391e8d8bef9SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess( 392e8d8bef9SDimitry Andric llvm::StringRef process_name, bool include_existing) { 39381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 394e8d8bef9SDimitry Andric 395e8d8bef9SDimitry Andric std::chrono::milliseconds polling_interval = std::chrono::milliseconds(1); 396e8d8bef9SDimitry Andric 397e8d8bef9SDimitry Andric // Create the matcher used to search the process list. 398e8d8bef9SDimitry Andric ProcessInstanceInfoList exclusion_list; 399e8d8bef9SDimitry Andric ProcessInstanceInfoMatch match_info; 400e8d8bef9SDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile( 401e8d8bef9SDimitry Andric process_name, llvm::sys::path::Style::native); 402e8d8bef9SDimitry Andric match_info.SetNameMatchType(NameMatch::Equals); 403e8d8bef9SDimitry Andric 404e8d8bef9SDimitry Andric if (include_existing) { 405e8d8bef9SDimitry Andric LLDB_LOG(log, "including existing processes in search"); 406e8d8bef9SDimitry Andric } else { 407e8d8bef9SDimitry Andric // Create the excluded process list before polling begins. 408e8d8bef9SDimitry Andric Host::FindProcesses(match_info, exclusion_list); 409e8d8bef9SDimitry Andric LLDB_LOG(log, "placed '{0}' processes in the exclusion list.", 410e8d8bef9SDimitry Andric exclusion_list.size()); 411e8d8bef9SDimitry Andric } 412e8d8bef9SDimitry Andric 413e8d8bef9SDimitry Andric LLDB_LOG(log, "waiting for '{0}' to appear", process_name); 414e8d8bef9SDimitry Andric 415e8d8bef9SDimitry Andric auto is_in_exclusion_list = 416e8d8bef9SDimitry Andric [&exclusion_list](const ProcessInstanceInfo &info) { 417e8d8bef9SDimitry Andric for (auto &excluded : exclusion_list) { 418e8d8bef9SDimitry Andric if (excluded.GetProcessID() == info.GetProcessID()) 419e8d8bef9SDimitry Andric return true; 420e8d8bef9SDimitry Andric } 421e8d8bef9SDimitry Andric return false; 422e8d8bef9SDimitry Andric }; 423e8d8bef9SDimitry Andric 424e8d8bef9SDimitry Andric ProcessInstanceInfoList loop_process_list; 425e8d8bef9SDimitry Andric while (true) { 426e8d8bef9SDimitry Andric loop_process_list.clear(); 427e8d8bef9SDimitry Andric if (Host::FindProcesses(match_info, loop_process_list)) { 428e8d8bef9SDimitry Andric // Remove all the elements that are in the exclusion list. 429e8d8bef9SDimitry Andric llvm::erase_if(loop_process_list, is_in_exclusion_list); 430e8d8bef9SDimitry Andric 431e8d8bef9SDimitry Andric // One match! We found the desired process. 432e8d8bef9SDimitry Andric if (loop_process_list.size() == 1) { 433e8d8bef9SDimitry Andric auto matching_process_pid = loop_process_list[0].GetProcessID(); 434e8d8bef9SDimitry Andric LLDB_LOG(log, "found pid {0}", matching_process_pid); 435e8d8bef9SDimitry Andric return AttachToProcess(matching_process_pid); 436e8d8bef9SDimitry Andric } 437e8d8bef9SDimitry Andric 438e8d8bef9SDimitry Andric // Multiple matches! Return an error reporting the PIDs we found. 439e8d8bef9SDimitry Andric if (loop_process_list.size() > 1) { 440e8d8bef9SDimitry Andric StreamString error_stream; 441e8d8bef9SDimitry Andric error_stream.Format( 442e8d8bef9SDimitry Andric "Multiple executables with name: '{0}' found. Pids: ", 443e8d8bef9SDimitry Andric process_name); 444e8d8bef9SDimitry Andric for (size_t i = 0; i < loop_process_list.size() - 1; ++i) { 445e8d8bef9SDimitry Andric error_stream.Format("{0}, ", loop_process_list[i].GetProcessID()); 446e8d8bef9SDimitry Andric } 447e8d8bef9SDimitry Andric error_stream.Format("{0}.", loop_process_list.back().GetProcessID()); 448e8d8bef9SDimitry Andric 449e8d8bef9SDimitry Andric Status error; 450e8d8bef9SDimitry Andric error.SetErrorString(error_stream.GetString()); 451e8d8bef9SDimitry Andric return error; 452e8d8bef9SDimitry Andric } 453e8d8bef9SDimitry Andric } 454e8d8bef9SDimitry Andric // No matches, we have not found the process. Sleep until next poll. 455e8d8bef9SDimitry Andric LLDB_LOG(log, "sleep {0} seconds", polling_interval); 456e8d8bef9SDimitry Andric std::this_thread::sleep_for(polling_interval); 457e8d8bef9SDimitry Andric } 458e8d8bef9SDimitry Andric } 459e8d8bef9SDimitry Andric 4600b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::InitializeDelegate( 4610b57cec5SDimitry Andric NativeProcessProtocol *process) { 4620b57cec5SDimitry Andric assert(process && "process cannot be NULL"); 46381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 4640b57cec5SDimitry Andric if (log) { 4659dba64beSDimitry Andric LLDB_LOGF(log, 4669dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s called with " 4670b57cec5SDimitry Andric "NativeProcessProtocol pid %" PRIu64 ", current state: %s", 4680b57cec5SDimitry Andric __FUNCTION__, process->GetID(), 4690b57cec5SDimitry Andric StateAsCString(process->GetState())); 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 4740b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendWResponse( 4750b57cec5SDimitry Andric NativeProcessProtocol *process) { 4760b57cec5SDimitry Andric assert(process && "process cannot be NULL"); 47781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric // send W notification 4800b57cec5SDimitry Andric auto wait_status = process->GetExitStatus(); 4810b57cec5SDimitry Andric if (!wait_status) { 4820b57cec5SDimitry Andric LLDB_LOG(log, "pid = {0}, failed to retrieve process exit status", 4830b57cec5SDimitry Andric process->GetID()); 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric StreamGDBRemote response; 4860b57cec5SDimitry Andric response.PutChar('E'); 4870b57cec5SDimitry Andric response.PutHex8(GDBRemoteServerError::eErrorExitStatus); 4880b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(), 4920b57cec5SDimitry Andric *wait_status); 4930b57cec5SDimitry Andric 49481ad6265SDimitry Andric // If the process was killed through vKill, return "OK". 495fcaf7f86SDimitry Andric if (bool(m_debugged_processes.at(process->GetID()).flags & 496fcaf7f86SDimitry Andric DebuggedProcess::Flag::vkilled)) 49781ad6265SDimitry Andric return SendOKResponse(); 49881ad6265SDimitry Andric 4990b57cec5SDimitry Andric StreamGDBRemote response; 5000b57cec5SDimitry Andric response.Format("{0:g}", *wait_status); 501fcaf7f86SDimitry Andric if (bool(m_extensions_supported & 502fcaf7f86SDimitry Andric NativeProcessProtocol::Extension::multiprocess)) 50381ad6265SDimitry Andric response.Format(";process:{0:x-}", process->GetID()); 50481ad6265SDimitry Andric if (m_non_stop) 50581ad6265SDimitry Andric return SendNotificationPacketNoLock("Stop", m_stop_notification_queue, 50681ad6265SDimitry Andric response.GetString()); 5070b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric static void AppendHexValue(StreamString &response, const uint8_t *buf, 5110b57cec5SDimitry Andric uint32_t buf_size, bool swap) { 5120b57cec5SDimitry Andric int64_t i; 5130b57cec5SDimitry Andric if (swap) { 5140b57cec5SDimitry Andric for (i = buf_size - 1; i >= 0; i--) 5150b57cec5SDimitry Andric response.PutHex8(buf[i]); 5160b57cec5SDimitry Andric } else { 5170b57cec5SDimitry Andric for (i = 0; i < buf_size; i++) 5180b57cec5SDimitry Andric response.PutHex8(buf[i]); 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 5225ffd83dbSDimitry Andric static llvm::StringRef GetEncodingNameOrEmpty(const RegisterInfo ®_info) { 5235ffd83dbSDimitry Andric switch (reg_info.encoding) { 5245ffd83dbSDimitry Andric case eEncodingUint: 5255ffd83dbSDimitry Andric return "uint"; 5265ffd83dbSDimitry Andric case eEncodingSint: 5275ffd83dbSDimitry Andric return "sint"; 5285ffd83dbSDimitry Andric case eEncodingIEEE754: 5295ffd83dbSDimitry Andric return "ieee754"; 5305ffd83dbSDimitry Andric case eEncodingVector: 5315ffd83dbSDimitry Andric return "vector"; 5325ffd83dbSDimitry Andric default: 5335ffd83dbSDimitry Andric return ""; 5345ffd83dbSDimitry Andric } 5355ffd83dbSDimitry Andric } 5365ffd83dbSDimitry Andric 5375ffd83dbSDimitry Andric static llvm::StringRef GetFormatNameOrEmpty(const RegisterInfo ®_info) { 5385ffd83dbSDimitry Andric switch (reg_info.format) { 5395ffd83dbSDimitry Andric case eFormatBinary: 5405ffd83dbSDimitry Andric return "binary"; 5415ffd83dbSDimitry Andric case eFormatDecimal: 5425ffd83dbSDimitry Andric return "decimal"; 5435ffd83dbSDimitry Andric case eFormatHex: 5445ffd83dbSDimitry Andric return "hex"; 5455ffd83dbSDimitry Andric case eFormatFloat: 5465ffd83dbSDimitry Andric return "float"; 5475ffd83dbSDimitry Andric case eFormatVectorOfSInt8: 5485ffd83dbSDimitry Andric return "vector-sint8"; 5495ffd83dbSDimitry Andric case eFormatVectorOfUInt8: 5505ffd83dbSDimitry Andric return "vector-uint8"; 5515ffd83dbSDimitry Andric case eFormatVectorOfSInt16: 5525ffd83dbSDimitry Andric return "vector-sint16"; 5535ffd83dbSDimitry Andric case eFormatVectorOfUInt16: 5545ffd83dbSDimitry Andric return "vector-uint16"; 5555ffd83dbSDimitry Andric case eFormatVectorOfSInt32: 5565ffd83dbSDimitry Andric return "vector-sint32"; 5575ffd83dbSDimitry Andric case eFormatVectorOfUInt32: 5585ffd83dbSDimitry Andric return "vector-uint32"; 5595ffd83dbSDimitry Andric case eFormatVectorOfFloat32: 5605ffd83dbSDimitry Andric return "vector-float32"; 5615ffd83dbSDimitry Andric case eFormatVectorOfUInt64: 5625ffd83dbSDimitry Andric return "vector-uint64"; 5635ffd83dbSDimitry Andric case eFormatVectorOfUInt128: 5645ffd83dbSDimitry Andric return "vector-uint128"; 5655ffd83dbSDimitry Andric default: 5665ffd83dbSDimitry Andric return ""; 5675ffd83dbSDimitry Andric }; 5685ffd83dbSDimitry Andric } 5695ffd83dbSDimitry Andric 5705ffd83dbSDimitry Andric static llvm::StringRef GetKindGenericOrEmpty(const RegisterInfo ®_info) { 5715ffd83dbSDimitry Andric switch (reg_info.kinds[RegisterKind::eRegisterKindGeneric]) { 5725ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_PC: 5735ffd83dbSDimitry Andric return "pc"; 5745ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_SP: 5755ffd83dbSDimitry Andric return "sp"; 5765ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_FP: 5775ffd83dbSDimitry Andric return "fp"; 5785ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_RA: 5795ffd83dbSDimitry Andric return "ra"; 5805ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_FLAGS: 5815ffd83dbSDimitry Andric return "flags"; 5825ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG1: 5835ffd83dbSDimitry Andric return "arg1"; 5845ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG2: 5855ffd83dbSDimitry Andric return "arg2"; 5865ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG3: 5875ffd83dbSDimitry Andric return "arg3"; 5885ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG4: 5895ffd83dbSDimitry Andric return "arg4"; 5905ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG5: 5915ffd83dbSDimitry Andric return "arg5"; 5925ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG6: 5935ffd83dbSDimitry Andric return "arg6"; 5945ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG7: 5955ffd83dbSDimitry Andric return "arg7"; 5965ffd83dbSDimitry Andric case LLDB_REGNUM_GENERIC_ARG8: 5975ffd83dbSDimitry Andric return "arg8"; 5985f757f3fSDimitry Andric case LLDB_REGNUM_GENERIC_TP: 5995f757f3fSDimitry Andric return "tp"; 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) { 6365f757f3fSDimitry Andric std::vector<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) { 2090*0fca6ea1SDimitry 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. 227006c3fb27SDimitry Andric size_t reg_size = packet.GetHexBytesAvail(m_reg_bytes); 22710b57cec5SDimitry Andric 22720b57cec5SDimitry Andric // Get the thread to use. 22730b57cec5SDimitry Andric NativeThreadProtocol *thread = GetThreadFromSuffix(packet); 22740b57cec5SDimitry Andric if (!thread) { 22759dba64beSDimitry Andric LLDB_LOGF(log, 22769dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no thread " 22770b57cec5SDimitry Andric "available (thread index 0)", 22780b57cec5SDimitry Andric __FUNCTION__); 22790b57cec5SDimitry Andric return SendErrorResponse(0x28); 22800b57cec5SDimitry Andric } 22810b57cec5SDimitry Andric 22820b57cec5SDimitry Andric // Get the thread's register context. 22830b57cec5SDimitry Andric NativeRegisterContext ®_context = thread->GetRegisterContext(); 22840b57cec5SDimitry Andric const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); 22850b57cec5SDimitry Andric if (!reg_info) { 22869dba64beSDimitry Andric LLDB_LOGF(log, 22879dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, requested " 22880b57cec5SDimitry Andric "register %" PRIu32 " returned NULL", 22890b57cec5SDimitry Andric __FUNCTION__, reg_index); 22900b57cec5SDimitry Andric return SendErrorResponse(0x48); 22910b57cec5SDimitry Andric } 22920b57cec5SDimitry Andric 22930b57cec5SDimitry Andric // Return the end of registers response if we've iterated one past the end of 22940b57cec5SDimitry Andric // the register set. 22950b57cec5SDimitry Andric if (reg_index >= reg_context.GetUserRegisterCount()) { 22969dba64beSDimitry Andric LLDB_LOGF(log, 22979dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, requested " 22980b57cec5SDimitry Andric "register %" PRIu32 " beyond register count %" PRIu32, 22990b57cec5SDimitry Andric __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); 23000b57cec5SDimitry Andric return SendErrorResponse(0x47); 23010b57cec5SDimitry Andric } 23020b57cec5SDimitry Andric 2303349cc55cSDimitry Andric if (reg_size != reg_info->byte_size) 23040b57cec5SDimitry Andric return SendIllFormedResponse(packet, "P packet register size is incorrect"); 23050b57cec5SDimitry Andric 23060b57cec5SDimitry Andric // Build the reginfos response. 23070b57cec5SDimitry Andric StreamGDBRemote response; 23080b57cec5SDimitry Andric 23095f757f3fSDimitry Andric RegisterValue reg_value(ArrayRef<uint8_t>(m_reg_bytes, reg_size), 2310fe6060f1SDimitry Andric m_current_process->GetArchitecture().GetByteOrder()); 23110b57cec5SDimitry Andric Status error = reg_context.WriteRegister(reg_info, reg_value); 23120b57cec5SDimitry Andric if (error.Fail()) { 23139dba64beSDimitry Andric LLDB_LOGF(log, 23149dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, write of " 23150b57cec5SDimitry Andric "requested register %" PRIu32 " (%s) failed: %s", 23160b57cec5SDimitry Andric __FUNCTION__, reg_index, reg_info->name, error.AsCString()); 23170b57cec5SDimitry Andric return SendErrorResponse(0x32); 23180b57cec5SDimitry Andric } 23190b57cec5SDimitry Andric 23200b57cec5SDimitry Andric return SendOKResponse(); 23210b57cec5SDimitry Andric } 23220b57cec5SDimitry Andric 23230b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 23240b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { 232581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 23260b57cec5SDimitry Andric 23270b57cec5SDimitry Andric // Parse out which variant of $H is requested. 23280b57cec5SDimitry Andric packet.SetFilePos(strlen("H")); 23290b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) { 23309dba64beSDimitry Andric LLDB_LOGF(log, 23319dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, H command " 23320b57cec5SDimitry Andric "missing {g,c} variant", 23330b57cec5SDimitry Andric __FUNCTION__); 23340b57cec5SDimitry Andric return SendIllFormedResponse(packet, "H command missing {g,c} variant"); 23350b57cec5SDimitry Andric } 23360b57cec5SDimitry Andric 23370b57cec5SDimitry Andric const char h_variant = packet.GetChar(); 2338fe6060f1SDimitry Andric NativeProcessProtocol *default_process; 23390b57cec5SDimitry Andric switch (h_variant) { 23400b57cec5SDimitry Andric case 'g': 2341fe6060f1SDimitry Andric default_process = m_current_process; 23420b57cec5SDimitry Andric break; 23430b57cec5SDimitry Andric 23440b57cec5SDimitry Andric case 'c': 2345fe6060f1SDimitry Andric default_process = m_continue_process; 23460b57cec5SDimitry Andric break; 23470b57cec5SDimitry Andric 23480b57cec5SDimitry Andric default: 23499dba64beSDimitry Andric LLDB_LOGF( 23509dba64beSDimitry Andric log, 23510b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", 23520b57cec5SDimitry Andric __FUNCTION__, h_variant); 23530b57cec5SDimitry Andric return SendIllFormedResponse(packet, 23540b57cec5SDimitry Andric "H variant unsupported, should be c or g"); 23550b57cec5SDimitry Andric } 23560b57cec5SDimitry Andric 23570b57cec5SDimitry Andric // Parse out the thread number. 2358fe6060f1SDimitry Andric auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID() 2359fe6060f1SDimitry Andric : LLDB_INVALID_PROCESS_ID); 2360fe6060f1SDimitry Andric if (!pid_tid) 2361fe6060f1SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 2362fe6060f1SDimitry Andric inconvertibleErrorCode(), "Malformed thread-id")); 2363fe6060f1SDimitry Andric 2364fe6060f1SDimitry Andric lldb::pid_t pid = pid_tid->first; 2365fe6060f1SDimitry Andric lldb::tid_t tid = pid_tid->second; 2366fe6060f1SDimitry Andric 2367fe6060f1SDimitry Andric if (pid == StringExtractorGDBRemote::AllProcesses) 2368fe6060f1SDimitry Andric return SendUnimplementedResponse("Selecting all processes not supported"); 2369fe6060f1SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 2370fe6060f1SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 2371fe6060f1SDimitry Andric inconvertibleErrorCode(), "No current process and no PID provided")); 2372fe6060f1SDimitry Andric 2373fe6060f1SDimitry Andric // Check the process ID and find respective process instance. 2374fe6060f1SDimitry Andric auto new_process_it = m_debugged_processes.find(pid); 2375fe6060f1SDimitry Andric if (new_process_it == m_debugged_processes.end()) 2376fe6060f1SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 2377fe6060f1SDimitry Andric inconvertibleErrorCode(), 2378fe6060f1SDimitry Andric llvm::formatv("No process with PID {0} debugged", pid))); 23790b57cec5SDimitry Andric 23800b57cec5SDimitry Andric // Ensure we have the given thread when not specifying -1 (all threads) or 0 23810b57cec5SDimitry Andric // (any thread). 23820b57cec5SDimitry Andric if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { 2383fcaf7f86SDimitry Andric NativeThreadProtocol *thread = 2384fcaf7f86SDimitry Andric new_process_it->second.process_up->GetThreadByID(tid); 23850b57cec5SDimitry Andric if (!thread) { 23869dba64beSDimitry Andric LLDB_LOGF(log, 23879dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 23880b57cec5SDimitry Andric " not found", 23890b57cec5SDimitry Andric __FUNCTION__, tid); 23900b57cec5SDimitry Andric return SendErrorResponse(0x15); 23910b57cec5SDimitry Andric } 23920b57cec5SDimitry Andric } 23930b57cec5SDimitry Andric 2394fe6060f1SDimitry Andric // Now switch the given process and thread type. 23950b57cec5SDimitry Andric switch (h_variant) { 23960b57cec5SDimitry Andric case 'g': 2397fcaf7f86SDimitry Andric m_current_process = new_process_it->second.process_up.get(); 23980b57cec5SDimitry Andric SetCurrentThreadID(tid); 23990b57cec5SDimitry Andric break; 24000b57cec5SDimitry Andric 24010b57cec5SDimitry Andric case 'c': 2402fcaf7f86SDimitry Andric m_continue_process = new_process_it->second.process_up.get(); 24030b57cec5SDimitry Andric SetContinueThreadID(tid); 24040b57cec5SDimitry Andric break; 24050b57cec5SDimitry Andric 24060b57cec5SDimitry Andric default: 24070b57cec5SDimitry Andric assert(false && "unsupported $H variant - shouldn't get here"); 24080b57cec5SDimitry Andric return SendIllFormedResponse(packet, 24090b57cec5SDimitry Andric "H variant unsupported, should be c or g"); 24100b57cec5SDimitry Andric } 24110b57cec5SDimitry Andric 24120b57cec5SDimitry Andric return SendOKResponse(); 24130b57cec5SDimitry Andric } 24140b57cec5SDimitry Andric 24150b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 24160b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { 241781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 24180b57cec5SDimitry Andric 24190b57cec5SDimitry Andric // Fail if we don't have a current process. 2420fe6060f1SDimitry Andric if (!m_current_process || 2421fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 24229dba64beSDimitry Andric LLDB_LOGF( 24239dba64beSDimitry Andric log, 24240b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 24250b57cec5SDimitry Andric __FUNCTION__); 24260b57cec5SDimitry Andric return SendErrorResponse(0x15); 24270b57cec5SDimitry Andric } 24280b57cec5SDimitry Andric 24290b57cec5SDimitry Andric packet.SetFilePos(::strlen("I")); 24300b57cec5SDimitry Andric uint8_t tmp[4096]; 24310b57cec5SDimitry Andric for (;;) { 24320b57cec5SDimitry Andric size_t read = packet.GetHexBytesAvail(tmp); 24330b57cec5SDimitry Andric if (read == 0) { 24340b57cec5SDimitry Andric break; 24350b57cec5SDimitry Andric } 24360b57cec5SDimitry Andric // write directly to stdin *this might block if stdin buffer is full* 24370b57cec5SDimitry Andric // TODO: enqueue this block in circular buffer and send window size to 24380b57cec5SDimitry Andric // remote host 24390b57cec5SDimitry Andric ConnectionStatus status; 24400b57cec5SDimitry Andric Status error; 2441bdd1243dSDimitry Andric m_stdio_communication.WriteAll(tmp, read, status, &error); 24420b57cec5SDimitry Andric if (error.Fail()) { 24430b57cec5SDimitry Andric return SendErrorResponse(0x15); 24440b57cec5SDimitry Andric } 24450b57cec5SDimitry Andric } 24460b57cec5SDimitry Andric 24470b57cec5SDimitry Andric return SendOKResponse(); 24480b57cec5SDimitry Andric } 24490b57cec5SDimitry Andric 24500b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 24510b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_interrupt( 24520b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 245381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 24540b57cec5SDimitry Andric 24550b57cec5SDimitry Andric // Fail if we don't have a current process. 2456fe6060f1SDimitry Andric if (!m_current_process || 2457fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 24580b57cec5SDimitry Andric LLDB_LOG(log, "failed, no process available"); 24590b57cec5SDimitry Andric return SendErrorResponse(0x15); 24600b57cec5SDimitry Andric } 24610b57cec5SDimitry Andric 24620b57cec5SDimitry Andric // Interrupt the process. 2463fe6060f1SDimitry Andric Status error = m_current_process->Interrupt(); 24640b57cec5SDimitry Andric if (error.Fail()) { 2465fe6060f1SDimitry Andric LLDB_LOG(log, "failed for process {0}: {1}", m_current_process->GetID(), 24660b57cec5SDimitry Andric error); 24670b57cec5SDimitry Andric return SendErrorResponse(GDBRemoteServerError::eErrorResume); 24680b57cec5SDimitry Andric } 24690b57cec5SDimitry Andric 2470fe6060f1SDimitry Andric LLDB_LOG(log, "stopped process {0}", m_current_process->GetID()); 24710b57cec5SDimitry Andric 24720b57cec5SDimitry Andric // No response required from stop all. 24730b57cec5SDimitry Andric return PacketResult::Success; 24740b57cec5SDimitry Andric } 24750b57cec5SDimitry Andric 24760b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 24770b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_memory_read( 24780b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 247981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 24800b57cec5SDimitry Andric 2481fe6060f1SDimitry Andric if (!m_current_process || 2482fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 24839dba64beSDimitry Andric LLDB_LOGF( 24849dba64beSDimitry Andric log, 24850b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 24860b57cec5SDimitry Andric __FUNCTION__); 24870b57cec5SDimitry Andric return SendErrorResponse(0x15); 24880b57cec5SDimitry Andric } 24890b57cec5SDimitry Andric 24900b57cec5SDimitry Andric // Parse out the memory address. 24910b57cec5SDimitry Andric packet.SetFilePos(strlen("m")); 24920b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 24930b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short m packet"); 24940b57cec5SDimitry Andric 24950b57cec5SDimitry Andric // Read the address. Punting on validation. 24960b57cec5SDimitry Andric // FIXME replace with Hex U64 read with no default value that fails on failed 24970b57cec5SDimitry Andric // read. 24980b57cec5SDimitry Andric const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); 24990b57cec5SDimitry Andric 25000b57cec5SDimitry Andric // Validate comma. 25010b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) 25020b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Comma sep missing in m packet"); 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric // Get # bytes to read. 25050b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 25060b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Length missing in m packet"); 25070b57cec5SDimitry Andric 25080b57cec5SDimitry Andric const uint64_t byte_count = packet.GetHexMaxU64(false, 0); 25090b57cec5SDimitry Andric if (byte_count == 0) { 25109dba64beSDimitry Andric LLDB_LOGF(log, 25119dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s nothing to read: " 25120b57cec5SDimitry Andric "zero-length packet", 25130b57cec5SDimitry Andric __FUNCTION__); 25140b57cec5SDimitry Andric return SendOKResponse(); 25150b57cec5SDimitry Andric } 25160b57cec5SDimitry Andric 25170b57cec5SDimitry Andric // Allocate the response buffer. 25180b57cec5SDimitry Andric std::string buf(byte_count, '\0'); 25190b57cec5SDimitry Andric if (buf.empty()) 25200b57cec5SDimitry Andric return SendErrorResponse(0x78); 25210b57cec5SDimitry Andric 25220b57cec5SDimitry Andric // Retrieve the process memory. 25230b57cec5SDimitry Andric size_t bytes_read = 0; 2524fe6060f1SDimitry Andric Status error = m_current_process->ReadMemoryWithoutTrap( 25250b57cec5SDimitry Andric read_addr, &buf[0], byte_count, bytes_read); 25260b57cec5SDimitry Andric if (error.Fail()) { 25279dba64beSDimitry Andric LLDB_LOGF(log, 25289dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 25290b57cec5SDimitry Andric " mem 0x%" PRIx64 ": failed to read. Error: %s", 2530fe6060f1SDimitry Andric __FUNCTION__, m_current_process->GetID(), read_addr, 25310b57cec5SDimitry Andric error.AsCString()); 25320b57cec5SDimitry Andric return SendErrorResponse(0x08); 25330b57cec5SDimitry Andric } 25340b57cec5SDimitry Andric 25350b57cec5SDimitry Andric if (bytes_read == 0) { 25369dba64beSDimitry Andric LLDB_LOGF(log, 25379dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 25380b57cec5SDimitry Andric " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", 2539fe6060f1SDimitry Andric __FUNCTION__, m_current_process->GetID(), read_addr, byte_count); 25400b57cec5SDimitry Andric return SendErrorResponse(0x08); 25410b57cec5SDimitry Andric } 25420b57cec5SDimitry Andric 25430b57cec5SDimitry Andric StreamGDBRemote response; 25440b57cec5SDimitry Andric packet.SetFilePos(0); 25450b57cec5SDimitry Andric char kind = packet.GetChar('?'); 25460b57cec5SDimitry Andric if (kind == 'x') 25470b57cec5SDimitry Andric response.PutEscapedBytes(buf.data(), byte_count); 25480b57cec5SDimitry Andric else { 25490b57cec5SDimitry Andric assert(kind == 'm'); 25500b57cec5SDimitry Andric for (size_t i = 0; i < bytes_read; ++i) 25510b57cec5SDimitry Andric response.PutHex8(buf[i]); 25520b57cec5SDimitry Andric } 25530b57cec5SDimitry Andric 25540b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 25550b57cec5SDimitry Andric } 25560b57cec5SDimitry Andric 25570b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 2558e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) { 255981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 2560e8d8bef9SDimitry Andric 2561fe6060f1SDimitry Andric if (!m_current_process || 2562fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 2563e8d8bef9SDimitry Andric LLDB_LOGF( 2564e8d8bef9SDimitry Andric log, 2565e8d8bef9SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 2566e8d8bef9SDimitry Andric __FUNCTION__); 2567e8d8bef9SDimitry Andric return SendErrorResponse(0x15); 2568e8d8bef9SDimitry Andric } 2569e8d8bef9SDimitry Andric 2570e8d8bef9SDimitry Andric // Parse out the memory address. 2571e8d8bef9SDimitry Andric packet.SetFilePos(strlen("_M")); 2572e8d8bef9SDimitry Andric if (packet.GetBytesLeft() < 1) 2573e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Too short _M packet"); 2574e8d8bef9SDimitry Andric 2575e8d8bef9SDimitry Andric const lldb::addr_t size = packet.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 2576e8d8bef9SDimitry Andric if (size == LLDB_INVALID_ADDRESS) 2577e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Address not valid"); 2578e8d8bef9SDimitry Andric if (packet.GetChar() != ',') 2579e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Bad packet"); 2580e8d8bef9SDimitry Andric Permissions perms = {}; 2581e8d8bef9SDimitry Andric while (packet.GetBytesLeft() > 0) { 2582e8d8bef9SDimitry Andric switch (packet.GetChar()) { 2583e8d8bef9SDimitry Andric case 'r': 2584e8d8bef9SDimitry Andric perms |= ePermissionsReadable; 2585e8d8bef9SDimitry Andric break; 2586e8d8bef9SDimitry Andric case 'w': 2587e8d8bef9SDimitry Andric perms |= ePermissionsWritable; 2588e8d8bef9SDimitry Andric break; 2589e8d8bef9SDimitry Andric case 'x': 2590e8d8bef9SDimitry Andric perms |= ePermissionsExecutable; 2591e8d8bef9SDimitry Andric break; 2592e8d8bef9SDimitry Andric default: 2593e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Bad permissions"); 2594e8d8bef9SDimitry Andric } 2595e8d8bef9SDimitry Andric } 2596e8d8bef9SDimitry Andric 2597fe6060f1SDimitry Andric llvm::Expected<addr_t> addr = m_current_process->AllocateMemory(size, perms); 2598e8d8bef9SDimitry Andric if (!addr) 2599e8d8bef9SDimitry Andric return SendErrorResponse(addr.takeError()); 2600e8d8bef9SDimitry Andric 2601e8d8bef9SDimitry Andric StreamGDBRemote response; 2602e8d8bef9SDimitry Andric response.PutHex64(*addr); 2603e8d8bef9SDimitry Andric return SendPacketNoLock(response.GetString()); 2604e8d8bef9SDimitry Andric } 2605e8d8bef9SDimitry Andric 2606e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 2607e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) { 260881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 2609e8d8bef9SDimitry Andric 2610fe6060f1SDimitry Andric if (!m_current_process || 2611fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 2612e8d8bef9SDimitry Andric LLDB_LOGF( 2613e8d8bef9SDimitry Andric log, 2614e8d8bef9SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 2615e8d8bef9SDimitry Andric __FUNCTION__); 2616e8d8bef9SDimitry Andric return SendErrorResponse(0x15); 2617e8d8bef9SDimitry Andric } 2618e8d8bef9SDimitry Andric 2619e8d8bef9SDimitry Andric // Parse out the memory address. 2620e8d8bef9SDimitry Andric packet.SetFilePos(strlen("_m")); 2621e8d8bef9SDimitry Andric if (packet.GetBytesLeft() < 1) 2622e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Too short m packet"); 2623e8d8bef9SDimitry Andric 2624e8d8bef9SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); 2625e8d8bef9SDimitry Andric if (addr == LLDB_INVALID_ADDRESS) 2626e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "Address not valid"); 2627e8d8bef9SDimitry Andric 2628fe6060f1SDimitry Andric if (llvm::Error Err = m_current_process->DeallocateMemory(addr)) 2629e8d8bef9SDimitry Andric return SendErrorResponse(std::move(Err)); 2630e8d8bef9SDimitry Andric 2631e8d8bef9SDimitry Andric return SendOKResponse(); 2632e8d8bef9SDimitry Andric } 2633e8d8bef9SDimitry Andric 2634e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 26350b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { 263681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 26370b57cec5SDimitry Andric 2638fe6060f1SDimitry Andric if (!m_current_process || 2639fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 26409dba64beSDimitry Andric LLDB_LOGF( 26419dba64beSDimitry Andric log, 26420b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 26430b57cec5SDimitry Andric __FUNCTION__); 26440b57cec5SDimitry Andric return SendErrorResponse(0x15); 26450b57cec5SDimitry Andric } 26460b57cec5SDimitry Andric 26470b57cec5SDimitry Andric // Parse out the memory address. 26480b57cec5SDimitry Andric packet.SetFilePos(strlen("M")); 26490b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 26500b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short M packet"); 26510b57cec5SDimitry Andric 26520b57cec5SDimitry Andric // Read the address. Punting on validation. 26530b57cec5SDimitry Andric // FIXME replace with Hex U64 read with no default value that fails on failed 26540b57cec5SDimitry Andric // read. 26550b57cec5SDimitry Andric const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0); 26560b57cec5SDimitry Andric 26570b57cec5SDimitry Andric // Validate comma. 26580b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) 26590b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Comma sep missing in M packet"); 26600b57cec5SDimitry Andric 26610b57cec5SDimitry Andric // Get # bytes to read. 26620b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 26630b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Length missing in M packet"); 26640b57cec5SDimitry Andric 26650b57cec5SDimitry Andric const uint64_t byte_count = packet.GetHexMaxU64(false, 0); 26660b57cec5SDimitry Andric if (byte_count == 0) { 26670b57cec5SDimitry Andric LLDB_LOG(log, "nothing to write: zero-length packet"); 26680b57cec5SDimitry Andric return PacketResult::Success; 26690b57cec5SDimitry Andric } 26700b57cec5SDimitry Andric 26710b57cec5SDimitry Andric // Validate colon. 26720b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':')) 26730b57cec5SDimitry Andric return SendIllFormedResponse( 26740b57cec5SDimitry Andric packet, "Comma sep missing in M packet after byte length"); 26750b57cec5SDimitry Andric 26760b57cec5SDimitry Andric // Allocate the conversion buffer. 26770b57cec5SDimitry Andric std::vector<uint8_t> buf(byte_count, 0); 26780b57cec5SDimitry Andric if (buf.empty()) 26790b57cec5SDimitry Andric return SendErrorResponse(0x78); 26800b57cec5SDimitry Andric 26810b57cec5SDimitry Andric // Convert the hex memory write contents to bytes. 26820b57cec5SDimitry Andric StreamGDBRemote response; 26830b57cec5SDimitry Andric const uint64_t convert_count = packet.GetHexBytes(buf, 0); 26840b57cec5SDimitry Andric if (convert_count != byte_count) { 26850b57cec5SDimitry Andric LLDB_LOG(log, 26860b57cec5SDimitry Andric "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " 26870b57cec5SDimitry Andric "to convert.", 2688fe6060f1SDimitry Andric m_current_process->GetID(), write_addr, byte_count, convert_count); 26890b57cec5SDimitry Andric return SendIllFormedResponse(packet, "M content byte length specified did " 26900b57cec5SDimitry Andric "not match hex-encoded content " 26910b57cec5SDimitry Andric "length"); 26920b57cec5SDimitry Andric } 26930b57cec5SDimitry Andric 26940b57cec5SDimitry Andric // Write the process memory. 26950b57cec5SDimitry Andric size_t bytes_written = 0; 2696fe6060f1SDimitry Andric Status error = m_current_process->WriteMemory(write_addr, &buf[0], byte_count, 2697fe6060f1SDimitry Andric bytes_written); 26980b57cec5SDimitry Andric if (error.Fail()) { 26990b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}", 2700fe6060f1SDimitry Andric m_current_process->GetID(), write_addr, error); 27010b57cec5SDimitry Andric return SendErrorResponse(0x09); 27020b57cec5SDimitry Andric } 27030b57cec5SDimitry Andric 27040b57cec5SDimitry Andric if (bytes_written == 0) { 27050b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes", 2706fe6060f1SDimitry Andric m_current_process->GetID(), write_addr, byte_count); 27070b57cec5SDimitry Andric return SendErrorResponse(0x09); 27080b57cec5SDimitry Andric } 27090b57cec5SDimitry Andric 27100b57cec5SDimitry Andric return SendOKResponse(); 27110b57cec5SDimitry Andric } 27120b57cec5SDimitry Andric 27130b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 27140b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( 27150b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 271681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 27170b57cec5SDimitry Andric 27180b57cec5SDimitry Andric // Currently only the NativeProcessProtocol knows if it can handle a 27190b57cec5SDimitry Andric // qMemoryRegionInfoSupported request, but we're not guaranteed to be 27200b57cec5SDimitry Andric // attached to a process. For now we'll assume the client only asks this 27210b57cec5SDimitry Andric // when a process is being debugged. 27220b57cec5SDimitry Andric 27230b57cec5SDimitry Andric // Ensure we have a process running; otherwise, we can't figure this out 27240b57cec5SDimitry Andric // since we won't have a NativeProcessProtocol. 2725fe6060f1SDimitry Andric if (!m_current_process || 2726fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 27279dba64beSDimitry Andric LLDB_LOGF( 27289dba64beSDimitry Andric log, 27290b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 27300b57cec5SDimitry Andric __FUNCTION__); 27310b57cec5SDimitry Andric return SendErrorResponse(0x15); 27320b57cec5SDimitry Andric } 27330b57cec5SDimitry Andric 27340b57cec5SDimitry Andric // Test if we can get any region back when asking for the region around NULL. 27350b57cec5SDimitry Andric MemoryRegionInfo region_info; 2736fe6060f1SDimitry Andric const Status error = m_current_process->GetMemoryRegionInfo(0, region_info); 27370b57cec5SDimitry Andric if (error.Fail()) { 27380b57cec5SDimitry Andric // We don't support memory region info collection for this 27390b57cec5SDimitry Andric // NativeProcessProtocol. 27400b57cec5SDimitry Andric return SendUnimplementedResponse(""); 27410b57cec5SDimitry Andric } 27420b57cec5SDimitry Andric 27430b57cec5SDimitry Andric return SendOKResponse(); 27440b57cec5SDimitry Andric } 27450b57cec5SDimitry Andric 27460b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 27470b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( 27480b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 274981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 27500b57cec5SDimitry Andric 27510b57cec5SDimitry Andric // Ensure we have a process. 2752fe6060f1SDimitry Andric if (!m_current_process || 2753fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 27549dba64beSDimitry Andric LLDB_LOGF( 27559dba64beSDimitry Andric log, 27560b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 27570b57cec5SDimitry Andric __FUNCTION__); 27580b57cec5SDimitry Andric return SendErrorResponse(0x15); 27590b57cec5SDimitry Andric } 27600b57cec5SDimitry Andric 27610b57cec5SDimitry Andric // Parse out the memory address. 27620b57cec5SDimitry Andric packet.SetFilePos(strlen("qMemoryRegionInfo:")); 27630b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 27640b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet"); 27650b57cec5SDimitry Andric 27660b57cec5SDimitry Andric // Read the address. Punting on validation. 27670b57cec5SDimitry Andric const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); 27680b57cec5SDimitry Andric 27690b57cec5SDimitry Andric StreamGDBRemote response; 27700b57cec5SDimitry Andric 27710b57cec5SDimitry Andric // Get the memory region info for the target address. 27720b57cec5SDimitry Andric MemoryRegionInfo region_info; 27730b57cec5SDimitry Andric const Status error = 2774fe6060f1SDimitry Andric m_current_process->GetMemoryRegionInfo(read_addr, region_info); 27750b57cec5SDimitry Andric if (error.Fail()) { 27760b57cec5SDimitry Andric // Return the error message. 27770b57cec5SDimitry Andric 27780b57cec5SDimitry Andric response.PutCString("error:"); 27790b57cec5SDimitry Andric response.PutStringAsRawHex8(error.AsCString()); 27800b57cec5SDimitry Andric response.PutChar(';'); 27810b57cec5SDimitry Andric } else { 27820b57cec5SDimitry Andric // Range start and size. 27830b57cec5SDimitry Andric response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";", 27840b57cec5SDimitry Andric region_info.GetRange().GetRangeBase(), 27850b57cec5SDimitry Andric region_info.GetRange().GetByteSize()); 27860b57cec5SDimitry Andric 27870b57cec5SDimitry Andric // Permissions. 27880b57cec5SDimitry Andric if (region_info.GetReadable() || region_info.GetWritable() || 27890b57cec5SDimitry Andric region_info.GetExecutable()) { 27900b57cec5SDimitry Andric // Write permissions info. 27910b57cec5SDimitry Andric response.PutCString("permissions:"); 27920b57cec5SDimitry Andric 27930b57cec5SDimitry Andric if (region_info.GetReadable()) 27940b57cec5SDimitry Andric response.PutChar('r'); 27950b57cec5SDimitry Andric if (region_info.GetWritable()) 27960b57cec5SDimitry Andric response.PutChar('w'); 27970b57cec5SDimitry Andric if (region_info.GetExecutable()) 27980b57cec5SDimitry Andric response.PutChar('x'); 27990b57cec5SDimitry Andric 28000b57cec5SDimitry Andric response.PutChar(';'); 28010b57cec5SDimitry Andric } 28020b57cec5SDimitry Andric 2803e8d8bef9SDimitry Andric // Flags 2804e8d8bef9SDimitry Andric MemoryRegionInfo::OptionalBool memory_tagged = 2805e8d8bef9SDimitry Andric region_info.GetMemoryTagged(); 2806e8d8bef9SDimitry Andric if (memory_tagged != MemoryRegionInfo::eDontKnow) { 2807e8d8bef9SDimitry Andric response.PutCString("flags:"); 2808e8d8bef9SDimitry Andric if (memory_tagged == MemoryRegionInfo::eYes) { 2809e8d8bef9SDimitry Andric response.PutCString("mt"); 2810e8d8bef9SDimitry Andric } 2811e8d8bef9SDimitry Andric response.PutChar(';'); 2812e8d8bef9SDimitry Andric } 2813e8d8bef9SDimitry Andric 28140b57cec5SDimitry Andric // Name 28150b57cec5SDimitry Andric ConstString name = region_info.GetName(); 28160b57cec5SDimitry Andric if (name) { 28170b57cec5SDimitry Andric response.PutCString("name:"); 28185ffd83dbSDimitry Andric response.PutStringAsRawHex8(name.GetStringRef()); 28190b57cec5SDimitry Andric response.PutChar(';'); 28200b57cec5SDimitry Andric } 28210b57cec5SDimitry Andric } 28220b57cec5SDimitry Andric 28230b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 28240b57cec5SDimitry Andric } 28250b57cec5SDimitry Andric 28260b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 28270b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { 28280b57cec5SDimitry Andric // Ensure we have a process. 2829fe6060f1SDimitry Andric if (!m_current_process || 2830fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 283181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 28320b57cec5SDimitry Andric LLDB_LOG(log, "failed, no process available"); 28330b57cec5SDimitry Andric return SendErrorResponse(0x15); 28340b57cec5SDimitry Andric } 28350b57cec5SDimitry Andric 28360b57cec5SDimitry Andric // Parse out software or hardware breakpoint or watchpoint requested. 28370b57cec5SDimitry Andric packet.SetFilePos(strlen("Z")); 28380b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 28390b57cec5SDimitry Andric return SendIllFormedResponse( 28400b57cec5SDimitry Andric packet, "Too short Z packet, missing software/hardware specifier"); 28410b57cec5SDimitry Andric 28420b57cec5SDimitry Andric bool want_breakpoint = true; 28430b57cec5SDimitry Andric bool want_hardware = false; 28440b57cec5SDimitry Andric uint32_t watch_flags = 0; 28450b57cec5SDimitry Andric 28460b57cec5SDimitry Andric const GDBStoppointType stoppoint_type = 28470b57cec5SDimitry Andric GDBStoppointType(packet.GetS32(eStoppointInvalid)); 28480b57cec5SDimitry Andric switch (stoppoint_type) { 28490b57cec5SDimitry Andric case eBreakpointSoftware: 28500b57cec5SDimitry Andric want_hardware = false; 28510b57cec5SDimitry Andric want_breakpoint = true; 28520b57cec5SDimitry Andric break; 28530b57cec5SDimitry Andric case eBreakpointHardware: 28540b57cec5SDimitry Andric want_hardware = true; 28550b57cec5SDimitry Andric want_breakpoint = true; 28560b57cec5SDimitry Andric break; 28570b57cec5SDimitry Andric case eWatchpointWrite: 28580b57cec5SDimitry Andric watch_flags = 1; 28590b57cec5SDimitry Andric want_hardware = true; 28600b57cec5SDimitry Andric want_breakpoint = false; 28610b57cec5SDimitry Andric break; 28620b57cec5SDimitry Andric case eWatchpointRead: 28630b57cec5SDimitry Andric watch_flags = 2; 28640b57cec5SDimitry Andric want_hardware = true; 28650b57cec5SDimitry Andric want_breakpoint = false; 28660b57cec5SDimitry Andric break; 28670b57cec5SDimitry Andric case eWatchpointReadWrite: 28680b57cec5SDimitry Andric watch_flags = 3; 28690b57cec5SDimitry Andric want_hardware = true; 28700b57cec5SDimitry Andric want_breakpoint = false; 28710b57cec5SDimitry Andric break; 28720b57cec5SDimitry Andric case eStoppointInvalid: 28730b57cec5SDimitry Andric return SendIllFormedResponse( 28740b57cec5SDimitry Andric packet, "Z packet had invalid software/hardware specifier"); 28750b57cec5SDimitry Andric } 28760b57cec5SDimitry Andric 28770b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') 28780b57cec5SDimitry Andric return SendIllFormedResponse( 28790b57cec5SDimitry Andric packet, "Malformed Z packet, expecting comma after stoppoint type"); 28800b57cec5SDimitry Andric 28810b57cec5SDimitry Andric // Parse out the stoppoint address. 28820b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 28830b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short Z packet, missing address"); 28840b57cec5SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); 28850b57cec5SDimitry Andric 28860b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') 28870b57cec5SDimitry Andric return SendIllFormedResponse( 28880b57cec5SDimitry Andric packet, "Malformed Z packet, expecting comma after address"); 28890b57cec5SDimitry Andric 28900b57cec5SDimitry Andric // Parse out the stoppoint size (i.e. size hint for opcode size). 28910b57cec5SDimitry Andric const uint32_t size = 28920b57cec5SDimitry Andric packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); 28930b57cec5SDimitry Andric if (size == std::numeric_limits<uint32_t>::max()) 28940b57cec5SDimitry Andric return SendIllFormedResponse( 28950b57cec5SDimitry Andric packet, "Malformed Z packet, failed to parse size argument"); 28960b57cec5SDimitry Andric 28970b57cec5SDimitry Andric if (want_breakpoint) { 28980b57cec5SDimitry Andric // Try to set the breakpoint. 28990b57cec5SDimitry Andric const Status error = 2900fe6060f1SDimitry Andric m_current_process->SetBreakpoint(addr, size, want_hardware); 29010b57cec5SDimitry Andric if (error.Success()) 29020b57cec5SDimitry Andric return SendOKResponse(); 290381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Breakpoints); 29040b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}", 2905fe6060f1SDimitry Andric m_current_process->GetID(), error); 29060b57cec5SDimitry Andric return SendErrorResponse(0x09); 29070b57cec5SDimitry Andric } else { 29080b57cec5SDimitry Andric // Try to set the watchpoint. 2909fe6060f1SDimitry Andric const Status error = m_current_process->SetWatchpoint( 29100b57cec5SDimitry Andric addr, size, watch_flags, want_hardware); 29110b57cec5SDimitry Andric if (error.Success()) 29120b57cec5SDimitry Andric return SendOKResponse(); 291381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Watchpoints); 29140b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}", 2915fe6060f1SDimitry Andric m_current_process->GetID(), error); 29160b57cec5SDimitry Andric return SendErrorResponse(0x09); 29170b57cec5SDimitry Andric } 29180b57cec5SDimitry Andric } 29190b57cec5SDimitry Andric 29200b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 29210b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { 29220b57cec5SDimitry Andric // Ensure we have a process. 2923fe6060f1SDimitry Andric if (!m_current_process || 2924fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 292581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 29260b57cec5SDimitry Andric LLDB_LOG(log, "failed, no process available"); 29270b57cec5SDimitry Andric return SendErrorResponse(0x15); 29280b57cec5SDimitry Andric } 29290b57cec5SDimitry Andric 29300b57cec5SDimitry Andric // Parse out software or hardware breakpoint or watchpoint requested. 29310b57cec5SDimitry Andric packet.SetFilePos(strlen("z")); 29320b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 29330b57cec5SDimitry Andric return SendIllFormedResponse( 29340b57cec5SDimitry Andric packet, "Too short z packet, missing software/hardware specifier"); 29350b57cec5SDimitry Andric 29360b57cec5SDimitry Andric bool want_breakpoint = true; 29370b57cec5SDimitry Andric bool want_hardware = false; 29380b57cec5SDimitry Andric 29390b57cec5SDimitry Andric const GDBStoppointType stoppoint_type = 29400b57cec5SDimitry Andric GDBStoppointType(packet.GetS32(eStoppointInvalid)); 29410b57cec5SDimitry Andric switch (stoppoint_type) { 29420b57cec5SDimitry Andric case eBreakpointHardware: 29430b57cec5SDimitry Andric want_breakpoint = true; 29440b57cec5SDimitry Andric want_hardware = true; 29450b57cec5SDimitry Andric break; 29460b57cec5SDimitry Andric case eBreakpointSoftware: 29470b57cec5SDimitry Andric want_breakpoint = true; 29480b57cec5SDimitry Andric break; 29490b57cec5SDimitry Andric case eWatchpointWrite: 29500b57cec5SDimitry Andric want_breakpoint = false; 29510b57cec5SDimitry Andric break; 29520b57cec5SDimitry Andric case eWatchpointRead: 29530b57cec5SDimitry Andric want_breakpoint = false; 29540b57cec5SDimitry Andric break; 29550b57cec5SDimitry Andric case eWatchpointReadWrite: 29560b57cec5SDimitry Andric want_breakpoint = false; 29570b57cec5SDimitry Andric break; 29580b57cec5SDimitry Andric default: 29590b57cec5SDimitry Andric return SendIllFormedResponse( 29600b57cec5SDimitry Andric packet, "z packet had invalid software/hardware specifier"); 29610b57cec5SDimitry Andric } 29620b57cec5SDimitry Andric 29630b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') 29640b57cec5SDimitry Andric return SendIllFormedResponse( 29650b57cec5SDimitry Andric packet, "Malformed z packet, expecting comma after stoppoint type"); 29660b57cec5SDimitry Andric 29670b57cec5SDimitry Andric // Parse out the stoppoint address. 29680b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 29690b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Too short z packet, missing address"); 29700b57cec5SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); 29710b57cec5SDimitry Andric 29720b57cec5SDimitry Andric if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') 29730b57cec5SDimitry Andric return SendIllFormedResponse( 29740b57cec5SDimitry Andric packet, "Malformed z packet, expecting comma after address"); 29750b57cec5SDimitry Andric 29760b57cec5SDimitry Andric /* 29770b57cec5SDimitry Andric // Parse out the stoppoint size (i.e. size hint for opcode size). 29780b57cec5SDimitry Andric const uint32_t size = packet.GetHexMaxU32 (false, 29790b57cec5SDimitry Andric std::numeric_limits<uint32_t>::max ()); 29800b57cec5SDimitry Andric if (size == std::numeric_limits<uint32_t>::max ()) 29810b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Malformed z packet, failed to parse 29820b57cec5SDimitry Andric size argument"); 29830b57cec5SDimitry Andric */ 29840b57cec5SDimitry Andric 29850b57cec5SDimitry Andric if (want_breakpoint) { 29860b57cec5SDimitry Andric // Try to clear the breakpoint. 29870b57cec5SDimitry Andric const Status error = 2988fe6060f1SDimitry Andric m_current_process->RemoveBreakpoint(addr, want_hardware); 29890b57cec5SDimitry Andric if (error.Success()) 29900b57cec5SDimitry Andric return SendOKResponse(); 299181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Breakpoints); 29920b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}", 2993fe6060f1SDimitry Andric m_current_process->GetID(), error); 29940b57cec5SDimitry Andric return SendErrorResponse(0x09); 29950b57cec5SDimitry Andric } else { 29960b57cec5SDimitry Andric // Try to clear the watchpoint. 2997fe6060f1SDimitry Andric const Status error = m_current_process->RemoveWatchpoint(addr); 29980b57cec5SDimitry Andric if (error.Success()) 29990b57cec5SDimitry Andric return SendOKResponse(); 300081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Watchpoints); 30010b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}", 3002fe6060f1SDimitry Andric m_current_process->GetID(), error); 30030b57cec5SDimitry Andric return SendErrorResponse(0x09); 30040b57cec5SDimitry Andric } 30050b57cec5SDimitry Andric } 30060b57cec5SDimitry Andric 30070b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 30080b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { 300981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 30100b57cec5SDimitry Andric 30110b57cec5SDimitry Andric // Ensure we have a process. 3012fe6060f1SDimitry Andric if (!m_continue_process || 3013fe6060f1SDimitry Andric (m_continue_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 30149dba64beSDimitry Andric LLDB_LOGF( 30159dba64beSDimitry Andric log, 30160b57cec5SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 30170b57cec5SDimitry Andric __FUNCTION__); 30180b57cec5SDimitry Andric return SendErrorResponse(0x32); 30190b57cec5SDimitry Andric } 30200b57cec5SDimitry Andric 30210b57cec5SDimitry Andric // We first try to use a continue thread id. If any one or any all set, use 30220b57cec5SDimitry Andric // the current thread. Bail out if we don't have a thread id. 30230b57cec5SDimitry Andric lldb::tid_t tid = GetContinueThreadID(); 30240b57cec5SDimitry Andric if (tid == 0 || tid == LLDB_INVALID_THREAD_ID) 30250b57cec5SDimitry Andric tid = GetCurrentThreadID(); 30260b57cec5SDimitry Andric if (tid == LLDB_INVALID_THREAD_ID) 30270b57cec5SDimitry Andric return SendErrorResponse(0x33); 30280b57cec5SDimitry Andric 30290b57cec5SDimitry Andric // Double check that we have such a thread. 30300b57cec5SDimitry Andric // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. 3031fe6060f1SDimitry Andric NativeThreadProtocol *thread = m_continue_process->GetThreadByID(tid); 30320b57cec5SDimitry Andric if (!thread) 30330b57cec5SDimitry Andric return SendErrorResponse(0x33); 30340b57cec5SDimitry Andric 30350b57cec5SDimitry Andric // Create the step action for the given thread. 30369dba64beSDimitry Andric ResumeAction action = {tid, eStateStepping, LLDB_INVALID_SIGNAL_NUMBER}; 30370b57cec5SDimitry Andric 30380b57cec5SDimitry Andric // Setup the actions list. 30390b57cec5SDimitry Andric ResumeActionList actions; 30400b57cec5SDimitry Andric actions.Append(action); 30410b57cec5SDimitry Andric 30420b57cec5SDimitry Andric // All other threads stop while we're single stepping a thread. 30430b57cec5SDimitry Andric actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); 3044fcaf7f86SDimitry Andric 3045fcaf7f86SDimitry Andric PacketResult resume_res = ResumeProcess(*m_continue_process, actions); 3046fcaf7f86SDimitry Andric if (resume_res != PacketResult::Success) 3047fcaf7f86SDimitry Andric return resume_res; 30480b57cec5SDimitry Andric 304981ad6265SDimitry Andric // No response here, unless in non-stop mode. 305081ad6265SDimitry Andric // Otherwise, the stop or exit will come from the resulting action. 305181ad6265SDimitry Andric return SendContinueSuccessResponse(); 30520b57cec5SDimitry Andric } 30530b57cec5SDimitry Andric 30540b57cec5SDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> 30555ffd83dbSDimitry Andric GDBRemoteCommunicationServerLLGS::BuildTargetXml() { 30565ffd83dbSDimitry Andric // Ensure we have a thread. 3057fe6060f1SDimitry Andric NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0); 30585ffd83dbSDimitry Andric if (!thread) 30595ffd83dbSDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 30605ffd83dbSDimitry Andric "No thread available"); 30615ffd83dbSDimitry Andric 306281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 30635ffd83dbSDimitry Andric // Get the register context for the first thread. 30645ffd83dbSDimitry Andric NativeRegisterContext ®_context = thread->GetRegisterContext(); 30655ffd83dbSDimitry Andric 30665ffd83dbSDimitry Andric StreamString response; 30675ffd83dbSDimitry Andric 3068bdd1243dSDimitry Andric response.Printf("<?xml version=\"1.0\"?>\n"); 3069bdd1243dSDimitry Andric response.Printf("<target version=\"1.0\">\n"); 3070bdd1243dSDimitry Andric response.IndentMore(); 30715ffd83dbSDimitry Andric 3072bdd1243dSDimitry Andric response.Indent(); 3073bdd1243dSDimitry Andric response.Printf("<architecture>%s</architecture>\n", 3074fe6060f1SDimitry Andric m_current_process->GetArchitecture() 30755ffd83dbSDimitry Andric .GetTriple() 30765ffd83dbSDimitry Andric .getArchName() 30775ffd83dbSDimitry Andric .str() 30785ffd83dbSDimitry Andric .c_str()); 30795ffd83dbSDimitry Andric 3080bdd1243dSDimitry Andric response.Indent("<feature>\n"); 30815ffd83dbSDimitry Andric 30825ffd83dbSDimitry Andric const int registers_count = reg_context.GetUserRegisterCount(); 3083bdd1243dSDimitry Andric if (registers_count) 3084bdd1243dSDimitry Andric response.IndentMore(); 3085bdd1243dSDimitry Andric 3086*0fca6ea1SDimitry Andric llvm::StringSet<> field_enums_seen; 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 30985f757f3fSDimitry Andric if (reg_info->flags_type) { 30995f757f3fSDimitry Andric response.IndentMore(); 3100*0fca6ea1SDimitry Andric reg_info->flags_type->EnumsToXML(response, field_enums_seen); 31015f757f3fSDimitry Andric reg_info->flags_type->ToXML(response); 31025f757f3fSDimitry Andric response.IndentLess(); 31035f757f3fSDimitry Andric } 31045f757f3fSDimitry Andric 3105bdd1243dSDimitry Andric response.Indent(); 3106bdd1243dSDimitry Andric response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 3107bdd1243dSDimitry Andric "\" regnum=\"%d\" ", 3108e8d8bef9SDimitry Andric reg_info->name, reg_info->byte_size * 8, reg_index); 3109e8d8bef9SDimitry Andric 3110e8d8bef9SDimitry Andric if (!reg_context.RegisterOffsetIsDynamic()) 3111e8d8bef9SDimitry Andric response.Printf("offset=\"%" PRIu32 "\" ", reg_info->byte_offset); 31125ffd83dbSDimitry Andric 31135ffd83dbSDimitry Andric if (reg_info->alt_name && reg_info->alt_name[0]) 31145ffd83dbSDimitry Andric response.Printf("altname=\"%s\" ", reg_info->alt_name); 31155ffd83dbSDimitry Andric 31165ffd83dbSDimitry Andric llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info); 31175ffd83dbSDimitry Andric if (!encoding.empty()) 31185ffd83dbSDimitry Andric response << "encoding=\"" << encoding << "\" "; 31195ffd83dbSDimitry Andric 31205ffd83dbSDimitry Andric llvm::StringRef format = GetFormatNameOrEmpty(*reg_info); 31215ffd83dbSDimitry Andric if (!format.empty()) 31225ffd83dbSDimitry Andric response << "format=\"" << format << "\" "; 31235ffd83dbSDimitry Andric 31245f757f3fSDimitry Andric if (reg_info->flags_type) 31255f757f3fSDimitry Andric response << "type=\"" << reg_info->flags_type->GetID() << "\" "; 31265f757f3fSDimitry Andric 31275ffd83dbSDimitry Andric const char *const register_set_name = 31285ffd83dbSDimitry Andric reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); 31295ffd83dbSDimitry Andric if (register_set_name) 31305ffd83dbSDimitry Andric response << "group=\"" << register_set_name << "\" "; 31315ffd83dbSDimitry Andric 31325ffd83dbSDimitry Andric if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != 31335ffd83dbSDimitry Andric LLDB_INVALID_REGNUM) 31345ffd83dbSDimitry Andric response.Printf("ehframe_regnum=\"%" PRIu32 "\" ", 31355ffd83dbSDimitry Andric reg_info->kinds[RegisterKind::eRegisterKindEHFrame]); 31365ffd83dbSDimitry Andric 31375ffd83dbSDimitry Andric if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != 31385ffd83dbSDimitry Andric LLDB_INVALID_REGNUM) 31395ffd83dbSDimitry Andric response.Printf("dwarf_regnum=\"%" PRIu32 "\" ", 31405ffd83dbSDimitry Andric reg_info->kinds[RegisterKind::eRegisterKindDWARF]); 31415ffd83dbSDimitry Andric 31425ffd83dbSDimitry Andric llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info); 31435ffd83dbSDimitry Andric if (!kind_generic.empty()) 31445ffd83dbSDimitry Andric response << "generic=\"" << kind_generic << "\" "; 31455ffd83dbSDimitry Andric 31465ffd83dbSDimitry Andric if (reg_info->value_regs && 31475ffd83dbSDimitry Andric reg_info->value_regs[0] != LLDB_INVALID_REGNUM) { 31485ffd83dbSDimitry Andric response.PutCString("value_regnums=\""); 31495ffd83dbSDimitry Andric CollectRegNums(reg_info->value_regs, response, false); 31505ffd83dbSDimitry Andric response.Printf("\" "); 31515ffd83dbSDimitry Andric } 31525ffd83dbSDimitry Andric 31535ffd83dbSDimitry Andric if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) { 31545ffd83dbSDimitry Andric response.PutCString("invalidate_regnums=\""); 31555ffd83dbSDimitry Andric CollectRegNums(reg_info->invalidate_regs, response, false); 31565ffd83dbSDimitry Andric response.Printf("\" "); 31575ffd83dbSDimitry Andric } 31585ffd83dbSDimitry Andric 3159bdd1243dSDimitry Andric response.Printf("/>\n"); 31605ffd83dbSDimitry Andric } 31615ffd83dbSDimitry Andric 3162bdd1243dSDimitry Andric if (registers_count) 3163bdd1243dSDimitry Andric response.IndentLess(); 3164bdd1243dSDimitry Andric 3165bdd1243dSDimitry Andric response.Indent("</feature>\n"); 3166bdd1243dSDimitry Andric response.IndentLess(); 3167bdd1243dSDimitry Andric response.Indent("</target>\n"); 31685ffd83dbSDimitry Andric return MemoryBuffer::getMemBufferCopy(response.GetString(), "target.xml"); 31695ffd83dbSDimitry Andric } 31705ffd83dbSDimitry Andric 31715ffd83dbSDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> 31720b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, 31730b57cec5SDimitry Andric llvm::StringRef annex) { 31740b57cec5SDimitry Andric // Make sure we have a valid process. 3175fe6060f1SDimitry Andric if (!m_current_process || 3176fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 31770b57cec5SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 31780b57cec5SDimitry Andric "No process available"); 31790b57cec5SDimitry Andric } 31800b57cec5SDimitry Andric 31815ffd83dbSDimitry Andric if (object == "auxv") { 31820b57cec5SDimitry Andric // Grab the auxv data. 3183fe6060f1SDimitry Andric auto buffer_or_error = m_current_process->GetAuxvData(); 31840b57cec5SDimitry Andric if (!buffer_or_error) 31850b57cec5SDimitry Andric return llvm::errorCodeToError(buffer_or_error.getError()); 31860b57cec5SDimitry Andric return std::move(*buffer_or_error); 31870b57cec5SDimitry Andric } 31880b57cec5SDimitry Andric 318904eeddc0SDimitry Andric if (object == "siginfo") { 319004eeddc0SDimitry Andric NativeThreadProtocol *thread = m_current_process->GetCurrentThread(); 319104eeddc0SDimitry Andric if (!thread) 319204eeddc0SDimitry Andric return llvm::createStringError(llvm::inconvertibleErrorCode(), 319304eeddc0SDimitry Andric "no current thread"); 319404eeddc0SDimitry Andric 319504eeddc0SDimitry Andric auto buffer_or_error = thread->GetSiginfo(); 319604eeddc0SDimitry Andric if (!buffer_or_error) 319704eeddc0SDimitry Andric return buffer_or_error.takeError(); 319804eeddc0SDimitry Andric return std::move(*buffer_or_error); 319904eeddc0SDimitry Andric } 320004eeddc0SDimitry Andric 32019dba64beSDimitry Andric if (object == "libraries-svr4") { 3202fe6060f1SDimitry Andric auto library_list = m_current_process->GetLoadedSVR4Libraries(); 32039dba64beSDimitry Andric if (!library_list) 32049dba64beSDimitry Andric return library_list.takeError(); 32059dba64beSDimitry Andric 32069dba64beSDimitry Andric StreamString response; 32079dba64beSDimitry Andric response.Printf("<library-list-svr4 version=\"1.0\">"); 32089dba64beSDimitry Andric for (auto const &library : *library_list) { 32099dba64beSDimitry Andric response.Printf("<library name=\"%s\" ", 32109dba64beSDimitry Andric XMLEncodeAttributeValue(library.name.c_str()).c_str()); 32119dba64beSDimitry Andric response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map); 32129dba64beSDimitry Andric response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr); 32139dba64beSDimitry Andric response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr); 32149dba64beSDimitry Andric } 32159dba64beSDimitry Andric response.Printf("</library-list-svr4>"); 32169dba64beSDimitry Andric return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__); 32179dba64beSDimitry Andric } 32189dba64beSDimitry Andric 32195ffd83dbSDimitry Andric if (object == "features" && annex == "target.xml") 32205ffd83dbSDimitry Andric return BuildTargetXml(); 32215ffd83dbSDimitry Andric 3222e8d8bef9SDimitry Andric return llvm::make_error<UnimplementedError>(); 32230b57cec5SDimitry Andric } 32240b57cec5SDimitry Andric 32250b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 32260b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qXfer( 32270b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 32280b57cec5SDimitry Andric SmallVector<StringRef, 5> fields; 32290b57cec5SDimitry Andric // The packet format is "qXfer:<object>:<action>:<annex>:offset,length" 32300b57cec5SDimitry Andric StringRef(packet.GetStringRef()).split(fields, ':', 4); 32310b57cec5SDimitry Andric if (fields.size() != 5) 32320b57cec5SDimitry Andric return SendIllFormedResponse(packet, "malformed qXfer packet"); 32330b57cec5SDimitry Andric StringRef &xfer_object = fields[1]; 32340b57cec5SDimitry Andric StringRef &xfer_action = fields[2]; 32350b57cec5SDimitry Andric StringRef &xfer_annex = fields[3]; 32360b57cec5SDimitry Andric StringExtractor offset_data(fields[4]); 32370b57cec5SDimitry Andric if (xfer_action != "read") 32380b57cec5SDimitry Andric return SendUnimplementedResponse("qXfer action not supported"); 32390b57cec5SDimitry Andric // Parse offset. 32400b57cec5SDimitry Andric const uint64_t xfer_offset = 32410b57cec5SDimitry Andric offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); 32420b57cec5SDimitry Andric if (xfer_offset == std::numeric_limits<uint64_t>::max()) 32430b57cec5SDimitry Andric return SendIllFormedResponse(packet, "qXfer packet missing offset"); 32440b57cec5SDimitry Andric // Parse out comma. 32450b57cec5SDimitry Andric if (offset_data.GetChar() != ',') 32460b57cec5SDimitry Andric return SendIllFormedResponse(packet, 32470b57cec5SDimitry Andric "qXfer packet missing comma after offset"); 32480b57cec5SDimitry Andric // Parse out the length. 32490b57cec5SDimitry Andric const uint64_t xfer_length = 32500b57cec5SDimitry Andric offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); 32510b57cec5SDimitry Andric if (xfer_length == std::numeric_limits<uint64_t>::max()) 32520b57cec5SDimitry Andric return SendIllFormedResponse(packet, "qXfer packet missing length"); 32530b57cec5SDimitry Andric 32540b57cec5SDimitry Andric // Get a previously constructed buffer if it exists or create it now. 32550b57cec5SDimitry Andric std::string buffer_key = (xfer_object + xfer_action + xfer_annex).str(); 32560b57cec5SDimitry Andric auto buffer_it = m_xfer_buffer_map.find(buffer_key); 32570b57cec5SDimitry Andric if (buffer_it == m_xfer_buffer_map.end()) { 32580b57cec5SDimitry Andric auto buffer_up = ReadXferObject(xfer_object, xfer_annex); 32590b57cec5SDimitry Andric if (!buffer_up) 32600b57cec5SDimitry Andric return SendErrorResponse(buffer_up.takeError()); 32610b57cec5SDimitry Andric buffer_it = m_xfer_buffer_map 32620b57cec5SDimitry Andric .insert(std::make_pair(buffer_key, std::move(*buffer_up))) 32630b57cec5SDimitry Andric .first; 32640b57cec5SDimitry Andric } 32650b57cec5SDimitry Andric 32660b57cec5SDimitry Andric // Send back the response 32670b57cec5SDimitry Andric StreamGDBRemote response; 32680b57cec5SDimitry Andric bool done_with_buffer = false; 32690b57cec5SDimitry Andric llvm::StringRef buffer = buffer_it->second->getBuffer(); 32700b57cec5SDimitry Andric if (xfer_offset >= buffer.size()) { 32710b57cec5SDimitry Andric // We have nothing left to send. Mark the buffer as complete. 32720b57cec5SDimitry Andric response.PutChar('l'); 32730b57cec5SDimitry Andric done_with_buffer = true; 32740b57cec5SDimitry Andric } else { 32750b57cec5SDimitry Andric // Figure out how many bytes are available starting at the given offset. 32760b57cec5SDimitry Andric buffer = buffer.drop_front(xfer_offset); 32770b57cec5SDimitry Andric // Mark the response type according to whether we're reading the remainder 32780b57cec5SDimitry Andric // of the data. 32790b57cec5SDimitry Andric if (xfer_length >= buffer.size()) { 32800b57cec5SDimitry Andric // There will be nothing left to read after this 32810b57cec5SDimitry Andric response.PutChar('l'); 32820b57cec5SDimitry Andric done_with_buffer = true; 32830b57cec5SDimitry Andric } else { 32840b57cec5SDimitry Andric // There will still be bytes to read after this request. 32850b57cec5SDimitry Andric response.PutChar('m'); 32860b57cec5SDimitry Andric buffer = buffer.take_front(xfer_length); 32870b57cec5SDimitry Andric } 32880b57cec5SDimitry Andric // Now write the data in encoded binary form. 32890b57cec5SDimitry Andric response.PutEscapedBytes(buffer.data(), buffer.size()); 32900b57cec5SDimitry Andric } 32910b57cec5SDimitry Andric 32920b57cec5SDimitry Andric if (done_with_buffer) 32930b57cec5SDimitry Andric m_xfer_buffer_map.erase(buffer_it); 32940b57cec5SDimitry Andric 32950b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 32960b57cec5SDimitry Andric } 32970b57cec5SDimitry Andric 32980b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 32990b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( 33000b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 330181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 33020b57cec5SDimitry Andric 33030b57cec5SDimitry Andric // Move past packet name. 33040b57cec5SDimitry Andric packet.SetFilePos(strlen("QSaveRegisterState")); 33050b57cec5SDimitry Andric 33060b57cec5SDimitry Andric // Get the thread to use. 33070b57cec5SDimitry Andric NativeThreadProtocol *thread = GetThreadFromSuffix(packet); 33080b57cec5SDimitry Andric if (!thread) { 33090b57cec5SDimitry Andric if (m_thread_suffix_supported) 33100b57cec5SDimitry Andric return SendIllFormedResponse( 33110b57cec5SDimitry Andric packet, "No thread specified in QSaveRegisterState packet"); 33120b57cec5SDimitry Andric else 33130b57cec5SDimitry Andric return SendIllFormedResponse(packet, 33140b57cec5SDimitry Andric "No thread was is set with the Hg packet"); 33150b57cec5SDimitry Andric } 33160b57cec5SDimitry Andric 33170b57cec5SDimitry Andric // Grab the register context for the thread. 33180b57cec5SDimitry Andric NativeRegisterContext& reg_context = thread->GetRegisterContext(); 33190b57cec5SDimitry Andric 33200b57cec5SDimitry Andric // Save registers to a buffer. 332181ad6265SDimitry Andric WritableDataBufferSP register_data_sp; 33220b57cec5SDimitry Andric Status error = reg_context.ReadAllRegisterValues(register_data_sp); 33230b57cec5SDimitry Andric if (error.Fail()) { 33240b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to save all register values: {1}", 3325fe6060f1SDimitry Andric m_current_process->GetID(), error); 33260b57cec5SDimitry Andric return SendErrorResponse(0x75); 33270b57cec5SDimitry Andric } 33280b57cec5SDimitry Andric 33290b57cec5SDimitry Andric // Allocate a new save id. 33300b57cec5SDimitry Andric const uint32_t save_id = GetNextSavedRegistersID(); 33310b57cec5SDimitry Andric assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) && 33320b57cec5SDimitry Andric "GetNextRegisterSaveID() returned an existing register save id"); 33330b57cec5SDimitry Andric 33340b57cec5SDimitry Andric // Save the register data buffer under the save id. 33350b57cec5SDimitry Andric { 33360b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_saved_registers_mutex); 33370b57cec5SDimitry Andric m_saved_registers_map[save_id] = register_data_sp; 33380b57cec5SDimitry Andric } 33390b57cec5SDimitry Andric 33400b57cec5SDimitry Andric // Write the response. 33410b57cec5SDimitry Andric StreamGDBRemote response; 33420b57cec5SDimitry Andric response.Printf("%" PRIu32, save_id); 33430b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 33440b57cec5SDimitry Andric } 33450b57cec5SDimitry Andric 33460b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 33470b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( 33480b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 334981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 33500b57cec5SDimitry Andric 33510b57cec5SDimitry Andric // Parse out save id. 33520b57cec5SDimitry Andric packet.SetFilePos(strlen("QRestoreRegisterState:")); 33530b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1) 33540b57cec5SDimitry Andric return SendIllFormedResponse( 33550b57cec5SDimitry Andric packet, "QRestoreRegisterState packet missing register save id"); 33560b57cec5SDimitry Andric 33570b57cec5SDimitry Andric const uint32_t save_id = packet.GetU32(0); 33580b57cec5SDimitry Andric if (save_id == 0) { 33590b57cec5SDimitry Andric LLDB_LOG(log, "QRestoreRegisterState packet has malformed save id, " 33600b57cec5SDimitry Andric "expecting decimal uint32_t"); 33610b57cec5SDimitry Andric return SendErrorResponse(0x76); 33620b57cec5SDimitry Andric } 33630b57cec5SDimitry Andric 33640b57cec5SDimitry Andric // Get the thread to use. 33650b57cec5SDimitry Andric NativeThreadProtocol *thread = GetThreadFromSuffix(packet); 33660b57cec5SDimitry Andric if (!thread) { 33670b57cec5SDimitry Andric if (m_thread_suffix_supported) 33680b57cec5SDimitry Andric return SendIllFormedResponse( 33690b57cec5SDimitry Andric packet, "No thread specified in QRestoreRegisterState packet"); 33700b57cec5SDimitry Andric else 33710b57cec5SDimitry Andric return SendIllFormedResponse(packet, 33720b57cec5SDimitry Andric "No thread was is set with the Hg packet"); 33730b57cec5SDimitry Andric } 33740b57cec5SDimitry Andric 33750b57cec5SDimitry Andric // Grab the register context for the thread. 33760b57cec5SDimitry Andric NativeRegisterContext ®_context = thread->GetRegisterContext(); 33770b57cec5SDimitry Andric 33780b57cec5SDimitry Andric // Retrieve register state buffer, then remove from the list. 33790b57cec5SDimitry Andric DataBufferSP register_data_sp; 33800b57cec5SDimitry Andric { 33810b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_saved_registers_mutex); 33820b57cec5SDimitry Andric 33830b57cec5SDimitry Andric // Find the register set buffer for the given save id. 33840b57cec5SDimitry Andric auto it = m_saved_registers_map.find(save_id); 33850b57cec5SDimitry Andric if (it == m_saved_registers_map.end()) { 33860b57cec5SDimitry Andric LLDB_LOG(log, 33870b57cec5SDimitry Andric "pid {0} does not have a register set save buffer for id {1}", 3388fe6060f1SDimitry Andric m_current_process->GetID(), save_id); 33890b57cec5SDimitry Andric return SendErrorResponse(0x77); 33900b57cec5SDimitry Andric } 33910b57cec5SDimitry Andric register_data_sp = it->second; 33920b57cec5SDimitry Andric 33930b57cec5SDimitry Andric // Remove it from the map. 33940b57cec5SDimitry Andric m_saved_registers_map.erase(it); 33950b57cec5SDimitry Andric } 33960b57cec5SDimitry Andric 33970b57cec5SDimitry Andric Status error = reg_context.WriteAllRegisterValues(register_data_sp); 33980b57cec5SDimitry Andric if (error.Fail()) { 33990b57cec5SDimitry Andric LLDB_LOG(log, "pid {0} failed to restore all register values: {1}", 3400fe6060f1SDimitry Andric m_current_process->GetID(), error); 34010b57cec5SDimitry Andric return SendErrorResponse(0x77); 34020b57cec5SDimitry Andric } 34030b57cec5SDimitry Andric 34040b57cec5SDimitry Andric return SendOKResponse(); 34050b57cec5SDimitry Andric } 34060b57cec5SDimitry Andric 34070b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 34080b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttach( 34090b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 341081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 34110b57cec5SDimitry Andric 34120b57cec5SDimitry Andric // Consume the ';' after vAttach. 34130b57cec5SDimitry Andric packet.SetFilePos(strlen("vAttach")); 34140b57cec5SDimitry Andric if (!packet.GetBytesLeft() || packet.GetChar() != ';') 34150b57cec5SDimitry Andric return SendIllFormedResponse(packet, "vAttach missing expected ';'"); 34160b57cec5SDimitry Andric 34170b57cec5SDimitry Andric // Grab the PID to which we will attach (assume hex encoding). 34180b57cec5SDimitry Andric lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); 34190b57cec5SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 34200b57cec5SDimitry Andric return SendIllFormedResponse(packet, 34210b57cec5SDimitry Andric "vAttach failed to parse the process id"); 34220b57cec5SDimitry Andric 34230b57cec5SDimitry Andric // Attempt to attach. 34249dba64beSDimitry Andric LLDB_LOGF(log, 34259dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s attempting to attach to " 34260b57cec5SDimitry Andric "pid %" PRIu64, 34270b57cec5SDimitry Andric __FUNCTION__, pid); 34280b57cec5SDimitry Andric 34290b57cec5SDimitry Andric Status error = AttachToProcess(pid); 34300b57cec5SDimitry Andric 34310b57cec5SDimitry Andric if (error.Fail()) { 34329dba64beSDimitry Andric LLDB_LOGF(log, 34339dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed to attach to " 34340b57cec5SDimitry Andric "pid %" PRIu64 ": %s\n", 34350b57cec5SDimitry Andric __FUNCTION__, pid, error.AsCString()); 34360b57cec5SDimitry Andric return SendErrorResponse(error); 34370b57cec5SDimitry Andric } 34380b57cec5SDimitry Andric 34390b57cec5SDimitry Andric // Notify we attached by sending a stop packet. 344081ad6265SDimitry Andric assert(m_current_process); 344181ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 344281ad6265SDimitry Andric m_current_process->GetState(), 344381ad6265SDimitry Andric /*force_synchronous=*/false); 34440b57cec5SDimitry Andric } 34450b57cec5SDimitry Andric 34460b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 3447e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachWait( 3448e8d8bef9SDimitry Andric StringExtractorGDBRemote &packet) { 344981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3450e8d8bef9SDimitry Andric 3451e8d8bef9SDimitry Andric // Consume the ';' after the identifier. 3452e8d8bef9SDimitry Andric packet.SetFilePos(strlen("vAttachWait")); 3453e8d8bef9SDimitry Andric 3454e8d8bef9SDimitry Andric if (!packet.GetBytesLeft() || packet.GetChar() != ';') 3455e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "vAttachWait missing expected ';'"); 3456e8d8bef9SDimitry Andric 3457e8d8bef9SDimitry Andric // Allocate the buffer for the process name from vAttachWait. 3458e8d8bef9SDimitry Andric std::string process_name; 3459e8d8bef9SDimitry Andric if (!packet.GetHexByteString(process_name)) 3460e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, 3461e8d8bef9SDimitry Andric "vAttachWait failed to parse process name"); 3462e8d8bef9SDimitry Andric 3463e8d8bef9SDimitry Andric LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name); 3464e8d8bef9SDimitry Andric 3465e8d8bef9SDimitry Andric Status error = AttachWaitProcess(process_name, false); 3466e8d8bef9SDimitry Andric if (error.Fail()) { 3467e8d8bef9SDimitry Andric LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name, 3468e8d8bef9SDimitry Andric error); 3469e8d8bef9SDimitry Andric return SendErrorResponse(error); 3470e8d8bef9SDimitry Andric } 3471e8d8bef9SDimitry Andric 3472e8d8bef9SDimitry Andric // Notify we attached by sending a stop packet. 347381ad6265SDimitry Andric assert(m_current_process); 347481ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 347581ad6265SDimitry Andric m_current_process->GetState(), 347681ad6265SDimitry Andric /*force_synchronous=*/false); 3477e8d8bef9SDimitry Andric } 3478e8d8bef9SDimitry Andric 3479e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 3480e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported( 3481e8d8bef9SDimitry Andric StringExtractorGDBRemote &packet) { 3482e8d8bef9SDimitry Andric return SendOKResponse(); 3483e8d8bef9SDimitry Andric } 3484e8d8bef9SDimitry Andric 3485e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 3486e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait( 3487e8d8bef9SDimitry Andric StringExtractorGDBRemote &packet) { 348881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3489e8d8bef9SDimitry Andric 3490e8d8bef9SDimitry Andric // Consume the ';' after the identifier. 3491e8d8bef9SDimitry Andric packet.SetFilePos(strlen("vAttachOrWait")); 3492e8d8bef9SDimitry Andric 3493e8d8bef9SDimitry Andric if (!packet.GetBytesLeft() || packet.GetChar() != ';') 3494e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, "vAttachOrWait missing expected ';'"); 3495e8d8bef9SDimitry Andric 3496e8d8bef9SDimitry Andric // Allocate the buffer for the process name from vAttachWait. 3497e8d8bef9SDimitry Andric std::string process_name; 3498e8d8bef9SDimitry Andric if (!packet.GetHexByteString(process_name)) 3499e8d8bef9SDimitry Andric return SendIllFormedResponse(packet, 3500e8d8bef9SDimitry Andric "vAttachOrWait failed to parse process name"); 3501e8d8bef9SDimitry Andric 3502e8d8bef9SDimitry Andric LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name); 3503e8d8bef9SDimitry Andric 3504e8d8bef9SDimitry Andric Status error = AttachWaitProcess(process_name, true); 3505e8d8bef9SDimitry Andric if (error.Fail()) { 3506e8d8bef9SDimitry Andric LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name, 3507e8d8bef9SDimitry Andric error); 3508e8d8bef9SDimitry Andric return SendErrorResponse(error); 3509e8d8bef9SDimitry Andric } 3510e8d8bef9SDimitry Andric 3511e8d8bef9SDimitry Andric // Notify we attached by sending a stop packet. 351281ad6265SDimitry Andric assert(m_current_process); 351381ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 351481ad6265SDimitry Andric m_current_process->GetState(), 351581ad6265SDimitry Andric /*force_synchronous=*/false); 3516e8d8bef9SDimitry Andric } 3517e8d8bef9SDimitry Andric 3518e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult 3519349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vRun( 3520349cc55cSDimitry Andric StringExtractorGDBRemote &packet) { 352181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3522349cc55cSDimitry Andric 3523349cc55cSDimitry Andric llvm::StringRef s = packet.GetStringRef(); 3524349cc55cSDimitry Andric if (!s.consume_front("vRun;")) 3525349cc55cSDimitry Andric return SendErrorResponse(8); 3526349cc55cSDimitry Andric 3527349cc55cSDimitry Andric llvm::SmallVector<llvm::StringRef, 16> argv; 3528349cc55cSDimitry Andric s.split(argv, ';'); 3529349cc55cSDimitry Andric 3530349cc55cSDimitry Andric for (llvm::StringRef hex_arg : argv) { 3531349cc55cSDimitry Andric StringExtractor arg_ext{hex_arg}; 3532349cc55cSDimitry Andric std::string arg; 3533349cc55cSDimitry Andric arg_ext.GetHexByteString(arg); 3534349cc55cSDimitry Andric m_process_launch_info.GetArguments().AppendArgument(arg); 3535349cc55cSDimitry Andric LLDB_LOGF(log, "LLGSPacketHandler::%s added arg: \"%s\"", __FUNCTION__, 3536349cc55cSDimitry Andric arg.c_str()); 3537349cc55cSDimitry Andric } 3538349cc55cSDimitry Andric 3539bdd1243dSDimitry Andric if (argv.empty()) 3540bdd1243dSDimitry Andric return SendErrorResponse(Status("No arguments")); 3541349cc55cSDimitry Andric m_process_launch_info.GetExecutableFile().SetFile( 3542349cc55cSDimitry Andric m_process_launch_info.GetArguments()[0].ref(), FileSpec::Style::native); 3543349cc55cSDimitry Andric m_process_launch_error = LaunchProcess(); 3544bdd1243dSDimitry Andric if (m_process_launch_error.Fail()) 3545bdd1243dSDimitry Andric return SendErrorResponse(m_process_launch_error); 354681ad6265SDimitry Andric assert(m_current_process); 354781ad6265SDimitry Andric return SendStopReasonForState(*m_current_process, 354881ad6265SDimitry Andric m_current_process->GetState(), 354981ad6265SDimitry Andric /*force_synchronous=*/true); 355081ad6265SDimitry Andric } 3551349cc55cSDimitry Andric 3552349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult 35530b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { 355481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3555fcaf7f86SDimitry Andric if (!m_non_stop) 35560b57cec5SDimitry Andric StopSTDIOForwarding(); 35570b57cec5SDimitry Andric 35580b57cec5SDimitry Andric lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; 35590b57cec5SDimitry Andric 35600b57cec5SDimitry Andric // Consume the ';' after D. 35610b57cec5SDimitry Andric packet.SetFilePos(1); 35620b57cec5SDimitry Andric if (packet.GetBytesLeft()) { 35630b57cec5SDimitry Andric if (packet.GetChar() != ';') 35640b57cec5SDimitry Andric return SendIllFormedResponse(packet, "D missing expected ';'"); 35650b57cec5SDimitry Andric 35660b57cec5SDimitry Andric // Grab the PID from which we will detach (assume hex encoding). 35670b57cec5SDimitry Andric pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); 35680b57cec5SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 35690b57cec5SDimitry Andric return SendIllFormedResponse(packet, "D failed to parse the process id"); 35700b57cec5SDimitry Andric } 35710b57cec5SDimitry Andric 3572fe6060f1SDimitry Andric // Detach forked children if their PID was specified *or* no PID was requested 3573fe6060f1SDimitry Andric // (i.e. detach-all packet). 3574fe6060f1SDimitry Andric llvm::Error detach_error = llvm::Error::success(); 3575fe6060f1SDimitry Andric bool detached = false; 3576fe6060f1SDimitry Andric for (auto it = m_debugged_processes.begin(); 3577fe6060f1SDimitry Andric it != m_debugged_processes.end();) { 3578fe6060f1SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) { 357981ad6265SDimitry Andric LLDB_LOGF(log, 358081ad6265SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s detaching %" PRId64, 358181ad6265SDimitry Andric __FUNCTION__, it->first); 3582fcaf7f86SDimitry Andric if (llvm::Error e = it->second.process_up->Detach().ToError()) 3583fe6060f1SDimitry Andric detach_error = llvm::joinErrors(std::move(detach_error), std::move(e)); 3584fe6060f1SDimitry Andric else { 3585fcaf7f86SDimitry Andric if (it->second.process_up.get() == m_current_process) 3586fe6060f1SDimitry Andric m_current_process = nullptr; 3587fcaf7f86SDimitry Andric if (it->second.process_up.get() == m_continue_process) 3588fe6060f1SDimitry Andric m_continue_process = nullptr; 3589fe6060f1SDimitry Andric it = m_debugged_processes.erase(it); 3590fe6060f1SDimitry Andric detached = true; 3591fe6060f1SDimitry Andric continue; 3592fe6060f1SDimitry Andric } 3593fe6060f1SDimitry Andric } 3594fe6060f1SDimitry Andric ++it; 35950b57cec5SDimitry Andric } 35960b57cec5SDimitry Andric 3597fe6060f1SDimitry Andric if (detach_error) 3598fe6060f1SDimitry Andric return SendErrorResponse(std::move(detach_error)); 3599fe6060f1SDimitry Andric if (!detached) 3600fe6060f1SDimitry Andric return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid)); 36010b57cec5SDimitry Andric return SendOKResponse(); 36020b57cec5SDimitry Andric } 36030b57cec5SDimitry Andric 36040b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 36050b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo( 36060b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 360781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 360881ad6265SDimitry Andric 360981ad6265SDimitry Andric if (!m_current_process || 361081ad6265SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 361181ad6265SDimitry Andric return SendErrorResponse(50); 36120b57cec5SDimitry Andric 36130b57cec5SDimitry Andric packet.SetFilePos(strlen("qThreadStopInfo")); 3614fe6060f1SDimitry Andric const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID); 36150b57cec5SDimitry Andric if (tid == LLDB_INVALID_THREAD_ID) { 36169dba64beSDimitry Andric LLDB_LOGF(log, 36179dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, could not " 36180b57cec5SDimitry Andric "parse thread id from request \"%s\"", 36199dba64beSDimitry Andric __FUNCTION__, packet.GetStringRef().data()); 36200b57cec5SDimitry Andric return SendErrorResponse(0x15); 36210b57cec5SDimitry Andric } 362281ad6265SDimitry Andric return SendStopReplyPacketForThread(*m_current_process, tid, 362381ad6265SDimitry Andric /*force_synchronous=*/true); 36240b57cec5SDimitry Andric } 36250b57cec5SDimitry Andric 36260b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 36270b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( 36280b57cec5SDimitry Andric StringExtractorGDBRemote &) { 362981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); 36300b57cec5SDimitry Andric 36310b57cec5SDimitry Andric // Ensure we have a debugged process. 3632fe6060f1SDimitry Andric if (!m_current_process || 3633fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 36340b57cec5SDimitry Andric return SendErrorResponse(50); 3635fe6060f1SDimitry Andric LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID()); 36360b57cec5SDimitry Andric 36370b57cec5SDimitry Andric StreamString response; 36380b57cec5SDimitry Andric const bool threads_with_valid_stop_info_only = false; 3639fe6060f1SDimitry Andric llvm::Expected<json::Value> threads_info = 3640fe6060f1SDimitry Andric GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only); 36419dba64beSDimitry Andric if (!threads_info) { 3642480093f4SDimitry Andric LLDB_LOG_ERROR(log, threads_info.takeError(), 3643480093f4SDimitry Andric "failed to prepare a packet for pid {1}: {0}", 3644fe6060f1SDimitry Andric m_current_process->GetID()); 36450b57cec5SDimitry Andric return SendErrorResponse(52); 36460b57cec5SDimitry Andric } 36470b57cec5SDimitry Andric 36489dba64beSDimitry Andric response.AsRawOstream() << *threads_info; 36490b57cec5SDimitry Andric StreamGDBRemote escaped_response; 36500b57cec5SDimitry Andric escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); 36510b57cec5SDimitry Andric return SendPacketNoLock(escaped_response.GetString()); 36520b57cec5SDimitry Andric } 36530b57cec5SDimitry Andric 36540b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 36550b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( 36560b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 36570b57cec5SDimitry Andric // Fail if we don't have a current process. 3658fe6060f1SDimitry Andric if (!m_current_process || 3659fe6060f1SDimitry Andric m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) 36600b57cec5SDimitry Andric return SendErrorResponse(68); 36610b57cec5SDimitry Andric 36620b57cec5SDimitry Andric packet.SetFilePos(strlen("qWatchpointSupportInfo")); 36630b57cec5SDimitry Andric if (packet.GetBytesLeft() == 0) 36640b57cec5SDimitry Andric return SendOKResponse(); 36650b57cec5SDimitry Andric if (packet.GetChar() != ':') 36660b57cec5SDimitry Andric return SendErrorResponse(67); 36670b57cec5SDimitry Andric 3668fe6060f1SDimitry Andric auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo(); 36690b57cec5SDimitry Andric 36700b57cec5SDimitry Andric StreamGDBRemote response; 3671bdd1243dSDimitry Andric if (hw_debug_cap == std::nullopt) 36720b57cec5SDimitry Andric response.Printf("num:0;"); 36730b57cec5SDimitry Andric else 36740b57cec5SDimitry Andric response.Printf("num:%d;", hw_debug_cap->second); 36750b57cec5SDimitry Andric 36760b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 36770b57cec5SDimitry Andric } 36780b57cec5SDimitry Andric 36790b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 36800b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( 36810b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 36820b57cec5SDimitry Andric // Fail if we don't have a current process. 3683fe6060f1SDimitry Andric if (!m_current_process || 3684fe6060f1SDimitry Andric m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) 36850b57cec5SDimitry Andric return SendErrorResponse(67); 36860b57cec5SDimitry Andric 36870b57cec5SDimitry Andric packet.SetFilePos(strlen("qFileLoadAddress:")); 36880b57cec5SDimitry Andric if (packet.GetBytesLeft() == 0) 36890b57cec5SDimitry Andric return SendErrorResponse(68); 36900b57cec5SDimitry Andric 36910b57cec5SDimitry Andric std::string file_name; 36920b57cec5SDimitry Andric packet.GetHexByteString(file_name); 36930b57cec5SDimitry Andric 36940b57cec5SDimitry Andric lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS; 36950b57cec5SDimitry Andric Status error = 3696fe6060f1SDimitry Andric m_current_process->GetFileLoadAddress(file_name, file_load_address); 36970b57cec5SDimitry Andric if (error.Fail()) 36980b57cec5SDimitry Andric return SendErrorResponse(69); 36990b57cec5SDimitry Andric 37000b57cec5SDimitry Andric if (file_load_address == LLDB_INVALID_ADDRESS) 37010b57cec5SDimitry Andric return SendErrorResponse(1); // File not loaded 37020b57cec5SDimitry Andric 37030b57cec5SDimitry Andric StreamGDBRemote response; 37040b57cec5SDimitry Andric response.PutHex64(file_load_address); 37050b57cec5SDimitry Andric return SendPacketNoLock(response.GetString()); 37060b57cec5SDimitry Andric } 37070b57cec5SDimitry Andric 37080b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult 37090b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QPassSignals( 37100b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 37110b57cec5SDimitry Andric std::vector<int> signals; 37120b57cec5SDimitry Andric packet.SetFilePos(strlen("QPassSignals:")); 37130b57cec5SDimitry Andric 37140b57cec5SDimitry Andric // Read sequence of hex signal numbers divided by a semicolon and optionally 37150b57cec5SDimitry Andric // spaces. 37160b57cec5SDimitry Andric while (packet.GetBytesLeft() > 0) { 37170b57cec5SDimitry Andric int signal = packet.GetS32(-1, 16); 37180b57cec5SDimitry Andric if (signal < 0) 37190b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Failed to parse signal number."); 37200b57cec5SDimitry Andric signals.push_back(signal); 37210b57cec5SDimitry Andric 37220b57cec5SDimitry Andric packet.SkipSpaces(); 37230b57cec5SDimitry Andric char separator = packet.GetChar(); 37240b57cec5SDimitry Andric if (separator == '\0') 37250b57cec5SDimitry Andric break; // End of string 37260b57cec5SDimitry Andric if (separator != ';') 37270b57cec5SDimitry Andric return SendIllFormedResponse(packet, "Invalid separator," 37280b57cec5SDimitry Andric " expected semicolon."); 37290b57cec5SDimitry Andric } 37300b57cec5SDimitry Andric 37310b57cec5SDimitry Andric // Fail if we don't have a current process. 3732fe6060f1SDimitry Andric if (!m_current_process) 37330b57cec5SDimitry Andric return SendErrorResponse(68); 37340b57cec5SDimitry Andric 3735fe6060f1SDimitry Andric Status error = m_current_process->IgnoreSignals(signals); 37360b57cec5SDimitry Andric if (error.Fail()) 37370b57cec5SDimitry Andric return SendErrorResponse(69); 37380b57cec5SDimitry Andric 37390b57cec5SDimitry Andric return SendOKResponse(); 37400b57cec5SDimitry Andric } 37410b57cec5SDimitry Andric 3742fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult 3743fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemTags( 3744fe6060f1SDimitry Andric StringExtractorGDBRemote &packet) { 374581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3746fe6060f1SDimitry Andric 3747fe6060f1SDimitry Andric // Ensure we have a process. 3748fe6060f1SDimitry Andric if (!m_current_process || 3749fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 3750fe6060f1SDimitry Andric LLDB_LOGF( 3751fe6060f1SDimitry Andric log, 3752fe6060f1SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 3753fe6060f1SDimitry Andric __FUNCTION__); 3754fe6060f1SDimitry Andric return SendErrorResponse(1); 3755fe6060f1SDimitry Andric } 3756fe6060f1SDimitry Andric 3757fe6060f1SDimitry Andric // We are expecting 3758fe6060f1SDimitry Andric // qMemTags:<hex address>,<hex length>:<hex type> 3759fe6060f1SDimitry Andric 3760fe6060f1SDimitry Andric // Address 3761fe6060f1SDimitry Andric packet.SetFilePos(strlen("qMemTags:")); 3762fe6060f1SDimitry Andric const char *current_char = packet.Peek(); 3763fe6060f1SDimitry Andric if (!current_char || *current_char == ',') 3764fe6060f1SDimitry Andric return SendIllFormedResponse(packet, "Missing address in qMemTags packet"); 3765fe6060f1SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0); 3766fe6060f1SDimitry Andric 3767fe6060f1SDimitry Andric // Length 3768fe6060f1SDimitry Andric char previous_char = packet.GetChar(); 3769fe6060f1SDimitry Andric current_char = packet.Peek(); 3770fe6060f1SDimitry Andric // If we don't have a separator or the length field is empty 3771fe6060f1SDimitry Andric if (previous_char != ',' || (current_char && *current_char == ':')) 3772fe6060f1SDimitry Andric return SendIllFormedResponse(packet, 3773fe6060f1SDimitry Andric "Invalid addr,length pair in qMemTags packet"); 3774fe6060f1SDimitry Andric 3775fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1) 3776fe6060f1SDimitry Andric return SendIllFormedResponse( 3777fe6060f1SDimitry Andric packet, "Too short qMemtags: packet (looking for length)"); 3778fe6060f1SDimitry Andric const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0); 3779fe6060f1SDimitry Andric 3780fe6060f1SDimitry Andric // Type 3781fe6060f1SDimitry Andric const char *invalid_type_err = "Invalid type field in qMemTags: packet"; 3782fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') 3783fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 3784fe6060f1SDimitry Andric 37856e75b2fbSDimitry Andric // Type is a signed integer but packed into the packet as its raw bytes. 37866e75b2fbSDimitry Andric // However, our GetU64 uses strtoull which allows +/-. We do not want this. 37876e75b2fbSDimitry Andric const char *first_type_char = packet.Peek(); 37886e75b2fbSDimitry Andric if (first_type_char && (*first_type_char == '+' || *first_type_char == '-')) 37896e75b2fbSDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 37906e75b2fbSDimitry Andric 37916e75b2fbSDimitry Andric // Extract type as unsigned then cast to signed. 37926e75b2fbSDimitry Andric // Using a uint64_t here so that we have some value outside of the 32 bit 37936e75b2fbSDimitry Andric // range to use as the invalid return value. 37946e75b2fbSDimitry Andric uint64_t raw_type = 37956e75b2fbSDimitry Andric packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16); 37966e75b2fbSDimitry Andric 37976e75b2fbSDimitry Andric if ( // Make sure the cast below would be valid 37986e75b2fbSDimitry Andric raw_type > std::numeric_limits<uint32_t>::max() || 3799fe6060f1SDimitry Andric // To catch inputs like "123aardvark" that will parse but clearly aren't 3800fe6060f1SDimitry Andric // valid in this case. 3801fe6060f1SDimitry Andric packet.GetBytesLeft()) { 3802fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 3803fe6060f1SDimitry Andric } 3804fe6060f1SDimitry Andric 38056e75b2fbSDimitry Andric // First narrow to 32 bits otherwise the copy into type would take 38066e75b2fbSDimitry Andric // the wrong 4 bytes on big endian. 38076e75b2fbSDimitry Andric uint32_t raw_type_32 = raw_type; 38086e75b2fbSDimitry Andric int32_t type = reinterpret_cast<int32_t &>(raw_type_32); 38096e75b2fbSDimitry Andric 3810fe6060f1SDimitry Andric StreamGDBRemote response; 3811fe6060f1SDimitry Andric std::vector<uint8_t> tags; 3812fe6060f1SDimitry Andric Status error = m_current_process->ReadMemoryTags(type, addr, length, tags); 3813fe6060f1SDimitry Andric if (error.Fail()) 3814fe6060f1SDimitry Andric return SendErrorResponse(1); 3815fe6060f1SDimitry Andric 3816fe6060f1SDimitry Andric // This m is here in case we want to support multi part replies in the future. 3817fe6060f1SDimitry Andric // In the same manner as qfThreadInfo/qsThreadInfo. 3818fe6060f1SDimitry Andric response.PutChar('m'); 3819fe6060f1SDimitry Andric response.PutBytesAsRawHex8(tags.data(), tags.size()); 3820fe6060f1SDimitry Andric return SendPacketNoLock(response.GetString()); 3821fe6060f1SDimitry Andric } 3822fe6060f1SDimitry Andric 3823fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult 3824fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QMemTags( 3825fe6060f1SDimitry Andric StringExtractorGDBRemote &packet) { 382681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3827fe6060f1SDimitry Andric 3828fe6060f1SDimitry Andric // Ensure we have a process. 3829fe6060f1SDimitry Andric if (!m_current_process || 3830fe6060f1SDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { 3831fe6060f1SDimitry Andric LLDB_LOGF( 3832fe6060f1SDimitry Andric log, 3833fe6060f1SDimitry Andric "GDBRemoteCommunicationServerLLGS::%s failed, no process available", 3834fe6060f1SDimitry Andric __FUNCTION__); 3835fe6060f1SDimitry Andric return SendErrorResponse(1); 3836fe6060f1SDimitry Andric } 3837fe6060f1SDimitry Andric 3838fe6060f1SDimitry Andric // We are expecting 3839fe6060f1SDimitry Andric // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes> 3840fe6060f1SDimitry Andric 3841fe6060f1SDimitry Andric // Address 3842fe6060f1SDimitry Andric packet.SetFilePos(strlen("QMemTags:")); 3843fe6060f1SDimitry Andric const char *current_char = packet.Peek(); 3844fe6060f1SDimitry Andric if (!current_char || *current_char == ',') 3845fe6060f1SDimitry Andric return SendIllFormedResponse(packet, "Missing address in QMemTags packet"); 3846fe6060f1SDimitry Andric const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0); 3847fe6060f1SDimitry Andric 3848fe6060f1SDimitry Andric // Length 3849fe6060f1SDimitry Andric char previous_char = packet.GetChar(); 3850fe6060f1SDimitry Andric current_char = packet.Peek(); 3851fe6060f1SDimitry Andric // If we don't have a separator or the length field is empty 3852fe6060f1SDimitry Andric if (previous_char != ',' || (current_char && *current_char == ':')) 3853fe6060f1SDimitry Andric return SendIllFormedResponse(packet, 3854fe6060f1SDimitry Andric "Invalid addr,length pair in QMemTags packet"); 3855fe6060f1SDimitry Andric 3856fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1) 3857fe6060f1SDimitry Andric return SendIllFormedResponse( 3858fe6060f1SDimitry Andric packet, "Too short QMemtags: packet (looking for length)"); 3859fe6060f1SDimitry Andric const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0); 3860fe6060f1SDimitry Andric 3861fe6060f1SDimitry Andric // Type 3862fe6060f1SDimitry Andric const char *invalid_type_err = "Invalid type field in QMemTags: packet"; 3863fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') 3864fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 3865fe6060f1SDimitry Andric 3866fe6060f1SDimitry Andric // Our GetU64 uses strtoull which allows leading +/-, we don't want that. 3867fe6060f1SDimitry Andric const char *first_type_char = packet.Peek(); 3868fe6060f1SDimitry Andric if (first_type_char && (*first_type_char == '+' || *first_type_char == '-')) 3869fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 3870fe6060f1SDimitry Andric 3871fe6060f1SDimitry Andric // The type is a signed integer but is in the packet as its raw bytes. 3872fe6060f1SDimitry Andric // So parse first as unsigned then cast to signed later. 3873fe6060f1SDimitry Andric // We extract to 64 bit, even though we only expect 32, so that we've 3874fe6060f1SDimitry Andric // got some invalid value we can check for. 3875fe6060f1SDimitry Andric uint64_t raw_type = 3876fe6060f1SDimitry Andric packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16); 3877fe6060f1SDimitry Andric if (raw_type > std::numeric_limits<uint32_t>::max()) 3878fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_type_err); 38796e75b2fbSDimitry Andric 38806e75b2fbSDimitry Andric // First narrow to 32 bits. Otherwise the copy below would get the wrong 38816e75b2fbSDimitry Andric // 4 bytes on big endian. 38826e75b2fbSDimitry Andric uint32_t raw_type_32 = raw_type; 38836e75b2fbSDimitry Andric int32_t type = reinterpret_cast<int32_t &>(raw_type_32); 3884fe6060f1SDimitry Andric 3885fe6060f1SDimitry Andric // Tag data 3886fe6060f1SDimitry Andric if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') 3887fe6060f1SDimitry Andric return SendIllFormedResponse(packet, 3888fe6060f1SDimitry Andric "Missing tag data in QMemTags: packet"); 3889fe6060f1SDimitry Andric 3890fe6060f1SDimitry Andric // Must be 2 chars per byte 3891fe6060f1SDimitry Andric const char *invalid_data_err = "Invalid tag data in QMemTags: packet"; 3892fe6060f1SDimitry Andric if (packet.GetBytesLeft() % 2) 3893fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_data_err); 3894fe6060f1SDimitry Andric 3895fe6060f1SDimitry Andric // This is bytes here and is unpacked into target specific tags later 3896fe6060f1SDimitry Andric // We cannot assume that number of bytes == length here because the server 3897fe6060f1SDimitry Andric // can repeat tags to fill a given range. 3898fe6060f1SDimitry Andric std::vector<uint8_t> tag_data; 3899fe6060f1SDimitry Andric // Zero length writes will not have any tag data 3900fe6060f1SDimitry Andric // (but we pass them on because it will still check that tagging is enabled) 3901fe6060f1SDimitry Andric if (packet.GetBytesLeft()) { 3902fe6060f1SDimitry Andric size_t byte_count = packet.GetBytesLeft() / 2; 3903fe6060f1SDimitry Andric tag_data.resize(byte_count); 3904fe6060f1SDimitry Andric size_t converted_bytes = packet.GetHexBytes(tag_data, 0); 3905fe6060f1SDimitry Andric if (converted_bytes != byte_count) { 3906fe6060f1SDimitry Andric return SendIllFormedResponse(packet, invalid_data_err); 3907fe6060f1SDimitry Andric } 3908fe6060f1SDimitry Andric } 3909fe6060f1SDimitry Andric 3910fe6060f1SDimitry Andric Status status = 3911fe6060f1SDimitry Andric m_current_process->WriteMemoryTags(type, addr, length, tag_data); 3912fe6060f1SDimitry Andric return status.Success() ? SendOKResponse() : SendErrorResponse(1); 3913fe6060f1SDimitry Andric } 3914fe6060f1SDimitry Andric 3915349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult 3916349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qSaveCore( 3917349cc55cSDimitry Andric StringExtractorGDBRemote &packet) { 3918349cc55cSDimitry Andric // Fail if we don't have a current process. 3919349cc55cSDimitry Andric if (!m_current_process || 3920349cc55cSDimitry Andric (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) 3921349cc55cSDimitry Andric return SendErrorResponse(Status("Process not running.")); 3922349cc55cSDimitry Andric 3923349cc55cSDimitry Andric std::string path_hint; 3924349cc55cSDimitry Andric 3925349cc55cSDimitry Andric StringRef packet_str{packet.GetStringRef()}; 39265f757f3fSDimitry Andric assert(packet_str.starts_with("qSaveCore")); 3927349cc55cSDimitry Andric if (packet_str.consume_front("qSaveCore;")) { 3928349cc55cSDimitry Andric for (auto x : llvm::split(packet_str, ';')) { 3929349cc55cSDimitry Andric if (x.consume_front("path-hint:")) 3930349cc55cSDimitry Andric StringExtractor(x).GetHexByteString(path_hint); 3931349cc55cSDimitry Andric else 3932349cc55cSDimitry Andric return SendErrorResponse(Status("Unsupported qSaveCore option")); 3933349cc55cSDimitry Andric } 3934349cc55cSDimitry Andric } 3935349cc55cSDimitry Andric 3936349cc55cSDimitry Andric llvm::Expected<std::string> ret = m_current_process->SaveCore(path_hint); 3937349cc55cSDimitry Andric if (!ret) 3938349cc55cSDimitry Andric return SendErrorResponse(ret.takeError()); 3939349cc55cSDimitry Andric 3940349cc55cSDimitry Andric StreamString response; 3941349cc55cSDimitry Andric response.PutCString("core-path:"); 3942349cc55cSDimitry Andric response.PutStringAsRawHex8(ret.get()); 3943349cc55cSDimitry Andric return SendPacketNoLock(response.GetString()); 3944349cc55cSDimitry Andric } 3945349cc55cSDimitry Andric 394681ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 394781ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QNonStop( 394881ad6265SDimitry Andric StringExtractorGDBRemote &packet) { 3949fcaf7f86SDimitry Andric Log *log = GetLog(LLDBLog::Process); 3950fcaf7f86SDimitry Andric 395181ad6265SDimitry Andric StringRef packet_str{packet.GetStringRef()}; 39525f757f3fSDimitry Andric assert(packet_str.starts_with("QNonStop:")); 395381ad6265SDimitry Andric packet_str.consume_front("QNonStop:"); 395481ad6265SDimitry Andric if (packet_str == "0") { 3955fcaf7f86SDimitry Andric if (m_non_stop) 3956fcaf7f86SDimitry Andric StopSTDIOForwarding(); 3957fcaf7f86SDimitry Andric for (auto &process_it : m_debugged_processes) { 3958fcaf7f86SDimitry Andric if (process_it.second.process_up->IsRunning()) { 3959fcaf7f86SDimitry Andric assert(m_non_stop); 3960fcaf7f86SDimitry Andric Status error = process_it.second.process_up->Interrupt(); 3961fcaf7f86SDimitry Andric if (error.Fail()) { 3962fcaf7f86SDimitry Andric LLDB_LOG(log, 3963fcaf7f86SDimitry Andric "while disabling nonstop, failed to halt process {0}: {1}", 3964fcaf7f86SDimitry Andric process_it.first, error); 3965fcaf7f86SDimitry Andric return SendErrorResponse(0x41); 3966fcaf7f86SDimitry Andric } 3967fcaf7f86SDimitry Andric // we must not send stop reasons after QNonStop 3968fcaf7f86SDimitry Andric m_disabling_non_stop = true; 3969fcaf7f86SDimitry Andric } 3970fcaf7f86SDimitry Andric } 3971fcaf7f86SDimitry Andric m_stdio_notification_queue.clear(); 3972fcaf7f86SDimitry Andric m_stop_notification_queue.clear(); 397381ad6265SDimitry Andric m_non_stop = false; 3974fcaf7f86SDimitry Andric // If we are stopping anything, defer sending the OK response until we're 3975fcaf7f86SDimitry Andric // done. 3976fcaf7f86SDimitry Andric if (m_disabling_non_stop) 3977fcaf7f86SDimitry Andric return PacketResult::Success; 397881ad6265SDimitry Andric } else if (packet_str == "1") { 3979fcaf7f86SDimitry Andric if (!m_non_stop) 3980fcaf7f86SDimitry Andric StartSTDIOForwarding(); 398181ad6265SDimitry Andric m_non_stop = true; 398281ad6265SDimitry Andric } else 398381ad6265SDimitry Andric return SendErrorResponse(Status("Invalid QNonStop packet")); 398481ad6265SDimitry Andric return SendOKResponse(); 398581ad6265SDimitry Andric } 398681ad6265SDimitry Andric 398781ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 3988fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::HandleNotificationAck( 3989fcaf7f86SDimitry Andric std::deque<std::string> &queue) { 3990fcaf7f86SDimitry Andric // Per the protocol, the first message put into the queue is sent 3991fcaf7f86SDimitry Andric // immediately. However, it remains the queue until the client ACKs it -- 3992fcaf7f86SDimitry Andric // then we pop it and send the next message. The process repeats until 3993fcaf7f86SDimitry Andric // the last message in the queue is ACK-ed, in which case the packet sends 3994fcaf7f86SDimitry Andric // an OK response. 3995fcaf7f86SDimitry Andric if (queue.empty()) 3996fcaf7f86SDimitry Andric return SendErrorResponse(Status("No pending notification to ack")); 3997fcaf7f86SDimitry Andric queue.pop_front(); 3998fcaf7f86SDimitry Andric if (!queue.empty()) 3999fcaf7f86SDimitry Andric return SendPacketNoLock(queue.front()); 4000fcaf7f86SDimitry Andric return SendOKResponse(); 4001fcaf7f86SDimitry Andric } 4002fcaf7f86SDimitry Andric 4003fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult 4004fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStdio( 4005fcaf7f86SDimitry Andric StringExtractorGDBRemote &packet) { 4006fcaf7f86SDimitry Andric return HandleNotificationAck(m_stdio_notification_queue); 4007fcaf7f86SDimitry Andric } 4008fcaf7f86SDimitry Andric 4009fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult 401081ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStopped( 401181ad6265SDimitry Andric StringExtractorGDBRemote &packet) { 4012fcaf7f86SDimitry Andric PacketResult ret = HandleNotificationAck(m_stop_notification_queue); 401381ad6265SDimitry Andric // If this was the last notification and all the processes exited, 401481ad6265SDimitry Andric // terminate the server. 4015fcaf7f86SDimitry Andric if (m_stop_notification_queue.empty() && m_debugged_processes.empty()) { 401681ad6265SDimitry Andric m_exit_now = true; 401781ad6265SDimitry Andric m_mainloop.RequestTermination(); 401881ad6265SDimitry Andric } 4019fcaf7f86SDimitry Andric return ret; 402081ad6265SDimitry Andric } 402181ad6265SDimitry Andric 402281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 402381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCtrlC( 402481ad6265SDimitry Andric StringExtractorGDBRemote &packet) { 402581ad6265SDimitry Andric if (!m_non_stop) 402681ad6265SDimitry Andric return SendErrorResponse(Status("vCtrl is only valid in non-stop mode")); 402781ad6265SDimitry Andric 402881ad6265SDimitry Andric PacketResult interrupt_res = Handle_interrupt(packet); 402981ad6265SDimitry Andric // If interrupting the process failed, pass the result through. 403081ad6265SDimitry Andric if (interrupt_res != PacketResult::Success) 403181ad6265SDimitry Andric return interrupt_res; 403281ad6265SDimitry Andric // Otherwise, vCtrlC should issue an OK response (normal interrupts do not). 403381ad6265SDimitry Andric return SendOKResponse(); 403481ad6265SDimitry Andric } 403581ad6265SDimitry Andric 403681ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 403781ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_T(StringExtractorGDBRemote &packet) { 403881ad6265SDimitry Andric packet.SetFilePos(strlen("T")); 403981ad6265SDimitry Andric auto pid_tid = packet.GetPidTid(m_current_process ? m_current_process->GetID() 404081ad6265SDimitry Andric : LLDB_INVALID_PROCESS_ID); 404181ad6265SDimitry Andric if (!pid_tid) 404281ad6265SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 404381ad6265SDimitry Andric inconvertibleErrorCode(), "Malformed thread-id")); 404481ad6265SDimitry Andric 404581ad6265SDimitry Andric lldb::pid_t pid = pid_tid->first; 404681ad6265SDimitry Andric lldb::tid_t tid = pid_tid->second; 404781ad6265SDimitry Andric 404881ad6265SDimitry Andric // Technically, this would also be caught by the PID check but let's be more 404981ad6265SDimitry Andric // explicit about the error. 405081ad6265SDimitry Andric if (pid == LLDB_INVALID_PROCESS_ID) 405181ad6265SDimitry Andric return SendErrorResponse(llvm::make_error<StringError>( 405281ad6265SDimitry Andric inconvertibleErrorCode(), "No current process and no PID provided")); 405381ad6265SDimitry Andric 405481ad6265SDimitry Andric // Check the process ID and find respective process instance. 405581ad6265SDimitry Andric auto new_process_it = m_debugged_processes.find(pid); 405681ad6265SDimitry Andric if (new_process_it == m_debugged_processes.end()) 405781ad6265SDimitry Andric return SendErrorResponse(1); 405881ad6265SDimitry Andric 405981ad6265SDimitry Andric // Check the thread ID 4060fcaf7f86SDimitry Andric if (!new_process_it->second.process_up->GetThreadByID(tid)) 406181ad6265SDimitry Andric return SendErrorResponse(2); 406281ad6265SDimitry Andric 406381ad6265SDimitry Andric return SendOKResponse(); 406481ad6265SDimitry Andric } 406581ad6265SDimitry Andric 40660b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { 406781ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 40680b57cec5SDimitry Andric 40690b57cec5SDimitry Andric // Tell the stdio connection to shut down. 40700b57cec5SDimitry Andric if (m_stdio_communication.IsConnected()) { 40710b57cec5SDimitry Andric auto connection = m_stdio_communication.GetConnection(); 40720b57cec5SDimitry Andric if (connection) { 40730b57cec5SDimitry Andric Status error; 40740b57cec5SDimitry Andric connection->Disconnect(&error); 40750b57cec5SDimitry Andric 40760b57cec5SDimitry Andric if (error.Success()) { 40779dba64beSDimitry Andric LLDB_LOGF(log, 40789dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s disconnect process " 40790b57cec5SDimitry Andric "terminal stdio - SUCCESS", 40800b57cec5SDimitry Andric __FUNCTION__); 40810b57cec5SDimitry Andric } else { 40829dba64beSDimitry Andric LLDB_LOGF(log, 40839dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s disconnect process " 40840b57cec5SDimitry Andric "terminal stdio - FAIL: %s", 40850b57cec5SDimitry Andric __FUNCTION__, error.AsCString()); 40860b57cec5SDimitry Andric } 40870b57cec5SDimitry Andric } 40880b57cec5SDimitry Andric } 40890b57cec5SDimitry Andric } 40900b57cec5SDimitry Andric 40910b57cec5SDimitry Andric NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( 40920b57cec5SDimitry Andric StringExtractorGDBRemote &packet) { 40930b57cec5SDimitry Andric // We have no thread if we don't have a process. 4094fe6060f1SDimitry Andric if (!m_current_process || 4095fe6060f1SDimitry Andric m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) 40960b57cec5SDimitry Andric return nullptr; 40970b57cec5SDimitry Andric 40980b57cec5SDimitry Andric // If the client hasn't asked for thread suffix support, there will not be a 40990b57cec5SDimitry Andric // thread suffix. Use the current thread in that case. 41000b57cec5SDimitry Andric if (!m_thread_suffix_supported) { 41010b57cec5SDimitry Andric const lldb::tid_t current_tid = GetCurrentThreadID(); 41020b57cec5SDimitry Andric if (current_tid == LLDB_INVALID_THREAD_ID) 41030b57cec5SDimitry Andric return nullptr; 41040b57cec5SDimitry Andric else if (current_tid == 0) { 41050b57cec5SDimitry Andric // Pick a thread. 4106fe6060f1SDimitry Andric return m_current_process->GetThreadAtIndex(0); 41070b57cec5SDimitry Andric } else 4108fe6060f1SDimitry Andric return m_current_process->GetThreadByID(current_tid); 41090b57cec5SDimitry Andric } 41100b57cec5SDimitry Andric 411181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Thread); 41120b57cec5SDimitry Andric 41130b57cec5SDimitry Andric // Parse out the ';'. 41140b57cec5SDimitry Andric if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') { 41159dba64beSDimitry Andric LLDB_LOGF(log, 41169dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " 41170b57cec5SDimitry Andric "error: expected ';' prior to start of thread suffix: packet " 41180b57cec5SDimitry Andric "contents = '%s'", 41199dba64beSDimitry Andric __FUNCTION__, packet.GetStringRef().data()); 41200b57cec5SDimitry Andric return nullptr; 41210b57cec5SDimitry Andric } 41220b57cec5SDimitry Andric 41230b57cec5SDimitry Andric if (!packet.GetBytesLeft()) 41240b57cec5SDimitry Andric return nullptr; 41250b57cec5SDimitry Andric 41260b57cec5SDimitry Andric // Parse out thread: portion. 41270b57cec5SDimitry Andric if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { 41289dba64beSDimitry Andric LLDB_LOGF(log, 41299dba64beSDimitry Andric "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " 41300b57cec5SDimitry Andric "error: expected 'thread:' but not found, packet contents = " 41310b57cec5SDimitry Andric "'%s'", 41329dba64beSDimitry Andric __FUNCTION__, packet.GetStringRef().data()); 41330b57cec5SDimitry Andric return nullptr; 41340b57cec5SDimitry Andric } 41350b57cec5SDimitry Andric packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); 41360b57cec5SDimitry Andric const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); 41370b57cec5SDimitry Andric if (tid != 0) 4138fe6060f1SDimitry Andric return m_current_process->GetThreadByID(tid); 41390b57cec5SDimitry Andric 41400b57cec5SDimitry Andric return nullptr; 41410b57cec5SDimitry Andric } 41420b57cec5SDimitry Andric 41430b57cec5SDimitry Andric lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { 41440b57cec5SDimitry Andric if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) { 41450b57cec5SDimitry Andric // Use whatever the debug process says is the current thread id since the 41460b57cec5SDimitry Andric // protocol either didn't specify or specified we want any/all threads 41470b57cec5SDimitry Andric // marked as the current thread. 4148fe6060f1SDimitry Andric if (!m_current_process) 41490b57cec5SDimitry Andric return LLDB_INVALID_THREAD_ID; 4150fe6060f1SDimitry Andric return m_current_process->GetCurrentThreadID(); 41510b57cec5SDimitry Andric } 41520b57cec5SDimitry Andric // Use the specific current thread id set by the gdb remote protocol. 41530b57cec5SDimitry Andric return m_current_tid; 41540b57cec5SDimitry Andric } 41550b57cec5SDimitry Andric 41560b57cec5SDimitry Andric uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() { 41570b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_saved_registers_mutex); 41580b57cec5SDimitry Andric return m_next_saved_registers_id++; 41590b57cec5SDimitry Andric } 41600b57cec5SDimitry Andric 41610b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() { 416281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Process); 41630b57cec5SDimitry Andric 41640b57cec5SDimitry Andric LLDB_LOG(log, "clearing {0} xfer buffers", m_xfer_buffer_map.size()); 41650b57cec5SDimitry Andric m_xfer_buffer_map.clear(); 41660b57cec5SDimitry Andric } 41670b57cec5SDimitry Andric 41680b57cec5SDimitry Andric FileSpec 41690b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, 41700b57cec5SDimitry Andric const ArchSpec &arch) { 4171fe6060f1SDimitry Andric if (m_current_process) { 41720b57cec5SDimitry Andric FileSpec file_spec; 4173fe6060f1SDimitry Andric if (m_current_process 41740b57cec5SDimitry Andric ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec) 41750b57cec5SDimitry Andric .Success()) { 41760b57cec5SDimitry Andric if (FileSystem::Instance().Exists(file_spec)) 41770b57cec5SDimitry Andric return file_spec; 41780b57cec5SDimitry Andric } 41790b57cec5SDimitry Andric } 41800b57cec5SDimitry Andric 41810b57cec5SDimitry Andric return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch); 41820b57cec5SDimitry Andric } 41839dba64beSDimitry Andric 41849dba64beSDimitry Andric std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue( 41859dba64beSDimitry Andric llvm::StringRef value) { 41869dba64beSDimitry Andric std::string result; 41879dba64beSDimitry Andric for (const char &c : value) { 41889dba64beSDimitry Andric switch (c) { 41899dba64beSDimitry Andric case '\'': 41909dba64beSDimitry Andric result += "'"; 41919dba64beSDimitry Andric break; 41929dba64beSDimitry Andric case '"': 41939dba64beSDimitry Andric result += """; 41949dba64beSDimitry Andric break; 41959dba64beSDimitry Andric case '<': 41969dba64beSDimitry Andric result += "<"; 41979dba64beSDimitry Andric break; 41989dba64beSDimitry Andric case '>': 41999dba64beSDimitry Andric result += ">"; 42009dba64beSDimitry Andric break; 42019dba64beSDimitry Andric default: 42029dba64beSDimitry Andric result += c; 42039dba64beSDimitry Andric break; 42049dba64beSDimitry Andric } 42059dba64beSDimitry Andric } 42069dba64beSDimitry Andric return result; 42079dba64beSDimitry Andric } 4208fe6060f1SDimitry Andric 4209fe6060f1SDimitry Andric std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures( 4210fe6060f1SDimitry Andric const llvm::ArrayRef<llvm::StringRef> client_features) { 4211fe6060f1SDimitry Andric std::vector<std::string> ret = 4212fe6060f1SDimitry Andric GDBRemoteCommunicationServerCommon::HandleFeatures(client_features); 4213fe6060f1SDimitry Andric ret.insert(ret.end(), { 4214fe6060f1SDimitry Andric "QThreadSuffixSupported+", 4215fe6060f1SDimitry Andric "QListThreadsInStopReply+", 4216fe6060f1SDimitry Andric "qXfer:features:read+", 421781ad6265SDimitry Andric "QNonStop+", 4218fe6060f1SDimitry Andric }); 4219fe6060f1SDimitry Andric 4220fe6060f1SDimitry Andric // report server-only features 4221fe6060f1SDimitry Andric using Extension = NativeProcessProtocol::Extension; 422206c3fb27SDimitry Andric Extension plugin_features = m_process_manager.GetSupportedExtensions(); 4223fe6060f1SDimitry Andric if (bool(plugin_features & Extension::pass_signals)) 4224fe6060f1SDimitry Andric ret.push_back("QPassSignals+"); 4225fe6060f1SDimitry Andric if (bool(plugin_features & Extension::auxv)) 4226fe6060f1SDimitry Andric ret.push_back("qXfer:auxv:read+"); 4227fe6060f1SDimitry Andric if (bool(plugin_features & Extension::libraries_svr4)) 4228fe6060f1SDimitry Andric ret.push_back("qXfer:libraries-svr4:read+"); 422904eeddc0SDimitry Andric if (bool(plugin_features & Extension::siginfo_read)) 423004eeddc0SDimitry Andric ret.push_back("qXfer:siginfo:read+"); 4231fe6060f1SDimitry Andric if (bool(plugin_features & Extension::memory_tagging)) 4232fe6060f1SDimitry Andric ret.push_back("memory-tagging+"); 4233349cc55cSDimitry Andric if (bool(plugin_features & Extension::savecore)) 4234349cc55cSDimitry Andric ret.push_back("qSaveCore+"); 4235fe6060f1SDimitry Andric 4236fe6060f1SDimitry Andric // check for client features 4237fe6060f1SDimitry Andric m_extensions_supported = {}; 4238fe6060f1SDimitry Andric for (llvm::StringRef x : client_features) 4239fe6060f1SDimitry Andric m_extensions_supported |= 4240fe6060f1SDimitry Andric llvm::StringSwitch<Extension>(x) 4241fe6060f1SDimitry Andric .Case("multiprocess+", Extension::multiprocess) 4242fe6060f1SDimitry Andric .Case("fork-events+", Extension::fork) 4243fe6060f1SDimitry Andric .Case("vfork-events+", Extension::vfork) 4244fe6060f1SDimitry Andric .Default({}); 4245fe6060f1SDimitry Andric 4246fe6060f1SDimitry Andric m_extensions_supported &= plugin_features; 4247fe6060f1SDimitry Andric 4248fe6060f1SDimitry Andric // fork & vfork require multiprocess 4249fe6060f1SDimitry Andric if (!bool(m_extensions_supported & Extension::multiprocess)) 4250fe6060f1SDimitry Andric m_extensions_supported &= ~(Extension::fork | Extension::vfork); 4251fe6060f1SDimitry Andric 4252fe6060f1SDimitry Andric // report only if actually supported 4253fe6060f1SDimitry Andric if (bool(m_extensions_supported & Extension::multiprocess)) 4254fe6060f1SDimitry Andric ret.push_back("multiprocess+"); 4255fe6060f1SDimitry Andric if (bool(m_extensions_supported & Extension::fork)) 4256fe6060f1SDimitry Andric ret.push_back("fork-events+"); 4257fe6060f1SDimitry Andric if (bool(m_extensions_supported & Extension::vfork)) 4258fe6060f1SDimitry Andric ret.push_back("vfork-events+"); 4259fe6060f1SDimitry Andric 4260fe6060f1SDimitry Andric for (auto &x : m_debugged_processes) 4261fcaf7f86SDimitry Andric SetEnabledExtensions(*x.second.process_up); 4262fe6060f1SDimitry Andric return ret; 4263fe6060f1SDimitry Andric } 4264fe6060f1SDimitry Andric 4265fe6060f1SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions( 4266fe6060f1SDimitry Andric NativeProcessProtocol &process) { 4267fe6060f1SDimitry Andric NativeProcessProtocol::Extension flags = m_extensions_supported; 426806c3fb27SDimitry Andric assert(!bool(flags & ~m_process_manager.GetSupportedExtensions())); 4269fe6060f1SDimitry Andric process.SetEnabledExtensions(flags); 4270fe6060f1SDimitry Andric } 4271349cc55cSDimitry Andric 427281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult 427381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() { 4274fcaf7f86SDimitry Andric if (m_non_stop) 4275fcaf7f86SDimitry Andric return SendOKResponse(); 427681ad6265SDimitry Andric StartSTDIOForwarding(); 4277fcaf7f86SDimitry Andric return PacketResult::Success; 427881ad6265SDimitry Andric } 427981ad6265SDimitry Andric 428081ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse( 428181ad6265SDimitry Andric Stream &response, lldb::pid_t pid, lldb::tid_t tid) { 428281ad6265SDimitry Andric if (bool(m_extensions_supported & 428381ad6265SDimitry Andric NativeProcessProtocol::Extension::multiprocess)) 428481ad6265SDimitry Andric response.Format("p{0:x-}.", pid); 428581ad6265SDimitry Andric response.Format("{0:x-}", tid); 428681ad6265SDimitry Andric } 428781ad6265SDimitry Andric 4288349cc55cSDimitry Andric std::string 4289349cc55cSDimitry Andric lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg, 4290349cc55cSDimitry Andric bool reverse_connect) { 4291349cc55cSDimitry Andric // Try parsing the argument as URL. 4292bdd1243dSDimitry Andric if (std::optional<URI> url = URI::Parse(url_arg)) { 4293349cc55cSDimitry Andric if (reverse_connect) 4294349cc55cSDimitry Andric return url_arg.str(); 4295349cc55cSDimitry Andric 4296349cc55cSDimitry Andric // Translate the scheme from LLGS notation to ConnectionFileDescriptor. 4297349cc55cSDimitry Andric // If the scheme doesn't match any, pass it through to support using CFD 4298349cc55cSDimitry Andric // schemes directly. 4299349cc55cSDimitry Andric std::string new_url = llvm::StringSwitch<std::string>(url->scheme) 4300349cc55cSDimitry Andric .Case("tcp", "listen") 4301349cc55cSDimitry Andric .Case("unix", "unix-accept") 4302349cc55cSDimitry Andric .Case("unix-abstract", "unix-abstract-accept") 4303349cc55cSDimitry Andric .Default(url->scheme.str()); 4304349cc55cSDimitry Andric llvm::append_range(new_url, url_arg.substr(url->scheme.size())); 4305349cc55cSDimitry Andric return new_url; 4306349cc55cSDimitry Andric } 4307349cc55cSDimitry Andric 4308349cc55cSDimitry Andric std::string host_port = url_arg.str(); 4309349cc55cSDimitry Andric // If host_and_port starts with ':', default the host to be "localhost" and 4310349cc55cSDimitry Andric // expect the remainder to be the port. 43115f757f3fSDimitry Andric if (url_arg.starts_with(":")) 4312349cc55cSDimitry Andric host_port.insert(0, "localhost"); 4313349cc55cSDimitry Andric 4314349cc55cSDimitry Andric // Try parsing the (preprocessed) argument as host:port pair. 4315349cc55cSDimitry Andric if (!llvm::errorToBool(Socket::DecodeHostAndPort(host_port).takeError())) 4316349cc55cSDimitry Andric return (reverse_connect ? "connect://" : "listen://") + host_port; 4317349cc55cSDimitry Andric 4318349cc55cSDimitry Andric // If none of the above applied, interpret the argument as UNIX socket path. 4319349cc55cSDimitry Andric return (reverse_connect ? "unix-connect://" : "unix-accept://") + 4320349cc55cSDimitry Andric url_arg.str(); 4321349cc55cSDimitry Andric } 4322