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
GDBRemoteCommunicationServerLLGS(MainLoop & mainloop,NativeProcessProtocol::Manager & process_manager)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 
RegisterPacketHandlers()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 
SetLaunchInfo(const ProcessLaunchInfo & info)2560b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) {
2570b57cec5SDimitry Andric   m_process_launch_info = info;
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
LaunchProcess()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 
AttachToProcess(lldb::pid_t pid)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 
AttachWaitProcess(llvm::StringRef process_name,bool include_existing)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 
InitializeDelegate(NativeProcessProtocol * process)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
SendWResponse(NativeProcessProtocol * process)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 
AppendHexValue(StreamString & response,const uint8_t * buf,uint32_t buf_size,bool swap)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 
GetEncodingNameOrEmpty(const RegisterInfo & reg_info)5225ffd83dbSDimitry Andric static llvm::StringRef GetEncodingNameOrEmpty(const RegisterInfo &reg_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 
GetFormatNameOrEmpty(const RegisterInfo & reg_info)5375ffd83dbSDimitry Andric static llvm::StringRef GetFormatNameOrEmpty(const RegisterInfo &reg_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 
GetKindGenericOrEmpty(const RegisterInfo & reg_info)5705ffd83dbSDimitry Andric static llvm::StringRef GetKindGenericOrEmpty(const RegisterInfo &reg_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 
CollectRegNums(const uint32_t * reg_num,StreamString & response,bool usehex)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 
WriteRegisterValueInHexFixedWidth(StreamString & response,NativeRegisterContext & reg_ctx,const RegisterInfo & reg_info,const RegisterValue * reg_value_p,lldb::ByteOrder byte_order)6170b57cec5SDimitry Andric static void WriteRegisterValueInHexFixedWidth(
6180b57cec5SDimitry Andric     StreamString &response, NativeRegisterContext &reg_ctx,
6190b57cec5SDimitry Andric     const RegisterInfo &reg_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(&reg_info, reg_value);
6240b57cec5SDimitry Andric     if (error.Success())
6250b57cec5SDimitry Andric       reg_value_p = &reg_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>
GetRegistersAsJSON(NativeThreadProtocol & thread)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 &reg_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                                       &reg_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 
GetStopReasonString(StopReason stop_reason)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>
GetJSONThreadsInfo(NativeProcessProtocol & process,bool abridged)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
PrepareStopReplyPacketForThread(NativeThreadProtocol & thread)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 &reg_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                                         &reg_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 &reg_ctx = thread.GetRegisterContext();
927e8d8bef9SDimitry Andric   const auto expedited_regs =
928e8d8bef9SDimitry Andric       reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Full);
9290b57cec5SDimitry Andric 
930e8d8bef9SDimitry Andric   for (auto &reg_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                                           &reg_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
SendStopReplyPacketForThread(NativeProcessProtocol & process,lldb::tid_t tid,bool force_synchronous)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 
EnqueueStopReplyPackets(lldb::tid_t thread_to_skip)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 
HandleInferiorState_Exited(NativeProcessProtocol * process)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 
HandleInferiorState_Stopped(NativeProcessProtocol * process)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 
ProcessStateChanged(NativeProcessProtocol * process,lldb::StateType state)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 
DidExec(NativeProcessProtocol * process)11380b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) {
11390b57cec5SDimitry Andric   ClearProcessSpecificData();
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric 
NewSubprocess(NativeProcessProtocol * parent_process,std::unique_ptr<NativeProcessProtocol> child_process)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 
DataAvailableCallback()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 
InitializeConnection(std::unique_ptr<Connection> connection)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
SendONotification(const char * buffer,uint32_t len)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 
SetSTDIOFileDescriptor(int fd)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 
StartSTDIOForwarding()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 
StopSTDIOForwarding()12470b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() {
12480b57cec5SDimitry Andric   m_stdio_handle_up.reset();
12490b57cec5SDimitry Andric }
12500b57cec5SDimitry Andric 
SendProcessOutput()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
Handle_jLLDBTraceSupported(StringExtractorGDBRemote & packet)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
Handle_jLLDBTraceStop(StringExtractorGDBRemote & packet)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
Handle_jLLDBTraceStart(StringExtractorGDBRemote & packet)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
Handle_jLLDBTraceGetState(StringExtractorGDBRemote & packet)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
Handle_jLLDBTraceGetBinaryData(StringExtractorGDBRemote & packet)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
Handle_qProcessInfo(StringExtractorGDBRemote & packet)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
Handle_qC(StringExtractorGDBRemote & packet)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
Handle_k(StringExtractorGDBRemote & packet)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
Handle_vKill(StringExtractorGDBRemote & packet)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
Handle_QSetDisableASLR(StringExtractorGDBRemote & packet)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
Handle_QSetWorkingDir(StringExtractorGDBRemote & packet)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
Handle_qGetWorkingDir(StringExtractorGDBRemote & packet)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
Handle_QThreadSuffixSupported(StringExtractorGDBRemote & packet)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
Handle_QListThreadsInStopReply(StringExtractorGDBRemote & packet)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
ResumeProcess(NativeProcessProtocol & process,const ResumeActionList & actions)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
Handle_C(StringExtractorGDBRemote & packet)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
Handle_c(StringExtractorGDBRemote & packet)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
Handle_vCont_actions(StringExtractorGDBRemote & packet)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 
ResumeActionListStopsAllThreads(ResumeActionList & actions)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
Handle_vCont(StringExtractorGDBRemote & packet)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 
SetCurrentThreadID(lldb::tid_t tid)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 
SetContinueThreadID(lldb::tid_t tid)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
Handle_stop_reason(StringExtractorGDBRemote & packet)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
SendStopReasonForState(NativeProcessProtocol & process,lldb::StateType process_state,bool force_synchronous)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
Handle_qRegisterInfo(StringExtractorGDBRemote & packet)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 &reg_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 
AddProcessThreads(StreamGDBRemote & response,NativeProcessProtocol & process,bool & had_any)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
Handle_qfThreadInfo(StringExtractorGDBRemote & packet)20880b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
20890b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
209081ad6265SDimitry Andric   assert(m_debugged_processes.size() == 1 ||
209181ad6265SDimitry Andric          bool(m_extensions_supported &
209281ad6265SDimitry Andric               NativeProcessProtocol::Extension::multiprocess));
20930b57cec5SDimitry Andric 
209481ad6265SDimitry Andric   bool had_any = false;
20950b57cec5SDimitry Andric   StreamGDBRemote response;
20960b57cec5SDimitry Andric 
209781ad6265SDimitry Andric   for (auto &pid_ptr : m_debugged_processes)
2098fcaf7f86SDimitry Andric     AddProcessThreads(response, *pid_ptr.second.process_up, had_any);
20990b57cec5SDimitry Andric 
210081ad6265SDimitry Andric   if (!had_any)
210181ad6265SDimitry Andric     return SendOKResponse();
21020b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
21030b57cec5SDimitry Andric }
21040b57cec5SDimitry Andric 
21050b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_qsThreadInfo(StringExtractorGDBRemote & packet)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
Handle_g(StringExtractorGDBRemote & packet)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 &reg_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
Handle_p(StringExtractorGDBRemote & packet)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 &reg_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
Handle_P(StringExtractorGDBRemote & packet)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 &reg_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
Handle_H(StringExtractorGDBRemote & packet)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
Handle_I(StringExtractorGDBRemote & packet)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
Handle_interrupt(StringExtractorGDBRemote & packet)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
Handle_memory_read(StringExtractorGDBRemote & packet)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
Handle__M(StringExtractorGDBRemote & packet)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
Handle__m(StringExtractorGDBRemote & packet)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
Handle_M(StringExtractorGDBRemote & packet)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
Handle_qMemoryRegionInfoSupported(StringExtractorGDBRemote & packet)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
Handle_qMemoryRegionInfo(StringExtractorGDBRemote & packet)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
Handle_Z(StringExtractorGDBRemote & packet)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
Handle_z(StringExtractorGDBRemote & packet)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
Handle_s(StringExtractorGDBRemote & packet)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>>
BuildTargetXml()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 &reg_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 
30865ffd83dbSDimitry Andric   for (int reg_index = 0; reg_index < registers_count; reg_index++) {
30875ffd83dbSDimitry Andric     const RegisterInfo *reg_info =
30885ffd83dbSDimitry Andric         reg_context.GetRegisterInfoAtIndex(reg_index);
30895ffd83dbSDimitry Andric 
30905ffd83dbSDimitry Andric     if (!reg_info) {
30915ffd83dbSDimitry Andric       LLDB_LOGF(log,
30925ffd83dbSDimitry Andric                 "%s failed to get register info for register index %" PRIu32,
30935ffd83dbSDimitry Andric                 "target.xml", reg_index);
30945ffd83dbSDimitry Andric       continue;
30955ffd83dbSDimitry Andric     }
30965ffd83dbSDimitry Andric 
30975f757f3fSDimitry Andric     if (reg_info->flags_type) {
30985f757f3fSDimitry Andric       response.IndentMore();
30995f757f3fSDimitry Andric       reg_info->flags_type->ToXML(response);
31005f757f3fSDimitry Andric       response.IndentLess();
31015f757f3fSDimitry Andric     }
31025f757f3fSDimitry Andric 
3103bdd1243dSDimitry Andric     response.Indent();
3104bdd1243dSDimitry Andric     response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32
3105bdd1243dSDimitry Andric                     "\" regnum=\"%d\" ",
3106e8d8bef9SDimitry Andric                     reg_info->name, reg_info->byte_size * 8, reg_index);
3107e8d8bef9SDimitry Andric 
3108e8d8bef9SDimitry Andric     if (!reg_context.RegisterOffsetIsDynamic())
3109e8d8bef9SDimitry Andric       response.Printf("offset=\"%" PRIu32 "\" ", reg_info->byte_offset);
31105ffd83dbSDimitry Andric 
31115ffd83dbSDimitry Andric     if (reg_info->alt_name && reg_info->alt_name[0])
31125ffd83dbSDimitry Andric       response.Printf("altname=\"%s\" ", reg_info->alt_name);
31135ffd83dbSDimitry Andric 
31145ffd83dbSDimitry Andric     llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info);
31155ffd83dbSDimitry Andric     if (!encoding.empty())
31165ffd83dbSDimitry Andric       response << "encoding=\"" << encoding << "\" ";
31175ffd83dbSDimitry Andric 
31185ffd83dbSDimitry Andric     llvm::StringRef format = GetFormatNameOrEmpty(*reg_info);
31195ffd83dbSDimitry Andric     if (!format.empty())
31205ffd83dbSDimitry Andric       response << "format=\"" << format << "\" ";
31215ffd83dbSDimitry Andric 
31225f757f3fSDimitry Andric     if (reg_info->flags_type)
31235f757f3fSDimitry Andric       response << "type=\"" << reg_info->flags_type->GetID() << "\" ";
31245f757f3fSDimitry Andric 
31255ffd83dbSDimitry Andric     const char *const register_set_name =
31265ffd83dbSDimitry Andric         reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index);
31275ffd83dbSDimitry Andric     if (register_set_name)
31285ffd83dbSDimitry Andric       response << "group=\"" << register_set_name << "\" ";
31295ffd83dbSDimitry Andric 
31305ffd83dbSDimitry Andric     if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
31315ffd83dbSDimitry Andric         LLDB_INVALID_REGNUM)
31325ffd83dbSDimitry Andric       response.Printf("ehframe_regnum=\"%" PRIu32 "\" ",
31335ffd83dbSDimitry Andric                       reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
31345ffd83dbSDimitry Andric 
31355ffd83dbSDimitry Andric     if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] !=
31365ffd83dbSDimitry Andric         LLDB_INVALID_REGNUM)
31375ffd83dbSDimitry Andric       response.Printf("dwarf_regnum=\"%" PRIu32 "\" ",
31385ffd83dbSDimitry Andric                       reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
31395ffd83dbSDimitry Andric 
31405ffd83dbSDimitry Andric     llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info);
31415ffd83dbSDimitry Andric     if (!kind_generic.empty())
31425ffd83dbSDimitry Andric       response << "generic=\"" << kind_generic << "\" ";
31435ffd83dbSDimitry Andric 
31445ffd83dbSDimitry Andric     if (reg_info->value_regs &&
31455ffd83dbSDimitry Andric         reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
31465ffd83dbSDimitry Andric       response.PutCString("value_regnums=\"");
31475ffd83dbSDimitry Andric       CollectRegNums(reg_info->value_regs, response, false);
31485ffd83dbSDimitry Andric       response.Printf("\" ");
31495ffd83dbSDimitry Andric     }
31505ffd83dbSDimitry Andric 
31515ffd83dbSDimitry Andric     if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
31525ffd83dbSDimitry Andric       response.PutCString("invalidate_regnums=\"");
31535ffd83dbSDimitry Andric       CollectRegNums(reg_info->invalidate_regs, response, false);
31545ffd83dbSDimitry Andric       response.Printf("\" ");
31555ffd83dbSDimitry Andric     }
31565ffd83dbSDimitry Andric 
3157bdd1243dSDimitry Andric     response.Printf("/>\n");
31585ffd83dbSDimitry Andric   }
31595ffd83dbSDimitry Andric 
3160bdd1243dSDimitry Andric   if (registers_count)
3161bdd1243dSDimitry Andric     response.IndentLess();
3162bdd1243dSDimitry Andric 
3163bdd1243dSDimitry Andric   response.Indent("</feature>\n");
3164bdd1243dSDimitry Andric   response.IndentLess();
3165bdd1243dSDimitry Andric   response.Indent("</target>\n");
31665ffd83dbSDimitry Andric   return MemoryBuffer::getMemBufferCopy(response.GetString(), "target.xml");
31675ffd83dbSDimitry Andric }
31685ffd83dbSDimitry Andric 
31695ffd83dbSDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
ReadXferObject(llvm::StringRef object,llvm::StringRef annex)31700b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object,
31710b57cec5SDimitry Andric                                                  llvm::StringRef annex) {
31720b57cec5SDimitry Andric   // Make sure we have a valid process.
3173fe6060f1SDimitry Andric   if (!m_current_process ||
3174fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
31750b57cec5SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
31760b57cec5SDimitry Andric                                    "No process available");
31770b57cec5SDimitry Andric   }
31780b57cec5SDimitry Andric 
31795ffd83dbSDimitry Andric   if (object == "auxv") {
31800b57cec5SDimitry Andric     // Grab the auxv data.
3181fe6060f1SDimitry Andric     auto buffer_or_error = m_current_process->GetAuxvData();
31820b57cec5SDimitry Andric     if (!buffer_or_error)
31830b57cec5SDimitry Andric       return llvm::errorCodeToError(buffer_or_error.getError());
31840b57cec5SDimitry Andric     return std::move(*buffer_or_error);
31850b57cec5SDimitry Andric   }
31860b57cec5SDimitry Andric 
318704eeddc0SDimitry Andric   if (object == "siginfo") {
318804eeddc0SDimitry Andric     NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
318904eeddc0SDimitry Andric     if (!thread)
319004eeddc0SDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
319104eeddc0SDimitry Andric                                      "no current thread");
319204eeddc0SDimitry Andric 
319304eeddc0SDimitry Andric     auto buffer_or_error = thread->GetSiginfo();
319404eeddc0SDimitry Andric     if (!buffer_or_error)
319504eeddc0SDimitry Andric       return buffer_or_error.takeError();
319604eeddc0SDimitry Andric     return std::move(*buffer_or_error);
319704eeddc0SDimitry Andric   }
319804eeddc0SDimitry Andric 
31999dba64beSDimitry Andric   if (object == "libraries-svr4") {
3200fe6060f1SDimitry Andric     auto library_list = m_current_process->GetLoadedSVR4Libraries();
32019dba64beSDimitry Andric     if (!library_list)
32029dba64beSDimitry Andric       return library_list.takeError();
32039dba64beSDimitry Andric 
32049dba64beSDimitry Andric     StreamString response;
32059dba64beSDimitry Andric     response.Printf("<library-list-svr4 version=\"1.0\">");
32069dba64beSDimitry Andric     for (auto const &library : *library_list) {
32079dba64beSDimitry Andric       response.Printf("<library name=\"%s\" ",
32089dba64beSDimitry Andric                       XMLEncodeAttributeValue(library.name.c_str()).c_str());
32099dba64beSDimitry Andric       response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map);
32109dba64beSDimitry Andric       response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr);
32119dba64beSDimitry Andric       response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr);
32129dba64beSDimitry Andric     }
32139dba64beSDimitry Andric     response.Printf("</library-list-svr4>");
32149dba64beSDimitry Andric     return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__);
32159dba64beSDimitry Andric   }
32169dba64beSDimitry Andric 
32175ffd83dbSDimitry Andric   if (object == "features" && annex == "target.xml")
32185ffd83dbSDimitry Andric     return BuildTargetXml();
32195ffd83dbSDimitry Andric 
3220e8d8bef9SDimitry Andric   return llvm::make_error<UnimplementedError>();
32210b57cec5SDimitry Andric }
32220b57cec5SDimitry Andric 
32230b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_qXfer(StringExtractorGDBRemote & packet)32240b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qXfer(
32250b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
32260b57cec5SDimitry Andric   SmallVector<StringRef, 5> fields;
32270b57cec5SDimitry Andric   // The packet format is "qXfer:<object>:<action>:<annex>:offset,length"
32280b57cec5SDimitry Andric   StringRef(packet.GetStringRef()).split(fields, ':', 4);
32290b57cec5SDimitry Andric   if (fields.size() != 5)
32300b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "malformed qXfer packet");
32310b57cec5SDimitry Andric   StringRef &xfer_object = fields[1];
32320b57cec5SDimitry Andric   StringRef &xfer_action = fields[2];
32330b57cec5SDimitry Andric   StringRef &xfer_annex = fields[3];
32340b57cec5SDimitry Andric   StringExtractor offset_data(fields[4]);
32350b57cec5SDimitry Andric   if (xfer_action != "read")
32360b57cec5SDimitry Andric     return SendUnimplementedResponse("qXfer action not supported");
32370b57cec5SDimitry Andric   // Parse offset.
32380b57cec5SDimitry Andric   const uint64_t xfer_offset =
32390b57cec5SDimitry Andric       offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
32400b57cec5SDimitry Andric   if (xfer_offset == std::numeric_limits<uint64_t>::max())
32410b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "qXfer packet missing offset");
32420b57cec5SDimitry Andric   // Parse out comma.
32430b57cec5SDimitry Andric   if (offset_data.GetChar() != ',')
32440b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
32450b57cec5SDimitry Andric                                  "qXfer packet missing comma after offset");
32460b57cec5SDimitry Andric   // Parse out the length.
32470b57cec5SDimitry Andric   const uint64_t xfer_length =
32480b57cec5SDimitry Andric       offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
32490b57cec5SDimitry Andric   if (xfer_length == std::numeric_limits<uint64_t>::max())
32500b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "qXfer packet missing length");
32510b57cec5SDimitry Andric 
32520b57cec5SDimitry Andric   // Get a previously constructed buffer if it exists or create it now.
32530b57cec5SDimitry Andric   std::string buffer_key = (xfer_object + xfer_action + xfer_annex).str();
32540b57cec5SDimitry Andric   auto buffer_it = m_xfer_buffer_map.find(buffer_key);
32550b57cec5SDimitry Andric   if (buffer_it == m_xfer_buffer_map.end()) {
32560b57cec5SDimitry Andric     auto buffer_up = ReadXferObject(xfer_object, xfer_annex);
32570b57cec5SDimitry Andric     if (!buffer_up)
32580b57cec5SDimitry Andric       return SendErrorResponse(buffer_up.takeError());
32590b57cec5SDimitry Andric     buffer_it = m_xfer_buffer_map
32600b57cec5SDimitry Andric                     .insert(std::make_pair(buffer_key, std::move(*buffer_up)))
32610b57cec5SDimitry Andric                     .first;
32620b57cec5SDimitry Andric   }
32630b57cec5SDimitry Andric 
32640b57cec5SDimitry Andric   // Send back the response
32650b57cec5SDimitry Andric   StreamGDBRemote response;
32660b57cec5SDimitry Andric   bool done_with_buffer = false;
32670b57cec5SDimitry Andric   llvm::StringRef buffer = buffer_it->second->getBuffer();
32680b57cec5SDimitry Andric   if (xfer_offset >= buffer.size()) {
32690b57cec5SDimitry Andric     // We have nothing left to send.  Mark the buffer as complete.
32700b57cec5SDimitry Andric     response.PutChar('l');
32710b57cec5SDimitry Andric     done_with_buffer = true;
32720b57cec5SDimitry Andric   } else {
32730b57cec5SDimitry Andric     // Figure out how many bytes are available starting at the given offset.
32740b57cec5SDimitry Andric     buffer = buffer.drop_front(xfer_offset);
32750b57cec5SDimitry Andric     // Mark the response type according to whether we're reading the remainder
32760b57cec5SDimitry Andric     // of the data.
32770b57cec5SDimitry Andric     if (xfer_length >= buffer.size()) {
32780b57cec5SDimitry Andric       // There will be nothing left to read after this
32790b57cec5SDimitry Andric       response.PutChar('l');
32800b57cec5SDimitry Andric       done_with_buffer = true;
32810b57cec5SDimitry Andric     } else {
32820b57cec5SDimitry Andric       // There will still be bytes to read after this request.
32830b57cec5SDimitry Andric       response.PutChar('m');
32840b57cec5SDimitry Andric       buffer = buffer.take_front(xfer_length);
32850b57cec5SDimitry Andric     }
32860b57cec5SDimitry Andric     // Now write the data in encoded binary form.
32870b57cec5SDimitry Andric     response.PutEscapedBytes(buffer.data(), buffer.size());
32880b57cec5SDimitry Andric   }
32890b57cec5SDimitry Andric 
32900b57cec5SDimitry Andric   if (done_with_buffer)
32910b57cec5SDimitry Andric     m_xfer_buffer_map.erase(buffer_it);
32920b57cec5SDimitry Andric 
32930b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
32940b57cec5SDimitry Andric }
32950b57cec5SDimitry Andric 
32960b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_QSaveRegisterState(StringExtractorGDBRemote & packet)32970b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
32980b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
329981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
33000b57cec5SDimitry Andric 
33010b57cec5SDimitry Andric   // Move past packet name.
33020b57cec5SDimitry Andric   packet.SetFilePos(strlen("QSaveRegisterState"));
33030b57cec5SDimitry Andric 
33040b57cec5SDimitry Andric   // Get the thread to use.
33050b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
33060b57cec5SDimitry Andric   if (!thread) {
33070b57cec5SDimitry Andric     if (m_thread_suffix_supported)
33080b57cec5SDimitry Andric       return SendIllFormedResponse(
33090b57cec5SDimitry Andric           packet, "No thread specified in QSaveRegisterState packet");
33100b57cec5SDimitry Andric     else
33110b57cec5SDimitry Andric       return SendIllFormedResponse(packet,
33120b57cec5SDimitry Andric                                    "No thread was is set with the Hg packet");
33130b57cec5SDimitry Andric   }
33140b57cec5SDimitry Andric 
33150b57cec5SDimitry Andric   // Grab the register context for the thread.
33160b57cec5SDimitry Andric   NativeRegisterContext& reg_context = thread->GetRegisterContext();
33170b57cec5SDimitry Andric 
33180b57cec5SDimitry Andric   // Save registers to a buffer.
331981ad6265SDimitry Andric   WritableDataBufferSP register_data_sp;
33200b57cec5SDimitry Andric   Status error = reg_context.ReadAllRegisterValues(register_data_sp);
33210b57cec5SDimitry Andric   if (error.Fail()) {
33220b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to save all register values: {1}",
3323fe6060f1SDimitry Andric              m_current_process->GetID(), error);
33240b57cec5SDimitry Andric     return SendErrorResponse(0x75);
33250b57cec5SDimitry Andric   }
33260b57cec5SDimitry Andric 
33270b57cec5SDimitry Andric   // Allocate a new save id.
33280b57cec5SDimitry Andric   const uint32_t save_id = GetNextSavedRegistersID();
33290b57cec5SDimitry Andric   assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) &&
33300b57cec5SDimitry Andric          "GetNextRegisterSaveID() returned an existing register save id");
33310b57cec5SDimitry Andric 
33320b57cec5SDimitry Andric   // Save the register data buffer under the save id.
33330b57cec5SDimitry Andric   {
33340b57cec5SDimitry Andric     std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
33350b57cec5SDimitry Andric     m_saved_registers_map[save_id] = register_data_sp;
33360b57cec5SDimitry Andric   }
33370b57cec5SDimitry Andric 
33380b57cec5SDimitry Andric   // Write the response.
33390b57cec5SDimitry Andric   StreamGDBRemote response;
33400b57cec5SDimitry Andric   response.Printf("%" PRIu32, save_id);
33410b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
33420b57cec5SDimitry Andric }
33430b57cec5SDimitry Andric 
33440b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_QRestoreRegisterState(StringExtractorGDBRemote & packet)33450b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
33460b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
334781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
33480b57cec5SDimitry Andric 
33490b57cec5SDimitry Andric   // Parse out save id.
33500b57cec5SDimitry Andric   packet.SetFilePos(strlen("QRestoreRegisterState:"));
33510b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
33520b57cec5SDimitry Andric     return SendIllFormedResponse(
33530b57cec5SDimitry Andric         packet, "QRestoreRegisterState packet missing register save id");
33540b57cec5SDimitry Andric 
33550b57cec5SDimitry Andric   const uint32_t save_id = packet.GetU32(0);
33560b57cec5SDimitry Andric   if (save_id == 0) {
33570b57cec5SDimitry Andric     LLDB_LOG(log, "QRestoreRegisterState packet has malformed save id, "
33580b57cec5SDimitry Andric                   "expecting decimal uint32_t");
33590b57cec5SDimitry Andric     return SendErrorResponse(0x76);
33600b57cec5SDimitry Andric   }
33610b57cec5SDimitry Andric 
33620b57cec5SDimitry Andric   // Get the thread to use.
33630b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
33640b57cec5SDimitry Andric   if (!thread) {
33650b57cec5SDimitry Andric     if (m_thread_suffix_supported)
33660b57cec5SDimitry Andric       return SendIllFormedResponse(
33670b57cec5SDimitry Andric           packet, "No thread specified in QRestoreRegisterState packet");
33680b57cec5SDimitry Andric     else
33690b57cec5SDimitry Andric       return SendIllFormedResponse(packet,
33700b57cec5SDimitry Andric                                    "No thread was is set with the Hg packet");
33710b57cec5SDimitry Andric   }
33720b57cec5SDimitry Andric 
33730b57cec5SDimitry Andric   // Grab the register context for the thread.
33740b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
33750b57cec5SDimitry Andric 
33760b57cec5SDimitry Andric   // Retrieve register state buffer, then remove from the list.
33770b57cec5SDimitry Andric   DataBufferSP register_data_sp;
33780b57cec5SDimitry Andric   {
33790b57cec5SDimitry Andric     std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
33800b57cec5SDimitry Andric 
33810b57cec5SDimitry Andric     // Find the register set buffer for the given save id.
33820b57cec5SDimitry Andric     auto it = m_saved_registers_map.find(save_id);
33830b57cec5SDimitry Andric     if (it == m_saved_registers_map.end()) {
33840b57cec5SDimitry Andric       LLDB_LOG(log,
33850b57cec5SDimitry Andric                "pid {0} does not have a register set save buffer for id {1}",
3386fe6060f1SDimitry Andric                m_current_process->GetID(), save_id);
33870b57cec5SDimitry Andric       return SendErrorResponse(0x77);
33880b57cec5SDimitry Andric     }
33890b57cec5SDimitry Andric     register_data_sp = it->second;
33900b57cec5SDimitry Andric 
33910b57cec5SDimitry Andric     // Remove it from the map.
33920b57cec5SDimitry Andric     m_saved_registers_map.erase(it);
33930b57cec5SDimitry Andric   }
33940b57cec5SDimitry Andric 
33950b57cec5SDimitry Andric   Status error = reg_context.WriteAllRegisterValues(register_data_sp);
33960b57cec5SDimitry Andric   if (error.Fail()) {
33970b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to restore all register values: {1}",
3398fe6060f1SDimitry Andric              m_current_process->GetID(), error);
33990b57cec5SDimitry Andric     return SendErrorResponse(0x77);
34000b57cec5SDimitry Andric   }
34010b57cec5SDimitry Andric 
34020b57cec5SDimitry Andric   return SendOKResponse();
34030b57cec5SDimitry Andric }
34040b57cec5SDimitry Andric 
34050b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_vAttach(StringExtractorGDBRemote & packet)34060b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttach(
34070b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
340881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
34090b57cec5SDimitry Andric 
34100b57cec5SDimitry Andric   // Consume the ';' after vAttach.
34110b57cec5SDimitry Andric   packet.SetFilePos(strlen("vAttach"));
34120b57cec5SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
34130b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "vAttach missing expected ';'");
34140b57cec5SDimitry Andric 
34150b57cec5SDimitry Andric   // Grab the PID to which we will attach (assume hex encoding).
34160b57cec5SDimitry Andric   lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
34170b57cec5SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
34180b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
34190b57cec5SDimitry Andric                                  "vAttach failed to parse the process id");
34200b57cec5SDimitry Andric 
34210b57cec5SDimitry Andric   // Attempt to attach.
34229dba64beSDimitry Andric   LLDB_LOGF(log,
34239dba64beSDimitry Andric             "GDBRemoteCommunicationServerLLGS::%s attempting to attach to "
34240b57cec5SDimitry Andric             "pid %" PRIu64,
34250b57cec5SDimitry Andric             __FUNCTION__, pid);
34260b57cec5SDimitry Andric 
34270b57cec5SDimitry Andric   Status error = AttachToProcess(pid);
34280b57cec5SDimitry Andric 
34290b57cec5SDimitry Andric   if (error.Fail()) {
34309dba64beSDimitry Andric     LLDB_LOGF(log,
34319dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to attach to "
34320b57cec5SDimitry Andric               "pid %" PRIu64 ": %s\n",
34330b57cec5SDimitry Andric               __FUNCTION__, pid, error.AsCString());
34340b57cec5SDimitry Andric     return SendErrorResponse(error);
34350b57cec5SDimitry Andric   }
34360b57cec5SDimitry Andric 
34370b57cec5SDimitry Andric   // Notify we attached by sending a stop packet.
343881ad6265SDimitry Andric   assert(m_current_process);
343981ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
344081ad6265SDimitry Andric                                 m_current_process->GetState(),
344181ad6265SDimitry Andric                                 /*force_synchronous=*/false);
34420b57cec5SDimitry Andric }
34430b57cec5SDimitry Andric 
34440b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_vAttachWait(StringExtractorGDBRemote & packet)3445e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachWait(
3446e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
344781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3448e8d8bef9SDimitry Andric 
3449e8d8bef9SDimitry Andric   // Consume the ';' after the identifier.
3450e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("vAttachWait"));
3451e8d8bef9SDimitry Andric 
3452e8d8bef9SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
3453e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "vAttachWait missing expected ';'");
3454e8d8bef9SDimitry Andric 
3455e8d8bef9SDimitry Andric   // Allocate the buffer for the process name from vAttachWait.
3456e8d8bef9SDimitry Andric   std::string process_name;
3457e8d8bef9SDimitry Andric   if (!packet.GetHexByteString(process_name))
3458e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet,
3459e8d8bef9SDimitry Andric                                  "vAttachWait failed to parse process name");
3460e8d8bef9SDimitry Andric 
3461e8d8bef9SDimitry Andric   LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name);
3462e8d8bef9SDimitry Andric 
3463e8d8bef9SDimitry Andric   Status error = AttachWaitProcess(process_name, false);
3464e8d8bef9SDimitry Andric   if (error.Fail()) {
3465e8d8bef9SDimitry Andric     LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name,
3466e8d8bef9SDimitry Andric              error);
3467e8d8bef9SDimitry Andric     return SendErrorResponse(error);
3468e8d8bef9SDimitry Andric   }
3469e8d8bef9SDimitry Andric 
3470e8d8bef9SDimitry Andric   // Notify we attached by sending a stop packet.
347181ad6265SDimitry Andric   assert(m_current_process);
347281ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
347381ad6265SDimitry Andric                                 m_current_process->GetState(),
347481ad6265SDimitry Andric                                 /*force_synchronous=*/false);
3475e8d8bef9SDimitry Andric }
3476e8d8bef9SDimitry Andric 
3477e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_qVAttachOrWaitSupported(StringExtractorGDBRemote & packet)3478e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported(
3479e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
3480e8d8bef9SDimitry Andric   return SendOKResponse();
3481e8d8bef9SDimitry Andric }
3482e8d8bef9SDimitry Andric 
3483e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_vAttachOrWait(StringExtractorGDBRemote & packet)3484e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait(
3485e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
348681ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3487e8d8bef9SDimitry Andric 
3488e8d8bef9SDimitry Andric   // Consume the ';' after the identifier.
3489e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("vAttachOrWait"));
3490e8d8bef9SDimitry Andric 
3491e8d8bef9SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
3492e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "vAttachOrWait missing expected ';'");
3493e8d8bef9SDimitry Andric 
3494e8d8bef9SDimitry Andric   // Allocate the buffer for the process name from vAttachWait.
3495e8d8bef9SDimitry Andric   std::string process_name;
3496e8d8bef9SDimitry Andric   if (!packet.GetHexByteString(process_name))
3497e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet,
3498e8d8bef9SDimitry Andric                                  "vAttachOrWait failed to parse process name");
3499e8d8bef9SDimitry Andric 
3500e8d8bef9SDimitry Andric   LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name);
3501e8d8bef9SDimitry Andric 
3502e8d8bef9SDimitry Andric   Status error = AttachWaitProcess(process_name, true);
3503e8d8bef9SDimitry Andric   if (error.Fail()) {
3504e8d8bef9SDimitry Andric     LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name,
3505e8d8bef9SDimitry Andric              error);
3506e8d8bef9SDimitry Andric     return SendErrorResponse(error);
3507e8d8bef9SDimitry Andric   }
3508e8d8bef9SDimitry Andric 
3509e8d8bef9SDimitry Andric   // Notify we attached by sending a stop packet.
351081ad6265SDimitry Andric   assert(m_current_process);
351181ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
351281ad6265SDimitry Andric                                 m_current_process->GetState(),
351381ad6265SDimitry Andric                                 /*force_synchronous=*/false);
3514e8d8bef9SDimitry Andric }
3515e8d8bef9SDimitry Andric 
3516e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_vRun(StringExtractorGDBRemote & packet)3517349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vRun(
3518349cc55cSDimitry Andric     StringExtractorGDBRemote &packet) {
351981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3520349cc55cSDimitry Andric 
3521349cc55cSDimitry Andric   llvm::StringRef s = packet.GetStringRef();
3522349cc55cSDimitry Andric   if (!s.consume_front("vRun;"))
3523349cc55cSDimitry Andric     return SendErrorResponse(8);
3524349cc55cSDimitry Andric 
3525349cc55cSDimitry Andric   llvm::SmallVector<llvm::StringRef, 16> argv;
3526349cc55cSDimitry Andric   s.split(argv, ';');
3527349cc55cSDimitry Andric 
3528349cc55cSDimitry Andric   for (llvm::StringRef hex_arg : argv) {
3529349cc55cSDimitry Andric     StringExtractor arg_ext{hex_arg};
3530349cc55cSDimitry Andric     std::string arg;
3531349cc55cSDimitry Andric     arg_ext.GetHexByteString(arg);
3532349cc55cSDimitry Andric     m_process_launch_info.GetArguments().AppendArgument(arg);
3533349cc55cSDimitry Andric     LLDB_LOGF(log, "LLGSPacketHandler::%s added arg: \"%s\"", __FUNCTION__,
3534349cc55cSDimitry Andric               arg.c_str());
3535349cc55cSDimitry Andric   }
3536349cc55cSDimitry Andric 
3537bdd1243dSDimitry Andric   if (argv.empty())
3538bdd1243dSDimitry Andric     return SendErrorResponse(Status("No arguments"));
3539349cc55cSDimitry Andric   m_process_launch_info.GetExecutableFile().SetFile(
3540349cc55cSDimitry Andric       m_process_launch_info.GetArguments()[0].ref(), FileSpec::Style::native);
3541349cc55cSDimitry Andric   m_process_launch_error = LaunchProcess();
3542bdd1243dSDimitry Andric   if (m_process_launch_error.Fail())
3543bdd1243dSDimitry Andric     return SendErrorResponse(m_process_launch_error);
354481ad6265SDimitry Andric   assert(m_current_process);
354581ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
354681ad6265SDimitry Andric                                 m_current_process->GetState(),
354781ad6265SDimitry Andric                                 /*force_synchronous=*/true);
354881ad6265SDimitry Andric }
3549349cc55cSDimitry Andric 
3550349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult
Handle_D(StringExtractorGDBRemote & packet)35510b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
355281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3553fcaf7f86SDimitry Andric   if (!m_non_stop)
35540b57cec5SDimitry Andric     StopSTDIOForwarding();
35550b57cec5SDimitry Andric 
35560b57cec5SDimitry Andric   lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
35570b57cec5SDimitry Andric 
35580b57cec5SDimitry Andric   // Consume the ';' after D.
35590b57cec5SDimitry Andric   packet.SetFilePos(1);
35600b57cec5SDimitry Andric   if (packet.GetBytesLeft()) {
35610b57cec5SDimitry Andric     if (packet.GetChar() != ';')
35620b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "D missing expected ';'");
35630b57cec5SDimitry Andric 
35640b57cec5SDimitry Andric     // Grab the PID from which we will detach (assume hex encoding).
35650b57cec5SDimitry Andric     pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
35660b57cec5SDimitry Andric     if (pid == LLDB_INVALID_PROCESS_ID)
35670b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "D failed to parse the process id");
35680b57cec5SDimitry Andric   }
35690b57cec5SDimitry Andric 
3570fe6060f1SDimitry Andric   // Detach forked children if their PID was specified *or* no PID was requested
3571fe6060f1SDimitry Andric   // (i.e. detach-all packet).
3572fe6060f1SDimitry Andric   llvm::Error detach_error = llvm::Error::success();
3573fe6060f1SDimitry Andric   bool detached = false;
3574fe6060f1SDimitry Andric   for (auto it = m_debugged_processes.begin();
3575fe6060f1SDimitry Andric        it != m_debugged_processes.end();) {
3576fe6060f1SDimitry Andric     if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) {
357781ad6265SDimitry Andric       LLDB_LOGF(log,
357881ad6265SDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s detaching %" PRId64,
357981ad6265SDimitry Andric                 __FUNCTION__, it->first);
3580fcaf7f86SDimitry Andric       if (llvm::Error e = it->second.process_up->Detach().ToError())
3581fe6060f1SDimitry Andric         detach_error = llvm::joinErrors(std::move(detach_error), std::move(e));
3582fe6060f1SDimitry Andric       else {
3583fcaf7f86SDimitry Andric         if (it->second.process_up.get() == m_current_process)
3584fe6060f1SDimitry Andric           m_current_process = nullptr;
3585fcaf7f86SDimitry Andric         if (it->second.process_up.get() == m_continue_process)
3586fe6060f1SDimitry Andric           m_continue_process = nullptr;
3587fe6060f1SDimitry Andric         it = m_debugged_processes.erase(it);
3588fe6060f1SDimitry Andric         detached = true;
3589fe6060f1SDimitry Andric         continue;
3590fe6060f1SDimitry Andric       }
3591fe6060f1SDimitry Andric     }
3592fe6060f1SDimitry Andric     ++it;
35930b57cec5SDimitry Andric   }
35940b57cec5SDimitry Andric 
3595fe6060f1SDimitry Andric   if (detach_error)
3596fe6060f1SDimitry Andric     return SendErrorResponse(std::move(detach_error));
3597fe6060f1SDimitry Andric   if (!detached)
3598fe6060f1SDimitry Andric     return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid));
35990b57cec5SDimitry Andric   return SendOKResponse();
36000b57cec5SDimitry Andric }
36010b57cec5SDimitry Andric 
36020b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_qThreadStopInfo(StringExtractorGDBRemote & packet)36030b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
36040b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
360581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
360681ad6265SDimitry Andric 
360781ad6265SDimitry Andric   if (!m_current_process ||
360881ad6265SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
360981ad6265SDimitry Andric     return SendErrorResponse(50);
36100b57cec5SDimitry Andric 
36110b57cec5SDimitry Andric   packet.SetFilePos(strlen("qThreadStopInfo"));
3612fe6060f1SDimitry Andric   const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
36130b57cec5SDimitry Andric   if (tid == LLDB_INVALID_THREAD_ID) {
36149dba64beSDimitry Andric     LLDB_LOGF(log,
36159dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
36160b57cec5SDimitry Andric               "parse thread id from request \"%s\"",
36179dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
36180b57cec5SDimitry Andric     return SendErrorResponse(0x15);
36190b57cec5SDimitry Andric   }
362081ad6265SDimitry Andric   return SendStopReplyPacketForThread(*m_current_process, tid,
362181ad6265SDimitry Andric                                       /*force_synchronous=*/true);
36220b57cec5SDimitry Andric }
36230b57cec5SDimitry Andric 
36240b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_jThreadsInfo(StringExtractorGDBRemote &)36250b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
36260b57cec5SDimitry Andric     StringExtractorGDBRemote &) {
362781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
36280b57cec5SDimitry Andric 
36290b57cec5SDimitry Andric   // Ensure we have a debugged process.
3630fe6060f1SDimitry Andric   if (!m_current_process ||
3631fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
36320b57cec5SDimitry Andric     return SendErrorResponse(50);
3633fe6060f1SDimitry Andric   LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID());
36340b57cec5SDimitry Andric 
36350b57cec5SDimitry Andric   StreamString response;
36360b57cec5SDimitry Andric   const bool threads_with_valid_stop_info_only = false;
3637fe6060f1SDimitry Andric   llvm::Expected<json::Value> threads_info =
3638fe6060f1SDimitry Andric       GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only);
36399dba64beSDimitry Andric   if (!threads_info) {
3640480093f4SDimitry Andric     LLDB_LOG_ERROR(log, threads_info.takeError(),
3641480093f4SDimitry Andric                    "failed to prepare a packet for pid {1}: {0}",
3642fe6060f1SDimitry Andric                    m_current_process->GetID());
36430b57cec5SDimitry Andric     return SendErrorResponse(52);
36440b57cec5SDimitry Andric   }
36450b57cec5SDimitry Andric 
36469dba64beSDimitry Andric   response.AsRawOstream() << *threads_info;
36470b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
36480b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
36490b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
36500b57cec5SDimitry Andric }
36510b57cec5SDimitry Andric 
36520b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_qWatchpointSupportInfo(StringExtractorGDBRemote & packet)36530b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
36540b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
36550b57cec5SDimitry Andric   // Fail if we don't have a current process.
3656fe6060f1SDimitry Andric   if (!m_current_process ||
3657fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
36580b57cec5SDimitry Andric     return SendErrorResponse(68);
36590b57cec5SDimitry Andric 
36600b57cec5SDimitry Andric   packet.SetFilePos(strlen("qWatchpointSupportInfo"));
36610b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0)
36620b57cec5SDimitry Andric     return SendOKResponse();
36630b57cec5SDimitry Andric   if (packet.GetChar() != ':')
36640b57cec5SDimitry Andric     return SendErrorResponse(67);
36650b57cec5SDimitry Andric 
3666fe6060f1SDimitry Andric   auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo();
36670b57cec5SDimitry Andric 
36680b57cec5SDimitry Andric   StreamGDBRemote response;
3669bdd1243dSDimitry Andric   if (hw_debug_cap == std::nullopt)
36700b57cec5SDimitry Andric     response.Printf("num:0;");
36710b57cec5SDimitry Andric   else
36720b57cec5SDimitry Andric     response.Printf("num:%d;", hw_debug_cap->second);
36730b57cec5SDimitry Andric 
36740b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
36750b57cec5SDimitry Andric }
36760b57cec5SDimitry Andric 
36770b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_qFileLoadAddress(StringExtractorGDBRemote & packet)36780b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
36790b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
36800b57cec5SDimitry Andric   // Fail if we don't have a current process.
3681fe6060f1SDimitry Andric   if (!m_current_process ||
3682fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
36830b57cec5SDimitry Andric     return SendErrorResponse(67);
36840b57cec5SDimitry Andric 
36850b57cec5SDimitry Andric   packet.SetFilePos(strlen("qFileLoadAddress:"));
36860b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0)
36870b57cec5SDimitry Andric     return SendErrorResponse(68);
36880b57cec5SDimitry Andric 
36890b57cec5SDimitry Andric   std::string file_name;
36900b57cec5SDimitry Andric   packet.GetHexByteString(file_name);
36910b57cec5SDimitry Andric 
36920b57cec5SDimitry Andric   lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
36930b57cec5SDimitry Andric   Status error =
3694fe6060f1SDimitry Andric       m_current_process->GetFileLoadAddress(file_name, file_load_address);
36950b57cec5SDimitry Andric   if (error.Fail())
36960b57cec5SDimitry Andric     return SendErrorResponse(69);
36970b57cec5SDimitry Andric 
36980b57cec5SDimitry Andric   if (file_load_address == LLDB_INVALID_ADDRESS)
36990b57cec5SDimitry Andric     return SendErrorResponse(1); // File not loaded
37000b57cec5SDimitry Andric 
37010b57cec5SDimitry Andric   StreamGDBRemote response;
37020b57cec5SDimitry Andric   response.PutHex64(file_load_address);
37030b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
37040b57cec5SDimitry Andric }
37050b57cec5SDimitry Andric 
37060b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_QPassSignals(StringExtractorGDBRemote & packet)37070b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
37080b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
37090b57cec5SDimitry Andric   std::vector<int> signals;
37100b57cec5SDimitry Andric   packet.SetFilePos(strlen("QPassSignals:"));
37110b57cec5SDimitry Andric 
37120b57cec5SDimitry Andric   // Read sequence of hex signal numbers divided by a semicolon and optionally
37130b57cec5SDimitry Andric   // spaces.
37140b57cec5SDimitry Andric   while (packet.GetBytesLeft() > 0) {
37150b57cec5SDimitry Andric     int signal = packet.GetS32(-1, 16);
37160b57cec5SDimitry Andric     if (signal < 0)
37170b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Failed to parse signal number.");
37180b57cec5SDimitry Andric     signals.push_back(signal);
37190b57cec5SDimitry Andric 
37200b57cec5SDimitry Andric     packet.SkipSpaces();
37210b57cec5SDimitry Andric     char separator = packet.GetChar();
37220b57cec5SDimitry Andric     if (separator == '\0')
37230b57cec5SDimitry Andric       break; // End of string
37240b57cec5SDimitry Andric     if (separator != ';')
37250b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Invalid separator,"
37260b57cec5SDimitry Andric                                             " expected semicolon.");
37270b57cec5SDimitry Andric   }
37280b57cec5SDimitry Andric 
37290b57cec5SDimitry Andric   // Fail if we don't have a current process.
3730fe6060f1SDimitry Andric   if (!m_current_process)
37310b57cec5SDimitry Andric     return SendErrorResponse(68);
37320b57cec5SDimitry Andric 
3733fe6060f1SDimitry Andric   Status error = m_current_process->IgnoreSignals(signals);
37340b57cec5SDimitry Andric   if (error.Fail())
37350b57cec5SDimitry Andric     return SendErrorResponse(69);
37360b57cec5SDimitry Andric 
37370b57cec5SDimitry Andric   return SendOKResponse();
37380b57cec5SDimitry Andric }
37390b57cec5SDimitry Andric 
3740fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_qMemTags(StringExtractorGDBRemote & packet)3741fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
3742fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
374381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3744fe6060f1SDimitry Andric 
3745fe6060f1SDimitry Andric   // Ensure we have a process.
3746fe6060f1SDimitry Andric   if (!m_current_process ||
3747fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
3748fe6060f1SDimitry Andric     LLDB_LOGF(
3749fe6060f1SDimitry Andric         log,
3750fe6060f1SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
3751fe6060f1SDimitry Andric         __FUNCTION__);
3752fe6060f1SDimitry Andric     return SendErrorResponse(1);
3753fe6060f1SDimitry Andric   }
3754fe6060f1SDimitry Andric 
3755fe6060f1SDimitry Andric   // We are expecting
3756fe6060f1SDimitry Andric   // qMemTags:<hex address>,<hex length>:<hex type>
3757fe6060f1SDimitry Andric 
3758fe6060f1SDimitry Andric   // Address
3759fe6060f1SDimitry Andric   packet.SetFilePos(strlen("qMemTags:"));
3760fe6060f1SDimitry Andric   const char *current_char = packet.Peek();
3761fe6060f1SDimitry Andric   if (!current_char || *current_char == ',')
3762fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, "Missing address in qMemTags packet");
3763fe6060f1SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3764fe6060f1SDimitry Andric 
3765fe6060f1SDimitry Andric   // Length
3766fe6060f1SDimitry Andric   char previous_char = packet.GetChar();
3767fe6060f1SDimitry Andric   current_char = packet.Peek();
3768fe6060f1SDimitry Andric   // If we don't have a separator or the length field is empty
3769fe6060f1SDimitry Andric   if (previous_char != ',' || (current_char && *current_char == ':'))
3770fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3771fe6060f1SDimitry Andric                                  "Invalid addr,length pair in qMemTags packet");
3772fe6060f1SDimitry Andric 
3773fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1)
3774fe6060f1SDimitry Andric     return SendIllFormedResponse(
3775fe6060f1SDimitry Andric         packet, "Too short qMemtags: packet (looking for length)");
3776fe6060f1SDimitry Andric   const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3777fe6060f1SDimitry Andric 
3778fe6060f1SDimitry Andric   // Type
3779fe6060f1SDimitry Andric   const char *invalid_type_err = "Invalid type field in qMemTags: packet";
3780fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3781fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3782fe6060f1SDimitry Andric 
37836e75b2fbSDimitry Andric   // Type is a signed integer but packed into the packet as its raw bytes.
37846e75b2fbSDimitry Andric   // However, our GetU64 uses strtoull which allows +/-. We do not want this.
37856e75b2fbSDimitry Andric   const char *first_type_char = packet.Peek();
37866e75b2fbSDimitry Andric   if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
37876e75b2fbSDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
37886e75b2fbSDimitry Andric 
37896e75b2fbSDimitry Andric   // Extract type as unsigned then cast to signed.
37906e75b2fbSDimitry Andric   // Using a uint64_t here so that we have some value outside of the 32 bit
37916e75b2fbSDimitry Andric   // range to use as the invalid return value.
37926e75b2fbSDimitry Andric   uint64_t raw_type =
37936e75b2fbSDimitry Andric       packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
37946e75b2fbSDimitry Andric 
37956e75b2fbSDimitry Andric   if ( // Make sure the cast below would be valid
37966e75b2fbSDimitry Andric       raw_type > std::numeric_limits<uint32_t>::max() ||
3797fe6060f1SDimitry Andric       // To catch inputs like "123aardvark" that will parse but clearly aren't
3798fe6060f1SDimitry Andric       // valid in this case.
3799fe6060f1SDimitry Andric       packet.GetBytesLeft()) {
3800fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3801fe6060f1SDimitry Andric   }
3802fe6060f1SDimitry Andric 
38036e75b2fbSDimitry Andric   // First narrow to 32 bits otherwise the copy into type would take
38046e75b2fbSDimitry Andric   // the wrong 4 bytes on big endian.
38056e75b2fbSDimitry Andric   uint32_t raw_type_32 = raw_type;
38066e75b2fbSDimitry Andric   int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
38076e75b2fbSDimitry Andric 
3808fe6060f1SDimitry Andric   StreamGDBRemote response;
3809fe6060f1SDimitry Andric   std::vector<uint8_t> tags;
3810fe6060f1SDimitry Andric   Status error = m_current_process->ReadMemoryTags(type, addr, length, tags);
3811fe6060f1SDimitry Andric   if (error.Fail())
3812fe6060f1SDimitry Andric     return SendErrorResponse(1);
3813fe6060f1SDimitry Andric 
3814fe6060f1SDimitry Andric   // This m is here in case we want to support multi part replies in the future.
3815fe6060f1SDimitry Andric   // In the same manner as qfThreadInfo/qsThreadInfo.
3816fe6060f1SDimitry Andric   response.PutChar('m');
3817fe6060f1SDimitry Andric   response.PutBytesAsRawHex8(tags.data(), tags.size());
3818fe6060f1SDimitry Andric   return SendPacketNoLock(response.GetString());
3819fe6060f1SDimitry Andric }
3820fe6060f1SDimitry Andric 
3821fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_QMemTags(StringExtractorGDBRemote & packet)3822fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QMemTags(
3823fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
382481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3825fe6060f1SDimitry Andric 
3826fe6060f1SDimitry Andric   // Ensure we have a process.
3827fe6060f1SDimitry Andric   if (!m_current_process ||
3828fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
3829fe6060f1SDimitry Andric     LLDB_LOGF(
3830fe6060f1SDimitry Andric         log,
3831fe6060f1SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
3832fe6060f1SDimitry Andric         __FUNCTION__);
3833fe6060f1SDimitry Andric     return SendErrorResponse(1);
3834fe6060f1SDimitry Andric   }
3835fe6060f1SDimitry Andric 
3836fe6060f1SDimitry Andric   // We are expecting
3837fe6060f1SDimitry Andric   // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes>
3838fe6060f1SDimitry Andric 
3839fe6060f1SDimitry Andric   // Address
3840fe6060f1SDimitry Andric   packet.SetFilePos(strlen("QMemTags:"));
3841fe6060f1SDimitry Andric   const char *current_char = packet.Peek();
3842fe6060f1SDimitry Andric   if (!current_char || *current_char == ',')
3843fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, "Missing address in QMemTags packet");
3844fe6060f1SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3845fe6060f1SDimitry Andric 
3846fe6060f1SDimitry Andric   // Length
3847fe6060f1SDimitry Andric   char previous_char = packet.GetChar();
3848fe6060f1SDimitry Andric   current_char = packet.Peek();
3849fe6060f1SDimitry Andric   // If we don't have a separator or the length field is empty
3850fe6060f1SDimitry Andric   if (previous_char != ',' || (current_char && *current_char == ':'))
3851fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3852fe6060f1SDimitry Andric                                  "Invalid addr,length pair in QMemTags packet");
3853fe6060f1SDimitry Andric 
3854fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1)
3855fe6060f1SDimitry Andric     return SendIllFormedResponse(
3856fe6060f1SDimitry Andric         packet, "Too short QMemtags: packet (looking for length)");
3857fe6060f1SDimitry Andric   const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3858fe6060f1SDimitry Andric 
3859fe6060f1SDimitry Andric   // Type
3860fe6060f1SDimitry Andric   const char *invalid_type_err = "Invalid type field in QMemTags: packet";
3861fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3862fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3863fe6060f1SDimitry Andric 
3864fe6060f1SDimitry Andric   // Our GetU64 uses strtoull which allows leading +/-, we don't want that.
3865fe6060f1SDimitry Andric   const char *first_type_char = packet.Peek();
3866fe6060f1SDimitry Andric   if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
3867fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3868fe6060f1SDimitry Andric 
3869fe6060f1SDimitry Andric   // The type is a signed integer but is in the packet as its raw bytes.
3870fe6060f1SDimitry Andric   // So parse first as unsigned then cast to signed later.
3871fe6060f1SDimitry Andric   // We extract to 64 bit, even though we only expect 32, so that we've
3872fe6060f1SDimitry Andric   // got some invalid value we can check for.
3873fe6060f1SDimitry Andric   uint64_t raw_type =
3874fe6060f1SDimitry Andric       packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
3875fe6060f1SDimitry Andric   if (raw_type > std::numeric_limits<uint32_t>::max())
3876fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
38776e75b2fbSDimitry Andric 
38786e75b2fbSDimitry Andric   // First narrow to 32 bits. Otherwise the copy below would get the wrong
38796e75b2fbSDimitry Andric   // 4 bytes on big endian.
38806e75b2fbSDimitry Andric   uint32_t raw_type_32 = raw_type;
38816e75b2fbSDimitry Andric   int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
3882fe6060f1SDimitry Andric 
3883fe6060f1SDimitry Andric   // Tag data
3884fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3885fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3886fe6060f1SDimitry Andric                                  "Missing tag data in QMemTags: packet");
3887fe6060f1SDimitry Andric 
3888fe6060f1SDimitry Andric   // Must be 2 chars per byte
3889fe6060f1SDimitry Andric   const char *invalid_data_err = "Invalid tag data in QMemTags: packet";
3890fe6060f1SDimitry Andric   if (packet.GetBytesLeft() % 2)
3891fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_data_err);
3892fe6060f1SDimitry Andric 
3893fe6060f1SDimitry Andric   // This is bytes here and is unpacked into target specific tags later
3894fe6060f1SDimitry Andric   // We cannot assume that number of bytes == length here because the server
3895fe6060f1SDimitry Andric   // can repeat tags to fill a given range.
3896fe6060f1SDimitry Andric   std::vector<uint8_t> tag_data;
3897fe6060f1SDimitry Andric   // Zero length writes will not have any tag data
3898fe6060f1SDimitry Andric   // (but we pass them on because it will still check that tagging is enabled)
3899fe6060f1SDimitry Andric   if (packet.GetBytesLeft()) {
3900fe6060f1SDimitry Andric     size_t byte_count = packet.GetBytesLeft() / 2;
3901fe6060f1SDimitry Andric     tag_data.resize(byte_count);
3902fe6060f1SDimitry Andric     size_t converted_bytes = packet.GetHexBytes(tag_data, 0);
3903fe6060f1SDimitry Andric     if (converted_bytes != byte_count) {
3904fe6060f1SDimitry Andric       return SendIllFormedResponse(packet, invalid_data_err);
3905fe6060f1SDimitry Andric     }
3906fe6060f1SDimitry Andric   }
3907fe6060f1SDimitry Andric 
3908fe6060f1SDimitry Andric   Status status =
3909fe6060f1SDimitry Andric       m_current_process->WriteMemoryTags(type, addr, length, tag_data);
3910fe6060f1SDimitry Andric   return status.Success() ? SendOKResponse() : SendErrorResponse(1);
3911fe6060f1SDimitry Andric }
3912fe6060f1SDimitry Andric 
3913349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult
Handle_qSaveCore(StringExtractorGDBRemote & packet)3914349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qSaveCore(
3915349cc55cSDimitry Andric     StringExtractorGDBRemote &packet) {
3916349cc55cSDimitry Andric   // Fail if we don't have a current process.
3917349cc55cSDimitry Andric   if (!m_current_process ||
3918349cc55cSDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
3919349cc55cSDimitry Andric     return SendErrorResponse(Status("Process not running."));
3920349cc55cSDimitry Andric 
3921349cc55cSDimitry Andric   std::string path_hint;
3922349cc55cSDimitry Andric 
3923349cc55cSDimitry Andric   StringRef packet_str{packet.GetStringRef()};
39245f757f3fSDimitry Andric   assert(packet_str.starts_with("qSaveCore"));
3925349cc55cSDimitry Andric   if (packet_str.consume_front("qSaveCore;")) {
3926349cc55cSDimitry Andric     for (auto x : llvm::split(packet_str, ';')) {
3927349cc55cSDimitry Andric       if (x.consume_front("path-hint:"))
3928349cc55cSDimitry Andric         StringExtractor(x).GetHexByteString(path_hint);
3929349cc55cSDimitry Andric       else
3930349cc55cSDimitry Andric         return SendErrorResponse(Status("Unsupported qSaveCore option"));
3931349cc55cSDimitry Andric     }
3932349cc55cSDimitry Andric   }
3933349cc55cSDimitry Andric 
3934349cc55cSDimitry Andric   llvm::Expected<std::string> ret = m_current_process->SaveCore(path_hint);
3935349cc55cSDimitry Andric   if (!ret)
3936349cc55cSDimitry Andric     return SendErrorResponse(ret.takeError());
3937349cc55cSDimitry Andric 
3938349cc55cSDimitry Andric   StreamString response;
3939349cc55cSDimitry Andric   response.PutCString("core-path:");
3940349cc55cSDimitry Andric   response.PutStringAsRawHex8(ret.get());
3941349cc55cSDimitry Andric   return SendPacketNoLock(response.GetString());
3942349cc55cSDimitry Andric }
3943349cc55cSDimitry Andric 
394481ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_QNonStop(StringExtractorGDBRemote & packet)394581ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QNonStop(
394681ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
3947fcaf7f86SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3948fcaf7f86SDimitry Andric 
394981ad6265SDimitry Andric   StringRef packet_str{packet.GetStringRef()};
39505f757f3fSDimitry Andric   assert(packet_str.starts_with("QNonStop:"));
395181ad6265SDimitry Andric   packet_str.consume_front("QNonStop:");
395281ad6265SDimitry Andric   if (packet_str == "0") {
3953fcaf7f86SDimitry Andric     if (m_non_stop)
3954fcaf7f86SDimitry Andric       StopSTDIOForwarding();
3955fcaf7f86SDimitry Andric     for (auto &process_it : m_debugged_processes) {
3956fcaf7f86SDimitry Andric       if (process_it.second.process_up->IsRunning()) {
3957fcaf7f86SDimitry Andric         assert(m_non_stop);
3958fcaf7f86SDimitry Andric         Status error = process_it.second.process_up->Interrupt();
3959fcaf7f86SDimitry Andric         if (error.Fail()) {
3960fcaf7f86SDimitry Andric           LLDB_LOG(log,
3961fcaf7f86SDimitry Andric                    "while disabling nonstop, failed to halt process {0}: {1}",
3962fcaf7f86SDimitry Andric                    process_it.first, error);
3963fcaf7f86SDimitry Andric           return SendErrorResponse(0x41);
3964fcaf7f86SDimitry Andric         }
3965fcaf7f86SDimitry Andric         // we must not send stop reasons after QNonStop
3966fcaf7f86SDimitry Andric         m_disabling_non_stop = true;
3967fcaf7f86SDimitry Andric       }
3968fcaf7f86SDimitry Andric     }
3969fcaf7f86SDimitry Andric     m_stdio_notification_queue.clear();
3970fcaf7f86SDimitry Andric     m_stop_notification_queue.clear();
397181ad6265SDimitry Andric     m_non_stop = false;
3972fcaf7f86SDimitry Andric     // If we are stopping anything, defer sending the OK response until we're
3973fcaf7f86SDimitry Andric     // done.
3974fcaf7f86SDimitry Andric     if (m_disabling_non_stop)
3975fcaf7f86SDimitry Andric       return PacketResult::Success;
397681ad6265SDimitry Andric   } else if (packet_str == "1") {
3977fcaf7f86SDimitry Andric     if (!m_non_stop)
3978fcaf7f86SDimitry Andric       StartSTDIOForwarding();
397981ad6265SDimitry Andric     m_non_stop = true;
398081ad6265SDimitry Andric   } else
398181ad6265SDimitry Andric     return SendErrorResponse(Status("Invalid QNonStop packet"));
398281ad6265SDimitry Andric   return SendOKResponse();
398381ad6265SDimitry Andric }
398481ad6265SDimitry Andric 
398581ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
HandleNotificationAck(std::deque<std::string> & queue)3986fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::HandleNotificationAck(
3987fcaf7f86SDimitry Andric     std::deque<std::string> &queue) {
3988fcaf7f86SDimitry Andric   // Per the protocol, the first message put into the queue is sent
3989fcaf7f86SDimitry Andric   // immediately.  However, it remains the queue until the client ACKs it --
3990fcaf7f86SDimitry Andric   // then we pop it and send the next message.  The process repeats until
3991fcaf7f86SDimitry Andric   // the last message in the queue is ACK-ed, in which case the packet sends
3992fcaf7f86SDimitry Andric   // an OK response.
3993fcaf7f86SDimitry Andric   if (queue.empty())
3994fcaf7f86SDimitry Andric     return SendErrorResponse(Status("No pending notification to ack"));
3995fcaf7f86SDimitry Andric   queue.pop_front();
3996fcaf7f86SDimitry Andric   if (!queue.empty())
3997fcaf7f86SDimitry Andric     return SendPacketNoLock(queue.front());
3998fcaf7f86SDimitry Andric   return SendOKResponse();
3999fcaf7f86SDimitry Andric }
4000fcaf7f86SDimitry Andric 
4001fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_vStdio(StringExtractorGDBRemote & packet)4002fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStdio(
4003fcaf7f86SDimitry Andric     StringExtractorGDBRemote &packet) {
4004fcaf7f86SDimitry Andric   return HandleNotificationAck(m_stdio_notification_queue);
4005fcaf7f86SDimitry Andric }
4006fcaf7f86SDimitry Andric 
4007fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_vStopped(StringExtractorGDBRemote & packet)400881ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStopped(
400981ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
4010fcaf7f86SDimitry Andric   PacketResult ret = HandleNotificationAck(m_stop_notification_queue);
401181ad6265SDimitry Andric   // If this was the last notification and all the processes exited,
401281ad6265SDimitry Andric   // terminate the server.
4013fcaf7f86SDimitry Andric   if (m_stop_notification_queue.empty() && m_debugged_processes.empty()) {
401481ad6265SDimitry Andric     m_exit_now = true;
401581ad6265SDimitry Andric     m_mainloop.RequestTermination();
401681ad6265SDimitry Andric   }
4017fcaf7f86SDimitry Andric   return ret;
401881ad6265SDimitry Andric }
401981ad6265SDimitry Andric 
402081ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_vCtrlC(StringExtractorGDBRemote & packet)402181ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCtrlC(
402281ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
402381ad6265SDimitry Andric   if (!m_non_stop)
402481ad6265SDimitry Andric     return SendErrorResponse(Status("vCtrl is only valid in non-stop mode"));
402581ad6265SDimitry Andric 
402681ad6265SDimitry Andric   PacketResult interrupt_res = Handle_interrupt(packet);
402781ad6265SDimitry Andric   // If interrupting the process failed, pass the result through.
402881ad6265SDimitry Andric   if (interrupt_res != PacketResult::Success)
402981ad6265SDimitry Andric     return interrupt_res;
403081ad6265SDimitry Andric   // Otherwise, vCtrlC should issue an OK response (normal interrupts do not).
403181ad6265SDimitry Andric   return SendOKResponse();
403281ad6265SDimitry Andric }
403381ad6265SDimitry Andric 
403481ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
Handle_T(StringExtractorGDBRemote & packet)403581ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_T(StringExtractorGDBRemote &packet) {
403681ad6265SDimitry Andric   packet.SetFilePos(strlen("T"));
403781ad6265SDimitry Andric   auto pid_tid = packet.GetPidTid(m_current_process ? m_current_process->GetID()
403881ad6265SDimitry Andric                                                     : LLDB_INVALID_PROCESS_ID);
403981ad6265SDimitry Andric   if (!pid_tid)
404081ad6265SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
404181ad6265SDimitry Andric         inconvertibleErrorCode(), "Malformed thread-id"));
404281ad6265SDimitry Andric 
404381ad6265SDimitry Andric   lldb::pid_t pid = pid_tid->first;
404481ad6265SDimitry Andric   lldb::tid_t tid = pid_tid->second;
404581ad6265SDimitry Andric 
404681ad6265SDimitry Andric   // Technically, this would also be caught by the PID check but let's be more
404781ad6265SDimitry Andric   // explicit about the error.
404881ad6265SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
404981ad6265SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
405081ad6265SDimitry Andric         inconvertibleErrorCode(), "No current process and no PID provided"));
405181ad6265SDimitry Andric 
405281ad6265SDimitry Andric   // Check the process ID and find respective process instance.
405381ad6265SDimitry Andric   auto new_process_it = m_debugged_processes.find(pid);
405481ad6265SDimitry Andric   if (new_process_it == m_debugged_processes.end())
405581ad6265SDimitry Andric     return SendErrorResponse(1);
405681ad6265SDimitry Andric 
405781ad6265SDimitry Andric   // Check the thread ID
4058fcaf7f86SDimitry Andric   if (!new_process_it->second.process_up->GetThreadByID(tid))
405981ad6265SDimitry Andric     return SendErrorResponse(2);
406081ad6265SDimitry Andric 
406181ad6265SDimitry Andric   return SendOKResponse();
406281ad6265SDimitry Andric }
406381ad6265SDimitry Andric 
MaybeCloseInferiorTerminalConnection()40640b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
406581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
40660b57cec5SDimitry Andric 
40670b57cec5SDimitry Andric   // Tell the stdio connection to shut down.
40680b57cec5SDimitry Andric   if (m_stdio_communication.IsConnected()) {
40690b57cec5SDimitry Andric     auto connection = m_stdio_communication.GetConnection();
40700b57cec5SDimitry Andric     if (connection) {
40710b57cec5SDimitry Andric       Status error;
40720b57cec5SDimitry Andric       connection->Disconnect(&error);
40730b57cec5SDimitry Andric 
40740b57cec5SDimitry Andric       if (error.Success()) {
40759dba64beSDimitry Andric         LLDB_LOGF(log,
40769dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s disconnect process "
40770b57cec5SDimitry Andric                   "terminal stdio - SUCCESS",
40780b57cec5SDimitry Andric                   __FUNCTION__);
40790b57cec5SDimitry Andric       } else {
40809dba64beSDimitry Andric         LLDB_LOGF(log,
40819dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s disconnect process "
40820b57cec5SDimitry Andric                   "terminal stdio - FAIL: %s",
40830b57cec5SDimitry Andric                   __FUNCTION__, error.AsCString());
40840b57cec5SDimitry Andric       }
40850b57cec5SDimitry Andric     }
40860b57cec5SDimitry Andric   }
40870b57cec5SDimitry Andric }
40880b57cec5SDimitry Andric 
GetThreadFromSuffix(StringExtractorGDBRemote & packet)40890b57cec5SDimitry Andric NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
40900b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
40910b57cec5SDimitry Andric   // We have no thread if we don't have a process.
4092fe6060f1SDimitry Andric   if (!m_current_process ||
4093fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
40940b57cec5SDimitry Andric     return nullptr;
40950b57cec5SDimitry Andric 
40960b57cec5SDimitry Andric   // If the client hasn't asked for thread suffix support, there will not be a
40970b57cec5SDimitry Andric   // thread suffix. Use the current thread in that case.
40980b57cec5SDimitry Andric   if (!m_thread_suffix_supported) {
40990b57cec5SDimitry Andric     const lldb::tid_t current_tid = GetCurrentThreadID();
41000b57cec5SDimitry Andric     if (current_tid == LLDB_INVALID_THREAD_ID)
41010b57cec5SDimitry Andric       return nullptr;
41020b57cec5SDimitry Andric     else if (current_tid == 0) {
41030b57cec5SDimitry Andric       // Pick a thread.
4104fe6060f1SDimitry Andric       return m_current_process->GetThreadAtIndex(0);
41050b57cec5SDimitry Andric     } else
4106fe6060f1SDimitry Andric       return m_current_process->GetThreadByID(current_tid);
41070b57cec5SDimitry Andric   }
41080b57cec5SDimitry Andric 
410981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
41100b57cec5SDimitry Andric 
41110b57cec5SDimitry Andric   // Parse out the ';'.
41120b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') {
41139dba64beSDimitry Andric     LLDB_LOGF(log,
41149dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
41150b57cec5SDimitry Andric               "error: expected ';' prior to start of thread suffix: packet "
41160b57cec5SDimitry Andric               "contents = '%s'",
41179dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
41180b57cec5SDimitry Andric     return nullptr;
41190b57cec5SDimitry Andric   }
41200b57cec5SDimitry Andric 
41210b57cec5SDimitry Andric   if (!packet.GetBytesLeft())
41220b57cec5SDimitry Andric     return nullptr;
41230b57cec5SDimitry Andric 
41240b57cec5SDimitry Andric   // Parse out thread: portion.
41250b57cec5SDimitry Andric   if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) {
41269dba64beSDimitry Andric     LLDB_LOGF(log,
41279dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
41280b57cec5SDimitry Andric               "error: expected 'thread:' but not found, packet contents = "
41290b57cec5SDimitry Andric               "'%s'",
41309dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
41310b57cec5SDimitry Andric     return nullptr;
41320b57cec5SDimitry Andric   }
41330b57cec5SDimitry Andric   packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
41340b57cec5SDimitry Andric   const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
41350b57cec5SDimitry Andric   if (tid != 0)
4136fe6060f1SDimitry Andric     return m_current_process->GetThreadByID(tid);
41370b57cec5SDimitry Andric 
41380b57cec5SDimitry Andric   return nullptr;
41390b57cec5SDimitry Andric }
41400b57cec5SDimitry Andric 
GetCurrentThreadID() const41410b57cec5SDimitry Andric lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
41420b57cec5SDimitry Andric   if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
41430b57cec5SDimitry Andric     // Use whatever the debug process says is the current thread id since the
41440b57cec5SDimitry Andric     // protocol either didn't specify or specified we want any/all threads
41450b57cec5SDimitry Andric     // marked as the current thread.
4146fe6060f1SDimitry Andric     if (!m_current_process)
41470b57cec5SDimitry Andric       return LLDB_INVALID_THREAD_ID;
4148fe6060f1SDimitry Andric     return m_current_process->GetCurrentThreadID();
41490b57cec5SDimitry Andric   }
41500b57cec5SDimitry Andric   // Use the specific current thread id set by the gdb remote protocol.
41510b57cec5SDimitry Andric   return m_current_tid;
41520b57cec5SDimitry Andric }
41530b57cec5SDimitry Andric 
GetNextSavedRegistersID()41540b57cec5SDimitry Andric uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() {
41550b57cec5SDimitry Andric   std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
41560b57cec5SDimitry Andric   return m_next_saved_registers_id++;
41570b57cec5SDimitry Andric }
41580b57cec5SDimitry Andric 
ClearProcessSpecificData()41590b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
416081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
41610b57cec5SDimitry Andric 
41620b57cec5SDimitry Andric   LLDB_LOG(log, "clearing {0} xfer buffers", m_xfer_buffer_map.size());
41630b57cec5SDimitry Andric   m_xfer_buffer_map.clear();
41640b57cec5SDimitry Andric }
41650b57cec5SDimitry Andric 
41660b57cec5SDimitry Andric FileSpec
FindModuleFile(const std::string & module_path,const ArchSpec & arch)41670b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
41680b57cec5SDimitry Andric                                                  const ArchSpec &arch) {
4169fe6060f1SDimitry Andric   if (m_current_process) {
41700b57cec5SDimitry Andric     FileSpec file_spec;
4171fe6060f1SDimitry Andric     if (m_current_process
41720b57cec5SDimitry Andric             ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
41730b57cec5SDimitry Andric             .Success()) {
41740b57cec5SDimitry Andric       if (FileSystem::Instance().Exists(file_spec))
41750b57cec5SDimitry Andric         return file_spec;
41760b57cec5SDimitry Andric     }
41770b57cec5SDimitry Andric   }
41780b57cec5SDimitry Andric 
41790b57cec5SDimitry Andric   return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch);
41800b57cec5SDimitry Andric }
41819dba64beSDimitry Andric 
XMLEncodeAttributeValue(llvm::StringRef value)41829dba64beSDimitry Andric std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue(
41839dba64beSDimitry Andric     llvm::StringRef value) {
41849dba64beSDimitry Andric   std::string result;
41859dba64beSDimitry Andric   for (const char &c : value) {
41869dba64beSDimitry Andric     switch (c) {
41879dba64beSDimitry Andric     case '\'':
41889dba64beSDimitry Andric       result += "&apos;";
41899dba64beSDimitry Andric       break;
41909dba64beSDimitry Andric     case '"':
41919dba64beSDimitry Andric       result += "&quot;";
41929dba64beSDimitry Andric       break;
41939dba64beSDimitry Andric     case '<':
41949dba64beSDimitry Andric       result += "&lt;";
41959dba64beSDimitry Andric       break;
41969dba64beSDimitry Andric     case '>':
41979dba64beSDimitry Andric       result += "&gt;";
41989dba64beSDimitry Andric       break;
41999dba64beSDimitry Andric     default:
42009dba64beSDimitry Andric       result += c;
42019dba64beSDimitry Andric       break;
42029dba64beSDimitry Andric     }
42039dba64beSDimitry Andric   }
42049dba64beSDimitry Andric   return result;
42059dba64beSDimitry Andric }
4206fe6060f1SDimitry Andric 
HandleFeatures(const llvm::ArrayRef<llvm::StringRef> client_features)4207fe6060f1SDimitry Andric std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
4208fe6060f1SDimitry Andric     const llvm::ArrayRef<llvm::StringRef> client_features) {
4209fe6060f1SDimitry Andric   std::vector<std::string> ret =
4210fe6060f1SDimitry Andric       GDBRemoteCommunicationServerCommon::HandleFeatures(client_features);
4211fe6060f1SDimitry Andric   ret.insert(ret.end(), {
4212fe6060f1SDimitry Andric                             "QThreadSuffixSupported+",
4213fe6060f1SDimitry Andric                             "QListThreadsInStopReply+",
4214fe6060f1SDimitry Andric                             "qXfer:features:read+",
421581ad6265SDimitry Andric                             "QNonStop+",
4216fe6060f1SDimitry Andric                         });
4217fe6060f1SDimitry Andric 
4218fe6060f1SDimitry Andric   // report server-only features
4219fe6060f1SDimitry Andric   using Extension = NativeProcessProtocol::Extension;
422006c3fb27SDimitry Andric   Extension plugin_features = m_process_manager.GetSupportedExtensions();
4221fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::pass_signals))
4222fe6060f1SDimitry Andric     ret.push_back("QPassSignals+");
4223fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::auxv))
4224fe6060f1SDimitry Andric     ret.push_back("qXfer:auxv:read+");
4225fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::libraries_svr4))
4226fe6060f1SDimitry Andric     ret.push_back("qXfer:libraries-svr4:read+");
422704eeddc0SDimitry Andric   if (bool(plugin_features & Extension::siginfo_read))
422804eeddc0SDimitry Andric     ret.push_back("qXfer:siginfo:read+");
4229fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::memory_tagging))
4230fe6060f1SDimitry Andric     ret.push_back("memory-tagging+");
4231349cc55cSDimitry Andric   if (bool(plugin_features & Extension::savecore))
4232349cc55cSDimitry Andric     ret.push_back("qSaveCore+");
4233fe6060f1SDimitry Andric 
4234fe6060f1SDimitry Andric   // check for client features
4235fe6060f1SDimitry Andric   m_extensions_supported = {};
4236fe6060f1SDimitry Andric   for (llvm::StringRef x : client_features)
4237fe6060f1SDimitry Andric     m_extensions_supported |=
4238fe6060f1SDimitry Andric         llvm::StringSwitch<Extension>(x)
4239fe6060f1SDimitry Andric             .Case("multiprocess+", Extension::multiprocess)
4240fe6060f1SDimitry Andric             .Case("fork-events+", Extension::fork)
4241fe6060f1SDimitry Andric             .Case("vfork-events+", Extension::vfork)
4242fe6060f1SDimitry Andric             .Default({});
4243fe6060f1SDimitry Andric 
4244fe6060f1SDimitry Andric   m_extensions_supported &= plugin_features;
4245fe6060f1SDimitry Andric 
4246fe6060f1SDimitry Andric   // fork & vfork require multiprocess
4247fe6060f1SDimitry Andric   if (!bool(m_extensions_supported & Extension::multiprocess))
4248fe6060f1SDimitry Andric     m_extensions_supported &= ~(Extension::fork | Extension::vfork);
4249fe6060f1SDimitry Andric 
4250fe6060f1SDimitry Andric   // report only if actually supported
4251fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::multiprocess))
4252fe6060f1SDimitry Andric     ret.push_back("multiprocess+");
4253fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::fork))
4254fe6060f1SDimitry Andric     ret.push_back("fork-events+");
4255fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::vfork))
4256fe6060f1SDimitry Andric     ret.push_back("vfork-events+");
4257fe6060f1SDimitry Andric 
4258fe6060f1SDimitry Andric   for (auto &x : m_debugged_processes)
4259fcaf7f86SDimitry Andric     SetEnabledExtensions(*x.second.process_up);
4260fe6060f1SDimitry Andric   return ret;
4261fe6060f1SDimitry Andric }
4262fe6060f1SDimitry Andric 
SetEnabledExtensions(NativeProcessProtocol & process)4263fe6060f1SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
4264fe6060f1SDimitry Andric     NativeProcessProtocol &process) {
4265fe6060f1SDimitry Andric   NativeProcessProtocol::Extension flags = m_extensions_supported;
426606c3fb27SDimitry Andric   assert(!bool(flags & ~m_process_manager.GetSupportedExtensions()));
4267fe6060f1SDimitry Andric   process.SetEnabledExtensions(flags);
4268fe6060f1SDimitry Andric }
4269349cc55cSDimitry Andric 
427081ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
SendContinueSuccessResponse()427181ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() {
4272fcaf7f86SDimitry Andric   if (m_non_stop)
4273fcaf7f86SDimitry Andric     return SendOKResponse();
427481ad6265SDimitry Andric   StartSTDIOForwarding();
4275fcaf7f86SDimitry Andric   return PacketResult::Success;
427681ad6265SDimitry Andric }
427781ad6265SDimitry Andric 
AppendThreadIDToResponse(Stream & response,lldb::pid_t pid,lldb::tid_t tid)427881ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse(
427981ad6265SDimitry Andric     Stream &response, lldb::pid_t pid, lldb::tid_t tid) {
428081ad6265SDimitry Andric   if (bool(m_extensions_supported &
428181ad6265SDimitry Andric            NativeProcessProtocol::Extension::multiprocess))
428281ad6265SDimitry Andric     response.Format("p{0:x-}.", pid);
428381ad6265SDimitry Andric   response.Format("{0:x-}", tid);
428481ad6265SDimitry Andric }
428581ad6265SDimitry Andric 
4286349cc55cSDimitry Andric std::string
LLGSArgToURL(llvm::StringRef url_arg,bool reverse_connect)4287349cc55cSDimitry Andric lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg,
4288349cc55cSDimitry Andric                                                bool reverse_connect) {
4289349cc55cSDimitry Andric   // Try parsing the argument as URL.
4290bdd1243dSDimitry Andric   if (std::optional<URI> url = URI::Parse(url_arg)) {
4291349cc55cSDimitry Andric     if (reverse_connect)
4292349cc55cSDimitry Andric       return url_arg.str();
4293349cc55cSDimitry Andric 
4294349cc55cSDimitry Andric     // Translate the scheme from LLGS notation to ConnectionFileDescriptor.
4295349cc55cSDimitry Andric     // If the scheme doesn't match any, pass it through to support using CFD
4296349cc55cSDimitry Andric     // schemes directly.
4297349cc55cSDimitry Andric     std::string new_url = llvm::StringSwitch<std::string>(url->scheme)
4298349cc55cSDimitry Andric                               .Case("tcp", "listen")
4299349cc55cSDimitry Andric                               .Case("unix", "unix-accept")
4300349cc55cSDimitry Andric                               .Case("unix-abstract", "unix-abstract-accept")
4301349cc55cSDimitry Andric                               .Default(url->scheme.str());
4302349cc55cSDimitry Andric     llvm::append_range(new_url, url_arg.substr(url->scheme.size()));
4303349cc55cSDimitry Andric     return new_url;
4304349cc55cSDimitry Andric   }
4305349cc55cSDimitry Andric 
4306349cc55cSDimitry Andric   std::string host_port = url_arg.str();
4307349cc55cSDimitry Andric   // If host_and_port starts with ':', default the host to be "localhost" and
4308349cc55cSDimitry Andric   // expect the remainder to be the port.
43095f757f3fSDimitry Andric   if (url_arg.starts_with(":"))
4310349cc55cSDimitry Andric     host_port.insert(0, "localhost");
4311349cc55cSDimitry Andric 
4312349cc55cSDimitry Andric   // Try parsing the (preprocessed) argument as host:port pair.
4313349cc55cSDimitry Andric   if (!llvm::errorToBool(Socket::DecodeHostAndPort(host_port).takeError()))
4314349cc55cSDimitry Andric     return (reverse_connect ? "connect://" : "listen://") + host_port;
4315349cc55cSDimitry Andric 
4316349cc55cSDimitry Andric   // If none of the above applied, interpret the argument as UNIX socket path.
4317349cc55cSDimitry Andric   return (reverse_connect ? "unix-connect://" : "unix-accept://") +
4318349cc55cSDimitry Andric          url_arg.str();
4319349cc55cSDimitry Andric }
4320