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 
140b57cec5SDimitry Andric #include <chrono>
150b57cec5SDimitry Andric #include <cstring>
16fe6060f1SDimitry Andric #include <limits>
170b57cec5SDimitry Andric #include <thread>
180b57cec5SDimitry Andric 
19e8d8bef9SDimitry Andric #include "GDBRemoteCommunicationServerLLGS.h"
200b57cec5SDimitry Andric #include "lldb/Host/ConnectionFileDescriptor.h"
210b57cec5SDimitry Andric #include "lldb/Host/Debug.h"
220b57cec5SDimitry Andric #include "lldb/Host/File.h"
230b57cec5SDimitry Andric #include "lldb/Host/FileAction.h"
240b57cec5SDimitry Andric #include "lldb/Host/FileSystem.h"
250b57cec5SDimitry Andric #include "lldb/Host/Host.h"
260b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h"
270b57cec5SDimitry Andric #include "lldb/Host/PosixApi.h"
28349cc55cSDimitry Andric #include "lldb/Host/Socket.h"
290b57cec5SDimitry Andric #include "lldb/Host/common/NativeProcessProtocol.h"
300b57cec5SDimitry Andric #include "lldb/Host/common/NativeRegisterContext.h"
310b57cec5SDimitry Andric #include "lldb/Host/common/NativeThreadProtocol.h"
320b57cec5SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h"
330b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
340b57cec5SDimitry Andric #include "lldb/Utility/DataBuffer.h"
350b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
36e8d8bef9SDimitry Andric #include "lldb/Utility/GDBRemote.h"
370b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
3881ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
390b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
400b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
410b57cec5SDimitry Andric #include "lldb/Utility/State.h"
420b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
43e8d8bef9SDimitry Andric #include "lldb/Utility/UnimplementedError.h"
440b57cec5SDimitry Andric #include "lldb/Utility/UriParser.h"
450b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
469dba64beSDimitry Andric #include "llvm/Support/JSON.h"
470b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric #include "ProcessGDBRemote.h"
500b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h"
510b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric using namespace lldb;
540b57cec5SDimitry Andric using namespace lldb_private;
550b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote;
560b57cec5SDimitry Andric using namespace llvm;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric // GDBRemote Errors
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric namespace {
610b57cec5SDimitry Andric enum GDBRemoteServerError {
620b57cec5SDimitry Andric   // Set to the first unused error number in literal form below
630b57cec5SDimitry Andric   eErrorFirst = 29,
640b57cec5SDimitry Andric   eErrorNoProcess = eErrorFirst,
650b57cec5SDimitry Andric   eErrorResume,
660b57cec5SDimitry Andric   eErrorExitStatus
670b57cec5SDimitry Andric };
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric // GDBRemoteCommunicationServerLLGS constructor
710b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
720b57cec5SDimitry Andric     MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory)
730b57cec5SDimitry Andric     : GDBRemoteCommunicationServerCommon("gdb-remote.server",
740b57cec5SDimitry Andric                                          "gdb-remote.server.rx_packet"),
750b57cec5SDimitry Andric       m_mainloop(mainloop), m_process_factory(process_factory),
76fe6060f1SDimitry Andric       m_current_process(nullptr), m_continue_process(nullptr),
770b57cec5SDimitry Andric       m_stdio_communication("process.stdio") {
780b57cec5SDimitry Andric   RegisterPacketHandlers();
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
820b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C,
830b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_C);
840b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c,
850b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_c);
860b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D,
870b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_D);
880b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H,
890b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_H);
900b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I,
910b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_I);
920b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
930b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_interrupt,
940b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_interrupt);
950b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
960b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_m,
970b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
980b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,
990b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_M);
100e8d8bef9SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType__M,
101e8d8bef9SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle__M);
102e8d8bef9SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType__m,
103e8d8bef9SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle__m);
1040b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p,
1050b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_p);
1060b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P,
1070b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_P);
1080b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
1090b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_qC);
11081ad6265SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_T,
11181ad6265SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_T);
1120b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1130b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qfThreadInfo,
1140b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo);
1150b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1160b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress,
1170b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress);
1180b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1190b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
1200b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir);
1210b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
122fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
123fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported);
124fe6060f1SDimitry Andric   RegisterMemberFunctionHandler(
125fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
126fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply);
127fe6060f1SDimitry Andric   RegisterMemberFunctionHandler(
1280b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo,
1290b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo);
1300b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1310b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported,
1320b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported);
1330b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1340b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
1350b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo);
1360b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1370b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qRegisterInfo,
1380b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo);
1390b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1400b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState,
1410b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState);
1420b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1430b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState,
1440b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState);
1450b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1460b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR,
1470b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR);
1480b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1490b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
1500b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir);
1510b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1520b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qsThreadInfo,
1530b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);
1540b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1550b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,
1560b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo);
1570b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1580b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jThreadsInfo,
1590b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);
1600b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1610b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,
1620b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);
1630b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1640b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qXfer,
1650b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qXfer);
1660b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s,
1670b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_s);
1680b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1690b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_stop_reason,
1700b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ?
1710b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1720b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vAttach,
1730b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vAttach);
1740b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
175e8d8bef9SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vAttachWait,
176e8d8bef9SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vAttachWait);
177e8d8bef9SDimitry Andric   RegisterMemberFunctionHandler(
178e8d8bef9SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qVAttachOrWaitSupported,
179e8d8bef9SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported);
180e8d8bef9SDimitry Andric   RegisterMemberFunctionHandler(
181e8d8bef9SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vAttachOrWait,
182e8d8bef9SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait);
183e8d8bef9SDimitry Andric   RegisterMemberFunctionHandler(
1840b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vCont,
1850b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vCont);
1860b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1870b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vCont_actions,
1880b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions);
1890b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
190349cc55cSDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vRun,
191349cc55cSDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vRun);
192349cc55cSDimitry Andric   RegisterMemberFunctionHandler(
1930b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_x,
1940b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
1950b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,
1960b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_Z);
1970b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
1980b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_z);
1990b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
2000b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QPassSignals,
2010b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
204fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupported,
205fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported);
2060b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
207fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStart,
208fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart);
2090b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
210fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStop,
211fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop);
2120b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
213fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetState,
214fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState);
2150b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
216fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetBinaryData,
217fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData);
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
2200b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_g);
2210b57cec5SDimitry Andric 
222fe6060f1SDimitry Andric   RegisterMemberFunctionHandler(
223fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qMemTags,
224fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qMemTags);
225fe6060f1SDimitry Andric 
226fe6060f1SDimitry Andric   RegisterMemberFunctionHandler(
227fe6060f1SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QMemTags,
228fe6060f1SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QMemTags);
229fe6060f1SDimitry Andric 
2300b57cec5SDimitry Andric   RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
2310b57cec5SDimitry Andric                         [this](StringExtractorGDBRemote packet, Status &error,
2320b57cec5SDimitry Andric                                bool &interrupt, bool &quit) {
2330b57cec5SDimitry Andric                           quit = true;
2340b57cec5SDimitry Andric                           return this->Handle_k(packet);
2350b57cec5SDimitry Andric                         });
236349cc55cSDimitry Andric 
237349cc55cSDimitry Andric   RegisterMemberFunctionHandler(
23881ad6265SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vKill,
23981ad6265SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vKill);
24081ad6265SDimitry Andric 
24181ad6265SDimitry Andric   RegisterMemberFunctionHandler(
242349cc55cSDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qLLDBSaveCore,
243349cc55cSDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qSaveCore);
24481ad6265SDimitry Andric 
24581ad6265SDimitry Andric   RegisterMemberFunctionHandler(
24681ad6265SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QNonStop,
24781ad6265SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QNonStop);
24881ad6265SDimitry Andric   RegisterMemberFunctionHandler(
249fcaf7f86SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vStdio,
250fcaf7f86SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vStdio);
251fcaf7f86SDimitry Andric   RegisterMemberFunctionHandler(
25281ad6265SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vStopped,
25381ad6265SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vStopped);
25481ad6265SDimitry Andric   RegisterMemberFunctionHandler(
25581ad6265SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vCtrlC,
25681ad6265SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vCtrlC);
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) {
2600b57cec5SDimitry Andric   m_process_launch_info = info;
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
26481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   if (!m_process_launch_info.GetArguments().GetArgumentCount())
2670b57cec5SDimitry Andric     return Status("%s: no process command line specified to launch",
2680b57cec5SDimitry Andric                   __FUNCTION__);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   const bool should_forward_stdio =
2710b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
2720b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
2730b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr;
2740b57cec5SDimitry Andric   m_process_launch_info.SetLaunchInSeparateProcessGroup(true);
2750b57cec5SDimitry Andric   m_process_launch_info.GetFlags().Set(eLaunchFlagDebug);
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   if (should_forward_stdio) {
2789dba64beSDimitry Andric     // Temporarily relax the following for Windows until we can take advantage
2799dba64beSDimitry Andric     // of the recently added pty support. This doesn't really affect the use of
2809dba64beSDimitry Andric     // lldb-server on Windows.
2819dba64beSDimitry Andric #if !defined(_WIN32)
2820b57cec5SDimitry Andric     if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection())
2830b57cec5SDimitry Andric       return Status(std::move(Err));
2849dba64beSDimitry Andric #endif
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   {
2880b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
289fe6060f1SDimitry Andric     assert(m_debugged_processes.empty() && "lldb-server creating debugged "
2900b57cec5SDimitry Andric                                            "process but one already exists");
2910b57cec5SDimitry Andric     auto process_or =
2920b57cec5SDimitry Andric         m_process_factory.Launch(m_process_launch_info, *this, m_mainloop);
2930b57cec5SDimitry Andric     if (!process_or)
2940b57cec5SDimitry Andric       return Status(process_or.takeError());
295fe6060f1SDimitry Andric     m_continue_process = m_current_process = process_or->get();
296fcaf7f86SDimitry Andric     m_debugged_processes.emplace(
297fcaf7f86SDimitry Andric         m_current_process->GetID(),
298fcaf7f86SDimitry Andric         DebuggedProcess{std::move(*process_or), DebuggedProcess::Flag{}});
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric 
301fe6060f1SDimitry Andric   SetEnabledExtensions(*m_current_process);
302fe6060f1SDimitry Andric 
3030b57cec5SDimitry Andric   // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
3040b57cec5SDimitry Andric   // needed. llgs local-process debugging may specify PTY paths, which will
3050b57cec5SDimitry Andric   // make these file actions non-null process launch -i/e/o will also make
3060b57cec5SDimitry Andric   // these file actions non-null nullptr means that the traffic is expected to
3070b57cec5SDimitry Andric   // flow over gdb-remote protocol
3080b57cec5SDimitry Andric   if (should_forward_stdio) {
3090b57cec5SDimitry Andric     // nullptr means it's not redirected to file or pty (in case of LLGS local)
3100b57cec5SDimitry Andric     // at least one of stdio will be transferred pty<->gdb-remote we need to
311349cc55cSDimitry Andric     // give the pty primary handle to this object to read and/or write
3120b57cec5SDimitry Andric     LLDB_LOG(log,
3130b57cec5SDimitry Andric              "pid = {0}: setting up stdout/stderr redirection via $O "
3140b57cec5SDimitry Andric              "gdb-remote commands",
315fe6060f1SDimitry Andric              m_current_process->GetID());
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric     // Setup stdout/stderr mapping from inferior to $O
318fe6060f1SDimitry Andric     auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
3190b57cec5SDimitry Andric     if (terminal_fd >= 0) {
3209dba64beSDimitry Andric       LLDB_LOGF(log,
3219dba64beSDimitry Andric                 "ProcessGDBRemoteCommunicationServerLLGS::%s setting "
3220b57cec5SDimitry Andric                 "inferior STDIO fd to %d",
3230b57cec5SDimitry Andric                 __FUNCTION__, terminal_fd);
3240b57cec5SDimitry Andric       Status status = SetSTDIOFileDescriptor(terminal_fd);
3250b57cec5SDimitry Andric       if (status.Fail())
3260b57cec5SDimitry Andric         return status;
3270b57cec5SDimitry Andric     } else {
3289dba64beSDimitry Andric       LLDB_LOGF(log,
3299dba64beSDimitry Andric                 "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
3300b57cec5SDimitry Andric                 "inferior STDIO since terminal fd reported as %d",
3310b57cec5SDimitry Andric                 __FUNCTION__, terminal_fd);
3320b57cec5SDimitry Andric     }
3330b57cec5SDimitry Andric   } else {
3340b57cec5SDimitry Andric     LLDB_LOG(log,
3350b57cec5SDimitry Andric              "pid = {0} skipping stdout/stderr redirection via $O: inferior "
3360b57cec5SDimitry Andric              "will communicate over client-provided file descriptors",
337fe6060f1SDimitry Andric              m_current_process->GetID());
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   printf("Launched '%s' as process %" PRIu64 "...\n",
3410b57cec5SDimitry Andric          m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
342fe6060f1SDimitry Andric          m_current_process->GetID());
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   return Status();
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
34881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3499dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64,
3500b57cec5SDimitry Andric             __FUNCTION__, pid);
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   // Before we try to attach, make sure we aren't already monitoring something
3530b57cec5SDimitry Andric   // else.
354fe6060f1SDimitry Andric   if (!m_debugged_processes.empty())
3550b57cec5SDimitry Andric     return Status("cannot attach to process %" PRIu64
3560b57cec5SDimitry Andric                   " when another process with pid %" PRIu64
3570b57cec5SDimitry Andric                   " is being debugged.",
358fe6060f1SDimitry Andric                   pid, m_current_process->GetID());
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   // Try to attach.
3610b57cec5SDimitry Andric   auto process_or = m_process_factory.Attach(pid, *this, m_mainloop);
3620b57cec5SDimitry Andric   if (!process_or) {
3630b57cec5SDimitry Andric     Status status(process_or.takeError());
364349cc55cSDimitry Andric     llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}\n", pid,
3650b57cec5SDimitry Andric                                   status);
3660b57cec5SDimitry Andric     return status;
3670b57cec5SDimitry Andric   }
368fe6060f1SDimitry Andric   m_continue_process = m_current_process = process_or->get();
369fcaf7f86SDimitry Andric   m_debugged_processes.emplace(
370fcaf7f86SDimitry Andric       m_current_process->GetID(),
371fcaf7f86SDimitry Andric       DebuggedProcess{std::move(*process_or), DebuggedProcess::Flag{}});
372fe6060f1SDimitry Andric   SetEnabledExtensions(*m_current_process);
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   // Setup stdout/stderr mapping from inferior.
375fe6060f1SDimitry Andric   auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
3760b57cec5SDimitry Andric   if (terminal_fd >= 0) {
3779dba64beSDimitry Andric     LLDB_LOGF(log,
3789dba64beSDimitry Andric               "ProcessGDBRemoteCommunicationServerLLGS::%s setting "
3790b57cec5SDimitry Andric               "inferior STDIO fd to %d",
3800b57cec5SDimitry Andric               __FUNCTION__, terminal_fd);
3810b57cec5SDimitry Andric     Status status = SetSTDIOFileDescriptor(terminal_fd);
3820b57cec5SDimitry Andric     if (status.Fail())
3830b57cec5SDimitry Andric       return status;
3840b57cec5SDimitry Andric   } else {
3859dba64beSDimitry Andric     LLDB_LOGF(log,
3869dba64beSDimitry Andric               "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
3870b57cec5SDimitry Andric               "inferior STDIO since terminal fd reported as %d",
3880b57cec5SDimitry Andric               __FUNCTION__, terminal_fd);
3890b57cec5SDimitry Andric   }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   printf("Attached to process %" PRIu64 "...\n", pid);
3920b57cec5SDimitry Andric   return Status();
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
395e8d8bef9SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess(
396e8d8bef9SDimitry Andric     llvm::StringRef process_name, bool include_existing) {
39781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
398e8d8bef9SDimitry Andric 
399e8d8bef9SDimitry Andric   std::chrono::milliseconds polling_interval = std::chrono::milliseconds(1);
400e8d8bef9SDimitry Andric 
401e8d8bef9SDimitry Andric   // Create the matcher used to search the process list.
402e8d8bef9SDimitry Andric   ProcessInstanceInfoList exclusion_list;
403e8d8bef9SDimitry Andric   ProcessInstanceInfoMatch match_info;
404e8d8bef9SDimitry Andric   match_info.GetProcessInfo().GetExecutableFile().SetFile(
405e8d8bef9SDimitry Andric       process_name, llvm::sys::path::Style::native);
406e8d8bef9SDimitry Andric   match_info.SetNameMatchType(NameMatch::Equals);
407e8d8bef9SDimitry Andric 
408e8d8bef9SDimitry Andric   if (include_existing) {
409e8d8bef9SDimitry Andric     LLDB_LOG(log, "including existing processes in search");
410e8d8bef9SDimitry Andric   } else {
411e8d8bef9SDimitry Andric     // Create the excluded process list before polling begins.
412e8d8bef9SDimitry Andric     Host::FindProcesses(match_info, exclusion_list);
413e8d8bef9SDimitry Andric     LLDB_LOG(log, "placed '{0}' processes in the exclusion list.",
414e8d8bef9SDimitry Andric              exclusion_list.size());
415e8d8bef9SDimitry Andric   }
416e8d8bef9SDimitry Andric 
417e8d8bef9SDimitry Andric   LLDB_LOG(log, "waiting for '{0}' to appear", process_name);
418e8d8bef9SDimitry Andric 
419e8d8bef9SDimitry Andric   auto is_in_exclusion_list =
420e8d8bef9SDimitry Andric       [&exclusion_list](const ProcessInstanceInfo &info) {
421e8d8bef9SDimitry Andric         for (auto &excluded : exclusion_list) {
422e8d8bef9SDimitry Andric           if (excluded.GetProcessID() == info.GetProcessID())
423e8d8bef9SDimitry Andric             return true;
424e8d8bef9SDimitry Andric         }
425e8d8bef9SDimitry Andric         return false;
426e8d8bef9SDimitry Andric       };
427e8d8bef9SDimitry Andric 
428e8d8bef9SDimitry Andric   ProcessInstanceInfoList loop_process_list;
429e8d8bef9SDimitry Andric   while (true) {
430e8d8bef9SDimitry Andric     loop_process_list.clear();
431e8d8bef9SDimitry Andric     if (Host::FindProcesses(match_info, loop_process_list)) {
432e8d8bef9SDimitry Andric       // Remove all the elements that are in the exclusion list.
433e8d8bef9SDimitry Andric       llvm::erase_if(loop_process_list, is_in_exclusion_list);
434e8d8bef9SDimitry Andric 
435e8d8bef9SDimitry Andric       // One match! We found the desired process.
436e8d8bef9SDimitry Andric       if (loop_process_list.size() == 1) {
437e8d8bef9SDimitry Andric         auto matching_process_pid = loop_process_list[0].GetProcessID();
438e8d8bef9SDimitry Andric         LLDB_LOG(log, "found pid {0}", matching_process_pid);
439e8d8bef9SDimitry Andric         return AttachToProcess(matching_process_pid);
440e8d8bef9SDimitry Andric       }
441e8d8bef9SDimitry Andric 
442e8d8bef9SDimitry Andric       // Multiple matches! Return an error reporting the PIDs we found.
443e8d8bef9SDimitry Andric       if (loop_process_list.size() > 1) {
444e8d8bef9SDimitry Andric         StreamString error_stream;
445e8d8bef9SDimitry Andric         error_stream.Format(
446e8d8bef9SDimitry Andric             "Multiple executables with name: '{0}' found. Pids: ",
447e8d8bef9SDimitry Andric             process_name);
448e8d8bef9SDimitry Andric         for (size_t i = 0; i < loop_process_list.size() - 1; ++i) {
449e8d8bef9SDimitry Andric           error_stream.Format("{0}, ", loop_process_list[i].GetProcessID());
450e8d8bef9SDimitry Andric         }
451e8d8bef9SDimitry Andric         error_stream.Format("{0}.", loop_process_list.back().GetProcessID());
452e8d8bef9SDimitry Andric 
453e8d8bef9SDimitry Andric         Status error;
454e8d8bef9SDimitry Andric         error.SetErrorString(error_stream.GetString());
455e8d8bef9SDimitry Andric         return error;
456e8d8bef9SDimitry Andric       }
457e8d8bef9SDimitry Andric     }
458e8d8bef9SDimitry Andric     // No matches, we have not found the process. Sleep until next poll.
459e8d8bef9SDimitry Andric     LLDB_LOG(log, "sleep {0} seconds", polling_interval);
460e8d8bef9SDimitry Andric     std::this_thread::sleep_for(polling_interval);
461e8d8bef9SDimitry Andric   }
462e8d8bef9SDimitry Andric }
463e8d8bef9SDimitry Andric 
4640b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::InitializeDelegate(
4650b57cec5SDimitry Andric     NativeProcessProtocol *process) {
4660b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
46781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
4680b57cec5SDimitry Andric   if (log) {
4699dba64beSDimitry Andric     LLDB_LOGF(log,
4709dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s called with "
4710b57cec5SDimitry Andric               "NativeProcessProtocol pid %" PRIu64 ", current state: %s",
4720b57cec5SDimitry Andric               __FUNCTION__, process->GetID(),
4730b57cec5SDimitry Andric               StateAsCString(process->GetState()));
4740b57cec5SDimitry Andric   }
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4780b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendWResponse(
4790b57cec5SDimitry Andric     NativeProcessProtocol *process) {
4800b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
48181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   // send W notification
4840b57cec5SDimitry Andric   auto wait_status = process->GetExitStatus();
4850b57cec5SDimitry Andric   if (!wait_status) {
4860b57cec5SDimitry Andric     LLDB_LOG(log, "pid = {0}, failed to retrieve process exit status",
4870b57cec5SDimitry Andric              process->GetID());
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric     StreamGDBRemote response;
4900b57cec5SDimitry Andric     response.PutChar('E');
4910b57cec5SDimitry Andric     response.PutHex8(GDBRemoteServerError::eErrorExitStatus);
4920b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
4930b57cec5SDimitry Andric   }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric   LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(),
4960b57cec5SDimitry Andric            *wait_status);
4970b57cec5SDimitry Andric 
49881ad6265SDimitry Andric   // If the process was killed through vKill, return "OK".
499fcaf7f86SDimitry Andric   if (bool(m_debugged_processes.at(process->GetID()).flags &
500fcaf7f86SDimitry Andric            DebuggedProcess::Flag::vkilled))
50181ad6265SDimitry Andric     return SendOKResponse();
50281ad6265SDimitry Andric 
5030b57cec5SDimitry Andric   StreamGDBRemote response;
5040b57cec5SDimitry Andric   response.Format("{0:g}", *wait_status);
505fcaf7f86SDimitry Andric   if (bool(m_extensions_supported &
506fcaf7f86SDimitry Andric            NativeProcessProtocol::Extension::multiprocess))
50781ad6265SDimitry Andric     response.Format(";process:{0:x-}", process->GetID());
50881ad6265SDimitry Andric   if (m_non_stop)
50981ad6265SDimitry Andric     return SendNotificationPacketNoLock("Stop", m_stop_notification_queue,
51081ad6265SDimitry Andric                                         response.GetString());
5110b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
5120b57cec5SDimitry Andric }
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric static void AppendHexValue(StreamString &response, const uint8_t *buf,
5150b57cec5SDimitry Andric                            uint32_t buf_size, bool swap) {
5160b57cec5SDimitry Andric   int64_t i;
5170b57cec5SDimitry Andric   if (swap) {
5180b57cec5SDimitry Andric     for (i = buf_size - 1; i >= 0; i--)
5190b57cec5SDimitry Andric       response.PutHex8(buf[i]);
5200b57cec5SDimitry Andric   } else {
5210b57cec5SDimitry Andric     for (i = 0; i < buf_size; i++)
5220b57cec5SDimitry Andric       response.PutHex8(buf[i]);
5230b57cec5SDimitry Andric   }
5240b57cec5SDimitry Andric }
5250b57cec5SDimitry Andric 
5265ffd83dbSDimitry Andric static llvm::StringRef GetEncodingNameOrEmpty(const RegisterInfo &reg_info) {
5275ffd83dbSDimitry Andric   switch (reg_info.encoding) {
5285ffd83dbSDimitry Andric   case eEncodingUint:
5295ffd83dbSDimitry Andric     return "uint";
5305ffd83dbSDimitry Andric   case eEncodingSint:
5315ffd83dbSDimitry Andric     return "sint";
5325ffd83dbSDimitry Andric   case eEncodingIEEE754:
5335ffd83dbSDimitry Andric     return "ieee754";
5345ffd83dbSDimitry Andric   case eEncodingVector:
5355ffd83dbSDimitry Andric     return "vector";
5365ffd83dbSDimitry Andric   default:
5375ffd83dbSDimitry Andric     return "";
5385ffd83dbSDimitry Andric   }
5395ffd83dbSDimitry Andric }
5405ffd83dbSDimitry Andric 
5415ffd83dbSDimitry Andric static llvm::StringRef GetFormatNameOrEmpty(const RegisterInfo &reg_info) {
5425ffd83dbSDimitry Andric   switch (reg_info.format) {
5435ffd83dbSDimitry Andric   case eFormatBinary:
5445ffd83dbSDimitry Andric     return "binary";
5455ffd83dbSDimitry Andric   case eFormatDecimal:
5465ffd83dbSDimitry Andric     return "decimal";
5475ffd83dbSDimitry Andric   case eFormatHex:
5485ffd83dbSDimitry Andric     return "hex";
5495ffd83dbSDimitry Andric   case eFormatFloat:
5505ffd83dbSDimitry Andric     return "float";
5515ffd83dbSDimitry Andric   case eFormatVectorOfSInt8:
5525ffd83dbSDimitry Andric     return "vector-sint8";
5535ffd83dbSDimitry Andric   case eFormatVectorOfUInt8:
5545ffd83dbSDimitry Andric     return "vector-uint8";
5555ffd83dbSDimitry Andric   case eFormatVectorOfSInt16:
5565ffd83dbSDimitry Andric     return "vector-sint16";
5575ffd83dbSDimitry Andric   case eFormatVectorOfUInt16:
5585ffd83dbSDimitry Andric     return "vector-uint16";
5595ffd83dbSDimitry Andric   case eFormatVectorOfSInt32:
5605ffd83dbSDimitry Andric     return "vector-sint32";
5615ffd83dbSDimitry Andric   case eFormatVectorOfUInt32:
5625ffd83dbSDimitry Andric     return "vector-uint32";
5635ffd83dbSDimitry Andric   case eFormatVectorOfFloat32:
5645ffd83dbSDimitry Andric     return "vector-float32";
5655ffd83dbSDimitry Andric   case eFormatVectorOfUInt64:
5665ffd83dbSDimitry Andric     return "vector-uint64";
5675ffd83dbSDimitry Andric   case eFormatVectorOfUInt128:
5685ffd83dbSDimitry Andric     return "vector-uint128";
5695ffd83dbSDimitry Andric   default:
5705ffd83dbSDimitry Andric     return "";
5715ffd83dbSDimitry Andric   };
5725ffd83dbSDimitry Andric }
5735ffd83dbSDimitry Andric 
5745ffd83dbSDimitry Andric static llvm::StringRef GetKindGenericOrEmpty(const RegisterInfo &reg_info) {
5755ffd83dbSDimitry Andric   switch (reg_info.kinds[RegisterKind::eRegisterKindGeneric]) {
5765ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_PC:
5775ffd83dbSDimitry Andric     return "pc";
5785ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_SP:
5795ffd83dbSDimitry Andric     return "sp";
5805ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_FP:
5815ffd83dbSDimitry Andric     return "fp";
5825ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_RA:
5835ffd83dbSDimitry Andric     return "ra";
5845ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_FLAGS:
5855ffd83dbSDimitry Andric     return "flags";
5865ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG1:
5875ffd83dbSDimitry Andric     return "arg1";
5885ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG2:
5895ffd83dbSDimitry Andric     return "arg2";
5905ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG3:
5915ffd83dbSDimitry Andric     return "arg3";
5925ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG4:
5935ffd83dbSDimitry Andric     return "arg4";
5945ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG5:
5955ffd83dbSDimitry Andric     return "arg5";
5965ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG6:
5975ffd83dbSDimitry Andric     return "arg6";
5985ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG7:
5995ffd83dbSDimitry Andric     return "arg7";
6005ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG8:
6015ffd83dbSDimitry Andric     return "arg8";
6025ffd83dbSDimitry Andric   default:
6035ffd83dbSDimitry Andric     return "";
6045ffd83dbSDimitry Andric   }
6055ffd83dbSDimitry Andric }
6065ffd83dbSDimitry Andric 
6075ffd83dbSDimitry Andric static void CollectRegNums(const uint32_t *reg_num, StreamString &response,
6085ffd83dbSDimitry Andric                            bool usehex) {
6095ffd83dbSDimitry Andric   for (int i = 0; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) {
6105ffd83dbSDimitry Andric     if (i > 0)
6115ffd83dbSDimitry Andric       response.PutChar(',');
6125ffd83dbSDimitry Andric     if (usehex)
6135ffd83dbSDimitry Andric       response.Printf("%" PRIx32, *reg_num);
6145ffd83dbSDimitry Andric     else
6155ffd83dbSDimitry Andric       response.Printf("%" PRIu32, *reg_num);
6165ffd83dbSDimitry Andric   }
6175ffd83dbSDimitry Andric }
6185ffd83dbSDimitry Andric 
6190b57cec5SDimitry Andric static void WriteRegisterValueInHexFixedWidth(
6200b57cec5SDimitry Andric     StreamString &response, NativeRegisterContext &reg_ctx,
6210b57cec5SDimitry Andric     const RegisterInfo &reg_info, const RegisterValue *reg_value_p,
6220b57cec5SDimitry Andric     lldb::ByteOrder byte_order) {
6230b57cec5SDimitry Andric   RegisterValue reg_value;
6240b57cec5SDimitry Andric   if (!reg_value_p) {
6250b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(&reg_info, reg_value);
6260b57cec5SDimitry Andric     if (error.Success())
6270b57cec5SDimitry Andric       reg_value_p = &reg_value;
6280b57cec5SDimitry Andric     // else log.
6290b57cec5SDimitry Andric   }
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric   if (reg_value_p) {
6320b57cec5SDimitry Andric     AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(),
6330b57cec5SDimitry Andric                    reg_value_p->GetByteSize(),
6340b57cec5SDimitry Andric                    byte_order == lldb::eByteOrderLittle);
6350b57cec5SDimitry Andric   } else {
6360b57cec5SDimitry Andric     // Zero-out any unreadable values.
6370b57cec5SDimitry Andric     if (reg_info.byte_size > 0) {
6380b57cec5SDimitry Andric       std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0');
6390b57cec5SDimitry Andric       AppendHexValue(response, zeros.data(), zeros.size(), false);
6400b57cec5SDimitry Andric     }
6410b57cec5SDimitry Andric   }
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric 
644e8d8bef9SDimitry Andric static llvm::Optional<json::Object>
6459dba64beSDimitry Andric GetRegistersAsJSON(NativeThreadProtocol &thread) {
64681ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   NativeRegisterContext& reg_ctx = thread.GetRegisterContext();
6490b57cec5SDimitry Andric 
6509dba64beSDimitry Andric   json::Object register_object;
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
653e8d8bef9SDimitry Andric   const auto expedited_regs =
654e8d8bef9SDimitry Andric       reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Full);
6550b57cec5SDimitry Andric #else
656e8d8bef9SDimitry Andric   const auto expedited_regs =
657e8d8bef9SDimitry Andric       reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Minimal);
6580b57cec5SDimitry Andric #endif
659e8d8bef9SDimitry Andric   if (expedited_regs.empty())
660e8d8bef9SDimitry Andric     return llvm::None;
6610b57cec5SDimitry Andric 
662e8d8bef9SDimitry Andric   for (auto &reg_num : expedited_regs) {
6630b57cec5SDimitry Andric     const RegisterInfo *const reg_info_p =
6640b57cec5SDimitry Andric         reg_ctx.GetRegisterInfoAtIndex(reg_num);
6650b57cec5SDimitry Andric     if (reg_info_p == nullptr) {
6669dba64beSDimitry Andric       LLDB_LOGF(log,
6670b57cec5SDimitry Andric                 "%s failed to get register info for register index %" PRIu32,
6680b57cec5SDimitry Andric                 __FUNCTION__, reg_num);
6690b57cec5SDimitry Andric       continue;
6700b57cec5SDimitry Andric     }
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric     if (reg_info_p->value_regs != nullptr)
6730b57cec5SDimitry Andric       continue; // Only expedite registers that are not contained in other
6740b57cec5SDimitry Andric                 // registers.
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric     RegisterValue reg_value;
6770b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
6780b57cec5SDimitry Andric     if (error.Fail()) {
6799dba64beSDimitry Andric       LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s",
6800b57cec5SDimitry Andric                 __FUNCTION__,
6810b57cec5SDimitry Andric                 reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
6820b57cec5SDimitry Andric                 reg_num, error.AsCString());
6830b57cec5SDimitry Andric       continue;
6840b57cec5SDimitry Andric     }
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric     StreamString stream;
6870b57cec5SDimitry Andric     WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p,
6880b57cec5SDimitry Andric                                       &reg_value, lldb::eByteOrderBig);
6890b57cec5SDimitry Andric 
6909dba64beSDimitry Andric     register_object.try_emplace(llvm::to_string(reg_num),
6919dba64beSDimitry Andric                                 stream.GetString().str());
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric 
6949dba64beSDimitry Andric   return register_object;
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric static const char *GetStopReasonString(StopReason stop_reason) {
6980b57cec5SDimitry Andric   switch (stop_reason) {
6990b57cec5SDimitry Andric   case eStopReasonTrace:
7000b57cec5SDimitry Andric     return "trace";
7010b57cec5SDimitry Andric   case eStopReasonBreakpoint:
7020b57cec5SDimitry Andric     return "breakpoint";
7030b57cec5SDimitry Andric   case eStopReasonWatchpoint:
7040b57cec5SDimitry Andric     return "watchpoint";
7050b57cec5SDimitry Andric   case eStopReasonSignal:
7060b57cec5SDimitry Andric     return "signal";
7070b57cec5SDimitry Andric   case eStopReasonException:
7080b57cec5SDimitry Andric     return "exception";
7090b57cec5SDimitry Andric   case eStopReasonExec:
7100b57cec5SDimitry Andric     return "exec";
711fe6060f1SDimitry Andric   case eStopReasonProcessorTrace:
712fe6060f1SDimitry Andric     return "processor trace";
713fe6060f1SDimitry Andric   case eStopReasonFork:
714fe6060f1SDimitry Andric     return "fork";
715fe6060f1SDimitry Andric   case eStopReasonVFork:
716fe6060f1SDimitry Andric     return "vfork";
717fe6060f1SDimitry Andric   case eStopReasonVForkDone:
718fe6060f1SDimitry Andric     return "vforkdone";
7190b57cec5SDimitry Andric   case eStopReasonInstrumentation:
7200b57cec5SDimitry Andric   case eStopReasonInvalid:
7210b57cec5SDimitry Andric   case eStopReasonPlanComplete:
7220b57cec5SDimitry Andric   case eStopReasonThreadExiting:
7230b57cec5SDimitry Andric   case eStopReasonNone:
7240b57cec5SDimitry Andric     break; // ignored
7250b57cec5SDimitry Andric   }
7260b57cec5SDimitry Andric   return nullptr;
7270b57cec5SDimitry Andric }
7280b57cec5SDimitry Andric 
7299dba64beSDimitry Andric static llvm::Expected<json::Array>
7309dba64beSDimitry Andric GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) {
73181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
7320b57cec5SDimitry Andric 
7339dba64beSDimitry Andric   json::Array threads_array;
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric   // Ensure we can get info on the given thread.
73681ad6265SDimitry Andric   for (NativeThreadProtocol &thread : process.Threads()) {
73781ad6265SDimitry Andric     lldb::tid_t tid = thread.GetID();
7380b57cec5SDimitry Andric     // Grab the reason this thread stopped.
7390b57cec5SDimitry Andric     struct ThreadStopInfo tid_stop_info;
7400b57cec5SDimitry Andric     std::string description;
74181ad6265SDimitry Andric     if (!thread.GetStopReason(tid_stop_info, description))
7429dba64beSDimitry Andric       return llvm::make_error<llvm::StringError>(
7439dba64beSDimitry Andric           "failed to get stop reason", llvm::inconvertibleErrorCode());
7440b57cec5SDimitry Andric 
74581ad6265SDimitry Andric     const int signum = tid_stop_info.signo;
7460b57cec5SDimitry Andric     if (log) {
7479dba64beSDimitry Andric       LLDB_LOGF(log,
7489dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
7490b57cec5SDimitry Andric                 " tid %" PRIu64
7500b57cec5SDimitry Andric                 " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
7510b57cec5SDimitry Andric                 __FUNCTION__, process.GetID(), tid, signum,
7520b57cec5SDimitry Andric                 tid_stop_info.reason, tid_stop_info.details.exception.type);
7530b57cec5SDimitry Andric     }
7540b57cec5SDimitry Andric 
7559dba64beSDimitry Andric     json::Object thread_obj;
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric     if (!abridged) {
75881ad6265SDimitry Andric       if (llvm::Optional<json::Object> registers = GetRegistersAsJSON(thread))
7599dba64beSDimitry Andric         thread_obj.try_emplace("registers", std::move(*registers));
7600b57cec5SDimitry Andric     }
7610b57cec5SDimitry Andric 
7629dba64beSDimitry Andric     thread_obj.try_emplace("tid", static_cast<int64_t>(tid));
7639dba64beSDimitry Andric 
7640b57cec5SDimitry Andric     if (signum != 0)
7659dba64beSDimitry Andric       thread_obj.try_emplace("signal", signum);
7660b57cec5SDimitry Andric 
76781ad6265SDimitry Andric     const std::string thread_name = thread.GetName();
7680b57cec5SDimitry Andric     if (!thread_name.empty())
7699dba64beSDimitry Andric       thread_obj.try_emplace("name", thread_name);
7700b57cec5SDimitry Andric 
7719dba64beSDimitry Andric     const char *stop_reason = GetStopReasonString(tid_stop_info.reason);
7729dba64beSDimitry Andric     if (stop_reason)
7739dba64beSDimitry Andric       thread_obj.try_emplace("reason", stop_reason);
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric     if (!description.empty())
7769dba64beSDimitry Andric       thread_obj.try_emplace("description", description);
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric     if ((tid_stop_info.reason == eStopReasonException) &&
7790b57cec5SDimitry Andric         tid_stop_info.details.exception.type) {
7809dba64beSDimitry Andric       thread_obj.try_emplace(
7819dba64beSDimitry Andric           "metype", static_cast<int64_t>(tid_stop_info.details.exception.type));
7820b57cec5SDimitry Andric 
7839dba64beSDimitry Andric       json::Array medata_array;
7840b57cec5SDimitry Andric       for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count;
7850b57cec5SDimitry Andric            ++i) {
7869dba64beSDimitry Andric         medata_array.push_back(
7879dba64beSDimitry Andric             static_cast<int64_t>(tid_stop_info.details.exception.data[i]));
7880b57cec5SDimitry Andric       }
7899dba64beSDimitry Andric       thread_obj.try_emplace("medata", std::move(medata_array));
7900b57cec5SDimitry Andric     }
7919dba64beSDimitry Andric     threads_array.push_back(std::move(thread_obj));
7920b57cec5SDimitry Andric   }
7939dba64beSDimitry Andric   return threads_array;
7940b57cec5SDimitry Andric }
7950b57cec5SDimitry Andric 
79681ad6265SDimitry Andric StreamString
79781ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::PrepareStopReplyPacketForThread(
79881ad6265SDimitry Andric     NativeThreadProtocol &thread) {
79981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
8000b57cec5SDimitry Andric 
80181ad6265SDimitry Andric   NativeProcessProtocol &process = thread.GetProcess();
8020b57cec5SDimitry Andric 
80381ad6265SDimitry Andric   LLDB_LOG(log, "preparing packet for pid {0} tid {1}", process.GetID(),
80481ad6265SDimitry Andric            thread.GetID());
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric   // Grab the reason this thread stopped.
80781ad6265SDimitry Andric   StreamString response;
8080b57cec5SDimitry Andric   struct ThreadStopInfo tid_stop_info;
8090b57cec5SDimitry Andric   std::string description;
81081ad6265SDimitry Andric   if (!thread.GetStopReason(tid_stop_info, description))
81181ad6265SDimitry Andric     return response;
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric   // FIXME implement register handling for exec'd inferiors.
8140b57cec5SDimitry Andric   // if (tid_stop_info.reason == eStopReasonExec) {
8150b57cec5SDimitry Andric   //     const bool force = true;
8160b57cec5SDimitry Andric   //     InitializeRegisters(force);
8170b57cec5SDimitry Andric   // }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   // Output the T packet with the thread
8200b57cec5SDimitry Andric   response.PutChar('T');
82181ad6265SDimitry Andric   int signum = tid_stop_info.signo;
8220b57cec5SDimitry Andric   LLDB_LOG(
8230b57cec5SDimitry Andric       log,
8240b57cec5SDimitry Andric       "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}",
82581ad6265SDimitry Andric       process.GetID(), thread.GetID(), signum, int(tid_stop_info.reason),
8260b57cec5SDimitry Andric       tid_stop_info.details.exception.type);
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric   // Print the signal number.
8290b57cec5SDimitry Andric   response.PutHex8(signum & 0xff);
8300b57cec5SDimitry Andric 
83181ad6265SDimitry Andric   // Include the (pid and) tid.
83281ad6265SDimitry Andric   response.PutCString("thread:");
83381ad6265SDimitry Andric   AppendThreadIDToResponse(response, process.GetID(), thread.GetID());
83481ad6265SDimitry Andric   response.PutChar(';');
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric   // Include the thread name if there is one.
83781ad6265SDimitry Andric   const std::string thread_name = thread.GetName();
8380b57cec5SDimitry Andric   if (!thread_name.empty()) {
8390b57cec5SDimitry Andric     size_t thread_name_len = thread_name.length();
8400b57cec5SDimitry Andric 
8410b57cec5SDimitry Andric     if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) {
8420b57cec5SDimitry Andric       response.PutCString("name:");
8430b57cec5SDimitry Andric       response.PutCString(thread_name);
8440b57cec5SDimitry Andric     } else {
8450b57cec5SDimitry Andric       // The thread name contains special chars, send as hex bytes.
8460b57cec5SDimitry Andric       response.PutCString("hexname:");
8470b57cec5SDimitry Andric       response.PutStringAsRawHex8(thread_name);
8480b57cec5SDimitry Andric     }
8490b57cec5SDimitry Andric     response.PutChar(';');
8500b57cec5SDimitry Andric   }
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric   // If a 'QListThreadsInStopReply' was sent to enable this feature, we will
8530b57cec5SDimitry Andric   // send all thread IDs back in the "threads" key whose value is a list of hex
8540b57cec5SDimitry Andric   // thread IDs separated by commas:
8550b57cec5SDimitry Andric   //  "threads:10a,10b,10c;"
8560b57cec5SDimitry Andric   // This will save the debugger from having to send a pair of qfThreadInfo and
8570b57cec5SDimitry Andric   // qsThreadInfo packets, but it also might take a lot of room in the stop
8580b57cec5SDimitry Andric   // reply packet, so it must be enabled only on systems where there are no
8590b57cec5SDimitry Andric   // limits on packet lengths.
8600b57cec5SDimitry Andric   if (m_list_threads_in_stop_reply) {
8610b57cec5SDimitry Andric     response.PutCString("threads:");
8620b57cec5SDimitry Andric 
86381ad6265SDimitry Andric     uint32_t thread_num = 0;
86481ad6265SDimitry Andric     for (NativeThreadProtocol &listed_thread : process.Threads()) {
86581ad6265SDimitry Andric       if (thread_num > 0)
8660b57cec5SDimitry Andric         response.PutChar(',');
86781ad6265SDimitry Andric       response.Printf("%" PRIx64, listed_thread.GetID());
86881ad6265SDimitry Andric       ++thread_num;
8690b57cec5SDimitry Andric     }
8700b57cec5SDimitry Andric     response.PutChar(';');
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric     // Include JSON info that describes the stop reason for any threads that
8730b57cec5SDimitry Andric     // actually have stop reasons. We use the new "jstopinfo" key whose values
8740b57cec5SDimitry Andric     // is hex ascii JSON that contains the thread IDs thread stop info only for
8750b57cec5SDimitry Andric     // threads that have stop reasons. Only send this if we have more than one
8760b57cec5SDimitry Andric     // thread otherwise this packet has all the info it needs.
87781ad6265SDimitry Andric     if (thread_num > 1) {
8780b57cec5SDimitry Andric       const bool threads_with_valid_stop_info_only = true;
8799dba64beSDimitry Andric       llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo(
880fe6060f1SDimitry Andric           *m_current_process, threads_with_valid_stop_info_only);
8819dba64beSDimitry Andric       if (threads_info) {
8820b57cec5SDimitry Andric         response.PutCString("jstopinfo:");
8830b57cec5SDimitry Andric         StreamString unescaped_response;
8849dba64beSDimitry Andric         unescaped_response.AsRawOstream() << std::move(*threads_info);
8850b57cec5SDimitry Andric         response.PutStringAsRawHex8(unescaped_response.GetData());
8860b57cec5SDimitry Andric         response.PutChar(';');
8879dba64beSDimitry Andric       } else {
888480093f4SDimitry Andric         LLDB_LOG_ERROR(log, threads_info.takeError(),
889480093f4SDimitry Andric                        "failed to prepare a jstopinfo field for pid {1}: {0}",
89081ad6265SDimitry Andric                        process.GetID());
8919dba64beSDimitry Andric       }
8920b57cec5SDimitry Andric     }
8930b57cec5SDimitry Andric 
8940b57cec5SDimitry Andric     response.PutCString("thread-pcs");
8950b57cec5SDimitry Andric     char delimiter = ':';
89681ad6265SDimitry Andric     for (NativeThreadProtocol &thread : process.Threads()) {
89781ad6265SDimitry Andric       NativeRegisterContext &reg_ctx = thread.GetRegisterContext();
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric       uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber(
9000b57cec5SDimitry Andric           eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
9010b57cec5SDimitry Andric       const RegisterInfo *const reg_info_p =
9020b57cec5SDimitry Andric           reg_ctx.GetRegisterInfoAtIndex(reg_to_read);
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric       RegisterValue reg_value;
9050b57cec5SDimitry Andric       Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
9060b57cec5SDimitry Andric       if (error.Fail()) {
9079dba64beSDimitry Andric         LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s",
9080b57cec5SDimitry Andric                   __FUNCTION__,
9099dba64beSDimitry Andric                   reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
9100b57cec5SDimitry Andric                   reg_to_read, error.AsCString());
9110b57cec5SDimitry Andric         continue;
9120b57cec5SDimitry Andric       }
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric       response.PutChar(delimiter);
9150b57cec5SDimitry Andric       delimiter = ',';
9160b57cec5SDimitry Andric       WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p,
9170b57cec5SDimitry Andric                                         &reg_value, endian::InlHostByteOrder());
9180b57cec5SDimitry Andric     }
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric     response.PutChar(';');
9210b57cec5SDimitry Andric   }
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric   //
9240b57cec5SDimitry Andric   // Expedite registers.
9250b57cec5SDimitry Andric   //
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   // Grab the register context.
92881ad6265SDimitry Andric   NativeRegisterContext &reg_ctx = thread.GetRegisterContext();
929e8d8bef9SDimitry Andric   const auto expedited_regs =
930e8d8bef9SDimitry Andric       reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Full);
9310b57cec5SDimitry Andric 
932e8d8bef9SDimitry Andric   for (auto &reg_num : expedited_regs) {
9330b57cec5SDimitry Andric     const RegisterInfo *const reg_info_p =
934e8d8bef9SDimitry Andric         reg_ctx.GetRegisterInfoAtIndex(reg_num);
9350b57cec5SDimitry Andric     // Only expediate registers that are not contained in other registers.
936e8d8bef9SDimitry Andric     if (reg_info_p != nullptr && reg_info_p->value_regs == nullptr) {
9370b57cec5SDimitry Andric       RegisterValue reg_value;
9380b57cec5SDimitry Andric       Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
9390b57cec5SDimitry Andric       if (error.Success()) {
940e8d8bef9SDimitry Andric         response.Printf("%.02x:", reg_num);
9410b57cec5SDimitry Andric         WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p,
9420b57cec5SDimitry Andric                                           &reg_value, lldb::eByteOrderBig);
9430b57cec5SDimitry Andric         response.PutChar(';');
9440b57cec5SDimitry Andric       } else {
94581ad6265SDimitry Andric         LLDB_LOGF(log,
94681ad6265SDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s failed to read "
9470b57cec5SDimitry Andric                   "register '%s' index %" PRIu32 ": %s",
9480b57cec5SDimitry Andric                   __FUNCTION__,
9499dba64beSDimitry Andric                   reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
950e8d8bef9SDimitry Andric                   reg_num, error.AsCString());
9510b57cec5SDimitry Andric       }
9520b57cec5SDimitry Andric     }
9530b57cec5SDimitry Andric   }
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric   const char *reason_str = GetStopReasonString(tid_stop_info.reason);
9560b57cec5SDimitry Andric   if (reason_str != nullptr) {
9570b57cec5SDimitry Andric     response.Printf("reason:%s;", reason_str);
9580b57cec5SDimitry Andric   }
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   if (!description.empty()) {
9610b57cec5SDimitry Andric     // Description may contains special chars, send as hex bytes.
9620b57cec5SDimitry Andric     response.PutCString("description:");
9630b57cec5SDimitry Andric     response.PutStringAsRawHex8(description);
9640b57cec5SDimitry Andric     response.PutChar(';');
9650b57cec5SDimitry Andric   } else if ((tid_stop_info.reason == eStopReasonException) &&
9660b57cec5SDimitry Andric              tid_stop_info.details.exception.type) {
9670b57cec5SDimitry Andric     response.PutCString("metype:");
9680b57cec5SDimitry Andric     response.PutHex64(tid_stop_info.details.exception.type);
9690b57cec5SDimitry Andric     response.PutCString(";mecount:");
9700b57cec5SDimitry Andric     response.PutHex32(tid_stop_info.details.exception.data_count);
9710b57cec5SDimitry Andric     response.PutChar(';');
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric     for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) {
9740b57cec5SDimitry Andric       response.PutCString("medata:");
9750b57cec5SDimitry Andric       response.PutHex64(tid_stop_info.details.exception.data[i]);
9760b57cec5SDimitry Andric       response.PutChar(';');
9770b57cec5SDimitry Andric     }
9780b57cec5SDimitry Andric   }
9790b57cec5SDimitry Andric 
980fe6060f1SDimitry Andric   // Include child process PID/TID for forks.
981fe6060f1SDimitry Andric   if (tid_stop_info.reason == eStopReasonFork ||
982fe6060f1SDimitry Andric       tid_stop_info.reason == eStopReasonVFork) {
983fe6060f1SDimitry Andric     assert(bool(m_extensions_supported &
984fe6060f1SDimitry Andric                 NativeProcessProtocol::Extension::multiprocess));
985fe6060f1SDimitry Andric     if (tid_stop_info.reason == eStopReasonFork)
986fe6060f1SDimitry Andric       assert(bool(m_extensions_supported &
987fe6060f1SDimitry Andric                   NativeProcessProtocol::Extension::fork));
988fe6060f1SDimitry Andric     if (tid_stop_info.reason == eStopReasonVFork)
989fe6060f1SDimitry Andric       assert(bool(m_extensions_supported &
990fe6060f1SDimitry Andric                   NativeProcessProtocol::Extension::vfork));
991fe6060f1SDimitry Andric     response.Printf("%s:p%" PRIx64 ".%" PRIx64 ";", reason_str,
992fe6060f1SDimitry Andric                     tid_stop_info.details.fork.child_pid,
993fe6060f1SDimitry Andric                     tid_stop_info.details.fork.child_tid);
994fe6060f1SDimitry Andric   }
995fe6060f1SDimitry Andric 
99681ad6265SDimitry Andric   return response;
99781ad6265SDimitry Andric }
99881ad6265SDimitry Andric 
99981ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
100081ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
100181ad6265SDimitry Andric     NativeProcessProtocol &process, lldb::tid_t tid, bool force_synchronous) {
100281ad6265SDimitry Andric   // Ensure we can get info on the given thread.
100381ad6265SDimitry Andric   NativeThreadProtocol *thread = process.GetThreadByID(tid);
100481ad6265SDimitry Andric   if (!thread)
100581ad6265SDimitry Andric     return SendErrorResponse(51);
100681ad6265SDimitry Andric 
100781ad6265SDimitry Andric   StreamString response = PrepareStopReplyPacketForThread(*thread);
100881ad6265SDimitry Andric   if (response.Empty())
100981ad6265SDimitry Andric     return SendErrorResponse(42);
101081ad6265SDimitry Andric 
101181ad6265SDimitry Andric   if (m_non_stop && !force_synchronous) {
101281ad6265SDimitry Andric     PacketResult ret = SendNotificationPacketNoLock(
101381ad6265SDimitry Andric         "Stop", m_stop_notification_queue, response.GetString());
101481ad6265SDimitry Andric     // Queue notification events for the remaining threads.
101581ad6265SDimitry Andric     EnqueueStopReplyPackets(tid);
101681ad6265SDimitry Andric     return ret;
101781ad6265SDimitry Andric   }
101881ad6265SDimitry Andric 
10190b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
10200b57cec5SDimitry Andric }
10210b57cec5SDimitry Andric 
102281ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::EnqueueStopReplyPackets(
102381ad6265SDimitry Andric     lldb::tid_t thread_to_skip) {
102481ad6265SDimitry Andric   if (!m_non_stop)
102581ad6265SDimitry Andric     return;
102681ad6265SDimitry Andric 
102781ad6265SDimitry Andric   for (NativeThreadProtocol &listed_thread : m_current_process->Threads()) {
1028fcaf7f86SDimitry Andric     if (listed_thread.GetID() != thread_to_skip) {
1029fcaf7f86SDimitry Andric       StreamString stop_reply = PrepareStopReplyPacketForThread(listed_thread);
1030fcaf7f86SDimitry Andric       if (!stop_reply.Empty())
1031fcaf7f86SDimitry Andric         m_stop_notification_queue.push_back(stop_reply.GetString().str());
1032fcaf7f86SDimitry Andric     }
103381ad6265SDimitry Andric   }
103481ad6265SDimitry Andric }
103581ad6265SDimitry Andric 
10360b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
10370b57cec5SDimitry Andric     NativeProcessProtocol *process) {
10380b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
10390b57cec5SDimitry Andric 
104081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
10419dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
10420b57cec5SDimitry Andric 
104381ad6265SDimitry Andric   PacketResult result = SendStopReasonForState(
104481ad6265SDimitry Andric       *process, StateType::eStateExited, /*force_synchronous=*/false);
10450b57cec5SDimitry Andric   if (result != PacketResult::Success) {
10469dba64beSDimitry Andric     LLDB_LOGF(log,
10479dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to send stop "
10480b57cec5SDimitry Andric               "notification for PID %" PRIu64 ", state: eStateExited",
10490b57cec5SDimitry Andric               __FUNCTION__, process->GetID());
10500b57cec5SDimitry Andric   }
10510b57cec5SDimitry Andric 
105281ad6265SDimitry Andric   if (m_current_process == process)
105381ad6265SDimitry Andric     m_current_process = nullptr;
105481ad6265SDimitry Andric   if (m_continue_process == process)
105581ad6265SDimitry Andric     m_continue_process = nullptr;
105681ad6265SDimitry Andric 
105781ad6265SDimitry Andric   lldb::pid_t pid = process->GetID();
105881ad6265SDimitry Andric   m_mainloop.AddPendingCallback([this, pid](MainLoopBase &loop) {
1059fcaf7f86SDimitry Andric     auto find_it = m_debugged_processes.find(pid);
1060fcaf7f86SDimitry Andric     assert(find_it != m_debugged_processes.end());
1061fcaf7f86SDimitry Andric     bool vkilled = bool(find_it->second.flags & DebuggedProcess::Flag::vkilled);
1062fcaf7f86SDimitry Andric     m_debugged_processes.erase(find_it);
106381ad6265SDimitry Andric     // Terminate the main loop only if vKill has not been used.
106481ad6265SDimitry Andric     // When running in non-stop mode, wait for the vStopped to clear
106581ad6265SDimitry Andric     // the notification queue.
1066fcaf7f86SDimitry Andric     if (m_debugged_processes.empty() && !m_non_stop && !vkilled) {
106781ad6265SDimitry Andric       // Close the pipe to the inferior terminal i/o if we launched it and set
106881ad6265SDimitry Andric       // one up.
10690b57cec5SDimitry Andric       MaybeCloseInferiorTerminalConnection();
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric       // We are ready to exit the debug monitor.
10720b57cec5SDimitry Andric       m_exit_now = true;
107381ad6265SDimitry Andric       loop.RequestTermination();
107481ad6265SDimitry Andric     }
107581ad6265SDimitry Andric   });
10760b57cec5SDimitry Andric }
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
10790b57cec5SDimitry Andric     NativeProcessProtocol *process) {
10800b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
10810b57cec5SDimitry Andric 
108281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
10839dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
10840b57cec5SDimitry Andric 
108581ad6265SDimitry Andric   PacketResult result = SendStopReasonForState(
108681ad6265SDimitry Andric       *process, StateType::eStateStopped, /*force_synchronous=*/false);
10870b57cec5SDimitry Andric   if (result != PacketResult::Success) {
10889dba64beSDimitry Andric     LLDB_LOGF(log,
10899dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to send stop "
10900b57cec5SDimitry Andric               "notification for PID %" PRIu64 ", state: eStateExited",
10910b57cec5SDimitry Andric               __FUNCTION__, process->GetID());
10920b57cec5SDimitry Andric   }
10930b57cec5SDimitry Andric }
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
10960b57cec5SDimitry Andric     NativeProcessProtocol *process, lldb::StateType state) {
10970b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
109881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
10990b57cec5SDimitry Andric   if (log) {
11009dba64beSDimitry Andric     LLDB_LOGF(log,
11019dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s called with "
11020b57cec5SDimitry Andric               "NativeProcessProtocol pid %" PRIu64 ", state: %s",
11030b57cec5SDimitry Andric               __FUNCTION__, process->GetID(), StateAsCString(state));
11040b57cec5SDimitry Andric   }
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric   switch (state) {
11070b57cec5SDimitry Andric   case StateType::eStateRunning:
11080b57cec5SDimitry Andric     break;
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric   case StateType::eStateStopped:
11110b57cec5SDimitry Andric     // Make sure we get all of the pending stdout/stderr from the inferior and
11120b57cec5SDimitry Andric     // send it to the lldb host before we send the state change notification
11130b57cec5SDimitry Andric     SendProcessOutput();
11140b57cec5SDimitry Andric     // Then stop the forwarding, so that any late output (see llvm.org/pr25652)
11150b57cec5SDimitry Andric     // does not interfere with our protocol.
1116fcaf7f86SDimitry Andric     if (!m_non_stop)
11170b57cec5SDimitry Andric       StopSTDIOForwarding();
11180b57cec5SDimitry Andric     HandleInferiorState_Stopped(process);
11190b57cec5SDimitry Andric     break;
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric   case StateType::eStateExited:
11220b57cec5SDimitry Andric     // Same as above
11230b57cec5SDimitry Andric     SendProcessOutput();
1124fcaf7f86SDimitry Andric     if (!m_non_stop)
11250b57cec5SDimitry Andric       StopSTDIOForwarding();
11260b57cec5SDimitry Andric     HandleInferiorState_Exited(process);
11270b57cec5SDimitry Andric     break;
11280b57cec5SDimitry Andric 
11290b57cec5SDimitry Andric   default:
11300b57cec5SDimitry Andric     if (log) {
11319dba64beSDimitry Andric       LLDB_LOGF(log,
11329dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s didn't handle state "
11330b57cec5SDimitry Andric                 "change for pid %" PRIu64 ", new state: %s",
11340b57cec5SDimitry Andric                 __FUNCTION__, process->GetID(), StateAsCString(state));
11350b57cec5SDimitry Andric     }
11360b57cec5SDimitry Andric     break;
11370b57cec5SDimitry Andric   }
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric 
11400b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) {
11410b57cec5SDimitry Andric   ClearProcessSpecificData();
11420b57cec5SDimitry Andric }
11430b57cec5SDimitry Andric 
1144fe6060f1SDimitry Andric void GDBRemoteCommunicationServerLLGS::NewSubprocess(
1145fe6060f1SDimitry Andric     NativeProcessProtocol *parent_process,
1146fe6060f1SDimitry Andric     std::unique_ptr<NativeProcessProtocol> child_process) {
1147fe6060f1SDimitry Andric   lldb::pid_t child_pid = child_process->GetID();
1148fe6060f1SDimitry Andric   assert(child_pid != LLDB_INVALID_PROCESS_ID);
1149fe6060f1SDimitry Andric   assert(m_debugged_processes.find(child_pid) == m_debugged_processes.end());
1150fcaf7f86SDimitry Andric   m_debugged_processes.emplace(
1151fcaf7f86SDimitry Andric       child_pid,
1152fcaf7f86SDimitry Andric       DebuggedProcess{std::move(child_process), DebuggedProcess::Flag{}});
1153fe6060f1SDimitry Andric }
1154fe6060f1SDimitry Andric 
11550b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
115604eeddc0SDimitry Andric   Log *log = GetLog(GDBRLog::Comm);
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric   bool interrupt = false;
11590b57cec5SDimitry Andric   bool done = false;
11600b57cec5SDimitry Andric   Status error;
11610b57cec5SDimitry Andric   while (true) {
11620b57cec5SDimitry Andric     const PacketResult result = GetPacketAndSendResponse(
11630b57cec5SDimitry Andric         std::chrono::microseconds(0), error, interrupt, done);
11640b57cec5SDimitry Andric     if (result == PacketResult::ErrorReplyTimeout)
11650b57cec5SDimitry Andric       break; // No more packets in the queue
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric     if ((result != PacketResult::Success)) {
11689dba64beSDimitry Andric       LLDB_LOGF(log,
11699dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s processing a packet "
11700b57cec5SDimitry Andric                 "failed: %s",
11710b57cec5SDimitry Andric                 __FUNCTION__, error.AsCString());
11720b57cec5SDimitry Andric       m_mainloop.RequestTermination();
11730b57cec5SDimitry Andric       break;
11740b57cec5SDimitry Andric     }
11750b57cec5SDimitry Andric   }
11760b57cec5SDimitry Andric }
11770b57cec5SDimitry Andric 
11780b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::InitializeConnection(
11795ffd83dbSDimitry Andric     std::unique_ptr<Connection> connection) {
11800b57cec5SDimitry Andric   IOObjectSP read_object_sp = connection->GetReadObject();
11815ffd83dbSDimitry Andric   GDBRemoteCommunicationServer::SetConnection(std::move(connection));
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric   Status error;
11840b57cec5SDimitry Andric   m_network_handle_up = m_mainloop.RegisterReadObject(
11850b57cec5SDimitry Andric       read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); },
11860b57cec5SDimitry Andric       error);
11870b57cec5SDimitry Andric   return error;
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
11910b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer,
11920b57cec5SDimitry Andric                                                     uint32_t len) {
11930b57cec5SDimitry Andric   if ((buffer == nullptr) || (len == 0)) {
11940b57cec5SDimitry Andric     // Nothing to send.
11950b57cec5SDimitry Andric     return PacketResult::Success;
11960b57cec5SDimitry Andric   }
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric   StreamString response;
11990b57cec5SDimitry Andric   response.PutChar('O');
12000b57cec5SDimitry Andric   response.PutBytesAsRawHex8(buffer, len);
12010b57cec5SDimitry Andric 
1202fcaf7f86SDimitry Andric   if (m_non_stop)
1203fcaf7f86SDimitry Andric     return SendNotificationPacketNoLock("Stdio", m_stdio_notification_queue,
1204fcaf7f86SDimitry Andric                                         response.GetString());
12050b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
12060b57cec5SDimitry Andric }
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) {
12090b57cec5SDimitry Andric   Status error;
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric   // Set up the reading/handling of process I/O
12120b57cec5SDimitry Andric   std::unique_ptr<ConnectionFileDescriptor> conn_up(
12130b57cec5SDimitry Andric       new ConnectionFileDescriptor(fd, true));
12140b57cec5SDimitry Andric   if (!conn_up) {
12150b57cec5SDimitry Andric     error.SetErrorString("failed to create ConnectionFileDescriptor");
12160b57cec5SDimitry Andric     return error;
12170b57cec5SDimitry Andric   }
12180b57cec5SDimitry Andric 
12190b57cec5SDimitry Andric   m_stdio_communication.SetCloseOnEOF(false);
12205ffd83dbSDimitry Andric   m_stdio_communication.SetConnection(std::move(conn_up));
12210b57cec5SDimitry Andric   if (!m_stdio_communication.IsConnected()) {
12220b57cec5SDimitry Andric     error.SetErrorString(
12230b57cec5SDimitry Andric         "failed to set connection for inferior I/O communication");
12240b57cec5SDimitry Andric     return error;
12250b57cec5SDimitry Andric   }
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric   return Status();
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() {
12310b57cec5SDimitry Andric   // Don't forward if not connected (e.g. when attaching).
12320b57cec5SDimitry Andric   if (!m_stdio_communication.IsConnected())
12330b57cec5SDimitry Andric     return;
12340b57cec5SDimitry Andric 
12350b57cec5SDimitry Andric   Status error;
123681ad6265SDimitry Andric   assert(!m_stdio_handle_up);
12370b57cec5SDimitry Andric   m_stdio_handle_up = m_mainloop.RegisterReadObject(
12380b57cec5SDimitry Andric       m_stdio_communication.GetConnection()->GetReadObject(),
12390b57cec5SDimitry Andric       [this](MainLoopBase &) { SendProcessOutput(); }, error);
12400b57cec5SDimitry Andric 
12410b57cec5SDimitry Andric   if (!m_stdio_handle_up) {
12420b57cec5SDimitry Andric     // Not much we can do about the failure. Log it and continue without
12430b57cec5SDimitry Andric     // forwarding.
124481ad6265SDimitry Andric     if (Log *log = GetLog(LLDBLog::Process))
124581ad6265SDimitry Andric       LLDB_LOG(log, "Failed to set up stdio forwarding: {0}", error);
12460b57cec5SDimitry Andric   }
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() {
12500b57cec5SDimitry Andric   m_stdio_handle_up.reset();
12510b57cec5SDimitry Andric }
12520b57cec5SDimitry Andric 
12530b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
12540b57cec5SDimitry Andric   char buffer[1024];
12550b57cec5SDimitry Andric   ConnectionStatus status;
12560b57cec5SDimitry Andric   Status error;
12570b57cec5SDimitry Andric   while (true) {
12580b57cec5SDimitry Andric     size_t bytes_read = m_stdio_communication.Read(
12590b57cec5SDimitry Andric         buffer, sizeof buffer, std::chrono::microseconds(0), status, &error);
12600b57cec5SDimitry Andric     switch (status) {
12610b57cec5SDimitry Andric     case eConnectionStatusSuccess:
12620b57cec5SDimitry Andric       SendONotification(buffer, bytes_read);
12630b57cec5SDimitry Andric       break;
12640b57cec5SDimitry Andric     case eConnectionStatusLostConnection:
12650b57cec5SDimitry Andric     case eConnectionStatusEndOfFile:
12660b57cec5SDimitry Andric     case eConnectionStatusError:
12670b57cec5SDimitry Andric     case eConnectionStatusNoConnection:
126881ad6265SDimitry Andric       if (Log *log = GetLog(LLDBLog::Process))
12699dba64beSDimitry Andric         LLDB_LOGF(log,
12709dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s Stopping stdio "
12710b57cec5SDimitry Andric                   "forwarding as communication returned status %d (error: "
12720b57cec5SDimitry Andric                   "%s)",
12730b57cec5SDimitry Andric                   __FUNCTION__, status, error.AsCString());
12740b57cec5SDimitry Andric       m_stdio_handle_up.reset();
12750b57cec5SDimitry Andric       return;
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric     case eConnectionStatusInterrupted:
12780b57cec5SDimitry Andric     case eConnectionStatusTimedOut:
12790b57cec5SDimitry Andric       return;
12800b57cec5SDimitry Andric     }
12810b57cec5SDimitry Andric   }
12820b57cec5SDimitry Andric }
12830b57cec5SDimitry Andric 
12840b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1285fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported(
12860b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
1287fe6060f1SDimitry Andric 
12880b57cec5SDimitry Andric   // Fail if we don't have a current process.
1289fe6060f1SDimitry Andric   if (!m_current_process ||
1290fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1291fe6060f1SDimitry Andric     return SendErrorResponse(Status("Process not running."));
12920b57cec5SDimitry Andric 
1293fe6060f1SDimitry Andric   return SendJSONResponse(m_current_process->TraceSupported());
12940b57cec5SDimitry Andric }
12950b57cec5SDimitry Andric 
12960b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1297fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop(
12980b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
12990b57cec5SDimitry Andric   // Fail if we don't have a current process.
1300fe6060f1SDimitry Andric   if (!m_current_process ||
1301fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1302fe6060f1SDimitry Andric     return SendErrorResponse(Status("Process not running."));
13030b57cec5SDimitry Andric 
1304fe6060f1SDimitry Andric   packet.ConsumeFront("jLLDBTraceStop:");
1305fe6060f1SDimitry Andric   Expected<TraceStopRequest> stop_request =
1306fe6060f1SDimitry Andric       json::parse<TraceStopRequest>(packet.Peek(), "TraceStopRequest");
1307fe6060f1SDimitry Andric   if (!stop_request)
1308fe6060f1SDimitry Andric     return SendErrorResponse(stop_request.takeError());
13090b57cec5SDimitry Andric 
1310fe6060f1SDimitry Andric   if (Error err = m_current_process->TraceStop(*stop_request))
1311fe6060f1SDimitry Andric     return SendErrorResponse(std::move(err));
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric   return SendOKResponse();
13140b57cec5SDimitry Andric }
13150b57cec5SDimitry Andric 
13160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1317fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart(
1318e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
1319e8d8bef9SDimitry Andric 
1320e8d8bef9SDimitry Andric   // Fail if we don't have a current process.
1321fe6060f1SDimitry Andric   if (!m_current_process ||
1322fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1323e8d8bef9SDimitry Andric     return SendErrorResponse(Status("Process not running."));
1324e8d8bef9SDimitry Andric 
1325fe6060f1SDimitry Andric   packet.ConsumeFront("jLLDBTraceStart:");
1326fe6060f1SDimitry Andric   Expected<TraceStartRequest> request =
1327fe6060f1SDimitry Andric       json::parse<TraceStartRequest>(packet.Peek(), "TraceStartRequest");
1328fe6060f1SDimitry Andric   if (!request)
1329fe6060f1SDimitry Andric     return SendErrorResponse(request.takeError());
1330e8d8bef9SDimitry Andric 
1331fe6060f1SDimitry Andric   if (Error err = m_current_process->TraceStart(packet.Peek(), request->type))
1332fe6060f1SDimitry Andric     return SendErrorResponse(std::move(err));
1333e8d8bef9SDimitry Andric 
1334fe6060f1SDimitry Andric   return SendOKResponse();
1335e8d8bef9SDimitry Andric }
1336e8d8bef9SDimitry Andric 
1337e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
1338fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState(
13390b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric   // Fail if we don't have a current process.
1342fe6060f1SDimitry Andric   if (!m_current_process ||
1343fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1344fe6060f1SDimitry Andric     return SendErrorResponse(Status("Process not running."));
13450b57cec5SDimitry Andric 
1346fe6060f1SDimitry Andric   packet.ConsumeFront("jLLDBTraceGetState:");
1347fe6060f1SDimitry Andric   Expected<TraceGetStateRequest> request =
1348fe6060f1SDimitry Andric       json::parse<TraceGetStateRequest>(packet.Peek(), "TraceGetStateRequest");
1349fe6060f1SDimitry Andric   if (!request)
1350fe6060f1SDimitry Andric     return SendErrorResponse(request.takeError());
13510b57cec5SDimitry Andric 
1352fe6060f1SDimitry Andric   return SendJSONResponse(m_current_process->TraceGetState(request->type));
13530b57cec5SDimitry Andric }
13540b57cec5SDimitry Andric 
13550b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1356fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData(
13570b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric   // Fail if we don't have a current process.
1360fe6060f1SDimitry Andric   if (!m_current_process ||
1361fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1362fe6060f1SDimitry Andric     return SendErrorResponse(Status("Process not running."));
13630b57cec5SDimitry Andric 
1364fe6060f1SDimitry Andric   packet.ConsumeFront("jLLDBTraceGetBinaryData:");
1365fe6060f1SDimitry Andric   llvm::Expected<TraceGetBinaryDataRequest> request =
1366fe6060f1SDimitry Andric       llvm::json::parse<TraceGetBinaryDataRequest>(packet.Peek(),
1367fe6060f1SDimitry Andric                                                    "TraceGetBinaryDataRequest");
1368fe6060f1SDimitry Andric   if (!request)
1369fe6060f1SDimitry Andric     return SendErrorResponse(Status(request.takeError()));
13700b57cec5SDimitry Andric 
1371fe6060f1SDimitry Andric   if (Expected<std::vector<uint8_t>> bytes =
1372fe6060f1SDimitry Andric           m_current_process->TraceGetBinaryData(*request)) {
13730b57cec5SDimitry Andric     StreamGDBRemote response;
1374fe6060f1SDimitry Andric     response.PutEscapedBytes(bytes->data(), bytes->size());
1375fe6060f1SDimitry Andric     return SendPacketNoLock(response.GetString());
1376fe6060f1SDimitry Andric   } else
1377fe6060f1SDimitry Andric     return SendErrorResponse(bytes.takeError());
13780b57cec5SDimitry Andric }
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
13810b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
13820b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
13830b57cec5SDimitry Andric   // Fail if we don't have a current process.
1384fe6060f1SDimitry Andric   if (!m_current_process ||
1385fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
13860b57cec5SDimitry Andric     return SendErrorResponse(68);
13870b57cec5SDimitry Andric 
1388fe6060f1SDimitry Andric   lldb::pid_t pid = m_current_process->GetID();
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
13910b57cec5SDimitry Andric     return SendErrorResponse(1);
13920b57cec5SDimitry Andric 
13930b57cec5SDimitry Andric   ProcessInstanceInfo proc_info;
13940b57cec5SDimitry Andric   if (!Host::GetProcessInfo(pid, proc_info))
13950b57cec5SDimitry Andric     return SendErrorResponse(1);
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric   StreamString response;
13980b57cec5SDimitry Andric   CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
13990b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
14000b57cec5SDimitry Andric }
14010b57cec5SDimitry Andric 
14020b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14030b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
14040b57cec5SDimitry Andric   // Fail if we don't have a current process.
1405fe6060f1SDimitry Andric   if (!m_current_process ||
1406fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
14070b57cec5SDimitry Andric     return SendErrorResponse(68);
14080b57cec5SDimitry Andric 
14090b57cec5SDimitry Andric   // Make sure we set the current thread so g and p packets return the data the
14100b57cec5SDimitry Andric   // gdb will expect.
1411fe6060f1SDimitry Andric   lldb::tid_t tid = m_current_process->GetCurrentThreadID();
14120b57cec5SDimitry Andric   SetCurrentThreadID(tid);
14130b57cec5SDimitry Andric 
1414fe6060f1SDimitry Andric   NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
14150b57cec5SDimitry Andric   if (!thread)
14160b57cec5SDimitry Andric     return SendErrorResponse(69);
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric   StreamString response;
141981ad6265SDimitry Andric   response.PutCString("QC");
142081ad6265SDimitry Andric   AppendThreadIDToResponse(response, m_current_process->GetID(),
142181ad6265SDimitry Andric                            thread->GetID());
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14270b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
142881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
14290b57cec5SDimitry Andric 
1430fcaf7f86SDimitry Andric   if (!m_non_stop)
14310b57cec5SDimitry Andric     StopSTDIOForwarding();
14320b57cec5SDimitry Andric 
143381ad6265SDimitry Andric   if (m_debugged_processes.empty()) {
14340b57cec5SDimitry Andric     LLDB_LOG(log, "No debugged process found.");
14350b57cec5SDimitry Andric     return PacketResult::Success;
14360b57cec5SDimitry Andric   }
14370b57cec5SDimitry Andric 
143881ad6265SDimitry Andric   for (auto it = m_debugged_processes.begin(); it != m_debugged_processes.end();
143981ad6265SDimitry Andric        ++it) {
144081ad6265SDimitry Andric     LLDB_LOG(log, "Killing process {0}", it->first);
1441fcaf7f86SDimitry Andric     Status error = it->second.process_up->Kill();
14420b57cec5SDimitry Andric     if (error.Fail())
144381ad6265SDimitry Andric       LLDB_LOG(log, "Failed to kill debugged process {0}: {1}", it->first,
144481ad6265SDimitry Andric                error);
144581ad6265SDimitry Andric   }
14460b57cec5SDimitry Andric 
144781ad6265SDimitry Andric   // The response to kill packet is undefined per the spec.  LLDB
144881ad6265SDimitry Andric   // follows the same rules as for continue packets, i.e. no response
144981ad6265SDimitry Andric   // in all-stop mode, and "OK" in non-stop mode; in both cases this
145081ad6265SDimitry Andric   // is followed by the actual stop reason.
145181ad6265SDimitry Andric   return SendContinueSuccessResponse();
145281ad6265SDimitry Andric }
145381ad6265SDimitry Andric 
145481ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
145581ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vKill(
145681ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
1457fcaf7f86SDimitry Andric   if (!m_non_stop)
145881ad6265SDimitry Andric     StopSTDIOForwarding();
145981ad6265SDimitry Andric 
146081ad6265SDimitry Andric   packet.SetFilePos(6); // vKill;
146181ad6265SDimitry Andric   uint32_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
146281ad6265SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
146381ad6265SDimitry Andric     return SendIllFormedResponse(packet,
146481ad6265SDimitry Andric                                  "vKill failed to parse the process id");
146581ad6265SDimitry Andric 
146681ad6265SDimitry Andric   auto it = m_debugged_processes.find(pid);
146781ad6265SDimitry Andric   if (it == m_debugged_processes.end())
146881ad6265SDimitry Andric     return SendErrorResponse(42);
146981ad6265SDimitry Andric 
1470fcaf7f86SDimitry Andric   Status error = it->second.process_up->Kill();
147181ad6265SDimitry Andric   if (error.Fail())
147281ad6265SDimitry Andric     return SendErrorResponse(error.ToError());
147381ad6265SDimitry Andric 
147481ad6265SDimitry Andric   // OK response is sent when the process dies.
1475fcaf7f86SDimitry Andric   it->second.flags |= DebuggedProcess::Flag::vkilled;
14760b57cec5SDimitry Andric   return PacketResult::Success;
14770b57cec5SDimitry Andric }
14780b57cec5SDimitry Andric 
14790b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14800b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR(
14810b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
14820b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetDisableASLR:"));
14830b57cec5SDimitry Andric   if (packet.GetU32(0))
14840b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
14850b57cec5SDimitry Andric   else
14860b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
14870b57cec5SDimitry Andric   return SendOKResponse();
14880b57cec5SDimitry Andric }
14890b57cec5SDimitry Andric 
14900b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14910b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir(
14920b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
14930b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetWorkingDir:"));
14940b57cec5SDimitry Andric   std::string path;
14950b57cec5SDimitry Andric   packet.GetHexByteString(path);
14960b57cec5SDimitry Andric   m_process_launch_info.SetWorkingDirectory(FileSpec(path));
14970b57cec5SDimitry Andric   return SendOKResponse();
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric 
15000b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
15010b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir(
15020b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
15030b57cec5SDimitry Andric   FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()};
15040b57cec5SDimitry Andric   if (working_dir) {
15050b57cec5SDimitry Andric     StreamString response;
15060b57cec5SDimitry Andric     response.PutStringAsRawHex8(working_dir.GetCString());
15070b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
15080b57cec5SDimitry Andric   }
15090b57cec5SDimitry Andric 
15100b57cec5SDimitry Andric   return SendErrorResponse(14);
15110b57cec5SDimitry Andric }
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1514fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported(
1515fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
1516fe6060f1SDimitry Andric   m_thread_suffix_supported = true;
1517fe6060f1SDimitry Andric   return SendOKResponse();
1518fe6060f1SDimitry Andric }
1519fe6060f1SDimitry Andric 
1520fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
1521fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply(
1522fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
1523fe6060f1SDimitry Andric   m_list_threads_in_stop_reply = true;
1524fe6060f1SDimitry Andric   return SendOKResponse();
1525fe6060f1SDimitry Andric }
1526fe6060f1SDimitry Andric 
1527fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
1528fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::ResumeProcess(
1529fcaf7f86SDimitry Andric     NativeProcessProtocol &process, const ResumeActionList &actions) {
1530fcaf7f86SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
1531fcaf7f86SDimitry Andric 
1532fcaf7f86SDimitry Andric   // In non-stop protocol mode, the process could be running already.
1533fcaf7f86SDimitry Andric   // We do not support resuming threads independently, so just error out.
1534fcaf7f86SDimitry Andric   if (!process.CanResume()) {
1535fcaf7f86SDimitry Andric     LLDB_LOG(log, "process {0} cannot be resumed (state={1})", process.GetID(),
1536fcaf7f86SDimitry Andric              process.GetState());
1537fcaf7f86SDimitry Andric     return SendErrorResponse(0x37);
1538fcaf7f86SDimitry Andric   }
1539fcaf7f86SDimitry Andric 
1540fcaf7f86SDimitry Andric   Status error = process.Resume(actions);
1541fcaf7f86SDimitry Andric   if (error.Fail()) {
1542fcaf7f86SDimitry Andric     LLDB_LOG(log, "process {0} failed to resume: {1}", process.GetID(), error);
1543fcaf7f86SDimitry Andric     return SendErrorResponse(GDBRemoteServerError::eErrorResume);
1544fcaf7f86SDimitry Andric   }
1545fcaf7f86SDimitry Andric 
1546fcaf7f86SDimitry Andric   LLDB_LOG(log, "process {0} resumed", process.GetID());
1547fcaf7f86SDimitry Andric 
1548fcaf7f86SDimitry Andric   return PacketResult::Success;
1549fcaf7f86SDimitry Andric }
1550fcaf7f86SDimitry Andric 
1551fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult
15520b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
155381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
15549dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
15550b57cec5SDimitry Andric 
15560b57cec5SDimitry Andric   // Ensure we have a native process.
1557fe6060f1SDimitry Andric   if (!m_continue_process) {
15589dba64beSDimitry Andric     LLDB_LOGF(log,
15599dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s no debugged process "
15600b57cec5SDimitry Andric               "shared pointer",
15610b57cec5SDimitry Andric               __FUNCTION__);
15620b57cec5SDimitry Andric     return SendErrorResponse(0x36);
15630b57cec5SDimitry Andric   }
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric   // Pull out the signal number.
15660b57cec5SDimitry Andric   packet.SetFilePos(::strlen("C"));
15670b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1) {
15680b57cec5SDimitry Andric     // Shouldn't be using a C without a signal.
15690b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "C packet specified without signal.");
15700b57cec5SDimitry Andric   }
15710b57cec5SDimitry Andric   const uint32_t signo =
15720b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
15730b57cec5SDimitry Andric   if (signo == std::numeric_limits<uint32_t>::max())
15740b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "failed to parse signal number");
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   // Handle optional continue address.
15770b57cec5SDimitry Andric   if (packet.GetBytesLeft() > 0) {
15780b57cec5SDimitry Andric     // FIXME add continue at address support for $C{signo}[;{continue-address}].
15790b57cec5SDimitry Andric     if (*packet.Peek() == ';')
15809dba64beSDimitry Andric       return SendUnimplementedResponse(packet.GetStringRef().data());
15810b57cec5SDimitry Andric     else
15820b57cec5SDimitry Andric       return SendIllFormedResponse(
15830b57cec5SDimitry Andric           packet, "unexpected content after $C{signal-number}");
15840b57cec5SDimitry Andric   }
15850b57cec5SDimitry Andric 
1586fcaf7f86SDimitry Andric   // In non-stop protocol mode, the process could be running already.
1587fcaf7f86SDimitry Andric   // We do not support resuming threads independently, so just error out.
1588fcaf7f86SDimitry Andric   if (!m_continue_process->CanResume()) {
1589fcaf7f86SDimitry Andric     LLDB_LOG(log, "process cannot be resumed (state={0})",
1590fcaf7f86SDimitry Andric              m_continue_process->GetState());
1591fcaf7f86SDimitry Andric     return SendErrorResponse(0x37);
1592fcaf7f86SDimitry Andric   }
1593fcaf7f86SDimitry Andric 
15949dba64beSDimitry Andric   ResumeActionList resume_actions(StateType::eStateRunning,
15959dba64beSDimitry Andric                                   LLDB_INVALID_SIGNAL_NUMBER);
15960b57cec5SDimitry Andric   Status error;
15970b57cec5SDimitry Andric 
15980b57cec5SDimitry Andric   // We have two branches: what to do if a continue thread is specified (in
15990b57cec5SDimitry Andric   // which case we target sending the signal to that thread), or when we don't
16000b57cec5SDimitry Andric   // have a continue thread set (in which case we send a signal to the
16010b57cec5SDimitry Andric   // process).
16020b57cec5SDimitry Andric 
16030b57cec5SDimitry Andric   // TODO discuss with Greg Clayton, make sure this makes sense.
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric   lldb::tid_t signal_tid = GetContinueThreadID();
16060b57cec5SDimitry Andric   if (signal_tid != LLDB_INVALID_THREAD_ID) {
16070b57cec5SDimitry Andric     // The resume action for the continue thread (or all threads if a continue
16080b57cec5SDimitry Andric     // thread is not set).
16090b57cec5SDimitry Andric     ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning,
16100b57cec5SDimitry Andric                            static_cast<int>(signo)};
16110b57cec5SDimitry Andric 
16120b57cec5SDimitry Andric     // Add the action for the continue thread (or all threads when the continue
16130b57cec5SDimitry Andric     // thread isn't present).
16140b57cec5SDimitry Andric     resume_actions.Append(action);
16150b57cec5SDimitry Andric   } else {
16160b57cec5SDimitry Andric     // Send the signal to the process since we weren't targeting a specific
16170b57cec5SDimitry Andric     // continue thread with the signal.
1618fe6060f1SDimitry Andric     error = m_continue_process->Signal(signo);
16190b57cec5SDimitry Andric     if (error.Fail()) {
16200b57cec5SDimitry Andric       LLDB_LOG(log, "failed to send signal for process {0}: {1}",
1621fe6060f1SDimitry Andric                m_continue_process->GetID(), error);
16220b57cec5SDimitry Andric 
16230b57cec5SDimitry Andric       return SendErrorResponse(0x52);
16240b57cec5SDimitry Andric     }
16250b57cec5SDimitry Andric   }
16260b57cec5SDimitry Andric 
1627fcaf7f86SDimitry Andric   // NB: this checks CanResume() twice but using a single code path for
1628fcaf7f86SDimitry Andric   // resuming still seems worth it.
1629fcaf7f86SDimitry Andric   PacketResult resume_res = ResumeProcess(*m_continue_process, resume_actions);
1630fcaf7f86SDimitry Andric   if (resume_res != PacketResult::Success)
1631fcaf7f86SDimitry Andric     return resume_res;
16320b57cec5SDimitry Andric 
163381ad6265SDimitry Andric   // Don't send an "OK" packet, except in non-stop mode;
163481ad6265SDimitry Andric   // otherwise, the response is the stopped/exited message.
163581ad6265SDimitry Andric   return SendContinueSuccessResponse();
16360b57cec5SDimitry Andric }
16370b57cec5SDimitry Andric 
16380b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
16390b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
164081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
16419dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
16420b57cec5SDimitry Andric 
16430b57cec5SDimitry Andric   packet.SetFilePos(packet.GetFilePos() + ::strlen("c"));
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric   // For now just support all continue.
16460b57cec5SDimitry Andric   const bool has_continue_address = (packet.GetBytesLeft() > 0);
16470b57cec5SDimitry Andric   if (has_continue_address) {
16480b57cec5SDimitry Andric     LLDB_LOG(log, "not implemented for c[address] variant [{0} remains]",
16490b57cec5SDimitry Andric              packet.Peek());
16509dba64beSDimitry Andric     return SendUnimplementedResponse(packet.GetStringRef().data());
16510b57cec5SDimitry Andric   }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric   // Ensure we have a native process.
1654fe6060f1SDimitry Andric   if (!m_continue_process) {
16559dba64beSDimitry Andric     LLDB_LOGF(log,
16569dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s no debugged process "
16570b57cec5SDimitry Andric               "shared pointer",
16580b57cec5SDimitry Andric               __FUNCTION__);
16590b57cec5SDimitry Andric     return SendErrorResponse(0x36);
16600b57cec5SDimitry Andric   }
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric   // Build the ResumeActionList
16639dba64beSDimitry Andric   ResumeActionList actions(StateType::eStateRunning,
16649dba64beSDimitry Andric                            LLDB_INVALID_SIGNAL_NUMBER);
16650b57cec5SDimitry Andric 
1666fcaf7f86SDimitry Andric   PacketResult resume_res = ResumeProcess(*m_continue_process, actions);
1667fcaf7f86SDimitry Andric   if (resume_res != PacketResult::Success)
1668fcaf7f86SDimitry Andric     return resume_res;
166981ad6265SDimitry Andric 
167081ad6265SDimitry Andric   return SendContinueSuccessResponse();
16710b57cec5SDimitry Andric }
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
16740b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCont_actions(
16750b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
16760b57cec5SDimitry Andric   StreamString response;
167781ad6265SDimitry Andric   response.Printf("vCont;c;C;s;S;t");
16780b57cec5SDimitry Andric 
16790b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
16800b57cec5SDimitry Andric }
16810b57cec5SDimitry Andric 
1682fcaf7f86SDimitry Andric static bool ResumeActionListStopsAllThreads(ResumeActionList &actions) {
1683fcaf7f86SDimitry Andric   // We're doing a stop-all if and only if our only action is a "t" for all
1684fcaf7f86SDimitry Andric   // threads.
1685fcaf7f86SDimitry Andric   if (const ResumeAction *default_action =
1686fcaf7f86SDimitry Andric           actions.GetActionForThread(LLDB_INVALID_THREAD_ID, false)) {
1687fcaf7f86SDimitry Andric     if (default_action->state == eStateSuspended && actions.GetSize() == 1)
1688fcaf7f86SDimitry Andric       return true;
1689fcaf7f86SDimitry Andric   }
1690fcaf7f86SDimitry Andric 
1691fcaf7f86SDimitry Andric   return false;
1692fcaf7f86SDimitry Andric }
1693fcaf7f86SDimitry Andric 
16940b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
16950b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCont(
16960b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
169781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
16989dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s handling vCont packet",
16990b57cec5SDimitry Andric             __FUNCTION__);
17000b57cec5SDimitry Andric 
17010b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vCont"));
17020b57cec5SDimitry Andric 
17030b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0) {
17049dba64beSDimitry Andric     LLDB_LOGF(log,
17059dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s missing action from "
17060b57cec5SDimitry Andric               "vCont package",
17070b57cec5SDimitry Andric               __FUNCTION__);
17080b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Missing action from vCont package");
17090b57cec5SDimitry Andric   }
17100b57cec5SDimitry Andric 
171181ad6265SDimitry Andric   if (::strcmp(packet.Peek(), ";s") == 0) {
17120b57cec5SDimitry Andric     // Move past the ';', then do a simple 's'.
17130b57cec5SDimitry Andric     packet.SetFilePos(packet.GetFilePos() + 1);
17140b57cec5SDimitry Andric     return Handle_s(packet);
17150b57cec5SDimitry Andric   }
17160b57cec5SDimitry Andric 
171781ad6265SDimitry Andric   std::unordered_map<lldb::pid_t, ResumeActionList> thread_actions;
17180b57cec5SDimitry Andric 
17190b57cec5SDimitry Andric   while (packet.GetBytesLeft() && *packet.Peek() == ';') {
17200b57cec5SDimitry Andric     // Skip the semi-colon.
17210b57cec5SDimitry Andric     packet.GetChar();
17220b57cec5SDimitry Andric 
17230b57cec5SDimitry Andric     // Build up the thread action.
17240b57cec5SDimitry Andric     ResumeAction thread_action;
17250b57cec5SDimitry Andric     thread_action.tid = LLDB_INVALID_THREAD_ID;
17260b57cec5SDimitry Andric     thread_action.state = eStateInvalid;
17279dba64beSDimitry Andric     thread_action.signal = LLDB_INVALID_SIGNAL_NUMBER;
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric     const char action = packet.GetChar();
17300b57cec5SDimitry Andric     switch (action) {
17310b57cec5SDimitry Andric     case 'C':
17320b57cec5SDimitry Andric       thread_action.signal = packet.GetHexMaxU32(false, 0);
17330b57cec5SDimitry Andric       if (thread_action.signal == 0)
17340b57cec5SDimitry Andric         return SendIllFormedResponse(
17350b57cec5SDimitry Andric             packet, "Could not parse signal in vCont packet C action");
17360b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
17370b57cec5SDimitry Andric 
17380b57cec5SDimitry Andric     case 'c':
17390b57cec5SDimitry Andric       // Continue
17400b57cec5SDimitry Andric       thread_action.state = eStateRunning;
17410b57cec5SDimitry Andric       break;
17420b57cec5SDimitry Andric 
17430b57cec5SDimitry Andric     case 'S':
17440b57cec5SDimitry Andric       thread_action.signal = packet.GetHexMaxU32(false, 0);
17450b57cec5SDimitry Andric       if (thread_action.signal == 0)
17460b57cec5SDimitry Andric         return SendIllFormedResponse(
17470b57cec5SDimitry Andric             packet, "Could not parse signal in vCont packet S action");
17480b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
17490b57cec5SDimitry Andric 
17500b57cec5SDimitry Andric     case 's':
17510b57cec5SDimitry Andric       // Step
17520b57cec5SDimitry Andric       thread_action.state = eStateStepping;
17530b57cec5SDimitry Andric       break;
17540b57cec5SDimitry Andric 
175581ad6265SDimitry Andric     case 't':
175681ad6265SDimitry Andric       // Stop
175781ad6265SDimitry Andric       thread_action.state = eStateSuspended;
175881ad6265SDimitry Andric       break;
175981ad6265SDimitry Andric 
17600b57cec5SDimitry Andric     default:
17610b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Unsupported vCont action");
17620b57cec5SDimitry Andric       break;
17630b57cec5SDimitry Andric     }
17640b57cec5SDimitry Andric 
176581ad6265SDimitry Andric     lldb::pid_t pid = StringExtractorGDBRemote::AllProcesses;
176681ad6265SDimitry Andric     lldb::tid_t tid = StringExtractorGDBRemote::AllThreads;
176781ad6265SDimitry Andric 
17680b57cec5SDimitry Andric     // Parse out optional :{thread-id} value.
17690b57cec5SDimitry Andric     if (packet.GetBytesLeft() && (*packet.Peek() == ':')) {
17700b57cec5SDimitry Andric       // Consume the separator.
17710b57cec5SDimitry Andric       packet.GetChar();
17720b57cec5SDimitry Andric 
177381ad6265SDimitry Andric       auto pid_tid = packet.GetPidTid(StringExtractorGDBRemote::AllProcesses);
177481ad6265SDimitry Andric       if (!pid_tid)
177581ad6265SDimitry Andric         return SendIllFormedResponse(packet, "Malformed thread-id");
1776fe6060f1SDimitry Andric 
177781ad6265SDimitry Andric       pid = pid_tid->first;
177881ad6265SDimitry Andric       tid = pid_tid->second;
17790b57cec5SDimitry Andric     }
17800b57cec5SDimitry Andric 
1781fcaf7f86SDimitry Andric     if (thread_action.state == eStateSuspended &&
1782fcaf7f86SDimitry Andric         tid != StringExtractorGDBRemote::AllThreads) {
1783fcaf7f86SDimitry Andric       return SendIllFormedResponse(
1784fcaf7f86SDimitry Andric           packet, "'t' action not supported for individual threads");
1785fcaf7f86SDimitry Andric     }
1786fcaf7f86SDimitry Andric 
178781ad6265SDimitry Andric     if (pid == StringExtractorGDBRemote::AllProcesses) {
178881ad6265SDimitry Andric       if (m_debugged_processes.size() > 1)
178981ad6265SDimitry Andric         return SendIllFormedResponse(
179081ad6265SDimitry Andric             packet, "Resuming multiple processes not supported yet");
179181ad6265SDimitry Andric       if (!m_continue_process) {
179281ad6265SDimitry Andric         LLDB_LOG(log, "no debugged process");
179381ad6265SDimitry Andric         return SendErrorResponse(0x36);
179481ad6265SDimitry Andric       }
179581ad6265SDimitry Andric       pid = m_continue_process->GetID();
17960b57cec5SDimitry Andric     }
17970b57cec5SDimitry Andric 
179881ad6265SDimitry Andric     if (tid == StringExtractorGDBRemote::AllThreads)
179981ad6265SDimitry Andric       tid = LLDB_INVALID_THREAD_ID;
180081ad6265SDimitry Andric 
180181ad6265SDimitry Andric     thread_action.tid = tid;
180281ad6265SDimitry Andric 
180381ad6265SDimitry Andric     thread_actions[pid].Append(thread_action);
180481ad6265SDimitry Andric   }
180581ad6265SDimitry Andric 
180681ad6265SDimitry Andric   assert(thread_actions.size() >= 1);
180781ad6265SDimitry Andric   if (thread_actions.size() > 1)
180881ad6265SDimitry Andric     return SendIllFormedResponse(
180981ad6265SDimitry Andric         packet, "Resuming multiple processes not supported yet");
181081ad6265SDimitry Andric 
181181ad6265SDimitry Andric   for (std::pair<lldb::pid_t, ResumeActionList> x : thread_actions) {
181281ad6265SDimitry Andric     auto process_it = m_debugged_processes.find(x.first);
181381ad6265SDimitry Andric     if (process_it == m_debugged_processes.end()) {
181481ad6265SDimitry Andric       LLDB_LOG(log, "vCont failed for process {0}: process not debugged",
181581ad6265SDimitry Andric                x.first);
18160b57cec5SDimitry Andric       return SendErrorResponse(GDBRemoteServerError::eErrorResume);
18170b57cec5SDimitry Andric     }
18180b57cec5SDimitry Andric 
1819fcaf7f86SDimitry Andric     // There are four possible scenarios here.  These are:
1820fcaf7f86SDimitry Andric     // 1. vCont on a stopped process that resumes at least one thread.
1821fcaf7f86SDimitry Andric     //    In this case, we call Resume().
1822fcaf7f86SDimitry Andric     // 2. vCont on a stopped process that leaves all threads suspended.
1823fcaf7f86SDimitry Andric     //    A no-op.
1824fcaf7f86SDimitry Andric     // 3. vCont on a running process that requests suspending all
1825fcaf7f86SDimitry Andric     //    running threads.  In this case, we call Interrupt().
1826fcaf7f86SDimitry Andric     // 4. vCont on a running process that requests suspending a subset
1827fcaf7f86SDimitry Andric     //    of running threads or resuming a subset of suspended threads.
1828fcaf7f86SDimitry Andric     //    Since we do not support full nonstop mode, this is unsupported
1829fcaf7f86SDimitry Andric     //    and we return an error.
1830fcaf7f86SDimitry Andric 
1831fcaf7f86SDimitry Andric     assert(process_it->second.process_up);
1832fcaf7f86SDimitry Andric     if (ResumeActionListStopsAllThreads(x.second)) {
1833fcaf7f86SDimitry Andric       if (process_it->second.process_up->IsRunning()) {
1834fcaf7f86SDimitry Andric         assert(m_non_stop);
1835fcaf7f86SDimitry Andric 
1836fcaf7f86SDimitry Andric         Status error = process_it->second.process_up->Interrupt();
183781ad6265SDimitry Andric         if (error.Fail()) {
1838fcaf7f86SDimitry Andric           LLDB_LOG(log, "vCont failed to halt process {0}: {1}", x.first,
1839fcaf7f86SDimitry Andric                    error);
184081ad6265SDimitry Andric           return SendErrorResponse(GDBRemoteServerError::eErrorResume);
184181ad6265SDimitry Andric         }
184281ad6265SDimitry Andric 
1843fcaf7f86SDimitry Andric         LLDB_LOG(log, "halted process {0}", x.first);
1844fcaf7f86SDimitry Andric 
1845fcaf7f86SDimitry Andric         // hack to avoid enabling stdio forwarding after stop
1846fcaf7f86SDimitry Andric         // TODO: remove this when we improve stdio forwarding for nonstop
1847fcaf7f86SDimitry Andric         assert(thread_actions.size() == 1);
1848fcaf7f86SDimitry Andric         return SendOKResponse();
1849fcaf7f86SDimitry Andric       }
1850fcaf7f86SDimitry Andric     } else {
1851fcaf7f86SDimitry Andric       PacketResult resume_res =
1852fcaf7f86SDimitry Andric           ResumeProcess(*process_it->second.process_up, x.second);
1853fcaf7f86SDimitry Andric       if (resume_res != PacketResult::Success)
1854fcaf7f86SDimitry Andric         return resume_res;
1855fcaf7f86SDimitry Andric     }
185681ad6265SDimitry Andric   }
185781ad6265SDimitry Andric 
185881ad6265SDimitry Andric   return SendContinueSuccessResponse();
18590b57cec5SDimitry Andric }
18600b57cec5SDimitry Andric 
18610b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
186281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
18630b57cec5SDimitry Andric   LLDB_LOG(log, "setting current thread id to {0}", tid);
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric   m_current_tid = tid;
1866fe6060f1SDimitry Andric   if (m_current_process)
1867fe6060f1SDimitry Andric     m_current_process->SetCurrentThreadID(m_current_tid);
18680b57cec5SDimitry Andric }
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
187181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
18720b57cec5SDimitry Andric   LLDB_LOG(log, "setting continue thread id to {0}", tid);
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric   m_continue_tid = tid;
18750b57cec5SDimitry Andric }
18760b57cec5SDimitry Andric 
18770b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
18780b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_stop_reason(
18790b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
18800b57cec5SDimitry Andric   // Handle the $? gdbremote command.
18810b57cec5SDimitry Andric 
188281ad6265SDimitry Andric   if (m_non_stop) {
188381ad6265SDimitry Andric     // Clear the notification queue first, except for pending exit
188481ad6265SDimitry Andric     // notifications.
188581ad6265SDimitry Andric     llvm::erase_if(m_stop_notification_queue, [](const std::string &x) {
188681ad6265SDimitry Andric       return x.front() != 'W' && x.front() != 'X';
188781ad6265SDimitry Andric     });
188881ad6265SDimitry Andric 
188981ad6265SDimitry Andric     if (m_current_process) {
189081ad6265SDimitry Andric       // Queue stop reply packets for all active threads.  Start with
189181ad6265SDimitry Andric       // the current thread (for clients that don't actually support multiple
189281ad6265SDimitry Andric       // stop reasons).
189381ad6265SDimitry Andric       NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
1894fcaf7f86SDimitry Andric       if (thread) {
1895fcaf7f86SDimitry Andric         StreamString stop_reply = PrepareStopReplyPacketForThread(*thread);
1896fcaf7f86SDimitry Andric         if (!stop_reply.Empty())
1897fcaf7f86SDimitry Andric           m_stop_notification_queue.push_back(stop_reply.GetString().str());
1898fcaf7f86SDimitry Andric       }
189981ad6265SDimitry Andric       EnqueueStopReplyPackets(thread ? thread->GetID()
190081ad6265SDimitry Andric                                      : LLDB_INVALID_THREAD_ID);
190181ad6265SDimitry Andric     }
190281ad6265SDimitry Andric 
190381ad6265SDimitry Andric     // If the notification queue is empty (i.e. everything is running), send OK.
190481ad6265SDimitry Andric     if (m_stop_notification_queue.empty())
190581ad6265SDimitry Andric       return SendOKResponse();
190681ad6265SDimitry Andric 
190781ad6265SDimitry Andric     // Send the first item from the new notification queue synchronously.
190881ad6265SDimitry Andric     return SendPacketNoLock(m_stop_notification_queue.front());
190981ad6265SDimitry Andric   }
191081ad6265SDimitry Andric 
19110b57cec5SDimitry Andric   // If no process, indicate error
1912fe6060f1SDimitry Andric   if (!m_current_process)
19130b57cec5SDimitry Andric     return SendErrorResponse(02);
19140b57cec5SDimitry Andric 
191581ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
191681ad6265SDimitry Andric                                 m_current_process->GetState(),
191781ad6265SDimitry Andric                                 /*force_synchronous=*/true);
19180b57cec5SDimitry Andric }
19190b57cec5SDimitry Andric 
19200b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
19210b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
192281ad6265SDimitry Andric     NativeProcessProtocol &process, lldb::StateType process_state,
192381ad6265SDimitry Andric     bool force_synchronous) {
192481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
19250b57cec5SDimitry Andric 
1926fcaf7f86SDimitry Andric   if (m_disabling_non_stop) {
1927fcaf7f86SDimitry Andric     // Check if we are waiting for any more processes to stop.  If we are,
1928fcaf7f86SDimitry Andric     // do not send the OK response yet.
1929fcaf7f86SDimitry Andric     for (const auto &it : m_debugged_processes) {
1930fcaf7f86SDimitry Andric       if (it.second.process_up->IsRunning())
1931fcaf7f86SDimitry Andric         return PacketResult::Success;
1932fcaf7f86SDimitry Andric     }
1933fcaf7f86SDimitry Andric 
1934fcaf7f86SDimitry Andric     // If all expected processes were stopped after a QNonStop:0 request,
1935fcaf7f86SDimitry Andric     // send the OK response.
1936fcaf7f86SDimitry Andric     m_disabling_non_stop = false;
1937fcaf7f86SDimitry Andric     return SendOKResponse();
1938fcaf7f86SDimitry Andric   }
1939fcaf7f86SDimitry Andric 
19400b57cec5SDimitry Andric   switch (process_state) {
19410b57cec5SDimitry Andric   case eStateAttaching:
19420b57cec5SDimitry Andric   case eStateLaunching:
19430b57cec5SDimitry Andric   case eStateRunning:
19440b57cec5SDimitry Andric   case eStateStepping:
19450b57cec5SDimitry Andric   case eStateDetached:
19460b57cec5SDimitry Andric     // NOTE: gdb protocol doc looks like it should return $OK
19470b57cec5SDimitry Andric     // when everything is running (i.e. no stopped result).
19480b57cec5SDimitry Andric     return PacketResult::Success; // Ignore
19490b57cec5SDimitry Andric 
19500b57cec5SDimitry Andric   case eStateSuspended:
19510b57cec5SDimitry Andric   case eStateStopped:
19520b57cec5SDimitry Andric   case eStateCrashed: {
195381ad6265SDimitry Andric     lldb::tid_t tid = process.GetCurrentThreadID();
19540b57cec5SDimitry Andric     // Make sure we set the current thread so g and p packets return the data
19550b57cec5SDimitry Andric     // the gdb will expect.
19560b57cec5SDimitry Andric     SetCurrentThreadID(tid);
195781ad6265SDimitry Andric     return SendStopReplyPacketForThread(process, tid, force_synchronous);
19580b57cec5SDimitry Andric   }
19590b57cec5SDimitry Andric 
19600b57cec5SDimitry Andric   case eStateInvalid:
19610b57cec5SDimitry Andric   case eStateUnloaded:
19620b57cec5SDimitry Andric   case eStateExited:
196381ad6265SDimitry Andric     return SendWResponse(&process);
19640b57cec5SDimitry Andric 
19650b57cec5SDimitry Andric   default:
19660b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}",
196781ad6265SDimitry Andric              process.GetID(), process_state);
19680b57cec5SDimitry Andric     break;
19690b57cec5SDimitry Andric   }
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric   return SendErrorResponse(0);
19720b57cec5SDimitry Andric }
19730b57cec5SDimitry Andric 
19740b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
19750b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
19760b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
19770b57cec5SDimitry Andric   // Fail if we don't have a current process.
1978fe6060f1SDimitry Andric   if (!m_current_process ||
1979fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
19800b57cec5SDimitry Andric     return SendErrorResponse(68);
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric   // Ensure we have a thread.
1983fe6060f1SDimitry Andric   NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
19840b57cec5SDimitry Andric   if (!thread)
19850b57cec5SDimitry Andric     return SendErrorResponse(69);
19860b57cec5SDimitry Andric 
19870b57cec5SDimitry Andric   // Get the register context for the first thread.
19880b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
19890b57cec5SDimitry Andric 
19900b57cec5SDimitry Andric   // Parse out the register number from the request.
19910b57cec5SDimitry Andric   packet.SetFilePos(strlen("qRegisterInfo"));
19920b57cec5SDimitry Andric   const uint32_t reg_index =
19930b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
19940b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max())
19950b57cec5SDimitry Andric     return SendErrorResponse(69);
19960b57cec5SDimitry Andric 
19970b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
19980b57cec5SDimitry Andric   // the register set.
19990b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount())
20000b57cec5SDimitry Andric     return SendErrorResponse(69);
20010b57cec5SDimitry Andric 
20020b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
20030b57cec5SDimitry Andric   if (!reg_info)
20040b57cec5SDimitry Andric     return SendErrorResponse(69);
20050b57cec5SDimitry Andric 
20060b57cec5SDimitry Andric   // Build the reginfos response.
20070b57cec5SDimitry Andric   StreamGDBRemote response;
20080b57cec5SDimitry Andric 
20090b57cec5SDimitry Andric   response.PutCString("name:");
20100b57cec5SDimitry Andric   response.PutCString(reg_info->name);
20110b57cec5SDimitry Andric   response.PutChar(';');
20120b57cec5SDimitry Andric 
20130b57cec5SDimitry Andric   if (reg_info->alt_name && reg_info->alt_name[0]) {
20140b57cec5SDimitry Andric     response.PutCString("alt-name:");
20150b57cec5SDimitry Andric     response.PutCString(reg_info->alt_name);
20160b57cec5SDimitry Andric     response.PutChar(';');
20170b57cec5SDimitry Andric   }
20180b57cec5SDimitry Andric 
2019e8d8bef9SDimitry Andric   response.Printf("bitsize:%" PRIu32 ";", reg_info->byte_size * 8);
2020e8d8bef9SDimitry Andric 
2021e8d8bef9SDimitry Andric   if (!reg_context.RegisterOffsetIsDynamic())
2022e8d8bef9SDimitry Andric     response.Printf("offset:%" PRIu32 ";", reg_info->byte_offset);
20230b57cec5SDimitry Andric 
20245ffd83dbSDimitry Andric   llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info);
20255ffd83dbSDimitry Andric   if (!encoding.empty())
20265ffd83dbSDimitry Andric     response << "encoding:" << encoding << ';';
20270b57cec5SDimitry Andric 
20285ffd83dbSDimitry Andric   llvm::StringRef format = GetFormatNameOrEmpty(*reg_info);
20295ffd83dbSDimitry Andric   if (!format.empty())
20305ffd83dbSDimitry Andric     response << "format:" << format << ';';
20310b57cec5SDimitry Andric 
20320b57cec5SDimitry Andric   const char *const register_set_name =
20330b57cec5SDimitry Andric       reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index);
20345ffd83dbSDimitry Andric   if (register_set_name)
20355ffd83dbSDimitry Andric     response << "set:" << register_set_name << ';';
20360b57cec5SDimitry Andric 
20370b57cec5SDimitry Andric   if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
20380b57cec5SDimitry Andric       LLDB_INVALID_REGNUM)
20390b57cec5SDimitry Andric     response.Printf("ehframe:%" PRIu32 ";",
20400b57cec5SDimitry Andric                     reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
20410b57cec5SDimitry Andric 
20420b57cec5SDimitry Andric   if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
20430b57cec5SDimitry Andric     response.Printf("dwarf:%" PRIu32 ";",
20440b57cec5SDimitry Andric                     reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
20450b57cec5SDimitry Andric 
20465ffd83dbSDimitry Andric   llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info);
20475ffd83dbSDimitry Andric   if (!kind_generic.empty())
20485ffd83dbSDimitry Andric     response << "generic:" << kind_generic << ';';
20490b57cec5SDimitry Andric 
20500b57cec5SDimitry Andric   if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
20510b57cec5SDimitry Andric     response.PutCString("container-regs:");
20525ffd83dbSDimitry Andric     CollectRegNums(reg_info->value_regs, response, true);
20530b57cec5SDimitry Andric     response.PutChar(';');
20540b57cec5SDimitry Andric   }
20550b57cec5SDimitry Andric 
20560b57cec5SDimitry Andric   if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
20570b57cec5SDimitry Andric     response.PutCString("invalidate-regs:");
20585ffd83dbSDimitry Andric     CollectRegNums(reg_info->invalidate_regs, response, true);
20590b57cec5SDimitry Andric     response.PutChar(';');
20600b57cec5SDimitry Andric   }
20610b57cec5SDimitry Andric 
20620b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
20630b57cec5SDimitry Andric }
20640b57cec5SDimitry Andric 
206581ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::AddProcessThreads(
206681ad6265SDimitry Andric     StreamGDBRemote &response, NativeProcessProtocol &process, bool &had_any) {
206781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
206881ad6265SDimitry Andric 
206981ad6265SDimitry Andric   lldb::pid_t pid = process.GetID();
207081ad6265SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
207181ad6265SDimitry Andric     return;
207281ad6265SDimitry Andric 
207381ad6265SDimitry Andric   LLDB_LOG(log, "iterating over threads of process {0}", process.GetID());
207481ad6265SDimitry Andric   for (NativeThreadProtocol &thread : process.Threads()) {
207581ad6265SDimitry Andric     LLDB_LOG(log, "iterated thread tid={0}", thread.GetID());
207681ad6265SDimitry Andric     response.PutChar(had_any ? ',' : 'm');
207781ad6265SDimitry Andric     AppendThreadIDToResponse(response, pid, thread.GetID());
207881ad6265SDimitry Andric     had_any = true;
207981ad6265SDimitry Andric   }
208081ad6265SDimitry Andric }
208181ad6265SDimitry Andric 
20820b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
20830b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
20840b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
208581ad6265SDimitry Andric   assert(m_debugged_processes.size() == 1 ||
208681ad6265SDimitry Andric          bool(m_extensions_supported &
208781ad6265SDimitry Andric               NativeProcessProtocol::Extension::multiprocess));
20880b57cec5SDimitry Andric 
208981ad6265SDimitry Andric   bool had_any = false;
20900b57cec5SDimitry Andric   StreamGDBRemote response;
20910b57cec5SDimitry Andric 
209281ad6265SDimitry Andric   for (auto &pid_ptr : m_debugged_processes)
2093fcaf7f86SDimitry Andric     AddProcessThreads(response, *pid_ptr.second.process_up, had_any);
20940b57cec5SDimitry Andric 
209581ad6265SDimitry Andric   if (!had_any)
209681ad6265SDimitry Andric     return SendOKResponse();
20970b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
20980b57cec5SDimitry Andric }
20990b57cec5SDimitry Andric 
21000b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
21010b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo(
21020b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
21030b57cec5SDimitry Andric   // FIXME for now we return the full thread list in the initial packet and
21040b57cec5SDimitry Andric   // always do nothing here.
21050b57cec5SDimitry Andric   return SendPacketNoLock("l");
21060b57cec5SDimitry Andric }
21070b57cec5SDimitry Andric 
21080b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
21090b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) {
211081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
21110b57cec5SDimitry Andric 
21120b57cec5SDimitry Andric   // Move past packet name.
21130b57cec5SDimitry Andric   packet.SetFilePos(strlen("g"));
21140b57cec5SDimitry Andric 
21150b57cec5SDimitry Andric   // Get the thread to use.
21160b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
21170b57cec5SDimitry Andric   if (!thread) {
21180b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no thread available");
21190b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21200b57cec5SDimitry Andric   }
21210b57cec5SDimitry Andric 
21220b57cec5SDimitry Andric   // Get the thread's register context.
21230b57cec5SDimitry Andric   NativeRegisterContext &reg_ctx = thread->GetRegisterContext();
21240b57cec5SDimitry Andric 
21250b57cec5SDimitry Andric   std::vector<uint8_t> regs_buffer;
21260b57cec5SDimitry Andric   for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount();
21270b57cec5SDimitry Andric        ++reg_num) {
21280b57cec5SDimitry Andric     const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num);
21290b57cec5SDimitry Andric 
21300b57cec5SDimitry Andric     if (reg_info == nullptr) {
21310b57cec5SDimitry Andric       LLDB_LOG(log, "failed to get register info for register index {0}",
21320b57cec5SDimitry Andric                reg_num);
21330b57cec5SDimitry Andric       return SendErrorResponse(0x15);
21340b57cec5SDimitry Andric     }
21350b57cec5SDimitry Andric 
21360b57cec5SDimitry Andric     if (reg_info->value_regs != nullptr)
21370b57cec5SDimitry Andric       continue; // skip registers that are contained in other registers
21380b57cec5SDimitry Andric 
21390b57cec5SDimitry Andric     RegisterValue reg_value;
21400b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(reg_info, reg_value);
21410b57cec5SDimitry Andric     if (error.Fail()) {
21420b57cec5SDimitry Andric       LLDB_LOG(log, "failed to read register at index {0}", reg_num);
21430b57cec5SDimitry Andric       return SendErrorResponse(0x15);
21440b57cec5SDimitry Andric     }
21450b57cec5SDimitry Andric 
21460b57cec5SDimitry Andric     if (reg_info->byte_offset + reg_info->byte_size >= regs_buffer.size())
21470b57cec5SDimitry Andric       // Resize the buffer to guarantee it can store the register offsetted
21480b57cec5SDimitry Andric       // data.
21490b57cec5SDimitry Andric       regs_buffer.resize(reg_info->byte_offset + reg_info->byte_size);
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric     // Copy the register offsetted data to the buffer.
21520b57cec5SDimitry Andric     memcpy(regs_buffer.data() + reg_info->byte_offset, reg_value.GetBytes(),
21530b57cec5SDimitry Andric            reg_info->byte_size);
21540b57cec5SDimitry Andric   }
21550b57cec5SDimitry Andric 
21560b57cec5SDimitry Andric   // Write the response.
21570b57cec5SDimitry Andric   StreamGDBRemote response;
21580b57cec5SDimitry Andric   response.PutBytesAsRawHex8(regs_buffer.data(), regs_buffer.size());
21590b57cec5SDimitry Andric 
21600b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
21610b57cec5SDimitry Andric }
21620b57cec5SDimitry Andric 
21630b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
21640b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
216581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
21660b57cec5SDimitry Andric 
21670b57cec5SDimitry Andric   // Parse out the register number from the request.
21680b57cec5SDimitry Andric   packet.SetFilePos(strlen("p"));
21690b57cec5SDimitry Andric   const uint32_t reg_index =
21700b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
21710b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max()) {
21729dba64beSDimitry Andric     LLDB_LOGF(log,
21739dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
21740b57cec5SDimitry Andric               "parse register number from request \"%s\"",
21759dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
21760b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21770b57cec5SDimitry Andric   }
21780b57cec5SDimitry Andric 
21790b57cec5SDimitry Andric   // Get the thread to use.
21800b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
21810b57cec5SDimitry Andric   if (!thread) {
21820b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no thread available");
21830b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21840b57cec5SDimitry Andric   }
21850b57cec5SDimitry Andric 
21860b57cec5SDimitry Andric   // Get the thread's register context.
21870b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
21880b57cec5SDimitry Andric 
21890b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
21900b57cec5SDimitry Andric   // the register set.
21910b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount()) {
21929dba64beSDimitry Andric     LLDB_LOGF(log,
21939dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
21940b57cec5SDimitry Andric               "register %" PRIu32 " beyond register count %" PRIu32,
21959dba64beSDimitry Andric               __FUNCTION__, reg_index, reg_context.GetUserRegisterCount());
21960b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21970b57cec5SDimitry Andric   }
21980b57cec5SDimitry Andric 
21990b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
22000b57cec5SDimitry Andric   if (!reg_info) {
22019dba64beSDimitry Andric     LLDB_LOGF(log,
22029dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
22030b57cec5SDimitry Andric               "register %" PRIu32 " returned NULL",
22040b57cec5SDimitry Andric               __FUNCTION__, reg_index);
22050b57cec5SDimitry Andric     return SendErrorResponse(0x15);
22060b57cec5SDimitry Andric   }
22070b57cec5SDimitry Andric 
22080b57cec5SDimitry Andric   // Build the reginfos response.
22090b57cec5SDimitry Andric   StreamGDBRemote response;
22100b57cec5SDimitry Andric 
22110b57cec5SDimitry Andric   // Retrieve the value
22120b57cec5SDimitry Andric   RegisterValue reg_value;
22130b57cec5SDimitry Andric   Status error = reg_context.ReadRegister(reg_info, reg_value);
22140b57cec5SDimitry Andric   if (error.Fail()) {
22159dba64beSDimitry Andric     LLDB_LOGF(log,
22169dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, read of "
22170b57cec5SDimitry Andric               "requested register %" PRIu32 " (%s) failed: %s",
22180b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_info->name, error.AsCString());
22190b57cec5SDimitry Andric     return SendErrorResponse(0x15);
22200b57cec5SDimitry Andric   }
22210b57cec5SDimitry Andric 
22220b57cec5SDimitry Andric   const uint8_t *const data =
2223480093f4SDimitry Andric       static_cast<const uint8_t *>(reg_value.GetBytes());
22240b57cec5SDimitry Andric   if (!data) {
22259dba64beSDimitry Andric     LLDB_LOGF(log,
22269dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to get data "
22270b57cec5SDimitry Andric               "bytes from requested register %" PRIu32,
22280b57cec5SDimitry Andric               __FUNCTION__, reg_index);
22290b57cec5SDimitry Andric     return SendErrorResponse(0x15);
22300b57cec5SDimitry Andric   }
22310b57cec5SDimitry Andric 
22320b57cec5SDimitry Andric   // FIXME flip as needed to get data in big/little endian format for this host.
22330b57cec5SDimitry Andric   for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i)
22340b57cec5SDimitry Andric     response.PutHex8(data[i]);
22350b57cec5SDimitry Andric 
22360b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
22370b57cec5SDimitry Andric }
22380b57cec5SDimitry Andric 
22390b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
22400b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
224181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
22420b57cec5SDimitry Andric 
22430b57cec5SDimitry Andric   // Ensure there is more content.
22440b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
22450b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Empty P packet");
22460b57cec5SDimitry Andric 
22470b57cec5SDimitry Andric   // Parse out the register number from the request.
22480b57cec5SDimitry Andric   packet.SetFilePos(strlen("P"));
22490b57cec5SDimitry Andric   const uint32_t reg_index =
22500b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
22510b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max()) {
22529dba64beSDimitry Andric     LLDB_LOGF(log,
22539dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
22540b57cec5SDimitry Andric               "parse register number from request \"%s\"",
22559dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
22560b57cec5SDimitry Andric     return SendErrorResponse(0x29);
22570b57cec5SDimitry Andric   }
22580b57cec5SDimitry Andric 
22590b57cec5SDimitry Andric   // Note debugserver would send an E30 here.
22600b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '='))
22610b57cec5SDimitry Andric     return SendIllFormedResponse(
22620b57cec5SDimitry Andric         packet, "P packet missing '=' char after register number");
22630b57cec5SDimitry Andric 
22640b57cec5SDimitry Andric   // Parse out the value.
22655ffd83dbSDimitry Andric   uint8_t reg_bytes[RegisterValue::kMaxRegisterByteSize];
22660b57cec5SDimitry Andric   size_t reg_size = packet.GetHexBytesAvail(reg_bytes);
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric   // Get the thread to use.
22690b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
22700b57cec5SDimitry Andric   if (!thread) {
22719dba64beSDimitry Andric     LLDB_LOGF(log,
22729dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, no thread "
22730b57cec5SDimitry Andric               "available (thread index 0)",
22740b57cec5SDimitry Andric               __FUNCTION__);
22750b57cec5SDimitry Andric     return SendErrorResponse(0x28);
22760b57cec5SDimitry Andric   }
22770b57cec5SDimitry Andric 
22780b57cec5SDimitry Andric   // Get the thread's register context.
22790b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
22800b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
22810b57cec5SDimitry Andric   if (!reg_info) {
22829dba64beSDimitry Andric     LLDB_LOGF(log,
22839dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
22840b57cec5SDimitry Andric               "register %" PRIu32 " returned NULL",
22850b57cec5SDimitry Andric               __FUNCTION__, reg_index);
22860b57cec5SDimitry Andric     return SendErrorResponse(0x48);
22870b57cec5SDimitry Andric   }
22880b57cec5SDimitry Andric 
22890b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
22900b57cec5SDimitry Andric   // the register set.
22910b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount()) {
22929dba64beSDimitry Andric     LLDB_LOGF(log,
22939dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
22940b57cec5SDimitry Andric               "register %" PRIu32 " beyond register count %" PRIu32,
22950b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_context.GetUserRegisterCount());
22960b57cec5SDimitry Andric     return SendErrorResponse(0x47);
22970b57cec5SDimitry Andric   }
22980b57cec5SDimitry Andric 
2299349cc55cSDimitry Andric   if (reg_size != reg_info->byte_size)
23000b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "P packet register size is incorrect");
23010b57cec5SDimitry Andric 
23020b57cec5SDimitry Andric   // Build the reginfos response.
23030b57cec5SDimitry Andric   StreamGDBRemote response;
23040b57cec5SDimitry Andric 
2305fe6060f1SDimitry Andric   RegisterValue reg_value(makeArrayRef(reg_bytes, reg_size),
2306fe6060f1SDimitry Andric                           m_current_process->GetArchitecture().GetByteOrder());
23070b57cec5SDimitry Andric   Status error = reg_context.WriteRegister(reg_info, reg_value);
23080b57cec5SDimitry Andric   if (error.Fail()) {
23099dba64beSDimitry Andric     LLDB_LOGF(log,
23109dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, write of "
23110b57cec5SDimitry Andric               "requested register %" PRIu32 " (%s) failed: %s",
23120b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_info->name, error.AsCString());
23130b57cec5SDimitry Andric     return SendErrorResponse(0x32);
23140b57cec5SDimitry Andric   }
23150b57cec5SDimitry Andric 
23160b57cec5SDimitry Andric   return SendOKResponse();
23170b57cec5SDimitry Andric }
23180b57cec5SDimitry Andric 
23190b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
23200b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
232181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric   // Parse out which variant of $H is requested.
23240b57cec5SDimitry Andric   packet.SetFilePos(strlen("H"));
23250b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1) {
23269dba64beSDimitry Andric     LLDB_LOGF(log,
23279dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, H command "
23280b57cec5SDimitry Andric               "missing {g,c} variant",
23290b57cec5SDimitry Andric               __FUNCTION__);
23300b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "H command missing {g,c} variant");
23310b57cec5SDimitry Andric   }
23320b57cec5SDimitry Andric 
23330b57cec5SDimitry Andric   const char h_variant = packet.GetChar();
2334fe6060f1SDimitry Andric   NativeProcessProtocol *default_process;
23350b57cec5SDimitry Andric   switch (h_variant) {
23360b57cec5SDimitry Andric   case 'g':
2337fe6060f1SDimitry Andric     default_process = m_current_process;
23380b57cec5SDimitry Andric     break;
23390b57cec5SDimitry Andric 
23400b57cec5SDimitry Andric   case 'c':
2341fe6060f1SDimitry Andric     default_process = m_continue_process;
23420b57cec5SDimitry Andric     break;
23430b57cec5SDimitry Andric 
23440b57cec5SDimitry Andric   default:
23459dba64beSDimitry Andric     LLDB_LOGF(
23469dba64beSDimitry Andric         log,
23470b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c",
23480b57cec5SDimitry Andric         __FUNCTION__, h_variant);
23490b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
23500b57cec5SDimitry Andric                                  "H variant unsupported, should be c or g");
23510b57cec5SDimitry Andric   }
23520b57cec5SDimitry Andric 
23530b57cec5SDimitry Andric   // Parse out the thread number.
2354fe6060f1SDimitry Andric   auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID()
2355fe6060f1SDimitry Andric                                                   : LLDB_INVALID_PROCESS_ID);
2356fe6060f1SDimitry Andric   if (!pid_tid)
2357fe6060f1SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
2358fe6060f1SDimitry Andric         inconvertibleErrorCode(), "Malformed thread-id"));
2359fe6060f1SDimitry Andric 
2360fe6060f1SDimitry Andric   lldb::pid_t pid = pid_tid->first;
2361fe6060f1SDimitry Andric   lldb::tid_t tid = pid_tid->second;
2362fe6060f1SDimitry Andric 
2363fe6060f1SDimitry Andric   if (pid == StringExtractorGDBRemote::AllProcesses)
2364fe6060f1SDimitry Andric     return SendUnimplementedResponse("Selecting all processes not supported");
2365fe6060f1SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
2366fe6060f1SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
2367fe6060f1SDimitry Andric         inconvertibleErrorCode(), "No current process and no PID provided"));
2368fe6060f1SDimitry Andric 
2369fe6060f1SDimitry Andric   // Check the process ID and find respective process instance.
2370fe6060f1SDimitry Andric   auto new_process_it = m_debugged_processes.find(pid);
2371fe6060f1SDimitry Andric   if (new_process_it == m_debugged_processes.end())
2372fe6060f1SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
2373fe6060f1SDimitry Andric         inconvertibleErrorCode(),
2374fe6060f1SDimitry Andric         llvm::formatv("No process with PID {0} debugged", pid)));
23750b57cec5SDimitry Andric 
23760b57cec5SDimitry Andric   // Ensure we have the given thread when not specifying -1 (all threads) or 0
23770b57cec5SDimitry Andric   // (any thread).
23780b57cec5SDimitry Andric   if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
2379fcaf7f86SDimitry Andric     NativeThreadProtocol *thread =
2380fcaf7f86SDimitry Andric         new_process_it->second.process_up->GetThreadByID(tid);
23810b57cec5SDimitry Andric     if (!thread) {
23829dba64beSDimitry Andric       LLDB_LOGF(log,
23839dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
23840b57cec5SDimitry Andric                 " not found",
23850b57cec5SDimitry Andric                 __FUNCTION__, tid);
23860b57cec5SDimitry Andric       return SendErrorResponse(0x15);
23870b57cec5SDimitry Andric     }
23880b57cec5SDimitry Andric   }
23890b57cec5SDimitry Andric 
2390fe6060f1SDimitry Andric   // Now switch the given process and thread type.
23910b57cec5SDimitry Andric   switch (h_variant) {
23920b57cec5SDimitry Andric   case 'g':
2393fcaf7f86SDimitry Andric     m_current_process = new_process_it->second.process_up.get();
23940b57cec5SDimitry Andric     SetCurrentThreadID(tid);
23950b57cec5SDimitry Andric     break;
23960b57cec5SDimitry Andric 
23970b57cec5SDimitry Andric   case 'c':
2398fcaf7f86SDimitry Andric     m_continue_process = new_process_it->second.process_up.get();
23990b57cec5SDimitry Andric     SetContinueThreadID(tid);
24000b57cec5SDimitry Andric     break;
24010b57cec5SDimitry Andric 
24020b57cec5SDimitry Andric   default:
24030b57cec5SDimitry Andric     assert(false && "unsupported $H variant - shouldn't get here");
24040b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
24050b57cec5SDimitry Andric                                  "H variant unsupported, should be c or g");
24060b57cec5SDimitry Andric   }
24070b57cec5SDimitry Andric 
24080b57cec5SDimitry Andric   return SendOKResponse();
24090b57cec5SDimitry Andric }
24100b57cec5SDimitry Andric 
24110b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
24120b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
241381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
24140b57cec5SDimitry Andric 
24150b57cec5SDimitry Andric   // Fail if we don't have a current process.
2416fe6060f1SDimitry Andric   if (!m_current_process ||
2417fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
24189dba64beSDimitry Andric     LLDB_LOGF(
24199dba64beSDimitry Andric         log,
24200b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
24210b57cec5SDimitry Andric         __FUNCTION__);
24220b57cec5SDimitry Andric     return SendErrorResponse(0x15);
24230b57cec5SDimitry Andric   }
24240b57cec5SDimitry Andric 
24250b57cec5SDimitry Andric   packet.SetFilePos(::strlen("I"));
24260b57cec5SDimitry Andric   uint8_t tmp[4096];
24270b57cec5SDimitry Andric   for (;;) {
24280b57cec5SDimitry Andric     size_t read = packet.GetHexBytesAvail(tmp);
24290b57cec5SDimitry Andric     if (read == 0) {
24300b57cec5SDimitry Andric       break;
24310b57cec5SDimitry Andric     }
24320b57cec5SDimitry Andric     // write directly to stdin *this might block if stdin buffer is full*
24330b57cec5SDimitry Andric     // TODO: enqueue this block in circular buffer and send window size to
24340b57cec5SDimitry Andric     // remote host
24350b57cec5SDimitry Andric     ConnectionStatus status;
24360b57cec5SDimitry Andric     Status error;
24370b57cec5SDimitry Andric     m_stdio_communication.Write(tmp, read, status, &error);
24380b57cec5SDimitry Andric     if (error.Fail()) {
24390b57cec5SDimitry Andric       return SendErrorResponse(0x15);
24400b57cec5SDimitry Andric     }
24410b57cec5SDimitry Andric   }
24420b57cec5SDimitry Andric 
24430b57cec5SDimitry Andric   return SendOKResponse();
24440b57cec5SDimitry Andric }
24450b57cec5SDimitry Andric 
24460b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
24470b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_interrupt(
24480b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
244981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
24500b57cec5SDimitry Andric 
24510b57cec5SDimitry Andric   // Fail if we don't have a current process.
2452fe6060f1SDimitry Andric   if (!m_current_process ||
2453fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
24540b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
24550b57cec5SDimitry Andric     return SendErrorResponse(0x15);
24560b57cec5SDimitry Andric   }
24570b57cec5SDimitry Andric 
24580b57cec5SDimitry Andric   // Interrupt the process.
2459fe6060f1SDimitry Andric   Status error = m_current_process->Interrupt();
24600b57cec5SDimitry Andric   if (error.Fail()) {
2461fe6060f1SDimitry Andric     LLDB_LOG(log, "failed for process {0}: {1}", m_current_process->GetID(),
24620b57cec5SDimitry Andric              error);
24630b57cec5SDimitry Andric     return SendErrorResponse(GDBRemoteServerError::eErrorResume);
24640b57cec5SDimitry Andric   }
24650b57cec5SDimitry Andric 
2466fe6060f1SDimitry Andric   LLDB_LOG(log, "stopped process {0}", m_current_process->GetID());
24670b57cec5SDimitry Andric 
24680b57cec5SDimitry Andric   // No response required from stop all.
24690b57cec5SDimitry Andric   return PacketResult::Success;
24700b57cec5SDimitry Andric }
24710b57cec5SDimitry Andric 
24720b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
24730b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_memory_read(
24740b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
247581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
24760b57cec5SDimitry Andric 
2477fe6060f1SDimitry Andric   if (!m_current_process ||
2478fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
24799dba64beSDimitry Andric     LLDB_LOGF(
24809dba64beSDimitry Andric         log,
24810b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
24820b57cec5SDimitry Andric         __FUNCTION__);
24830b57cec5SDimitry Andric     return SendErrorResponse(0x15);
24840b57cec5SDimitry Andric   }
24850b57cec5SDimitry Andric 
24860b57cec5SDimitry Andric   // Parse out the memory address.
24870b57cec5SDimitry Andric   packet.SetFilePos(strlen("m"));
24880b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
24890b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short m packet");
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric   // Read the address.  Punting on validation.
24920b57cec5SDimitry Andric   // FIXME replace with Hex U64 read with no default value that fails on failed
24930b57cec5SDimitry Andric   // read.
24940b57cec5SDimitry Andric   const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
24950b57cec5SDimitry Andric 
24960b57cec5SDimitry Andric   // Validate comma.
24970b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
24980b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Comma sep missing in m packet");
24990b57cec5SDimitry Andric 
25000b57cec5SDimitry Andric   // Get # bytes to read.
25010b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
25020b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Length missing in m packet");
25030b57cec5SDimitry Andric 
25040b57cec5SDimitry Andric   const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
25050b57cec5SDimitry Andric   if (byte_count == 0) {
25069dba64beSDimitry Andric     LLDB_LOGF(log,
25079dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s nothing to read: "
25080b57cec5SDimitry Andric               "zero-length packet",
25090b57cec5SDimitry Andric               __FUNCTION__);
25100b57cec5SDimitry Andric     return SendOKResponse();
25110b57cec5SDimitry Andric   }
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric   // Allocate the response buffer.
25140b57cec5SDimitry Andric   std::string buf(byte_count, '\0');
25150b57cec5SDimitry Andric   if (buf.empty())
25160b57cec5SDimitry Andric     return SendErrorResponse(0x78);
25170b57cec5SDimitry Andric 
25180b57cec5SDimitry Andric   // Retrieve the process memory.
25190b57cec5SDimitry Andric   size_t bytes_read = 0;
2520fe6060f1SDimitry Andric   Status error = m_current_process->ReadMemoryWithoutTrap(
25210b57cec5SDimitry Andric       read_addr, &buf[0], byte_count, bytes_read);
25220b57cec5SDimitry Andric   if (error.Fail()) {
25239dba64beSDimitry Andric     LLDB_LOGF(log,
25249dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
25250b57cec5SDimitry Andric               " mem 0x%" PRIx64 ": failed to read. Error: %s",
2526fe6060f1SDimitry Andric               __FUNCTION__, m_current_process->GetID(), read_addr,
25270b57cec5SDimitry Andric               error.AsCString());
25280b57cec5SDimitry Andric     return SendErrorResponse(0x08);
25290b57cec5SDimitry Andric   }
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric   if (bytes_read == 0) {
25329dba64beSDimitry Andric     LLDB_LOGF(log,
25339dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
25340b57cec5SDimitry Andric               " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes",
2535fe6060f1SDimitry Andric               __FUNCTION__, m_current_process->GetID(), read_addr, byte_count);
25360b57cec5SDimitry Andric     return SendErrorResponse(0x08);
25370b57cec5SDimitry Andric   }
25380b57cec5SDimitry Andric 
25390b57cec5SDimitry Andric   StreamGDBRemote response;
25400b57cec5SDimitry Andric   packet.SetFilePos(0);
25410b57cec5SDimitry Andric   char kind = packet.GetChar('?');
25420b57cec5SDimitry Andric   if (kind == 'x')
25430b57cec5SDimitry Andric     response.PutEscapedBytes(buf.data(), byte_count);
25440b57cec5SDimitry Andric   else {
25450b57cec5SDimitry Andric     assert(kind == 'm');
25460b57cec5SDimitry Andric     for (size_t i = 0; i < bytes_read; ++i)
25470b57cec5SDimitry Andric       response.PutHex8(buf[i]);
25480b57cec5SDimitry Andric   }
25490b57cec5SDimitry Andric 
25500b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
25510b57cec5SDimitry Andric }
25520b57cec5SDimitry Andric 
25530b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
2554e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
255581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
2556e8d8bef9SDimitry Andric 
2557fe6060f1SDimitry Andric   if (!m_current_process ||
2558fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
2559e8d8bef9SDimitry Andric     LLDB_LOGF(
2560e8d8bef9SDimitry Andric         log,
2561e8d8bef9SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
2562e8d8bef9SDimitry Andric         __FUNCTION__);
2563e8d8bef9SDimitry Andric     return SendErrorResponse(0x15);
2564e8d8bef9SDimitry Andric   }
2565e8d8bef9SDimitry Andric 
2566e8d8bef9SDimitry Andric   // Parse out the memory address.
2567e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("_M"));
2568e8d8bef9SDimitry Andric   if (packet.GetBytesLeft() < 1)
2569e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Too short _M packet");
2570e8d8bef9SDimitry Andric 
2571e8d8bef9SDimitry Andric   const lldb::addr_t size = packet.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
2572e8d8bef9SDimitry Andric   if (size == LLDB_INVALID_ADDRESS)
2573e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Address not valid");
2574e8d8bef9SDimitry Andric   if (packet.GetChar() != ',')
2575e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Bad packet");
2576e8d8bef9SDimitry Andric   Permissions perms = {};
2577e8d8bef9SDimitry Andric   while (packet.GetBytesLeft() > 0) {
2578e8d8bef9SDimitry Andric     switch (packet.GetChar()) {
2579e8d8bef9SDimitry Andric     case 'r':
2580e8d8bef9SDimitry Andric       perms |= ePermissionsReadable;
2581e8d8bef9SDimitry Andric       break;
2582e8d8bef9SDimitry Andric     case 'w':
2583e8d8bef9SDimitry Andric       perms |= ePermissionsWritable;
2584e8d8bef9SDimitry Andric       break;
2585e8d8bef9SDimitry Andric     case 'x':
2586e8d8bef9SDimitry Andric       perms |= ePermissionsExecutable;
2587e8d8bef9SDimitry Andric       break;
2588e8d8bef9SDimitry Andric     default:
2589e8d8bef9SDimitry Andric       return SendIllFormedResponse(packet, "Bad permissions");
2590e8d8bef9SDimitry Andric     }
2591e8d8bef9SDimitry Andric   }
2592e8d8bef9SDimitry Andric 
2593fe6060f1SDimitry Andric   llvm::Expected<addr_t> addr = m_current_process->AllocateMemory(size, perms);
2594e8d8bef9SDimitry Andric   if (!addr)
2595e8d8bef9SDimitry Andric     return SendErrorResponse(addr.takeError());
2596e8d8bef9SDimitry Andric 
2597e8d8bef9SDimitry Andric   StreamGDBRemote response;
2598e8d8bef9SDimitry Andric   response.PutHex64(*addr);
2599e8d8bef9SDimitry Andric   return SendPacketNoLock(response.GetString());
2600e8d8bef9SDimitry Andric }
2601e8d8bef9SDimitry Andric 
2602e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
2603e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
260481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
2605e8d8bef9SDimitry Andric 
2606fe6060f1SDimitry Andric   if (!m_current_process ||
2607fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
2608e8d8bef9SDimitry Andric     LLDB_LOGF(
2609e8d8bef9SDimitry Andric         log,
2610e8d8bef9SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
2611e8d8bef9SDimitry Andric         __FUNCTION__);
2612e8d8bef9SDimitry Andric     return SendErrorResponse(0x15);
2613e8d8bef9SDimitry Andric   }
2614e8d8bef9SDimitry Andric 
2615e8d8bef9SDimitry Andric   // Parse out the memory address.
2616e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("_m"));
2617e8d8bef9SDimitry Andric   if (packet.GetBytesLeft() < 1)
2618e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Too short m packet");
2619e8d8bef9SDimitry Andric 
2620e8d8bef9SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
2621e8d8bef9SDimitry Andric   if (addr == LLDB_INVALID_ADDRESS)
2622e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Address not valid");
2623e8d8bef9SDimitry Andric 
2624fe6060f1SDimitry Andric   if (llvm::Error Err = m_current_process->DeallocateMemory(addr))
2625e8d8bef9SDimitry Andric     return SendErrorResponse(std::move(Err));
2626e8d8bef9SDimitry Andric 
2627e8d8bef9SDimitry Andric   return SendOKResponse();
2628e8d8bef9SDimitry Andric }
2629e8d8bef9SDimitry Andric 
2630e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
26310b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
263281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
26330b57cec5SDimitry Andric 
2634fe6060f1SDimitry Andric   if (!m_current_process ||
2635fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
26369dba64beSDimitry Andric     LLDB_LOGF(
26379dba64beSDimitry Andric         log,
26380b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
26390b57cec5SDimitry Andric         __FUNCTION__);
26400b57cec5SDimitry Andric     return SendErrorResponse(0x15);
26410b57cec5SDimitry Andric   }
26420b57cec5SDimitry Andric 
26430b57cec5SDimitry Andric   // Parse out the memory address.
26440b57cec5SDimitry Andric   packet.SetFilePos(strlen("M"));
26450b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
26460b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short M packet");
26470b57cec5SDimitry Andric 
26480b57cec5SDimitry Andric   // Read the address.  Punting on validation.
26490b57cec5SDimitry Andric   // FIXME replace with Hex U64 read with no default value that fails on failed
26500b57cec5SDimitry Andric   // read.
26510b57cec5SDimitry Andric   const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0);
26520b57cec5SDimitry Andric 
26530b57cec5SDimitry Andric   // Validate comma.
26540b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
26550b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Comma sep missing in M packet");
26560b57cec5SDimitry Andric 
26570b57cec5SDimitry Andric   // Get # bytes to read.
26580b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
26590b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Length missing in M packet");
26600b57cec5SDimitry Andric 
26610b57cec5SDimitry Andric   const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
26620b57cec5SDimitry Andric   if (byte_count == 0) {
26630b57cec5SDimitry Andric     LLDB_LOG(log, "nothing to write: zero-length packet");
26640b57cec5SDimitry Andric     return PacketResult::Success;
26650b57cec5SDimitry Andric   }
26660b57cec5SDimitry Andric 
26670b57cec5SDimitry Andric   // Validate colon.
26680b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':'))
26690b57cec5SDimitry Andric     return SendIllFormedResponse(
26700b57cec5SDimitry Andric         packet, "Comma sep missing in M packet after byte length");
26710b57cec5SDimitry Andric 
26720b57cec5SDimitry Andric   // Allocate the conversion buffer.
26730b57cec5SDimitry Andric   std::vector<uint8_t> buf(byte_count, 0);
26740b57cec5SDimitry Andric   if (buf.empty())
26750b57cec5SDimitry Andric     return SendErrorResponse(0x78);
26760b57cec5SDimitry Andric 
26770b57cec5SDimitry Andric   // Convert the hex memory write contents to bytes.
26780b57cec5SDimitry Andric   StreamGDBRemote response;
26790b57cec5SDimitry Andric   const uint64_t convert_count = packet.GetHexBytes(buf, 0);
26800b57cec5SDimitry Andric   if (convert_count != byte_count) {
26810b57cec5SDimitry Andric     LLDB_LOG(log,
26820b57cec5SDimitry Andric              "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} "
26830b57cec5SDimitry Andric              "to convert.",
2684fe6060f1SDimitry Andric              m_current_process->GetID(), write_addr, byte_count, convert_count);
26850b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "M content byte length specified did "
26860b57cec5SDimitry Andric                                          "not match hex-encoded content "
26870b57cec5SDimitry Andric                                          "length");
26880b57cec5SDimitry Andric   }
26890b57cec5SDimitry Andric 
26900b57cec5SDimitry Andric   // Write the process memory.
26910b57cec5SDimitry Andric   size_t bytes_written = 0;
2692fe6060f1SDimitry Andric   Status error = m_current_process->WriteMemory(write_addr, &buf[0], byte_count,
2693fe6060f1SDimitry Andric                                                 bytes_written);
26940b57cec5SDimitry Andric   if (error.Fail()) {
26950b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}",
2696fe6060f1SDimitry Andric              m_current_process->GetID(), write_addr, error);
26970b57cec5SDimitry Andric     return SendErrorResponse(0x09);
26980b57cec5SDimitry Andric   }
26990b57cec5SDimitry Andric 
27000b57cec5SDimitry Andric   if (bytes_written == 0) {
27010b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes",
2702fe6060f1SDimitry Andric              m_current_process->GetID(), write_addr, byte_count);
27030b57cec5SDimitry Andric     return SendErrorResponse(0x09);
27040b57cec5SDimitry Andric   }
27050b57cec5SDimitry Andric 
27060b57cec5SDimitry Andric   return SendOKResponse();
27070b57cec5SDimitry Andric }
27080b57cec5SDimitry Andric 
27090b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
27100b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
27110b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
271281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
27130b57cec5SDimitry Andric 
27140b57cec5SDimitry Andric   // Currently only the NativeProcessProtocol knows if it can handle a
27150b57cec5SDimitry Andric   // qMemoryRegionInfoSupported request, but we're not guaranteed to be
27160b57cec5SDimitry Andric   // attached to a process.  For now we'll assume the client only asks this
27170b57cec5SDimitry Andric   // when a process is being debugged.
27180b57cec5SDimitry Andric 
27190b57cec5SDimitry Andric   // Ensure we have a process running; otherwise, we can't figure this out
27200b57cec5SDimitry Andric   // since we won't have a NativeProcessProtocol.
2721fe6060f1SDimitry Andric   if (!m_current_process ||
2722fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
27239dba64beSDimitry Andric     LLDB_LOGF(
27249dba64beSDimitry Andric         log,
27250b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
27260b57cec5SDimitry Andric         __FUNCTION__);
27270b57cec5SDimitry Andric     return SendErrorResponse(0x15);
27280b57cec5SDimitry Andric   }
27290b57cec5SDimitry Andric 
27300b57cec5SDimitry Andric   // Test if we can get any region back when asking for the region around NULL.
27310b57cec5SDimitry Andric   MemoryRegionInfo region_info;
2732fe6060f1SDimitry Andric   const Status error = m_current_process->GetMemoryRegionInfo(0, region_info);
27330b57cec5SDimitry Andric   if (error.Fail()) {
27340b57cec5SDimitry Andric     // We don't support memory region info collection for this
27350b57cec5SDimitry Andric     // NativeProcessProtocol.
27360b57cec5SDimitry Andric     return SendUnimplementedResponse("");
27370b57cec5SDimitry Andric   }
27380b57cec5SDimitry Andric 
27390b57cec5SDimitry Andric   return SendOKResponse();
27400b57cec5SDimitry Andric }
27410b57cec5SDimitry Andric 
27420b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
27430b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
27440b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
274581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
27460b57cec5SDimitry Andric 
27470b57cec5SDimitry Andric   // Ensure we have a process.
2748fe6060f1SDimitry Andric   if (!m_current_process ||
2749fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
27509dba64beSDimitry Andric     LLDB_LOGF(
27519dba64beSDimitry Andric         log,
27520b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
27530b57cec5SDimitry Andric         __FUNCTION__);
27540b57cec5SDimitry Andric     return SendErrorResponse(0x15);
27550b57cec5SDimitry Andric   }
27560b57cec5SDimitry Andric 
27570b57cec5SDimitry Andric   // Parse out the memory address.
27580b57cec5SDimitry Andric   packet.SetFilePos(strlen("qMemoryRegionInfo:"));
27590b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
27600b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet");
27610b57cec5SDimitry Andric 
27620b57cec5SDimitry Andric   // Read the address.  Punting on validation.
27630b57cec5SDimitry Andric   const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
27640b57cec5SDimitry Andric 
27650b57cec5SDimitry Andric   StreamGDBRemote response;
27660b57cec5SDimitry Andric 
27670b57cec5SDimitry Andric   // Get the memory region info for the target address.
27680b57cec5SDimitry Andric   MemoryRegionInfo region_info;
27690b57cec5SDimitry Andric   const Status error =
2770fe6060f1SDimitry Andric       m_current_process->GetMemoryRegionInfo(read_addr, region_info);
27710b57cec5SDimitry Andric   if (error.Fail()) {
27720b57cec5SDimitry Andric     // Return the error message.
27730b57cec5SDimitry Andric 
27740b57cec5SDimitry Andric     response.PutCString("error:");
27750b57cec5SDimitry Andric     response.PutStringAsRawHex8(error.AsCString());
27760b57cec5SDimitry Andric     response.PutChar(';');
27770b57cec5SDimitry Andric   } else {
27780b57cec5SDimitry Andric     // Range start and size.
27790b57cec5SDimitry Andric     response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";",
27800b57cec5SDimitry Andric                     region_info.GetRange().GetRangeBase(),
27810b57cec5SDimitry Andric                     region_info.GetRange().GetByteSize());
27820b57cec5SDimitry Andric 
27830b57cec5SDimitry Andric     // Permissions.
27840b57cec5SDimitry Andric     if (region_info.GetReadable() || region_info.GetWritable() ||
27850b57cec5SDimitry Andric         region_info.GetExecutable()) {
27860b57cec5SDimitry Andric       // Write permissions info.
27870b57cec5SDimitry Andric       response.PutCString("permissions:");
27880b57cec5SDimitry Andric 
27890b57cec5SDimitry Andric       if (region_info.GetReadable())
27900b57cec5SDimitry Andric         response.PutChar('r');
27910b57cec5SDimitry Andric       if (region_info.GetWritable())
27920b57cec5SDimitry Andric         response.PutChar('w');
27930b57cec5SDimitry Andric       if (region_info.GetExecutable())
27940b57cec5SDimitry Andric         response.PutChar('x');
27950b57cec5SDimitry Andric 
27960b57cec5SDimitry Andric       response.PutChar(';');
27970b57cec5SDimitry Andric     }
27980b57cec5SDimitry Andric 
2799e8d8bef9SDimitry Andric     // Flags
2800e8d8bef9SDimitry Andric     MemoryRegionInfo::OptionalBool memory_tagged =
2801e8d8bef9SDimitry Andric         region_info.GetMemoryTagged();
2802e8d8bef9SDimitry Andric     if (memory_tagged != MemoryRegionInfo::eDontKnow) {
2803e8d8bef9SDimitry Andric       response.PutCString("flags:");
2804e8d8bef9SDimitry Andric       if (memory_tagged == MemoryRegionInfo::eYes) {
2805e8d8bef9SDimitry Andric         response.PutCString("mt");
2806e8d8bef9SDimitry Andric       }
2807e8d8bef9SDimitry Andric       response.PutChar(';');
2808e8d8bef9SDimitry Andric     }
2809e8d8bef9SDimitry Andric 
28100b57cec5SDimitry Andric     // Name
28110b57cec5SDimitry Andric     ConstString name = region_info.GetName();
28120b57cec5SDimitry Andric     if (name) {
28130b57cec5SDimitry Andric       response.PutCString("name:");
28145ffd83dbSDimitry Andric       response.PutStringAsRawHex8(name.GetStringRef());
28150b57cec5SDimitry Andric       response.PutChar(';');
28160b57cec5SDimitry Andric     }
28170b57cec5SDimitry Andric   }
28180b57cec5SDimitry Andric 
28190b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
28200b57cec5SDimitry Andric }
28210b57cec5SDimitry Andric 
28220b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
28230b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
28240b57cec5SDimitry Andric   // Ensure we have a process.
2825fe6060f1SDimitry Andric   if (!m_current_process ||
2826fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
282781ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Process);
28280b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
28290b57cec5SDimitry Andric     return SendErrorResponse(0x15);
28300b57cec5SDimitry Andric   }
28310b57cec5SDimitry Andric 
28320b57cec5SDimitry Andric   // Parse out software or hardware breakpoint or watchpoint requested.
28330b57cec5SDimitry Andric   packet.SetFilePos(strlen("Z"));
28340b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
28350b57cec5SDimitry Andric     return SendIllFormedResponse(
28360b57cec5SDimitry Andric         packet, "Too short Z packet, missing software/hardware specifier");
28370b57cec5SDimitry Andric 
28380b57cec5SDimitry Andric   bool want_breakpoint = true;
28390b57cec5SDimitry Andric   bool want_hardware = false;
28400b57cec5SDimitry Andric   uint32_t watch_flags = 0;
28410b57cec5SDimitry Andric 
28420b57cec5SDimitry Andric   const GDBStoppointType stoppoint_type =
28430b57cec5SDimitry Andric       GDBStoppointType(packet.GetS32(eStoppointInvalid));
28440b57cec5SDimitry Andric   switch (stoppoint_type) {
28450b57cec5SDimitry Andric   case eBreakpointSoftware:
28460b57cec5SDimitry Andric     want_hardware = false;
28470b57cec5SDimitry Andric     want_breakpoint = true;
28480b57cec5SDimitry Andric     break;
28490b57cec5SDimitry Andric   case eBreakpointHardware:
28500b57cec5SDimitry Andric     want_hardware = true;
28510b57cec5SDimitry Andric     want_breakpoint = true;
28520b57cec5SDimitry Andric     break;
28530b57cec5SDimitry Andric   case eWatchpointWrite:
28540b57cec5SDimitry Andric     watch_flags = 1;
28550b57cec5SDimitry Andric     want_hardware = true;
28560b57cec5SDimitry Andric     want_breakpoint = false;
28570b57cec5SDimitry Andric     break;
28580b57cec5SDimitry Andric   case eWatchpointRead:
28590b57cec5SDimitry Andric     watch_flags = 2;
28600b57cec5SDimitry Andric     want_hardware = true;
28610b57cec5SDimitry Andric     want_breakpoint = false;
28620b57cec5SDimitry Andric     break;
28630b57cec5SDimitry Andric   case eWatchpointReadWrite:
28640b57cec5SDimitry Andric     watch_flags = 3;
28650b57cec5SDimitry Andric     want_hardware = true;
28660b57cec5SDimitry Andric     want_breakpoint = false;
28670b57cec5SDimitry Andric     break;
28680b57cec5SDimitry Andric   case eStoppointInvalid:
28690b57cec5SDimitry Andric     return SendIllFormedResponse(
28700b57cec5SDimitry Andric         packet, "Z packet had invalid software/hardware specifier");
28710b57cec5SDimitry Andric   }
28720b57cec5SDimitry Andric 
28730b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
28740b57cec5SDimitry Andric     return SendIllFormedResponse(
28750b57cec5SDimitry Andric         packet, "Malformed Z packet, expecting comma after stoppoint type");
28760b57cec5SDimitry Andric 
28770b57cec5SDimitry Andric   // Parse out the stoppoint address.
28780b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
28790b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short Z packet, missing address");
28800b57cec5SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
28810b57cec5SDimitry Andric 
28820b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
28830b57cec5SDimitry Andric     return SendIllFormedResponse(
28840b57cec5SDimitry Andric         packet, "Malformed Z packet, expecting comma after address");
28850b57cec5SDimitry Andric 
28860b57cec5SDimitry Andric   // Parse out the stoppoint size (i.e. size hint for opcode size).
28870b57cec5SDimitry Andric   const uint32_t size =
28880b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
28890b57cec5SDimitry Andric   if (size == std::numeric_limits<uint32_t>::max())
28900b57cec5SDimitry Andric     return SendIllFormedResponse(
28910b57cec5SDimitry Andric         packet, "Malformed Z packet, failed to parse size argument");
28920b57cec5SDimitry Andric 
28930b57cec5SDimitry Andric   if (want_breakpoint) {
28940b57cec5SDimitry Andric     // Try to set the breakpoint.
28950b57cec5SDimitry Andric     const Status error =
2896fe6060f1SDimitry Andric         m_current_process->SetBreakpoint(addr, size, want_hardware);
28970b57cec5SDimitry Andric     if (error.Success())
28980b57cec5SDimitry Andric       return SendOKResponse();
289981ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Breakpoints);
29000b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
2901fe6060f1SDimitry Andric              m_current_process->GetID(), error);
29020b57cec5SDimitry Andric     return SendErrorResponse(0x09);
29030b57cec5SDimitry Andric   } else {
29040b57cec5SDimitry Andric     // Try to set the watchpoint.
2905fe6060f1SDimitry Andric     const Status error = m_current_process->SetWatchpoint(
29060b57cec5SDimitry Andric         addr, size, watch_flags, want_hardware);
29070b57cec5SDimitry Andric     if (error.Success())
29080b57cec5SDimitry Andric       return SendOKResponse();
290981ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Watchpoints);
29100b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
2911fe6060f1SDimitry Andric              m_current_process->GetID(), error);
29120b57cec5SDimitry Andric     return SendErrorResponse(0x09);
29130b57cec5SDimitry Andric   }
29140b57cec5SDimitry Andric }
29150b57cec5SDimitry Andric 
29160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
29170b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
29180b57cec5SDimitry Andric   // Ensure we have a process.
2919fe6060f1SDimitry Andric   if (!m_current_process ||
2920fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
292181ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Process);
29220b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
29230b57cec5SDimitry Andric     return SendErrorResponse(0x15);
29240b57cec5SDimitry Andric   }
29250b57cec5SDimitry Andric 
29260b57cec5SDimitry Andric   // Parse out software or hardware breakpoint or watchpoint requested.
29270b57cec5SDimitry Andric   packet.SetFilePos(strlen("z"));
29280b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
29290b57cec5SDimitry Andric     return SendIllFormedResponse(
29300b57cec5SDimitry Andric         packet, "Too short z packet, missing software/hardware specifier");
29310b57cec5SDimitry Andric 
29320b57cec5SDimitry Andric   bool want_breakpoint = true;
29330b57cec5SDimitry Andric   bool want_hardware = false;
29340b57cec5SDimitry Andric 
29350b57cec5SDimitry Andric   const GDBStoppointType stoppoint_type =
29360b57cec5SDimitry Andric       GDBStoppointType(packet.GetS32(eStoppointInvalid));
29370b57cec5SDimitry Andric   switch (stoppoint_type) {
29380b57cec5SDimitry Andric   case eBreakpointHardware:
29390b57cec5SDimitry Andric     want_breakpoint = true;
29400b57cec5SDimitry Andric     want_hardware = true;
29410b57cec5SDimitry Andric     break;
29420b57cec5SDimitry Andric   case eBreakpointSoftware:
29430b57cec5SDimitry Andric     want_breakpoint = true;
29440b57cec5SDimitry Andric     break;
29450b57cec5SDimitry Andric   case eWatchpointWrite:
29460b57cec5SDimitry Andric     want_breakpoint = false;
29470b57cec5SDimitry Andric     break;
29480b57cec5SDimitry Andric   case eWatchpointRead:
29490b57cec5SDimitry Andric     want_breakpoint = false;
29500b57cec5SDimitry Andric     break;
29510b57cec5SDimitry Andric   case eWatchpointReadWrite:
29520b57cec5SDimitry Andric     want_breakpoint = false;
29530b57cec5SDimitry Andric     break;
29540b57cec5SDimitry Andric   default:
29550b57cec5SDimitry Andric     return SendIllFormedResponse(
29560b57cec5SDimitry Andric         packet, "z packet had invalid software/hardware specifier");
29570b57cec5SDimitry Andric   }
29580b57cec5SDimitry Andric 
29590b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
29600b57cec5SDimitry Andric     return SendIllFormedResponse(
29610b57cec5SDimitry Andric         packet, "Malformed z packet, expecting comma after stoppoint type");
29620b57cec5SDimitry Andric 
29630b57cec5SDimitry Andric   // Parse out the stoppoint address.
29640b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
29650b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short z packet, missing address");
29660b57cec5SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
29670b57cec5SDimitry Andric 
29680b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
29690b57cec5SDimitry Andric     return SendIllFormedResponse(
29700b57cec5SDimitry Andric         packet, "Malformed z packet, expecting comma after address");
29710b57cec5SDimitry Andric 
29720b57cec5SDimitry Andric   /*
29730b57cec5SDimitry Andric   // Parse out the stoppoint size (i.e. size hint for opcode size).
29740b57cec5SDimitry Andric   const uint32_t size = packet.GetHexMaxU32 (false,
29750b57cec5SDimitry Andric   std::numeric_limits<uint32_t>::max ());
29760b57cec5SDimitry Andric   if (size == std::numeric_limits<uint32_t>::max ())
29770b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Malformed z packet, failed to parse
29780b57cec5SDimitry Andric   size argument");
29790b57cec5SDimitry Andric   */
29800b57cec5SDimitry Andric 
29810b57cec5SDimitry Andric   if (want_breakpoint) {
29820b57cec5SDimitry Andric     // Try to clear the breakpoint.
29830b57cec5SDimitry Andric     const Status error =
2984fe6060f1SDimitry Andric         m_current_process->RemoveBreakpoint(addr, want_hardware);
29850b57cec5SDimitry Andric     if (error.Success())
29860b57cec5SDimitry Andric       return SendOKResponse();
298781ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Breakpoints);
29880b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
2989fe6060f1SDimitry Andric              m_current_process->GetID(), error);
29900b57cec5SDimitry Andric     return SendErrorResponse(0x09);
29910b57cec5SDimitry Andric   } else {
29920b57cec5SDimitry Andric     // Try to clear the watchpoint.
2993fe6060f1SDimitry Andric     const Status error = m_current_process->RemoveWatchpoint(addr);
29940b57cec5SDimitry Andric     if (error.Success())
29950b57cec5SDimitry Andric       return SendOKResponse();
299681ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Watchpoints);
29970b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
2998fe6060f1SDimitry Andric              m_current_process->GetID(), error);
29990b57cec5SDimitry Andric     return SendErrorResponse(0x09);
30000b57cec5SDimitry Andric   }
30010b57cec5SDimitry Andric }
30020b57cec5SDimitry Andric 
30030b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
30040b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
300581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
30060b57cec5SDimitry Andric 
30070b57cec5SDimitry Andric   // Ensure we have a process.
3008fe6060f1SDimitry Andric   if (!m_continue_process ||
3009fe6060f1SDimitry Andric       (m_continue_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
30109dba64beSDimitry Andric     LLDB_LOGF(
30119dba64beSDimitry Andric         log,
30120b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
30130b57cec5SDimitry Andric         __FUNCTION__);
30140b57cec5SDimitry Andric     return SendErrorResponse(0x32);
30150b57cec5SDimitry Andric   }
30160b57cec5SDimitry Andric 
30170b57cec5SDimitry Andric   // We first try to use a continue thread id.  If any one or any all set, use
30180b57cec5SDimitry Andric   // the current thread. Bail out if we don't have a thread id.
30190b57cec5SDimitry Andric   lldb::tid_t tid = GetContinueThreadID();
30200b57cec5SDimitry Andric   if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
30210b57cec5SDimitry Andric     tid = GetCurrentThreadID();
30220b57cec5SDimitry Andric   if (tid == LLDB_INVALID_THREAD_ID)
30230b57cec5SDimitry Andric     return SendErrorResponse(0x33);
30240b57cec5SDimitry Andric 
30250b57cec5SDimitry Andric   // Double check that we have such a thread.
30260b57cec5SDimitry Andric   // TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
3027fe6060f1SDimitry Andric   NativeThreadProtocol *thread = m_continue_process->GetThreadByID(tid);
30280b57cec5SDimitry Andric   if (!thread)
30290b57cec5SDimitry Andric     return SendErrorResponse(0x33);
30300b57cec5SDimitry Andric 
30310b57cec5SDimitry Andric   // Create the step action for the given thread.
30329dba64beSDimitry Andric   ResumeAction action = {tid, eStateStepping, LLDB_INVALID_SIGNAL_NUMBER};
30330b57cec5SDimitry Andric 
30340b57cec5SDimitry Andric   // Setup the actions list.
30350b57cec5SDimitry Andric   ResumeActionList actions;
30360b57cec5SDimitry Andric   actions.Append(action);
30370b57cec5SDimitry Andric 
30380b57cec5SDimitry Andric   // All other threads stop while we're single stepping a thread.
30390b57cec5SDimitry Andric   actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3040fcaf7f86SDimitry Andric 
3041fcaf7f86SDimitry Andric   PacketResult resume_res = ResumeProcess(*m_continue_process, actions);
3042fcaf7f86SDimitry Andric   if (resume_res != PacketResult::Success)
3043fcaf7f86SDimitry Andric     return resume_res;
30440b57cec5SDimitry Andric 
304581ad6265SDimitry Andric   // No response here, unless in non-stop mode.
304681ad6265SDimitry Andric   // Otherwise, the stop or exit will come from the resulting action.
304781ad6265SDimitry Andric   return SendContinueSuccessResponse();
30480b57cec5SDimitry Andric }
30490b57cec5SDimitry Andric 
30500b57cec5SDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
30515ffd83dbSDimitry Andric GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
30525ffd83dbSDimitry Andric   // Ensure we have a thread.
3053fe6060f1SDimitry Andric   NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
30545ffd83dbSDimitry Andric   if (!thread)
30555ffd83dbSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
30565ffd83dbSDimitry Andric                                    "No thread available");
30575ffd83dbSDimitry Andric 
305881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
30595ffd83dbSDimitry Andric   // Get the register context for the first thread.
30605ffd83dbSDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
30615ffd83dbSDimitry Andric 
30625ffd83dbSDimitry Andric   StreamString response;
30635ffd83dbSDimitry Andric 
30645ffd83dbSDimitry Andric   response.Printf("<?xml version=\"1.0\"?>");
30655ffd83dbSDimitry Andric   response.Printf("<target version=\"1.0\">");
30665ffd83dbSDimitry Andric 
30675ffd83dbSDimitry Andric   response.Printf("<architecture>%s</architecture>",
3068fe6060f1SDimitry Andric                   m_current_process->GetArchitecture()
30695ffd83dbSDimitry Andric                       .GetTriple()
30705ffd83dbSDimitry Andric                       .getArchName()
30715ffd83dbSDimitry Andric                       .str()
30725ffd83dbSDimitry Andric                       .c_str());
30735ffd83dbSDimitry Andric 
30745ffd83dbSDimitry Andric   response.Printf("<feature>");
30755ffd83dbSDimitry Andric 
30765ffd83dbSDimitry Andric   const int registers_count = reg_context.GetUserRegisterCount();
30775ffd83dbSDimitry Andric   for (int reg_index = 0; reg_index < registers_count; reg_index++) {
30785ffd83dbSDimitry Andric     const RegisterInfo *reg_info =
30795ffd83dbSDimitry Andric         reg_context.GetRegisterInfoAtIndex(reg_index);
30805ffd83dbSDimitry Andric 
30815ffd83dbSDimitry Andric     if (!reg_info) {
30825ffd83dbSDimitry Andric       LLDB_LOGF(log,
30835ffd83dbSDimitry Andric                 "%s failed to get register info for register index %" PRIu32,
30845ffd83dbSDimitry Andric                 "target.xml", reg_index);
30855ffd83dbSDimitry Andric       continue;
30865ffd83dbSDimitry Andric     }
30875ffd83dbSDimitry Andric 
3088e8d8bef9SDimitry Andric     response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 "\" regnum=\"%d\" ",
3089e8d8bef9SDimitry Andric                     reg_info->name, reg_info->byte_size * 8, reg_index);
3090e8d8bef9SDimitry Andric 
3091e8d8bef9SDimitry Andric     if (!reg_context.RegisterOffsetIsDynamic())
3092e8d8bef9SDimitry Andric       response.Printf("offset=\"%" PRIu32 "\" ", reg_info->byte_offset);
30935ffd83dbSDimitry Andric 
30945ffd83dbSDimitry Andric     if (reg_info->alt_name && reg_info->alt_name[0])
30955ffd83dbSDimitry Andric       response.Printf("altname=\"%s\" ", reg_info->alt_name);
30965ffd83dbSDimitry Andric 
30975ffd83dbSDimitry Andric     llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info);
30985ffd83dbSDimitry Andric     if (!encoding.empty())
30995ffd83dbSDimitry Andric       response << "encoding=\"" << encoding << "\" ";
31005ffd83dbSDimitry Andric 
31015ffd83dbSDimitry Andric     llvm::StringRef format = GetFormatNameOrEmpty(*reg_info);
31025ffd83dbSDimitry Andric     if (!format.empty())
31035ffd83dbSDimitry Andric       response << "format=\"" << format << "\" ";
31045ffd83dbSDimitry Andric 
31055ffd83dbSDimitry Andric     const char *const register_set_name =
31065ffd83dbSDimitry Andric         reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index);
31075ffd83dbSDimitry Andric     if (register_set_name)
31085ffd83dbSDimitry Andric       response << "group=\"" << register_set_name << "\" ";
31095ffd83dbSDimitry Andric 
31105ffd83dbSDimitry Andric     if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
31115ffd83dbSDimitry Andric         LLDB_INVALID_REGNUM)
31125ffd83dbSDimitry Andric       response.Printf("ehframe_regnum=\"%" PRIu32 "\" ",
31135ffd83dbSDimitry Andric                       reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
31145ffd83dbSDimitry Andric 
31155ffd83dbSDimitry Andric     if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] !=
31165ffd83dbSDimitry Andric         LLDB_INVALID_REGNUM)
31175ffd83dbSDimitry Andric       response.Printf("dwarf_regnum=\"%" PRIu32 "\" ",
31185ffd83dbSDimitry Andric                       reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
31195ffd83dbSDimitry Andric 
31205ffd83dbSDimitry Andric     llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info);
31215ffd83dbSDimitry Andric     if (!kind_generic.empty())
31225ffd83dbSDimitry Andric       response << "generic=\"" << kind_generic << "\" ";
31235ffd83dbSDimitry Andric 
31245ffd83dbSDimitry Andric     if (reg_info->value_regs &&
31255ffd83dbSDimitry Andric         reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
31265ffd83dbSDimitry Andric       response.PutCString("value_regnums=\"");
31275ffd83dbSDimitry Andric       CollectRegNums(reg_info->value_regs, response, false);
31285ffd83dbSDimitry Andric       response.Printf("\" ");
31295ffd83dbSDimitry Andric     }
31305ffd83dbSDimitry Andric 
31315ffd83dbSDimitry Andric     if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
31325ffd83dbSDimitry Andric       response.PutCString("invalidate_regnums=\"");
31335ffd83dbSDimitry Andric       CollectRegNums(reg_info->invalidate_regs, response, false);
31345ffd83dbSDimitry Andric       response.Printf("\" ");
31355ffd83dbSDimitry Andric     }
31365ffd83dbSDimitry Andric 
31375ffd83dbSDimitry Andric     response.Printf("/>");
31385ffd83dbSDimitry Andric   }
31395ffd83dbSDimitry Andric 
31405ffd83dbSDimitry Andric   response.Printf("</feature>");
31415ffd83dbSDimitry Andric   response.Printf("</target>");
31425ffd83dbSDimitry Andric   return MemoryBuffer::getMemBufferCopy(response.GetString(), "target.xml");
31435ffd83dbSDimitry Andric }
31445ffd83dbSDimitry Andric 
31455ffd83dbSDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
31460b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object,
31470b57cec5SDimitry Andric                                                  llvm::StringRef annex) {
31480b57cec5SDimitry Andric   // Make sure we have a valid process.
3149fe6060f1SDimitry Andric   if (!m_current_process ||
3150fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
31510b57cec5SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
31520b57cec5SDimitry Andric                                    "No process available");
31530b57cec5SDimitry Andric   }
31540b57cec5SDimitry Andric 
31555ffd83dbSDimitry Andric   if (object == "auxv") {
31560b57cec5SDimitry Andric     // Grab the auxv data.
3157fe6060f1SDimitry Andric     auto buffer_or_error = m_current_process->GetAuxvData();
31580b57cec5SDimitry Andric     if (!buffer_or_error)
31590b57cec5SDimitry Andric       return llvm::errorCodeToError(buffer_or_error.getError());
31600b57cec5SDimitry Andric     return std::move(*buffer_or_error);
31610b57cec5SDimitry Andric   }
31620b57cec5SDimitry Andric 
316304eeddc0SDimitry Andric   if (object == "siginfo") {
316404eeddc0SDimitry Andric     NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
316504eeddc0SDimitry Andric     if (!thread)
316604eeddc0SDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
316704eeddc0SDimitry Andric                                      "no current thread");
316804eeddc0SDimitry Andric 
316904eeddc0SDimitry Andric     auto buffer_or_error = thread->GetSiginfo();
317004eeddc0SDimitry Andric     if (!buffer_or_error)
317104eeddc0SDimitry Andric       return buffer_or_error.takeError();
317204eeddc0SDimitry Andric     return std::move(*buffer_or_error);
317304eeddc0SDimitry Andric   }
317404eeddc0SDimitry Andric 
31759dba64beSDimitry Andric   if (object == "libraries-svr4") {
3176fe6060f1SDimitry Andric     auto library_list = m_current_process->GetLoadedSVR4Libraries();
31779dba64beSDimitry Andric     if (!library_list)
31789dba64beSDimitry Andric       return library_list.takeError();
31799dba64beSDimitry Andric 
31809dba64beSDimitry Andric     StreamString response;
31819dba64beSDimitry Andric     response.Printf("<library-list-svr4 version=\"1.0\">");
31829dba64beSDimitry Andric     for (auto const &library : *library_list) {
31839dba64beSDimitry Andric       response.Printf("<library name=\"%s\" ",
31849dba64beSDimitry Andric                       XMLEncodeAttributeValue(library.name.c_str()).c_str());
31859dba64beSDimitry Andric       response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map);
31869dba64beSDimitry Andric       response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr);
31879dba64beSDimitry Andric       response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr);
31889dba64beSDimitry Andric     }
31899dba64beSDimitry Andric     response.Printf("</library-list-svr4>");
31909dba64beSDimitry Andric     return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__);
31919dba64beSDimitry Andric   }
31929dba64beSDimitry Andric 
31935ffd83dbSDimitry Andric   if (object == "features" && annex == "target.xml")
31945ffd83dbSDimitry Andric     return BuildTargetXml();
31955ffd83dbSDimitry Andric 
3196e8d8bef9SDimitry Andric   return llvm::make_error<UnimplementedError>();
31970b57cec5SDimitry Andric }
31980b57cec5SDimitry Andric 
31990b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
32000b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qXfer(
32010b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
32020b57cec5SDimitry Andric   SmallVector<StringRef, 5> fields;
32030b57cec5SDimitry Andric   // The packet format is "qXfer:<object>:<action>:<annex>:offset,length"
32040b57cec5SDimitry Andric   StringRef(packet.GetStringRef()).split(fields, ':', 4);
32050b57cec5SDimitry Andric   if (fields.size() != 5)
32060b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "malformed qXfer packet");
32070b57cec5SDimitry Andric   StringRef &xfer_object = fields[1];
32080b57cec5SDimitry Andric   StringRef &xfer_action = fields[2];
32090b57cec5SDimitry Andric   StringRef &xfer_annex = fields[3];
32100b57cec5SDimitry Andric   StringExtractor offset_data(fields[4]);
32110b57cec5SDimitry Andric   if (xfer_action != "read")
32120b57cec5SDimitry Andric     return SendUnimplementedResponse("qXfer action not supported");
32130b57cec5SDimitry Andric   // Parse offset.
32140b57cec5SDimitry Andric   const uint64_t xfer_offset =
32150b57cec5SDimitry Andric       offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
32160b57cec5SDimitry Andric   if (xfer_offset == std::numeric_limits<uint64_t>::max())
32170b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "qXfer packet missing offset");
32180b57cec5SDimitry Andric   // Parse out comma.
32190b57cec5SDimitry Andric   if (offset_data.GetChar() != ',')
32200b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
32210b57cec5SDimitry Andric                                  "qXfer packet missing comma after offset");
32220b57cec5SDimitry Andric   // Parse out the length.
32230b57cec5SDimitry Andric   const uint64_t xfer_length =
32240b57cec5SDimitry Andric       offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
32250b57cec5SDimitry Andric   if (xfer_length == std::numeric_limits<uint64_t>::max())
32260b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "qXfer packet missing length");
32270b57cec5SDimitry Andric 
32280b57cec5SDimitry Andric   // Get a previously constructed buffer if it exists or create it now.
32290b57cec5SDimitry Andric   std::string buffer_key = (xfer_object + xfer_action + xfer_annex).str();
32300b57cec5SDimitry Andric   auto buffer_it = m_xfer_buffer_map.find(buffer_key);
32310b57cec5SDimitry Andric   if (buffer_it == m_xfer_buffer_map.end()) {
32320b57cec5SDimitry Andric     auto buffer_up = ReadXferObject(xfer_object, xfer_annex);
32330b57cec5SDimitry Andric     if (!buffer_up)
32340b57cec5SDimitry Andric       return SendErrorResponse(buffer_up.takeError());
32350b57cec5SDimitry Andric     buffer_it = m_xfer_buffer_map
32360b57cec5SDimitry Andric                     .insert(std::make_pair(buffer_key, std::move(*buffer_up)))
32370b57cec5SDimitry Andric                     .first;
32380b57cec5SDimitry Andric   }
32390b57cec5SDimitry Andric 
32400b57cec5SDimitry Andric   // Send back the response
32410b57cec5SDimitry Andric   StreamGDBRemote response;
32420b57cec5SDimitry Andric   bool done_with_buffer = false;
32430b57cec5SDimitry Andric   llvm::StringRef buffer = buffer_it->second->getBuffer();
32440b57cec5SDimitry Andric   if (xfer_offset >= buffer.size()) {
32450b57cec5SDimitry Andric     // We have nothing left to send.  Mark the buffer as complete.
32460b57cec5SDimitry Andric     response.PutChar('l');
32470b57cec5SDimitry Andric     done_with_buffer = true;
32480b57cec5SDimitry Andric   } else {
32490b57cec5SDimitry Andric     // Figure out how many bytes are available starting at the given offset.
32500b57cec5SDimitry Andric     buffer = buffer.drop_front(xfer_offset);
32510b57cec5SDimitry Andric     // Mark the response type according to whether we're reading the remainder
32520b57cec5SDimitry Andric     // of the data.
32530b57cec5SDimitry Andric     if (xfer_length >= buffer.size()) {
32540b57cec5SDimitry Andric       // There will be nothing left to read after this
32550b57cec5SDimitry Andric       response.PutChar('l');
32560b57cec5SDimitry Andric       done_with_buffer = true;
32570b57cec5SDimitry Andric     } else {
32580b57cec5SDimitry Andric       // There will still be bytes to read after this request.
32590b57cec5SDimitry Andric       response.PutChar('m');
32600b57cec5SDimitry Andric       buffer = buffer.take_front(xfer_length);
32610b57cec5SDimitry Andric     }
32620b57cec5SDimitry Andric     // Now write the data in encoded binary form.
32630b57cec5SDimitry Andric     response.PutEscapedBytes(buffer.data(), buffer.size());
32640b57cec5SDimitry Andric   }
32650b57cec5SDimitry Andric 
32660b57cec5SDimitry Andric   if (done_with_buffer)
32670b57cec5SDimitry Andric     m_xfer_buffer_map.erase(buffer_it);
32680b57cec5SDimitry Andric 
32690b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
32700b57cec5SDimitry Andric }
32710b57cec5SDimitry Andric 
32720b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
32730b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
32740b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
327581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
32760b57cec5SDimitry Andric 
32770b57cec5SDimitry Andric   // Move past packet name.
32780b57cec5SDimitry Andric   packet.SetFilePos(strlen("QSaveRegisterState"));
32790b57cec5SDimitry Andric 
32800b57cec5SDimitry Andric   // Get the thread to use.
32810b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
32820b57cec5SDimitry Andric   if (!thread) {
32830b57cec5SDimitry Andric     if (m_thread_suffix_supported)
32840b57cec5SDimitry Andric       return SendIllFormedResponse(
32850b57cec5SDimitry Andric           packet, "No thread specified in QSaveRegisterState packet");
32860b57cec5SDimitry Andric     else
32870b57cec5SDimitry Andric       return SendIllFormedResponse(packet,
32880b57cec5SDimitry Andric                                    "No thread was is set with the Hg packet");
32890b57cec5SDimitry Andric   }
32900b57cec5SDimitry Andric 
32910b57cec5SDimitry Andric   // Grab the register context for the thread.
32920b57cec5SDimitry Andric   NativeRegisterContext& reg_context = thread->GetRegisterContext();
32930b57cec5SDimitry Andric 
32940b57cec5SDimitry Andric   // Save registers to a buffer.
329581ad6265SDimitry Andric   WritableDataBufferSP register_data_sp;
32960b57cec5SDimitry Andric   Status error = reg_context.ReadAllRegisterValues(register_data_sp);
32970b57cec5SDimitry Andric   if (error.Fail()) {
32980b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to save all register values: {1}",
3299fe6060f1SDimitry Andric              m_current_process->GetID(), error);
33000b57cec5SDimitry Andric     return SendErrorResponse(0x75);
33010b57cec5SDimitry Andric   }
33020b57cec5SDimitry Andric 
33030b57cec5SDimitry Andric   // Allocate a new save id.
33040b57cec5SDimitry Andric   const uint32_t save_id = GetNextSavedRegistersID();
33050b57cec5SDimitry Andric   assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) &&
33060b57cec5SDimitry Andric          "GetNextRegisterSaveID() returned an existing register save id");
33070b57cec5SDimitry Andric 
33080b57cec5SDimitry Andric   // Save the register data buffer under the save id.
33090b57cec5SDimitry Andric   {
33100b57cec5SDimitry Andric     std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
33110b57cec5SDimitry Andric     m_saved_registers_map[save_id] = register_data_sp;
33120b57cec5SDimitry Andric   }
33130b57cec5SDimitry Andric 
33140b57cec5SDimitry Andric   // Write the response.
33150b57cec5SDimitry Andric   StreamGDBRemote response;
33160b57cec5SDimitry Andric   response.Printf("%" PRIu32, save_id);
33170b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
33180b57cec5SDimitry Andric }
33190b57cec5SDimitry Andric 
33200b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
33210b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
33220b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
332381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
33240b57cec5SDimitry Andric 
33250b57cec5SDimitry Andric   // Parse out save id.
33260b57cec5SDimitry Andric   packet.SetFilePos(strlen("QRestoreRegisterState:"));
33270b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
33280b57cec5SDimitry Andric     return SendIllFormedResponse(
33290b57cec5SDimitry Andric         packet, "QRestoreRegisterState packet missing register save id");
33300b57cec5SDimitry Andric 
33310b57cec5SDimitry Andric   const uint32_t save_id = packet.GetU32(0);
33320b57cec5SDimitry Andric   if (save_id == 0) {
33330b57cec5SDimitry Andric     LLDB_LOG(log, "QRestoreRegisterState packet has malformed save id, "
33340b57cec5SDimitry Andric                   "expecting decimal uint32_t");
33350b57cec5SDimitry Andric     return SendErrorResponse(0x76);
33360b57cec5SDimitry Andric   }
33370b57cec5SDimitry Andric 
33380b57cec5SDimitry Andric   // Get the thread to use.
33390b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
33400b57cec5SDimitry Andric   if (!thread) {
33410b57cec5SDimitry Andric     if (m_thread_suffix_supported)
33420b57cec5SDimitry Andric       return SendIllFormedResponse(
33430b57cec5SDimitry Andric           packet, "No thread specified in QRestoreRegisterState packet");
33440b57cec5SDimitry Andric     else
33450b57cec5SDimitry Andric       return SendIllFormedResponse(packet,
33460b57cec5SDimitry Andric                                    "No thread was is set with the Hg packet");
33470b57cec5SDimitry Andric   }
33480b57cec5SDimitry Andric 
33490b57cec5SDimitry Andric   // Grab the register context for the thread.
33500b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
33510b57cec5SDimitry Andric 
33520b57cec5SDimitry Andric   // Retrieve register state buffer, then remove from the list.
33530b57cec5SDimitry Andric   DataBufferSP register_data_sp;
33540b57cec5SDimitry Andric   {
33550b57cec5SDimitry Andric     std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
33560b57cec5SDimitry Andric 
33570b57cec5SDimitry Andric     // Find the register set buffer for the given save id.
33580b57cec5SDimitry Andric     auto it = m_saved_registers_map.find(save_id);
33590b57cec5SDimitry Andric     if (it == m_saved_registers_map.end()) {
33600b57cec5SDimitry Andric       LLDB_LOG(log,
33610b57cec5SDimitry Andric                "pid {0} does not have a register set save buffer for id {1}",
3362fe6060f1SDimitry Andric                m_current_process->GetID(), save_id);
33630b57cec5SDimitry Andric       return SendErrorResponse(0x77);
33640b57cec5SDimitry Andric     }
33650b57cec5SDimitry Andric     register_data_sp = it->second;
33660b57cec5SDimitry Andric 
33670b57cec5SDimitry Andric     // Remove it from the map.
33680b57cec5SDimitry Andric     m_saved_registers_map.erase(it);
33690b57cec5SDimitry Andric   }
33700b57cec5SDimitry Andric 
33710b57cec5SDimitry Andric   Status error = reg_context.WriteAllRegisterValues(register_data_sp);
33720b57cec5SDimitry Andric   if (error.Fail()) {
33730b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to restore all register values: {1}",
3374fe6060f1SDimitry Andric              m_current_process->GetID(), error);
33750b57cec5SDimitry Andric     return SendErrorResponse(0x77);
33760b57cec5SDimitry Andric   }
33770b57cec5SDimitry Andric 
33780b57cec5SDimitry Andric   return SendOKResponse();
33790b57cec5SDimitry Andric }
33800b57cec5SDimitry Andric 
33810b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
33820b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttach(
33830b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
338481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
33850b57cec5SDimitry Andric 
33860b57cec5SDimitry Andric   // Consume the ';' after vAttach.
33870b57cec5SDimitry Andric   packet.SetFilePos(strlen("vAttach"));
33880b57cec5SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
33890b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "vAttach missing expected ';'");
33900b57cec5SDimitry Andric 
33910b57cec5SDimitry Andric   // Grab the PID to which we will attach (assume hex encoding).
33920b57cec5SDimitry Andric   lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
33930b57cec5SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
33940b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
33950b57cec5SDimitry Andric                                  "vAttach failed to parse the process id");
33960b57cec5SDimitry Andric 
33970b57cec5SDimitry Andric   // Attempt to attach.
33989dba64beSDimitry Andric   LLDB_LOGF(log,
33999dba64beSDimitry Andric             "GDBRemoteCommunicationServerLLGS::%s attempting to attach to "
34000b57cec5SDimitry Andric             "pid %" PRIu64,
34010b57cec5SDimitry Andric             __FUNCTION__, pid);
34020b57cec5SDimitry Andric 
34030b57cec5SDimitry Andric   Status error = AttachToProcess(pid);
34040b57cec5SDimitry Andric 
34050b57cec5SDimitry Andric   if (error.Fail()) {
34069dba64beSDimitry Andric     LLDB_LOGF(log,
34079dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to attach to "
34080b57cec5SDimitry Andric               "pid %" PRIu64 ": %s\n",
34090b57cec5SDimitry Andric               __FUNCTION__, pid, error.AsCString());
34100b57cec5SDimitry Andric     return SendErrorResponse(error);
34110b57cec5SDimitry Andric   }
34120b57cec5SDimitry Andric 
34130b57cec5SDimitry Andric   // Notify we attached by sending a stop packet.
341481ad6265SDimitry Andric   assert(m_current_process);
341581ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
341681ad6265SDimitry Andric                                 m_current_process->GetState(),
341781ad6265SDimitry Andric                                 /*force_synchronous=*/false);
34180b57cec5SDimitry Andric }
34190b57cec5SDimitry Andric 
34200b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3421e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachWait(
3422e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
342381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3424e8d8bef9SDimitry Andric 
3425e8d8bef9SDimitry Andric   // Consume the ';' after the identifier.
3426e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("vAttachWait"));
3427e8d8bef9SDimitry Andric 
3428e8d8bef9SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
3429e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "vAttachWait missing expected ';'");
3430e8d8bef9SDimitry Andric 
3431e8d8bef9SDimitry Andric   // Allocate the buffer for the process name from vAttachWait.
3432e8d8bef9SDimitry Andric   std::string process_name;
3433e8d8bef9SDimitry Andric   if (!packet.GetHexByteString(process_name))
3434e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet,
3435e8d8bef9SDimitry Andric                                  "vAttachWait failed to parse process name");
3436e8d8bef9SDimitry Andric 
3437e8d8bef9SDimitry Andric   LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name);
3438e8d8bef9SDimitry Andric 
3439e8d8bef9SDimitry Andric   Status error = AttachWaitProcess(process_name, false);
3440e8d8bef9SDimitry Andric   if (error.Fail()) {
3441e8d8bef9SDimitry Andric     LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name,
3442e8d8bef9SDimitry Andric              error);
3443e8d8bef9SDimitry Andric     return SendErrorResponse(error);
3444e8d8bef9SDimitry Andric   }
3445e8d8bef9SDimitry Andric 
3446e8d8bef9SDimitry Andric   // Notify we attached by sending a stop packet.
344781ad6265SDimitry Andric   assert(m_current_process);
344881ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
344981ad6265SDimitry Andric                                 m_current_process->GetState(),
345081ad6265SDimitry Andric                                 /*force_synchronous=*/false);
3451e8d8bef9SDimitry Andric }
3452e8d8bef9SDimitry Andric 
3453e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
3454e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported(
3455e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
3456e8d8bef9SDimitry Andric   return SendOKResponse();
3457e8d8bef9SDimitry Andric }
3458e8d8bef9SDimitry Andric 
3459e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
3460e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait(
3461e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
346281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3463e8d8bef9SDimitry Andric 
3464e8d8bef9SDimitry Andric   // Consume the ';' after the identifier.
3465e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("vAttachOrWait"));
3466e8d8bef9SDimitry Andric 
3467e8d8bef9SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
3468e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "vAttachOrWait missing expected ';'");
3469e8d8bef9SDimitry Andric 
3470e8d8bef9SDimitry Andric   // Allocate the buffer for the process name from vAttachWait.
3471e8d8bef9SDimitry Andric   std::string process_name;
3472e8d8bef9SDimitry Andric   if (!packet.GetHexByteString(process_name))
3473e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet,
3474e8d8bef9SDimitry Andric                                  "vAttachOrWait failed to parse process name");
3475e8d8bef9SDimitry Andric 
3476e8d8bef9SDimitry Andric   LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name);
3477e8d8bef9SDimitry Andric 
3478e8d8bef9SDimitry Andric   Status error = AttachWaitProcess(process_name, true);
3479e8d8bef9SDimitry Andric   if (error.Fail()) {
3480e8d8bef9SDimitry Andric     LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name,
3481e8d8bef9SDimitry Andric              error);
3482e8d8bef9SDimitry Andric     return SendErrorResponse(error);
3483e8d8bef9SDimitry Andric   }
3484e8d8bef9SDimitry Andric 
3485e8d8bef9SDimitry Andric   // Notify we attached by sending a stop packet.
348681ad6265SDimitry Andric   assert(m_current_process);
348781ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
348881ad6265SDimitry Andric                                 m_current_process->GetState(),
348981ad6265SDimitry Andric                                 /*force_synchronous=*/false);
3490e8d8bef9SDimitry Andric }
3491e8d8bef9SDimitry Andric 
3492e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
3493349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vRun(
3494349cc55cSDimitry Andric     StringExtractorGDBRemote &packet) {
349581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3496349cc55cSDimitry Andric 
3497349cc55cSDimitry Andric   llvm::StringRef s = packet.GetStringRef();
3498349cc55cSDimitry Andric   if (!s.consume_front("vRun;"))
3499349cc55cSDimitry Andric     return SendErrorResponse(8);
3500349cc55cSDimitry Andric 
3501349cc55cSDimitry Andric   llvm::SmallVector<llvm::StringRef, 16> argv;
3502349cc55cSDimitry Andric   s.split(argv, ';');
3503349cc55cSDimitry Andric 
3504349cc55cSDimitry Andric   for (llvm::StringRef hex_arg : argv) {
3505349cc55cSDimitry Andric     StringExtractor arg_ext{hex_arg};
3506349cc55cSDimitry Andric     std::string arg;
3507349cc55cSDimitry Andric     arg_ext.GetHexByteString(arg);
3508349cc55cSDimitry Andric     m_process_launch_info.GetArguments().AppendArgument(arg);
3509349cc55cSDimitry Andric     LLDB_LOGF(log, "LLGSPacketHandler::%s added arg: \"%s\"", __FUNCTION__,
3510349cc55cSDimitry Andric               arg.c_str());
3511349cc55cSDimitry Andric   }
3512349cc55cSDimitry Andric 
3513349cc55cSDimitry Andric   if (!argv.empty()) {
3514349cc55cSDimitry Andric     m_process_launch_info.GetExecutableFile().SetFile(
3515349cc55cSDimitry Andric         m_process_launch_info.GetArguments()[0].ref(), FileSpec::Style::native);
3516349cc55cSDimitry Andric     m_process_launch_error = LaunchProcess();
351781ad6265SDimitry Andric     if (m_process_launch_error.Success()) {
351881ad6265SDimitry Andric       assert(m_current_process);
351981ad6265SDimitry Andric       return SendStopReasonForState(*m_current_process,
352081ad6265SDimitry Andric                                     m_current_process->GetState(),
352181ad6265SDimitry Andric                                     /*force_synchronous=*/true);
352281ad6265SDimitry Andric     }
3523349cc55cSDimitry Andric     LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error);
3524349cc55cSDimitry Andric   }
3525349cc55cSDimitry Andric   return SendErrorResponse(8);
3526349cc55cSDimitry Andric }
3527349cc55cSDimitry Andric 
3528349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult
35290b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
353081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3531fcaf7f86SDimitry Andric   if (!m_non_stop)
35320b57cec5SDimitry Andric     StopSTDIOForwarding();
35330b57cec5SDimitry Andric 
35340b57cec5SDimitry Andric   lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
35350b57cec5SDimitry Andric 
35360b57cec5SDimitry Andric   // Consume the ';' after D.
35370b57cec5SDimitry Andric   packet.SetFilePos(1);
35380b57cec5SDimitry Andric   if (packet.GetBytesLeft()) {
35390b57cec5SDimitry Andric     if (packet.GetChar() != ';')
35400b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "D missing expected ';'");
35410b57cec5SDimitry Andric 
35420b57cec5SDimitry Andric     // Grab the PID from which we will detach (assume hex encoding).
35430b57cec5SDimitry Andric     pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
35440b57cec5SDimitry Andric     if (pid == LLDB_INVALID_PROCESS_ID)
35450b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "D failed to parse the process id");
35460b57cec5SDimitry Andric   }
35470b57cec5SDimitry Andric 
3548fe6060f1SDimitry Andric   // Detach forked children if their PID was specified *or* no PID was requested
3549fe6060f1SDimitry Andric   // (i.e. detach-all packet).
3550fe6060f1SDimitry Andric   llvm::Error detach_error = llvm::Error::success();
3551fe6060f1SDimitry Andric   bool detached = false;
3552fe6060f1SDimitry Andric   for (auto it = m_debugged_processes.begin();
3553fe6060f1SDimitry Andric        it != m_debugged_processes.end();) {
3554fe6060f1SDimitry Andric     if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) {
355581ad6265SDimitry Andric       LLDB_LOGF(log,
355681ad6265SDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s detaching %" PRId64,
355781ad6265SDimitry Andric                 __FUNCTION__, it->first);
3558fcaf7f86SDimitry Andric       if (llvm::Error e = it->second.process_up->Detach().ToError())
3559fe6060f1SDimitry Andric         detach_error = llvm::joinErrors(std::move(detach_error), std::move(e));
3560fe6060f1SDimitry Andric       else {
3561fcaf7f86SDimitry Andric         if (it->second.process_up.get() == m_current_process)
3562fe6060f1SDimitry Andric           m_current_process = nullptr;
3563fcaf7f86SDimitry Andric         if (it->second.process_up.get() == m_continue_process)
3564fe6060f1SDimitry Andric           m_continue_process = nullptr;
3565fe6060f1SDimitry Andric         it = m_debugged_processes.erase(it);
3566fe6060f1SDimitry Andric         detached = true;
3567fe6060f1SDimitry Andric         continue;
3568fe6060f1SDimitry Andric       }
3569fe6060f1SDimitry Andric     }
3570fe6060f1SDimitry Andric     ++it;
35710b57cec5SDimitry Andric   }
35720b57cec5SDimitry Andric 
3573fe6060f1SDimitry Andric   if (detach_error)
3574fe6060f1SDimitry Andric     return SendErrorResponse(std::move(detach_error));
3575fe6060f1SDimitry Andric   if (!detached)
3576fe6060f1SDimitry Andric     return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid));
35770b57cec5SDimitry Andric   return SendOKResponse();
35780b57cec5SDimitry Andric }
35790b57cec5SDimitry Andric 
35800b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
35810b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
35820b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
358381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
358481ad6265SDimitry Andric 
358581ad6265SDimitry Andric   if (!m_current_process ||
358681ad6265SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
358781ad6265SDimitry Andric     return SendErrorResponse(50);
35880b57cec5SDimitry Andric 
35890b57cec5SDimitry Andric   packet.SetFilePos(strlen("qThreadStopInfo"));
3590fe6060f1SDimitry Andric   const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
35910b57cec5SDimitry Andric   if (tid == LLDB_INVALID_THREAD_ID) {
35929dba64beSDimitry Andric     LLDB_LOGF(log,
35939dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
35940b57cec5SDimitry Andric               "parse thread id from request \"%s\"",
35959dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
35960b57cec5SDimitry Andric     return SendErrorResponse(0x15);
35970b57cec5SDimitry Andric   }
359881ad6265SDimitry Andric   return SendStopReplyPacketForThread(*m_current_process, tid,
359981ad6265SDimitry Andric                                       /*force_synchronous=*/true);
36000b57cec5SDimitry Andric }
36010b57cec5SDimitry Andric 
36020b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
36030b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
36040b57cec5SDimitry Andric     StringExtractorGDBRemote &) {
360581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
36060b57cec5SDimitry Andric 
36070b57cec5SDimitry Andric   // Ensure we have a debugged process.
3608fe6060f1SDimitry Andric   if (!m_current_process ||
3609fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
36100b57cec5SDimitry Andric     return SendErrorResponse(50);
3611fe6060f1SDimitry Andric   LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID());
36120b57cec5SDimitry Andric 
36130b57cec5SDimitry Andric   StreamString response;
36140b57cec5SDimitry Andric   const bool threads_with_valid_stop_info_only = false;
3615fe6060f1SDimitry Andric   llvm::Expected<json::Value> threads_info =
3616fe6060f1SDimitry Andric       GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only);
36179dba64beSDimitry Andric   if (!threads_info) {
3618480093f4SDimitry Andric     LLDB_LOG_ERROR(log, threads_info.takeError(),
3619480093f4SDimitry Andric                    "failed to prepare a packet for pid {1}: {0}",
3620fe6060f1SDimitry Andric                    m_current_process->GetID());
36210b57cec5SDimitry Andric     return SendErrorResponse(52);
36220b57cec5SDimitry Andric   }
36230b57cec5SDimitry Andric 
36249dba64beSDimitry Andric   response.AsRawOstream() << *threads_info;
36250b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
36260b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
36270b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
36280b57cec5SDimitry Andric }
36290b57cec5SDimitry Andric 
36300b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
36310b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
36320b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
36330b57cec5SDimitry Andric   // Fail if we don't have a current process.
3634fe6060f1SDimitry Andric   if (!m_current_process ||
3635fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
36360b57cec5SDimitry Andric     return SendErrorResponse(68);
36370b57cec5SDimitry Andric 
36380b57cec5SDimitry Andric   packet.SetFilePos(strlen("qWatchpointSupportInfo"));
36390b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0)
36400b57cec5SDimitry Andric     return SendOKResponse();
36410b57cec5SDimitry Andric   if (packet.GetChar() != ':')
36420b57cec5SDimitry Andric     return SendErrorResponse(67);
36430b57cec5SDimitry Andric 
3644fe6060f1SDimitry Andric   auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo();
36450b57cec5SDimitry Andric 
36460b57cec5SDimitry Andric   StreamGDBRemote response;
36470b57cec5SDimitry Andric   if (hw_debug_cap == llvm::None)
36480b57cec5SDimitry Andric     response.Printf("num:0;");
36490b57cec5SDimitry Andric   else
36500b57cec5SDimitry Andric     response.Printf("num:%d;", hw_debug_cap->second);
36510b57cec5SDimitry Andric 
36520b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
36530b57cec5SDimitry Andric }
36540b57cec5SDimitry Andric 
36550b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
36560b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
36570b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
36580b57cec5SDimitry Andric   // Fail if we don't have a current process.
3659fe6060f1SDimitry Andric   if (!m_current_process ||
3660fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
36610b57cec5SDimitry Andric     return SendErrorResponse(67);
36620b57cec5SDimitry Andric 
36630b57cec5SDimitry Andric   packet.SetFilePos(strlen("qFileLoadAddress:"));
36640b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0)
36650b57cec5SDimitry Andric     return SendErrorResponse(68);
36660b57cec5SDimitry Andric 
36670b57cec5SDimitry Andric   std::string file_name;
36680b57cec5SDimitry Andric   packet.GetHexByteString(file_name);
36690b57cec5SDimitry Andric 
36700b57cec5SDimitry Andric   lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
36710b57cec5SDimitry Andric   Status error =
3672fe6060f1SDimitry Andric       m_current_process->GetFileLoadAddress(file_name, file_load_address);
36730b57cec5SDimitry Andric   if (error.Fail())
36740b57cec5SDimitry Andric     return SendErrorResponse(69);
36750b57cec5SDimitry Andric 
36760b57cec5SDimitry Andric   if (file_load_address == LLDB_INVALID_ADDRESS)
36770b57cec5SDimitry Andric     return SendErrorResponse(1); // File not loaded
36780b57cec5SDimitry Andric 
36790b57cec5SDimitry Andric   StreamGDBRemote response;
36800b57cec5SDimitry Andric   response.PutHex64(file_load_address);
36810b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
36820b57cec5SDimitry Andric }
36830b57cec5SDimitry Andric 
36840b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
36850b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
36860b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
36870b57cec5SDimitry Andric   std::vector<int> signals;
36880b57cec5SDimitry Andric   packet.SetFilePos(strlen("QPassSignals:"));
36890b57cec5SDimitry Andric 
36900b57cec5SDimitry Andric   // Read sequence of hex signal numbers divided by a semicolon and optionally
36910b57cec5SDimitry Andric   // spaces.
36920b57cec5SDimitry Andric   while (packet.GetBytesLeft() > 0) {
36930b57cec5SDimitry Andric     int signal = packet.GetS32(-1, 16);
36940b57cec5SDimitry Andric     if (signal < 0)
36950b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Failed to parse signal number.");
36960b57cec5SDimitry Andric     signals.push_back(signal);
36970b57cec5SDimitry Andric 
36980b57cec5SDimitry Andric     packet.SkipSpaces();
36990b57cec5SDimitry Andric     char separator = packet.GetChar();
37000b57cec5SDimitry Andric     if (separator == '\0')
37010b57cec5SDimitry Andric       break; // End of string
37020b57cec5SDimitry Andric     if (separator != ';')
37030b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Invalid separator,"
37040b57cec5SDimitry Andric                                             " expected semicolon.");
37050b57cec5SDimitry Andric   }
37060b57cec5SDimitry Andric 
37070b57cec5SDimitry Andric   // Fail if we don't have a current process.
3708fe6060f1SDimitry Andric   if (!m_current_process)
37090b57cec5SDimitry Andric     return SendErrorResponse(68);
37100b57cec5SDimitry Andric 
3711fe6060f1SDimitry Andric   Status error = m_current_process->IgnoreSignals(signals);
37120b57cec5SDimitry Andric   if (error.Fail())
37130b57cec5SDimitry Andric     return SendErrorResponse(69);
37140b57cec5SDimitry Andric 
37150b57cec5SDimitry Andric   return SendOKResponse();
37160b57cec5SDimitry Andric }
37170b57cec5SDimitry Andric 
3718fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
3719fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
3720fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
372181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3722fe6060f1SDimitry Andric 
3723fe6060f1SDimitry Andric   // Ensure we have a process.
3724fe6060f1SDimitry Andric   if (!m_current_process ||
3725fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
3726fe6060f1SDimitry Andric     LLDB_LOGF(
3727fe6060f1SDimitry Andric         log,
3728fe6060f1SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
3729fe6060f1SDimitry Andric         __FUNCTION__);
3730fe6060f1SDimitry Andric     return SendErrorResponse(1);
3731fe6060f1SDimitry Andric   }
3732fe6060f1SDimitry Andric 
3733fe6060f1SDimitry Andric   // We are expecting
3734fe6060f1SDimitry Andric   // qMemTags:<hex address>,<hex length>:<hex type>
3735fe6060f1SDimitry Andric 
3736fe6060f1SDimitry Andric   // Address
3737fe6060f1SDimitry Andric   packet.SetFilePos(strlen("qMemTags:"));
3738fe6060f1SDimitry Andric   const char *current_char = packet.Peek();
3739fe6060f1SDimitry Andric   if (!current_char || *current_char == ',')
3740fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, "Missing address in qMemTags packet");
3741fe6060f1SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3742fe6060f1SDimitry Andric 
3743fe6060f1SDimitry Andric   // Length
3744fe6060f1SDimitry Andric   char previous_char = packet.GetChar();
3745fe6060f1SDimitry Andric   current_char = packet.Peek();
3746fe6060f1SDimitry Andric   // If we don't have a separator or the length field is empty
3747fe6060f1SDimitry Andric   if (previous_char != ',' || (current_char && *current_char == ':'))
3748fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3749fe6060f1SDimitry Andric                                  "Invalid addr,length pair in qMemTags packet");
3750fe6060f1SDimitry Andric 
3751fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1)
3752fe6060f1SDimitry Andric     return SendIllFormedResponse(
3753fe6060f1SDimitry Andric         packet, "Too short qMemtags: packet (looking for length)");
3754fe6060f1SDimitry Andric   const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3755fe6060f1SDimitry Andric 
3756fe6060f1SDimitry Andric   // Type
3757fe6060f1SDimitry Andric   const char *invalid_type_err = "Invalid type field in qMemTags: packet";
3758fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3759fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3760fe6060f1SDimitry Andric 
37616e75b2fbSDimitry Andric   // Type is a signed integer but packed into the packet as its raw bytes.
37626e75b2fbSDimitry Andric   // However, our GetU64 uses strtoull which allows +/-. We do not want this.
37636e75b2fbSDimitry Andric   const char *first_type_char = packet.Peek();
37646e75b2fbSDimitry Andric   if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
37656e75b2fbSDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
37666e75b2fbSDimitry Andric 
37676e75b2fbSDimitry Andric   // Extract type as unsigned then cast to signed.
37686e75b2fbSDimitry Andric   // Using a uint64_t here so that we have some value outside of the 32 bit
37696e75b2fbSDimitry Andric   // range to use as the invalid return value.
37706e75b2fbSDimitry Andric   uint64_t raw_type =
37716e75b2fbSDimitry Andric       packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
37726e75b2fbSDimitry Andric 
37736e75b2fbSDimitry Andric   if ( // Make sure the cast below would be valid
37746e75b2fbSDimitry Andric       raw_type > std::numeric_limits<uint32_t>::max() ||
3775fe6060f1SDimitry Andric       // To catch inputs like "123aardvark" that will parse but clearly aren't
3776fe6060f1SDimitry Andric       // valid in this case.
3777fe6060f1SDimitry Andric       packet.GetBytesLeft()) {
3778fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3779fe6060f1SDimitry Andric   }
3780fe6060f1SDimitry Andric 
37816e75b2fbSDimitry Andric   // First narrow to 32 bits otherwise the copy into type would take
37826e75b2fbSDimitry Andric   // the wrong 4 bytes on big endian.
37836e75b2fbSDimitry Andric   uint32_t raw_type_32 = raw_type;
37846e75b2fbSDimitry Andric   int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
37856e75b2fbSDimitry Andric 
3786fe6060f1SDimitry Andric   StreamGDBRemote response;
3787fe6060f1SDimitry Andric   std::vector<uint8_t> tags;
3788fe6060f1SDimitry Andric   Status error = m_current_process->ReadMemoryTags(type, addr, length, tags);
3789fe6060f1SDimitry Andric   if (error.Fail())
3790fe6060f1SDimitry Andric     return SendErrorResponse(1);
3791fe6060f1SDimitry Andric 
3792fe6060f1SDimitry Andric   // This m is here in case we want to support multi part replies in the future.
3793fe6060f1SDimitry Andric   // In the same manner as qfThreadInfo/qsThreadInfo.
3794fe6060f1SDimitry Andric   response.PutChar('m');
3795fe6060f1SDimitry Andric   response.PutBytesAsRawHex8(tags.data(), tags.size());
3796fe6060f1SDimitry Andric   return SendPacketNoLock(response.GetString());
3797fe6060f1SDimitry Andric }
3798fe6060f1SDimitry Andric 
3799fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
3800fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QMemTags(
3801fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
380281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3803fe6060f1SDimitry Andric 
3804fe6060f1SDimitry Andric   // Ensure we have a process.
3805fe6060f1SDimitry Andric   if (!m_current_process ||
3806fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
3807fe6060f1SDimitry Andric     LLDB_LOGF(
3808fe6060f1SDimitry Andric         log,
3809fe6060f1SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
3810fe6060f1SDimitry Andric         __FUNCTION__);
3811fe6060f1SDimitry Andric     return SendErrorResponse(1);
3812fe6060f1SDimitry Andric   }
3813fe6060f1SDimitry Andric 
3814fe6060f1SDimitry Andric   // We are expecting
3815fe6060f1SDimitry Andric   // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes>
3816fe6060f1SDimitry Andric 
3817fe6060f1SDimitry Andric   // Address
3818fe6060f1SDimitry Andric   packet.SetFilePos(strlen("QMemTags:"));
3819fe6060f1SDimitry Andric   const char *current_char = packet.Peek();
3820fe6060f1SDimitry Andric   if (!current_char || *current_char == ',')
3821fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, "Missing address in QMemTags packet");
3822fe6060f1SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3823fe6060f1SDimitry Andric 
3824fe6060f1SDimitry Andric   // Length
3825fe6060f1SDimitry Andric   char previous_char = packet.GetChar();
3826fe6060f1SDimitry Andric   current_char = packet.Peek();
3827fe6060f1SDimitry Andric   // If we don't have a separator or the length field is empty
3828fe6060f1SDimitry Andric   if (previous_char != ',' || (current_char && *current_char == ':'))
3829fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3830fe6060f1SDimitry Andric                                  "Invalid addr,length pair in QMemTags packet");
3831fe6060f1SDimitry Andric 
3832fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1)
3833fe6060f1SDimitry Andric     return SendIllFormedResponse(
3834fe6060f1SDimitry Andric         packet, "Too short QMemtags: packet (looking for length)");
3835fe6060f1SDimitry Andric   const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3836fe6060f1SDimitry Andric 
3837fe6060f1SDimitry Andric   // Type
3838fe6060f1SDimitry Andric   const char *invalid_type_err = "Invalid type field in QMemTags: packet";
3839fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3840fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3841fe6060f1SDimitry Andric 
3842fe6060f1SDimitry Andric   // Our GetU64 uses strtoull which allows leading +/-, we don't want that.
3843fe6060f1SDimitry Andric   const char *first_type_char = packet.Peek();
3844fe6060f1SDimitry Andric   if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
3845fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3846fe6060f1SDimitry Andric 
3847fe6060f1SDimitry Andric   // The type is a signed integer but is in the packet as its raw bytes.
3848fe6060f1SDimitry Andric   // So parse first as unsigned then cast to signed later.
3849fe6060f1SDimitry Andric   // We extract to 64 bit, even though we only expect 32, so that we've
3850fe6060f1SDimitry Andric   // got some invalid value we can check for.
3851fe6060f1SDimitry Andric   uint64_t raw_type =
3852fe6060f1SDimitry Andric       packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
3853fe6060f1SDimitry Andric   if (raw_type > std::numeric_limits<uint32_t>::max())
3854fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
38556e75b2fbSDimitry Andric 
38566e75b2fbSDimitry Andric   // First narrow to 32 bits. Otherwise the copy below would get the wrong
38576e75b2fbSDimitry Andric   // 4 bytes on big endian.
38586e75b2fbSDimitry Andric   uint32_t raw_type_32 = raw_type;
38596e75b2fbSDimitry Andric   int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
3860fe6060f1SDimitry Andric 
3861fe6060f1SDimitry Andric   // Tag data
3862fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3863fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3864fe6060f1SDimitry Andric                                  "Missing tag data in QMemTags: packet");
3865fe6060f1SDimitry Andric 
3866fe6060f1SDimitry Andric   // Must be 2 chars per byte
3867fe6060f1SDimitry Andric   const char *invalid_data_err = "Invalid tag data in QMemTags: packet";
3868fe6060f1SDimitry Andric   if (packet.GetBytesLeft() % 2)
3869fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_data_err);
3870fe6060f1SDimitry Andric 
3871fe6060f1SDimitry Andric   // This is bytes here and is unpacked into target specific tags later
3872fe6060f1SDimitry Andric   // We cannot assume that number of bytes == length here because the server
3873fe6060f1SDimitry Andric   // can repeat tags to fill a given range.
3874fe6060f1SDimitry Andric   std::vector<uint8_t> tag_data;
3875fe6060f1SDimitry Andric   // Zero length writes will not have any tag data
3876fe6060f1SDimitry Andric   // (but we pass them on because it will still check that tagging is enabled)
3877fe6060f1SDimitry Andric   if (packet.GetBytesLeft()) {
3878fe6060f1SDimitry Andric     size_t byte_count = packet.GetBytesLeft() / 2;
3879fe6060f1SDimitry Andric     tag_data.resize(byte_count);
3880fe6060f1SDimitry Andric     size_t converted_bytes = packet.GetHexBytes(tag_data, 0);
3881fe6060f1SDimitry Andric     if (converted_bytes != byte_count) {
3882fe6060f1SDimitry Andric       return SendIllFormedResponse(packet, invalid_data_err);
3883fe6060f1SDimitry Andric     }
3884fe6060f1SDimitry Andric   }
3885fe6060f1SDimitry Andric 
3886fe6060f1SDimitry Andric   Status status =
3887fe6060f1SDimitry Andric       m_current_process->WriteMemoryTags(type, addr, length, tag_data);
3888fe6060f1SDimitry Andric   return status.Success() ? SendOKResponse() : SendErrorResponse(1);
3889fe6060f1SDimitry Andric }
3890fe6060f1SDimitry Andric 
3891349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult
3892349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qSaveCore(
3893349cc55cSDimitry Andric     StringExtractorGDBRemote &packet) {
3894349cc55cSDimitry Andric   // Fail if we don't have a current process.
3895349cc55cSDimitry Andric   if (!m_current_process ||
3896349cc55cSDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
3897349cc55cSDimitry Andric     return SendErrorResponse(Status("Process not running."));
3898349cc55cSDimitry Andric 
3899349cc55cSDimitry Andric   std::string path_hint;
3900349cc55cSDimitry Andric 
3901349cc55cSDimitry Andric   StringRef packet_str{packet.GetStringRef()};
3902349cc55cSDimitry Andric   assert(packet_str.startswith("qSaveCore"));
3903349cc55cSDimitry Andric   if (packet_str.consume_front("qSaveCore;")) {
3904349cc55cSDimitry Andric     for (auto x : llvm::split(packet_str, ';')) {
3905349cc55cSDimitry Andric       if (x.consume_front("path-hint:"))
3906349cc55cSDimitry Andric         StringExtractor(x).GetHexByteString(path_hint);
3907349cc55cSDimitry Andric       else
3908349cc55cSDimitry Andric         return SendErrorResponse(Status("Unsupported qSaveCore option"));
3909349cc55cSDimitry Andric     }
3910349cc55cSDimitry Andric   }
3911349cc55cSDimitry Andric 
3912349cc55cSDimitry Andric   llvm::Expected<std::string> ret = m_current_process->SaveCore(path_hint);
3913349cc55cSDimitry Andric   if (!ret)
3914349cc55cSDimitry Andric     return SendErrorResponse(ret.takeError());
3915349cc55cSDimitry Andric 
3916349cc55cSDimitry Andric   StreamString response;
3917349cc55cSDimitry Andric   response.PutCString("core-path:");
3918349cc55cSDimitry Andric   response.PutStringAsRawHex8(ret.get());
3919349cc55cSDimitry Andric   return SendPacketNoLock(response.GetString());
3920349cc55cSDimitry Andric }
3921349cc55cSDimitry Andric 
392281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
392381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QNonStop(
392481ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
3925fcaf7f86SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3926fcaf7f86SDimitry Andric 
392781ad6265SDimitry Andric   StringRef packet_str{packet.GetStringRef()};
392881ad6265SDimitry Andric   assert(packet_str.startswith("QNonStop:"));
392981ad6265SDimitry Andric   packet_str.consume_front("QNonStop:");
393081ad6265SDimitry Andric   if (packet_str == "0") {
3931fcaf7f86SDimitry Andric     if (m_non_stop)
3932fcaf7f86SDimitry Andric       StopSTDIOForwarding();
3933fcaf7f86SDimitry Andric     for (auto &process_it : m_debugged_processes) {
3934fcaf7f86SDimitry Andric       if (process_it.second.process_up->IsRunning()) {
3935fcaf7f86SDimitry Andric         assert(m_non_stop);
3936fcaf7f86SDimitry Andric         Status error = process_it.second.process_up->Interrupt();
3937fcaf7f86SDimitry Andric         if (error.Fail()) {
3938fcaf7f86SDimitry Andric           LLDB_LOG(log,
3939fcaf7f86SDimitry Andric                    "while disabling nonstop, failed to halt process {0}: {1}",
3940fcaf7f86SDimitry Andric                    process_it.first, error);
3941fcaf7f86SDimitry Andric           return SendErrorResponse(0x41);
3942fcaf7f86SDimitry Andric         }
3943fcaf7f86SDimitry Andric         // we must not send stop reasons after QNonStop
3944fcaf7f86SDimitry Andric         m_disabling_non_stop = true;
3945fcaf7f86SDimitry Andric       }
3946fcaf7f86SDimitry Andric     }
3947fcaf7f86SDimitry Andric     m_stdio_notification_queue.clear();
3948fcaf7f86SDimitry Andric     m_stop_notification_queue.clear();
394981ad6265SDimitry Andric     m_non_stop = false;
3950fcaf7f86SDimitry Andric     // If we are stopping anything, defer sending the OK response until we're
3951fcaf7f86SDimitry Andric     // done.
3952fcaf7f86SDimitry Andric     if (m_disabling_non_stop)
3953fcaf7f86SDimitry Andric       return PacketResult::Success;
395481ad6265SDimitry Andric   } else if (packet_str == "1") {
3955fcaf7f86SDimitry Andric     if (!m_non_stop)
3956fcaf7f86SDimitry Andric       StartSTDIOForwarding();
395781ad6265SDimitry Andric     m_non_stop = true;
395881ad6265SDimitry Andric   } else
395981ad6265SDimitry Andric     return SendErrorResponse(Status("Invalid QNonStop packet"));
396081ad6265SDimitry Andric   return SendOKResponse();
396181ad6265SDimitry Andric }
396281ad6265SDimitry Andric 
396381ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
3964fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::HandleNotificationAck(
3965fcaf7f86SDimitry Andric     std::deque<std::string> &queue) {
3966fcaf7f86SDimitry Andric   // Per the protocol, the first message put into the queue is sent
3967fcaf7f86SDimitry Andric   // immediately.  However, it remains the queue until the client ACKs it --
3968fcaf7f86SDimitry Andric   // then we pop it and send the next message.  The process repeats until
3969fcaf7f86SDimitry Andric   // the last message in the queue is ACK-ed, in which case the packet sends
3970fcaf7f86SDimitry Andric   // an OK response.
3971fcaf7f86SDimitry Andric   if (queue.empty())
3972fcaf7f86SDimitry Andric     return SendErrorResponse(Status("No pending notification to ack"));
3973fcaf7f86SDimitry Andric   queue.pop_front();
3974fcaf7f86SDimitry Andric   if (!queue.empty())
3975fcaf7f86SDimitry Andric     return SendPacketNoLock(queue.front());
3976fcaf7f86SDimitry Andric   return SendOKResponse();
3977fcaf7f86SDimitry Andric }
3978fcaf7f86SDimitry Andric 
3979fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult
3980fcaf7f86SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStdio(
3981fcaf7f86SDimitry Andric     StringExtractorGDBRemote &packet) {
3982fcaf7f86SDimitry Andric   return HandleNotificationAck(m_stdio_notification_queue);
3983fcaf7f86SDimitry Andric }
3984fcaf7f86SDimitry Andric 
3985fcaf7f86SDimitry Andric GDBRemoteCommunication::PacketResult
398681ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStopped(
398781ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
3988fcaf7f86SDimitry Andric   PacketResult ret = HandleNotificationAck(m_stop_notification_queue);
398981ad6265SDimitry Andric   // If this was the last notification and all the processes exited,
399081ad6265SDimitry Andric   // terminate the server.
3991fcaf7f86SDimitry Andric   if (m_stop_notification_queue.empty() && m_debugged_processes.empty()) {
399281ad6265SDimitry Andric     m_exit_now = true;
399381ad6265SDimitry Andric     m_mainloop.RequestTermination();
399481ad6265SDimitry Andric   }
3995fcaf7f86SDimitry Andric   return ret;
399681ad6265SDimitry Andric }
399781ad6265SDimitry Andric 
399881ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
399981ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCtrlC(
400081ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
400181ad6265SDimitry Andric   if (!m_non_stop)
400281ad6265SDimitry Andric     return SendErrorResponse(Status("vCtrl is only valid in non-stop mode"));
400381ad6265SDimitry Andric 
400481ad6265SDimitry Andric   PacketResult interrupt_res = Handle_interrupt(packet);
400581ad6265SDimitry Andric   // If interrupting the process failed, pass the result through.
400681ad6265SDimitry Andric   if (interrupt_res != PacketResult::Success)
400781ad6265SDimitry Andric     return interrupt_res;
400881ad6265SDimitry Andric   // Otherwise, vCtrlC should issue an OK response (normal interrupts do not).
400981ad6265SDimitry Andric   return SendOKResponse();
401081ad6265SDimitry Andric }
401181ad6265SDimitry Andric 
401281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
401381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_T(StringExtractorGDBRemote &packet) {
401481ad6265SDimitry Andric   packet.SetFilePos(strlen("T"));
401581ad6265SDimitry Andric   auto pid_tid = packet.GetPidTid(m_current_process ? m_current_process->GetID()
401681ad6265SDimitry Andric                                                     : LLDB_INVALID_PROCESS_ID);
401781ad6265SDimitry Andric   if (!pid_tid)
401881ad6265SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
401981ad6265SDimitry Andric         inconvertibleErrorCode(), "Malformed thread-id"));
402081ad6265SDimitry Andric 
402181ad6265SDimitry Andric   lldb::pid_t pid = pid_tid->first;
402281ad6265SDimitry Andric   lldb::tid_t tid = pid_tid->second;
402381ad6265SDimitry Andric 
402481ad6265SDimitry Andric   // Technically, this would also be caught by the PID check but let's be more
402581ad6265SDimitry Andric   // explicit about the error.
402681ad6265SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
402781ad6265SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
402881ad6265SDimitry Andric         inconvertibleErrorCode(), "No current process and no PID provided"));
402981ad6265SDimitry Andric 
403081ad6265SDimitry Andric   // Check the process ID and find respective process instance.
403181ad6265SDimitry Andric   auto new_process_it = m_debugged_processes.find(pid);
403281ad6265SDimitry Andric   if (new_process_it == m_debugged_processes.end())
403381ad6265SDimitry Andric     return SendErrorResponse(1);
403481ad6265SDimitry Andric 
403581ad6265SDimitry Andric   // Check the thread ID
4036fcaf7f86SDimitry Andric   if (!new_process_it->second.process_up->GetThreadByID(tid))
403781ad6265SDimitry Andric     return SendErrorResponse(2);
403881ad6265SDimitry Andric 
403981ad6265SDimitry Andric   return SendOKResponse();
404081ad6265SDimitry Andric }
404181ad6265SDimitry Andric 
40420b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
404381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
40440b57cec5SDimitry Andric 
40450b57cec5SDimitry Andric   // Tell the stdio connection to shut down.
40460b57cec5SDimitry Andric   if (m_stdio_communication.IsConnected()) {
40470b57cec5SDimitry Andric     auto connection = m_stdio_communication.GetConnection();
40480b57cec5SDimitry Andric     if (connection) {
40490b57cec5SDimitry Andric       Status error;
40500b57cec5SDimitry Andric       connection->Disconnect(&error);
40510b57cec5SDimitry Andric 
40520b57cec5SDimitry Andric       if (error.Success()) {
40539dba64beSDimitry Andric         LLDB_LOGF(log,
40549dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s disconnect process "
40550b57cec5SDimitry Andric                   "terminal stdio - SUCCESS",
40560b57cec5SDimitry Andric                   __FUNCTION__);
40570b57cec5SDimitry Andric       } else {
40589dba64beSDimitry Andric         LLDB_LOGF(log,
40599dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s disconnect process "
40600b57cec5SDimitry Andric                   "terminal stdio - FAIL: %s",
40610b57cec5SDimitry Andric                   __FUNCTION__, error.AsCString());
40620b57cec5SDimitry Andric       }
40630b57cec5SDimitry Andric     }
40640b57cec5SDimitry Andric   }
40650b57cec5SDimitry Andric }
40660b57cec5SDimitry Andric 
40670b57cec5SDimitry Andric NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
40680b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
40690b57cec5SDimitry Andric   // We have no thread if we don't have a process.
4070fe6060f1SDimitry Andric   if (!m_current_process ||
4071fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
40720b57cec5SDimitry Andric     return nullptr;
40730b57cec5SDimitry Andric 
40740b57cec5SDimitry Andric   // If the client hasn't asked for thread suffix support, there will not be a
40750b57cec5SDimitry Andric   // thread suffix. Use the current thread in that case.
40760b57cec5SDimitry Andric   if (!m_thread_suffix_supported) {
40770b57cec5SDimitry Andric     const lldb::tid_t current_tid = GetCurrentThreadID();
40780b57cec5SDimitry Andric     if (current_tid == LLDB_INVALID_THREAD_ID)
40790b57cec5SDimitry Andric       return nullptr;
40800b57cec5SDimitry Andric     else if (current_tid == 0) {
40810b57cec5SDimitry Andric       // Pick a thread.
4082fe6060f1SDimitry Andric       return m_current_process->GetThreadAtIndex(0);
40830b57cec5SDimitry Andric     } else
4084fe6060f1SDimitry Andric       return m_current_process->GetThreadByID(current_tid);
40850b57cec5SDimitry Andric   }
40860b57cec5SDimitry Andric 
408781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
40880b57cec5SDimitry Andric 
40890b57cec5SDimitry Andric   // Parse out the ';'.
40900b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') {
40919dba64beSDimitry Andric     LLDB_LOGF(log,
40929dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
40930b57cec5SDimitry Andric               "error: expected ';' prior to start of thread suffix: packet "
40940b57cec5SDimitry Andric               "contents = '%s'",
40959dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
40960b57cec5SDimitry Andric     return nullptr;
40970b57cec5SDimitry Andric   }
40980b57cec5SDimitry Andric 
40990b57cec5SDimitry Andric   if (!packet.GetBytesLeft())
41000b57cec5SDimitry Andric     return nullptr;
41010b57cec5SDimitry Andric 
41020b57cec5SDimitry Andric   // Parse out thread: portion.
41030b57cec5SDimitry Andric   if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) {
41049dba64beSDimitry Andric     LLDB_LOGF(log,
41059dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
41060b57cec5SDimitry Andric               "error: expected 'thread:' but not found, packet contents = "
41070b57cec5SDimitry Andric               "'%s'",
41089dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
41090b57cec5SDimitry Andric     return nullptr;
41100b57cec5SDimitry Andric   }
41110b57cec5SDimitry Andric   packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
41120b57cec5SDimitry Andric   const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
41130b57cec5SDimitry Andric   if (tid != 0)
4114fe6060f1SDimitry Andric     return m_current_process->GetThreadByID(tid);
41150b57cec5SDimitry Andric 
41160b57cec5SDimitry Andric   return nullptr;
41170b57cec5SDimitry Andric }
41180b57cec5SDimitry Andric 
41190b57cec5SDimitry Andric lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
41200b57cec5SDimitry Andric   if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
41210b57cec5SDimitry Andric     // Use whatever the debug process says is the current thread id since the
41220b57cec5SDimitry Andric     // protocol either didn't specify or specified we want any/all threads
41230b57cec5SDimitry Andric     // marked as the current thread.
4124fe6060f1SDimitry Andric     if (!m_current_process)
41250b57cec5SDimitry Andric       return LLDB_INVALID_THREAD_ID;
4126fe6060f1SDimitry Andric     return m_current_process->GetCurrentThreadID();
41270b57cec5SDimitry Andric   }
41280b57cec5SDimitry Andric   // Use the specific current thread id set by the gdb remote protocol.
41290b57cec5SDimitry Andric   return m_current_tid;
41300b57cec5SDimitry Andric }
41310b57cec5SDimitry Andric 
41320b57cec5SDimitry Andric uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() {
41330b57cec5SDimitry Andric   std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
41340b57cec5SDimitry Andric   return m_next_saved_registers_id++;
41350b57cec5SDimitry Andric }
41360b57cec5SDimitry Andric 
41370b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
413881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
41390b57cec5SDimitry Andric 
41400b57cec5SDimitry Andric   LLDB_LOG(log, "clearing {0} xfer buffers", m_xfer_buffer_map.size());
41410b57cec5SDimitry Andric   m_xfer_buffer_map.clear();
41420b57cec5SDimitry Andric }
41430b57cec5SDimitry Andric 
41440b57cec5SDimitry Andric FileSpec
41450b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
41460b57cec5SDimitry Andric                                                  const ArchSpec &arch) {
4147fe6060f1SDimitry Andric   if (m_current_process) {
41480b57cec5SDimitry Andric     FileSpec file_spec;
4149fe6060f1SDimitry Andric     if (m_current_process
41500b57cec5SDimitry Andric             ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
41510b57cec5SDimitry Andric             .Success()) {
41520b57cec5SDimitry Andric       if (FileSystem::Instance().Exists(file_spec))
41530b57cec5SDimitry Andric         return file_spec;
41540b57cec5SDimitry Andric     }
41550b57cec5SDimitry Andric   }
41560b57cec5SDimitry Andric 
41570b57cec5SDimitry Andric   return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch);
41580b57cec5SDimitry Andric }
41599dba64beSDimitry Andric 
41609dba64beSDimitry Andric std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue(
41619dba64beSDimitry Andric     llvm::StringRef value) {
41629dba64beSDimitry Andric   std::string result;
41639dba64beSDimitry Andric   for (const char &c : value) {
41649dba64beSDimitry Andric     switch (c) {
41659dba64beSDimitry Andric     case '\'':
41669dba64beSDimitry Andric       result += "&apos;";
41679dba64beSDimitry Andric       break;
41689dba64beSDimitry Andric     case '"':
41699dba64beSDimitry Andric       result += "&quot;";
41709dba64beSDimitry Andric       break;
41719dba64beSDimitry Andric     case '<':
41729dba64beSDimitry Andric       result += "&lt;";
41739dba64beSDimitry Andric       break;
41749dba64beSDimitry Andric     case '>':
41759dba64beSDimitry Andric       result += "&gt;";
41769dba64beSDimitry Andric       break;
41779dba64beSDimitry Andric     default:
41789dba64beSDimitry Andric       result += c;
41799dba64beSDimitry Andric       break;
41809dba64beSDimitry Andric     }
41819dba64beSDimitry Andric   }
41829dba64beSDimitry Andric   return result;
41839dba64beSDimitry Andric }
4184fe6060f1SDimitry Andric 
4185fe6060f1SDimitry Andric std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
4186fe6060f1SDimitry Andric     const llvm::ArrayRef<llvm::StringRef> client_features) {
4187fe6060f1SDimitry Andric   std::vector<std::string> ret =
4188fe6060f1SDimitry Andric       GDBRemoteCommunicationServerCommon::HandleFeatures(client_features);
4189fe6060f1SDimitry Andric   ret.insert(ret.end(), {
4190fe6060f1SDimitry Andric                             "QThreadSuffixSupported+",
4191fe6060f1SDimitry Andric                             "QListThreadsInStopReply+",
4192fe6060f1SDimitry Andric                             "qXfer:features:read+",
419381ad6265SDimitry Andric                             "QNonStop+",
4194fe6060f1SDimitry Andric                         });
4195fe6060f1SDimitry Andric 
4196fe6060f1SDimitry Andric   // report server-only features
4197fe6060f1SDimitry Andric   using Extension = NativeProcessProtocol::Extension;
4198fe6060f1SDimitry Andric   Extension plugin_features = m_process_factory.GetSupportedExtensions();
4199fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::pass_signals))
4200fe6060f1SDimitry Andric     ret.push_back("QPassSignals+");
4201fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::auxv))
4202fe6060f1SDimitry Andric     ret.push_back("qXfer:auxv:read+");
4203fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::libraries_svr4))
4204fe6060f1SDimitry Andric     ret.push_back("qXfer:libraries-svr4:read+");
420504eeddc0SDimitry Andric   if (bool(plugin_features & Extension::siginfo_read))
420604eeddc0SDimitry Andric     ret.push_back("qXfer:siginfo:read+");
4207fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::memory_tagging))
4208fe6060f1SDimitry Andric     ret.push_back("memory-tagging+");
4209349cc55cSDimitry Andric   if (bool(plugin_features & Extension::savecore))
4210349cc55cSDimitry Andric     ret.push_back("qSaveCore+");
4211fe6060f1SDimitry Andric 
4212fe6060f1SDimitry Andric   // check for client features
4213fe6060f1SDimitry Andric   m_extensions_supported = {};
4214fe6060f1SDimitry Andric   for (llvm::StringRef x : client_features)
4215fe6060f1SDimitry Andric     m_extensions_supported |=
4216fe6060f1SDimitry Andric         llvm::StringSwitch<Extension>(x)
4217fe6060f1SDimitry Andric             .Case("multiprocess+", Extension::multiprocess)
4218fe6060f1SDimitry Andric             .Case("fork-events+", Extension::fork)
4219fe6060f1SDimitry Andric             .Case("vfork-events+", Extension::vfork)
4220fe6060f1SDimitry Andric             .Default({});
4221fe6060f1SDimitry Andric 
4222fe6060f1SDimitry Andric   m_extensions_supported &= plugin_features;
4223fe6060f1SDimitry Andric 
4224fe6060f1SDimitry Andric   // fork & vfork require multiprocess
4225fe6060f1SDimitry Andric   if (!bool(m_extensions_supported & Extension::multiprocess))
4226fe6060f1SDimitry Andric     m_extensions_supported &= ~(Extension::fork | Extension::vfork);
4227fe6060f1SDimitry Andric 
4228fe6060f1SDimitry Andric   // report only if actually supported
4229fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::multiprocess))
4230fe6060f1SDimitry Andric     ret.push_back("multiprocess+");
4231fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::fork))
4232fe6060f1SDimitry Andric     ret.push_back("fork-events+");
4233fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::vfork))
4234fe6060f1SDimitry Andric     ret.push_back("vfork-events+");
4235fe6060f1SDimitry Andric 
4236fe6060f1SDimitry Andric   for (auto &x : m_debugged_processes)
4237fcaf7f86SDimitry Andric     SetEnabledExtensions(*x.second.process_up);
4238fe6060f1SDimitry Andric   return ret;
4239fe6060f1SDimitry Andric }
4240fe6060f1SDimitry Andric 
4241fe6060f1SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
4242fe6060f1SDimitry Andric     NativeProcessProtocol &process) {
4243fe6060f1SDimitry Andric   NativeProcessProtocol::Extension flags = m_extensions_supported;
4244fe6060f1SDimitry Andric   assert(!bool(flags & ~m_process_factory.GetSupportedExtensions()));
4245fe6060f1SDimitry Andric   process.SetEnabledExtensions(flags);
4246fe6060f1SDimitry Andric }
4247349cc55cSDimitry Andric 
424881ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
424981ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() {
4250fcaf7f86SDimitry Andric   if (m_non_stop)
4251fcaf7f86SDimitry Andric     return SendOKResponse();
425281ad6265SDimitry Andric   StartSTDIOForwarding();
4253fcaf7f86SDimitry Andric   return PacketResult::Success;
425481ad6265SDimitry Andric }
425581ad6265SDimitry Andric 
425681ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse(
425781ad6265SDimitry Andric     Stream &response, lldb::pid_t pid, lldb::tid_t tid) {
425881ad6265SDimitry Andric   if (bool(m_extensions_supported &
425981ad6265SDimitry Andric            NativeProcessProtocol::Extension::multiprocess))
426081ad6265SDimitry Andric     response.Format("p{0:x-}.", pid);
426181ad6265SDimitry Andric   response.Format("{0:x-}", tid);
426281ad6265SDimitry Andric }
426381ad6265SDimitry Andric 
4264349cc55cSDimitry Andric std::string
4265349cc55cSDimitry Andric lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg,
4266349cc55cSDimitry Andric                                                bool reverse_connect) {
4267349cc55cSDimitry Andric   // Try parsing the argument as URL.
4268349cc55cSDimitry Andric   if (llvm::Optional<URI> url = URI::Parse(url_arg)) {
4269349cc55cSDimitry Andric     if (reverse_connect)
4270349cc55cSDimitry Andric       return url_arg.str();
4271349cc55cSDimitry Andric 
4272349cc55cSDimitry Andric     // Translate the scheme from LLGS notation to ConnectionFileDescriptor.
4273349cc55cSDimitry Andric     // If the scheme doesn't match any, pass it through to support using CFD
4274349cc55cSDimitry Andric     // schemes directly.
4275349cc55cSDimitry Andric     std::string new_url = llvm::StringSwitch<std::string>(url->scheme)
4276349cc55cSDimitry Andric                               .Case("tcp", "listen")
4277349cc55cSDimitry Andric                               .Case("unix", "unix-accept")
4278349cc55cSDimitry Andric                               .Case("unix-abstract", "unix-abstract-accept")
4279349cc55cSDimitry Andric                               .Default(url->scheme.str());
4280349cc55cSDimitry Andric     llvm::append_range(new_url, url_arg.substr(url->scheme.size()));
4281349cc55cSDimitry Andric     return new_url;
4282349cc55cSDimitry Andric   }
4283349cc55cSDimitry Andric 
4284349cc55cSDimitry Andric   std::string host_port = url_arg.str();
4285349cc55cSDimitry Andric   // If host_and_port starts with ':', default the host to be "localhost" and
4286349cc55cSDimitry Andric   // expect the remainder to be the port.
4287349cc55cSDimitry Andric   if (url_arg.startswith(":"))
4288349cc55cSDimitry Andric     host_port.insert(0, "localhost");
4289349cc55cSDimitry Andric 
4290349cc55cSDimitry Andric   // Try parsing the (preprocessed) argument as host:port pair.
4291349cc55cSDimitry Andric   if (!llvm::errorToBool(Socket::DecodeHostAndPort(host_port).takeError()))
4292349cc55cSDimitry Andric     return (reverse_connect ? "connect://" : "listen://") + host_port;
4293349cc55cSDimitry Andric 
4294349cc55cSDimitry Andric   // If none of the above applied, interpret the argument as UNIX socket path.
4295349cc55cSDimitry Andric   return (reverse_connect ? "unix-connect://" : "unix-accept://") +
4296349cc55cSDimitry Andric          url_arg.str();
4297349cc55cSDimitry Andric }
4298