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(
24981ad6265SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vStopped,
25081ad6265SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vStopped);
25181ad6265SDimitry Andric   RegisterMemberFunctionHandler(
25281ad6265SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vCtrlC,
25381ad6265SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vCtrlC);
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) {
2570b57cec5SDimitry Andric   m_process_launch_info = info;
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
26181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   if (!m_process_launch_info.GetArguments().GetArgumentCount())
2640b57cec5SDimitry Andric     return Status("%s: no process command line specified to launch",
2650b57cec5SDimitry Andric                   __FUNCTION__);
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   const bool should_forward_stdio =
2680b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
2690b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
2700b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr;
2710b57cec5SDimitry Andric   m_process_launch_info.SetLaunchInSeparateProcessGroup(true);
2720b57cec5SDimitry Andric   m_process_launch_info.GetFlags().Set(eLaunchFlagDebug);
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   if (should_forward_stdio) {
2759dba64beSDimitry Andric     // Temporarily relax the following for Windows until we can take advantage
2769dba64beSDimitry Andric     // of the recently added pty support. This doesn't really affect the use of
2779dba64beSDimitry Andric     // lldb-server on Windows.
2789dba64beSDimitry Andric #if !defined(_WIN32)
2790b57cec5SDimitry Andric     if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection())
2800b57cec5SDimitry Andric       return Status(std::move(Err));
2819dba64beSDimitry Andric #endif
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   {
2850b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
286fe6060f1SDimitry Andric     assert(m_debugged_processes.empty() && "lldb-server creating debugged "
2870b57cec5SDimitry Andric                                            "process but one already exists");
2880b57cec5SDimitry Andric     auto process_or =
2890b57cec5SDimitry Andric         m_process_factory.Launch(m_process_launch_info, *this, m_mainloop);
2900b57cec5SDimitry Andric     if (!process_or)
2910b57cec5SDimitry Andric       return Status(process_or.takeError());
292fe6060f1SDimitry Andric     m_continue_process = m_current_process = process_or->get();
293fe6060f1SDimitry Andric     m_debugged_processes[m_current_process->GetID()] = std::move(*process_or);
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric 
296fe6060f1SDimitry Andric   SetEnabledExtensions(*m_current_process);
297fe6060f1SDimitry Andric 
2980b57cec5SDimitry Andric   // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
2990b57cec5SDimitry Andric   // needed. llgs local-process debugging may specify PTY paths, which will
3000b57cec5SDimitry Andric   // make these file actions non-null process launch -i/e/o will also make
3010b57cec5SDimitry Andric   // these file actions non-null nullptr means that the traffic is expected to
3020b57cec5SDimitry Andric   // flow over gdb-remote protocol
3030b57cec5SDimitry Andric   if (should_forward_stdio) {
3040b57cec5SDimitry Andric     // nullptr means it's not redirected to file or pty (in case of LLGS local)
3050b57cec5SDimitry Andric     // at least one of stdio will be transferred pty<->gdb-remote we need to
306349cc55cSDimitry Andric     // give the pty primary handle to this object to read and/or write
3070b57cec5SDimitry Andric     LLDB_LOG(log,
3080b57cec5SDimitry Andric              "pid = {0}: setting up stdout/stderr redirection via $O "
3090b57cec5SDimitry Andric              "gdb-remote commands",
310fe6060f1SDimitry Andric              m_current_process->GetID());
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric     // Setup stdout/stderr mapping from inferior to $O
313fe6060f1SDimitry Andric     auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
3140b57cec5SDimitry Andric     if (terminal_fd >= 0) {
3159dba64beSDimitry Andric       LLDB_LOGF(log,
3169dba64beSDimitry Andric                 "ProcessGDBRemoteCommunicationServerLLGS::%s setting "
3170b57cec5SDimitry Andric                 "inferior STDIO fd to %d",
3180b57cec5SDimitry Andric                 __FUNCTION__, terminal_fd);
3190b57cec5SDimitry Andric       Status status = SetSTDIOFileDescriptor(terminal_fd);
3200b57cec5SDimitry Andric       if (status.Fail())
3210b57cec5SDimitry Andric         return status;
3220b57cec5SDimitry Andric     } else {
3239dba64beSDimitry Andric       LLDB_LOGF(log,
3249dba64beSDimitry Andric                 "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
3250b57cec5SDimitry Andric                 "inferior STDIO since terminal fd reported as %d",
3260b57cec5SDimitry Andric                 __FUNCTION__, terminal_fd);
3270b57cec5SDimitry Andric     }
3280b57cec5SDimitry Andric   } else {
3290b57cec5SDimitry Andric     LLDB_LOG(log,
3300b57cec5SDimitry Andric              "pid = {0} skipping stdout/stderr redirection via $O: inferior "
3310b57cec5SDimitry Andric              "will communicate over client-provided file descriptors",
332fe6060f1SDimitry Andric              m_current_process->GetID());
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   printf("Launched '%s' as process %" PRIu64 "...\n",
3360b57cec5SDimitry Andric          m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
337fe6060f1SDimitry Andric          m_current_process->GetID());
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   return Status();
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
34381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3449dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64,
3450b57cec5SDimitry Andric             __FUNCTION__, pid);
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   // Before we try to attach, make sure we aren't already monitoring something
3480b57cec5SDimitry Andric   // else.
349fe6060f1SDimitry Andric   if (!m_debugged_processes.empty())
3500b57cec5SDimitry Andric     return Status("cannot attach to process %" PRIu64
3510b57cec5SDimitry Andric                   " when another process with pid %" PRIu64
3520b57cec5SDimitry Andric                   " is being debugged.",
353fe6060f1SDimitry Andric                   pid, m_current_process->GetID());
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   // Try to attach.
3560b57cec5SDimitry Andric   auto process_or = m_process_factory.Attach(pid, *this, m_mainloop);
3570b57cec5SDimitry Andric   if (!process_or) {
3580b57cec5SDimitry Andric     Status status(process_or.takeError());
359349cc55cSDimitry Andric     llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}\n", pid,
3600b57cec5SDimitry Andric                                   status);
3610b57cec5SDimitry Andric     return status;
3620b57cec5SDimitry Andric   }
363fe6060f1SDimitry Andric   m_continue_process = m_current_process = process_or->get();
364fe6060f1SDimitry Andric   m_debugged_processes[m_current_process->GetID()] = std::move(*process_or);
365fe6060f1SDimitry Andric   SetEnabledExtensions(*m_current_process);
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   // Setup stdout/stderr mapping from inferior.
368fe6060f1SDimitry Andric   auto terminal_fd = m_current_process->GetTerminalFileDescriptor();
3690b57cec5SDimitry Andric   if (terminal_fd >= 0) {
3709dba64beSDimitry Andric     LLDB_LOGF(log,
3719dba64beSDimitry Andric               "ProcessGDBRemoteCommunicationServerLLGS::%s setting "
3720b57cec5SDimitry Andric               "inferior STDIO fd to %d",
3730b57cec5SDimitry Andric               __FUNCTION__, terminal_fd);
3740b57cec5SDimitry Andric     Status status = SetSTDIOFileDescriptor(terminal_fd);
3750b57cec5SDimitry Andric     if (status.Fail())
3760b57cec5SDimitry Andric       return status;
3770b57cec5SDimitry Andric   } else {
3789dba64beSDimitry Andric     LLDB_LOGF(log,
3799dba64beSDimitry Andric               "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
3800b57cec5SDimitry Andric               "inferior STDIO since terminal fd reported as %d",
3810b57cec5SDimitry Andric               __FUNCTION__, terminal_fd);
3820b57cec5SDimitry Andric   }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   printf("Attached to process %" PRIu64 "...\n", pid);
3850b57cec5SDimitry Andric   return Status();
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
388e8d8bef9SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess(
389e8d8bef9SDimitry Andric     llvm::StringRef process_name, bool include_existing) {
39081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
391e8d8bef9SDimitry Andric 
392e8d8bef9SDimitry Andric   std::chrono::milliseconds polling_interval = std::chrono::milliseconds(1);
393e8d8bef9SDimitry Andric 
394e8d8bef9SDimitry Andric   // Create the matcher used to search the process list.
395e8d8bef9SDimitry Andric   ProcessInstanceInfoList exclusion_list;
396e8d8bef9SDimitry Andric   ProcessInstanceInfoMatch match_info;
397e8d8bef9SDimitry Andric   match_info.GetProcessInfo().GetExecutableFile().SetFile(
398e8d8bef9SDimitry Andric       process_name, llvm::sys::path::Style::native);
399e8d8bef9SDimitry Andric   match_info.SetNameMatchType(NameMatch::Equals);
400e8d8bef9SDimitry Andric 
401e8d8bef9SDimitry Andric   if (include_existing) {
402e8d8bef9SDimitry Andric     LLDB_LOG(log, "including existing processes in search");
403e8d8bef9SDimitry Andric   } else {
404e8d8bef9SDimitry Andric     // Create the excluded process list before polling begins.
405e8d8bef9SDimitry Andric     Host::FindProcesses(match_info, exclusion_list);
406e8d8bef9SDimitry Andric     LLDB_LOG(log, "placed '{0}' processes in the exclusion list.",
407e8d8bef9SDimitry Andric              exclusion_list.size());
408e8d8bef9SDimitry Andric   }
409e8d8bef9SDimitry Andric 
410e8d8bef9SDimitry Andric   LLDB_LOG(log, "waiting for '{0}' to appear", process_name);
411e8d8bef9SDimitry Andric 
412e8d8bef9SDimitry Andric   auto is_in_exclusion_list =
413e8d8bef9SDimitry Andric       [&exclusion_list](const ProcessInstanceInfo &info) {
414e8d8bef9SDimitry Andric         for (auto &excluded : exclusion_list) {
415e8d8bef9SDimitry Andric           if (excluded.GetProcessID() == info.GetProcessID())
416e8d8bef9SDimitry Andric             return true;
417e8d8bef9SDimitry Andric         }
418e8d8bef9SDimitry Andric         return false;
419e8d8bef9SDimitry Andric       };
420e8d8bef9SDimitry Andric 
421e8d8bef9SDimitry Andric   ProcessInstanceInfoList loop_process_list;
422e8d8bef9SDimitry Andric   while (true) {
423e8d8bef9SDimitry Andric     loop_process_list.clear();
424e8d8bef9SDimitry Andric     if (Host::FindProcesses(match_info, loop_process_list)) {
425e8d8bef9SDimitry Andric       // Remove all the elements that are in the exclusion list.
426e8d8bef9SDimitry Andric       llvm::erase_if(loop_process_list, is_in_exclusion_list);
427e8d8bef9SDimitry Andric 
428e8d8bef9SDimitry Andric       // One match! We found the desired process.
429e8d8bef9SDimitry Andric       if (loop_process_list.size() == 1) {
430e8d8bef9SDimitry Andric         auto matching_process_pid = loop_process_list[0].GetProcessID();
431e8d8bef9SDimitry Andric         LLDB_LOG(log, "found pid {0}", matching_process_pid);
432e8d8bef9SDimitry Andric         return AttachToProcess(matching_process_pid);
433e8d8bef9SDimitry Andric       }
434e8d8bef9SDimitry Andric 
435e8d8bef9SDimitry Andric       // Multiple matches! Return an error reporting the PIDs we found.
436e8d8bef9SDimitry Andric       if (loop_process_list.size() > 1) {
437e8d8bef9SDimitry Andric         StreamString error_stream;
438e8d8bef9SDimitry Andric         error_stream.Format(
439e8d8bef9SDimitry Andric             "Multiple executables with name: '{0}' found. Pids: ",
440e8d8bef9SDimitry Andric             process_name);
441e8d8bef9SDimitry Andric         for (size_t i = 0; i < loop_process_list.size() - 1; ++i) {
442e8d8bef9SDimitry Andric           error_stream.Format("{0}, ", loop_process_list[i].GetProcessID());
443e8d8bef9SDimitry Andric         }
444e8d8bef9SDimitry Andric         error_stream.Format("{0}.", loop_process_list.back().GetProcessID());
445e8d8bef9SDimitry Andric 
446e8d8bef9SDimitry Andric         Status error;
447e8d8bef9SDimitry Andric         error.SetErrorString(error_stream.GetString());
448e8d8bef9SDimitry Andric         return error;
449e8d8bef9SDimitry Andric       }
450e8d8bef9SDimitry Andric     }
451e8d8bef9SDimitry Andric     // No matches, we have not found the process. Sleep until next poll.
452e8d8bef9SDimitry Andric     LLDB_LOG(log, "sleep {0} seconds", polling_interval);
453e8d8bef9SDimitry Andric     std::this_thread::sleep_for(polling_interval);
454e8d8bef9SDimitry Andric   }
455e8d8bef9SDimitry Andric }
456e8d8bef9SDimitry Andric 
4570b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::InitializeDelegate(
4580b57cec5SDimitry Andric     NativeProcessProtocol *process) {
4590b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
46081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
4610b57cec5SDimitry Andric   if (log) {
4629dba64beSDimitry Andric     LLDB_LOGF(log,
4639dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s called with "
4640b57cec5SDimitry Andric               "NativeProcessProtocol pid %" PRIu64 ", current state: %s",
4650b57cec5SDimitry Andric               __FUNCTION__, process->GetID(),
4660b57cec5SDimitry Andric               StateAsCString(process->GetState()));
4670b57cec5SDimitry Andric   }
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4710b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendWResponse(
4720b57cec5SDimitry Andric     NativeProcessProtocol *process) {
4730b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
47481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   // send W notification
4770b57cec5SDimitry Andric   auto wait_status = process->GetExitStatus();
4780b57cec5SDimitry Andric   if (!wait_status) {
4790b57cec5SDimitry Andric     LLDB_LOG(log, "pid = {0}, failed to retrieve process exit status",
4800b57cec5SDimitry Andric              process->GetID());
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric     StreamGDBRemote response;
4830b57cec5SDimitry Andric     response.PutChar('E');
4840b57cec5SDimitry Andric     response.PutHex8(GDBRemoteServerError::eErrorExitStatus);
4850b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
4860b57cec5SDimitry Andric   }
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(),
4890b57cec5SDimitry Andric            *wait_status);
4900b57cec5SDimitry Andric 
49181ad6265SDimitry Andric   // If the process was killed through vKill, return "OK".
49281ad6265SDimitry Andric   if (m_vkilled_processes.find(process->GetID()) != m_vkilled_processes.end())
49381ad6265SDimitry Andric     return SendOKResponse();
49481ad6265SDimitry Andric 
4950b57cec5SDimitry Andric   StreamGDBRemote response;
4960b57cec5SDimitry Andric   response.Format("{0:g}", *wait_status);
49781ad6265SDimitry Andric   if (bool(m_extensions_supported & NativeProcessProtocol::Extension::multiprocess))
49881ad6265SDimitry Andric     response.Format(";process:{0:x-}", process->GetID());
49981ad6265SDimitry Andric   if (m_non_stop)
50081ad6265SDimitry Andric     return SendNotificationPacketNoLock("Stop", m_stop_notification_queue,
50181ad6265SDimitry Andric                                         response.GetString());
5020b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric static void AppendHexValue(StreamString &response, const uint8_t *buf,
5060b57cec5SDimitry Andric                            uint32_t buf_size, bool swap) {
5070b57cec5SDimitry Andric   int64_t i;
5080b57cec5SDimitry Andric   if (swap) {
5090b57cec5SDimitry Andric     for (i = buf_size - 1; i >= 0; i--)
5100b57cec5SDimitry Andric       response.PutHex8(buf[i]);
5110b57cec5SDimitry Andric   } else {
5120b57cec5SDimitry Andric     for (i = 0; i < buf_size; i++)
5130b57cec5SDimitry Andric       response.PutHex8(buf[i]);
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric 
5175ffd83dbSDimitry Andric static llvm::StringRef GetEncodingNameOrEmpty(const RegisterInfo &reg_info) {
5185ffd83dbSDimitry Andric   switch (reg_info.encoding) {
5195ffd83dbSDimitry Andric   case eEncodingUint:
5205ffd83dbSDimitry Andric     return "uint";
5215ffd83dbSDimitry Andric   case eEncodingSint:
5225ffd83dbSDimitry Andric     return "sint";
5235ffd83dbSDimitry Andric   case eEncodingIEEE754:
5245ffd83dbSDimitry Andric     return "ieee754";
5255ffd83dbSDimitry Andric   case eEncodingVector:
5265ffd83dbSDimitry Andric     return "vector";
5275ffd83dbSDimitry Andric   default:
5285ffd83dbSDimitry Andric     return "";
5295ffd83dbSDimitry Andric   }
5305ffd83dbSDimitry Andric }
5315ffd83dbSDimitry Andric 
5325ffd83dbSDimitry Andric static llvm::StringRef GetFormatNameOrEmpty(const RegisterInfo &reg_info) {
5335ffd83dbSDimitry Andric   switch (reg_info.format) {
5345ffd83dbSDimitry Andric   case eFormatBinary:
5355ffd83dbSDimitry Andric     return "binary";
5365ffd83dbSDimitry Andric   case eFormatDecimal:
5375ffd83dbSDimitry Andric     return "decimal";
5385ffd83dbSDimitry Andric   case eFormatHex:
5395ffd83dbSDimitry Andric     return "hex";
5405ffd83dbSDimitry Andric   case eFormatFloat:
5415ffd83dbSDimitry Andric     return "float";
5425ffd83dbSDimitry Andric   case eFormatVectorOfSInt8:
5435ffd83dbSDimitry Andric     return "vector-sint8";
5445ffd83dbSDimitry Andric   case eFormatVectorOfUInt8:
5455ffd83dbSDimitry Andric     return "vector-uint8";
5465ffd83dbSDimitry Andric   case eFormatVectorOfSInt16:
5475ffd83dbSDimitry Andric     return "vector-sint16";
5485ffd83dbSDimitry Andric   case eFormatVectorOfUInt16:
5495ffd83dbSDimitry Andric     return "vector-uint16";
5505ffd83dbSDimitry Andric   case eFormatVectorOfSInt32:
5515ffd83dbSDimitry Andric     return "vector-sint32";
5525ffd83dbSDimitry Andric   case eFormatVectorOfUInt32:
5535ffd83dbSDimitry Andric     return "vector-uint32";
5545ffd83dbSDimitry Andric   case eFormatVectorOfFloat32:
5555ffd83dbSDimitry Andric     return "vector-float32";
5565ffd83dbSDimitry Andric   case eFormatVectorOfUInt64:
5575ffd83dbSDimitry Andric     return "vector-uint64";
5585ffd83dbSDimitry Andric   case eFormatVectorOfUInt128:
5595ffd83dbSDimitry Andric     return "vector-uint128";
5605ffd83dbSDimitry Andric   default:
5615ffd83dbSDimitry Andric     return "";
5625ffd83dbSDimitry Andric   };
5635ffd83dbSDimitry Andric }
5645ffd83dbSDimitry Andric 
5655ffd83dbSDimitry Andric static llvm::StringRef GetKindGenericOrEmpty(const RegisterInfo &reg_info) {
5665ffd83dbSDimitry Andric   switch (reg_info.kinds[RegisterKind::eRegisterKindGeneric]) {
5675ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_PC:
5685ffd83dbSDimitry Andric     return "pc";
5695ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_SP:
5705ffd83dbSDimitry Andric     return "sp";
5715ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_FP:
5725ffd83dbSDimitry Andric     return "fp";
5735ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_RA:
5745ffd83dbSDimitry Andric     return "ra";
5755ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_FLAGS:
5765ffd83dbSDimitry Andric     return "flags";
5775ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG1:
5785ffd83dbSDimitry Andric     return "arg1";
5795ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG2:
5805ffd83dbSDimitry Andric     return "arg2";
5815ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG3:
5825ffd83dbSDimitry Andric     return "arg3";
5835ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG4:
5845ffd83dbSDimitry Andric     return "arg4";
5855ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG5:
5865ffd83dbSDimitry Andric     return "arg5";
5875ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG6:
5885ffd83dbSDimitry Andric     return "arg6";
5895ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG7:
5905ffd83dbSDimitry Andric     return "arg7";
5915ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG8:
5925ffd83dbSDimitry Andric     return "arg8";
5935ffd83dbSDimitry Andric   default:
5945ffd83dbSDimitry Andric     return "";
5955ffd83dbSDimitry Andric   }
5965ffd83dbSDimitry Andric }
5975ffd83dbSDimitry Andric 
5985ffd83dbSDimitry Andric static void CollectRegNums(const uint32_t *reg_num, StreamString &response,
5995ffd83dbSDimitry Andric                            bool usehex) {
6005ffd83dbSDimitry Andric   for (int i = 0; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) {
6015ffd83dbSDimitry Andric     if (i > 0)
6025ffd83dbSDimitry Andric       response.PutChar(',');
6035ffd83dbSDimitry Andric     if (usehex)
6045ffd83dbSDimitry Andric       response.Printf("%" PRIx32, *reg_num);
6055ffd83dbSDimitry Andric     else
6065ffd83dbSDimitry Andric       response.Printf("%" PRIu32, *reg_num);
6075ffd83dbSDimitry Andric   }
6085ffd83dbSDimitry Andric }
6095ffd83dbSDimitry Andric 
6100b57cec5SDimitry Andric static void WriteRegisterValueInHexFixedWidth(
6110b57cec5SDimitry Andric     StreamString &response, NativeRegisterContext &reg_ctx,
6120b57cec5SDimitry Andric     const RegisterInfo &reg_info, const RegisterValue *reg_value_p,
6130b57cec5SDimitry Andric     lldb::ByteOrder byte_order) {
6140b57cec5SDimitry Andric   RegisterValue reg_value;
6150b57cec5SDimitry Andric   if (!reg_value_p) {
6160b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(&reg_info, reg_value);
6170b57cec5SDimitry Andric     if (error.Success())
6180b57cec5SDimitry Andric       reg_value_p = &reg_value;
6190b57cec5SDimitry Andric     // else log.
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric   if (reg_value_p) {
6230b57cec5SDimitry Andric     AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(),
6240b57cec5SDimitry Andric                    reg_value_p->GetByteSize(),
6250b57cec5SDimitry Andric                    byte_order == lldb::eByteOrderLittle);
6260b57cec5SDimitry Andric   } else {
6270b57cec5SDimitry Andric     // Zero-out any unreadable values.
6280b57cec5SDimitry Andric     if (reg_info.byte_size > 0) {
6290b57cec5SDimitry Andric       std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0');
6300b57cec5SDimitry Andric       AppendHexValue(response, zeros.data(), zeros.size(), false);
6310b57cec5SDimitry Andric     }
6320b57cec5SDimitry Andric   }
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
635e8d8bef9SDimitry Andric static llvm::Optional<json::Object>
6369dba64beSDimitry Andric GetRegistersAsJSON(NativeThreadProtocol &thread) {
63781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   NativeRegisterContext& reg_ctx = thread.GetRegisterContext();
6400b57cec5SDimitry Andric 
6419dba64beSDimitry Andric   json::Object register_object;
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
644e8d8bef9SDimitry Andric   const auto expedited_regs =
645e8d8bef9SDimitry Andric       reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Full);
6460b57cec5SDimitry Andric #else
647e8d8bef9SDimitry Andric   const auto expedited_regs =
648e8d8bef9SDimitry Andric       reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Minimal);
6490b57cec5SDimitry Andric #endif
650e8d8bef9SDimitry Andric   if (expedited_regs.empty())
651e8d8bef9SDimitry Andric     return llvm::None;
6520b57cec5SDimitry Andric 
653e8d8bef9SDimitry Andric   for (auto &reg_num : expedited_regs) {
6540b57cec5SDimitry Andric     const RegisterInfo *const reg_info_p =
6550b57cec5SDimitry Andric         reg_ctx.GetRegisterInfoAtIndex(reg_num);
6560b57cec5SDimitry Andric     if (reg_info_p == nullptr) {
6579dba64beSDimitry Andric       LLDB_LOGF(log,
6580b57cec5SDimitry Andric                 "%s failed to get register info for register index %" PRIu32,
6590b57cec5SDimitry Andric                 __FUNCTION__, reg_num);
6600b57cec5SDimitry Andric       continue;
6610b57cec5SDimitry Andric     }
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric     if (reg_info_p->value_regs != nullptr)
6640b57cec5SDimitry Andric       continue; // Only expedite registers that are not contained in other
6650b57cec5SDimitry Andric                 // registers.
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric     RegisterValue reg_value;
6680b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
6690b57cec5SDimitry Andric     if (error.Fail()) {
6709dba64beSDimitry Andric       LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s",
6710b57cec5SDimitry Andric                 __FUNCTION__,
6720b57cec5SDimitry Andric                 reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
6730b57cec5SDimitry Andric                 reg_num, error.AsCString());
6740b57cec5SDimitry Andric       continue;
6750b57cec5SDimitry Andric     }
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric     StreamString stream;
6780b57cec5SDimitry Andric     WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p,
6790b57cec5SDimitry Andric                                       &reg_value, lldb::eByteOrderBig);
6800b57cec5SDimitry Andric 
6819dba64beSDimitry Andric     register_object.try_emplace(llvm::to_string(reg_num),
6829dba64beSDimitry Andric                                 stream.GetString().str());
6830b57cec5SDimitry Andric   }
6840b57cec5SDimitry Andric 
6859dba64beSDimitry Andric   return register_object;
6860b57cec5SDimitry Andric }
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric static const char *GetStopReasonString(StopReason stop_reason) {
6890b57cec5SDimitry Andric   switch (stop_reason) {
6900b57cec5SDimitry Andric   case eStopReasonTrace:
6910b57cec5SDimitry Andric     return "trace";
6920b57cec5SDimitry Andric   case eStopReasonBreakpoint:
6930b57cec5SDimitry Andric     return "breakpoint";
6940b57cec5SDimitry Andric   case eStopReasonWatchpoint:
6950b57cec5SDimitry Andric     return "watchpoint";
6960b57cec5SDimitry Andric   case eStopReasonSignal:
6970b57cec5SDimitry Andric     return "signal";
6980b57cec5SDimitry Andric   case eStopReasonException:
6990b57cec5SDimitry Andric     return "exception";
7000b57cec5SDimitry Andric   case eStopReasonExec:
7010b57cec5SDimitry Andric     return "exec";
702fe6060f1SDimitry Andric   case eStopReasonProcessorTrace:
703fe6060f1SDimitry Andric     return "processor trace";
704fe6060f1SDimitry Andric   case eStopReasonFork:
705fe6060f1SDimitry Andric     return "fork";
706fe6060f1SDimitry Andric   case eStopReasonVFork:
707fe6060f1SDimitry Andric     return "vfork";
708fe6060f1SDimitry Andric   case eStopReasonVForkDone:
709fe6060f1SDimitry Andric     return "vforkdone";
7100b57cec5SDimitry Andric   case eStopReasonInstrumentation:
7110b57cec5SDimitry Andric   case eStopReasonInvalid:
7120b57cec5SDimitry Andric   case eStopReasonPlanComplete:
7130b57cec5SDimitry Andric   case eStopReasonThreadExiting:
7140b57cec5SDimitry Andric   case eStopReasonNone:
7150b57cec5SDimitry Andric     break; // ignored
7160b57cec5SDimitry Andric   }
7170b57cec5SDimitry Andric   return nullptr;
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric 
7209dba64beSDimitry Andric static llvm::Expected<json::Array>
7219dba64beSDimitry Andric GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) {
72281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
7230b57cec5SDimitry Andric 
7249dba64beSDimitry Andric   json::Array threads_array;
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric   // Ensure we can get info on the given thread.
72781ad6265SDimitry Andric   for (NativeThreadProtocol &thread : process.Threads()) {
72881ad6265SDimitry Andric     lldb::tid_t tid = thread.GetID();
7290b57cec5SDimitry Andric     // Grab the reason this thread stopped.
7300b57cec5SDimitry Andric     struct ThreadStopInfo tid_stop_info;
7310b57cec5SDimitry Andric     std::string description;
73281ad6265SDimitry Andric     if (!thread.GetStopReason(tid_stop_info, description))
7339dba64beSDimitry Andric       return llvm::make_error<llvm::StringError>(
7349dba64beSDimitry Andric           "failed to get stop reason", llvm::inconvertibleErrorCode());
7350b57cec5SDimitry Andric 
73681ad6265SDimitry Andric     const int signum = tid_stop_info.signo;
7370b57cec5SDimitry Andric     if (log) {
7389dba64beSDimitry Andric       LLDB_LOGF(log,
7399dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
7400b57cec5SDimitry Andric                 " tid %" PRIu64
7410b57cec5SDimitry Andric                 " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
7420b57cec5SDimitry Andric                 __FUNCTION__, process.GetID(), tid, signum,
7430b57cec5SDimitry Andric                 tid_stop_info.reason, tid_stop_info.details.exception.type);
7440b57cec5SDimitry Andric     }
7450b57cec5SDimitry Andric 
7469dba64beSDimitry Andric     json::Object thread_obj;
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric     if (!abridged) {
74981ad6265SDimitry Andric       if (llvm::Optional<json::Object> registers = GetRegistersAsJSON(thread))
7509dba64beSDimitry Andric         thread_obj.try_emplace("registers", std::move(*registers));
7510b57cec5SDimitry Andric     }
7520b57cec5SDimitry Andric 
7539dba64beSDimitry Andric     thread_obj.try_emplace("tid", static_cast<int64_t>(tid));
7549dba64beSDimitry Andric 
7550b57cec5SDimitry Andric     if (signum != 0)
7569dba64beSDimitry Andric       thread_obj.try_emplace("signal", signum);
7570b57cec5SDimitry Andric 
75881ad6265SDimitry Andric     const std::string thread_name = thread.GetName();
7590b57cec5SDimitry Andric     if (!thread_name.empty())
7609dba64beSDimitry Andric       thread_obj.try_emplace("name", thread_name);
7610b57cec5SDimitry Andric 
7629dba64beSDimitry Andric     const char *stop_reason = GetStopReasonString(tid_stop_info.reason);
7639dba64beSDimitry Andric     if (stop_reason)
7649dba64beSDimitry Andric       thread_obj.try_emplace("reason", stop_reason);
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric     if (!description.empty())
7679dba64beSDimitry Andric       thread_obj.try_emplace("description", description);
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric     if ((tid_stop_info.reason == eStopReasonException) &&
7700b57cec5SDimitry Andric         tid_stop_info.details.exception.type) {
7719dba64beSDimitry Andric       thread_obj.try_emplace(
7729dba64beSDimitry Andric           "metype", static_cast<int64_t>(tid_stop_info.details.exception.type));
7730b57cec5SDimitry Andric 
7749dba64beSDimitry Andric       json::Array medata_array;
7750b57cec5SDimitry Andric       for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count;
7760b57cec5SDimitry Andric            ++i) {
7779dba64beSDimitry Andric         medata_array.push_back(
7789dba64beSDimitry Andric             static_cast<int64_t>(tid_stop_info.details.exception.data[i]));
7790b57cec5SDimitry Andric       }
7809dba64beSDimitry Andric       thread_obj.try_emplace("medata", std::move(medata_array));
7810b57cec5SDimitry Andric     }
7829dba64beSDimitry Andric     threads_array.push_back(std::move(thread_obj));
7830b57cec5SDimitry Andric   }
7849dba64beSDimitry Andric   return threads_array;
7850b57cec5SDimitry Andric }
7860b57cec5SDimitry Andric 
78781ad6265SDimitry Andric StreamString
78881ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::PrepareStopReplyPacketForThread(
78981ad6265SDimitry Andric     NativeThreadProtocol &thread) {
79081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
7910b57cec5SDimitry Andric 
79281ad6265SDimitry Andric   NativeProcessProtocol &process = thread.GetProcess();
7930b57cec5SDimitry Andric 
79481ad6265SDimitry Andric   LLDB_LOG(log, "preparing packet for pid {0} tid {1}", process.GetID(),
79581ad6265SDimitry Andric            thread.GetID());
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   // Grab the reason this thread stopped.
79881ad6265SDimitry Andric   StreamString response;
7990b57cec5SDimitry Andric   struct ThreadStopInfo tid_stop_info;
8000b57cec5SDimitry Andric   std::string description;
80181ad6265SDimitry Andric   if (!thread.GetStopReason(tid_stop_info, description))
80281ad6265SDimitry Andric     return response;
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric   // FIXME implement register handling for exec'd inferiors.
8050b57cec5SDimitry Andric   // if (tid_stop_info.reason == eStopReasonExec) {
8060b57cec5SDimitry Andric   //     const bool force = true;
8070b57cec5SDimitry Andric   //     InitializeRegisters(force);
8080b57cec5SDimitry Andric   // }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric   // Output the T packet with the thread
8110b57cec5SDimitry Andric   response.PutChar('T');
81281ad6265SDimitry Andric   int signum = tid_stop_info.signo;
8130b57cec5SDimitry Andric   LLDB_LOG(
8140b57cec5SDimitry Andric       log,
8150b57cec5SDimitry Andric       "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}",
81681ad6265SDimitry Andric       process.GetID(), thread.GetID(), signum, int(tid_stop_info.reason),
8170b57cec5SDimitry Andric       tid_stop_info.details.exception.type);
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric   // Print the signal number.
8200b57cec5SDimitry Andric   response.PutHex8(signum & 0xff);
8210b57cec5SDimitry Andric 
82281ad6265SDimitry Andric   // Include the (pid and) tid.
82381ad6265SDimitry Andric   response.PutCString("thread:");
82481ad6265SDimitry Andric   AppendThreadIDToResponse(response, process.GetID(), thread.GetID());
82581ad6265SDimitry Andric   response.PutChar(';');
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric   // Include the thread name if there is one.
82881ad6265SDimitry Andric   const std::string thread_name = thread.GetName();
8290b57cec5SDimitry Andric   if (!thread_name.empty()) {
8300b57cec5SDimitry Andric     size_t thread_name_len = thread_name.length();
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric     if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) {
8330b57cec5SDimitry Andric       response.PutCString("name:");
8340b57cec5SDimitry Andric       response.PutCString(thread_name);
8350b57cec5SDimitry Andric     } else {
8360b57cec5SDimitry Andric       // The thread name contains special chars, send as hex bytes.
8370b57cec5SDimitry Andric       response.PutCString("hexname:");
8380b57cec5SDimitry Andric       response.PutStringAsRawHex8(thread_name);
8390b57cec5SDimitry Andric     }
8400b57cec5SDimitry Andric     response.PutChar(';');
8410b57cec5SDimitry Andric   }
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric   // If a 'QListThreadsInStopReply' was sent to enable this feature, we will
8440b57cec5SDimitry Andric   // send all thread IDs back in the "threads" key whose value is a list of hex
8450b57cec5SDimitry Andric   // thread IDs separated by commas:
8460b57cec5SDimitry Andric   //  "threads:10a,10b,10c;"
8470b57cec5SDimitry Andric   // This will save the debugger from having to send a pair of qfThreadInfo and
8480b57cec5SDimitry Andric   // qsThreadInfo packets, but it also might take a lot of room in the stop
8490b57cec5SDimitry Andric   // reply packet, so it must be enabled only on systems where there are no
8500b57cec5SDimitry Andric   // limits on packet lengths.
8510b57cec5SDimitry Andric   if (m_list_threads_in_stop_reply) {
8520b57cec5SDimitry Andric     response.PutCString("threads:");
8530b57cec5SDimitry Andric 
85481ad6265SDimitry Andric     uint32_t thread_num = 0;
85581ad6265SDimitry Andric     for (NativeThreadProtocol &listed_thread : process.Threads()) {
85681ad6265SDimitry Andric       if (thread_num > 0)
8570b57cec5SDimitry Andric         response.PutChar(',');
85881ad6265SDimitry Andric       response.Printf("%" PRIx64, listed_thread.GetID());
85981ad6265SDimitry Andric       ++thread_num;
8600b57cec5SDimitry Andric     }
8610b57cec5SDimitry Andric     response.PutChar(';');
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric     // Include JSON info that describes the stop reason for any threads that
8640b57cec5SDimitry Andric     // actually have stop reasons. We use the new "jstopinfo" key whose values
8650b57cec5SDimitry Andric     // is hex ascii JSON that contains the thread IDs thread stop info only for
8660b57cec5SDimitry Andric     // threads that have stop reasons. Only send this if we have more than one
8670b57cec5SDimitry Andric     // thread otherwise this packet has all the info it needs.
86881ad6265SDimitry Andric     if (thread_num > 1) {
8690b57cec5SDimitry Andric       const bool threads_with_valid_stop_info_only = true;
8709dba64beSDimitry Andric       llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo(
871fe6060f1SDimitry Andric           *m_current_process, threads_with_valid_stop_info_only);
8729dba64beSDimitry Andric       if (threads_info) {
8730b57cec5SDimitry Andric         response.PutCString("jstopinfo:");
8740b57cec5SDimitry Andric         StreamString unescaped_response;
8759dba64beSDimitry Andric         unescaped_response.AsRawOstream() << std::move(*threads_info);
8760b57cec5SDimitry Andric         response.PutStringAsRawHex8(unescaped_response.GetData());
8770b57cec5SDimitry Andric         response.PutChar(';');
8789dba64beSDimitry Andric       } else {
879480093f4SDimitry Andric         LLDB_LOG_ERROR(log, threads_info.takeError(),
880480093f4SDimitry Andric                        "failed to prepare a jstopinfo field for pid {1}: {0}",
88181ad6265SDimitry Andric                        process.GetID());
8829dba64beSDimitry Andric       }
8830b57cec5SDimitry Andric     }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric     response.PutCString("thread-pcs");
8860b57cec5SDimitry Andric     char delimiter = ':';
88781ad6265SDimitry Andric     for (NativeThreadProtocol &thread : process.Threads()) {
88881ad6265SDimitry Andric       NativeRegisterContext &reg_ctx = thread.GetRegisterContext();
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric       uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber(
8910b57cec5SDimitry Andric           eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
8920b57cec5SDimitry Andric       const RegisterInfo *const reg_info_p =
8930b57cec5SDimitry Andric           reg_ctx.GetRegisterInfoAtIndex(reg_to_read);
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric       RegisterValue reg_value;
8960b57cec5SDimitry Andric       Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
8970b57cec5SDimitry Andric       if (error.Fail()) {
8989dba64beSDimitry Andric         LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s",
8990b57cec5SDimitry Andric                   __FUNCTION__,
9009dba64beSDimitry Andric                   reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
9010b57cec5SDimitry Andric                   reg_to_read, error.AsCString());
9020b57cec5SDimitry Andric         continue;
9030b57cec5SDimitry Andric       }
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric       response.PutChar(delimiter);
9060b57cec5SDimitry Andric       delimiter = ',';
9070b57cec5SDimitry Andric       WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p,
9080b57cec5SDimitry Andric                                         &reg_value, endian::InlHostByteOrder());
9090b57cec5SDimitry Andric     }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric     response.PutChar(';');
9120b57cec5SDimitry Andric   }
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric   //
9150b57cec5SDimitry Andric   // Expedite registers.
9160b57cec5SDimitry Andric   //
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric   // Grab the register context.
91981ad6265SDimitry Andric   NativeRegisterContext &reg_ctx = thread.GetRegisterContext();
920e8d8bef9SDimitry Andric   const auto expedited_regs =
921e8d8bef9SDimitry Andric       reg_ctx.GetExpeditedRegisters(ExpeditedRegs::Full);
9220b57cec5SDimitry Andric 
923e8d8bef9SDimitry Andric   for (auto &reg_num : expedited_regs) {
9240b57cec5SDimitry Andric     const RegisterInfo *const reg_info_p =
925e8d8bef9SDimitry Andric         reg_ctx.GetRegisterInfoAtIndex(reg_num);
9260b57cec5SDimitry Andric     // Only expediate registers that are not contained in other registers.
927e8d8bef9SDimitry Andric     if (reg_info_p != nullptr && reg_info_p->value_regs == nullptr) {
9280b57cec5SDimitry Andric       RegisterValue reg_value;
9290b57cec5SDimitry Andric       Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
9300b57cec5SDimitry Andric       if (error.Success()) {
931e8d8bef9SDimitry Andric         response.Printf("%.02x:", reg_num);
9320b57cec5SDimitry Andric         WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p,
9330b57cec5SDimitry Andric                                           &reg_value, lldb::eByteOrderBig);
9340b57cec5SDimitry Andric         response.PutChar(';');
9350b57cec5SDimitry Andric       } else {
93681ad6265SDimitry Andric         LLDB_LOGF(log,
93781ad6265SDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s failed to read "
9380b57cec5SDimitry Andric                   "register '%s' index %" PRIu32 ": %s",
9390b57cec5SDimitry Andric                   __FUNCTION__,
9409dba64beSDimitry Andric                   reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
941e8d8bef9SDimitry Andric                   reg_num, error.AsCString());
9420b57cec5SDimitry Andric       }
9430b57cec5SDimitry Andric     }
9440b57cec5SDimitry Andric   }
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric   const char *reason_str = GetStopReasonString(tid_stop_info.reason);
9470b57cec5SDimitry Andric   if (reason_str != nullptr) {
9480b57cec5SDimitry Andric     response.Printf("reason:%s;", reason_str);
9490b57cec5SDimitry Andric   }
9500b57cec5SDimitry Andric 
9510b57cec5SDimitry Andric   if (!description.empty()) {
9520b57cec5SDimitry Andric     // Description may contains special chars, send as hex bytes.
9530b57cec5SDimitry Andric     response.PutCString("description:");
9540b57cec5SDimitry Andric     response.PutStringAsRawHex8(description);
9550b57cec5SDimitry Andric     response.PutChar(';');
9560b57cec5SDimitry Andric   } else if ((tid_stop_info.reason == eStopReasonException) &&
9570b57cec5SDimitry Andric              tid_stop_info.details.exception.type) {
9580b57cec5SDimitry Andric     response.PutCString("metype:");
9590b57cec5SDimitry Andric     response.PutHex64(tid_stop_info.details.exception.type);
9600b57cec5SDimitry Andric     response.PutCString(";mecount:");
9610b57cec5SDimitry Andric     response.PutHex32(tid_stop_info.details.exception.data_count);
9620b57cec5SDimitry Andric     response.PutChar(';');
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric     for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) {
9650b57cec5SDimitry Andric       response.PutCString("medata:");
9660b57cec5SDimitry Andric       response.PutHex64(tid_stop_info.details.exception.data[i]);
9670b57cec5SDimitry Andric       response.PutChar(';');
9680b57cec5SDimitry Andric     }
9690b57cec5SDimitry Andric   }
9700b57cec5SDimitry Andric 
971fe6060f1SDimitry Andric   // Include child process PID/TID for forks.
972fe6060f1SDimitry Andric   if (tid_stop_info.reason == eStopReasonFork ||
973fe6060f1SDimitry Andric       tid_stop_info.reason == eStopReasonVFork) {
974fe6060f1SDimitry Andric     assert(bool(m_extensions_supported &
975fe6060f1SDimitry Andric                 NativeProcessProtocol::Extension::multiprocess));
976fe6060f1SDimitry Andric     if (tid_stop_info.reason == eStopReasonFork)
977fe6060f1SDimitry Andric       assert(bool(m_extensions_supported &
978fe6060f1SDimitry Andric                   NativeProcessProtocol::Extension::fork));
979fe6060f1SDimitry Andric     if (tid_stop_info.reason == eStopReasonVFork)
980fe6060f1SDimitry Andric       assert(bool(m_extensions_supported &
981fe6060f1SDimitry Andric                   NativeProcessProtocol::Extension::vfork));
982fe6060f1SDimitry Andric     response.Printf("%s:p%" PRIx64 ".%" PRIx64 ";", reason_str,
983fe6060f1SDimitry Andric                     tid_stop_info.details.fork.child_pid,
984fe6060f1SDimitry Andric                     tid_stop_info.details.fork.child_tid);
985fe6060f1SDimitry Andric   }
986fe6060f1SDimitry Andric 
98781ad6265SDimitry Andric   return response;
98881ad6265SDimitry Andric }
98981ad6265SDimitry Andric 
99081ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
99181ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
99281ad6265SDimitry Andric     NativeProcessProtocol &process, lldb::tid_t tid, bool force_synchronous) {
99381ad6265SDimitry Andric   // Ensure we can get info on the given thread.
99481ad6265SDimitry Andric   NativeThreadProtocol *thread = process.GetThreadByID(tid);
99581ad6265SDimitry Andric   if (!thread)
99681ad6265SDimitry Andric     return SendErrorResponse(51);
99781ad6265SDimitry Andric 
99881ad6265SDimitry Andric   StreamString response = PrepareStopReplyPacketForThread(*thread);
99981ad6265SDimitry Andric   if (response.Empty())
100081ad6265SDimitry Andric     return SendErrorResponse(42);
100181ad6265SDimitry Andric 
100281ad6265SDimitry Andric   if (m_non_stop && !force_synchronous) {
100381ad6265SDimitry Andric     PacketResult ret = SendNotificationPacketNoLock(
100481ad6265SDimitry Andric         "Stop", m_stop_notification_queue, response.GetString());
100581ad6265SDimitry Andric     // Queue notification events for the remaining threads.
100681ad6265SDimitry Andric     EnqueueStopReplyPackets(tid);
100781ad6265SDimitry Andric     return ret;
100881ad6265SDimitry Andric   }
100981ad6265SDimitry Andric 
10100b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
10110b57cec5SDimitry Andric }
10120b57cec5SDimitry Andric 
101381ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::EnqueueStopReplyPackets(
101481ad6265SDimitry Andric     lldb::tid_t thread_to_skip) {
101581ad6265SDimitry Andric   if (!m_non_stop)
101681ad6265SDimitry Andric     return;
101781ad6265SDimitry Andric 
101881ad6265SDimitry Andric   for (NativeThreadProtocol &listed_thread : m_current_process->Threads()) {
101981ad6265SDimitry Andric     if (listed_thread.GetID() != thread_to_skip)
102081ad6265SDimitry Andric       m_stop_notification_queue.push_back(
102181ad6265SDimitry Andric           PrepareStopReplyPacketForThread(listed_thread).GetString().str());
102281ad6265SDimitry Andric   }
102381ad6265SDimitry Andric }
102481ad6265SDimitry Andric 
10250b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
10260b57cec5SDimitry Andric     NativeProcessProtocol *process) {
10270b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
10280b57cec5SDimitry Andric 
102981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
10309dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
10310b57cec5SDimitry Andric 
103281ad6265SDimitry Andric   PacketResult result = SendStopReasonForState(
103381ad6265SDimitry Andric       *process, StateType::eStateExited, /*force_synchronous=*/false);
10340b57cec5SDimitry Andric   if (result != PacketResult::Success) {
10359dba64beSDimitry Andric     LLDB_LOGF(log,
10369dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to send stop "
10370b57cec5SDimitry Andric               "notification for PID %" PRIu64 ", state: eStateExited",
10380b57cec5SDimitry Andric               __FUNCTION__, process->GetID());
10390b57cec5SDimitry Andric   }
10400b57cec5SDimitry Andric 
104181ad6265SDimitry Andric   if (m_current_process == process)
104281ad6265SDimitry Andric     m_current_process = nullptr;
104381ad6265SDimitry Andric   if (m_continue_process == process)
104481ad6265SDimitry Andric     m_continue_process = nullptr;
104581ad6265SDimitry Andric 
104681ad6265SDimitry Andric   lldb::pid_t pid = process->GetID();
104781ad6265SDimitry Andric   m_mainloop.AddPendingCallback([this, pid](MainLoopBase &loop) {
104881ad6265SDimitry Andric     m_debugged_processes.erase(pid);
104981ad6265SDimitry Andric     auto vkill_it = m_vkilled_processes.find(pid);
105081ad6265SDimitry Andric     if (vkill_it != m_vkilled_processes.end())
105181ad6265SDimitry Andric       m_vkilled_processes.erase(vkill_it);
105281ad6265SDimitry Andric     // Terminate the main loop only if vKill has not been used.
105381ad6265SDimitry Andric     // When running in non-stop mode, wait for the vStopped to clear
105481ad6265SDimitry Andric     // the notification queue.
105581ad6265SDimitry Andric     else if (m_debugged_processes.empty() && !m_non_stop) {
105681ad6265SDimitry Andric       // Close the pipe to the inferior terminal i/o if we launched it and set
105781ad6265SDimitry Andric       // one up.
10580b57cec5SDimitry Andric       MaybeCloseInferiorTerminalConnection();
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric       // We are ready to exit the debug monitor.
10610b57cec5SDimitry Andric       m_exit_now = true;
106281ad6265SDimitry Andric       loop.RequestTermination();
106381ad6265SDimitry Andric     }
106481ad6265SDimitry Andric   });
10650b57cec5SDimitry Andric }
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
10680b57cec5SDimitry Andric     NativeProcessProtocol *process) {
10690b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
10700b57cec5SDimitry Andric 
107181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
10729dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   // Send the stop reason unless this is the stop after the launch or attach.
10750b57cec5SDimitry Andric   switch (m_inferior_prev_state) {
10760b57cec5SDimitry Andric   case eStateLaunching:
10770b57cec5SDimitry Andric   case eStateAttaching:
10780b57cec5SDimitry Andric     // Don't send anything per debugserver behavior.
10790b57cec5SDimitry Andric     break;
10800b57cec5SDimitry Andric   default:
10810b57cec5SDimitry Andric     // In all other cases, send the stop reason.
108281ad6265SDimitry Andric     PacketResult result = SendStopReasonForState(
108381ad6265SDimitry Andric         *process, StateType::eStateStopped, /*force_synchronous=*/false);
10840b57cec5SDimitry Andric     if (result != PacketResult::Success) {
10859dba64beSDimitry Andric       LLDB_LOGF(log,
10869dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s failed to send stop "
10870b57cec5SDimitry Andric                 "notification for PID %" PRIu64 ", state: eStateExited",
10880b57cec5SDimitry Andric                 __FUNCTION__, process->GetID());
10890b57cec5SDimitry Andric     }
10900b57cec5SDimitry Andric     break;
10910b57cec5SDimitry Andric   }
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
10950b57cec5SDimitry Andric     NativeProcessProtocol *process, lldb::StateType state) {
10960b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
109781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
10980b57cec5SDimitry Andric   if (log) {
10999dba64beSDimitry Andric     LLDB_LOGF(log,
11009dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s called with "
11010b57cec5SDimitry Andric               "NativeProcessProtocol pid %" PRIu64 ", state: %s",
11020b57cec5SDimitry Andric               __FUNCTION__, process->GetID(), StateAsCString(state));
11030b57cec5SDimitry Andric   }
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   switch (state) {
11060b57cec5SDimitry Andric   case StateType::eStateRunning:
11070b57cec5SDimitry Andric     break;
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric   case StateType::eStateStopped:
11100b57cec5SDimitry Andric     // Make sure we get all of the pending stdout/stderr from the inferior and
11110b57cec5SDimitry Andric     // send it to the lldb host before we send the state change notification
11120b57cec5SDimitry Andric     SendProcessOutput();
11130b57cec5SDimitry Andric     // Then stop the forwarding, so that any late output (see llvm.org/pr25652)
11140b57cec5SDimitry Andric     // does not interfere with our protocol.
11150b57cec5SDimitry Andric     StopSTDIOForwarding();
11160b57cec5SDimitry Andric     HandleInferiorState_Stopped(process);
11170b57cec5SDimitry Andric     break;
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   case StateType::eStateExited:
11200b57cec5SDimitry Andric     // Same as above
11210b57cec5SDimitry Andric     SendProcessOutput();
11220b57cec5SDimitry Andric     StopSTDIOForwarding();
11230b57cec5SDimitry Andric     HandleInferiorState_Exited(process);
11240b57cec5SDimitry Andric     break;
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric   default:
11270b57cec5SDimitry Andric     if (log) {
11289dba64beSDimitry Andric       LLDB_LOGF(log,
11299dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s didn't handle state "
11300b57cec5SDimitry Andric                 "change for pid %" PRIu64 ", new state: %s",
11310b57cec5SDimitry Andric                 __FUNCTION__, process->GetID(), StateAsCString(state));
11320b57cec5SDimitry Andric     }
11330b57cec5SDimitry Andric     break;
11340b57cec5SDimitry Andric   }
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric   // Remember the previous state reported to us.
11370b57cec5SDimitry Andric   m_inferior_prev_state = state;
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());
1150fe6060f1SDimitry Andric   m_debugged_processes[child_pid] = std::move(child_process);
1151fe6060f1SDimitry Andric }
1152fe6060f1SDimitry Andric 
11530b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
115404eeddc0SDimitry Andric   Log *log = GetLog(GDBRLog::Comm);
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric   bool interrupt = false;
11570b57cec5SDimitry Andric   bool done = false;
11580b57cec5SDimitry Andric   Status error;
11590b57cec5SDimitry Andric   while (true) {
11600b57cec5SDimitry Andric     const PacketResult result = GetPacketAndSendResponse(
11610b57cec5SDimitry Andric         std::chrono::microseconds(0), error, interrupt, done);
11620b57cec5SDimitry Andric     if (result == PacketResult::ErrorReplyTimeout)
11630b57cec5SDimitry Andric       break; // No more packets in the queue
11640b57cec5SDimitry Andric 
11650b57cec5SDimitry Andric     if ((result != PacketResult::Success)) {
11669dba64beSDimitry Andric       LLDB_LOGF(log,
11679dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s processing a packet "
11680b57cec5SDimitry Andric                 "failed: %s",
11690b57cec5SDimitry Andric                 __FUNCTION__, error.AsCString());
11700b57cec5SDimitry Andric       m_mainloop.RequestTermination();
11710b57cec5SDimitry Andric       break;
11720b57cec5SDimitry Andric     }
11730b57cec5SDimitry Andric   }
11740b57cec5SDimitry Andric }
11750b57cec5SDimitry Andric 
11760b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::InitializeConnection(
11775ffd83dbSDimitry Andric     std::unique_ptr<Connection> connection) {
11780b57cec5SDimitry Andric   IOObjectSP read_object_sp = connection->GetReadObject();
11795ffd83dbSDimitry Andric   GDBRemoteCommunicationServer::SetConnection(std::move(connection));
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric   Status error;
11820b57cec5SDimitry Andric   m_network_handle_up = m_mainloop.RegisterReadObject(
11830b57cec5SDimitry Andric       read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); },
11840b57cec5SDimitry Andric       error);
11850b57cec5SDimitry Andric   return error;
11860b57cec5SDimitry Andric }
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
11890b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer,
11900b57cec5SDimitry Andric                                                     uint32_t len) {
11910b57cec5SDimitry Andric   if ((buffer == nullptr) || (len == 0)) {
11920b57cec5SDimitry Andric     // Nothing to send.
11930b57cec5SDimitry Andric     return PacketResult::Success;
11940b57cec5SDimitry Andric   }
11950b57cec5SDimitry Andric 
11960b57cec5SDimitry Andric   StreamString response;
11970b57cec5SDimitry Andric   response.PutChar('O');
11980b57cec5SDimitry Andric   response.PutBytesAsRawHex8(buffer, len);
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
12010b57cec5SDimitry Andric }
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) {
12040b57cec5SDimitry Andric   Status error;
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric   // Set up the reading/handling of process I/O
12070b57cec5SDimitry Andric   std::unique_ptr<ConnectionFileDescriptor> conn_up(
12080b57cec5SDimitry Andric       new ConnectionFileDescriptor(fd, true));
12090b57cec5SDimitry Andric   if (!conn_up) {
12100b57cec5SDimitry Andric     error.SetErrorString("failed to create ConnectionFileDescriptor");
12110b57cec5SDimitry Andric     return error;
12120b57cec5SDimitry Andric   }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric   m_stdio_communication.SetCloseOnEOF(false);
12155ffd83dbSDimitry Andric   m_stdio_communication.SetConnection(std::move(conn_up));
12160b57cec5SDimitry Andric   if (!m_stdio_communication.IsConnected()) {
12170b57cec5SDimitry Andric     error.SetErrorString(
12180b57cec5SDimitry Andric         "failed to set connection for inferior I/O communication");
12190b57cec5SDimitry Andric     return error;
12200b57cec5SDimitry Andric   }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric   return Status();
12230b57cec5SDimitry Andric }
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() {
12260b57cec5SDimitry Andric   // Don't forward if not connected (e.g. when attaching).
12270b57cec5SDimitry Andric   if (!m_stdio_communication.IsConnected())
12280b57cec5SDimitry Andric     return;
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric   Status error;
123181ad6265SDimitry Andric   assert(!m_stdio_handle_up);
12320b57cec5SDimitry Andric   m_stdio_handle_up = m_mainloop.RegisterReadObject(
12330b57cec5SDimitry Andric       m_stdio_communication.GetConnection()->GetReadObject(),
12340b57cec5SDimitry Andric       [this](MainLoopBase &) { SendProcessOutput(); }, error);
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric   if (!m_stdio_handle_up) {
12370b57cec5SDimitry Andric     // Not much we can do about the failure. Log it and continue without
12380b57cec5SDimitry Andric     // forwarding.
123981ad6265SDimitry Andric     if (Log *log = GetLog(LLDBLog::Process))
124081ad6265SDimitry Andric       LLDB_LOG(log, "Failed to set up stdio forwarding: {0}", error);
12410b57cec5SDimitry Andric   }
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() {
12450b57cec5SDimitry Andric   m_stdio_handle_up.reset();
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric 
12480b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
12490b57cec5SDimitry Andric   char buffer[1024];
12500b57cec5SDimitry Andric   ConnectionStatus status;
12510b57cec5SDimitry Andric   Status error;
12520b57cec5SDimitry Andric   while (true) {
12530b57cec5SDimitry Andric     size_t bytes_read = m_stdio_communication.Read(
12540b57cec5SDimitry Andric         buffer, sizeof buffer, std::chrono::microseconds(0), status, &error);
12550b57cec5SDimitry Andric     switch (status) {
12560b57cec5SDimitry Andric     case eConnectionStatusSuccess:
12570b57cec5SDimitry Andric       SendONotification(buffer, bytes_read);
12580b57cec5SDimitry Andric       break;
12590b57cec5SDimitry Andric     case eConnectionStatusLostConnection:
12600b57cec5SDimitry Andric     case eConnectionStatusEndOfFile:
12610b57cec5SDimitry Andric     case eConnectionStatusError:
12620b57cec5SDimitry Andric     case eConnectionStatusNoConnection:
126381ad6265SDimitry Andric       if (Log *log = GetLog(LLDBLog::Process))
12649dba64beSDimitry Andric         LLDB_LOGF(log,
12659dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s Stopping stdio "
12660b57cec5SDimitry Andric                   "forwarding as communication returned status %d (error: "
12670b57cec5SDimitry Andric                   "%s)",
12680b57cec5SDimitry Andric                   __FUNCTION__, status, error.AsCString());
12690b57cec5SDimitry Andric       m_stdio_handle_up.reset();
12700b57cec5SDimitry Andric       return;
12710b57cec5SDimitry Andric 
12720b57cec5SDimitry Andric     case eConnectionStatusInterrupted:
12730b57cec5SDimitry Andric     case eConnectionStatusTimedOut:
12740b57cec5SDimitry Andric       return;
12750b57cec5SDimitry Andric     }
12760b57cec5SDimitry Andric   }
12770b57cec5SDimitry Andric }
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1280fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported(
12810b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
1282fe6060f1SDimitry Andric 
12830b57cec5SDimitry Andric   // Fail if we don't have a current process.
1284fe6060f1SDimitry Andric   if (!m_current_process ||
1285fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1286fe6060f1SDimitry Andric     return SendErrorResponse(Status("Process not running."));
12870b57cec5SDimitry Andric 
1288fe6060f1SDimitry Andric   return SendJSONResponse(m_current_process->TraceSupported());
12890b57cec5SDimitry Andric }
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1292fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop(
12930b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
12940b57cec5SDimitry Andric   // Fail if we don't have a current process.
1295fe6060f1SDimitry Andric   if (!m_current_process ||
1296fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1297fe6060f1SDimitry Andric     return SendErrorResponse(Status("Process not running."));
12980b57cec5SDimitry Andric 
1299fe6060f1SDimitry Andric   packet.ConsumeFront("jLLDBTraceStop:");
1300fe6060f1SDimitry Andric   Expected<TraceStopRequest> stop_request =
1301fe6060f1SDimitry Andric       json::parse<TraceStopRequest>(packet.Peek(), "TraceStopRequest");
1302fe6060f1SDimitry Andric   if (!stop_request)
1303fe6060f1SDimitry Andric     return SendErrorResponse(stop_request.takeError());
13040b57cec5SDimitry Andric 
1305fe6060f1SDimitry Andric   if (Error err = m_current_process->TraceStop(*stop_request))
1306fe6060f1SDimitry Andric     return SendErrorResponse(std::move(err));
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric   return SendOKResponse();
13090b57cec5SDimitry Andric }
13100b57cec5SDimitry Andric 
13110b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1312fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart(
1313e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
1314e8d8bef9SDimitry Andric 
1315e8d8bef9SDimitry Andric   // Fail if we don't have a current process.
1316fe6060f1SDimitry Andric   if (!m_current_process ||
1317fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1318e8d8bef9SDimitry Andric     return SendErrorResponse(Status("Process not running."));
1319e8d8bef9SDimitry Andric 
1320fe6060f1SDimitry Andric   packet.ConsumeFront("jLLDBTraceStart:");
1321fe6060f1SDimitry Andric   Expected<TraceStartRequest> request =
1322fe6060f1SDimitry Andric       json::parse<TraceStartRequest>(packet.Peek(), "TraceStartRequest");
1323fe6060f1SDimitry Andric   if (!request)
1324fe6060f1SDimitry Andric     return SendErrorResponse(request.takeError());
1325e8d8bef9SDimitry Andric 
1326fe6060f1SDimitry Andric   if (Error err = m_current_process->TraceStart(packet.Peek(), request->type))
1327fe6060f1SDimitry Andric     return SendErrorResponse(std::move(err));
1328e8d8bef9SDimitry Andric 
1329fe6060f1SDimitry Andric   return SendOKResponse();
1330e8d8bef9SDimitry Andric }
1331e8d8bef9SDimitry Andric 
1332e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
1333fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState(
13340b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   // Fail if we don't have a current process.
1337fe6060f1SDimitry Andric   if (!m_current_process ||
1338fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1339fe6060f1SDimitry Andric     return SendErrorResponse(Status("Process not running."));
13400b57cec5SDimitry Andric 
1341fe6060f1SDimitry Andric   packet.ConsumeFront("jLLDBTraceGetState:");
1342fe6060f1SDimitry Andric   Expected<TraceGetStateRequest> request =
1343fe6060f1SDimitry Andric       json::parse<TraceGetStateRequest>(packet.Peek(), "TraceGetStateRequest");
1344fe6060f1SDimitry Andric   if (!request)
1345fe6060f1SDimitry Andric     return SendErrorResponse(request.takeError());
13460b57cec5SDimitry Andric 
1347fe6060f1SDimitry Andric   return SendJSONResponse(m_current_process->TraceGetState(request->type));
13480b57cec5SDimitry Andric }
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1351fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData(
13520b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
13530b57cec5SDimitry Andric 
13540b57cec5SDimitry Andric   // Fail if we don't have a current process.
1355fe6060f1SDimitry Andric   if (!m_current_process ||
1356fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
1357fe6060f1SDimitry Andric     return SendErrorResponse(Status("Process not running."));
13580b57cec5SDimitry Andric 
1359fe6060f1SDimitry Andric   packet.ConsumeFront("jLLDBTraceGetBinaryData:");
1360fe6060f1SDimitry Andric   llvm::Expected<TraceGetBinaryDataRequest> request =
1361fe6060f1SDimitry Andric       llvm::json::parse<TraceGetBinaryDataRequest>(packet.Peek(),
1362fe6060f1SDimitry Andric                                                    "TraceGetBinaryDataRequest");
1363fe6060f1SDimitry Andric   if (!request)
1364fe6060f1SDimitry Andric     return SendErrorResponse(Status(request.takeError()));
13650b57cec5SDimitry Andric 
1366fe6060f1SDimitry Andric   if (Expected<std::vector<uint8_t>> bytes =
1367fe6060f1SDimitry Andric           m_current_process->TraceGetBinaryData(*request)) {
13680b57cec5SDimitry Andric     StreamGDBRemote response;
1369fe6060f1SDimitry Andric     response.PutEscapedBytes(bytes->data(), bytes->size());
1370fe6060f1SDimitry Andric     return SendPacketNoLock(response.GetString());
1371fe6060f1SDimitry Andric   } else
1372fe6060f1SDimitry Andric     return SendErrorResponse(bytes.takeError());
13730b57cec5SDimitry Andric }
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
13760b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
13770b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
13780b57cec5SDimitry Andric   // Fail if we don't have a current process.
1379fe6060f1SDimitry Andric   if (!m_current_process ||
1380fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
13810b57cec5SDimitry Andric     return SendErrorResponse(68);
13820b57cec5SDimitry Andric 
1383fe6060f1SDimitry Andric   lldb::pid_t pid = m_current_process->GetID();
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
13860b57cec5SDimitry Andric     return SendErrorResponse(1);
13870b57cec5SDimitry Andric 
13880b57cec5SDimitry Andric   ProcessInstanceInfo proc_info;
13890b57cec5SDimitry Andric   if (!Host::GetProcessInfo(pid, proc_info))
13900b57cec5SDimitry Andric     return SendErrorResponse(1);
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric   StreamString response;
13930b57cec5SDimitry Andric   CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
13940b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
13950b57cec5SDimitry Andric }
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
13980b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
13990b57cec5SDimitry Andric   // Fail if we don't have a current process.
1400fe6060f1SDimitry Andric   if (!m_current_process ||
1401fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
14020b57cec5SDimitry Andric     return SendErrorResponse(68);
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric   // Make sure we set the current thread so g and p packets return the data the
14050b57cec5SDimitry Andric   // gdb will expect.
1406fe6060f1SDimitry Andric   lldb::tid_t tid = m_current_process->GetCurrentThreadID();
14070b57cec5SDimitry Andric   SetCurrentThreadID(tid);
14080b57cec5SDimitry Andric 
1409fe6060f1SDimitry Andric   NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
14100b57cec5SDimitry Andric   if (!thread)
14110b57cec5SDimitry Andric     return SendErrorResponse(69);
14120b57cec5SDimitry Andric 
14130b57cec5SDimitry Andric   StreamString response;
141481ad6265SDimitry Andric   response.PutCString("QC");
141581ad6265SDimitry Andric   AppendThreadIDToResponse(response, m_current_process->GetID(),
141681ad6265SDimitry Andric                            thread->GetID());
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric 
14210b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14220b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
142381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric   StopSTDIOForwarding();
14260b57cec5SDimitry Andric 
142781ad6265SDimitry Andric   if (m_debugged_processes.empty()) {
14280b57cec5SDimitry Andric     LLDB_LOG(log, "No debugged process found.");
14290b57cec5SDimitry Andric     return PacketResult::Success;
14300b57cec5SDimitry Andric   }
14310b57cec5SDimitry Andric 
143281ad6265SDimitry Andric   for (auto it = m_debugged_processes.begin(); it != m_debugged_processes.end();
143381ad6265SDimitry Andric        ++it) {
143481ad6265SDimitry Andric     LLDB_LOG(log, "Killing process {0}", it->first);
143581ad6265SDimitry Andric     Status error = it->second->Kill();
14360b57cec5SDimitry Andric     if (error.Fail())
143781ad6265SDimitry Andric       LLDB_LOG(log, "Failed to kill debugged process {0}: {1}", it->first,
143881ad6265SDimitry Andric                error);
143981ad6265SDimitry Andric   }
14400b57cec5SDimitry Andric 
144181ad6265SDimitry Andric   // The response to kill packet is undefined per the spec.  LLDB
144281ad6265SDimitry Andric   // follows the same rules as for continue packets, i.e. no response
144381ad6265SDimitry Andric   // in all-stop mode, and "OK" in non-stop mode; in both cases this
144481ad6265SDimitry Andric   // is followed by the actual stop reason.
144581ad6265SDimitry Andric   return SendContinueSuccessResponse();
144681ad6265SDimitry Andric }
144781ad6265SDimitry Andric 
144881ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
144981ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vKill(
145081ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
145181ad6265SDimitry Andric   StopSTDIOForwarding();
145281ad6265SDimitry Andric 
145381ad6265SDimitry Andric   packet.SetFilePos(6); // vKill;
145481ad6265SDimitry Andric   uint32_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
145581ad6265SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
145681ad6265SDimitry Andric     return SendIllFormedResponse(packet,
145781ad6265SDimitry Andric                                  "vKill failed to parse the process id");
145881ad6265SDimitry Andric 
145981ad6265SDimitry Andric   auto it = m_debugged_processes.find(pid);
146081ad6265SDimitry Andric   if (it == m_debugged_processes.end())
146181ad6265SDimitry Andric     return SendErrorResponse(42);
146281ad6265SDimitry Andric 
146381ad6265SDimitry Andric   Status error = it->second->Kill();
146481ad6265SDimitry Andric   if (error.Fail())
146581ad6265SDimitry Andric     return SendErrorResponse(error.ToError());
146681ad6265SDimitry Andric 
146781ad6265SDimitry Andric   // OK response is sent when the process dies.
146881ad6265SDimitry Andric   m_vkilled_processes.insert(pid);
14690b57cec5SDimitry Andric   return PacketResult::Success;
14700b57cec5SDimitry Andric }
14710b57cec5SDimitry Andric 
14720b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14730b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR(
14740b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
14750b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetDisableASLR:"));
14760b57cec5SDimitry Andric   if (packet.GetU32(0))
14770b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
14780b57cec5SDimitry Andric   else
14790b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
14800b57cec5SDimitry Andric   return SendOKResponse();
14810b57cec5SDimitry Andric }
14820b57cec5SDimitry Andric 
14830b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14840b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir(
14850b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
14860b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetWorkingDir:"));
14870b57cec5SDimitry Andric   std::string path;
14880b57cec5SDimitry Andric   packet.GetHexByteString(path);
14890b57cec5SDimitry Andric   m_process_launch_info.SetWorkingDirectory(FileSpec(path));
14900b57cec5SDimitry Andric   return SendOKResponse();
14910b57cec5SDimitry Andric }
14920b57cec5SDimitry Andric 
14930b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14940b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir(
14950b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
14960b57cec5SDimitry Andric   FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()};
14970b57cec5SDimitry Andric   if (working_dir) {
14980b57cec5SDimitry Andric     StreamString response;
14990b57cec5SDimitry Andric     response.PutStringAsRawHex8(working_dir.GetCString());
15000b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
15010b57cec5SDimitry Andric   }
15020b57cec5SDimitry Andric 
15030b57cec5SDimitry Andric   return SendErrorResponse(14);
15040b57cec5SDimitry Andric }
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
1507fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported(
1508fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
1509fe6060f1SDimitry Andric   m_thread_suffix_supported = true;
1510fe6060f1SDimitry Andric   return SendOKResponse();
1511fe6060f1SDimitry Andric }
1512fe6060f1SDimitry Andric 
1513fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
1514fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply(
1515fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
1516fe6060f1SDimitry Andric   m_list_threads_in_stop_reply = true;
1517fe6060f1SDimitry Andric   return SendOKResponse();
1518fe6060f1SDimitry Andric }
1519fe6060f1SDimitry Andric 
1520fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
15210b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
152281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
15239dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric   // Ensure we have a native process.
1526fe6060f1SDimitry Andric   if (!m_continue_process) {
15279dba64beSDimitry Andric     LLDB_LOGF(log,
15289dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s no debugged process "
15290b57cec5SDimitry Andric               "shared pointer",
15300b57cec5SDimitry Andric               __FUNCTION__);
15310b57cec5SDimitry Andric     return SendErrorResponse(0x36);
15320b57cec5SDimitry Andric   }
15330b57cec5SDimitry Andric 
15340b57cec5SDimitry Andric   // Pull out the signal number.
15350b57cec5SDimitry Andric   packet.SetFilePos(::strlen("C"));
15360b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1) {
15370b57cec5SDimitry Andric     // Shouldn't be using a C without a signal.
15380b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "C packet specified without signal.");
15390b57cec5SDimitry Andric   }
15400b57cec5SDimitry Andric   const uint32_t signo =
15410b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
15420b57cec5SDimitry Andric   if (signo == std::numeric_limits<uint32_t>::max())
15430b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "failed to parse signal number");
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric   // Handle optional continue address.
15460b57cec5SDimitry Andric   if (packet.GetBytesLeft() > 0) {
15470b57cec5SDimitry Andric     // FIXME add continue at address support for $C{signo}[;{continue-address}].
15480b57cec5SDimitry Andric     if (*packet.Peek() == ';')
15499dba64beSDimitry Andric       return SendUnimplementedResponse(packet.GetStringRef().data());
15500b57cec5SDimitry Andric     else
15510b57cec5SDimitry Andric       return SendIllFormedResponse(
15520b57cec5SDimitry Andric           packet, "unexpected content after $C{signal-number}");
15530b57cec5SDimitry Andric   }
15540b57cec5SDimitry Andric 
15559dba64beSDimitry Andric   ResumeActionList resume_actions(StateType::eStateRunning,
15569dba64beSDimitry Andric                                   LLDB_INVALID_SIGNAL_NUMBER);
15570b57cec5SDimitry Andric   Status error;
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   // We have two branches: what to do if a continue thread is specified (in
15600b57cec5SDimitry Andric   // which case we target sending the signal to that thread), or when we don't
15610b57cec5SDimitry Andric   // have a continue thread set (in which case we send a signal to the
15620b57cec5SDimitry Andric   // process).
15630b57cec5SDimitry Andric 
15640b57cec5SDimitry Andric   // TODO discuss with Greg Clayton, make sure this makes sense.
15650b57cec5SDimitry Andric 
15660b57cec5SDimitry Andric   lldb::tid_t signal_tid = GetContinueThreadID();
15670b57cec5SDimitry Andric   if (signal_tid != LLDB_INVALID_THREAD_ID) {
15680b57cec5SDimitry Andric     // The resume action for the continue thread (or all threads if a continue
15690b57cec5SDimitry Andric     // thread is not set).
15700b57cec5SDimitry Andric     ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning,
15710b57cec5SDimitry Andric                            static_cast<int>(signo)};
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric     // Add the action for the continue thread (or all threads when the continue
15740b57cec5SDimitry Andric     // thread isn't present).
15750b57cec5SDimitry Andric     resume_actions.Append(action);
15760b57cec5SDimitry Andric   } else {
15770b57cec5SDimitry Andric     // Send the signal to the process since we weren't targeting a specific
15780b57cec5SDimitry Andric     // continue thread with the signal.
1579fe6060f1SDimitry Andric     error = m_continue_process->Signal(signo);
15800b57cec5SDimitry Andric     if (error.Fail()) {
15810b57cec5SDimitry Andric       LLDB_LOG(log, "failed to send signal for process {0}: {1}",
1582fe6060f1SDimitry Andric                m_continue_process->GetID(), error);
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric       return SendErrorResponse(0x52);
15850b57cec5SDimitry Andric     }
15860b57cec5SDimitry Andric   }
15870b57cec5SDimitry Andric 
15880b57cec5SDimitry Andric   // Resume the threads.
1589fe6060f1SDimitry Andric   error = m_continue_process->Resume(resume_actions);
15900b57cec5SDimitry Andric   if (error.Fail()) {
15910b57cec5SDimitry Andric     LLDB_LOG(log, "failed to resume threads for process {0}: {1}",
1592fe6060f1SDimitry Andric              m_continue_process->GetID(), error);
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric     return SendErrorResponse(0x38);
15950b57cec5SDimitry Andric   }
15960b57cec5SDimitry Andric 
159781ad6265SDimitry Andric   // Don't send an "OK" packet, except in non-stop mode;
159881ad6265SDimitry Andric   // otherwise, the response is the stopped/exited message.
159981ad6265SDimitry Andric   return SendContinueSuccessResponse();
16000b57cec5SDimitry Andric }
16010b57cec5SDimitry Andric 
16020b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
16030b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
160481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
16059dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
16060b57cec5SDimitry Andric 
16070b57cec5SDimitry Andric   packet.SetFilePos(packet.GetFilePos() + ::strlen("c"));
16080b57cec5SDimitry Andric 
16090b57cec5SDimitry Andric   // For now just support all continue.
16100b57cec5SDimitry Andric   const bool has_continue_address = (packet.GetBytesLeft() > 0);
16110b57cec5SDimitry Andric   if (has_continue_address) {
16120b57cec5SDimitry Andric     LLDB_LOG(log, "not implemented for c[address] variant [{0} remains]",
16130b57cec5SDimitry Andric              packet.Peek());
16149dba64beSDimitry Andric     return SendUnimplementedResponse(packet.GetStringRef().data());
16150b57cec5SDimitry Andric   }
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric   // Ensure we have a native process.
1618fe6060f1SDimitry Andric   if (!m_continue_process) {
16199dba64beSDimitry Andric     LLDB_LOGF(log,
16209dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s no debugged process "
16210b57cec5SDimitry Andric               "shared pointer",
16220b57cec5SDimitry Andric               __FUNCTION__);
16230b57cec5SDimitry Andric     return SendErrorResponse(0x36);
16240b57cec5SDimitry Andric   }
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric   // Build the ResumeActionList
16279dba64beSDimitry Andric   ResumeActionList actions(StateType::eStateRunning,
16289dba64beSDimitry Andric                            LLDB_INVALID_SIGNAL_NUMBER);
16290b57cec5SDimitry Andric 
1630fe6060f1SDimitry Andric   Status error = m_continue_process->Resume(actions);
16310b57cec5SDimitry Andric   if (error.Fail()) {
1632fe6060f1SDimitry Andric     LLDB_LOG(log, "c failed for process {0}: {1}", m_continue_process->GetID(),
1633fe6060f1SDimitry Andric              error);
16340b57cec5SDimitry Andric     return SendErrorResponse(GDBRemoteServerError::eErrorResume);
16350b57cec5SDimitry Andric   }
16360b57cec5SDimitry Andric 
1637fe6060f1SDimitry Andric   LLDB_LOG(log, "continued process {0}", m_continue_process->GetID());
163881ad6265SDimitry Andric 
163981ad6265SDimitry Andric   return SendContinueSuccessResponse();
16400b57cec5SDimitry Andric }
16410b57cec5SDimitry Andric 
16420b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
16430b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCont_actions(
16440b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
16450b57cec5SDimitry Andric   StreamString response;
164681ad6265SDimitry Andric   response.Printf("vCont;c;C;s;S;t");
16470b57cec5SDimitry Andric 
16480b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
16490b57cec5SDimitry Andric }
16500b57cec5SDimitry Andric 
16510b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
16520b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCont(
16530b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
165481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
16559dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s handling vCont packet",
16560b57cec5SDimitry Andric             __FUNCTION__);
16570b57cec5SDimitry Andric 
16580b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vCont"));
16590b57cec5SDimitry Andric 
16600b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0) {
16619dba64beSDimitry Andric     LLDB_LOGF(log,
16629dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s missing action from "
16630b57cec5SDimitry Andric               "vCont package",
16640b57cec5SDimitry Andric               __FUNCTION__);
16650b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Missing action from vCont package");
16660b57cec5SDimitry Andric   }
16670b57cec5SDimitry Andric 
166881ad6265SDimitry Andric   if (::strcmp(packet.Peek(), ";s") == 0) {
16690b57cec5SDimitry Andric     // Move past the ';', then do a simple 's'.
16700b57cec5SDimitry Andric     packet.SetFilePos(packet.GetFilePos() + 1);
16710b57cec5SDimitry Andric     return Handle_s(packet);
167281ad6265SDimitry Andric   } else if (m_non_stop && ::strcmp(packet.Peek(), ";t") == 0) {
167381ad6265SDimitry Andric     // TODO: add full support for "t" action
167481ad6265SDimitry Andric     return SendOKResponse();
16750b57cec5SDimitry Andric   }
16760b57cec5SDimitry Andric 
167781ad6265SDimitry Andric   std::unordered_map<lldb::pid_t, ResumeActionList> thread_actions;
16780b57cec5SDimitry Andric 
16790b57cec5SDimitry Andric   while (packet.GetBytesLeft() && *packet.Peek() == ';') {
16800b57cec5SDimitry Andric     // Skip the semi-colon.
16810b57cec5SDimitry Andric     packet.GetChar();
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric     // Build up the thread action.
16840b57cec5SDimitry Andric     ResumeAction thread_action;
16850b57cec5SDimitry Andric     thread_action.tid = LLDB_INVALID_THREAD_ID;
16860b57cec5SDimitry Andric     thread_action.state = eStateInvalid;
16879dba64beSDimitry Andric     thread_action.signal = LLDB_INVALID_SIGNAL_NUMBER;
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric     const char action = packet.GetChar();
16900b57cec5SDimitry Andric     switch (action) {
16910b57cec5SDimitry Andric     case 'C':
16920b57cec5SDimitry Andric       thread_action.signal = packet.GetHexMaxU32(false, 0);
16930b57cec5SDimitry Andric       if (thread_action.signal == 0)
16940b57cec5SDimitry Andric         return SendIllFormedResponse(
16950b57cec5SDimitry Andric             packet, "Could not parse signal in vCont packet C action");
16960b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
16970b57cec5SDimitry Andric 
16980b57cec5SDimitry Andric     case 'c':
16990b57cec5SDimitry Andric       // Continue
17000b57cec5SDimitry Andric       thread_action.state = eStateRunning;
17010b57cec5SDimitry Andric       break;
17020b57cec5SDimitry Andric 
17030b57cec5SDimitry Andric     case 'S':
17040b57cec5SDimitry Andric       thread_action.signal = packet.GetHexMaxU32(false, 0);
17050b57cec5SDimitry Andric       if (thread_action.signal == 0)
17060b57cec5SDimitry Andric         return SendIllFormedResponse(
17070b57cec5SDimitry Andric             packet, "Could not parse signal in vCont packet S action");
17080b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric     case 's':
17110b57cec5SDimitry Andric       // Step
17120b57cec5SDimitry Andric       thread_action.state = eStateStepping;
17130b57cec5SDimitry Andric       break;
17140b57cec5SDimitry Andric 
171581ad6265SDimitry Andric     case 't':
171681ad6265SDimitry Andric       // Stop
171781ad6265SDimitry Andric       thread_action.state = eStateSuspended;
171881ad6265SDimitry Andric       break;
171981ad6265SDimitry Andric 
17200b57cec5SDimitry Andric     default:
17210b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Unsupported vCont action");
17220b57cec5SDimitry Andric       break;
17230b57cec5SDimitry Andric     }
17240b57cec5SDimitry Andric 
172581ad6265SDimitry Andric     lldb::pid_t pid = StringExtractorGDBRemote::AllProcesses;
172681ad6265SDimitry Andric     lldb::tid_t tid = StringExtractorGDBRemote::AllThreads;
172781ad6265SDimitry Andric 
17280b57cec5SDimitry Andric     // Parse out optional :{thread-id} value.
17290b57cec5SDimitry Andric     if (packet.GetBytesLeft() && (*packet.Peek() == ':')) {
17300b57cec5SDimitry Andric       // Consume the separator.
17310b57cec5SDimitry Andric       packet.GetChar();
17320b57cec5SDimitry Andric 
173381ad6265SDimitry Andric       auto pid_tid = packet.GetPidTid(StringExtractorGDBRemote::AllProcesses);
173481ad6265SDimitry Andric       if (!pid_tid)
173581ad6265SDimitry Andric         return SendIllFormedResponse(packet, "Malformed thread-id");
1736fe6060f1SDimitry Andric 
173781ad6265SDimitry Andric       pid = pid_tid->first;
173881ad6265SDimitry Andric       tid = pid_tid->second;
17390b57cec5SDimitry Andric     }
17400b57cec5SDimitry Andric 
174181ad6265SDimitry Andric     if (pid == StringExtractorGDBRemote::AllProcesses) {
174281ad6265SDimitry Andric       if (m_debugged_processes.size() > 1)
174381ad6265SDimitry Andric         return SendIllFormedResponse(
174481ad6265SDimitry Andric             packet, "Resuming multiple processes not supported yet");
174581ad6265SDimitry Andric       if (!m_continue_process) {
174681ad6265SDimitry Andric         LLDB_LOG(log, "no debugged process");
174781ad6265SDimitry Andric         return SendErrorResponse(0x36);
174881ad6265SDimitry Andric       }
174981ad6265SDimitry Andric       pid = m_continue_process->GetID();
17500b57cec5SDimitry Andric     }
17510b57cec5SDimitry Andric 
175281ad6265SDimitry Andric     if (tid == StringExtractorGDBRemote::AllThreads)
175381ad6265SDimitry Andric       tid = LLDB_INVALID_THREAD_ID;
175481ad6265SDimitry Andric 
175581ad6265SDimitry Andric     thread_action.tid = tid;
175681ad6265SDimitry Andric 
175781ad6265SDimitry Andric     thread_actions[pid].Append(thread_action);
175881ad6265SDimitry Andric   }
175981ad6265SDimitry Andric 
176081ad6265SDimitry Andric   assert(thread_actions.size() >= 1);
176181ad6265SDimitry Andric   if (thread_actions.size() > 1)
176281ad6265SDimitry Andric     return SendIllFormedResponse(
176381ad6265SDimitry Andric         packet, "Resuming multiple processes not supported yet");
176481ad6265SDimitry Andric 
176581ad6265SDimitry Andric   for (std::pair<lldb::pid_t, ResumeActionList> x : thread_actions) {
176681ad6265SDimitry Andric     auto process_it = m_debugged_processes.find(x.first);
176781ad6265SDimitry Andric     if (process_it == m_debugged_processes.end()) {
176881ad6265SDimitry Andric       LLDB_LOG(log, "vCont failed for process {0}: process not debugged",
176981ad6265SDimitry Andric                x.first);
17700b57cec5SDimitry Andric       return SendErrorResponse(GDBRemoteServerError::eErrorResume);
17710b57cec5SDimitry Andric     }
17720b57cec5SDimitry Andric 
177381ad6265SDimitry Andric     Status error = process_it->second->Resume(x.second);
177481ad6265SDimitry Andric     if (error.Fail()) {
177581ad6265SDimitry Andric       LLDB_LOG(log, "vCont failed for process {0}: {1}", x.first, error);
177681ad6265SDimitry Andric       return SendErrorResponse(GDBRemoteServerError::eErrorResume);
177781ad6265SDimitry Andric     }
177881ad6265SDimitry Andric 
177981ad6265SDimitry Andric     LLDB_LOG(log, "continued process {0}", x.first);
178081ad6265SDimitry Andric   }
178181ad6265SDimitry Andric 
178281ad6265SDimitry Andric   return SendContinueSuccessResponse();
17830b57cec5SDimitry Andric }
17840b57cec5SDimitry Andric 
17850b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
178681ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
17870b57cec5SDimitry Andric   LLDB_LOG(log, "setting current thread id to {0}", tid);
17880b57cec5SDimitry Andric 
17890b57cec5SDimitry Andric   m_current_tid = tid;
1790fe6060f1SDimitry Andric   if (m_current_process)
1791fe6060f1SDimitry Andric     m_current_process->SetCurrentThreadID(m_current_tid);
17920b57cec5SDimitry Andric }
17930b57cec5SDimitry Andric 
17940b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
179581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
17960b57cec5SDimitry Andric   LLDB_LOG(log, "setting continue thread id to {0}", tid);
17970b57cec5SDimitry Andric 
17980b57cec5SDimitry Andric   m_continue_tid = tid;
17990b57cec5SDimitry Andric }
18000b57cec5SDimitry Andric 
18010b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
18020b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_stop_reason(
18030b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
18040b57cec5SDimitry Andric   // Handle the $? gdbremote command.
18050b57cec5SDimitry Andric 
180681ad6265SDimitry Andric   if (m_non_stop) {
180781ad6265SDimitry Andric     // Clear the notification queue first, except for pending exit
180881ad6265SDimitry Andric     // notifications.
180981ad6265SDimitry Andric     llvm::erase_if(m_stop_notification_queue, [](const std::string &x) {
181081ad6265SDimitry Andric       return x.front() != 'W' && x.front() != 'X';
181181ad6265SDimitry Andric     });
181281ad6265SDimitry Andric 
181381ad6265SDimitry Andric     if (m_current_process) {
181481ad6265SDimitry Andric       // Queue stop reply packets for all active threads.  Start with
181581ad6265SDimitry Andric       // the current thread (for clients that don't actually support multiple
181681ad6265SDimitry Andric       // stop reasons).
181781ad6265SDimitry Andric       NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
181881ad6265SDimitry Andric       if (thread)
181981ad6265SDimitry Andric         m_stop_notification_queue.push_back(
182081ad6265SDimitry Andric             PrepareStopReplyPacketForThread(*thread).GetString().str());
182181ad6265SDimitry Andric       EnqueueStopReplyPackets(thread ? thread->GetID()
182281ad6265SDimitry Andric                                      : LLDB_INVALID_THREAD_ID);
182381ad6265SDimitry Andric     }
182481ad6265SDimitry Andric 
182581ad6265SDimitry Andric     // If the notification queue is empty (i.e. everything is running), send OK.
182681ad6265SDimitry Andric     if (m_stop_notification_queue.empty())
182781ad6265SDimitry Andric       return SendOKResponse();
182881ad6265SDimitry Andric 
182981ad6265SDimitry Andric     // Send the first item from the new notification queue synchronously.
183081ad6265SDimitry Andric     return SendPacketNoLock(m_stop_notification_queue.front());
183181ad6265SDimitry Andric   }
183281ad6265SDimitry Andric 
18330b57cec5SDimitry Andric   // If no process, indicate error
1834fe6060f1SDimitry Andric   if (!m_current_process)
18350b57cec5SDimitry Andric     return SendErrorResponse(02);
18360b57cec5SDimitry Andric 
183781ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
183881ad6265SDimitry Andric                                 m_current_process->GetState(),
183981ad6265SDimitry Andric                                 /*force_synchronous=*/true);
18400b57cec5SDimitry Andric }
18410b57cec5SDimitry Andric 
18420b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
18430b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
184481ad6265SDimitry Andric     NativeProcessProtocol &process, lldb::StateType process_state,
184581ad6265SDimitry Andric     bool force_synchronous) {
184681ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
18470b57cec5SDimitry Andric 
18480b57cec5SDimitry Andric   switch (process_state) {
18490b57cec5SDimitry Andric   case eStateAttaching:
18500b57cec5SDimitry Andric   case eStateLaunching:
18510b57cec5SDimitry Andric   case eStateRunning:
18520b57cec5SDimitry Andric   case eStateStepping:
18530b57cec5SDimitry Andric   case eStateDetached:
18540b57cec5SDimitry Andric     // NOTE: gdb protocol doc looks like it should return $OK
18550b57cec5SDimitry Andric     // when everything is running (i.e. no stopped result).
18560b57cec5SDimitry Andric     return PacketResult::Success; // Ignore
18570b57cec5SDimitry Andric 
18580b57cec5SDimitry Andric   case eStateSuspended:
18590b57cec5SDimitry Andric   case eStateStopped:
18600b57cec5SDimitry Andric   case eStateCrashed: {
186181ad6265SDimitry Andric     lldb::tid_t tid = process.GetCurrentThreadID();
18620b57cec5SDimitry Andric     // Make sure we set the current thread so g and p packets return the data
18630b57cec5SDimitry Andric     // the gdb will expect.
18640b57cec5SDimitry Andric     SetCurrentThreadID(tid);
186581ad6265SDimitry Andric     return SendStopReplyPacketForThread(process, tid, force_synchronous);
18660b57cec5SDimitry Andric   }
18670b57cec5SDimitry Andric 
18680b57cec5SDimitry Andric   case eStateInvalid:
18690b57cec5SDimitry Andric   case eStateUnloaded:
18700b57cec5SDimitry Andric   case eStateExited:
187181ad6265SDimitry Andric     return SendWResponse(&process);
18720b57cec5SDimitry Andric 
18730b57cec5SDimitry Andric   default:
18740b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}",
187581ad6265SDimitry Andric              process.GetID(), process_state);
18760b57cec5SDimitry Andric     break;
18770b57cec5SDimitry Andric   }
18780b57cec5SDimitry Andric 
18790b57cec5SDimitry Andric   return SendErrorResponse(0);
18800b57cec5SDimitry Andric }
18810b57cec5SDimitry Andric 
18820b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
18830b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
18840b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
18850b57cec5SDimitry Andric   // Fail if we don't have a current process.
1886fe6060f1SDimitry Andric   if (!m_current_process ||
1887fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
18880b57cec5SDimitry Andric     return SendErrorResponse(68);
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric   // Ensure we have a thread.
1891fe6060f1SDimitry Andric   NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
18920b57cec5SDimitry Andric   if (!thread)
18930b57cec5SDimitry Andric     return SendErrorResponse(69);
18940b57cec5SDimitry Andric 
18950b57cec5SDimitry Andric   // Get the register context for the first thread.
18960b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
18970b57cec5SDimitry Andric 
18980b57cec5SDimitry Andric   // Parse out the register number from the request.
18990b57cec5SDimitry Andric   packet.SetFilePos(strlen("qRegisterInfo"));
19000b57cec5SDimitry Andric   const uint32_t reg_index =
19010b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
19020b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max())
19030b57cec5SDimitry Andric     return SendErrorResponse(69);
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
19060b57cec5SDimitry Andric   // the register set.
19070b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount())
19080b57cec5SDimitry Andric     return SendErrorResponse(69);
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
19110b57cec5SDimitry Andric   if (!reg_info)
19120b57cec5SDimitry Andric     return SendErrorResponse(69);
19130b57cec5SDimitry Andric 
19140b57cec5SDimitry Andric   // Build the reginfos response.
19150b57cec5SDimitry Andric   StreamGDBRemote response;
19160b57cec5SDimitry Andric 
19170b57cec5SDimitry Andric   response.PutCString("name:");
19180b57cec5SDimitry Andric   response.PutCString(reg_info->name);
19190b57cec5SDimitry Andric   response.PutChar(';');
19200b57cec5SDimitry Andric 
19210b57cec5SDimitry Andric   if (reg_info->alt_name && reg_info->alt_name[0]) {
19220b57cec5SDimitry Andric     response.PutCString("alt-name:");
19230b57cec5SDimitry Andric     response.PutCString(reg_info->alt_name);
19240b57cec5SDimitry Andric     response.PutChar(';');
19250b57cec5SDimitry Andric   }
19260b57cec5SDimitry Andric 
1927e8d8bef9SDimitry Andric   response.Printf("bitsize:%" PRIu32 ";", reg_info->byte_size * 8);
1928e8d8bef9SDimitry Andric 
1929e8d8bef9SDimitry Andric   if (!reg_context.RegisterOffsetIsDynamic())
1930e8d8bef9SDimitry Andric     response.Printf("offset:%" PRIu32 ";", reg_info->byte_offset);
19310b57cec5SDimitry Andric 
19325ffd83dbSDimitry Andric   llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info);
19335ffd83dbSDimitry Andric   if (!encoding.empty())
19345ffd83dbSDimitry Andric     response << "encoding:" << encoding << ';';
19350b57cec5SDimitry Andric 
19365ffd83dbSDimitry Andric   llvm::StringRef format = GetFormatNameOrEmpty(*reg_info);
19375ffd83dbSDimitry Andric   if (!format.empty())
19385ffd83dbSDimitry Andric     response << "format:" << format << ';';
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric   const char *const register_set_name =
19410b57cec5SDimitry Andric       reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index);
19425ffd83dbSDimitry Andric   if (register_set_name)
19435ffd83dbSDimitry Andric     response << "set:" << register_set_name << ';';
19440b57cec5SDimitry Andric 
19450b57cec5SDimitry Andric   if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
19460b57cec5SDimitry Andric       LLDB_INVALID_REGNUM)
19470b57cec5SDimitry Andric     response.Printf("ehframe:%" PRIu32 ";",
19480b57cec5SDimitry Andric                     reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
19490b57cec5SDimitry Andric 
19500b57cec5SDimitry Andric   if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
19510b57cec5SDimitry Andric     response.Printf("dwarf:%" PRIu32 ";",
19520b57cec5SDimitry Andric                     reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
19530b57cec5SDimitry Andric 
19545ffd83dbSDimitry Andric   llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info);
19555ffd83dbSDimitry Andric   if (!kind_generic.empty())
19565ffd83dbSDimitry Andric     response << "generic:" << kind_generic << ';';
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
19590b57cec5SDimitry Andric     response.PutCString("container-regs:");
19605ffd83dbSDimitry Andric     CollectRegNums(reg_info->value_regs, response, true);
19610b57cec5SDimitry Andric     response.PutChar(';');
19620b57cec5SDimitry Andric   }
19630b57cec5SDimitry Andric 
19640b57cec5SDimitry Andric   if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
19650b57cec5SDimitry Andric     response.PutCString("invalidate-regs:");
19665ffd83dbSDimitry Andric     CollectRegNums(reg_info->invalidate_regs, response, true);
19670b57cec5SDimitry Andric     response.PutChar(';');
19680b57cec5SDimitry Andric   }
19690b57cec5SDimitry Andric 
19700b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
19710b57cec5SDimitry Andric }
19720b57cec5SDimitry Andric 
197381ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::AddProcessThreads(
197481ad6265SDimitry Andric     StreamGDBRemote &response, NativeProcessProtocol &process, bool &had_any) {
197581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
197681ad6265SDimitry Andric 
197781ad6265SDimitry Andric   lldb::pid_t pid = process.GetID();
197881ad6265SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
197981ad6265SDimitry Andric     return;
198081ad6265SDimitry Andric 
198181ad6265SDimitry Andric   LLDB_LOG(log, "iterating over threads of process {0}", process.GetID());
198281ad6265SDimitry Andric   for (NativeThreadProtocol &thread : process.Threads()) {
198381ad6265SDimitry Andric     LLDB_LOG(log, "iterated thread tid={0}", thread.GetID());
198481ad6265SDimitry Andric     response.PutChar(had_any ? ',' : 'm');
198581ad6265SDimitry Andric     AppendThreadIDToResponse(response, pid, thread.GetID());
198681ad6265SDimitry Andric     had_any = true;
198781ad6265SDimitry Andric   }
198881ad6265SDimitry Andric }
198981ad6265SDimitry Andric 
19900b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
19910b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
19920b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
199381ad6265SDimitry Andric   assert(m_debugged_processes.size() == 1 ||
199481ad6265SDimitry Andric          bool(m_extensions_supported &
199581ad6265SDimitry Andric               NativeProcessProtocol::Extension::multiprocess));
19960b57cec5SDimitry Andric 
199781ad6265SDimitry Andric   bool had_any = false;
19980b57cec5SDimitry Andric   StreamGDBRemote response;
19990b57cec5SDimitry Andric 
200081ad6265SDimitry Andric   for (auto &pid_ptr : m_debugged_processes)
200181ad6265SDimitry Andric     AddProcessThreads(response, *pid_ptr.second, had_any);
20020b57cec5SDimitry Andric 
200381ad6265SDimitry Andric   if (!had_any)
200481ad6265SDimitry Andric     return SendOKResponse();
20050b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
20060b57cec5SDimitry Andric }
20070b57cec5SDimitry Andric 
20080b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
20090b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo(
20100b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
20110b57cec5SDimitry Andric   // FIXME for now we return the full thread list in the initial packet and
20120b57cec5SDimitry Andric   // always do nothing here.
20130b57cec5SDimitry Andric   return SendPacketNoLock("l");
20140b57cec5SDimitry Andric }
20150b57cec5SDimitry Andric 
20160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
20170b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) {
201881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
20190b57cec5SDimitry Andric 
20200b57cec5SDimitry Andric   // Move past packet name.
20210b57cec5SDimitry Andric   packet.SetFilePos(strlen("g"));
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric   // Get the thread to use.
20240b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
20250b57cec5SDimitry Andric   if (!thread) {
20260b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no thread available");
20270b57cec5SDimitry Andric     return SendErrorResponse(0x15);
20280b57cec5SDimitry Andric   }
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric   // Get the thread's register context.
20310b57cec5SDimitry Andric   NativeRegisterContext &reg_ctx = thread->GetRegisterContext();
20320b57cec5SDimitry Andric 
20330b57cec5SDimitry Andric   std::vector<uint8_t> regs_buffer;
20340b57cec5SDimitry Andric   for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount();
20350b57cec5SDimitry Andric        ++reg_num) {
20360b57cec5SDimitry Andric     const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num);
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric     if (reg_info == nullptr) {
20390b57cec5SDimitry Andric       LLDB_LOG(log, "failed to get register info for register index {0}",
20400b57cec5SDimitry Andric                reg_num);
20410b57cec5SDimitry Andric       return SendErrorResponse(0x15);
20420b57cec5SDimitry Andric     }
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric     if (reg_info->value_regs != nullptr)
20450b57cec5SDimitry Andric       continue; // skip registers that are contained in other registers
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric     RegisterValue reg_value;
20480b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(reg_info, reg_value);
20490b57cec5SDimitry Andric     if (error.Fail()) {
20500b57cec5SDimitry Andric       LLDB_LOG(log, "failed to read register at index {0}", reg_num);
20510b57cec5SDimitry Andric       return SendErrorResponse(0x15);
20520b57cec5SDimitry Andric     }
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric     if (reg_info->byte_offset + reg_info->byte_size >= regs_buffer.size())
20550b57cec5SDimitry Andric       // Resize the buffer to guarantee it can store the register offsetted
20560b57cec5SDimitry Andric       // data.
20570b57cec5SDimitry Andric       regs_buffer.resize(reg_info->byte_offset + reg_info->byte_size);
20580b57cec5SDimitry Andric 
20590b57cec5SDimitry Andric     // Copy the register offsetted data to the buffer.
20600b57cec5SDimitry Andric     memcpy(regs_buffer.data() + reg_info->byte_offset, reg_value.GetBytes(),
20610b57cec5SDimitry Andric            reg_info->byte_size);
20620b57cec5SDimitry Andric   }
20630b57cec5SDimitry Andric 
20640b57cec5SDimitry Andric   // Write the response.
20650b57cec5SDimitry Andric   StreamGDBRemote response;
20660b57cec5SDimitry Andric   response.PutBytesAsRawHex8(regs_buffer.data(), regs_buffer.size());
20670b57cec5SDimitry Andric 
20680b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
20690b57cec5SDimitry Andric }
20700b57cec5SDimitry Andric 
20710b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
20720b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
207381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
20740b57cec5SDimitry Andric 
20750b57cec5SDimitry Andric   // Parse out the register number from the request.
20760b57cec5SDimitry Andric   packet.SetFilePos(strlen("p"));
20770b57cec5SDimitry Andric   const uint32_t reg_index =
20780b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
20790b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max()) {
20809dba64beSDimitry Andric     LLDB_LOGF(log,
20819dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
20820b57cec5SDimitry Andric               "parse register number from request \"%s\"",
20839dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
20840b57cec5SDimitry Andric     return SendErrorResponse(0x15);
20850b57cec5SDimitry Andric   }
20860b57cec5SDimitry Andric 
20870b57cec5SDimitry Andric   // Get the thread to use.
20880b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
20890b57cec5SDimitry Andric   if (!thread) {
20900b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no thread available");
20910b57cec5SDimitry Andric     return SendErrorResponse(0x15);
20920b57cec5SDimitry Andric   }
20930b57cec5SDimitry Andric 
20940b57cec5SDimitry Andric   // Get the thread's register context.
20950b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
20980b57cec5SDimitry Andric   // the register set.
20990b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount()) {
21009dba64beSDimitry Andric     LLDB_LOGF(log,
21019dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
21020b57cec5SDimitry Andric               "register %" PRIu32 " beyond register count %" PRIu32,
21039dba64beSDimitry Andric               __FUNCTION__, reg_index, reg_context.GetUserRegisterCount());
21040b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21050b57cec5SDimitry Andric   }
21060b57cec5SDimitry Andric 
21070b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
21080b57cec5SDimitry Andric   if (!reg_info) {
21099dba64beSDimitry Andric     LLDB_LOGF(log,
21109dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
21110b57cec5SDimitry Andric               "register %" PRIu32 " returned NULL",
21120b57cec5SDimitry Andric               __FUNCTION__, reg_index);
21130b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21140b57cec5SDimitry Andric   }
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric   // Build the reginfos response.
21170b57cec5SDimitry Andric   StreamGDBRemote response;
21180b57cec5SDimitry Andric 
21190b57cec5SDimitry Andric   // Retrieve the value
21200b57cec5SDimitry Andric   RegisterValue reg_value;
21210b57cec5SDimitry Andric   Status error = reg_context.ReadRegister(reg_info, reg_value);
21220b57cec5SDimitry Andric   if (error.Fail()) {
21239dba64beSDimitry Andric     LLDB_LOGF(log,
21249dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, read of "
21250b57cec5SDimitry Andric               "requested register %" PRIu32 " (%s) failed: %s",
21260b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_info->name, error.AsCString());
21270b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21280b57cec5SDimitry Andric   }
21290b57cec5SDimitry Andric 
21300b57cec5SDimitry Andric   const uint8_t *const data =
2131480093f4SDimitry Andric       static_cast<const uint8_t *>(reg_value.GetBytes());
21320b57cec5SDimitry Andric   if (!data) {
21339dba64beSDimitry Andric     LLDB_LOGF(log,
21349dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to get data "
21350b57cec5SDimitry Andric               "bytes from requested register %" PRIu32,
21360b57cec5SDimitry Andric               __FUNCTION__, reg_index);
21370b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21380b57cec5SDimitry Andric   }
21390b57cec5SDimitry Andric 
21400b57cec5SDimitry Andric   // FIXME flip as needed to get data in big/little endian format for this host.
21410b57cec5SDimitry Andric   for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i)
21420b57cec5SDimitry Andric     response.PutHex8(data[i]);
21430b57cec5SDimitry Andric 
21440b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
21450b57cec5SDimitry Andric }
21460b57cec5SDimitry Andric 
21470b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
21480b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
214981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
21500b57cec5SDimitry Andric 
21510b57cec5SDimitry Andric   // Ensure there is more content.
21520b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
21530b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Empty P packet");
21540b57cec5SDimitry Andric 
21550b57cec5SDimitry Andric   // Parse out the register number from the request.
21560b57cec5SDimitry Andric   packet.SetFilePos(strlen("P"));
21570b57cec5SDimitry Andric   const uint32_t reg_index =
21580b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
21590b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max()) {
21609dba64beSDimitry Andric     LLDB_LOGF(log,
21619dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
21620b57cec5SDimitry Andric               "parse register number from request \"%s\"",
21639dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
21640b57cec5SDimitry Andric     return SendErrorResponse(0x29);
21650b57cec5SDimitry Andric   }
21660b57cec5SDimitry Andric 
21670b57cec5SDimitry Andric   // Note debugserver would send an E30 here.
21680b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '='))
21690b57cec5SDimitry Andric     return SendIllFormedResponse(
21700b57cec5SDimitry Andric         packet, "P packet missing '=' char after register number");
21710b57cec5SDimitry Andric 
21720b57cec5SDimitry Andric   // Parse out the value.
21735ffd83dbSDimitry Andric   uint8_t reg_bytes[RegisterValue::kMaxRegisterByteSize];
21740b57cec5SDimitry Andric   size_t reg_size = packet.GetHexBytesAvail(reg_bytes);
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric   // Get the thread to use.
21770b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
21780b57cec5SDimitry Andric   if (!thread) {
21799dba64beSDimitry Andric     LLDB_LOGF(log,
21809dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, no thread "
21810b57cec5SDimitry Andric               "available (thread index 0)",
21820b57cec5SDimitry Andric               __FUNCTION__);
21830b57cec5SDimitry Andric     return SendErrorResponse(0x28);
21840b57cec5SDimitry Andric   }
21850b57cec5SDimitry Andric 
21860b57cec5SDimitry Andric   // Get the thread's register context.
21870b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
21880b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
21890b57cec5SDimitry Andric   if (!reg_info) {
21909dba64beSDimitry Andric     LLDB_LOGF(log,
21919dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
21920b57cec5SDimitry Andric               "register %" PRIu32 " returned NULL",
21930b57cec5SDimitry Andric               __FUNCTION__, reg_index);
21940b57cec5SDimitry Andric     return SendErrorResponse(0x48);
21950b57cec5SDimitry Andric   }
21960b57cec5SDimitry Andric 
21970b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
21980b57cec5SDimitry Andric   // the register set.
21990b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount()) {
22009dba64beSDimitry Andric     LLDB_LOGF(log,
22019dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
22020b57cec5SDimitry Andric               "register %" PRIu32 " beyond register count %" PRIu32,
22030b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_context.GetUserRegisterCount());
22040b57cec5SDimitry Andric     return SendErrorResponse(0x47);
22050b57cec5SDimitry Andric   }
22060b57cec5SDimitry Andric 
2207349cc55cSDimitry Andric   if (reg_size != reg_info->byte_size)
22080b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "P packet register size is incorrect");
22090b57cec5SDimitry Andric 
22100b57cec5SDimitry Andric   // Build the reginfos response.
22110b57cec5SDimitry Andric   StreamGDBRemote response;
22120b57cec5SDimitry Andric 
2213fe6060f1SDimitry Andric   RegisterValue reg_value(makeArrayRef(reg_bytes, reg_size),
2214fe6060f1SDimitry Andric                           m_current_process->GetArchitecture().GetByteOrder());
22150b57cec5SDimitry Andric   Status error = reg_context.WriteRegister(reg_info, reg_value);
22160b57cec5SDimitry Andric   if (error.Fail()) {
22179dba64beSDimitry Andric     LLDB_LOGF(log,
22189dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, write of "
22190b57cec5SDimitry Andric               "requested register %" PRIu32 " (%s) failed: %s",
22200b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_info->name, error.AsCString());
22210b57cec5SDimitry Andric     return SendErrorResponse(0x32);
22220b57cec5SDimitry Andric   }
22230b57cec5SDimitry Andric 
22240b57cec5SDimitry Andric   return SendOKResponse();
22250b57cec5SDimitry Andric }
22260b57cec5SDimitry Andric 
22270b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
22280b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
222981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric   // Parse out which variant of $H is requested.
22320b57cec5SDimitry Andric   packet.SetFilePos(strlen("H"));
22330b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1) {
22349dba64beSDimitry Andric     LLDB_LOGF(log,
22359dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, H command "
22360b57cec5SDimitry Andric               "missing {g,c} variant",
22370b57cec5SDimitry Andric               __FUNCTION__);
22380b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "H command missing {g,c} variant");
22390b57cec5SDimitry Andric   }
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric   const char h_variant = packet.GetChar();
2242fe6060f1SDimitry Andric   NativeProcessProtocol *default_process;
22430b57cec5SDimitry Andric   switch (h_variant) {
22440b57cec5SDimitry Andric   case 'g':
2245fe6060f1SDimitry Andric     default_process = m_current_process;
22460b57cec5SDimitry Andric     break;
22470b57cec5SDimitry Andric 
22480b57cec5SDimitry Andric   case 'c':
2249fe6060f1SDimitry Andric     default_process = m_continue_process;
22500b57cec5SDimitry Andric     break;
22510b57cec5SDimitry Andric 
22520b57cec5SDimitry Andric   default:
22539dba64beSDimitry Andric     LLDB_LOGF(
22549dba64beSDimitry Andric         log,
22550b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c",
22560b57cec5SDimitry Andric         __FUNCTION__, h_variant);
22570b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
22580b57cec5SDimitry Andric                                  "H variant unsupported, should be c or g");
22590b57cec5SDimitry Andric   }
22600b57cec5SDimitry Andric 
22610b57cec5SDimitry Andric   // Parse out the thread number.
2262fe6060f1SDimitry Andric   auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID()
2263fe6060f1SDimitry Andric                                                   : LLDB_INVALID_PROCESS_ID);
2264fe6060f1SDimitry Andric   if (!pid_tid)
2265fe6060f1SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
2266fe6060f1SDimitry Andric         inconvertibleErrorCode(), "Malformed thread-id"));
2267fe6060f1SDimitry Andric 
2268fe6060f1SDimitry Andric   lldb::pid_t pid = pid_tid->first;
2269fe6060f1SDimitry Andric   lldb::tid_t tid = pid_tid->second;
2270fe6060f1SDimitry Andric 
2271fe6060f1SDimitry Andric   if (pid == StringExtractorGDBRemote::AllProcesses)
2272fe6060f1SDimitry Andric     return SendUnimplementedResponse("Selecting all processes not supported");
2273fe6060f1SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
2274fe6060f1SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
2275fe6060f1SDimitry Andric         inconvertibleErrorCode(), "No current process and no PID provided"));
2276fe6060f1SDimitry Andric 
2277fe6060f1SDimitry Andric   // Check the process ID and find respective process instance.
2278fe6060f1SDimitry Andric   auto new_process_it = m_debugged_processes.find(pid);
2279fe6060f1SDimitry Andric   if (new_process_it == m_debugged_processes.end())
2280fe6060f1SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
2281fe6060f1SDimitry Andric         inconvertibleErrorCode(),
2282fe6060f1SDimitry Andric         llvm::formatv("No process with PID {0} debugged", pid)));
22830b57cec5SDimitry Andric 
22840b57cec5SDimitry Andric   // Ensure we have the given thread when not specifying -1 (all threads) or 0
22850b57cec5SDimitry Andric   // (any thread).
22860b57cec5SDimitry Andric   if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
2287fe6060f1SDimitry Andric     NativeThreadProtocol *thread = new_process_it->second->GetThreadByID(tid);
22880b57cec5SDimitry Andric     if (!thread) {
22899dba64beSDimitry Andric       LLDB_LOGF(log,
22909dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
22910b57cec5SDimitry Andric                 " not found",
22920b57cec5SDimitry Andric                 __FUNCTION__, tid);
22930b57cec5SDimitry Andric       return SendErrorResponse(0x15);
22940b57cec5SDimitry Andric     }
22950b57cec5SDimitry Andric   }
22960b57cec5SDimitry Andric 
2297fe6060f1SDimitry Andric   // Now switch the given process and thread type.
22980b57cec5SDimitry Andric   switch (h_variant) {
22990b57cec5SDimitry Andric   case 'g':
2300fe6060f1SDimitry Andric     m_current_process = new_process_it->second.get();
23010b57cec5SDimitry Andric     SetCurrentThreadID(tid);
23020b57cec5SDimitry Andric     break;
23030b57cec5SDimitry Andric 
23040b57cec5SDimitry Andric   case 'c':
2305fe6060f1SDimitry Andric     m_continue_process = new_process_it->second.get();
23060b57cec5SDimitry Andric     SetContinueThreadID(tid);
23070b57cec5SDimitry Andric     break;
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric   default:
23100b57cec5SDimitry Andric     assert(false && "unsupported $H variant - shouldn't get here");
23110b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
23120b57cec5SDimitry Andric                                  "H variant unsupported, should be c or g");
23130b57cec5SDimitry Andric   }
23140b57cec5SDimitry Andric 
23150b57cec5SDimitry Andric   return SendOKResponse();
23160b57cec5SDimitry Andric }
23170b57cec5SDimitry Andric 
23180b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
23190b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
232081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
23210b57cec5SDimitry Andric 
23220b57cec5SDimitry Andric   // Fail if we don't have a current process.
2323fe6060f1SDimitry Andric   if (!m_current_process ||
2324fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
23259dba64beSDimitry Andric     LLDB_LOGF(
23269dba64beSDimitry Andric         log,
23270b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
23280b57cec5SDimitry Andric         __FUNCTION__);
23290b57cec5SDimitry Andric     return SendErrorResponse(0x15);
23300b57cec5SDimitry Andric   }
23310b57cec5SDimitry Andric 
23320b57cec5SDimitry Andric   packet.SetFilePos(::strlen("I"));
23330b57cec5SDimitry Andric   uint8_t tmp[4096];
23340b57cec5SDimitry Andric   for (;;) {
23350b57cec5SDimitry Andric     size_t read = packet.GetHexBytesAvail(tmp);
23360b57cec5SDimitry Andric     if (read == 0) {
23370b57cec5SDimitry Andric       break;
23380b57cec5SDimitry Andric     }
23390b57cec5SDimitry Andric     // write directly to stdin *this might block if stdin buffer is full*
23400b57cec5SDimitry Andric     // TODO: enqueue this block in circular buffer and send window size to
23410b57cec5SDimitry Andric     // remote host
23420b57cec5SDimitry Andric     ConnectionStatus status;
23430b57cec5SDimitry Andric     Status error;
23440b57cec5SDimitry Andric     m_stdio_communication.Write(tmp, read, status, &error);
23450b57cec5SDimitry Andric     if (error.Fail()) {
23460b57cec5SDimitry Andric       return SendErrorResponse(0x15);
23470b57cec5SDimitry Andric     }
23480b57cec5SDimitry Andric   }
23490b57cec5SDimitry Andric 
23500b57cec5SDimitry Andric   return SendOKResponse();
23510b57cec5SDimitry Andric }
23520b57cec5SDimitry Andric 
23530b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
23540b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_interrupt(
23550b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
235681ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
23570b57cec5SDimitry Andric 
23580b57cec5SDimitry Andric   // Fail if we don't have a current process.
2359fe6060f1SDimitry Andric   if (!m_current_process ||
2360fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
23610b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
23620b57cec5SDimitry Andric     return SendErrorResponse(0x15);
23630b57cec5SDimitry Andric   }
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric   // Interrupt the process.
2366fe6060f1SDimitry Andric   Status error = m_current_process->Interrupt();
23670b57cec5SDimitry Andric   if (error.Fail()) {
2368fe6060f1SDimitry Andric     LLDB_LOG(log, "failed for process {0}: {1}", m_current_process->GetID(),
23690b57cec5SDimitry Andric              error);
23700b57cec5SDimitry Andric     return SendErrorResponse(GDBRemoteServerError::eErrorResume);
23710b57cec5SDimitry Andric   }
23720b57cec5SDimitry Andric 
2373fe6060f1SDimitry Andric   LLDB_LOG(log, "stopped process {0}", m_current_process->GetID());
23740b57cec5SDimitry Andric 
23750b57cec5SDimitry Andric   // No response required from stop all.
23760b57cec5SDimitry Andric   return PacketResult::Success;
23770b57cec5SDimitry Andric }
23780b57cec5SDimitry Andric 
23790b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
23800b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_memory_read(
23810b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
238281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
23830b57cec5SDimitry Andric 
2384fe6060f1SDimitry Andric   if (!m_current_process ||
2385fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
23869dba64beSDimitry Andric     LLDB_LOGF(
23879dba64beSDimitry Andric         log,
23880b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
23890b57cec5SDimitry Andric         __FUNCTION__);
23900b57cec5SDimitry Andric     return SendErrorResponse(0x15);
23910b57cec5SDimitry Andric   }
23920b57cec5SDimitry Andric 
23930b57cec5SDimitry Andric   // Parse out the memory address.
23940b57cec5SDimitry Andric   packet.SetFilePos(strlen("m"));
23950b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
23960b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short m packet");
23970b57cec5SDimitry Andric 
23980b57cec5SDimitry Andric   // Read the address.  Punting on validation.
23990b57cec5SDimitry Andric   // FIXME replace with Hex U64 read with no default value that fails on failed
24000b57cec5SDimitry Andric   // read.
24010b57cec5SDimitry Andric   const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
24020b57cec5SDimitry Andric 
24030b57cec5SDimitry Andric   // Validate comma.
24040b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
24050b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Comma sep missing in m packet");
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric   // Get # bytes to read.
24080b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
24090b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Length missing in m packet");
24100b57cec5SDimitry Andric 
24110b57cec5SDimitry Andric   const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
24120b57cec5SDimitry Andric   if (byte_count == 0) {
24139dba64beSDimitry Andric     LLDB_LOGF(log,
24149dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s nothing to read: "
24150b57cec5SDimitry Andric               "zero-length packet",
24160b57cec5SDimitry Andric               __FUNCTION__);
24170b57cec5SDimitry Andric     return SendOKResponse();
24180b57cec5SDimitry Andric   }
24190b57cec5SDimitry Andric 
24200b57cec5SDimitry Andric   // Allocate the response buffer.
24210b57cec5SDimitry Andric   std::string buf(byte_count, '\0');
24220b57cec5SDimitry Andric   if (buf.empty())
24230b57cec5SDimitry Andric     return SendErrorResponse(0x78);
24240b57cec5SDimitry Andric 
24250b57cec5SDimitry Andric   // Retrieve the process memory.
24260b57cec5SDimitry Andric   size_t bytes_read = 0;
2427fe6060f1SDimitry Andric   Status error = m_current_process->ReadMemoryWithoutTrap(
24280b57cec5SDimitry Andric       read_addr, &buf[0], byte_count, bytes_read);
24290b57cec5SDimitry Andric   if (error.Fail()) {
24309dba64beSDimitry Andric     LLDB_LOGF(log,
24319dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
24320b57cec5SDimitry Andric               " mem 0x%" PRIx64 ": failed to read. Error: %s",
2433fe6060f1SDimitry Andric               __FUNCTION__, m_current_process->GetID(), read_addr,
24340b57cec5SDimitry Andric               error.AsCString());
24350b57cec5SDimitry Andric     return SendErrorResponse(0x08);
24360b57cec5SDimitry Andric   }
24370b57cec5SDimitry Andric 
24380b57cec5SDimitry Andric   if (bytes_read == 0) {
24399dba64beSDimitry Andric     LLDB_LOGF(log,
24409dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
24410b57cec5SDimitry Andric               " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes",
2442fe6060f1SDimitry Andric               __FUNCTION__, m_current_process->GetID(), read_addr, byte_count);
24430b57cec5SDimitry Andric     return SendErrorResponse(0x08);
24440b57cec5SDimitry Andric   }
24450b57cec5SDimitry Andric 
24460b57cec5SDimitry Andric   StreamGDBRemote response;
24470b57cec5SDimitry Andric   packet.SetFilePos(0);
24480b57cec5SDimitry Andric   char kind = packet.GetChar('?');
24490b57cec5SDimitry Andric   if (kind == 'x')
24500b57cec5SDimitry Andric     response.PutEscapedBytes(buf.data(), byte_count);
24510b57cec5SDimitry Andric   else {
24520b57cec5SDimitry Andric     assert(kind == 'm');
24530b57cec5SDimitry Andric     for (size_t i = 0; i < bytes_read; ++i)
24540b57cec5SDimitry Andric       response.PutHex8(buf[i]);
24550b57cec5SDimitry Andric   }
24560b57cec5SDimitry Andric 
24570b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
24580b57cec5SDimitry Andric }
24590b57cec5SDimitry Andric 
24600b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
2461e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) {
246281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
2463e8d8bef9SDimitry Andric 
2464fe6060f1SDimitry Andric   if (!m_current_process ||
2465fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
2466e8d8bef9SDimitry Andric     LLDB_LOGF(
2467e8d8bef9SDimitry Andric         log,
2468e8d8bef9SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
2469e8d8bef9SDimitry Andric         __FUNCTION__);
2470e8d8bef9SDimitry Andric     return SendErrorResponse(0x15);
2471e8d8bef9SDimitry Andric   }
2472e8d8bef9SDimitry Andric 
2473e8d8bef9SDimitry Andric   // Parse out the memory address.
2474e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("_M"));
2475e8d8bef9SDimitry Andric   if (packet.GetBytesLeft() < 1)
2476e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Too short _M packet");
2477e8d8bef9SDimitry Andric 
2478e8d8bef9SDimitry Andric   const lldb::addr_t size = packet.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
2479e8d8bef9SDimitry Andric   if (size == LLDB_INVALID_ADDRESS)
2480e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Address not valid");
2481e8d8bef9SDimitry Andric   if (packet.GetChar() != ',')
2482e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Bad packet");
2483e8d8bef9SDimitry Andric   Permissions perms = {};
2484e8d8bef9SDimitry Andric   while (packet.GetBytesLeft() > 0) {
2485e8d8bef9SDimitry Andric     switch (packet.GetChar()) {
2486e8d8bef9SDimitry Andric     case 'r':
2487e8d8bef9SDimitry Andric       perms |= ePermissionsReadable;
2488e8d8bef9SDimitry Andric       break;
2489e8d8bef9SDimitry Andric     case 'w':
2490e8d8bef9SDimitry Andric       perms |= ePermissionsWritable;
2491e8d8bef9SDimitry Andric       break;
2492e8d8bef9SDimitry Andric     case 'x':
2493e8d8bef9SDimitry Andric       perms |= ePermissionsExecutable;
2494e8d8bef9SDimitry Andric       break;
2495e8d8bef9SDimitry Andric     default:
2496e8d8bef9SDimitry Andric       return SendIllFormedResponse(packet, "Bad permissions");
2497e8d8bef9SDimitry Andric     }
2498e8d8bef9SDimitry Andric   }
2499e8d8bef9SDimitry Andric 
2500fe6060f1SDimitry Andric   llvm::Expected<addr_t> addr = m_current_process->AllocateMemory(size, perms);
2501e8d8bef9SDimitry Andric   if (!addr)
2502e8d8bef9SDimitry Andric     return SendErrorResponse(addr.takeError());
2503e8d8bef9SDimitry Andric 
2504e8d8bef9SDimitry Andric   StreamGDBRemote response;
2505e8d8bef9SDimitry Andric   response.PutHex64(*addr);
2506e8d8bef9SDimitry Andric   return SendPacketNoLock(response.GetString());
2507e8d8bef9SDimitry Andric }
2508e8d8bef9SDimitry Andric 
2509e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
2510e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) {
251181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
2512e8d8bef9SDimitry Andric 
2513fe6060f1SDimitry Andric   if (!m_current_process ||
2514fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
2515e8d8bef9SDimitry Andric     LLDB_LOGF(
2516e8d8bef9SDimitry Andric         log,
2517e8d8bef9SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
2518e8d8bef9SDimitry Andric         __FUNCTION__);
2519e8d8bef9SDimitry Andric     return SendErrorResponse(0x15);
2520e8d8bef9SDimitry Andric   }
2521e8d8bef9SDimitry Andric 
2522e8d8bef9SDimitry Andric   // Parse out the memory address.
2523e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("_m"));
2524e8d8bef9SDimitry Andric   if (packet.GetBytesLeft() < 1)
2525e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Too short m packet");
2526e8d8bef9SDimitry Andric 
2527e8d8bef9SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
2528e8d8bef9SDimitry Andric   if (addr == LLDB_INVALID_ADDRESS)
2529e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "Address not valid");
2530e8d8bef9SDimitry Andric 
2531fe6060f1SDimitry Andric   if (llvm::Error Err = m_current_process->DeallocateMemory(addr))
2532e8d8bef9SDimitry Andric     return SendErrorResponse(std::move(Err));
2533e8d8bef9SDimitry Andric 
2534e8d8bef9SDimitry Andric   return SendOKResponse();
2535e8d8bef9SDimitry Andric }
2536e8d8bef9SDimitry Andric 
2537e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
25380b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
253981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
25400b57cec5SDimitry Andric 
2541fe6060f1SDimitry Andric   if (!m_current_process ||
2542fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
25439dba64beSDimitry Andric     LLDB_LOGF(
25449dba64beSDimitry Andric         log,
25450b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
25460b57cec5SDimitry Andric         __FUNCTION__);
25470b57cec5SDimitry Andric     return SendErrorResponse(0x15);
25480b57cec5SDimitry Andric   }
25490b57cec5SDimitry Andric 
25500b57cec5SDimitry Andric   // Parse out the memory address.
25510b57cec5SDimitry Andric   packet.SetFilePos(strlen("M"));
25520b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
25530b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short M packet");
25540b57cec5SDimitry Andric 
25550b57cec5SDimitry Andric   // Read the address.  Punting on validation.
25560b57cec5SDimitry Andric   // FIXME replace with Hex U64 read with no default value that fails on failed
25570b57cec5SDimitry Andric   // read.
25580b57cec5SDimitry Andric   const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0);
25590b57cec5SDimitry Andric 
25600b57cec5SDimitry Andric   // Validate comma.
25610b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
25620b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Comma sep missing in M packet");
25630b57cec5SDimitry Andric 
25640b57cec5SDimitry Andric   // Get # bytes to read.
25650b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
25660b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Length missing in M packet");
25670b57cec5SDimitry Andric 
25680b57cec5SDimitry Andric   const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
25690b57cec5SDimitry Andric   if (byte_count == 0) {
25700b57cec5SDimitry Andric     LLDB_LOG(log, "nothing to write: zero-length packet");
25710b57cec5SDimitry Andric     return PacketResult::Success;
25720b57cec5SDimitry Andric   }
25730b57cec5SDimitry Andric 
25740b57cec5SDimitry Andric   // Validate colon.
25750b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':'))
25760b57cec5SDimitry Andric     return SendIllFormedResponse(
25770b57cec5SDimitry Andric         packet, "Comma sep missing in M packet after byte length");
25780b57cec5SDimitry Andric 
25790b57cec5SDimitry Andric   // Allocate the conversion buffer.
25800b57cec5SDimitry Andric   std::vector<uint8_t> buf(byte_count, 0);
25810b57cec5SDimitry Andric   if (buf.empty())
25820b57cec5SDimitry Andric     return SendErrorResponse(0x78);
25830b57cec5SDimitry Andric 
25840b57cec5SDimitry Andric   // Convert the hex memory write contents to bytes.
25850b57cec5SDimitry Andric   StreamGDBRemote response;
25860b57cec5SDimitry Andric   const uint64_t convert_count = packet.GetHexBytes(buf, 0);
25870b57cec5SDimitry Andric   if (convert_count != byte_count) {
25880b57cec5SDimitry Andric     LLDB_LOG(log,
25890b57cec5SDimitry Andric              "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} "
25900b57cec5SDimitry Andric              "to convert.",
2591fe6060f1SDimitry Andric              m_current_process->GetID(), write_addr, byte_count, convert_count);
25920b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "M content byte length specified did "
25930b57cec5SDimitry Andric                                          "not match hex-encoded content "
25940b57cec5SDimitry Andric                                          "length");
25950b57cec5SDimitry Andric   }
25960b57cec5SDimitry Andric 
25970b57cec5SDimitry Andric   // Write the process memory.
25980b57cec5SDimitry Andric   size_t bytes_written = 0;
2599fe6060f1SDimitry Andric   Status error = m_current_process->WriteMemory(write_addr, &buf[0], byte_count,
2600fe6060f1SDimitry Andric                                                 bytes_written);
26010b57cec5SDimitry Andric   if (error.Fail()) {
26020b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}",
2603fe6060f1SDimitry Andric              m_current_process->GetID(), write_addr, error);
26040b57cec5SDimitry Andric     return SendErrorResponse(0x09);
26050b57cec5SDimitry Andric   }
26060b57cec5SDimitry Andric 
26070b57cec5SDimitry Andric   if (bytes_written == 0) {
26080b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes",
2609fe6060f1SDimitry Andric              m_current_process->GetID(), write_addr, byte_count);
26100b57cec5SDimitry Andric     return SendErrorResponse(0x09);
26110b57cec5SDimitry Andric   }
26120b57cec5SDimitry Andric 
26130b57cec5SDimitry Andric   return SendOKResponse();
26140b57cec5SDimitry Andric }
26150b57cec5SDimitry Andric 
26160b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
26170b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
26180b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
261981ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
26200b57cec5SDimitry Andric 
26210b57cec5SDimitry Andric   // Currently only the NativeProcessProtocol knows if it can handle a
26220b57cec5SDimitry Andric   // qMemoryRegionInfoSupported request, but we're not guaranteed to be
26230b57cec5SDimitry Andric   // attached to a process.  For now we'll assume the client only asks this
26240b57cec5SDimitry Andric   // when a process is being debugged.
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric   // Ensure we have a process running; otherwise, we can't figure this out
26270b57cec5SDimitry Andric   // since we won't have a NativeProcessProtocol.
2628fe6060f1SDimitry Andric   if (!m_current_process ||
2629fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
26309dba64beSDimitry Andric     LLDB_LOGF(
26319dba64beSDimitry Andric         log,
26320b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
26330b57cec5SDimitry Andric         __FUNCTION__);
26340b57cec5SDimitry Andric     return SendErrorResponse(0x15);
26350b57cec5SDimitry Andric   }
26360b57cec5SDimitry Andric 
26370b57cec5SDimitry Andric   // Test if we can get any region back when asking for the region around NULL.
26380b57cec5SDimitry Andric   MemoryRegionInfo region_info;
2639fe6060f1SDimitry Andric   const Status error = m_current_process->GetMemoryRegionInfo(0, region_info);
26400b57cec5SDimitry Andric   if (error.Fail()) {
26410b57cec5SDimitry Andric     // We don't support memory region info collection for this
26420b57cec5SDimitry Andric     // NativeProcessProtocol.
26430b57cec5SDimitry Andric     return SendUnimplementedResponse("");
26440b57cec5SDimitry Andric   }
26450b57cec5SDimitry Andric 
26460b57cec5SDimitry Andric   return SendOKResponse();
26470b57cec5SDimitry Andric }
26480b57cec5SDimitry Andric 
26490b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
26500b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
26510b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
265281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
26530b57cec5SDimitry Andric 
26540b57cec5SDimitry Andric   // Ensure we have a process.
2655fe6060f1SDimitry Andric   if (!m_current_process ||
2656fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
26579dba64beSDimitry Andric     LLDB_LOGF(
26589dba64beSDimitry Andric         log,
26590b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
26600b57cec5SDimitry Andric         __FUNCTION__);
26610b57cec5SDimitry Andric     return SendErrorResponse(0x15);
26620b57cec5SDimitry Andric   }
26630b57cec5SDimitry Andric 
26640b57cec5SDimitry Andric   // Parse out the memory address.
26650b57cec5SDimitry Andric   packet.SetFilePos(strlen("qMemoryRegionInfo:"));
26660b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
26670b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet");
26680b57cec5SDimitry Andric 
26690b57cec5SDimitry Andric   // Read the address.  Punting on validation.
26700b57cec5SDimitry Andric   const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
26710b57cec5SDimitry Andric 
26720b57cec5SDimitry Andric   StreamGDBRemote response;
26730b57cec5SDimitry Andric 
26740b57cec5SDimitry Andric   // Get the memory region info for the target address.
26750b57cec5SDimitry Andric   MemoryRegionInfo region_info;
26760b57cec5SDimitry Andric   const Status error =
2677fe6060f1SDimitry Andric       m_current_process->GetMemoryRegionInfo(read_addr, region_info);
26780b57cec5SDimitry Andric   if (error.Fail()) {
26790b57cec5SDimitry Andric     // Return the error message.
26800b57cec5SDimitry Andric 
26810b57cec5SDimitry Andric     response.PutCString("error:");
26820b57cec5SDimitry Andric     response.PutStringAsRawHex8(error.AsCString());
26830b57cec5SDimitry Andric     response.PutChar(';');
26840b57cec5SDimitry Andric   } else {
26850b57cec5SDimitry Andric     // Range start and size.
26860b57cec5SDimitry Andric     response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";",
26870b57cec5SDimitry Andric                     region_info.GetRange().GetRangeBase(),
26880b57cec5SDimitry Andric                     region_info.GetRange().GetByteSize());
26890b57cec5SDimitry Andric 
26900b57cec5SDimitry Andric     // Permissions.
26910b57cec5SDimitry Andric     if (region_info.GetReadable() || region_info.GetWritable() ||
26920b57cec5SDimitry Andric         region_info.GetExecutable()) {
26930b57cec5SDimitry Andric       // Write permissions info.
26940b57cec5SDimitry Andric       response.PutCString("permissions:");
26950b57cec5SDimitry Andric 
26960b57cec5SDimitry Andric       if (region_info.GetReadable())
26970b57cec5SDimitry Andric         response.PutChar('r');
26980b57cec5SDimitry Andric       if (region_info.GetWritable())
26990b57cec5SDimitry Andric         response.PutChar('w');
27000b57cec5SDimitry Andric       if (region_info.GetExecutable())
27010b57cec5SDimitry Andric         response.PutChar('x');
27020b57cec5SDimitry Andric 
27030b57cec5SDimitry Andric       response.PutChar(';');
27040b57cec5SDimitry Andric     }
27050b57cec5SDimitry Andric 
2706e8d8bef9SDimitry Andric     // Flags
2707e8d8bef9SDimitry Andric     MemoryRegionInfo::OptionalBool memory_tagged =
2708e8d8bef9SDimitry Andric         region_info.GetMemoryTagged();
2709e8d8bef9SDimitry Andric     if (memory_tagged != MemoryRegionInfo::eDontKnow) {
2710e8d8bef9SDimitry Andric       response.PutCString("flags:");
2711e8d8bef9SDimitry Andric       if (memory_tagged == MemoryRegionInfo::eYes) {
2712e8d8bef9SDimitry Andric         response.PutCString("mt");
2713e8d8bef9SDimitry Andric       }
2714e8d8bef9SDimitry Andric       response.PutChar(';');
2715e8d8bef9SDimitry Andric     }
2716e8d8bef9SDimitry Andric 
27170b57cec5SDimitry Andric     // Name
27180b57cec5SDimitry Andric     ConstString name = region_info.GetName();
27190b57cec5SDimitry Andric     if (name) {
27200b57cec5SDimitry Andric       response.PutCString("name:");
27215ffd83dbSDimitry Andric       response.PutStringAsRawHex8(name.GetStringRef());
27220b57cec5SDimitry Andric       response.PutChar(';');
27230b57cec5SDimitry Andric     }
27240b57cec5SDimitry Andric   }
27250b57cec5SDimitry Andric 
27260b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
27270b57cec5SDimitry Andric }
27280b57cec5SDimitry Andric 
27290b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
27300b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
27310b57cec5SDimitry Andric   // Ensure we have a process.
2732fe6060f1SDimitry Andric   if (!m_current_process ||
2733fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
273481ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Process);
27350b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
27360b57cec5SDimitry Andric     return SendErrorResponse(0x15);
27370b57cec5SDimitry Andric   }
27380b57cec5SDimitry Andric 
27390b57cec5SDimitry Andric   // Parse out software or hardware breakpoint or watchpoint requested.
27400b57cec5SDimitry Andric   packet.SetFilePos(strlen("Z"));
27410b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
27420b57cec5SDimitry Andric     return SendIllFormedResponse(
27430b57cec5SDimitry Andric         packet, "Too short Z packet, missing software/hardware specifier");
27440b57cec5SDimitry Andric 
27450b57cec5SDimitry Andric   bool want_breakpoint = true;
27460b57cec5SDimitry Andric   bool want_hardware = false;
27470b57cec5SDimitry Andric   uint32_t watch_flags = 0;
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric   const GDBStoppointType stoppoint_type =
27500b57cec5SDimitry Andric       GDBStoppointType(packet.GetS32(eStoppointInvalid));
27510b57cec5SDimitry Andric   switch (stoppoint_type) {
27520b57cec5SDimitry Andric   case eBreakpointSoftware:
27530b57cec5SDimitry Andric     want_hardware = false;
27540b57cec5SDimitry Andric     want_breakpoint = true;
27550b57cec5SDimitry Andric     break;
27560b57cec5SDimitry Andric   case eBreakpointHardware:
27570b57cec5SDimitry Andric     want_hardware = true;
27580b57cec5SDimitry Andric     want_breakpoint = true;
27590b57cec5SDimitry Andric     break;
27600b57cec5SDimitry Andric   case eWatchpointWrite:
27610b57cec5SDimitry Andric     watch_flags = 1;
27620b57cec5SDimitry Andric     want_hardware = true;
27630b57cec5SDimitry Andric     want_breakpoint = false;
27640b57cec5SDimitry Andric     break;
27650b57cec5SDimitry Andric   case eWatchpointRead:
27660b57cec5SDimitry Andric     watch_flags = 2;
27670b57cec5SDimitry Andric     want_hardware = true;
27680b57cec5SDimitry Andric     want_breakpoint = false;
27690b57cec5SDimitry Andric     break;
27700b57cec5SDimitry Andric   case eWatchpointReadWrite:
27710b57cec5SDimitry Andric     watch_flags = 3;
27720b57cec5SDimitry Andric     want_hardware = true;
27730b57cec5SDimitry Andric     want_breakpoint = false;
27740b57cec5SDimitry Andric     break;
27750b57cec5SDimitry Andric   case eStoppointInvalid:
27760b57cec5SDimitry Andric     return SendIllFormedResponse(
27770b57cec5SDimitry Andric         packet, "Z packet had invalid software/hardware specifier");
27780b57cec5SDimitry Andric   }
27790b57cec5SDimitry Andric 
27800b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
27810b57cec5SDimitry Andric     return SendIllFormedResponse(
27820b57cec5SDimitry Andric         packet, "Malformed Z packet, expecting comma after stoppoint type");
27830b57cec5SDimitry Andric 
27840b57cec5SDimitry Andric   // Parse out the stoppoint address.
27850b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
27860b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short Z packet, missing address");
27870b57cec5SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
27880b57cec5SDimitry Andric 
27890b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
27900b57cec5SDimitry Andric     return SendIllFormedResponse(
27910b57cec5SDimitry Andric         packet, "Malformed Z packet, expecting comma after address");
27920b57cec5SDimitry Andric 
27930b57cec5SDimitry Andric   // Parse out the stoppoint size (i.e. size hint for opcode size).
27940b57cec5SDimitry Andric   const uint32_t size =
27950b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
27960b57cec5SDimitry Andric   if (size == std::numeric_limits<uint32_t>::max())
27970b57cec5SDimitry Andric     return SendIllFormedResponse(
27980b57cec5SDimitry Andric         packet, "Malformed Z packet, failed to parse size argument");
27990b57cec5SDimitry Andric 
28000b57cec5SDimitry Andric   if (want_breakpoint) {
28010b57cec5SDimitry Andric     // Try to set the breakpoint.
28020b57cec5SDimitry Andric     const Status error =
2803fe6060f1SDimitry Andric         m_current_process->SetBreakpoint(addr, size, want_hardware);
28040b57cec5SDimitry Andric     if (error.Success())
28050b57cec5SDimitry Andric       return SendOKResponse();
280681ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Breakpoints);
28070b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
2808fe6060f1SDimitry Andric              m_current_process->GetID(), error);
28090b57cec5SDimitry Andric     return SendErrorResponse(0x09);
28100b57cec5SDimitry Andric   } else {
28110b57cec5SDimitry Andric     // Try to set the watchpoint.
2812fe6060f1SDimitry Andric     const Status error = m_current_process->SetWatchpoint(
28130b57cec5SDimitry Andric         addr, size, watch_flags, want_hardware);
28140b57cec5SDimitry Andric     if (error.Success())
28150b57cec5SDimitry Andric       return SendOKResponse();
281681ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Watchpoints);
28170b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
2818fe6060f1SDimitry Andric              m_current_process->GetID(), error);
28190b57cec5SDimitry Andric     return SendErrorResponse(0x09);
28200b57cec5SDimitry Andric   }
28210b57cec5SDimitry Andric }
28220b57cec5SDimitry Andric 
28230b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
28240b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
28250b57cec5SDimitry Andric   // Ensure we have a process.
2826fe6060f1SDimitry Andric   if (!m_current_process ||
2827fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
282881ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Process);
28290b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
28300b57cec5SDimitry Andric     return SendErrorResponse(0x15);
28310b57cec5SDimitry Andric   }
28320b57cec5SDimitry Andric 
28330b57cec5SDimitry Andric   // Parse out software or hardware breakpoint or watchpoint requested.
28340b57cec5SDimitry Andric   packet.SetFilePos(strlen("z"));
28350b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
28360b57cec5SDimitry Andric     return SendIllFormedResponse(
28370b57cec5SDimitry Andric         packet, "Too short z packet, missing software/hardware specifier");
28380b57cec5SDimitry Andric 
28390b57cec5SDimitry Andric   bool want_breakpoint = true;
28400b57cec5SDimitry Andric   bool want_hardware = false;
28410b57cec5SDimitry Andric 
28420b57cec5SDimitry Andric   const GDBStoppointType stoppoint_type =
28430b57cec5SDimitry Andric       GDBStoppointType(packet.GetS32(eStoppointInvalid));
28440b57cec5SDimitry Andric   switch (stoppoint_type) {
28450b57cec5SDimitry Andric   case eBreakpointHardware:
28460b57cec5SDimitry Andric     want_breakpoint = true;
28470b57cec5SDimitry Andric     want_hardware = true;
28480b57cec5SDimitry Andric     break;
28490b57cec5SDimitry Andric   case eBreakpointSoftware:
28500b57cec5SDimitry Andric     want_breakpoint = true;
28510b57cec5SDimitry Andric     break;
28520b57cec5SDimitry Andric   case eWatchpointWrite:
28530b57cec5SDimitry Andric     want_breakpoint = false;
28540b57cec5SDimitry Andric     break;
28550b57cec5SDimitry Andric   case eWatchpointRead:
28560b57cec5SDimitry Andric     want_breakpoint = false;
28570b57cec5SDimitry Andric     break;
28580b57cec5SDimitry Andric   case eWatchpointReadWrite:
28590b57cec5SDimitry Andric     want_breakpoint = false;
28600b57cec5SDimitry Andric     break;
28610b57cec5SDimitry Andric   default:
28620b57cec5SDimitry Andric     return SendIllFormedResponse(
28630b57cec5SDimitry Andric         packet, "z packet had invalid software/hardware specifier");
28640b57cec5SDimitry Andric   }
28650b57cec5SDimitry Andric 
28660b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
28670b57cec5SDimitry Andric     return SendIllFormedResponse(
28680b57cec5SDimitry Andric         packet, "Malformed z packet, expecting comma after stoppoint type");
28690b57cec5SDimitry Andric 
28700b57cec5SDimitry Andric   // Parse out the stoppoint address.
28710b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
28720b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short z packet, missing address");
28730b57cec5SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
28740b57cec5SDimitry Andric 
28750b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
28760b57cec5SDimitry Andric     return SendIllFormedResponse(
28770b57cec5SDimitry Andric         packet, "Malformed z packet, expecting comma after address");
28780b57cec5SDimitry Andric 
28790b57cec5SDimitry Andric   /*
28800b57cec5SDimitry Andric   // Parse out the stoppoint size (i.e. size hint for opcode size).
28810b57cec5SDimitry Andric   const uint32_t size = packet.GetHexMaxU32 (false,
28820b57cec5SDimitry Andric   std::numeric_limits<uint32_t>::max ());
28830b57cec5SDimitry Andric   if (size == std::numeric_limits<uint32_t>::max ())
28840b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Malformed z packet, failed to parse
28850b57cec5SDimitry Andric   size argument");
28860b57cec5SDimitry Andric   */
28870b57cec5SDimitry Andric 
28880b57cec5SDimitry Andric   if (want_breakpoint) {
28890b57cec5SDimitry Andric     // Try to clear the breakpoint.
28900b57cec5SDimitry Andric     const Status error =
2891fe6060f1SDimitry Andric         m_current_process->RemoveBreakpoint(addr, want_hardware);
28920b57cec5SDimitry Andric     if (error.Success())
28930b57cec5SDimitry Andric       return SendOKResponse();
289481ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Breakpoints);
28950b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
2896fe6060f1SDimitry Andric              m_current_process->GetID(), error);
28970b57cec5SDimitry Andric     return SendErrorResponse(0x09);
28980b57cec5SDimitry Andric   } else {
28990b57cec5SDimitry Andric     // Try to clear the watchpoint.
2900fe6060f1SDimitry Andric     const Status error = m_current_process->RemoveWatchpoint(addr);
29010b57cec5SDimitry Andric     if (error.Success())
29020b57cec5SDimitry Andric       return SendOKResponse();
290381ad6265SDimitry Andric     Log *log = GetLog(LLDBLog::Watchpoints);
29040b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
2905fe6060f1SDimitry Andric              m_current_process->GetID(), error);
29060b57cec5SDimitry Andric     return SendErrorResponse(0x09);
29070b57cec5SDimitry Andric   }
29080b57cec5SDimitry Andric }
29090b57cec5SDimitry Andric 
29100b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
29110b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
291281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
29130b57cec5SDimitry Andric 
29140b57cec5SDimitry Andric   // Ensure we have a process.
2915fe6060f1SDimitry Andric   if (!m_continue_process ||
2916fe6060f1SDimitry Andric       (m_continue_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
29179dba64beSDimitry Andric     LLDB_LOGF(
29189dba64beSDimitry Andric         log,
29190b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
29200b57cec5SDimitry Andric         __FUNCTION__);
29210b57cec5SDimitry Andric     return SendErrorResponse(0x32);
29220b57cec5SDimitry Andric   }
29230b57cec5SDimitry Andric 
29240b57cec5SDimitry Andric   // We first try to use a continue thread id.  If any one or any all set, use
29250b57cec5SDimitry Andric   // the current thread. Bail out if we don't have a thread id.
29260b57cec5SDimitry Andric   lldb::tid_t tid = GetContinueThreadID();
29270b57cec5SDimitry Andric   if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
29280b57cec5SDimitry Andric     tid = GetCurrentThreadID();
29290b57cec5SDimitry Andric   if (tid == LLDB_INVALID_THREAD_ID)
29300b57cec5SDimitry Andric     return SendErrorResponse(0x33);
29310b57cec5SDimitry Andric 
29320b57cec5SDimitry Andric   // Double check that we have such a thread.
29330b57cec5SDimitry Andric   // TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
2934fe6060f1SDimitry Andric   NativeThreadProtocol *thread = m_continue_process->GetThreadByID(tid);
29350b57cec5SDimitry Andric   if (!thread)
29360b57cec5SDimitry Andric     return SendErrorResponse(0x33);
29370b57cec5SDimitry Andric 
29380b57cec5SDimitry Andric   // Create the step action for the given thread.
29399dba64beSDimitry Andric   ResumeAction action = {tid, eStateStepping, LLDB_INVALID_SIGNAL_NUMBER};
29400b57cec5SDimitry Andric 
29410b57cec5SDimitry Andric   // Setup the actions list.
29420b57cec5SDimitry Andric   ResumeActionList actions;
29430b57cec5SDimitry Andric   actions.Append(action);
29440b57cec5SDimitry Andric 
29450b57cec5SDimitry Andric   // All other threads stop while we're single stepping a thread.
29460b57cec5SDimitry Andric   actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
2947fe6060f1SDimitry Andric   Status error = m_continue_process->Resume(actions);
29480b57cec5SDimitry Andric   if (error.Fail()) {
29499dba64beSDimitry Andric     LLDB_LOGF(log,
29509dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
29510b57cec5SDimitry Andric               " tid %" PRIu64 " Resume() failed with error: %s",
2952fe6060f1SDimitry Andric               __FUNCTION__, m_continue_process->GetID(), tid,
29530b57cec5SDimitry Andric               error.AsCString());
29540b57cec5SDimitry Andric     return SendErrorResponse(0x49);
29550b57cec5SDimitry Andric   }
29560b57cec5SDimitry Andric 
295781ad6265SDimitry Andric   // No response here, unless in non-stop mode.
295881ad6265SDimitry Andric   // Otherwise, the stop or exit will come from the resulting action.
295981ad6265SDimitry Andric   return SendContinueSuccessResponse();
29600b57cec5SDimitry Andric }
29610b57cec5SDimitry Andric 
29620b57cec5SDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
29635ffd83dbSDimitry Andric GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
29645ffd83dbSDimitry Andric   // Ensure we have a thread.
2965fe6060f1SDimitry Andric   NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0);
29665ffd83dbSDimitry Andric   if (!thread)
29675ffd83dbSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
29685ffd83dbSDimitry Andric                                    "No thread available");
29695ffd83dbSDimitry Andric 
297081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
29715ffd83dbSDimitry Andric   // Get the register context for the first thread.
29725ffd83dbSDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
29735ffd83dbSDimitry Andric 
29745ffd83dbSDimitry Andric   StreamString response;
29755ffd83dbSDimitry Andric 
29765ffd83dbSDimitry Andric   response.Printf("<?xml version=\"1.0\"?>");
29775ffd83dbSDimitry Andric   response.Printf("<target version=\"1.0\">");
29785ffd83dbSDimitry Andric 
29795ffd83dbSDimitry Andric   response.Printf("<architecture>%s</architecture>",
2980fe6060f1SDimitry Andric                   m_current_process->GetArchitecture()
29815ffd83dbSDimitry Andric                       .GetTriple()
29825ffd83dbSDimitry Andric                       .getArchName()
29835ffd83dbSDimitry Andric                       .str()
29845ffd83dbSDimitry Andric                       .c_str());
29855ffd83dbSDimitry Andric 
29865ffd83dbSDimitry Andric   response.Printf("<feature>");
29875ffd83dbSDimitry Andric 
29885ffd83dbSDimitry Andric   const int registers_count = reg_context.GetUserRegisterCount();
29895ffd83dbSDimitry Andric   for (int reg_index = 0; reg_index < registers_count; reg_index++) {
29905ffd83dbSDimitry Andric     const RegisterInfo *reg_info =
29915ffd83dbSDimitry Andric         reg_context.GetRegisterInfoAtIndex(reg_index);
29925ffd83dbSDimitry Andric 
29935ffd83dbSDimitry Andric     if (!reg_info) {
29945ffd83dbSDimitry Andric       LLDB_LOGF(log,
29955ffd83dbSDimitry Andric                 "%s failed to get register info for register index %" PRIu32,
29965ffd83dbSDimitry Andric                 "target.xml", reg_index);
29975ffd83dbSDimitry Andric       continue;
29985ffd83dbSDimitry Andric     }
29995ffd83dbSDimitry Andric 
3000e8d8bef9SDimitry Andric     response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 "\" regnum=\"%d\" ",
3001e8d8bef9SDimitry Andric                     reg_info->name, reg_info->byte_size * 8, reg_index);
3002e8d8bef9SDimitry Andric 
3003e8d8bef9SDimitry Andric     if (!reg_context.RegisterOffsetIsDynamic())
3004e8d8bef9SDimitry Andric       response.Printf("offset=\"%" PRIu32 "\" ", reg_info->byte_offset);
30055ffd83dbSDimitry Andric 
30065ffd83dbSDimitry Andric     if (reg_info->alt_name && reg_info->alt_name[0])
30075ffd83dbSDimitry Andric       response.Printf("altname=\"%s\" ", reg_info->alt_name);
30085ffd83dbSDimitry Andric 
30095ffd83dbSDimitry Andric     llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info);
30105ffd83dbSDimitry Andric     if (!encoding.empty())
30115ffd83dbSDimitry Andric       response << "encoding=\"" << encoding << "\" ";
30125ffd83dbSDimitry Andric 
30135ffd83dbSDimitry Andric     llvm::StringRef format = GetFormatNameOrEmpty(*reg_info);
30145ffd83dbSDimitry Andric     if (!format.empty())
30155ffd83dbSDimitry Andric       response << "format=\"" << format << "\" ";
30165ffd83dbSDimitry Andric 
30175ffd83dbSDimitry Andric     const char *const register_set_name =
30185ffd83dbSDimitry Andric         reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index);
30195ffd83dbSDimitry Andric     if (register_set_name)
30205ffd83dbSDimitry Andric       response << "group=\"" << register_set_name << "\" ";
30215ffd83dbSDimitry Andric 
30225ffd83dbSDimitry Andric     if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
30235ffd83dbSDimitry Andric         LLDB_INVALID_REGNUM)
30245ffd83dbSDimitry Andric       response.Printf("ehframe_regnum=\"%" PRIu32 "\" ",
30255ffd83dbSDimitry Andric                       reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
30265ffd83dbSDimitry Andric 
30275ffd83dbSDimitry Andric     if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] !=
30285ffd83dbSDimitry Andric         LLDB_INVALID_REGNUM)
30295ffd83dbSDimitry Andric       response.Printf("dwarf_regnum=\"%" PRIu32 "\" ",
30305ffd83dbSDimitry Andric                       reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
30315ffd83dbSDimitry Andric 
30325ffd83dbSDimitry Andric     llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info);
30335ffd83dbSDimitry Andric     if (!kind_generic.empty())
30345ffd83dbSDimitry Andric       response << "generic=\"" << kind_generic << "\" ";
30355ffd83dbSDimitry Andric 
30365ffd83dbSDimitry Andric     if (reg_info->value_regs &&
30375ffd83dbSDimitry Andric         reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
30385ffd83dbSDimitry Andric       response.PutCString("value_regnums=\"");
30395ffd83dbSDimitry Andric       CollectRegNums(reg_info->value_regs, response, false);
30405ffd83dbSDimitry Andric       response.Printf("\" ");
30415ffd83dbSDimitry Andric     }
30425ffd83dbSDimitry Andric 
30435ffd83dbSDimitry Andric     if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
30445ffd83dbSDimitry Andric       response.PutCString("invalidate_regnums=\"");
30455ffd83dbSDimitry Andric       CollectRegNums(reg_info->invalidate_regs, response, false);
30465ffd83dbSDimitry Andric       response.Printf("\" ");
30475ffd83dbSDimitry Andric     }
30485ffd83dbSDimitry Andric 
30495ffd83dbSDimitry Andric     response.Printf("/>");
30505ffd83dbSDimitry Andric   }
30515ffd83dbSDimitry Andric 
30525ffd83dbSDimitry Andric   response.Printf("</feature>");
30535ffd83dbSDimitry Andric   response.Printf("</target>");
30545ffd83dbSDimitry Andric   return MemoryBuffer::getMemBufferCopy(response.GetString(), "target.xml");
30555ffd83dbSDimitry Andric }
30565ffd83dbSDimitry Andric 
30575ffd83dbSDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
30580b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object,
30590b57cec5SDimitry Andric                                                  llvm::StringRef annex) {
30600b57cec5SDimitry Andric   // Make sure we have a valid process.
3061fe6060f1SDimitry Andric   if (!m_current_process ||
3062fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
30630b57cec5SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
30640b57cec5SDimitry Andric                                    "No process available");
30650b57cec5SDimitry Andric   }
30660b57cec5SDimitry Andric 
30675ffd83dbSDimitry Andric   if (object == "auxv") {
30680b57cec5SDimitry Andric     // Grab the auxv data.
3069fe6060f1SDimitry Andric     auto buffer_or_error = m_current_process->GetAuxvData();
30700b57cec5SDimitry Andric     if (!buffer_or_error)
30710b57cec5SDimitry Andric       return llvm::errorCodeToError(buffer_or_error.getError());
30720b57cec5SDimitry Andric     return std::move(*buffer_or_error);
30730b57cec5SDimitry Andric   }
30740b57cec5SDimitry Andric 
307504eeddc0SDimitry Andric   if (object == "siginfo") {
307604eeddc0SDimitry Andric     NativeThreadProtocol *thread = m_current_process->GetCurrentThread();
307704eeddc0SDimitry Andric     if (!thread)
307804eeddc0SDimitry Andric       return llvm::createStringError(llvm::inconvertibleErrorCode(),
307904eeddc0SDimitry Andric                                      "no current thread");
308004eeddc0SDimitry Andric 
308104eeddc0SDimitry Andric     auto buffer_or_error = thread->GetSiginfo();
308204eeddc0SDimitry Andric     if (!buffer_or_error)
308304eeddc0SDimitry Andric       return buffer_or_error.takeError();
308404eeddc0SDimitry Andric     return std::move(*buffer_or_error);
308504eeddc0SDimitry Andric   }
308604eeddc0SDimitry Andric 
30879dba64beSDimitry Andric   if (object == "libraries-svr4") {
3088fe6060f1SDimitry Andric     auto library_list = m_current_process->GetLoadedSVR4Libraries();
30899dba64beSDimitry Andric     if (!library_list)
30909dba64beSDimitry Andric       return library_list.takeError();
30919dba64beSDimitry Andric 
30929dba64beSDimitry Andric     StreamString response;
30939dba64beSDimitry Andric     response.Printf("<library-list-svr4 version=\"1.0\">");
30949dba64beSDimitry Andric     for (auto const &library : *library_list) {
30959dba64beSDimitry Andric       response.Printf("<library name=\"%s\" ",
30969dba64beSDimitry Andric                       XMLEncodeAttributeValue(library.name.c_str()).c_str());
30979dba64beSDimitry Andric       response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map);
30989dba64beSDimitry Andric       response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr);
30999dba64beSDimitry Andric       response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr);
31009dba64beSDimitry Andric     }
31019dba64beSDimitry Andric     response.Printf("</library-list-svr4>");
31029dba64beSDimitry Andric     return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__);
31039dba64beSDimitry Andric   }
31049dba64beSDimitry Andric 
31055ffd83dbSDimitry Andric   if (object == "features" && annex == "target.xml")
31065ffd83dbSDimitry Andric     return BuildTargetXml();
31075ffd83dbSDimitry Andric 
3108e8d8bef9SDimitry Andric   return llvm::make_error<UnimplementedError>();
31090b57cec5SDimitry Andric }
31100b57cec5SDimitry Andric 
31110b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
31120b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qXfer(
31130b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
31140b57cec5SDimitry Andric   SmallVector<StringRef, 5> fields;
31150b57cec5SDimitry Andric   // The packet format is "qXfer:<object>:<action>:<annex>:offset,length"
31160b57cec5SDimitry Andric   StringRef(packet.GetStringRef()).split(fields, ':', 4);
31170b57cec5SDimitry Andric   if (fields.size() != 5)
31180b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "malformed qXfer packet");
31190b57cec5SDimitry Andric   StringRef &xfer_object = fields[1];
31200b57cec5SDimitry Andric   StringRef &xfer_action = fields[2];
31210b57cec5SDimitry Andric   StringRef &xfer_annex = fields[3];
31220b57cec5SDimitry Andric   StringExtractor offset_data(fields[4]);
31230b57cec5SDimitry Andric   if (xfer_action != "read")
31240b57cec5SDimitry Andric     return SendUnimplementedResponse("qXfer action not supported");
31250b57cec5SDimitry Andric   // Parse offset.
31260b57cec5SDimitry Andric   const uint64_t xfer_offset =
31270b57cec5SDimitry Andric       offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
31280b57cec5SDimitry Andric   if (xfer_offset == std::numeric_limits<uint64_t>::max())
31290b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "qXfer packet missing offset");
31300b57cec5SDimitry Andric   // Parse out comma.
31310b57cec5SDimitry Andric   if (offset_data.GetChar() != ',')
31320b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
31330b57cec5SDimitry Andric                                  "qXfer packet missing comma after offset");
31340b57cec5SDimitry Andric   // Parse out the length.
31350b57cec5SDimitry Andric   const uint64_t xfer_length =
31360b57cec5SDimitry Andric       offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
31370b57cec5SDimitry Andric   if (xfer_length == std::numeric_limits<uint64_t>::max())
31380b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "qXfer packet missing length");
31390b57cec5SDimitry Andric 
31400b57cec5SDimitry Andric   // Get a previously constructed buffer if it exists or create it now.
31410b57cec5SDimitry Andric   std::string buffer_key = (xfer_object + xfer_action + xfer_annex).str();
31420b57cec5SDimitry Andric   auto buffer_it = m_xfer_buffer_map.find(buffer_key);
31430b57cec5SDimitry Andric   if (buffer_it == m_xfer_buffer_map.end()) {
31440b57cec5SDimitry Andric     auto buffer_up = ReadXferObject(xfer_object, xfer_annex);
31450b57cec5SDimitry Andric     if (!buffer_up)
31460b57cec5SDimitry Andric       return SendErrorResponse(buffer_up.takeError());
31470b57cec5SDimitry Andric     buffer_it = m_xfer_buffer_map
31480b57cec5SDimitry Andric                     .insert(std::make_pair(buffer_key, std::move(*buffer_up)))
31490b57cec5SDimitry Andric                     .first;
31500b57cec5SDimitry Andric   }
31510b57cec5SDimitry Andric 
31520b57cec5SDimitry Andric   // Send back the response
31530b57cec5SDimitry Andric   StreamGDBRemote response;
31540b57cec5SDimitry Andric   bool done_with_buffer = false;
31550b57cec5SDimitry Andric   llvm::StringRef buffer = buffer_it->second->getBuffer();
31560b57cec5SDimitry Andric   if (xfer_offset >= buffer.size()) {
31570b57cec5SDimitry Andric     // We have nothing left to send.  Mark the buffer as complete.
31580b57cec5SDimitry Andric     response.PutChar('l');
31590b57cec5SDimitry Andric     done_with_buffer = true;
31600b57cec5SDimitry Andric   } else {
31610b57cec5SDimitry Andric     // Figure out how many bytes are available starting at the given offset.
31620b57cec5SDimitry Andric     buffer = buffer.drop_front(xfer_offset);
31630b57cec5SDimitry Andric     // Mark the response type according to whether we're reading the remainder
31640b57cec5SDimitry Andric     // of the data.
31650b57cec5SDimitry Andric     if (xfer_length >= buffer.size()) {
31660b57cec5SDimitry Andric       // There will be nothing left to read after this
31670b57cec5SDimitry Andric       response.PutChar('l');
31680b57cec5SDimitry Andric       done_with_buffer = true;
31690b57cec5SDimitry Andric     } else {
31700b57cec5SDimitry Andric       // There will still be bytes to read after this request.
31710b57cec5SDimitry Andric       response.PutChar('m');
31720b57cec5SDimitry Andric       buffer = buffer.take_front(xfer_length);
31730b57cec5SDimitry Andric     }
31740b57cec5SDimitry Andric     // Now write the data in encoded binary form.
31750b57cec5SDimitry Andric     response.PutEscapedBytes(buffer.data(), buffer.size());
31760b57cec5SDimitry Andric   }
31770b57cec5SDimitry Andric 
31780b57cec5SDimitry Andric   if (done_with_buffer)
31790b57cec5SDimitry Andric     m_xfer_buffer_map.erase(buffer_it);
31800b57cec5SDimitry Andric 
31810b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
31820b57cec5SDimitry Andric }
31830b57cec5SDimitry Andric 
31840b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
31850b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
31860b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
318781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
31880b57cec5SDimitry Andric 
31890b57cec5SDimitry Andric   // Move past packet name.
31900b57cec5SDimitry Andric   packet.SetFilePos(strlen("QSaveRegisterState"));
31910b57cec5SDimitry Andric 
31920b57cec5SDimitry Andric   // Get the thread to use.
31930b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
31940b57cec5SDimitry Andric   if (!thread) {
31950b57cec5SDimitry Andric     if (m_thread_suffix_supported)
31960b57cec5SDimitry Andric       return SendIllFormedResponse(
31970b57cec5SDimitry Andric           packet, "No thread specified in QSaveRegisterState packet");
31980b57cec5SDimitry Andric     else
31990b57cec5SDimitry Andric       return SendIllFormedResponse(packet,
32000b57cec5SDimitry Andric                                    "No thread was is set with the Hg packet");
32010b57cec5SDimitry Andric   }
32020b57cec5SDimitry Andric 
32030b57cec5SDimitry Andric   // Grab the register context for the thread.
32040b57cec5SDimitry Andric   NativeRegisterContext& reg_context = thread->GetRegisterContext();
32050b57cec5SDimitry Andric 
32060b57cec5SDimitry Andric   // Save registers to a buffer.
320781ad6265SDimitry Andric   WritableDataBufferSP register_data_sp;
32080b57cec5SDimitry Andric   Status error = reg_context.ReadAllRegisterValues(register_data_sp);
32090b57cec5SDimitry Andric   if (error.Fail()) {
32100b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to save all register values: {1}",
3211fe6060f1SDimitry Andric              m_current_process->GetID(), error);
32120b57cec5SDimitry Andric     return SendErrorResponse(0x75);
32130b57cec5SDimitry Andric   }
32140b57cec5SDimitry Andric 
32150b57cec5SDimitry Andric   // Allocate a new save id.
32160b57cec5SDimitry Andric   const uint32_t save_id = GetNextSavedRegistersID();
32170b57cec5SDimitry Andric   assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) &&
32180b57cec5SDimitry Andric          "GetNextRegisterSaveID() returned an existing register save id");
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric   // Save the register data buffer under the save id.
32210b57cec5SDimitry Andric   {
32220b57cec5SDimitry Andric     std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
32230b57cec5SDimitry Andric     m_saved_registers_map[save_id] = register_data_sp;
32240b57cec5SDimitry Andric   }
32250b57cec5SDimitry Andric 
32260b57cec5SDimitry Andric   // Write the response.
32270b57cec5SDimitry Andric   StreamGDBRemote response;
32280b57cec5SDimitry Andric   response.Printf("%" PRIu32, save_id);
32290b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
32300b57cec5SDimitry Andric }
32310b57cec5SDimitry Andric 
32320b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
32330b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
32340b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
323581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
32360b57cec5SDimitry Andric 
32370b57cec5SDimitry Andric   // Parse out save id.
32380b57cec5SDimitry Andric   packet.SetFilePos(strlen("QRestoreRegisterState:"));
32390b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
32400b57cec5SDimitry Andric     return SendIllFormedResponse(
32410b57cec5SDimitry Andric         packet, "QRestoreRegisterState packet missing register save id");
32420b57cec5SDimitry Andric 
32430b57cec5SDimitry Andric   const uint32_t save_id = packet.GetU32(0);
32440b57cec5SDimitry Andric   if (save_id == 0) {
32450b57cec5SDimitry Andric     LLDB_LOG(log, "QRestoreRegisterState packet has malformed save id, "
32460b57cec5SDimitry Andric                   "expecting decimal uint32_t");
32470b57cec5SDimitry Andric     return SendErrorResponse(0x76);
32480b57cec5SDimitry Andric   }
32490b57cec5SDimitry Andric 
32500b57cec5SDimitry Andric   // Get the thread to use.
32510b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
32520b57cec5SDimitry Andric   if (!thread) {
32530b57cec5SDimitry Andric     if (m_thread_suffix_supported)
32540b57cec5SDimitry Andric       return SendIllFormedResponse(
32550b57cec5SDimitry Andric           packet, "No thread specified in QRestoreRegisterState packet");
32560b57cec5SDimitry Andric     else
32570b57cec5SDimitry Andric       return SendIllFormedResponse(packet,
32580b57cec5SDimitry Andric                                    "No thread was is set with the Hg packet");
32590b57cec5SDimitry Andric   }
32600b57cec5SDimitry Andric 
32610b57cec5SDimitry Andric   // Grab the register context for the thread.
32620b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
32630b57cec5SDimitry Andric 
32640b57cec5SDimitry Andric   // Retrieve register state buffer, then remove from the list.
32650b57cec5SDimitry Andric   DataBufferSP register_data_sp;
32660b57cec5SDimitry Andric   {
32670b57cec5SDimitry Andric     std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
32680b57cec5SDimitry Andric 
32690b57cec5SDimitry Andric     // Find the register set buffer for the given save id.
32700b57cec5SDimitry Andric     auto it = m_saved_registers_map.find(save_id);
32710b57cec5SDimitry Andric     if (it == m_saved_registers_map.end()) {
32720b57cec5SDimitry Andric       LLDB_LOG(log,
32730b57cec5SDimitry Andric                "pid {0} does not have a register set save buffer for id {1}",
3274fe6060f1SDimitry Andric                m_current_process->GetID(), save_id);
32750b57cec5SDimitry Andric       return SendErrorResponse(0x77);
32760b57cec5SDimitry Andric     }
32770b57cec5SDimitry Andric     register_data_sp = it->second;
32780b57cec5SDimitry Andric 
32790b57cec5SDimitry Andric     // Remove it from the map.
32800b57cec5SDimitry Andric     m_saved_registers_map.erase(it);
32810b57cec5SDimitry Andric   }
32820b57cec5SDimitry Andric 
32830b57cec5SDimitry Andric   Status error = reg_context.WriteAllRegisterValues(register_data_sp);
32840b57cec5SDimitry Andric   if (error.Fail()) {
32850b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to restore all register values: {1}",
3286fe6060f1SDimitry Andric              m_current_process->GetID(), error);
32870b57cec5SDimitry Andric     return SendErrorResponse(0x77);
32880b57cec5SDimitry Andric   }
32890b57cec5SDimitry Andric 
32900b57cec5SDimitry Andric   return SendOKResponse();
32910b57cec5SDimitry Andric }
32920b57cec5SDimitry Andric 
32930b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
32940b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttach(
32950b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
329681ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
32970b57cec5SDimitry Andric 
32980b57cec5SDimitry Andric   // Consume the ';' after vAttach.
32990b57cec5SDimitry Andric   packet.SetFilePos(strlen("vAttach"));
33000b57cec5SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
33010b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "vAttach missing expected ';'");
33020b57cec5SDimitry Andric 
33030b57cec5SDimitry Andric   // Grab the PID to which we will attach (assume hex encoding).
33040b57cec5SDimitry Andric   lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
33050b57cec5SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
33060b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
33070b57cec5SDimitry Andric                                  "vAttach failed to parse the process id");
33080b57cec5SDimitry Andric 
33090b57cec5SDimitry Andric   // Attempt to attach.
33109dba64beSDimitry Andric   LLDB_LOGF(log,
33119dba64beSDimitry Andric             "GDBRemoteCommunicationServerLLGS::%s attempting to attach to "
33120b57cec5SDimitry Andric             "pid %" PRIu64,
33130b57cec5SDimitry Andric             __FUNCTION__, pid);
33140b57cec5SDimitry Andric 
33150b57cec5SDimitry Andric   Status error = AttachToProcess(pid);
33160b57cec5SDimitry Andric 
33170b57cec5SDimitry Andric   if (error.Fail()) {
33189dba64beSDimitry Andric     LLDB_LOGF(log,
33199dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to attach to "
33200b57cec5SDimitry Andric               "pid %" PRIu64 ": %s\n",
33210b57cec5SDimitry Andric               __FUNCTION__, pid, error.AsCString());
33220b57cec5SDimitry Andric     return SendErrorResponse(error);
33230b57cec5SDimitry Andric   }
33240b57cec5SDimitry Andric 
33250b57cec5SDimitry Andric   // Notify we attached by sending a stop packet.
332681ad6265SDimitry Andric   assert(m_current_process);
332781ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
332881ad6265SDimitry Andric                                 m_current_process->GetState(),
332981ad6265SDimitry Andric                                 /*force_synchronous=*/false);
33300b57cec5SDimitry Andric }
33310b57cec5SDimitry Andric 
33320b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3333e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachWait(
3334e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
333581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3336e8d8bef9SDimitry Andric 
3337e8d8bef9SDimitry Andric   // Consume the ';' after the identifier.
3338e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("vAttachWait"));
3339e8d8bef9SDimitry Andric 
3340e8d8bef9SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
3341e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "vAttachWait missing expected ';'");
3342e8d8bef9SDimitry Andric 
3343e8d8bef9SDimitry Andric   // Allocate the buffer for the process name from vAttachWait.
3344e8d8bef9SDimitry Andric   std::string process_name;
3345e8d8bef9SDimitry Andric   if (!packet.GetHexByteString(process_name))
3346e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet,
3347e8d8bef9SDimitry Andric                                  "vAttachWait failed to parse process name");
3348e8d8bef9SDimitry Andric 
3349e8d8bef9SDimitry Andric   LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name);
3350e8d8bef9SDimitry Andric 
3351e8d8bef9SDimitry Andric   Status error = AttachWaitProcess(process_name, false);
3352e8d8bef9SDimitry Andric   if (error.Fail()) {
3353e8d8bef9SDimitry Andric     LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name,
3354e8d8bef9SDimitry Andric              error);
3355e8d8bef9SDimitry Andric     return SendErrorResponse(error);
3356e8d8bef9SDimitry Andric   }
3357e8d8bef9SDimitry Andric 
3358e8d8bef9SDimitry Andric   // Notify we attached by sending a stop packet.
335981ad6265SDimitry Andric   assert(m_current_process);
336081ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
336181ad6265SDimitry Andric                                 m_current_process->GetState(),
336281ad6265SDimitry Andric                                 /*force_synchronous=*/false);
3363e8d8bef9SDimitry Andric }
3364e8d8bef9SDimitry Andric 
3365e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
3366e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qVAttachOrWaitSupported(
3367e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
3368e8d8bef9SDimitry Andric   return SendOKResponse();
3369e8d8bef9SDimitry Andric }
3370e8d8bef9SDimitry Andric 
3371e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
3372e8d8bef9SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait(
3373e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
337481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3375e8d8bef9SDimitry Andric 
3376e8d8bef9SDimitry Andric   // Consume the ';' after the identifier.
3377e8d8bef9SDimitry Andric   packet.SetFilePos(strlen("vAttachOrWait"));
3378e8d8bef9SDimitry Andric 
3379e8d8bef9SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
3380e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet, "vAttachOrWait missing expected ';'");
3381e8d8bef9SDimitry Andric 
3382e8d8bef9SDimitry Andric   // Allocate the buffer for the process name from vAttachWait.
3383e8d8bef9SDimitry Andric   std::string process_name;
3384e8d8bef9SDimitry Andric   if (!packet.GetHexByteString(process_name))
3385e8d8bef9SDimitry Andric     return SendIllFormedResponse(packet,
3386e8d8bef9SDimitry Andric                                  "vAttachOrWait failed to parse process name");
3387e8d8bef9SDimitry Andric 
3388e8d8bef9SDimitry Andric   LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name);
3389e8d8bef9SDimitry Andric 
3390e8d8bef9SDimitry Andric   Status error = AttachWaitProcess(process_name, true);
3391e8d8bef9SDimitry Andric   if (error.Fail()) {
3392e8d8bef9SDimitry Andric     LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name,
3393e8d8bef9SDimitry Andric              error);
3394e8d8bef9SDimitry Andric     return SendErrorResponse(error);
3395e8d8bef9SDimitry Andric   }
3396e8d8bef9SDimitry Andric 
3397e8d8bef9SDimitry Andric   // Notify we attached by sending a stop packet.
339881ad6265SDimitry Andric   assert(m_current_process);
339981ad6265SDimitry Andric   return SendStopReasonForState(*m_current_process,
340081ad6265SDimitry Andric                                 m_current_process->GetState(),
340181ad6265SDimitry Andric                                 /*force_synchronous=*/false);
3402e8d8bef9SDimitry Andric }
3403e8d8bef9SDimitry Andric 
3404e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
3405349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vRun(
3406349cc55cSDimitry Andric     StringExtractorGDBRemote &packet) {
340781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3408349cc55cSDimitry Andric 
3409349cc55cSDimitry Andric   llvm::StringRef s = packet.GetStringRef();
3410349cc55cSDimitry Andric   if (!s.consume_front("vRun;"))
3411349cc55cSDimitry Andric     return SendErrorResponse(8);
3412349cc55cSDimitry Andric 
3413349cc55cSDimitry Andric   llvm::SmallVector<llvm::StringRef, 16> argv;
3414349cc55cSDimitry Andric   s.split(argv, ';');
3415349cc55cSDimitry Andric 
3416349cc55cSDimitry Andric   for (llvm::StringRef hex_arg : argv) {
3417349cc55cSDimitry Andric     StringExtractor arg_ext{hex_arg};
3418349cc55cSDimitry Andric     std::string arg;
3419349cc55cSDimitry Andric     arg_ext.GetHexByteString(arg);
3420349cc55cSDimitry Andric     m_process_launch_info.GetArguments().AppendArgument(arg);
3421349cc55cSDimitry Andric     LLDB_LOGF(log, "LLGSPacketHandler::%s added arg: \"%s\"", __FUNCTION__,
3422349cc55cSDimitry Andric               arg.c_str());
3423349cc55cSDimitry Andric   }
3424349cc55cSDimitry Andric 
3425349cc55cSDimitry Andric   if (!argv.empty()) {
3426349cc55cSDimitry Andric     m_process_launch_info.GetExecutableFile().SetFile(
3427349cc55cSDimitry Andric         m_process_launch_info.GetArguments()[0].ref(), FileSpec::Style::native);
3428349cc55cSDimitry Andric     m_process_launch_error = LaunchProcess();
342981ad6265SDimitry Andric     if (m_process_launch_error.Success()) {
343081ad6265SDimitry Andric       assert(m_current_process);
343181ad6265SDimitry Andric       return SendStopReasonForState(*m_current_process,
343281ad6265SDimitry Andric                                     m_current_process->GetState(),
343381ad6265SDimitry Andric                                     /*force_synchronous=*/true);
343481ad6265SDimitry Andric     }
3435349cc55cSDimitry Andric     LLDB_LOG(log, "failed to launch exe: {0}", m_process_launch_error);
3436349cc55cSDimitry Andric   }
3437349cc55cSDimitry Andric   return SendErrorResponse(8);
3438349cc55cSDimitry Andric }
3439349cc55cSDimitry Andric 
3440349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult
34410b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
344281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
34430b57cec5SDimitry Andric   StopSTDIOForwarding();
34440b57cec5SDimitry Andric 
34450b57cec5SDimitry Andric   lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
34460b57cec5SDimitry Andric 
34470b57cec5SDimitry Andric   // Consume the ';' after D.
34480b57cec5SDimitry Andric   packet.SetFilePos(1);
34490b57cec5SDimitry Andric   if (packet.GetBytesLeft()) {
34500b57cec5SDimitry Andric     if (packet.GetChar() != ';')
34510b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "D missing expected ';'");
34520b57cec5SDimitry Andric 
34530b57cec5SDimitry Andric     // Grab the PID from which we will detach (assume hex encoding).
34540b57cec5SDimitry Andric     pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
34550b57cec5SDimitry Andric     if (pid == LLDB_INVALID_PROCESS_ID)
34560b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "D failed to parse the process id");
34570b57cec5SDimitry Andric   }
34580b57cec5SDimitry Andric 
3459fe6060f1SDimitry Andric   // Detach forked children if their PID was specified *or* no PID was requested
3460fe6060f1SDimitry Andric   // (i.e. detach-all packet).
3461fe6060f1SDimitry Andric   llvm::Error detach_error = llvm::Error::success();
3462fe6060f1SDimitry Andric   bool detached = false;
3463fe6060f1SDimitry Andric   for (auto it = m_debugged_processes.begin();
3464fe6060f1SDimitry Andric        it != m_debugged_processes.end();) {
3465fe6060f1SDimitry Andric     if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) {
346681ad6265SDimitry Andric       LLDB_LOGF(log,
346781ad6265SDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s detaching %" PRId64,
346881ad6265SDimitry Andric                 __FUNCTION__, it->first);
3469fe6060f1SDimitry Andric       if (llvm::Error e = it->second->Detach().ToError())
3470fe6060f1SDimitry Andric         detach_error = llvm::joinErrors(std::move(detach_error), std::move(e));
3471fe6060f1SDimitry Andric       else {
3472fe6060f1SDimitry Andric         if (it->second.get() == m_current_process)
3473fe6060f1SDimitry Andric           m_current_process = nullptr;
3474fe6060f1SDimitry Andric         if (it->second.get() == m_continue_process)
3475fe6060f1SDimitry Andric           m_continue_process = nullptr;
3476fe6060f1SDimitry Andric         it = m_debugged_processes.erase(it);
3477fe6060f1SDimitry Andric         detached = true;
3478fe6060f1SDimitry Andric         continue;
3479fe6060f1SDimitry Andric       }
3480fe6060f1SDimitry Andric     }
3481fe6060f1SDimitry Andric     ++it;
34820b57cec5SDimitry Andric   }
34830b57cec5SDimitry Andric 
3484fe6060f1SDimitry Andric   if (detach_error)
3485fe6060f1SDimitry Andric     return SendErrorResponse(std::move(detach_error));
3486fe6060f1SDimitry Andric   if (!detached)
3487fe6060f1SDimitry Andric     return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid));
34880b57cec5SDimitry Andric   return SendOKResponse();
34890b57cec5SDimitry Andric }
34900b57cec5SDimitry Andric 
34910b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
34920b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
34930b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
349481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
349581ad6265SDimitry Andric 
349681ad6265SDimitry Andric   if (!m_current_process ||
349781ad6265SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
349881ad6265SDimitry Andric     return SendErrorResponse(50);
34990b57cec5SDimitry Andric 
35000b57cec5SDimitry Andric   packet.SetFilePos(strlen("qThreadStopInfo"));
3501fe6060f1SDimitry Andric   const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
35020b57cec5SDimitry Andric   if (tid == LLDB_INVALID_THREAD_ID) {
35039dba64beSDimitry Andric     LLDB_LOGF(log,
35049dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
35050b57cec5SDimitry Andric               "parse thread id from request \"%s\"",
35069dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
35070b57cec5SDimitry Andric     return SendErrorResponse(0x15);
35080b57cec5SDimitry Andric   }
350981ad6265SDimitry Andric   return SendStopReplyPacketForThread(*m_current_process, tid,
351081ad6265SDimitry Andric                                       /*force_synchronous=*/true);
35110b57cec5SDimitry Andric }
35120b57cec5SDimitry Andric 
35130b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
35140b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
35150b57cec5SDimitry Andric     StringExtractorGDBRemote &) {
351681ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread);
35170b57cec5SDimitry Andric 
35180b57cec5SDimitry Andric   // Ensure we have a debugged process.
3519fe6060f1SDimitry Andric   if (!m_current_process ||
3520fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
35210b57cec5SDimitry Andric     return SendErrorResponse(50);
3522fe6060f1SDimitry Andric   LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID());
35230b57cec5SDimitry Andric 
35240b57cec5SDimitry Andric   StreamString response;
35250b57cec5SDimitry Andric   const bool threads_with_valid_stop_info_only = false;
3526fe6060f1SDimitry Andric   llvm::Expected<json::Value> threads_info =
3527fe6060f1SDimitry Andric       GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only);
35289dba64beSDimitry Andric   if (!threads_info) {
3529480093f4SDimitry Andric     LLDB_LOG_ERROR(log, threads_info.takeError(),
3530480093f4SDimitry Andric                    "failed to prepare a packet for pid {1}: {0}",
3531fe6060f1SDimitry Andric                    m_current_process->GetID());
35320b57cec5SDimitry Andric     return SendErrorResponse(52);
35330b57cec5SDimitry Andric   }
35340b57cec5SDimitry Andric 
35359dba64beSDimitry Andric   response.AsRawOstream() << *threads_info;
35360b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
35370b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
35380b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
35390b57cec5SDimitry Andric }
35400b57cec5SDimitry Andric 
35410b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
35420b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
35430b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
35440b57cec5SDimitry Andric   // Fail if we don't have a current process.
3545fe6060f1SDimitry Andric   if (!m_current_process ||
3546fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
35470b57cec5SDimitry Andric     return SendErrorResponse(68);
35480b57cec5SDimitry Andric 
35490b57cec5SDimitry Andric   packet.SetFilePos(strlen("qWatchpointSupportInfo"));
35500b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0)
35510b57cec5SDimitry Andric     return SendOKResponse();
35520b57cec5SDimitry Andric   if (packet.GetChar() != ':')
35530b57cec5SDimitry Andric     return SendErrorResponse(67);
35540b57cec5SDimitry Andric 
3555fe6060f1SDimitry Andric   auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo();
35560b57cec5SDimitry Andric 
35570b57cec5SDimitry Andric   StreamGDBRemote response;
35580b57cec5SDimitry Andric   if (hw_debug_cap == llvm::None)
35590b57cec5SDimitry Andric     response.Printf("num:0;");
35600b57cec5SDimitry Andric   else
35610b57cec5SDimitry Andric     response.Printf("num:%d;", hw_debug_cap->second);
35620b57cec5SDimitry Andric 
35630b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
35640b57cec5SDimitry Andric }
35650b57cec5SDimitry Andric 
35660b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
35670b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
35680b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
35690b57cec5SDimitry Andric   // Fail if we don't have a current process.
3570fe6060f1SDimitry Andric   if (!m_current_process ||
3571fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
35720b57cec5SDimitry Andric     return SendErrorResponse(67);
35730b57cec5SDimitry Andric 
35740b57cec5SDimitry Andric   packet.SetFilePos(strlen("qFileLoadAddress:"));
35750b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0)
35760b57cec5SDimitry Andric     return SendErrorResponse(68);
35770b57cec5SDimitry Andric 
35780b57cec5SDimitry Andric   std::string file_name;
35790b57cec5SDimitry Andric   packet.GetHexByteString(file_name);
35800b57cec5SDimitry Andric 
35810b57cec5SDimitry Andric   lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
35820b57cec5SDimitry Andric   Status error =
3583fe6060f1SDimitry Andric       m_current_process->GetFileLoadAddress(file_name, file_load_address);
35840b57cec5SDimitry Andric   if (error.Fail())
35850b57cec5SDimitry Andric     return SendErrorResponse(69);
35860b57cec5SDimitry Andric 
35870b57cec5SDimitry Andric   if (file_load_address == LLDB_INVALID_ADDRESS)
35880b57cec5SDimitry Andric     return SendErrorResponse(1); // File not loaded
35890b57cec5SDimitry Andric 
35900b57cec5SDimitry Andric   StreamGDBRemote response;
35910b57cec5SDimitry Andric   response.PutHex64(file_load_address);
35920b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
35930b57cec5SDimitry Andric }
35940b57cec5SDimitry Andric 
35950b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
35960b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
35970b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
35980b57cec5SDimitry Andric   std::vector<int> signals;
35990b57cec5SDimitry Andric   packet.SetFilePos(strlen("QPassSignals:"));
36000b57cec5SDimitry Andric 
36010b57cec5SDimitry Andric   // Read sequence of hex signal numbers divided by a semicolon and optionally
36020b57cec5SDimitry Andric   // spaces.
36030b57cec5SDimitry Andric   while (packet.GetBytesLeft() > 0) {
36040b57cec5SDimitry Andric     int signal = packet.GetS32(-1, 16);
36050b57cec5SDimitry Andric     if (signal < 0)
36060b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Failed to parse signal number.");
36070b57cec5SDimitry Andric     signals.push_back(signal);
36080b57cec5SDimitry Andric 
36090b57cec5SDimitry Andric     packet.SkipSpaces();
36100b57cec5SDimitry Andric     char separator = packet.GetChar();
36110b57cec5SDimitry Andric     if (separator == '\0')
36120b57cec5SDimitry Andric       break; // End of string
36130b57cec5SDimitry Andric     if (separator != ';')
36140b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Invalid separator,"
36150b57cec5SDimitry Andric                                             " expected semicolon.");
36160b57cec5SDimitry Andric   }
36170b57cec5SDimitry Andric 
36180b57cec5SDimitry Andric   // Fail if we don't have a current process.
3619fe6060f1SDimitry Andric   if (!m_current_process)
36200b57cec5SDimitry Andric     return SendErrorResponse(68);
36210b57cec5SDimitry Andric 
3622fe6060f1SDimitry Andric   Status error = m_current_process->IgnoreSignals(signals);
36230b57cec5SDimitry Andric   if (error.Fail())
36240b57cec5SDimitry Andric     return SendErrorResponse(69);
36250b57cec5SDimitry Andric 
36260b57cec5SDimitry Andric   return SendOKResponse();
36270b57cec5SDimitry Andric }
36280b57cec5SDimitry Andric 
3629fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
3630fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemTags(
3631fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
363281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3633fe6060f1SDimitry Andric 
3634fe6060f1SDimitry Andric   // Ensure we have a process.
3635fe6060f1SDimitry Andric   if (!m_current_process ||
3636fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
3637fe6060f1SDimitry Andric     LLDB_LOGF(
3638fe6060f1SDimitry Andric         log,
3639fe6060f1SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
3640fe6060f1SDimitry Andric         __FUNCTION__);
3641fe6060f1SDimitry Andric     return SendErrorResponse(1);
3642fe6060f1SDimitry Andric   }
3643fe6060f1SDimitry Andric 
3644fe6060f1SDimitry Andric   // We are expecting
3645fe6060f1SDimitry Andric   // qMemTags:<hex address>,<hex length>:<hex type>
3646fe6060f1SDimitry Andric 
3647fe6060f1SDimitry Andric   // Address
3648fe6060f1SDimitry Andric   packet.SetFilePos(strlen("qMemTags:"));
3649fe6060f1SDimitry Andric   const char *current_char = packet.Peek();
3650fe6060f1SDimitry Andric   if (!current_char || *current_char == ',')
3651fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, "Missing address in qMemTags packet");
3652fe6060f1SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3653fe6060f1SDimitry Andric 
3654fe6060f1SDimitry Andric   // Length
3655fe6060f1SDimitry Andric   char previous_char = packet.GetChar();
3656fe6060f1SDimitry Andric   current_char = packet.Peek();
3657fe6060f1SDimitry Andric   // If we don't have a separator or the length field is empty
3658fe6060f1SDimitry Andric   if (previous_char != ',' || (current_char && *current_char == ':'))
3659fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3660fe6060f1SDimitry Andric                                  "Invalid addr,length pair in qMemTags packet");
3661fe6060f1SDimitry Andric 
3662fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1)
3663fe6060f1SDimitry Andric     return SendIllFormedResponse(
3664fe6060f1SDimitry Andric         packet, "Too short qMemtags: packet (looking for length)");
3665fe6060f1SDimitry Andric   const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3666fe6060f1SDimitry Andric 
3667fe6060f1SDimitry Andric   // Type
3668fe6060f1SDimitry Andric   const char *invalid_type_err = "Invalid type field in qMemTags: packet";
3669fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3670fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3671fe6060f1SDimitry Andric 
36726e75b2fbSDimitry Andric   // Type is a signed integer but packed into the packet as its raw bytes.
36736e75b2fbSDimitry Andric   // However, our GetU64 uses strtoull which allows +/-. We do not want this.
36746e75b2fbSDimitry Andric   const char *first_type_char = packet.Peek();
36756e75b2fbSDimitry Andric   if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
36766e75b2fbSDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
36776e75b2fbSDimitry Andric 
36786e75b2fbSDimitry Andric   // Extract type as unsigned then cast to signed.
36796e75b2fbSDimitry Andric   // Using a uint64_t here so that we have some value outside of the 32 bit
36806e75b2fbSDimitry Andric   // range to use as the invalid return value.
36816e75b2fbSDimitry Andric   uint64_t raw_type =
36826e75b2fbSDimitry Andric       packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
36836e75b2fbSDimitry Andric 
36846e75b2fbSDimitry Andric   if ( // Make sure the cast below would be valid
36856e75b2fbSDimitry Andric       raw_type > std::numeric_limits<uint32_t>::max() ||
3686fe6060f1SDimitry Andric       // To catch inputs like "123aardvark" that will parse but clearly aren't
3687fe6060f1SDimitry Andric       // valid in this case.
3688fe6060f1SDimitry Andric       packet.GetBytesLeft()) {
3689fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3690fe6060f1SDimitry Andric   }
3691fe6060f1SDimitry Andric 
36926e75b2fbSDimitry Andric   // First narrow to 32 bits otherwise the copy into type would take
36936e75b2fbSDimitry Andric   // the wrong 4 bytes on big endian.
36946e75b2fbSDimitry Andric   uint32_t raw_type_32 = raw_type;
36956e75b2fbSDimitry Andric   int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
36966e75b2fbSDimitry Andric 
3697fe6060f1SDimitry Andric   StreamGDBRemote response;
3698fe6060f1SDimitry Andric   std::vector<uint8_t> tags;
3699fe6060f1SDimitry Andric   Status error = m_current_process->ReadMemoryTags(type, addr, length, tags);
3700fe6060f1SDimitry Andric   if (error.Fail())
3701fe6060f1SDimitry Andric     return SendErrorResponse(1);
3702fe6060f1SDimitry Andric 
3703fe6060f1SDimitry Andric   // This m is here in case we want to support multi part replies in the future.
3704fe6060f1SDimitry Andric   // In the same manner as qfThreadInfo/qsThreadInfo.
3705fe6060f1SDimitry Andric   response.PutChar('m');
3706fe6060f1SDimitry Andric   response.PutBytesAsRawHex8(tags.data(), tags.size());
3707fe6060f1SDimitry Andric   return SendPacketNoLock(response.GetString());
3708fe6060f1SDimitry Andric }
3709fe6060f1SDimitry Andric 
3710fe6060f1SDimitry Andric GDBRemoteCommunication::PacketResult
3711fe6060f1SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QMemTags(
3712fe6060f1SDimitry Andric     StringExtractorGDBRemote &packet) {
371381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
3714fe6060f1SDimitry Andric 
3715fe6060f1SDimitry Andric   // Ensure we have a process.
3716fe6060f1SDimitry Andric   if (!m_current_process ||
3717fe6060f1SDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) {
3718fe6060f1SDimitry Andric     LLDB_LOGF(
3719fe6060f1SDimitry Andric         log,
3720fe6060f1SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
3721fe6060f1SDimitry Andric         __FUNCTION__);
3722fe6060f1SDimitry Andric     return SendErrorResponse(1);
3723fe6060f1SDimitry Andric   }
3724fe6060f1SDimitry Andric 
3725fe6060f1SDimitry Andric   // We are expecting
3726fe6060f1SDimitry Andric   // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes>
3727fe6060f1SDimitry Andric 
3728fe6060f1SDimitry Andric   // Address
3729fe6060f1SDimitry Andric   packet.SetFilePos(strlen("QMemTags:"));
3730fe6060f1SDimitry Andric   const char *current_char = packet.Peek();
3731fe6060f1SDimitry Andric   if (!current_char || *current_char == ',')
3732fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, "Missing address in QMemTags packet");
3733fe6060f1SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3734fe6060f1SDimitry Andric 
3735fe6060f1SDimitry Andric   // Length
3736fe6060f1SDimitry Andric   char previous_char = packet.GetChar();
3737fe6060f1SDimitry Andric   current_char = packet.Peek();
3738fe6060f1SDimitry Andric   // If we don't have a separator or the length field is empty
3739fe6060f1SDimitry Andric   if (previous_char != ',' || (current_char && *current_char == ':'))
3740fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3741fe6060f1SDimitry Andric                                  "Invalid addr,length pair in QMemTags packet");
3742fe6060f1SDimitry Andric 
3743fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1)
3744fe6060f1SDimitry Andric     return SendIllFormedResponse(
3745fe6060f1SDimitry Andric         packet, "Too short QMemtags: packet (looking for length)");
3746fe6060f1SDimitry Andric   const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0);
3747fe6060f1SDimitry Andric 
3748fe6060f1SDimitry Andric   // Type
3749fe6060f1SDimitry Andric   const char *invalid_type_err = "Invalid type field in QMemTags: packet";
3750fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3751fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3752fe6060f1SDimitry Andric 
3753fe6060f1SDimitry Andric   // Our GetU64 uses strtoull which allows leading +/-, we don't want that.
3754fe6060f1SDimitry Andric   const char *first_type_char = packet.Peek();
3755fe6060f1SDimitry Andric   if (first_type_char && (*first_type_char == '+' || *first_type_char == '-'))
3756fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
3757fe6060f1SDimitry Andric 
3758fe6060f1SDimitry Andric   // The type is a signed integer but is in the packet as its raw bytes.
3759fe6060f1SDimitry Andric   // So parse first as unsigned then cast to signed later.
3760fe6060f1SDimitry Andric   // We extract to 64 bit, even though we only expect 32, so that we've
3761fe6060f1SDimitry Andric   // got some invalid value we can check for.
3762fe6060f1SDimitry Andric   uint64_t raw_type =
3763fe6060f1SDimitry Andric       packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16);
3764fe6060f1SDimitry Andric   if (raw_type > std::numeric_limits<uint32_t>::max())
3765fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_type_err);
37666e75b2fbSDimitry Andric 
37676e75b2fbSDimitry Andric   // First narrow to 32 bits. Otherwise the copy below would get the wrong
37686e75b2fbSDimitry Andric   // 4 bytes on big endian.
37696e75b2fbSDimitry Andric   uint32_t raw_type_32 = raw_type;
37706e75b2fbSDimitry Andric   int32_t type = reinterpret_cast<int32_t &>(raw_type_32);
3771fe6060f1SDimitry Andric 
3772fe6060f1SDimitry Andric   // Tag data
3773fe6060f1SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':')
3774fe6060f1SDimitry Andric     return SendIllFormedResponse(packet,
3775fe6060f1SDimitry Andric                                  "Missing tag data in QMemTags: packet");
3776fe6060f1SDimitry Andric 
3777fe6060f1SDimitry Andric   // Must be 2 chars per byte
3778fe6060f1SDimitry Andric   const char *invalid_data_err = "Invalid tag data in QMemTags: packet";
3779fe6060f1SDimitry Andric   if (packet.GetBytesLeft() % 2)
3780fe6060f1SDimitry Andric     return SendIllFormedResponse(packet, invalid_data_err);
3781fe6060f1SDimitry Andric 
3782fe6060f1SDimitry Andric   // This is bytes here and is unpacked into target specific tags later
3783fe6060f1SDimitry Andric   // We cannot assume that number of bytes == length here because the server
3784fe6060f1SDimitry Andric   // can repeat tags to fill a given range.
3785fe6060f1SDimitry Andric   std::vector<uint8_t> tag_data;
3786fe6060f1SDimitry Andric   // Zero length writes will not have any tag data
3787fe6060f1SDimitry Andric   // (but we pass them on because it will still check that tagging is enabled)
3788fe6060f1SDimitry Andric   if (packet.GetBytesLeft()) {
3789fe6060f1SDimitry Andric     size_t byte_count = packet.GetBytesLeft() / 2;
3790fe6060f1SDimitry Andric     tag_data.resize(byte_count);
3791fe6060f1SDimitry Andric     size_t converted_bytes = packet.GetHexBytes(tag_data, 0);
3792fe6060f1SDimitry Andric     if (converted_bytes != byte_count) {
3793fe6060f1SDimitry Andric       return SendIllFormedResponse(packet, invalid_data_err);
3794fe6060f1SDimitry Andric     }
3795fe6060f1SDimitry Andric   }
3796fe6060f1SDimitry Andric 
3797fe6060f1SDimitry Andric   Status status =
3798fe6060f1SDimitry Andric       m_current_process->WriteMemoryTags(type, addr, length, tag_data);
3799fe6060f1SDimitry Andric   return status.Success() ? SendOKResponse() : SendErrorResponse(1);
3800fe6060f1SDimitry Andric }
3801fe6060f1SDimitry Andric 
3802349cc55cSDimitry Andric GDBRemoteCommunication::PacketResult
3803349cc55cSDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qSaveCore(
3804349cc55cSDimitry Andric     StringExtractorGDBRemote &packet) {
3805349cc55cSDimitry Andric   // Fail if we don't have a current process.
3806349cc55cSDimitry Andric   if (!m_current_process ||
3807349cc55cSDimitry Andric       (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
3808349cc55cSDimitry Andric     return SendErrorResponse(Status("Process not running."));
3809349cc55cSDimitry Andric 
3810349cc55cSDimitry Andric   std::string path_hint;
3811349cc55cSDimitry Andric 
3812349cc55cSDimitry Andric   StringRef packet_str{packet.GetStringRef()};
3813349cc55cSDimitry Andric   assert(packet_str.startswith("qSaveCore"));
3814349cc55cSDimitry Andric   if (packet_str.consume_front("qSaveCore;")) {
3815349cc55cSDimitry Andric     for (auto x : llvm::split(packet_str, ';')) {
3816349cc55cSDimitry Andric       if (x.consume_front("path-hint:"))
3817349cc55cSDimitry Andric         StringExtractor(x).GetHexByteString(path_hint);
3818349cc55cSDimitry Andric       else
3819349cc55cSDimitry Andric         return SendErrorResponse(Status("Unsupported qSaveCore option"));
3820349cc55cSDimitry Andric     }
3821349cc55cSDimitry Andric   }
3822349cc55cSDimitry Andric 
3823349cc55cSDimitry Andric   llvm::Expected<std::string> ret = m_current_process->SaveCore(path_hint);
3824349cc55cSDimitry Andric   if (!ret)
3825349cc55cSDimitry Andric     return SendErrorResponse(ret.takeError());
3826349cc55cSDimitry Andric 
3827349cc55cSDimitry Andric   StreamString response;
3828349cc55cSDimitry Andric   response.PutCString("core-path:");
3829349cc55cSDimitry Andric   response.PutStringAsRawHex8(ret.get());
3830349cc55cSDimitry Andric   return SendPacketNoLock(response.GetString());
3831349cc55cSDimitry Andric }
3832349cc55cSDimitry Andric 
383381ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
383481ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QNonStop(
383581ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
383681ad6265SDimitry Andric   StringRef packet_str{packet.GetStringRef()};
383781ad6265SDimitry Andric   assert(packet_str.startswith("QNonStop:"));
383881ad6265SDimitry Andric   packet_str.consume_front("QNonStop:");
383981ad6265SDimitry Andric   if (packet_str == "0") {
384081ad6265SDimitry Andric     m_non_stop = false;
384181ad6265SDimitry Andric     // TODO: stop all threads
384281ad6265SDimitry Andric   } else if (packet_str == "1") {
384381ad6265SDimitry Andric     m_non_stop = true;
384481ad6265SDimitry Andric   } else
384581ad6265SDimitry Andric     return SendErrorResponse(Status("Invalid QNonStop packet"));
384681ad6265SDimitry Andric   return SendOKResponse();
384781ad6265SDimitry Andric }
384881ad6265SDimitry Andric 
384981ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
385081ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vStopped(
385181ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
385281ad6265SDimitry Andric   // Per the protocol, the first message put into the queue is sent
385381ad6265SDimitry Andric   // immediately.  However, it remains the queue until the client ACKs
385481ad6265SDimitry Andric   // it via vStopped -- then we pop it and send the next message.
385581ad6265SDimitry Andric   // The process repeats until the last message in the queue is ACK-ed,
385681ad6265SDimitry Andric   // in which case the vStopped packet sends an OK response.
385781ad6265SDimitry Andric 
385881ad6265SDimitry Andric   if (m_stop_notification_queue.empty())
385981ad6265SDimitry Andric     return SendErrorResponse(Status("No pending notification to ack"));
386081ad6265SDimitry Andric   m_stop_notification_queue.pop_front();
386181ad6265SDimitry Andric   if (!m_stop_notification_queue.empty())
386281ad6265SDimitry Andric     return SendPacketNoLock(m_stop_notification_queue.front());
386381ad6265SDimitry Andric   // If this was the last notification and all the processes exited,
386481ad6265SDimitry Andric   // terminate the server.
386581ad6265SDimitry Andric   if (m_debugged_processes.empty()) {
386681ad6265SDimitry Andric     m_exit_now = true;
386781ad6265SDimitry Andric     m_mainloop.RequestTermination();
386881ad6265SDimitry Andric   }
386981ad6265SDimitry Andric   return SendOKResponse();
387081ad6265SDimitry Andric }
387181ad6265SDimitry Andric 
387281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
387381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCtrlC(
387481ad6265SDimitry Andric     StringExtractorGDBRemote &packet) {
387581ad6265SDimitry Andric   if (!m_non_stop)
387681ad6265SDimitry Andric     return SendErrorResponse(Status("vCtrl is only valid in non-stop mode"));
387781ad6265SDimitry Andric 
387881ad6265SDimitry Andric   PacketResult interrupt_res = Handle_interrupt(packet);
387981ad6265SDimitry Andric   // If interrupting the process failed, pass the result through.
388081ad6265SDimitry Andric   if (interrupt_res != PacketResult::Success)
388181ad6265SDimitry Andric     return interrupt_res;
388281ad6265SDimitry Andric   // Otherwise, vCtrlC should issue an OK response (normal interrupts do not).
388381ad6265SDimitry Andric   return SendOKResponse();
388481ad6265SDimitry Andric }
388581ad6265SDimitry Andric 
388681ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
388781ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_T(StringExtractorGDBRemote &packet) {
388881ad6265SDimitry Andric   packet.SetFilePos(strlen("T"));
388981ad6265SDimitry Andric   auto pid_tid = packet.GetPidTid(m_current_process ? m_current_process->GetID()
389081ad6265SDimitry Andric                                                     : LLDB_INVALID_PROCESS_ID);
389181ad6265SDimitry Andric   if (!pid_tid)
389281ad6265SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
389381ad6265SDimitry Andric         inconvertibleErrorCode(), "Malformed thread-id"));
389481ad6265SDimitry Andric 
389581ad6265SDimitry Andric   lldb::pid_t pid = pid_tid->first;
389681ad6265SDimitry Andric   lldb::tid_t tid = pid_tid->second;
389781ad6265SDimitry Andric 
389881ad6265SDimitry Andric   // Technically, this would also be caught by the PID check but let's be more
389981ad6265SDimitry Andric   // explicit about the error.
390081ad6265SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
390181ad6265SDimitry Andric     return SendErrorResponse(llvm::make_error<StringError>(
390281ad6265SDimitry Andric         inconvertibleErrorCode(), "No current process and no PID provided"));
390381ad6265SDimitry Andric 
390481ad6265SDimitry Andric   // Check the process ID and find respective process instance.
390581ad6265SDimitry Andric   auto new_process_it = m_debugged_processes.find(pid);
390681ad6265SDimitry Andric   if (new_process_it == m_debugged_processes.end())
390781ad6265SDimitry Andric     return SendErrorResponse(1);
390881ad6265SDimitry Andric 
390981ad6265SDimitry Andric   // Check the thread ID
391081ad6265SDimitry Andric   if (!new_process_it->second->GetThreadByID(tid))
391181ad6265SDimitry Andric     return SendErrorResponse(2);
391281ad6265SDimitry Andric 
391381ad6265SDimitry Andric   return SendOKResponse();
391481ad6265SDimitry Andric }
391581ad6265SDimitry Andric 
39160b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
391781ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
39180b57cec5SDimitry Andric 
39190b57cec5SDimitry Andric   // Tell the stdio connection to shut down.
39200b57cec5SDimitry Andric   if (m_stdio_communication.IsConnected()) {
39210b57cec5SDimitry Andric     auto connection = m_stdio_communication.GetConnection();
39220b57cec5SDimitry Andric     if (connection) {
39230b57cec5SDimitry Andric       Status error;
39240b57cec5SDimitry Andric       connection->Disconnect(&error);
39250b57cec5SDimitry Andric 
39260b57cec5SDimitry Andric       if (error.Success()) {
39279dba64beSDimitry Andric         LLDB_LOGF(log,
39289dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s disconnect process "
39290b57cec5SDimitry Andric                   "terminal stdio - SUCCESS",
39300b57cec5SDimitry Andric                   __FUNCTION__);
39310b57cec5SDimitry Andric       } else {
39329dba64beSDimitry Andric         LLDB_LOGF(log,
39339dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s disconnect process "
39340b57cec5SDimitry Andric                   "terminal stdio - FAIL: %s",
39350b57cec5SDimitry Andric                   __FUNCTION__, error.AsCString());
39360b57cec5SDimitry Andric       }
39370b57cec5SDimitry Andric     }
39380b57cec5SDimitry Andric   }
39390b57cec5SDimitry Andric }
39400b57cec5SDimitry Andric 
39410b57cec5SDimitry Andric NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
39420b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
39430b57cec5SDimitry Andric   // We have no thread if we don't have a process.
3944fe6060f1SDimitry Andric   if (!m_current_process ||
3945fe6060f1SDimitry Andric       m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)
39460b57cec5SDimitry Andric     return nullptr;
39470b57cec5SDimitry Andric 
39480b57cec5SDimitry Andric   // If the client hasn't asked for thread suffix support, there will not be a
39490b57cec5SDimitry Andric   // thread suffix. Use the current thread in that case.
39500b57cec5SDimitry Andric   if (!m_thread_suffix_supported) {
39510b57cec5SDimitry Andric     const lldb::tid_t current_tid = GetCurrentThreadID();
39520b57cec5SDimitry Andric     if (current_tid == LLDB_INVALID_THREAD_ID)
39530b57cec5SDimitry Andric       return nullptr;
39540b57cec5SDimitry Andric     else if (current_tid == 0) {
39550b57cec5SDimitry Andric       // Pick a thread.
3956fe6060f1SDimitry Andric       return m_current_process->GetThreadAtIndex(0);
39570b57cec5SDimitry Andric     } else
3958fe6060f1SDimitry Andric       return m_current_process->GetThreadByID(current_tid);
39590b57cec5SDimitry Andric   }
39600b57cec5SDimitry Andric 
396181ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Thread);
39620b57cec5SDimitry Andric 
39630b57cec5SDimitry Andric   // Parse out the ';'.
39640b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') {
39659dba64beSDimitry Andric     LLDB_LOGF(log,
39669dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
39670b57cec5SDimitry Andric               "error: expected ';' prior to start of thread suffix: packet "
39680b57cec5SDimitry Andric               "contents = '%s'",
39699dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
39700b57cec5SDimitry Andric     return nullptr;
39710b57cec5SDimitry Andric   }
39720b57cec5SDimitry Andric 
39730b57cec5SDimitry Andric   if (!packet.GetBytesLeft())
39740b57cec5SDimitry Andric     return nullptr;
39750b57cec5SDimitry Andric 
39760b57cec5SDimitry Andric   // Parse out thread: portion.
39770b57cec5SDimitry Andric   if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) {
39789dba64beSDimitry Andric     LLDB_LOGF(log,
39799dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
39800b57cec5SDimitry Andric               "error: expected 'thread:' but not found, packet contents = "
39810b57cec5SDimitry Andric               "'%s'",
39829dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
39830b57cec5SDimitry Andric     return nullptr;
39840b57cec5SDimitry Andric   }
39850b57cec5SDimitry Andric   packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
39860b57cec5SDimitry Andric   const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
39870b57cec5SDimitry Andric   if (tid != 0)
3988fe6060f1SDimitry Andric     return m_current_process->GetThreadByID(tid);
39890b57cec5SDimitry Andric 
39900b57cec5SDimitry Andric   return nullptr;
39910b57cec5SDimitry Andric }
39920b57cec5SDimitry Andric 
39930b57cec5SDimitry Andric lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
39940b57cec5SDimitry Andric   if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
39950b57cec5SDimitry Andric     // Use whatever the debug process says is the current thread id since the
39960b57cec5SDimitry Andric     // protocol either didn't specify or specified we want any/all threads
39970b57cec5SDimitry Andric     // marked as the current thread.
3998fe6060f1SDimitry Andric     if (!m_current_process)
39990b57cec5SDimitry Andric       return LLDB_INVALID_THREAD_ID;
4000fe6060f1SDimitry Andric     return m_current_process->GetCurrentThreadID();
40010b57cec5SDimitry Andric   }
40020b57cec5SDimitry Andric   // Use the specific current thread id set by the gdb remote protocol.
40030b57cec5SDimitry Andric   return m_current_tid;
40040b57cec5SDimitry Andric }
40050b57cec5SDimitry Andric 
40060b57cec5SDimitry Andric uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() {
40070b57cec5SDimitry Andric   std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
40080b57cec5SDimitry Andric   return m_next_saved_registers_id++;
40090b57cec5SDimitry Andric }
40100b57cec5SDimitry Andric 
40110b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
401281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Process);
40130b57cec5SDimitry Andric 
40140b57cec5SDimitry Andric   LLDB_LOG(log, "clearing {0} xfer buffers", m_xfer_buffer_map.size());
40150b57cec5SDimitry Andric   m_xfer_buffer_map.clear();
40160b57cec5SDimitry Andric }
40170b57cec5SDimitry Andric 
40180b57cec5SDimitry Andric FileSpec
40190b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
40200b57cec5SDimitry Andric                                                  const ArchSpec &arch) {
4021fe6060f1SDimitry Andric   if (m_current_process) {
40220b57cec5SDimitry Andric     FileSpec file_spec;
4023fe6060f1SDimitry Andric     if (m_current_process
40240b57cec5SDimitry Andric             ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
40250b57cec5SDimitry Andric             .Success()) {
40260b57cec5SDimitry Andric       if (FileSystem::Instance().Exists(file_spec))
40270b57cec5SDimitry Andric         return file_spec;
40280b57cec5SDimitry Andric     }
40290b57cec5SDimitry Andric   }
40300b57cec5SDimitry Andric 
40310b57cec5SDimitry Andric   return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch);
40320b57cec5SDimitry Andric }
40339dba64beSDimitry Andric 
40349dba64beSDimitry Andric std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue(
40359dba64beSDimitry Andric     llvm::StringRef value) {
40369dba64beSDimitry Andric   std::string result;
40379dba64beSDimitry Andric   for (const char &c : value) {
40389dba64beSDimitry Andric     switch (c) {
40399dba64beSDimitry Andric     case '\'':
40409dba64beSDimitry Andric       result += "&apos;";
40419dba64beSDimitry Andric       break;
40429dba64beSDimitry Andric     case '"':
40439dba64beSDimitry Andric       result += "&quot;";
40449dba64beSDimitry Andric       break;
40459dba64beSDimitry Andric     case '<':
40469dba64beSDimitry Andric       result += "&lt;";
40479dba64beSDimitry Andric       break;
40489dba64beSDimitry Andric     case '>':
40499dba64beSDimitry Andric       result += "&gt;";
40509dba64beSDimitry Andric       break;
40519dba64beSDimitry Andric     default:
40529dba64beSDimitry Andric       result += c;
40539dba64beSDimitry Andric       break;
40549dba64beSDimitry Andric     }
40559dba64beSDimitry Andric   }
40569dba64beSDimitry Andric   return result;
40579dba64beSDimitry Andric }
4058fe6060f1SDimitry Andric 
4059fe6060f1SDimitry Andric std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
4060fe6060f1SDimitry Andric     const llvm::ArrayRef<llvm::StringRef> client_features) {
4061fe6060f1SDimitry Andric   std::vector<std::string> ret =
4062fe6060f1SDimitry Andric       GDBRemoteCommunicationServerCommon::HandleFeatures(client_features);
4063fe6060f1SDimitry Andric   ret.insert(ret.end(), {
4064fe6060f1SDimitry Andric                             "QThreadSuffixSupported+",
4065fe6060f1SDimitry Andric                             "QListThreadsInStopReply+",
4066fe6060f1SDimitry Andric                             "qXfer:features:read+",
406781ad6265SDimitry Andric                             "QNonStop+",
4068fe6060f1SDimitry Andric                         });
4069fe6060f1SDimitry Andric 
4070fe6060f1SDimitry Andric   // report server-only features
4071fe6060f1SDimitry Andric   using Extension = NativeProcessProtocol::Extension;
4072fe6060f1SDimitry Andric   Extension plugin_features = m_process_factory.GetSupportedExtensions();
4073fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::pass_signals))
4074fe6060f1SDimitry Andric     ret.push_back("QPassSignals+");
4075fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::auxv))
4076fe6060f1SDimitry Andric     ret.push_back("qXfer:auxv:read+");
4077fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::libraries_svr4))
4078fe6060f1SDimitry Andric     ret.push_back("qXfer:libraries-svr4:read+");
407904eeddc0SDimitry Andric   if (bool(plugin_features & Extension::siginfo_read))
408004eeddc0SDimitry Andric     ret.push_back("qXfer:siginfo:read+");
4081fe6060f1SDimitry Andric   if (bool(plugin_features & Extension::memory_tagging))
4082fe6060f1SDimitry Andric     ret.push_back("memory-tagging+");
4083349cc55cSDimitry Andric   if (bool(plugin_features & Extension::savecore))
4084349cc55cSDimitry Andric     ret.push_back("qSaveCore+");
4085fe6060f1SDimitry Andric 
4086fe6060f1SDimitry Andric   // check for client features
4087fe6060f1SDimitry Andric   m_extensions_supported = {};
4088fe6060f1SDimitry Andric   for (llvm::StringRef x : client_features)
4089fe6060f1SDimitry Andric     m_extensions_supported |=
4090fe6060f1SDimitry Andric         llvm::StringSwitch<Extension>(x)
4091fe6060f1SDimitry Andric             .Case("multiprocess+", Extension::multiprocess)
4092fe6060f1SDimitry Andric             .Case("fork-events+", Extension::fork)
4093fe6060f1SDimitry Andric             .Case("vfork-events+", Extension::vfork)
4094fe6060f1SDimitry Andric             .Default({});
4095fe6060f1SDimitry Andric 
4096fe6060f1SDimitry Andric   m_extensions_supported &= plugin_features;
4097fe6060f1SDimitry Andric 
4098fe6060f1SDimitry Andric   // fork & vfork require multiprocess
4099fe6060f1SDimitry Andric   if (!bool(m_extensions_supported & Extension::multiprocess))
4100fe6060f1SDimitry Andric     m_extensions_supported &= ~(Extension::fork | Extension::vfork);
4101fe6060f1SDimitry Andric 
4102fe6060f1SDimitry Andric   // report only if actually supported
4103fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::multiprocess))
4104fe6060f1SDimitry Andric     ret.push_back("multiprocess+");
4105fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::fork))
4106fe6060f1SDimitry Andric     ret.push_back("fork-events+");
4107fe6060f1SDimitry Andric   if (bool(m_extensions_supported & Extension::vfork))
4108fe6060f1SDimitry Andric     ret.push_back("vfork-events+");
4109fe6060f1SDimitry Andric 
4110fe6060f1SDimitry Andric   for (auto &x : m_debugged_processes)
4111fe6060f1SDimitry Andric     SetEnabledExtensions(*x.second);
4112fe6060f1SDimitry Andric   return ret;
4113fe6060f1SDimitry Andric }
4114fe6060f1SDimitry Andric 
4115fe6060f1SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions(
4116fe6060f1SDimitry Andric     NativeProcessProtocol &process) {
4117fe6060f1SDimitry Andric   NativeProcessProtocol::Extension flags = m_extensions_supported;
4118fe6060f1SDimitry Andric   assert(!bool(flags & ~m_process_factory.GetSupportedExtensions()));
4119fe6060f1SDimitry Andric   process.SetEnabledExtensions(flags);
4120fe6060f1SDimitry Andric }
4121349cc55cSDimitry Andric 
412281ad6265SDimitry Andric GDBRemoteCommunication::PacketResult
412381ad6265SDimitry Andric GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() {
412481ad6265SDimitry Andric   // TODO: how to handle forwarding in non-stop mode?
412581ad6265SDimitry Andric   StartSTDIOForwarding();
412681ad6265SDimitry Andric   return m_non_stop ? SendOKResponse() : PacketResult::Success;
412781ad6265SDimitry Andric }
412881ad6265SDimitry Andric 
412981ad6265SDimitry Andric void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse(
413081ad6265SDimitry Andric     Stream &response, lldb::pid_t pid, lldb::tid_t tid) {
413181ad6265SDimitry Andric   if (bool(m_extensions_supported &
413281ad6265SDimitry Andric            NativeProcessProtocol::Extension::multiprocess))
413381ad6265SDimitry Andric     response.Format("p{0:x-}.", pid);
413481ad6265SDimitry Andric   response.Format("{0:x-}", tid);
413581ad6265SDimitry Andric }
413681ad6265SDimitry Andric 
4137349cc55cSDimitry Andric std::string
4138349cc55cSDimitry Andric lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg,
4139349cc55cSDimitry Andric                                                bool reverse_connect) {
4140349cc55cSDimitry Andric   // Try parsing the argument as URL.
4141349cc55cSDimitry Andric   if (llvm::Optional<URI> url = URI::Parse(url_arg)) {
4142349cc55cSDimitry Andric     if (reverse_connect)
4143349cc55cSDimitry Andric       return url_arg.str();
4144349cc55cSDimitry Andric 
4145349cc55cSDimitry Andric     // Translate the scheme from LLGS notation to ConnectionFileDescriptor.
4146349cc55cSDimitry Andric     // If the scheme doesn't match any, pass it through to support using CFD
4147349cc55cSDimitry Andric     // schemes directly.
4148349cc55cSDimitry Andric     std::string new_url = llvm::StringSwitch<std::string>(url->scheme)
4149349cc55cSDimitry Andric                               .Case("tcp", "listen")
4150349cc55cSDimitry Andric                               .Case("unix", "unix-accept")
4151349cc55cSDimitry Andric                               .Case("unix-abstract", "unix-abstract-accept")
4152349cc55cSDimitry Andric                               .Default(url->scheme.str());
4153349cc55cSDimitry Andric     llvm::append_range(new_url, url_arg.substr(url->scheme.size()));
4154349cc55cSDimitry Andric     return new_url;
4155349cc55cSDimitry Andric   }
4156349cc55cSDimitry Andric 
4157349cc55cSDimitry Andric   std::string host_port = url_arg.str();
4158349cc55cSDimitry Andric   // If host_and_port starts with ':', default the host to be "localhost" and
4159349cc55cSDimitry Andric   // expect the remainder to be the port.
4160349cc55cSDimitry Andric   if (url_arg.startswith(":"))
4161349cc55cSDimitry Andric     host_port.insert(0, "localhost");
4162349cc55cSDimitry Andric 
4163349cc55cSDimitry Andric   // Try parsing the (preprocessed) argument as host:port pair.
4164349cc55cSDimitry Andric   if (!llvm::errorToBool(Socket::DecodeHostAndPort(host_port).takeError()))
4165349cc55cSDimitry Andric     return (reverse_connect ? "connect://" : "listen://") + host_port;
4166349cc55cSDimitry Andric 
4167349cc55cSDimitry Andric   // If none of the above applied, interpret the argument as UNIX socket path.
4168349cc55cSDimitry Andric   return (reverse_connect ? "unix-connect://" : "unix-accept://") +
4169349cc55cSDimitry Andric          url_arg.str();
4170349cc55cSDimitry Andric }
4171