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 
90b57cec5SDimitry Andric #include <errno.h>
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Host/Config.h"
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "GDBRemoteCommunicationServerLLGS.h"
149dba64beSDimitry Andric #include "lldb/Utility/GDBRemote.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include <chrono>
170b57cec5SDimitry Andric #include <cstring>
180b57cec5SDimitry Andric #include <thread>
190b57cec5SDimitry Andric 
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"
280b57cec5SDimitry Andric #include "lldb/Host/common/NativeProcessProtocol.h"
290b57cec5SDimitry Andric #include "lldb/Host/common/NativeRegisterContext.h"
300b57cec5SDimitry Andric #include "lldb/Host/common/NativeThreadProtocol.h"
310b57cec5SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h"
320b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
330b57cec5SDimitry Andric #include "lldb/Utility/DataBuffer.h"
340b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
350b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
360b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
370b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
380b57cec5SDimitry Andric #include "lldb/Utility/State.h"
390b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
400b57cec5SDimitry Andric #include "lldb/Utility/UriParser.h"
410b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
429dba64beSDimitry Andric #include "llvm/Support/JSON.h"
430b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric #include "ProcessGDBRemote.h"
460b57cec5SDimitry Andric #include "ProcessGDBRemoteLog.h"
470b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric using namespace lldb;
500b57cec5SDimitry Andric using namespace lldb_private;
510b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote;
520b57cec5SDimitry Andric using namespace llvm;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric // GDBRemote Errors
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric namespace {
570b57cec5SDimitry Andric enum GDBRemoteServerError {
580b57cec5SDimitry Andric   // Set to the first unused error number in literal form below
590b57cec5SDimitry Andric   eErrorFirst = 29,
600b57cec5SDimitry Andric   eErrorNoProcess = eErrorFirst,
610b57cec5SDimitry Andric   eErrorResume,
620b57cec5SDimitry Andric   eErrorExitStatus
630b57cec5SDimitry Andric };
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric // GDBRemoteCommunicationServerLLGS constructor
670b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
680b57cec5SDimitry Andric     MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory)
690b57cec5SDimitry Andric     : GDBRemoteCommunicationServerCommon("gdb-remote.server",
700b57cec5SDimitry Andric                                          "gdb-remote.server.rx_packet"),
710b57cec5SDimitry Andric       m_mainloop(mainloop), m_process_factory(process_factory),
720b57cec5SDimitry Andric       m_stdio_communication("process.stdio") {
730b57cec5SDimitry Andric   RegisterPacketHandlers();
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
770b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C,
780b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_C);
790b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c,
800b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_c);
810b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D,
820b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_D);
830b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H,
840b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_H);
850b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I,
860b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_I);
870b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
880b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_interrupt,
890b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_interrupt);
900b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
910b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_m,
920b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
930b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,
940b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_M);
950b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p,
960b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_p);
970b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P,
980b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_P);
990b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
1000b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_qC);
1010b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1020b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qfThreadInfo,
1030b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo);
1040b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1050b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress,
1060b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress);
1070b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1080b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
1090b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir);
1100b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1110b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo,
1120b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo);
1130b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1140b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported,
1150b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported);
1160b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1170b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
1180b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo);
1190b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1200b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qRegisterInfo,
1210b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo);
1220b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1230b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState,
1240b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState);
1250b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1260b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState,
1270b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState);
1280b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1290b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR,
1300b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR);
1310b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1320b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
1330b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir);
1340b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1350b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qsThreadInfo,
1360b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);
1370b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1380b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,
1390b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo);
1400b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1410b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jThreadsInfo,
1420b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);
1430b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1440b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,
1450b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);
1460b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1470b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qXfer,
1480b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_qXfer);
1490b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s,
1500b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_s);
1510b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1520b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_stop_reason,
1530b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ?
1540b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1550b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vAttach,
1560b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vAttach);
1570b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1580b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vCont,
1590b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vCont);
1600b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1610b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_vCont_actions,
1620b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions);
1630b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1640b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_x,
1650b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
1660b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,
1670b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_Z);
1680b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
1690b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_z);
1700b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1710b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QPassSignals,
1720b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1750b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jTraceStart,
1760b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart);
1770b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1780b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead,
1790b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
1800b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1810b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead,
1820b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
1830b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1840b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jTraceStop,
1850b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop);
1860b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1870b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead,
1880b57cec5SDimitry Andric       &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead);
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
1910b57cec5SDimitry Andric                                 &GDBRemoteCommunicationServerLLGS::Handle_g);
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
1940b57cec5SDimitry Andric                         [this](StringExtractorGDBRemote packet, Status &error,
1950b57cec5SDimitry Andric                                bool &interrupt, bool &quit) {
1960b57cec5SDimitry Andric                           quit = true;
1970b57cec5SDimitry Andric                           return this->Handle_k(packet);
1980b57cec5SDimitry Andric                         });
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) {
2020b57cec5SDimitry Andric   m_process_launch_info = info;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
2060b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   if (!m_process_launch_info.GetArguments().GetArgumentCount())
2090b57cec5SDimitry Andric     return Status("%s: no process command line specified to launch",
2100b57cec5SDimitry Andric                   __FUNCTION__);
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   const bool should_forward_stdio =
2130b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
2140b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
2150b57cec5SDimitry Andric       m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr;
2160b57cec5SDimitry Andric   m_process_launch_info.SetLaunchInSeparateProcessGroup(true);
2170b57cec5SDimitry Andric   m_process_launch_info.GetFlags().Set(eLaunchFlagDebug);
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   if (should_forward_stdio) {
2209dba64beSDimitry Andric     // Temporarily relax the following for Windows until we can take advantage
2219dba64beSDimitry Andric     // of the recently added pty support. This doesn't really affect the use of
2229dba64beSDimitry Andric     // lldb-server on Windows.
2239dba64beSDimitry Andric #if !defined(_WIN32)
2240b57cec5SDimitry Andric     if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection())
2250b57cec5SDimitry Andric       return Status(std::move(Err));
2269dba64beSDimitry Andric #endif
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   {
2300b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
2310b57cec5SDimitry Andric     assert(!m_debugged_process_up && "lldb-server creating debugged "
2320b57cec5SDimitry Andric                                      "process but one already exists");
2330b57cec5SDimitry Andric     auto process_or =
2340b57cec5SDimitry Andric         m_process_factory.Launch(m_process_launch_info, *this, m_mainloop);
2350b57cec5SDimitry Andric     if (!process_or)
2360b57cec5SDimitry Andric       return Status(process_or.takeError());
2370b57cec5SDimitry Andric     m_debugged_process_up = std::move(*process_or);
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
2410b57cec5SDimitry Andric   // needed. llgs local-process debugging may specify PTY paths, which will
2420b57cec5SDimitry Andric   // make these file actions non-null process launch -i/e/o will also make
2430b57cec5SDimitry Andric   // these file actions non-null nullptr means that the traffic is expected to
2440b57cec5SDimitry Andric   // flow over gdb-remote protocol
2450b57cec5SDimitry Andric   if (should_forward_stdio) {
2460b57cec5SDimitry Andric     // nullptr means it's not redirected to file or pty (in case of LLGS local)
2470b57cec5SDimitry Andric     // at least one of stdio will be transferred pty<->gdb-remote we need to
2480b57cec5SDimitry Andric     // give the pty master handle to this object to read and/or write
2490b57cec5SDimitry Andric     LLDB_LOG(log,
2500b57cec5SDimitry Andric              "pid = {0}: setting up stdout/stderr redirection via $O "
2510b57cec5SDimitry Andric              "gdb-remote commands",
2520b57cec5SDimitry Andric              m_debugged_process_up->GetID());
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric     // Setup stdout/stderr mapping from inferior to $O
2550b57cec5SDimitry Andric     auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
2560b57cec5SDimitry Andric     if (terminal_fd >= 0) {
2579dba64beSDimitry Andric       LLDB_LOGF(log,
2589dba64beSDimitry Andric                 "ProcessGDBRemoteCommunicationServerLLGS::%s setting "
2590b57cec5SDimitry Andric                 "inferior STDIO fd to %d",
2600b57cec5SDimitry Andric                 __FUNCTION__, terminal_fd);
2610b57cec5SDimitry Andric       Status status = SetSTDIOFileDescriptor(terminal_fd);
2620b57cec5SDimitry Andric       if (status.Fail())
2630b57cec5SDimitry Andric         return status;
2640b57cec5SDimitry Andric     } else {
2659dba64beSDimitry Andric       LLDB_LOGF(log,
2669dba64beSDimitry Andric                 "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
2670b57cec5SDimitry Andric                 "inferior STDIO since terminal fd reported as %d",
2680b57cec5SDimitry Andric                 __FUNCTION__, terminal_fd);
2690b57cec5SDimitry Andric     }
2700b57cec5SDimitry Andric   } else {
2710b57cec5SDimitry Andric     LLDB_LOG(log,
2720b57cec5SDimitry Andric              "pid = {0} skipping stdout/stderr redirection via $O: inferior "
2730b57cec5SDimitry Andric              "will communicate over client-provided file descriptors",
2740b57cec5SDimitry Andric              m_debugged_process_up->GetID());
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   printf("Launched '%s' as process %" PRIu64 "...\n",
2780b57cec5SDimitry Andric          m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
2790b57cec5SDimitry Andric          m_debugged_process_up->GetID());
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   return Status();
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
2850b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
2869dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64,
2870b57cec5SDimitry Andric             __FUNCTION__, pid);
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   // Before we try to attach, make sure we aren't already monitoring something
2900b57cec5SDimitry Andric   // else.
2910b57cec5SDimitry Andric   if (m_debugged_process_up &&
2920b57cec5SDimitry Andric       m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID)
2930b57cec5SDimitry Andric     return Status("cannot attach to process %" PRIu64
2940b57cec5SDimitry Andric                   " when another process with pid %" PRIu64
2950b57cec5SDimitry Andric                   " is being debugged.",
2960b57cec5SDimitry Andric                   pid, m_debugged_process_up->GetID());
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   // Try to attach.
2990b57cec5SDimitry Andric   auto process_or = m_process_factory.Attach(pid, *this, m_mainloop);
3000b57cec5SDimitry Andric   if (!process_or) {
3010b57cec5SDimitry Andric     Status status(process_or.takeError());
3020b57cec5SDimitry Andric     llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}", pid,
3030b57cec5SDimitry Andric                                   status);
3040b57cec5SDimitry Andric     return status;
3050b57cec5SDimitry Andric   }
3060b57cec5SDimitry Andric   m_debugged_process_up = std::move(*process_or);
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   // Setup stdout/stderr mapping from inferior.
3090b57cec5SDimitry Andric   auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor();
3100b57cec5SDimitry Andric   if (terminal_fd >= 0) {
3119dba64beSDimitry Andric     LLDB_LOGF(log,
3129dba64beSDimitry Andric               "ProcessGDBRemoteCommunicationServerLLGS::%s setting "
3130b57cec5SDimitry Andric               "inferior STDIO fd to %d",
3140b57cec5SDimitry Andric               __FUNCTION__, terminal_fd);
3150b57cec5SDimitry Andric     Status status = SetSTDIOFileDescriptor(terminal_fd);
3160b57cec5SDimitry Andric     if (status.Fail())
3170b57cec5SDimitry Andric       return status;
3180b57cec5SDimitry Andric   } else {
3199dba64beSDimitry Andric     LLDB_LOGF(log,
3209dba64beSDimitry Andric               "ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
3210b57cec5SDimitry Andric               "inferior STDIO since terminal fd reported as %d",
3220b57cec5SDimitry Andric               __FUNCTION__, terminal_fd);
3230b57cec5SDimitry Andric   }
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   printf("Attached to process %" PRIu64 "...\n", pid);
3260b57cec5SDimitry Andric   return Status();
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::InitializeDelegate(
3300b57cec5SDimitry Andric     NativeProcessProtocol *process) {
3310b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
3320b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
3330b57cec5SDimitry Andric   if (log) {
3349dba64beSDimitry Andric     LLDB_LOGF(log,
3359dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s called with "
3360b57cec5SDimitry Andric               "NativeProcessProtocol pid %" PRIu64 ", current state: %s",
3370b57cec5SDimitry Andric               __FUNCTION__, process->GetID(),
3380b57cec5SDimitry Andric               StateAsCString(process->GetState()));
3390b57cec5SDimitry Andric   }
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3430b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendWResponse(
3440b57cec5SDimitry Andric     NativeProcessProtocol *process) {
3450b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
3460b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   // send W notification
3490b57cec5SDimitry Andric   auto wait_status = process->GetExitStatus();
3500b57cec5SDimitry Andric   if (!wait_status) {
3510b57cec5SDimitry Andric     LLDB_LOG(log, "pid = {0}, failed to retrieve process exit status",
3520b57cec5SDimitry Andric              process->GetID());
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric     StreamGDBRemote response;
3550b57cec5SDimitry Andric     response.PutChar('E');
3560b57cec5SDimitry Andric     response.PutHex8(GDBRemoteServerError::eErrorExitStatus);
3570b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
3580b57cec5SDimitry Andric   }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(),
3610b57cec5SDimitry Andric            *wait_status);
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   StreamGDBRemote response;
3640b57cec5SDimitry Andric   response.Format("{0:g}", *wait_status);
3650b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric static void AppendHexValue(StreamString &response, const uint8_t *buf,
3690b57cec5SDimitry Andric                            uint32_t buf_size, bool swap) {
3700b57cec5SDimitry Andric   int64_t i;
3710b57cec5SDimitry Andric   if (swap) {
3720b57cec5SDimitry Andric     for (i = buf_size - 1; i >= 0; i--)
3730b57cec5SDimitry Andric       response.PutHex8(buf[i]);
3740b57cec5SDimitry Andric   } else {
3750b57cec5SDimitry Andric     for (i = 0; i < buf_size; i++)
3760b57cec5SDimitry Andric       response.PutHex8(buf[i]);
3770b57cec5SDimitry Andric   }
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
3805ffd83dbSDimitry Andric static llvm::StringRef GetEncodingNameOrEmpty(const RegisterInfo &reg_info) {
3815ffd83dbSDimitry Andric   switch (reg_info.encoding) {
3825ffd83dbSDimitry Andric   case eEncodingUint:
3835ffd83dbSDimitry Andric     return "uint";
3845ffd83dbSDimitry Andric   case eEncodingSint:
3855ffd83dbSDimitry Andric     return "sint";
3865ffd83dbSDimitry Andric   case eEncodingIEEE754:
3875ffd83dbSDimitry Andric     return "ieee754";
3885ffd83dbSDimitry Andric   case eEncodingVector:
3895ffd83dbSDimitry Andric     return "vector";
3905ffd83dbSDimitry Andric   default:
3915ffd83dbSDimitry Andric     return "";
3925ffd83dbSDimitry Andric   }
3935ffd83dbSDimitry Andric }
3945ffd83dbSDimitry Andric 
3955ffd83dbSDimitry Andric static llvm::StringRef GetFormatNameOrEmpty(const RegisterInfo &reg_info) {
3965ffd83dbSDimitry Andric   switch (reg_info.format) {
3975ffd83dbSDimitry Andric   case eFormatBinary:
3985ffd83dbSDimitry Andric     return "binary";
3995ffd83dbSDimitry Andric   case eFormatDecimal:
4005ffd83dbSDimitry Andric     return "decimal";
4015ffd83dbSDimitry Andric   case eFormatHex:
4025ffd83dbSDimitry Andric     return "hex";
4035ffd83dbSDimitry Andric   case eFormatFloat:
4045ffd83dbSDimitry Andric     return "float";
4055ffd83dbSDimitry Andric   case eFormatVectorOfSInt8:
4065ffd83dbSDimitry Andric     return "vector-sint8";
4075ffd83dbSDimitry Andric   case eFormatVectorOfUInt8:
4085ffd83dbSDimitry Andric     return "vector-uint8";
4095ffd83dbSDimitry Andric   case eFormatVectorOfSInt16:
4105ffd83dbSDimitry Andric     return "vector-sint16";
4115ffd83dbSDimitry Andric   case eFormatVectorOfUInt16:
4125ffd83dbSDimitry Andric     return "vector-uint16";
4135ffd83dbSDimitry Andric   case eFormatVectorOfSInt32:
4145ffd83dbSDimitry Andric     return "vector-sint32";
4155ffd83dbSDimitry Andric   case eFormatVectorOfUInt32:
4165ffd83dbSDimitry Andric     return "vector-uint32";
4175ffd83dbSDimitry Andric   case eFormatVectorOfFloat32:
4185ffd83dbSDimitry Andric     return "vector-float32";
4195ffd83dbSDimitry Andric   case eFormatVectorOfUInt64:
4205ffd83dbSDimitry Andric     return "vector-uint64";
4215ffd83dbSDimitry Andric   case eFormatVectorOfUInt128:
4225ffd83dbSDimitry Andric     return "vector-uint128";
4235ffd83dbSDimitry Andric   default:
4245ffd83dbSDimitry Andric     return "";
4255ffd83dbSDimitry Andric   };
4265ffd83dbSDimitry Andric }
4275ffd83dbSDimitry Andric 
4285ffd83dbSDimitry Andric static llvm::StringRef GetKindGenericOrEmpty(const RegisterInfo &reg_info) {
4295ffd83dbSDimitry Andric   switch (reg_info.kinds[RegisterKind::eRegisterKindGeneric]) {
4305ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_PC:
4315ffd83dbSDimitry Andric     return "pc";
4325ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_SP:
4335ffd83dbSDimitry Andric     return "sp";
4345ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_FP:
4355ffd83dbSDimitry Andric     return "fp";
4365ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_RA:
4375ffd83dbSDimitry Andric     return "ra";
4385ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_FLAGS:
4395ffd83dbSDimitry Andric     return "flags";
4405ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG1:
4415ffd83dbSDimitry Andric     return "arg1";
4425ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG2:
4435ffd83dbSDimitry Andric     return "arg2";
4445ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG3:
4455ffd83dbSDimitry Andric     return "arg3";
4465ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG4:
4475ffd83dbSDimitry Andric     return "arg4";
4485ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG5:
4495ffd83dbSDimitry Andric     return "arg5";
4505ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG6:
4515ffd83dbSDimitry Andric     return "arg6";
4525ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG7:
4535ffd83dbSDimitry Andric     return "arg7";
4545ffd83dbSDimitry Andric   case LLDB_REGNUM_GENERIC_ARG8:
4555ffd83dbSDimitry Andric     return "arg8";
4565ffd83dbSDimitry Andric   default:
4575ffd83dbSDimitry Andric     return "";
4585ffd83dbSDimitry Andric   }
4595ffd83dbSDimitry Andric }
4605ffd83dbSDimitry Andric 
4615ffd83dbSDimitry Andric static void CollectRegNums(const uint32_t *reg_num, StreamString &response,
4625ffd83dbSDimitry Andric                            bool usehex) {
4635ffd83dbSDimitry Andric   for (int i = 0; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) {
4645ffd83dbSDimitry Andric     if (i > 0)
4655ffd83dbSDimitry Andric       response.PutChar(',');
4665ffd83dbSDimitry Andric     if (usehex)
4675ffd83dbSDimitry Andric       response.Printf("%" PRIx32, *reg_num);
4685ffd83dbSDimitry Andric     else
4695ffd83dbSDimitry Andric       response.Printf("%" PRIu32, *reg_num);
4705ffd83dbSDimitry Andric   }
4715ffd83dbSDimitry Andric }
4725ffd83dbSDimitry Andric 
4730b57cec5SDimitry Andric static void WriteRegisterValueInHexFixedWidth(
4740b57cec5SDimitry Andric     StreamString &response, NativeRegisterContext &reg_ctx,
4750b57cec5SDimitry Andric     const RegisterInfo &reg_info, const RegisterValue *reg_value_p,
4760b57cec5SDimitry Andric     lldb::ByteOrder byte_order) {
4770b57cec5SDimitry Andric   RegisterValue reg_value;
4780b57cec5SDimitry Andric   if (!reg_value_p) {
4790b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(&reg_info, reg_value);
4800b57cec5SDimitry Andric     if (error.Success())
4810b57cec5SDimitry Andric       reg_value_p = &reg_value;
4820b57cec5SDimitry Andric     // else log.
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   if (reg_value_p) {
4860b57cec5SDimitry Andric     AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(),
4870b57cec5SDimitry Andric                    reg_value_p->GetByteSize(),
4880b57cec5SDimitry Andric                    byte_order == lldb::eByteOrderLittle);
4890b57cec5SDimitry Andric   } else {
4900b57cec5SDimitry Andric     // Zero-out any unreadable values.
4910b57cec5SDimitry Andric     if (reg_info.byte_size > 0) {
4920b57cec5SDimitry Andric       std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0');
4930b57cec5SDimitry Andric       AppendHexValue(response, zeros.data(), zeros.size(), false);
4940b57cec5SDimitry Andric     }
4950b57cec5SDimitry Andric   }
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric 
4989dba64beSDimitry Andric static llvm::Expected<json::Object>
4999dba64beSDimitry Andric GetRegistersAsJSON(NativeThreadProtocol &thread) {
5000b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   NativeRegisterContext& reg_ctx = thread.GetRegisterContext();
5030b57cec5SDimitry Andric 
5049dba64beSDimitry Andric   json::Object register_object;
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
5070b57cec5SDimitry Andric   // Expedite all registers in the first register set (i.e. should be GPRs)
5080b57cec5SDimitry Andric   // that are not contained in other registers.
5090b57cec5SDimitry Andric   const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
5100b57cec5SDimitry Andric   if (!reg_set_p)
5119dba64beSDimitry Andric     return llvm::make_error<llvm::StringError>("failed to get registers",
5129dba64beSDimitry Andric                                                llvm::inconvertibleErrorCode());
5130b57cec5SDimitry Andric   for (const uint32_t *reg_num_p = reg_set_p->registers;
5140b57cec5SDimitry Andric        *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) {
5150b57cec5SDimitry Andric     uint32_t reg_num = *reg_num_p;
5160b57cec5SDimitry Andric #else
5170b57cec5SDimitry Andric   // Expedite only a couple of registers until we figure out why sending
5180b57cec5SDimitry Andric   // registers is expensive.
5190b57cec5SDimitry Andric   static const uint32_t k_expedited_registers[] = {
5200b57cec5SDimitry Andric       LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP,
5210b57cec5SDimitry Andric       LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM};
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   for (const uint32_t *generic_reg_p = k_expedited_registers;
5240b57cec5SDimitry Andric        *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) {
5250b57cec5SDimitry Andric     uint32_t reg_num = reg_ctx.ConvertRegisterKindToRegisterNumber(
5260b57cec5SDimitry Andric         eRegisterKindGeneric, *generic_reg_p);
5270b57cec5SDimitry Andric     if (reg_num == LLDB_INVALID_REGNUM)
5280b57cec5SDimitry Andric       continue; // Target does not support the given register.
5290b57cec5SDimitry Andric #endif
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric     const RegisterInfo *const reg_info_p =
5320b57cec5SDimitry Andric         reg_ctx.GetRegisterInfoAtIndex(reg_num);
5330b57cec5SDimitry Andric     if (reg_info_p == nullptr) {
5349dba64beSDimitry Andric       LLDB_LOGF(log,
5350b57cec5SDimitry Andric                 "%s failed to get register info for register index %" PRIu32,
5360b57cec5SDimitry Andric                 __FUNCTION__, reg_num);
5370b57cec5SDimitry Andric       continue;
5380b57cec5SDimitry Andric     }
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric     if (reg_info_p->value_regs != nullptr)
5410b57cec5SDimitry Andric       continue; // Only expedite registers that are not contained in other
5420b57cec5SDimitry Andric                 // registers.
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric     RegisterValue reg_value;
5450b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
5460b57cec5SDimitry Andric     if (error.Fail()) {
5479dba64beSDimitry Andric       LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s",
5480b57cec5SDimitry Andric                 __FUNCTION__,
5490b57cec5SDimitry Andric                 reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
5500b57cec5SDimitry Andric                 reg_num, error.AsCString());
5510b57cec5SDimitry Andric       continue;
5520b57cec5SDimitry Andric     }
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric     StreamString stream;
5550b57cec5SDimitry Andric     WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p,
5560b57cec5SDimitry Andric                                       &reg_value, lldb::eByteOrderBig);
5570b57cec5SDimitry Andric 
5589dba64beSDimitry Andric     register_object.try_emplace(llvm::to_string(reg_num),
5599dba64beSDimitry Andric                                 stream.GetString().str());
5600b57cec5SDimitry Andric   }
5610b57cec5SDimitry Andric 
5629dba64beSDimitry Andric   return register_object;
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric static const char *GetStopReasonString(StopReason stop_reason) {
5660b57cec5SDimitry Andric   switch (stop_reason) {
5670b57cec5SDimitry Andric   case eStopReasonTrace:
5680b57cec5SDimitry Andric     return "trace";
5690b57cec5SDimitry Andric   case eStopReasonBreakpoint:
5700b57cec5SDimitry Andric     return "breakpoint";
5710b57cec5SDimitry Andric   case eStopReasonWatchpoint:
5720b57cec5SDimitry Andric     return "watchpoint";
5730b57cec5SDimitry Andric   case eStopReasonSignal:
5740b57cec5SDimitry Andric     return "signal";
5750b57cec5SDimitry Andric   case eStopReasonException:
5760b57cec5SDimitry Andric     return "exception";
5770b57cec5SDimitry Andric   case eStopReasonExec:
5780b57cec5SDimitry Andric     return "exec";
5790b57cec5SDimitry Andric   case eStopReasonInstrumentation:
5800b57cec5SDimitry Andric   case eStopReasonInvalid:
5810b57cec5SDimitry Andric   case eStopReasonPlanComplete:
5820b57cec5SDimitry Andric   case eStopReasonThreadExiting:
5830b57cec5SDimitry Andric   case eStopReasonNone:
5840b57cec5SDimitry Andric     break; // ignored
5850b57cec5SDimitry Andric   }
5860b57cec5SDimitry Andric   return nullptr;
5870b57cec5SDimitry Andric }
5880b57cec5SDimitry Andric 
5899dba64beSDimitry Andric static llvm::Expected<json::Array>
5909dba64beSDimitry Andric GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) {
5910b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
5920b57cec5SDimitry Andric 
5939dba64beSDimitry Andric   json::Array threads_array;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   // Ensure we can get info on the given thread.
5960b57cec5SDimitry Andric   uint32_t thread_idx = 0;
5970b57cec5SDimitry Andric   for (NativeThreadProtocol *thread;
5980b57cec5SDimitry Andric        (thread = process.GetThreadAtIndex(thread_idx)) != nullptr;
5990b57cec5SDimitry Andric        ++thread_idx) {
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric     lldb::tid_t tid = thread->GetID();
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric     // Grab the reason this thread stopped.
6040b57cec5SDimitry Andric     struct ThreadStopInfo tid_stop_info;
6050b57cec5SDimitry Andric     std::string description;
6060b57cec5SDimitry Andric     if (!thread->GetStopReason(tid_stop_info, description))
6079dba64beSDimitry Andric       return llvm::make_error<llvm::StringError>(
6089dba64beSDimitry Andric           "failed to get stop reason", llvm::inconvertibleErrorCode());
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric     const int signum = tid_stop_info.details.signal.signo;
6110b57cec5SDimitry Andric     if (log) {
6129dba64beSDimitry Andric       LLDB_LOGF(log,
6139dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
6140b57cec5SDimitry Andric                 " tid %" PRIu64
6150b57cec5SDimitry Andric                 " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
6160b57cec5SDimitry Andric                 __FUNCTION__, process.GetID(), tid, signum,
6170b57cec5SDimitry Andric                 tid_stop_info.reason, tid_stop_info.details.exception.type);
6180b57cec5SDimitry Andric     }
6190b57cec5SDimitry Andric 
6209dba64beSDimitry Andric     json::Object thread_obj;
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric     if (!abridged) {
6239dba64beSDimitry Andric       if (llvm::Expected<json::Object> registers =
6249dba64beSDimitry Andric               GetRegistersAsJSON(*thread)) {
6259dba64beSDimitry Andric         thread_obj.try_emplace("registers", std::move(*registers));
6269dba64beSDimitry Andric       } else {
6279dba64beSDimitry Andric         return registers.takeError();
6289dba64beSDimitry Andric       }
6290b57cec5SDimitry Andric     }
6300b57cec5SDimitry Andric 
6319dba64beSDimitry Andric     thread_obj.try_emplace("tid", static_cast<int64_t>(tid));
6329dba64beSDimitry Andric 
6330b57cec5SDimitry Andric     if (signum != 0)
6349dba64beSDimitry Andric       thread_obj.try_emplace("signal", signum);
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric     const std::string thread_name = thread->GetName();
6370b57cec5SDimitry Andric     if (!thread_name.empty())
6389dba64beSDimitry Andric       thread_obj.try_emplace("name", thread_name);
6390b57cec5SDimitry Andric 
6409dba64beSDimitry Andric     const char *stop_reason = GetStopReasonString(tid_stop_info.reason);
6419dba64beSDimitry Andric     if (stop_reason)
6429dba64beSDimitry Andric       thread_obj.try_emplace("reason", stop_reason);
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric     if (!description.empty())
6459dba64beSDimitry Andric       thread_obj.try_emplace("description", description);
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric     if ((tid_stop_info.reason == eStopReasonException) &&
6480b57cec5SDimitry Andric         tid_stop_info.details.exception.type) {
6499dba64beSDimitry Andric       thread_obj.try_emplace(
6509dba64beSDimitry Andric           "metype", static_cast<int64_t>(tid_stop_info.details.exception.type));
6510b57cec5SDimitry Andric 
6529dba64beSDimitry Andric       json::Array medata_array;
6530b57cec5SDimitry Andric       for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count;
6540b57cec5SDimitry Andric            ++i) {
6559dba64beSDimitry Andric         medata_array.push_back(
6569dba64beSDimitry Andric             static_cast<int64_t>(tid_stop_info.details.exception.data[i]));
6570b57cec5SDimitry Andric       }
6589dba64beSDimitry Andric       thread_obj.try_emplace("medata", std::move(medata_array));
6590b57cec5SDimitry Andric     }
6609dba64beSDimitry Andric     threads_array.push_back(std::move(thread_obj));
6610b57cec5SDimitry Andric   }
6629dba64beSDimitry Andric   return threads_array;
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
6660b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
6670b57cec5SDimitry Andric     lldb::tid_t tid) {
6680b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   // Ensure we have a debugged process.
6710b57cec5SDimitry Andric   if (!m_debugged_process_up ||
6720b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
6730b57cec5SDimitry Andric     return SendErrorResponse(50);
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   LLDB_LOG(log, "preparing packet for pid {0} tid {1}",
6760b57cec5SDimitry Andric            m_debugged_process_up->GetID(), tid);
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   // Ensure we can get info on the given thread.
6790b57cec5SDimitry Andric   NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
6800b57cec5SDimitry Andric   if (!thread)
6810b57cec5SDimitry Andric     return SendErrorResponse(51);
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric   // Grab the reason this thread stopped.
6840b57cec5SDimitry Andric   struct ThreadStopInfo tid_stop_info;
6850b57cec5SDimitry Andric   std::string description;
6860b57cec5SDimitry Andric   if (!thread->GetStopReason(tid_stop_info, description))
6870b57cec5SDimitry Andric     return SendErrorResponse(52);
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric   // FIXME implement register handling for exec'd inferiors.
6900b57cec5SDimitry Andric   // if (tid_stop_info.reason == eStopReasonExec) {
6910b57cec5SDimitry Andric   //     const bool force = true;
6920b57cec5SDimitry Andric   //     InitializeRegisters(force);
6930b57cec5SDimitry Andric   // }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric   StreamString response;
6960b57cec5SDimitry Andric   // Output the T packet with the thread
6970b57cec5SDimitry Andric   response.PutChar('T');
6980b57cec5SDimitry Andric   int signum = tid_stop_info.details.signal.signo;
6990b57cec5SDimitry Andric   LLDB_LOG(
7000b57cec5SDimitry Andric       log,
7010b57cec5SDimitry Andric       "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}",
7020b57cec5SDimitry Andric       m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info.reason),
7030b57cec5SDimitry Andric       tid_stop_info.details.exception.type);
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   // Print the signal number.
7060b57cec5SDimitry Andric   response.PutHex8(signum & 0xff);
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   // Include the tid.
7090b57cec5SDimitry Andric   response.Printf("thread:%" PRIx64 ";", tid);
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric   // Include the thread name if there is one.
7120b57cec5SDimitry Andric   const std::string thread_name = thread->GetName();
7130b57cec5SDimitry Andric   if (!thread_name.empty()) {
7140b57cec5SDimitry Andric     size_t thread_name_len = thread_name.length();
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric     if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) {
7170b57cec5SDimitry Andric       response.PutCString("name:");
7180b57cec5SDimitry Andric       response.PutCString(thread_name);
7190b57cec5SDimitry Andric     } else {
7200b57cec5SDimitry Andric       // The thread name contains special chars, send as hex bytes.
7210b57cec5SDimitry Andric       response.PutCString("hexname:");
7220b57cec5SDimitry Andric       response.PutStringAsRawHex8(thread_name);
7230b57cec5SDimitry Andric     }
7240b57cec5SDimitry Andric     response.PutChar(';');
7250b57cec5SDimitry Andric   }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   // If a 'QListThreadsInStopReply' was sent to enable this feature, we will
7280b57cec5SDimitry Andric   // send all thread IDs back in the "threads" key whose value is a list of hex
7290b57cec5SDimitry Andric   // thread IDs separated by commas:
7300b57cec5SDimitry Andric   //  "threads:10a,10b,10c;"
7310b57cec5SDimitry Andric   // This will save the debugger from having to send a pair of qfThreadInfo and
7320b57cec5SDimitry Andric   // qsThreadInfo packets, but it also might take a lot of room in the stop
7330b57cec5SDimitry Andric   // reply packet, so it must be enabled only on systems where there are no
7340b57cec5SDimitry Andric   // limits on packet lengths.
7350b57cec5SDimitry Andric   if (m_list_threads_in_stop_reply) {
7360b57cec5SDimitry Andric     response.PutCString("threads:");
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric     uint32_t thread_index = 0;
7390b57cec5SDimitry Andric     NativeThreadProtocol *listed_thread;
7400b57cec5SDimitry Andric     for (listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index);
7410b57cec5SDimitry Andric          listed_thread; ++thread_index,
7420b57cec5SDimitry Andric         listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) {
7430b57cec5SDimitry Andric       if (thread_index > 0)
7440b57cec5SDimitry Andric         response.PutChar(',');
7450b57cec5SDimitry Andric       response.Printf("%" PRIx64, listed_thread->GetID());
7460b57cec5SDimitry Andric     }
7470b57cec5SDimitry Andric     response.PutChar(';');
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric     // Include JSON info that describes the stop reason for any threads that
7500b57cec5SDimitry Andric     // actually have stop reasons. We use the new "jstopinfo" key whose values
7510b57cec5SDimitry Andric     // is hex ascii JSON that contains the thread IDs thread stop info only for
7520b57cec5SDimitry Andric     // threads that have stop reasons. Only send this if we have more than one
7530b57cec5SDimitry Andric     // thread otherwise this packet has all the info it needs.
7549dba64beSDimitry Andric     if (thread_index > 1) {
7550b57cec5SDimitry Andric       const bool threads_with_valid_stop_info_only = true;
7569dba64beSDimitry Andric       llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo(
7570b57cec5SDimitry Andric           *m_debugged_process_up, threads_with_valid_stop_info_only);
7589dba64beSDimitry Andric       if (threads_info) {
7590b57cec5SDimitry Andric         response.PutCString("jstopinfo:");
7600b57cec5SDimitry Andric         StreamString unescaped_response;
7619dba64beSDimitry Andric         unescaped_response.AsRawOstream() << std::move(*threads_info);
7620b57cec5SDimitry Andric         response.PutStringAsRawHex8(unescaped_response.GetData());
7630b57cec5SDimitry Andric         response.PutChar(';');
7649dba64beSDimitry Andric       } else {
765480093f4SDimitry Andric         LLDB_LOG_ERROR(log, threads_info.takeError(),
766480093f4SDimitry Andric                        "failed to prepare a jstopinfo field for pid {1}: {0}",
767480093f4SDimitry Andric                        m_debugged_process_up->GetID());
7689dba64beSDimitry Andric       }
7690b57cec5SDimitry Andric     }
7700b57cec5SDimitry Andric 
7710b57cec5SDimitry Andric     uint32_t i = 0;
7720b57cec5SDimitry Andric     response.PutCString("thread-pcs");
7730b57cec5SDimitry Andric     char delimiter = ':';
7740b57cec5SDimitry Andric     for (NativeThreadProtocol *thread;
7750b57cec5SDimitry Andric          (thread = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr;
7760b57cec5SDimitry Andric          ++i) {
7770b57cec5SDimitry Andric       NativeRegisterContext& reg_ctx = thread->GetRegisterContext();
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric       uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber(
7800b57cec5SDimitry Andric           eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7810b57cec5SDimitry Andric       const RegisterInfo *const reg_info_p =
7820b57cec5SDimitry Andric           reg_ctx.GetRegisterInfoAtIndex(reg_to_read);
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric       RegisterValue reg_value;
7850b57cec5SDimitry Andric       Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
7860b57cec5SDimitry Andric       if (error.Fail()) {
7879dba64beSDimitry Andric         LLDB_LOGF(log, "%s failed to read register '%s' index %" PRIu32 ": %s",
7880b57cec5SDimitry Andric                   __FUNCTION__,
7899dba64beSDimitry Andric                   reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
7900b57cec5SDimitry Andric                   reg_to_read, error.AsCString());
7910b57cec5SDimitry Andric         continue;
7920b57cec5SDimitry Andric       }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric       response.PutChar(delimiter);
7950b57cec5SDimitry Andric       delimiter = ',';
7960b57cec5SDimitry Andric       WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p,
7970b57cec5SDimitry Andric                                         &reg_value, endian::InlHostByteOrder());
7980b57cec5SDimitry Andric     }
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric     response.PutChar(';');
8010b57cec5SDimitry Andric   }
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   //
8040b57cec5SDimitry Andric   // Expedite registers.
8050b57cec5SDimitry Andric   //
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric   // Grab the register context.
8080b57cec5SDimitry Andric   NativeRegisterContext& reg_ctx = thread->GetRegisterContext();
8090b57cec5SDimitry Andric   // Expedite all registers in the first register set (i.e. should be GPRs)
8100b57cec5SDimitry Andric   // that are not contained in other registers.
8110b57cec5SDimitry Andric   const RegisterSet *reg_set_p;
8120b57cec5SDimitry Andric   if (reg_ctx.GetRegisterSetCount() > 0 &&
8130b57cec5SDimitry Andric       ((reg_set_p = reg_ctx.GetRegisterSet(0)) != nullptr)) {
8149dba64beSDimitry Andric     LLDB_LOGF(log,
8159dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s expediting registers "
8160b57cec5SDimitry Andric               "from set '%s' (registers set count: %zu)",
8179dba64beSDimitry Andric               __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>",
8180b57cec5SDimitry Andric               reg_set_p->num_registers);
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric     for (const uint32_t *reg_num_p = reg_set_p->registers;
8210b57cec5SDimitry Andric          *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) {
8220b57cec5SDimitry Andric       const RegisterInfo *const reg_info_p =
8230b57cec5SDimitry Andric           reg_ctx.GetRegisterInfoAtIndex(*reg_num_p);
8240b57cec5SDimitry Andric       if (reg_info_p == nullptr) {
8259dba64beSDimitry Andric         LLDB_LOGF(log,
8269dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s failed to get "
8270b57cec5SDimitry Andric                   "register info for register set '%s', register index "
8280b57cec5SDimitry Andric                   "%" PRIu32,
8290b57cec5SDimitry Andric                   __FUNCTION__,
8300b57cec5SDimitry Andric                   reg_set_p->name ? reg_set_p->name : "<unnamed-set>",
8310b57cec5SDimitry Andric                   *reg_num_p);
8320b57cec5SDimitry Andric       } else if (reg_info_p->value_regs == nullptr) {
8330b57cec5SDimitry Andric         // Only expediate registers that are not contained in other registers.
8340b57cec5SDimitry Andric         RegisterValue reg_value;
8350b57cec5SDimitry Andric         Status error = reg_ctx.ReadRegister(reg_info_p, reg_value);
8360b57cec5SDimitry Andric         if (error.Success()) {
8370b57cec5SDimitry Andric           response.Printf("%.02x:", *reg_num_p);
8380b57cec5SDimitry Andric           WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p,
8390b57cec5SDimitry Andric                                             &reg_value, lldb::eByteOrderBig);
8400b57cec5SDimitry Andric           response.PutChar(';');
8410b57cec5SDimitry Andric         } else {
8429dba64beSDimitry Andric           LLDB_LOGF(log,
8439dba64beSDimitry Andric                     "GDBRemoteCommunicationServerLLGS::%s failed to read "
8440b57cec5SDimitry Andric                     "register '%s' index %" PRIu32 ": %s",
8450b57cec5SDimitry Andric                     __FUNCTION__,
8469dba64beSDimitry Andric                     reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
8470b57cec5SDimitry Andric                     *reg_num_p, error.AsCString());
8480b57cec5SDimitry Andric         }
8490b57cec5SDimitry Andric       }
8500b57cec5SDimitry Andric     }
8510b57cec5SDimitry Andric   }
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric   const char *reason_str = GetStopReasonString(tid_stop_info.reason);
8540b57cec5SDimitry Andric   if (reason_str != nullptr) {
8550b57cec5SDimitry Andric     response.Printf("reason:%s;", reason_str);
8560b57cec5SDimitry Andric   }
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric   if (!description.empty()) {
8590b57cec5SDimitry Andric     // Description may contains special chars, send as hex bytes.
8600b57cec5SDimitry Andric     response.PutCString("description:");
8610b57cec5SDimitry Andric     response.PutStringAsRawHex8(description);
8620b57cec5SDimitry Andric     response.PutChar(';');
8630b57cec5SDimitry Andric   } else if ((tid_stop_info.reason == eStopReasonException) &&
8640b57cec5SDimitry Andric              tid_stop_info.details.exception.type) {
8650b57cec5SDimitry Andric     response.PutCString("metype:");
8660b57cec5SDimitry Andric     response.PutHex64(tid_stop_info.details.exception.type);
8670b57cec5SDimitry Andric     response.PutCString(";mecount:");
8680b57cec5SDimitry Andric     response.PutHex32(tid_stop_info.details.exception.data_count);
8690b57cec5SDimitry Andric     response.PutChar(';');
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric     for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) {
8720b57cec5SDimitry Andric       response.PutCString("medata:");
8730b57cec5SDimitry Andric       response.PutHex64(tid_stop_info.details.exception.data[i]);
8740b57cec5SDimitry Andric       response.PutChar(';');
8750b57cec5SDimitry Andric     }
8760b57cec5SDimitry Andric   }
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
8820b57cec5SDimitry Andric     NativeProcessProtocol *process) {
8830b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
8869dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
8870b57cec5SDimitry Andric 
8880b57cec5SDimitry Andric   PacketResult result = SendStopReasonForState(StateType::eStateExited);
8890b57cec5SDimitry Andric   if (result != PacketResult::Success) {
8909dba64beSDimitry Andric     LLDB_LOGF(log,
8919dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to send stop "
8920b57cec5SDimitry Andric               "notification for PID %" PRIu64 ", state: eStateExited",
8930b57cec5SDimitry Andric               __FUNCTION__, process->GetID());
8940b57cec5SDimitry Andric   }
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric   // Close the pipe to the inferior terminal i/o if we launched it and set one
8970b57cec5SDimitry Andric   // up.
8980b57cec5SDimitry Andric   MaybeCloseInferiorTerminalConnection();
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric   // We are ready to exit the debug monitor.
9010b57cec5SDimitry Andric   m_exit_now = true;
9020b57cec5SDimitry Andric   m_mainloop.RequestTermination();
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
9060b57cec5SDimitry Andric     NativeProcessProtocol *process) {
9070b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
9109dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric   // Send the stop reason unless this is the stop after the launch or attach.
9130b57cec5SDimitry Andric   switch (m_inferior_prev_state) {
9140b57cec5SDimitry Andric   case eStateLaunching:
9150b57cec5SDimitry Andric   case eStateAttaching:
9160b57cec5SDimitry Andric     // Don't send anything per debugserver behavior.
9170b57cec5SDimitry Andric     break;
9180b57cec5SDimitry Andric   default:
9190b57cec5SDimitry Andric     // In all other cases, send the stop reason.
9200b57cec5SDimitry Andric     PacketResult result = SendStopReasonForState(StateType::eStateStopped);
9210b57cec5SDimitry Andric     if (result != PacketResult::Success) {
9229dba64beSDimitry Andric       LLDB_LOGF(log,
9239dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s failed to send stop "
9240b57cec5SDimitry Andric                 "notification for PID %" PRIu64 ", state: eStateExited",
9250b57cec5SDimitry Andric                 __FUNCTION__, process->GetID());
9260b57cec5SDimitry Andric     }
9270b57cec5SDimitry Andric     break;
9280b57cec5SDimitry Andric   }
9290b57cec5SDimitry Andric }
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
9320b57cec5SDimitry Andric     NativeProcessProtocol *process, lldb::StateType state) {
9330b57cec5SDimitry Andric   assert(process && "process cannot be NULL");
9340b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
9350b57cec5SDimitry Andric   if (log) {
9369dba64beSDimitry Andric     LLDB_LOGF(log,
9379dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s called with "
9380b57cec5SDimitry Andric               "NativeProcessProtocol pid %" PRIu64 ", state: %s",
9390b57cec5SDimitry Andric               __FUNCTION__, process->GetID(), StateAsCString(state));
9400b57cec5SDimitry Andric   }
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   switch (state) {
9430b57cec5SDimitry Andric   case StateType::eStateRunning:
9440b57cec5SDimitry Andric     StartSTDIOForwarding();
9450b57cec5SDimitry Andric     break;
9460b57cec5SDimitry Andric 
9470b57cec5SDimitry Andric   case StateType::eStateStopped:
9480b57cec5SDimitry Andric     // Make sure we get all of the pending stdout/stderr from the inferior and
9490b57cec5SDimitry Andric     // send it to the lldb host before we send the state change notification
9500b57cec5SDimitry Andric     SendProcessOutput();
9510b57cec5SDimitry Andric     // Then stop the forwarding, so that any late output (see llvm.org/pr25652)
9520b57cec5SDimitry Andric     // does not interfere with our protocol.
9530b57cec5SDimitry Andric     StopSTDIOForwarding();
9540b57cec5SDimitry Andric     HandleInferiorState_Stopped(process);
9550b57cec5SDimitry Andric     break;
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric   case StateType::eStateExited:
9580b57cec5SDimitry Andric     // Same as above
9590b57cec5SDimitry Andric     SendProcessOutput();
9600b57cec5SDimitry Andric     StopSTDIOForwarding();
9610b57cec5SDimitry Andric     HandleInferiorState_Exited(process);
9620b57cec5SDimitry Andric     break;
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric   default:
9650b57cec5SDimitry Andric     if (log) {
9669dba64beSDimitry Andric       LLDB_LOGF(log,
9679dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s didn't handle state "
9680b57cec5SDimitry Andric                 "change for pid %" PRIu64 ", new state: %s",
9690b57cec5SDimitry Andric                 __FUNCTION__, process->GetID(), StateAsCString(state));
9700b57cec5SDimitry Andric     }
9710b57cec5SDimitry Andric     break;
9720b57cec5SDimitry Andric   }
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric   // Remember the previous state reported to us.
9750b57cec5SDimitry Andric   m_inferior_prev_state = state;
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) {
9790b57cec5SDimitry Andric   ClearProcessSpecificData();
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
9830b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));
9840b57cec5SDimitry Andric 
9850b57cec5SDimitry Andric   if (!m_handshake_completed) {
9860b57cec5SDimitry Andric     if (!HandshakeWithClient()) {
9879dba64beSDimitry Andric       LLDB_LOGF(log,
9889dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s handshake with "
9890b57cec5SDimitry Andric                 "client failed, exiting",
9900b57cec5SDimitry Andric                 __FUNCTION__);
9910b57cec5SDimitry Andric       m_mainloop.RequestTermination();
9920b57cec5SDimitry Andric       return;
9930b57cec5SDimitry Andric     }
9940b57cec5SDimitry Andric     m_handshake_completed = true;
9950b57cec5SDimitry Andric   }
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   bool interrupt = false;
9980b57cec5SDimitry Andric   bool done = false;
9990b57cec5SDimitry Andric   Status error;
10000b57cec5SDimitry Andric   while (true) {
10010b57cec5SDimitry Andric     const PacketResult result = GetPacketAndSendResponse(
10020b57cec5SDimitry Andric         std::chrono::microseconds(0), error, interrupt, done);
10030b57cec5SDimitry Andric     if (result == PacketResult::ErrorReplyTimeout)
10040b57cec5SDimitry Andric       break; // No more packets in the queue
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric     if ((result != PacketResult::Success)) {
10079dba64beSDimitry Andric       LLDB_LOGF(log,
10089dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s processing a packet "
10090b57cec5SDimitry Andric                 "failed: %s",
10100b57cec5SDimitry Andric                 __FUNCTION__, error.AsCString());
10110b57cec5SDimitry Andric       m_mainloop.RequestTermination();
10120b57cec5SDimitry Andric       break;
10130b57cec5SDimitry Andric     }
10140b57cec5SDimitry Andric   }
10150b57cec5SDimitry Andric }
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::InitializeConnection(
10185ffd83dbSDimitry Andric     std::unique_ptr<Connection> connection) {
10190b57cec5SDimitry Andric   IOObjectSP read_object_sp = connection->GetReadObject();
10205ffd83dbSDimitry Andric   GDBRemoteCommunicationServer::SetConnection(std::move(connection));
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric   Status error;
10230b57cec5SDimitry Andric   m_network_handle_up = m_mainloop.RegisterReadObject(
10240b57cec5SDimitry Andric       read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); },
10250b57cec5SDimitry Andric       error);
10260b57cec5SDimitry Andric   return error;
10270b57cec5SDimitry Andric }
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
10300b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer,
10310b57cec5SDimitry Andric                                                     uint32_t len) {
10320b57cec5SDimitry Andric   if ((buffer == nullptr) || (len == 0)) {
10330b57cec5SDimitry Andric     // Nothing to send.
10340b57cec5SDimitry Andric     return PacketResult::Success;
10350b57cec5SDimitry Andric   }
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric   StreamString response;
10380b57cec5SDimitry Andric   response.PutChar('O');
10390b57cec5SDimitry Andric   response.PutBytesAsRawHex8(buffer, len);
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
10420b57cec5SDimitry Andric }
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) {
10450b57cec5SDimitry Andric   Status error;
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   // Set up the reading/handling of process I/O
10480b57cec5SDimitry Andric   std::unique_ptr<ConnectionFileDescriptor> conn_up(
10490b57cec5SDimitry Andric       new ConnectionFileDescriptor(fd, true));
10500b57cec5SDimitry Andric   if (!conn_up) {
10510b57cec5SDimitry Andric     error.SetErrorString("failed to create ConnectionFileDescriptor");
10520b57cec5SDimitry Andric     return error;
10530b57cec5SDimitry Andric   }
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric   m_stdio_communication.SetCloseOnEOF(false);
10565ffd83dbSDimitry Andric   m_stdio_communication.SetConnection(std::move(conn_up));
10570b57cec5SDimitry Andric   if (!m_stdio_communication.IsConnected()) {
10580b57cec5SDimitry Andric     error.SetErrorString(
10590b57cec5SDimitry Andric         "failed to set connection for inferior I/O communication");
10600b57cec5SDimitry Andric     return error;
10610b57cec5SDimitry Andric   }
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   return Status();
10640b57cec5SDimitry Andric }
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() {
10670b57cec5SDimitry Andric   // Don't forward if not connected (e.g. when attaching).
10680b57cec5SDimitry Andric   if (!m_stdio_communication.IsConnected())
10690b57cec5SDimitry Andric     return;
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   Status error;
10720b57cec5SDimitry Andric   lldbassert(!m_stdio_handle_up);
10730b57cec5SDimitry Andric   m_stdio_handle_up = m_mainloop.RegisterReadObject(
10740b57cec5SDimitry Andric       m_stdio_communication.GetConnection()->GetReadObject(),
10750b57cec5SDimitry Andric       [this](MainLoopBase &) { SendProcessOutput(); }, error);
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric   if (!m_stdio_handle_up) {
10780b57cec5SDimitry Andric     // Not much we can do about the failure. Log it and continue without
10790b57cec5SDimitry Andric     // forwarding.
10800b57cec5SDimitry Andric     if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
10819dba64beSDimitry Andric       LLDB_LOGF(log,
10829dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio "
10830b57cec5SDimitry Andric                 "forwarding: %s",
10840b57cec5SDimitry Andric                 __FUNCTION__, error.AsCString());
10850b57cec5SDimitry Andric   }
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() {
10890b57cec5SDimitry Andric   m_stdio_handle_up.reset();
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
10930b57cec5SDimitry Andric   char buffer[1024];
10940b57cec5SDimitry Andric   ConnectionStatus status;
10950b57cec5SDimitry Andric   Status error;
10960b57cec5SDimitry Andric   while (true) {
10970b57cec5SDimitry Andric     size_t bytes_read = m_stdio_communication.Read(
10980b57cec5SDimitry Andric         buffer, sizeof buffer, std::chrono::microseconds(0), status, &error);
10990b57cec5SDimitry Andric     switch (status) {
11000b57cec5SDimitry Andric     case eConnectionStatusSuccess:
11010b57cec5SDimitry Andric       SendONotification(buffer, bytes_read);
11020b57cec5SDimitry Andric       break;
11030b57cec5SDimitry Andric     case eConnectionStatusLostConnection:
11040b57cec5SDimitry Andric     case eConnectionStatusEndOfFile:
11050b57cec5SDimitry Andric     case eConnectionStatusError:
11060b57cec5SDimitry Andric     case eConnectionStatusNoConnection:
11070b57cec5SDimitry Andric       if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
11089dba64beSDimitry Andric         LLDB_LOGF(log,
11099dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s Stopping stdio "
11100b57cec5SDimitry Andric                   "forwarding as communication returned status %d (error: "
11110b57cec5SDimitry Andric                   "%s)",
11120b57cec5SDimitry Andric                   __FUNCTION__, status, error.AsCString());
11130b57cec5SDimitry Andric       m_stdio_handle_up.reset();
11140b57cec5SDimitry Andric       return;
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric     case eConnectionStatusInterrupted:
11170b57cec5SDimitry Andric     case eConnectionStatusTimedOut:
11180b57cec5SDimitry Andric       return;
11190b57cec5SDimitry Andric     }
11200b57cec5SDimitry Andric   }
11210b57cec5SDimitry Andric }
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
11240b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jTraceStart(
11250b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
11260b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
11270b57cec5SDimitry Andric   // Fail if we don't have a current process.
11280b57cec5SDimitry Andric   if (!m_debugged_process_up ||
11290b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
11300b57cec5SDimitry Andric     return SendErrorResponse(68);
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   if (!packet.ConsumeFront("jTraceStart:"))
11330b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
11340b57cec5SDimitry Andric 
11350b57cec5SDimitry Andric   TraceOptions options;
11360b57cec5SDimitry Andric   uint64_t type = std::numeric_limits<uint64_t>::max();
11370b57cec5SDimitry Andric   uint64_t buffersize = std::numeric_limits<uint64_t>::max();
11380b57cec5SDimitry Andric   lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
11390b57cec5SDimitry Andric   uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
11400b57cec5SDimitry Andric 
11410b57cec5SDimitry Andric   auto json_object = StructuredData::ParseJSON(packet.Peek());
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric   if (!json_object ||
11440b57cec5SDimitry Andric       json_object->GetType() != lldb::eStructuredDataTypeDictionary)
11450b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
11460b57cec5SDimitry Andric 
11470b57cec5SDimitry Andric   auto json_dict = json_object->GetAsDictionary();
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric   json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize);
11500b57cec5SDimitry Andric   options.setMetaDataBufferSize(metabuffersize);
11510b57cec5SDimitry Andric 
11520b57cec5SDimitry Andric   json_dict->GetValueForKeyAsInteger("buffersize", buffersize);
11530b57cec5SDimitry Andric   options.setTraceBufferSize(buffersize);
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric   json_dict->GetValueForKeyAsInteger("type", type);
11560b57cec5SDimitry Andric   options.setType(static_cast<lldb::TraceType>(type));
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric   json_dict->GetValueForKeyAsInteger("threadid", tid);
11590b57cec5SDimitry Andric   options.setThreadID(tid);
11600b57cec5SDimitry Andric 
11610b57cec5SDimitry Andric   StructuredData::ObjectSP custom_params_sp =
11620b57cec5SDimitry Andric       json_dict->GetValueForKey("params");
11630b57cec5SDimitry Andric   if (custom_params_sp &&
11640b57cec5SDimitry Andric       custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary)
11650b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   options.setTraceParams(
11685ffd83dbSDimitry Andric       std::static_pointer_cast<StructuredData::Dictionary>(custom_params_sp));
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric   if (buffersize == std::numeric_limits<uint64_t>::max() ||
11710b57cec5SDimitry Andric       type != lldb::TraceType::eTraceTypeProcessorTrace) {
11720b57cec5SDimitry Andric     LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize,
11730b57cec5SDimitry Andric              type);
11740b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet ");
11750b57cec5SDimitry Andric   }
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   Status error;
11780b57cec5SDimitry Andric   lldb::user_id_t uid = LLDB_INVALID_UID;
11790b57cec5SDimitry Andric   uid = m_debugged_process_up->StartTrace(options, error);
11800b57cec5SDimitry Andric   LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError());
11810b57cec5SDimitry Andric   if (error.Fail())
11820b57cec5SDimitry Andric     return SendErrorResponse(error);
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric   StreamGDBRemote response;
11850b57cec5SDimitry Andric   response.Printf("%" PRIx64, uid);
11860b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
11870b57cec5SDimitry Andric }
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
11900b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jTraceStop(
11910b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
11920b57cec5SDimitry Andric   // Fail if we don't have a current process.
11930b57cec5SDimitry Andric   if (!m_debugged_process_up ||
11940b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
11950b57cec5SDimitry Andric     return SendErrorResponse(68);
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric   if (!packet.ConsumeFront("jTraceStop:"))
11980b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric   lldb::user_id_t uid = LLDB_INVALID_UID;
12010b57cec5SDimitry Andric   lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric   auto json_object = StructuredData::ParseJSON(packet.Peek());
12040b57cec5SDimitry Andric 
12050b57cec5SDimitry Andric   if (!json_object ||
12060b57cec5SDimitry Andric       json_object->GetType() != lldb::eStructuredDataTypeDictionary)
12070b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric   auto json_dict = json_object->GetAsDictionary();
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric   if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
12120b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric   json_dict->GetValueForKeyAsInteger("threadid", tid);
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric   Status error = m_debugged_process_up->StopTrace(uid, tid);
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric   if (error.Fail())
12190b57cec5SDimitry Andric     return SendErrorResponse(error);
12200b57cec5SDimitry Andric 
12210b57cec5SDimitry Andric   return SendOKResponse();
12220b57cec5SDimitry Andric }
12230b57cec5SDimitry Andric 
12240b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
12250b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead(
12260b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric   // Fail if we don't have a current process.
12290b57cec5SDimitry Andric   if (!m_debugged_process_up ||
12300b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
12310b57cec5SDimitry Andric     return SendErrorResponse(68);
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   if (!packet.ConsumeFront("jTraceConfigRead:"))
12340b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
12350b57cec5SDimitry Andric                                  "jTraceConfigRead: Ill formed packet ");
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric   lldb::user_id_t uid = LLDB_INVALID_UID;
12380b57cec5SDimitry Andric   lldb::tid_t threadid = LLDB_INVALID_THREAD_ID;
12390b57cec5SDimitry Andric 
12400b57cec5SDimitry Andric   auto json_object = StructuredData::ParseJSON(packet.Peek());
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric   if (!json_object ||
12430b57cec5SDimitry Andric       json_object->GetType() != lldb::eStructuredDataTypeDictionary)
12440b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
12450b57cec5SDimitry Andric                                  "jTraceConfigRead: Ill formed packet ");
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric   auto json_dict = json_object->GetAsDictionary();
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric   if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
12500b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
12510b57cec5SDimitry Andric                                  "jTraceConfigRead: Ill formed packet ");
12520b57cec5SDimitry Andric 
12530b57cec5SDimitry Andric   json_dict->GetValueForKeyAsInteger("threadid", threadid);
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric   TraceOptions options;
12560b57cec5SDimitry Andric   StreamGDBRemote response;
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric   options.setThreadID(threadid);
12590b57cec5SDimitry Andric   Status error = m_debugged_process_up->GetTraceConfig(uid, options);
12600b57cec5SDimitry Andric 
12610b57cec5SDimitry Andric   if (error.Fail())
12620b57cec5SDimitry Andric     return SendErrorResponse(error);
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
12650b57cec5SDimitry Andric   StructuredData::Dictionary json_packet;
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric   json_packet.AddIntegerItem("type", options.getType());
12680b57cec5SDimitry Andric   json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
12690b57cec5SDimitry Andric   json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
12700b57cec5SDimitry Andric 
12710b57cec5SDimitry Andric   StructuredData::DictionarySP custom_params = options.getTraceParams();
12720b57cec5SDimitry Andric   if (custom_params)
12730b57cec5SDimitry Andric     json_packet.AddItem("params", custom_params);
12740b57cec5SDimitry Andric 
12750b57cec5SDimitry Andric   StreamString json_string;
12760b57cec5SDimitry Andric   json_packet.Dump(json_string, false);
12770b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(json_string.GetData(),
12780b57cec5SDimitry Andric                                    json_string.GetSize());
12790b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
12800b57cec5SDimitry Andric }
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
12830b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jTraceRead(
12840b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric   // Fail if we don't have a current process.
12870b57cec5SDimitry Andric   if (!m_debugged_process_up ||
12880b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
12890b57cec5SDimitry Andric     return SendErrorResponse(68);
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric   enum PacketType { MetaData, BufferData };
12920b57cec5SDimitry Andric   PacketType tracetype = MetaData;
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric   if (packet.ConsumeFront("jTraceBufferRead:"))
12950b57cec5SDimitry Andric     tracetype = BufferData;
12960b57cec5SDimitry Andric   else if (packet.ConsumeFront("jTraceMetaRead:"))
12970b57cec5SDimitry Andric     tracetype = MetaData;
12980b57cec5SDimitry Andric   else {
12990b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
13000b57cec5SDimitry Andric   }
13010b57cec5SDimitry Andric 
13020b57cec5SDimitry Andric   lldb::user_id_t uid = LLDB_INVALID_UID;
13030b57cec5SDimitry Andric 
13040b57cec5SDimitry Andric   uint64_t byte_count = std::numeric_limits<uint64_t>::max();
13050b57cec5SDimitry Andric   lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
13060b57cec5SDimitry Andric   uint64_t offset = std::numeric_limits<uint64_t>::max();
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric   auto json_object = StructuredData::ParseJSON(packet.Peek());
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric   if (!json_object ||
13110b57cec5SDimitry Andric       json_object->GetType() != lldb::eStructuredDataTypeDictionary)
13120b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric   auto json_dict = json_object->GetAsDictionary();
13150b57cec5SDimitry Andric 
13160b57cec5SDimitry Andric   if (!json_dict->GetValueForKeyAsInteger("traceid", uid) ||
13170b57cec5SDimitry Andric       !json_dict->GetValueForKeyAsInteger("offset", offset) ||
13180b57cec5SDimitry Andric       !json_dict->GetValueForKeyAsInteger("buffersize", byte_count))
13190b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric   json_dict->GetValueForKeyAsInteger("threadid", tid);
13220b57cec5SDimitry Andric 
13230b57cec5SDimitry Andric   // Allocate the response buffer.
13240b57cec5SDimitry Andric   std::unique_ptr<uint8_t[]> buffer (new (std::nothrow) uint8_t[byte_count]);
13250b57cec5SDimitry Andric   if (!buffer)
13260b57cec5SDimitry Andric     return SendErrorResponse(0x78);
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric   StreamGDBRemote response;
13290b57cec5SDimitry Andric   Status error;
13300b57cec5SDimitry Andric   llvm::MutableArrayRef<uint8_t> buf(buffer.get(), byte_count);
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric   if (tracetype == BufferData)
13330b57cec5SDimitry Andric     error = m_debugged_process_up->GetData(uid, tid, buf, offset);
13340b57cec5SDimitry Andric   else if (tracetype == MetaData)
13350b57cec5SDimitry Andric     error = m_debugged_process_up->GetMetaData(uid, tid, buf, offset);
13360b57cec5SDimitry Andric 
13370b57cec5SDimitry Andric   if (error.Fail())
13380b57cec5SDimitry Andric     return SendErrorResponse(error);
13390b57cec5SDimitry Andric 
13400b57cec5SDimitry Andric   for (auto i : buf)
13410b57cec5SDimitry Andric     response.PutHex8(i);
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
13440b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
13450b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
13460b57cec5SDimitry Andric }
13470b57cec5SDimitry Andric 
13480b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
13490b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
13500b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
13510b57cec5SDimitry Andric   // Fail if we don't have a current process.
13520b57cec5SDimitry Andric   if (!m_debugged_process_up ||
13530b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
13540b57cec5SDimitry Andric     return SendErrorResponse(68);
13550b57cec5SDimitry Andric 
13560b57cec5SDimitry Andric   lldb::pid_t pid = m_debugged_process_up->GetID();
13570b57cec5SDimitry Andric 
13580b57cec5SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
13590b57cec5SDimitry Andric     return SendErrorResponse(1);
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric   ProcessInstanceInfo proc_info;
13620b57cec5SDimitry Andric   if (!Host::GetProcessInfo(pid, proc_info))
13630b57cec5SDimitry Andric     return SendErrorResponse(1);
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric   StreamString response;
13660b57cec5SDimitry Andric   CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
13670b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
13680b57cec5SDimitry Andric }
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
13710b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
13720b57cec5SDimitry Andric   // Fail if we don't have a current process.
13730b57cec5SDimitry Andric   if (!m_debugged_process_up ||
13740b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
13750b57cec5SDimitry Andric     return SendErrorResponse(68);
13760b57cec5SDimitry Andric 
13770b57cec5SDimitry Andric   // Make sure we set the current thread so g and p packets return the data the
13780b57cec5SDimitry Andric   // gdb will expect.
13790b57cec5SDimitry Andric   lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
13800b57cec5SDimitry Andric   SetCurrentThreadID(tid);
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric   NativeThreadProtocol *thread = m_debugged_process_up->GetCurrentThread();
13830b57cec5SDimitry Andric   if (!thread)
13840b57cec5SDimitry Andric     return SendErrorResponse(69);
13850b57cec5SDimitry Andric 
13860b57cec5SDimitry Andric   StreamString response;
13870b57cec5SDimitry Andric   response.Printf("QC%" PRIx64, thread->GetID());
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
13900b57cec5SDimitry Andric }
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
13930b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
13940b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
13950b57cec5SDimitry Andric 
13960b57cec5SDimitry Andric   StopSTDIOForwarding();
13970b57cec5SDimitry Andric 
13980b57cec5SDimitry Andric   if (!m_debugged_process_up) {
13990b57cec5SDimitry Andric     LLDB_LOG(log, "No debugged process found.");
14000b57cec5SDimitry Andric     return PacketResult::Success;
14010b57cec5SDimitry Andric   }
14020b57cec5SDimitry Andric 
14030b57cec5SDimitry Andric   Status error = m_debugged_process_up->Kill();
14040b57cec5SDimitry Andric   if (error.Fail())
14050b57cec5SDimitry Andric     LLDB_LOG(log, "Failed to kill debugged process {0}: {1}",
14060b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric   // No OK response for kill packet.
14090b57cec5SDimitry Andric   // return SendOKResponse ();
14100b57cec5SDimitry Andric   return PacketResult::Success;
14110b57cec5SDimitry Andric }
14120b57cec5SDimitry Andric 
14130b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14140b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR(
14150b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
14160b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetDisableASLR:"));
14170b57cec5SDimitry Andric   if (packet.GetU32(0))
14180b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
14190b57cec5SDimitry Andric   else
14200b57cec5SDimitry Andric     m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
14210b57cec5SDimitry Andric   return SendOKResponse();
14220b57cec5SDimitry Andric }
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14250b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir(
14260b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
14270b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetWorkingDir:"));
14280b57cec5SDimitry Andric   std::string path;
14290b57cec5SDimitry Andric   packet.GetHexByteString(path);
14300b57cec5SDimitry Andric   m_process_launch_info.SetWorkingDirectory(FileSpec(path));
14310b57cec5SDimitry Andric   return SendOKResponse();
14320b57cec5SDimitry Andric }
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14350b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir(
14360b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
14370b57cec5SDimitry Andric   FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()};
14380b57cec5SDimitry Andric   if (working_dir) {
14390b57cec5SDimitry Andric     StreamString response;
14400b57cec5SDimitry Andric     response.PutStringAsRawHex8(working_dir.GetCString());
14410b57cec5SDimitry Andric     return SendPacketNoLock(response.GetString());
14420b57cec5SDimitry Andric   }
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric   return SendErrorResponse(14);
14450b57cec5SDimitry Andric }
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
14480b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
14490b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
14509dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
14510b57cec5SDimitry Andric 
14520b57cec5SDimitry Andric   // Ensure we have a native process.
14530b57cec5SDimitry Andric   if (!m_debugged_process_up) {
14549dba64beSDimitry Andric     LLDB_LOGF(log,
14559dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s no debugged process "
14560b57cec5SDimitry Andric               "shared pointer",
14570b57cec5SDimitry Andric               __FUNCTION__);
14580b57cec5SDimitry Andric     return SendErrorResponse(0x36);
14590b57cec5SDimitry Andric   }
14600b57cec5SDimitry Andric 
14610b57cec5SDimitry Andric   // Pull out the signal number.
14620b57cec5SDimitry Andric   packet.SetFilePos(::strlen("C"));
14630b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1) {
14640b57cec5SDimitry Andric     // Shouldn't be using a C without a signal.
14650b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "C packet specified without signal.");
14660b57cec5SDimitry Andric   }
14670b57cec5SDimitry Andric   const uint32_t signo =
14680b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
14690b57cec5SDimitry Andric   if (signo == std::numeric_limits<uint32_t>::max())
14700b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "failed to parse signal number");
14710b57cec5SDimitry Andric 
14720b57cec5SDimitry Andric   // Handle optional continue address.
14730b57cec5SDimitry Andric   if (packet.GetBytesLeft() > 0) {
14740b57cec5SDimitry Andric     // FIXME add continue at address support for $C{signo}[;{continue-address}].
14750b57cec5SDimitry Andric     if (*packet.Peek() == ';')
14769dba64beSDimitry Andric       return SendUnimplementedResponse(packet.GetStringRef().data());
14770b57cec5SDimitry Andric     else
14780b57cec5SDimitry Andric       return SendIllFormedResponse(
14790b57cec5SDimitry Andric           packet, "unexpected content after $C{signal-number}");
14800b57cec5SDimitry Andric   }
14810b57cec5SDimitry Andric 
14829dba64beSDimitry Andric   ResumeActionList resume_actions(StateType::eStateRunning,
14839dba64beSDimitry Andric                                   LLDB_INVALID_SIGNAL_NUMBER);
14840b57cec5SDimitry Andric   Status error;
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric   // We have two branches: what to do if a continue thread is specified (in
14870b57cec5SDimitry Andric   // which case we target sending the signal to that thread), or when we don't
14880b57cec5SDimitry Andric   // have a continue thread set (in which case we send a signal to the
14890b57cec5SDimitry Andric   // process).
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric   // TODO discuss with Greg Clayton, make sure this makes sense.
14920b57cec5SDimitry Andric 
14930b57cec5SDimitry Andric   lldb::tid_t signal_tid = GetContinueThreadID();
14940b57cec5SDimitry Andric   if (signal_tid != LLDB_INVALID_THREAD_ID) {
14950b57cec5SDimitry Andric     // The resume action for the continue thread (or all threads if a continue
14960b57cec5SDimitry Andric     // thread is not set).
14970b57cec5SDimitry Andric     ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning,
14980b57cec5SDimitry Andric                            static_cast<int>(signo)};
14990b57cec5SDimitry Andric 
15000b57cec5SDimitry Andric     // Add the action for the continue thread (or all threads when the continue
15010b57cec5SDimitry Andric     // thread isn't present).
15020b57cec5SDimitry Andric     resume_actions.Append(action);
15030b57cec5SDimitry Andric   } else {
15040b57cec5SDimitry Andric     // Send the signal to the process since we weren't targeting a specific
15050b57cec5SDimitry Andric     // continue thread with the signal.
15060b57cec5SDimitry Andric     error = m_debugged_process_up->Signal(signo);
15070b57cec5SDimitry Andric     if (error.Fail()) {
15080b57cec5SDimitry Andric       LLDB_LOG(log, "failed to send signal for process {0}: {1}",
15090b57cec5SDimitry Andric                m_debugged_process_up->GetID(), error);
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric       return SendErrorResponse(0x52);
15120b57cec5SDimitry Andric     }
15130b57cec5SDimitry Andric   }
15140b57cec5SDimitry Andric 
15150b57cec5SDimitry Andric   // Resume the threads.
15160b57cec5SDimitry Andric   error = m_debugged_process_up->Resume(resume_actions);
15170b57cec5SDimitry Andric   if (error.Fail()) {
15180b57cec5SDimitry Andric     LLDB_LOG(log, "failed to resume threads for process {0}: {1}",
15190b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
15200b57cec5SDimitry Andric 
15210b57cec5SDimitry Andric     return SendErrorResponse(0x38);
15220b57cec5SDimitry Andric   }
15230b57cec5SDimitry Andric 
15240b57cec5SDimitry Andric   // Don't send an "OK" packet; response is the stopped/exited message.
15250b57cec5SDimitry Andric   return PacketResult::Success;
15260b57cec5SDimitry Andric }
15270b57cec5SDimitry Andric 
15280b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
15290b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
15300b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
15319dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
15320b57cec5SDimitry Andric 
15330b57cec5SDimitry Andric   packet.SetFilePos(packet.GetFilePos() + ::strlen("c"));
15340b57cec5SDimitry Andric 
15350b57cec5SDimitry Andric   // For now just support all continue.
15360b57cec5SDimitry Andric   const bool has_continue_address = (packet.GetBytesLeft() > 0);
15370b57cec5SDimitry Andric   if (has_continue_address) {
15380b57cec5SDimitry Andric     LLDB_LOG(log, "not implemented for c[address] variant [{0} remains]",
15390b57cec5SDimitry Andric              packet.Peek());
15409dba64beSDimitry Andric     return SendUnimplementedResponse(packet.GetStringRef().data());
15410b57cec5SDimitry Andric   }
15420b57cec5SDimitry Andric 
15430b57cec5SDimitry Andric   // Ensure we have a native process.
15440b57cec5SDimitry Andric   if (!m_debugged_process_up) {
15459dba64beSDimitry Andric     LLDB_LOGF(log,
15469dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s no debugged process "
15470b57cec5SDimitry Andric               "shared pointer",
15480b57cec5SDimitry Andric               __FUNCTION__);
15490b57cec5SDimitry Andric     return SendErrorResponse(0x36);
15500b57cec5SDimitry Andric   }
15510b57cec5SDimitry Andric 
15520b57cec5SDimitry Andric   // Build the ResumeActionList
15539dba64beSDimitry Andric   ResumeActionList actions(StateType::eStateRunning,
15549dba64beSDimitry Andric                            LLDB_INVALID_SIGNAL_NUMBER);
15550b57cec5SDimitry Andric 
15560b57cec5SDimitry Andric   Status error = m_debugged_process_up->Resume(actions);
15570b57cec5SDimitry Andric   if (error.Fail()) {
15580b57cec5SDimitry Andric     LLDB_LOG(log, "c failed for process {0}: {1}",
15590b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
15600b57cec5SDimitry Andric     return SendErrorResponse(GDBRemoteServerError::eErrorResume);
15610b57cec5SDimitry Andric   }
15620b57cec5SDimitry Andric 
15630b57cec5SDimitry Andric   LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID());
15640b57cec5SDimitry Andric   // No response required from continue.
15650b57cec5SDimitry Andric   return PacketResult::Success;
15660b57cec5SDimitry Andric }
15670b57cec5SDimitry Andric 
15680b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
15690b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCont_actions(
15700b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
15710b57cec5SDimitry Andric   StreamString response;
15720b57cec5SDimitry Andric   response.Printf("vCont;c;C;s;S");
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
15750b57cec5SDimitry Andric }
15760b57cec5SDimitry Andric 
15770b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
15780b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vCont(
15790b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
15800b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
15819dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s handling vCont packet",
15820b57cec5SDimitry Andric             __FUNCTION__);
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric   packet.SetFilePos(::strlen("vCont"));
15850b57cec5SDimitry Andric 
15860b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0) {
15879dba64beSDimitry Andric     LLDB_LOGF(log,
15889dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s missing action from "
15890b57cec5SDimitry Andric               "vCont package",
15900b57cec5SDimitry Andric               __FUNCTION__);
15910b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Missing action from vCont package");
15920b57cec5SDimitry Andric   }
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric   // Check if this is all continue (no options or ";c").
15950b57cec5SDimitry Andric   if (::strcmp(packet.Peek(), ";c") == 0) {
15960b57cec5SDimitry Andric     // Move past the ';', then do a simple 'c'.
15970b57cec5SDimitry Andric     packet.SetFilePos(packet.GetFilePos() + 1);
15980b57cec5SDimitry Andric     return Handle_c(packet);
15990b57cec5SDimitry Andric   } else if (::strcmp(packet.Peek(), ";s") == 0) {
16000b57cec5SDimitry Andric     // Move past the ';', then do a simple 's'.
16010b57cec5SDimitry Andric     packet.SetFilePos(packet.GetFilePos() + 1);
16020b57cec5SDimitry Andric     return Handle_s(packet);
16030b57cec5SDimitry Andric   }
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric   // Ensure we have a native process.
16060b57cec5SDimitry Andric   if (!m_debugged_process_up) {
16070b57cec5SDimitry Andric     LLDB_LOG(log, "no debugged process");
16080b57cec5SDimitry Andric     return SendErrorResponse(0x36);
16090b57cec5SDimitry Andric   }
16100b57cec5SDimitry Andric 
16110b57cec5SDimitry Andric   ResumeActionList thread_actions;
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric   while (packet.GetBytesLeft() && *packet.Peek() == ';') {
16140b57cec5SDimitry Andric     // Skip the semi-colon.
16150b57cec5SDimitry Andric     packet.GetChar();
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric     // Build up the thread action.
16180b57cec5SDimitry Andric     ResumeAction thread_action;
16190b57cec5SDimitry Andric     thread_action.tid = LLDB_INVALID_THREAD_ID;
16200b57cec5SDimitry Andric     thread_action.state = eStateInvalid;
16219dba64beSDimitry Andric     thread_action.signal = LLDB_INVALID_SIGNAL_NUMBER;
16220b57cec5SDimitry Andric 
16230b57cec5SDimitry Andric     const char action = packet.GetChar();
16240b57cec5SDimitry Andric     switch (action) {
16250b57cec5SDimitry Andric     case 'C':
16260b57cec5SDimitry Andric       thread_action.signal = packet.GetHexMaxU32(false, 0);
16270b57cec5SDimitry Andric       if (thread_action.signal == 0)
16280b57cec5SDimitry Andric         return SendIllFormedResponse(
16290b57cec5SDimitry Andric             packet, "Could not parse signal in vCont packet C action");
16300b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
16310b57cec5SDimitry Andric 
16320b57cec5SDimitry Andric     case 'c':
16330b57cec5SDimitry Andric       // Continue
16340b57cec5SDimitry Andric       thread_action.state = eStateRunning;
16350b57cec5SDimitry Andric       break;
16360b57cec5SDimitry Andric 
16370b57cec5SDimitry Andric     case 'S':
16380b57cec5SDimitry Andric       thread_action.signal = packet.GetHexMaxU32(false, 0);
16390b57cec5SDimitry Andric       if (thread_action.signal == 0)
16400b57cec5SDimitry Andric         return SendIllFormedResponse(
16410b57cec5SDimitry Andric             packet, "Could not parse signal in vCont packet S action");
16420b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
16430b57cec5SDimitry Andric 
16440b57cec5SDimitry Andric     case 's':
16450b57cec5SDimitry Andric       // Step
16460b57cec5SDimitry Andric       thread_action.state = eStateStepping;
16470b57cec5SDimitry Andric       break;
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric     default:
16500b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Unsupported vCont action");
16510b57cec5SDimitry Andric       break;
16520b57cec5SDimitry Andric     }
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric     // Parse out optional :{thread-id} value.
16550b57cec5SDimitry Andric     if (packet.GetBytesLeft() && (*packet.Peek() == ':')) {
16560b57cec5SDimitry Andric       // Consume the separator.
16570b57cec5SDimitry Andric       packet.GetChar();
16580b57cec5SDimitry Andric 
16590b57cec5SDimitry Andric       thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
16600b57cec5SDimitry Andric       if (thread_action.tid == LLDB_INVALID_THREAD_ID)
16610b57cec5SDimitry Andric         return SendIllFormedResponse(
16620b57cec5SDimitry Andric             packet, "Could not parse thread number in vCont packet");
16630b57cec5SDimitry Andric     }
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric     thread_actions.Append(thread_action);
16660b57cec5SDimitry Andric   }
16670b57cec5SDimitry Andric 
16680b57cec5SDimitry Andric   Status error = m_debugged_process_up->Resume(thread_actions);
16690b57cec5SDimitry Andric   if (error.Fail()) {
16700b57cec5SDimitry Andric     LLDB_LOG(log, "vCont failed for process {0}: {1}",
16710b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
16720b57cec5SDimitry Andric     return SendErrorResponse(GDBRemoteServerError::eErrorResume);
16730b57cec5SDimitry Andric   }
16740b57cec5SDimitry Andric 
16750b57cec5SDimitry Andric   LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID());
16760b57cec5SDimitry Andric   // No response required from vCont.
16770b57cec5SDimitry Andric   return PacketResult::Success;
16780b57cec5SDimitry Andric }
16790b57cec5SDimitry Andric 
16800b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
16810b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
16820b57cec5SDimitry Andric   LLDB_LOG(log, "setting current thread id to {0}", tid);
16830b57cec5SDimitry Andric 
16840b57cec5SDimitry Andric   m_current_tid = tid;
16850b57cec5SDimitry Andric   if (m_debugged_process_up)
16860b57cec5SDimitry Andric     m_debugged_process_up->SetCurrentThreadID(m_current_tid);
16870b57cec5SDimitry Andric }
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
16900b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
16910b57cec5SDimitry Andric   LLDB_LOG(log, "setting continue thread id to {0}", tid);
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric   m_continue_tid = tid;
16940b57cec5SDimitry Andric }
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
16970b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_stop_reason(
16980b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
16990b57cec5SDimitry Andric   // Handle the $? gdbremote command.
17000b57cec5SDimitry Andric 
17010b57cec5SDimitry Andric   // If no process, indicate error
17020b57cec5SDimitry Andric   if (!m_debugged_process_up)
17030b57cec5SDimitry Andric     return SendErrorResponse(02);
17040b57cec5SDimitry Andric 
17050b57cec5SDimitry Andric   return SendStopReasonForState(m_debugged_process_up->GetState());
17060b57cec5SDimitry Andric }
17070b57cec5SDimitry Andric 
17080b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
17090b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
17100b57cec5SDimitry Andric     lldb::StateType process_state) {
17110b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric   switch (process_state) {
17140b57cec5SDimitry Andric   case eStateAttaching:
17150b57cec5SDimitry Andric   case eStateLaunching:
17160b57cec5SDimitry Andric   case eStateRunning:
17170b57cec5SDimitry Andric   case eStateStepping:
17180b57cec5SDimitry Andric   case eStateDetached:
17190b57cec5SDimitry Andric     // NOTE: gdb protocol doc looks like it should return $OK
17200b57cec5SDimitry Andric     // when everything is running (i.e. no stopped result).
17210b57cec5SDimitry Andric     return PacketResult::Success; // Ignore
17220b57cec5SDimitry Andric 
17230b57cec5SDimitry Andric   case eStateSuspended:
17240b57cec5SDimitry Andric   case eStateStopped:
17250b57cec5SDimitry Andric   case eStateCrashed: {
17260b57cec5SDimitry Andric     lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
17270b57cec5SDimitry Andric     // Make sure we set the current thread so g and p packets return the data
17280b57cec5SDimitry Andric     // the gdb will expect.
17290b57cec5SDimitry Andric     SetCurrentThreadID(tid);
17300b57cec5SDimitry Andric     return SendStopReplyPacketForThread(tid);
17310b57cec5SDimitry Andric   }
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric   case eStateInvalid:
17340b57cec5SDimitry Andric   case eStateUnloaded:
17350b57cec5SDimitry Andric   case eStateExited:
17360b57cec5SDimitry Andric     return SendWResponse(m_debugged_process_up.get());
17370b57cec5SDimitry Andric 
17380b57cec5SDimitry Andric   default:
17390b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}",
17400b57cec5SDimitry Andric              m_debugged_process_up->GetID(), process_state);
17410b57cec5SDimitry Andric     break;
17420b57cec5SDimitry Andric   }
17430b57cec5SDimitry Andric 
17440b57cec5SDimitry Andric   return SendErrorResponse(0);
17450b57cec5SDimitry Andric }
17460b57cec5SDimitry Andric 
17470b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
17480b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
17490b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
17500b57cec5SDimitry Andric   // Fail if we don't have a current process.
17510b57cec5SDimitry Andric   if (!m_debugged_process_up ||
17520b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
17530b57cec5SDimitry Andric     return SendErrorResponse(68);
17540b57cec5SDimitry Andric 
17550b57cec5SDimitry Andric   // Ensure we have a thread.
17560b57cec5SDimitry Andric   NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0);
17570b57cec5SDimitry Andric   if (!thread)
17580b57cec5SDimitry Andric     return SendErrorResponse(69);
17590b57cec5SDimitry Andric 
17600b57cec5SDimitry Andric   // Get the register context for the first thread.
17610b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
17620b57cec5SDimitry Andric 
17630b57cec5SDimitry Andric   // Parse out the register number from the request.
17640b57cec5SDimitry Andric   packet.SetFilePos(strlen("qRegisterInfo"));
17650b57cec5SDimitry Andric   const uint32_t reg_index =
17660b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
17670b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max())
17680b57cec5SDimitry Andric     return SendErrorResponse(69);
17690b57cec5SDimitry Andric 
17700b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
17710b57cec5SDimitry Andric   // the register set.
17720b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount())
17730b57cec5SDimitry Andric     return SendErrorResponse(69);
17740b57cec5SDimitry Andric 
17750b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
17760b57cec5SDimitry Andric   if (!reg_info)
17770b57cec5SDimitry Andric     return SendErrorResponse(69);
17780b57cec5SDimitry Andric 
17790b57cec5SDimitry Andric   // Build the reginfos response.
17800b57cec5SDimitry Andric   StreamGDBRemote response;
17810b57cec5SDimitry Andric 
17820b57cec5SDimitry Andric   response.PutCString("name:");
17830b57cec5SDimitry Andric   response.PutCString(reg_info->name);
17840b57cec5SDimitry Andric   response.PutChar(';');
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric   if (reg_info->alt_name && reg_info->alt_name[0]) {
17870b57cec5SDimitry Andric     response.PutCString("alt-name:");
17880b57cec5SDimitry Andric     response.PutCString(reg_info->alt_name);
17890b57cec5SDimitry Andric     response.PutChar(';');
17900b57cec5SDimitry Andric   }
17910b57cec5SDimitry Andric 
17920b57cec5SDimitry Andric   response.Printf("bitsize:%" PRIu32 ";offset:%" PRIu32 ";",
17930b57cec5SDimitry Andric                   reg_info->byte_size * 8, reg_info->byte_offset);
17940b57cec5SDimitry Andric 
17955ffd83dbSDimitry Andric   llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info);
17965ffd83dbSDimitry Andric   if (!encoding.empty())
17975ffd83dbSDimitry Andric     response << "encoding:" << encoding << ';';
17980b57cec5SDimitry Andric 
17995ffd83dbSDimitry Andric   llvm::StringRef format = GetFormatNameOrEmpty(*reg_info);
18005ffd83dbSDimitry Andric   if (!format.empty())
18015ffd83dbSDimitry Andric     response << "format:" << format << ';';
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric   const char *const register_set_name =
18040b57cec5SDimitry Andric       reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index);
18055ffd83dbSDimitry Andric   if (register_set_name)
18065ffd83dbSDimitry Andric     response << "set:" << register_set_name << ';';
18070b57cec5SDimitry Andric 
18080b57cec5SDimitry Andric   if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
18090b57cec5SDimitry Andric       LLDB_INVALID_REGNUM)
18100b57cec5SDimitry Andric     response.Printf("ehframe:%" PRIu32 ";",
18110b57cec5SDimitry Andric                     reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
18120b57cec5SDimitry Andric 
18130b57cec5SDimitry Andric   if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
18140b57cec5SDimitry Andric     response.Printf("dwarf:%" PRIu32 ";",
18150b57cec5SDimitry Andric                     reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
18160b57cec5SDimitry Andric 
18175ffd83dbSDimitry Andric   llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info);
18185ffd83dbSDimitry Andric   if (!kind_generic.empty())
18195ffd83dbSDimitry Andric     response << "generic:" << kind_generic << ';';
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric   if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
18220b57cec5SDimitry Andric     response.PutCString("container-regs:");
18235ffd83dbSDimitry Andric     CollectRegNums(reg_info->value_regs, response, true);
18240b57cec5SDimitry Andric     response.PutChar(';');
18250b57cec5SDimitry Andric   }
18260b57cec5SDimitry Andric 
18270b57cec5SDimitry Andric   if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
18280b57cec5SDimitry Andric     response.PutCString("invalidate-regs:");
18295ffd83dbSDimitry Andric     CollectRegNums(reg_info->invalidate_regs, response, true);
18300b57cec5SDimitry Andric     response.PutChar(';');
18310b57cec5SDimitry Andric   }
18320b57cec5SDimitry Andric 
18330b57cec5SDimitry Andric   if (reg_info->dynamic_size_dwarf_expr_bytes) {
18340b57cec5SDimitry Andric     const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len;
18350b57cec5SDimitry Andric     response.PutCString("dynamic_size_dwarf_expr_bytes:");
18360b57cec5SDimitry Andric     for (uint32_t i = 0; i < dwarf_opcode_len; ++i)
18370b57cec5SDimitry Andric       response.PutHex8(reg_info->dynamic_size_dwarf_expr_bytes[i]);
18380b57cec5SDimitry Andric     response.PutChar(';');
18390b57cec5SDimitry Andric   }
18400b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
18410b57cec5SDimitry Andric }
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
18440b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
18450b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
18460b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
18470b57cec5SDimitry Andric 
18480b57cec5SDimitry Andric   // Fail if we don't have a current process.
18490b57cec5SDimitry Andric   if (!m_debugged_process_up ||
18500b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
18510b57cec5SDimitry Andric     LLDB_LOG(log, "no process ({0}), returning OK",
18520b57cec5SDimitry Andric              m_debugged_process_up ? "invalid process id"
18530b57cec5SDimitry Andric                                    : "null m_debugged_process_up");
18540b57cec5SDimitry Andric     return SendOKResponse();
18550b57cec5SDimitry Andric   }
18560b57cec5SDimitry Andric 
18570b57cec5SDimitry Andric   StreamGDBRemote response;
18580b57cec5SDimitry Andric   response.PutChar('m');
18590b57cec5SDimitry Andric 
18600b57cec5SDimitry Andric   LLDB_LOG(log, "starting thread iteration");
18610b57cec5SDimitry Andric   NativeThreadProtocol *thread;
18620b57cec5SDimitry Andric   uint32_t thread_index;
18630b57cec5SDimitry Andric   for (thread_index = 0,
18640b57cec5SDimitry Andric       thread = m_debugged_process_up->GetThreadAtIndex(thread_index);
18650b57cec5SDimitry Andric        thread; ++thread_index,
18660b57cec5SDimitry Andric       thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) {
18670b57cec5SDimitry Andric     LLDB_LOG(log, "iterated thread {0}(tid={2})", thread_index,
18680b57cec5SDimitry Andric              thread->GetID());
18690b57cec5SDimitry Andric     if (thread_index > 0)
18700b57cec5SDimitry Andric       response.PutChar(',');
18710b57cec5SDimitry Andric     response.Printf("%" PRIx64, thread->GetID());
18720b57cec5SDimitry Andric   }
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric   LLDB_LOG(log, "finished thread iteration");
18750b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
18760b57cec5SDimitry Andric }
18770b57cec5SDimitry Andric 
18780b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
18790b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo(
18800b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
18810b57cec5SDimitry Andric   // FIXME for now we return the full thread list in the initial packet and
18820b57cec5SDimitry Andric   // always do nothing here.
18830b57cec5SDimitry Andric   return SendPacketNoLock("l");
18840b57cec5SDimitry Andric }
18850b57cec5SDimitry Andric 
18860b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
18870b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_g(StringExtractorGDBRemote &packet) {
18880b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric   // Move past packet name.
18910b57cec5SDimitry Andric   packet.SetFilePos(strlen("g"));
18920b57cec5SDimitry Andric 
18930b57cec5SDimitry Andric   // Get the thread to use.
18940b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
18950b57cec5SDimitry Andric   if (!thread) {
18960b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no thread available");
18970b57cec5SDimitry Andric     return SendErrorResponse(0x15);
18980b57cec5SDimitry Andric   }
18990b57cec5SDimitry Andric 
19000b57cec5SDimitry Andric   // Get the thread's register context.
19010b57cec5SDimitry Andric   NativeRegisterContext &reg_ctx = thread->GetRegisterContext();
19020b57cec5SDimitry Andric 
19030b57cec5SDimitry Andric   std::vector<uint8_t> regs_buffer;
19040b57cec5SDimitry Andric   for (uint32_t reg_num = 0; reg_num < reg_ctx.GetUserRegisterCount();
19050b57cec5SDimitry Andric        ++reg_num) {
19060b57cec5SDimitry Andric     const RegisterInfo *reg_info = reg_ctx.GetRegisterInfoAtIndex(reg_num);
19070b57cec5SDimitry Andric 
19080b57cec5SDimitry Andric     if (reg_info == nullptr) {
19090b57cec5SDimitry Andric       LLDB_LOG(log, "failed to get register info for register index {0}",
19100b57cec5SDimitry Andric                reg_num);
19110b57cec5SDimitry Andric       return SendErrorResponse(0x15);
19120b57cec5SDimitry Andric     }
19130b57cec5SDimitry Andric 
19140b57cec5SDimitry Andric     if (reg_info->value_regs != nullptr)
19150b57cec5SDimitry Andric       continue; // skip registers that are contained in other registers
19160b57cec5SDimitry Andric 
19170b57cec5SDimitry Andric     RegisterValue reg_value;
19180b57cec5SDimitry Andric     Status error = reg_ctx.ReadRegister(reg_info, reg_value);
19190b57cec5SDimitry Andric     if (error.Fail()) {
19200b57cec5SDimitry Andric       LLDB_LOG(log, "failed to read register at index {0}", reg_num);
19210b57cec5SDimitry Andric       return SendErrorResponse(0x15);
19220b57cec5SDimitry Andric     }
19230b57cec5SDimitry Andric 
19240b57cec5SDimitry Andric     if (reg_info->byte_offset + reg_info->byte_size >= regs_buffer.size())
19250b57cec5SDimitry Andric       // Resize the buffer to guarantee it can store the register offsetted
19260b57cec5SDimitry Andric       // data.
19270b57cec5SDimitry Andric       regs_buffer.resize(reg_info->byte_offset + reg_info->byte_size);
19280b57cec5SDimitry Andric 
19290b57cec5SDimitry Andric     // Copy the register offsetted data to the buffer.
19300b57cec5SDimitry Andric     memcpy(regs_buffer.data() + reg_info->byte_offset, reg_value.GetBytes(),
19310b57cec5SDimitry Andric            reg_info->byte_size);
19320b57cec5SDimitry Andric   }
19330b57cec5SDimitry Andric 
19340b57cec5SDimitry Andric   // Write the response.
19350b57cec5SDimitry Andric   StreamGDBRemote response;
19360b57cec5SDimitry Andric   response.PutBytesAsRawHex8(regs_buffer.data(), regs_buffer.size());
19370b57cec5SDimitry Andric 
19380b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
19390b57cec5SDimitry Andric }
19400b57cec5SDimitry Andric 
19410b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
19420b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
19430b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
19440b57cec5SDimitry Andric 
19450b57cec5SDimitry Andric   // Parse out the register number from the request.
19460b57cec5SDimitry Andric   packet.SetFilePos(strlen("p"));
19470b57cec5SDimitry Andric   const uint32_t reg_index =
19480b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
19490b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max()) {
19509dba64beSDimitry Andric     LLDB_LOGF(log,
19519dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
19520b57cec5SDimitry Andric               "parse register number from request \"%s\"",
19539dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
19540b57cec5SDimitry Andric     return SendErrorResponse(0x15);
19550b57cec5SDimitry Andric   }
19560b57cec5SDimitry Andric 
19570b57cec5SDimitry Andric   // Get the thread to use.
19580b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
19590b57cec5SDimitry Andric   if (!thread) {
19600b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no thread available");
19610b57cec5SDimitry Andric     return SendErrorResponse(0x15);
19620b57cec5SDimitry Andric   }
19630b57cec5SDimitry Andric 
19640b57cec5SDimitry Andric   // Get the thread's register context.
19650b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
19660b57cec5SDimitry Andric 
19670b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
19680b57cec5SDimitry Andric   // the register set.
19690b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount()) {
19709dba64beSDimitry Andric     LLDB_LOGF(log,
19719dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
19720b57cec5SDimitry Andric               "register %" PRIu32 " beyond register count %" PRIu32,
19739dba64beSDimitry Andric               __FUNCTION__, reg_index, reg_context.GetUserRegisterCount());
19740b57cec5SDimitry Andric     return SendErrorResponse(0x15);
19750b57cec5SDimitry Andric   }
19760b57cec5SDimitry Andric 
19770b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
19780b57cec5SDimitry Andric   if (!reg_info) {
19799dba64beSDimitry Andric     LLDB_LOGF(log,
19809dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
19810b57cec5SDimitry Andric               "register %" PRIu32 " returned NULL",
19820b57cec5SDimitry Andric               __FUNCTION__, reg_index);
19830b57cec5SDimitry Andric     return SendErrorResponse(0x15);
19840b57cec5SDimitry Andric   }
19850b57cec5SDimitry Andric 
19860b57cec5SDimitry Andric   // Build the reginfos response.
19870b57cec5SDimitry Andric   StreamGDBRemote response;
19880b57cec5SDimitry Andric 
19890b57cec5SDimitry Andric   // Retrieve the value
19900b57cec5SDimitry Andric   RegisterValue reg_value;
19910b57cec5SDimitry Andric   Status error = reg_context.ReadRegister(reg_info, reg_value);
19920b57cec5SDimitry Andric   if (error.Fail()) {
19939dba64beSDimitry Andric     LLDB_LOGF(log,
19949dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, read of "
19950b57cec5SDimitry Andric               "requested register %" PRIu32 " (%s) failed: %s",
19960b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_info->name, error.AsCString());
19970b57cec5SDimitry Andric     return SendErrorResponse(0x15);
19980b57cec5SDimitry Andric   }
19990b57cec5SDimitry Andric 
20000b57cec5SDimitry Andric   const uint8_t *const data =
2001480093f4SDimitry Andric       static_cast<const uint8_t *>(reg_value.GetBytes());
20020b57cec5SDimitry Andric   if (!data) {
20039dba64beSDimitry Andric     LLDB_LOGF(log,
20049dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to get data "
20050b57cec5SDimitry Andric               "bytes from requested register %" PRIu32,
20060b57cec5SDimitry Andric               __FUNCTION__, reg_index);
20070b57cec5SDimitry Andric     return SendErrorResponse(0x15);
20080b57cec5SDimitry Andric   }
20090b57cec5SDimitry Andric 
20100b57cec5SDimitry Andric   // FIXME flip as needed to get data in big/little endian format for this host.
20110b57cec5SDimitry Andric   for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i)
20120b57cec5SDimitry Andric     response.PutHex8(data[i]);
20130b57cec5SDimitry Andric 
20140b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
20150b57cec5SDimitry Andric }
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
20180b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
20190b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric   // Ensure there is more content.
20220b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
20230b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Empty P packet");
20240b57cec5SDimitry Andric 
20250b57cec5SDimitry Andric   // Parse out the register number from the request.
20260b57cec5SDimitry Andric   packet.SetFilePos(strlen("P"));
20270b57cec5SDimitry Andric   const uint32_t reg_index =
20280b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
20290b57cec5SDimitry Andric   if (reg_index == std::numeric_limits<uint32_t>::max()) {
20309dba64beSDimitry Andric     LLDB_LOGF(log,
20319dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
20320b57cec5SDimitry Andric               "parse register number from request \"%s\"",
20339dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
20340b57cec5SDimitry Andric     return SendErrorResponse(0x29);
20350b57cec5SDimitry Andric   }
20360b57cec5SDimitry Andric 
20370b57cec5SDimitry Andric   // Note debugserver would send an E30 here.
20380b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '='))
20390b57cec5SDimitry Andric     return SendIllFormedResponse(
20400b57cec5SDimitry Andric         packet, "P packet missing '=' char after register number");
20410b57cec5SDimitry Andric 
20420b57cec5SDimitry Andric   // Parse out the value.
20435ffd83dbSDimitry Andric   uint8_t reg_bytes[RegisterValue::kMaxRegisterByteSize];
20440b57cec5SDimitry Andric   size_t reg_size = packet.GetHexBytesAvail(reg_bytes);
20450b57cec5SDimitry Andric 
20460b57cec5SDimitry Andric   // Get the thread to use.
20470b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
20480b57cec5SDimitry Andric   if (!thread) {
20499dba64beSDimitry Andric     LLDB_LOGF(log,
20509dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, no thread "
20510b57cec5SDimitry Andric               "available (thread index 0)",
20520b57cec5SDimitry Andric               __FUNCTION__);
20530b57cec5SDimitry Andric     return SendErrorResponse(0x28);
20540b57cec5SDimitry Andric   }
20550b57cec5SDimitry Andric 
20560b57cec5SDimitry Andric   // Get the thread's register context.
20570b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
20580b57cec5SDimitry Andric   const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index);
20590b57cec5SDimitry Andric   if (!reg_info) {
20609dba64beSDimitry Andric     LLDB_LOGF(log,
20619dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
20620b57cec5SDimitry Andric               "register %" PRIu32 " returned NULL",
20630b57cec5SDimitry Andric               __FUNCTION__, reg_index);
20640b57cec5SDimitry Andric     return SendErrorResponse(0x48);
20650b57cec5SDimitry Andric   }
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric   // Return the end of registers response if we've iterated one past the end of
20680b57cec5SDimitry Andric   // the register set.
20690b57cec5SDimitry Andric   if (reg_index >= reg_context.GetUserRegisterCount()) {
20709dba64beSDimitry Andric     LLDB_LOGF(log,
20719dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, requested "
20720b57cec5SDimitry Andric               "register %" PRIu32 " beyond register count %" PRIu32,
20730b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_context.GetUserRegisterCount());
20740b57cec5SDimitry Andric     return SendErrorResponse(0x47);
20750b57cec5SDimitry Andric   }
20760b57cec5SDimitry Andric 
20770b57cec5SDimitry Andric   // The dwarf expression are evaluate on host site which may cause register
20780b57cec5SDimitry Andric   // size to change Hence the reg_size may not be same as reg_info->bytes_size
20790b57cec5SDimitry Andric   if ((reg_size != reg_info->byte_size) &&
20800b57cec5SDimitry Andric       !(reg_info->dynamic_size_dwarf_expr_bytes)) {
20810b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "P packet register size is incorrect");
20820b57cec5SDimitry Andric   }
20830b57cec5SDimitry Andric 
20840b57cec5SDimitry Andric   // Build the reginfos response.
20850b57cec5SDimitry Andric   StreamGDBRemote response;
20860b57cec5SDimitry Andric 
20870b57cec5SDimitry Andric   RegisterValue reg_value(
20880b57cec5SDimitry Andric       reg_bytes, reg_size,
20890b57cec5SDimitry Andric       m_debugged_process_up->GetArchitecture().GetByteOrder());
20900b57cec5SDimitry Andric   Status error = reg_context.WriteRegister(reg_info, reg_value);
20910b57cec5SDimitry Andric   if (error.Fail()) {
20929dba64beSDimitry Andric     LLDB_LOGF(log,
20939dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, write of "
20940b57cec5SDimitry Andric               "requested register %" PRIu32 " (%s) failed: %s",
20950b57cec5SDimitry Andric               __FUNCTION__, reg_index, reg_info->name, error.AsCString());
20960b57cec5SDimitry Andric     return SendErrorResponse(0x32);
20970b57cec5SDimitry Andric   }
20980b57cec5SDimitry Andric 
20990b57cec5SDimitry Andric   return SendOKResponse();
21000b57cec5SDimitry Andric }
21010b57cec5SDimitry Andric 
21020b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
21030b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
21040b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
21050b57cec5SDimitry Andric 
21060b57cec5SDimitry Andric   // Fail if we don't have a current process.
21070b57cec5SDimitry Andric   if (!m_debugged_process_up ||
21080b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
21099dba64beSDimitry Andric     LLDB_LOGF(
21109dba64beSDimitry Andric         log,
21110b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
21120b57cec5SDimitry Andric         __FUNCTION__);
21130b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21140b57cec5SDimitry Andric   }
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric   // Parse out which variant of $H is requested.
21170b57cec5SDimitry Andric   packet.SetFilePos(strlen("H"));
21180b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1) {
21199dba64beSDimitry Andric     LLDB_LOGF(log,
21209dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, H command "
21210b57cec5SDimitry Andric               "missing {g,c} variant",
21220b57cec5SDimitry Andric               __FUNCTION__);
21230b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "H command missing {g,c} variant");
21240b57cec5SDimitry Andric   }
21250b57cec5SDimitry Andric 
21260b57cec5SDimitry Andric   const char h_variant = packet.GetChar();
21270b57cec5SDimitry Andric   switch (h_variant) {
21280b57cec5SDimitry Andric   case 'g':
21290b57cec5SDimitry Andric     break;
21300b57cec5SDimitry Andric 
21310b57cec5SDimitry Andric   case 'c':
21320b57cec5SDimitry Andric     break;
21330b57cec5SDimitry Andric 
21340b57cec5SDimitry Andric   default:
21359dba64beSDimitry Andric     LLDB_LOGF(
21369dba64beSDimitry Andric         log,
21370b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c",
21380b57cec5SDimitry Andric         __FUNCTION__, h_variant);
21390b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
21400b57cec5SDimitry Andric                                  "H variant unsupported, should be c or g");
21410b57cec5SDimitry Andric   }
21420b57cec5SDimitry Andric 
21430b57cec5SDimitry Andric   // Parse out the thread number.
21440b57cec5SDimitry Andric   // FIXME return a parse success/fail value.  All values are valid here.
21450b57cec5SDimitry Andric   const lldb::tid_t tid =
21460b57cec5SDimitry Andric       packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max());
21470b57cec5SDimitry Andric 
21480b57cec5SDimitry Andric   // Ensure we have the given thread when not specifying -1 (all threads) or 0
21490b57cec5SDimitry Andric   // (any thread).
21500b57cec5SDimitry Andric   if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
21510b57cec5SDimitry Andric     NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
21520b57cec5SDimitry Andric     if (!thread) {
21539dba64beSDimitry Andric       LLDB_LOGF(log,
21549dba64beSDimitry Andric                 "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
21550b57cec5SDimitry Andric                 " not found",
21560b57cec5SDimitry Andric                 __FUNCTION__, tid);
21570b57cec5SDimitry Andric       return SendErrorResponse(0x15);
21580b57cec5SDimitry Andric     }
21590b57cec5SDimitry Andric   }
21600b57cec5SDimitry Andric 
21610b57cec5SDimitry Andric   // Now switch the given thread type.
21620b57cec5SDimitry Andric   switch (h_variant) {
21630b57cec5SDimitry Andric   case 'g':
21640b57cec5SDimitry Andric     SetCurrentThreadID(tid);
21650b57cec5SDimitry Andric     break;
21660b57cec5SDimitry Andric 
21670b57cec5SDimitry Andric   case 'c':
21680b57cec5SDimitry Andric     SetContinueThreadID(tid);
21690b57cec5SDimitry Andric     break;
21700b57cec5SDimitry Andric 
21710b57cec5SDimitry Andric   default:
21720b57cec5SDimitry Andric     assert(false && "unsupported $H variant - shouldn't get here");
21730b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
21740b57cec5SDimitry Andric                                  "H variant unsupported, should be c or g");
21750b57cec5SDimitry Andric   }
21760b57cec5SDimitry Andric 
21770b57cec5SDimitry Andric   return SendOKResponse();
21780b57cec5SDimitry Andric }
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
21810b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
21820b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
21830b57cec5SDimitry Andric 
21840b57cec5SDimitry Andric   // Fail if we don't have a current process.
21850b57cec5SDimitry Andric   if (!m_debugged_process_up ||
21860b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
21879dba64beSDimitry Andric     LLDB_LOGF(
21889dba64beSDimitry Andric         log,
21890b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
21900b57cec5SDimitry Andric         __FUNCTION__);
21910b57cec5SDimitry Andric     return SendErrorResponse(0x15);
21920b57cec5SDimitry Andric   }
21930b57cec5SDimitry Andric 
21940b57cec5SDimitry Andric   packet.SetFilePos(::strlen("I"));
21950b57cec5SDimitry Andric   uint8_t tmp[4096];
21960b57cec5SDimitry Andric   for (;;) {
21970b57cec5SDimitry Andric     size_t read = packet.GetHexBytesAvail(tmp);
21980b57cec5SDimitry Andric     if (read == 0) {
21990b57cec5SDimitry Andric       break;
22000b57cec5SDimitry Andric     }
22010b57cec5SDimitry Andric     // write directly to stdin *this might block if stdin buffer is full*
22020b57cec5SDimitry Andric     // TODO: enqueue this block in circular buffer and send window size to
22030b57cec5SDimitry Andric     // remote host
22040b57cec5SDimitry Andric     ConnectionStatus status;
22050b57cec5SDimitry Andric     Status error;
22060b57cec5SDimitry Andric     m_stdio_communication.Write(tmp, read, status, &error);
22070b57cec5SDimitry Andric     if (error.Fail()) {
22080b57cec5SDimitry Andric       return SendErrorResponse(0x15);
22090b57cec5SDimitry Andric     }
22100b57cec5SDimitry Andric   }
22110b57cec5SDimitry Andric 
22120b57cec5SDimitry Andric   return SendOKResponse();
22130b57cec5SDimitry Andric }
22140b57cec5SDimitry Andric 
22150b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
22160b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_interrupt(
22170b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
22180b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
22190b57cec5SDimitry Andric 
22200b57cec5SDimitry Andric   // Fail if we don't have a current process.
22210b57cec5SDimitry Andric   if (!m_debugged_process_up ||
22220b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
22230b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
22240b57cec5SDimitry Andric     return SendErrorResponse(0x15);
22250b57cec5SDimitry Andric   }
22260b57cec5SDimitry Andric 
22270b57cec5SDimitry Andric   // Interrupt the process.
22280b57cec5SDimitry Andric   Status error = m_debugged_process_up->Interrupt();
22290b57cec5SDimitry Andric   if (error.Fail()) {
22300b57cec5SDimitry Andric     LLDB_LOG(log, "failed for process {0}: {1}", m_debugged_process_up->GetID(),
22310b57cec5SDimitry Andric              error);
22320b57cec5SDimitry Andric     return SendErrorResponse(GDBRemoteServerError::eErrorResume);
22330b57cec5SDimitry Andric   }
22340b57cec5SDimitry Andric 
22350b57cec5SDimitry Andric   LLDB_LOG(log, "stopped process {0}", m_debugged_process_up->GetID());
22360b57cec5SDimitry Andric 
22370b57cec5SDimitry Andric   // No response required from stop all.
22380b57cec5SDimitry Andric   return PacketResult::Success;
22390b57cec5SDimitry Andric }
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
22420b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_memory_read(
22430b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
22440b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
22450b57cec5SDimitry Andric 
22460b57cec5SDimitry Andric   if (!m_debugged_process_up ||
22470b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
22489dba64beSDimitry Andric     LLDB_LOGF(
22499dba64beSDimitry Andric         log,
22500b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
22510b57cec5SDimitry Andric         __FUNCTION__);
22520b57cec5SDimitry Andric     return SendErrorResponse(0x15);
22530b57cec5SDimitry Andric   }
22540b57cec5SDimitry Andric 
22550b57cec5SDimitry Andric   // Parse out the memory address.
22560b57cec5SDimitry Andric   packet.SetFilePos(strlen("m"));
22570b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
22580b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short m packet");
22590b57cec5SDimitry Andric 
22600b57cec5SDimitry Andric   // Read the address.  Punting on validation.
22610b57cec5SDimitry Andric   // FIXME replace with Hex U64 read with no default value that fails on failed
22620b57cec5SDimitry Andric   // read.
22630b57cec5SDimitry Andric   const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
22640b57cec5SDimitry Andric 
22650b57cec5SDimitry Andric   // Validate comma.
22660b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
22670b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Comma sep missing in m packet");
22680b57cec5SDimitry Andric 
22690b57cec5SDimitry Andric   // Get # bytes to read.
22700b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
22710b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Length missing in m packet");
22720b57cec5SDimitry Andric 
22730b57cec5SDimitry Andric   const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
22740b57cec5SDimitry Andric   if (byte_count == 0) {
22759dba64beSDimitry Andric     LLDB_LOGF(log,
22769dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s nothing to read: "
22770b57cec5SDimitry Andric               "zero-length packet",
22780b57cec5SDimitry Andric               __FUNCTION__);
22790b57cec5SDimitry Andric     return SendOKResponse();
22800b57cec5SDimitry Andric   }
22810b57cec5SDimitry Andric 
22820b57cec5SDimitry Andric   // Allocate the response buffer.
22830b57cec5SDimitry Andric   std::string buf(byte_count, '\0');
22840b57cec5SDimitry Andric   if (buf.empty())
22850b57cec5SDimitry Andric     return SendErrorResponse(0x78);
22860b57cec5SDimitry Andric 
22870b57cec5SDimitry Andric   // Retrieve the process memory.
22880b57cec5SDimitry Andric   size_t bytes_read = 0;
22890b57cec5SDimitry Andric   Status error = m_debugged_process_up->ReadMemoryWithoutTrap(
22900b57cec5SDimitry Andric       read_addr, &buf[0], byte_count, bytes_read);
22910b57cec5SDimitry Andric   if (error.Fail()) {
22929dba64beSDimitry Andric     LLDB_LOGF(log,
22939dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
22940b57cec5SDimitry Andric               " mem 0x%" PRIx64 ": failed to read. Error: %s",
22950b57cec5SDimitry Andric               __FUNCTION__, m_debugged_process_up->GetID(), read_addr,
22960b57cec5SDimitry Andric               error.AsCString());
22970b57cec5SDimitry Andric     return SendErrorResponse(0x08);
22980b57cec5SDimitry Andric   }
22990b57cec5SDimitry Andric 
23000b57cec5SDimitry Andric   if (bytes_read == 0) {
23019dba64beSDimitry Andric     LLDB_LOGF(log,
23029dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
23030b57cec5SDimitry Andric               " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes",
23040b57cec5SDimitry Andric               __FUNCTION__, m_debugged_process_up->GetID(), read_addr,
23050b57cec5SDimitry Andric               byte_count);
23060b57cec5SDimitry Andric     return SendErrorResponse(0x08);
23070b57cec5SDimitry Andric   }
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric   StreamGDBRemote response;
23100b57cec5SDimitry Andric   packet.SetFilePos(0);
23110b57cec5SDimitry Andric   char kind = packet.GetChar('?');
23120b57cec5SDimitry Andric   if (kind == 'x')
23130b57cec5SDimitry Andric     response.PutEscapedBytes(buf.data(), byte_count);
23140b57cec5SDimitry Andric   else {
23150b57cec5SDimitry Andric     assert(kind == 'm');
23160b57cec5SDimitry Andric     for (size_t i = 0; i < bytes_read; ++i)
23170b57cec5SDimitry Andric       response.PutHex8(buf[i]);
23180b57cec5SDimitry Andric   }
23190b57cec5SDimitry Andric 
23200b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
23210b57cec5SDimitry Andric }
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
23240b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
23250b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
23260b57cec5SDimitry Andric 
23270b57cec5SDimitry Andric   if (!m_debugged_process_up ||
23280b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
23299dba64beSDimitry Andric     LLDB_LOGF(
23309dba64beSDimitry Andric         log,
23310b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
23320b57cec5SDimitry Andric         __FUNCTION__);
23330b57cec5SDimitry Andric     return SendErrorResponse(0x15);
23340b57cec5SDimitry Andric   }
23350b57cec5SDimitry Andric 
23360b57cec5SDimitry Andric   // Parse out the memory address.
23370b57cec5SDimitry Andric   packet.SetFilePos(strlen("M"));
23380b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
23390b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short M packet");
23400b57cec5SDimitry Andric 
23410b57cec5SDimitry Andric   // Read the address.  Punting on validation.
23420b57cec5SDimitry Andric   // FIXME replace with Hex U64 read with no default value that fails on failed
23430b57cec5SDimitry Andric   // read.
23440b57cec5SDimitry Andric   const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0);
23450b57cec5SDimitry Andric 
23460b57cec5SDimitry Andric   // Validate comma.
23470b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
23480b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Comma sep missing in M packet");
23490b57cec5SDimitry Andric 
23500b57cec5SDimitry Andric   // Get # bytes to read.
23510b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
23520b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Length missing in M packet");
23530b57cec5SDimitry Andric 
23540b57cec5SDimitry Andric   const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
23550b57cec5SDimitry Andric   if (byte_count == 0) {
23560b57cec5SDimitry Andric     LLDB_LOG(log, "nothing to write: zero-length packet");
23570b57cec5SDimitry Andric     return PacketResult::Success;
23580b57cec5SDimitry Andric   }
23590b57cec5SDimitry Andric 
23600b57cec5SDimitry Andric   // Validate colon.
23610b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':'))
23620b57cec5SDimitry Andric     return SendIllFormedResponse(
23630b57cec5SDimitry Andric         packet, "Comma sep missing in M packet after byte length");
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric   // Allocate the conversion buffer.
23660b57cec5SDimitry Andric   std::vector<uint8_t> buf(byte_count, 0);
23670b57cec5SDimitry Andric   if (buf.empty())
23680b57cec5SDimitry Andric     return SendErrorResponse(0x78);
23690b57cec5SDimitry Andric 
23700b57cec5SDimitry Andric   // Convert the hex memory write contents to bytes.
23710b57cec5SDimitry Andric   StreamGDBRemote response;
23720b57cec5SDimitry Andric   const uint64_t convert_count = packet.GetHexBytes(buf, 0);
23730b57cec5SDimitry Andric   if (convert_count != byte_count) {
23740b57cec5SDimitry Andric     LLDB_LOG(log,
23750b57cec5SDimitry Andric              "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} "
23760b57cec5SDimitry Andric              "to convert.",
23770b57cec5SDimitry Andric              m_debugged_process_up->GetID(), write_addr, byte_count,
23780b57cec5SDimitry Andric              convert_count);
23790b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "M content byte length specified did "
23800b57cec5SDimitry Andric                                          "not match hex-encoded content "
23810b57cec5SDimitry Andric                                          "length");
23820b57cec5SDimitry Andric   }
23830b57cec5SDimitry Andric 
23840b57cec5SDimitry Andric   // Write the process memory.
23850b57cec5SDimitry Andric   size_t bytes_written = 0;
23860b57cec5SDimitry Andric   Status error = m_debugged_process_up->WriteMemory(write_addr, &buf[0],
23870b57cec5SDimitry Andric                                                     byte_count, bytes_written);
23880b57cec5SDimitry Andric   if (error.Fail()) {
23890b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}",
23900b57cec5SDimitry Andric              m_debugged_process_up->GetID(), write_addr, error);
23910b57cec5SDimitry Andric     return SendErrorResponse(0x09);
23920b57cec5SDimitry Andric   }
23930b57cec5SDimitry Andric 
23940b57cec5SDimitry Andric   if (bytes_written == 0) {
23950b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes",
23960b57cec5SDimitry Andric              m_debugged_process_up->GetID(), write_addr, byte_count);
23970b57cec5SDimitry Andric     return SendErrorResponse(0x09);
23980b57cec5SDimitry Andric   }
23990b57cec5SDimitry Andric 
24000b57cec5SDimitry Andric   return SendOKResponse();
24010b57cec5SDimitry Andric }
24020b57cec5SDimitry Andric 
24030b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
24040b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
24050b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
24060b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
24070b57cec5SDimitry Andric 
24080b57cec5SDimitry Andric   // Currently only the NativeProcessProtocol knows if it can handle a
24090b57cec5SDimitry Andric   // qMemoryRegionInfoSupported request, but we're not guaranteed to be
24100b57cec5SDimitry Andric   // attached to a process.  For now we'll assume the client only asks this
24110b57cec5SDimitry Andric   // when a process is being debugged.
24120b57cec5SDimitry Andric 
24130b57cec5SDimitry Andric   // Ensure we have a process running; otherwise, we can't figure this out
24140b57cec5SDimitry Andric   // since we won't have a NativeProcessProtocol.
24150b57cec5SDimitry Andric   if (!m_debugged_process_up ||
24160b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
24179dba64beSDimitry Andric     LLDB_LOGF(
24189dba64beSDimitry Andric         log,
24190b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
24200b57cec5SDimitry Andric         __FUNCTION__);
24210b57cec5SDimitry Andric     return SendErrorResponse(0x15);
24220b57cec5SDimitry Andric   }
24230b57cec5SDimitry Andric 
24240b57cec5SDimitry Andric   // Test if we can get any region back when asking for the region around NULL.
24250b57cec5SDimitry Andric   MemoryRegionInfo region_info;
24260b57cec5SDimitry Andric   const Status error =
24270b57cec5SDimitry Andric       m_debugged_process_up->GetMemoryRegionInfo(0, region_info);
24280b57cec5SDimitry Andric   if (error.Fail()) {
24290b57cec5SDimitry Andric     // We don't support memory region info collection for this
24300b57cec5SDimitry Andric     // NativeProcessProtocol.
24310b57cec5SDimitry Andric     return SendUnimplementedResponse("");
24320b57cec5SDimitry Andric   }
24330b57cec5SDimitry Andric 
24340b57cec5SDimitry Andric   return SendOKResponse();
24350b57cec5SDimitry Andric }
24360b57cec5SDimitry Andric 
24370b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
24380b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
24390b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
24400b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
24410b57cec5SDimitry Andric 
24420b57cec5SDimitry Andric   // Ensure we have a process.
24430b57cec5SDimitry Andric   if (!m_debugged_process_up ||
24440b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
24459dba64beSDimitry Andric     LLDB_LOGF(
24469dba64beSDimitry Andric         log,
24470b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
24480b57cec5SDimitry Andric         __FUNCTION__);
24490b57cec5SDimitry Andric     return SendErrorResponse(0x15);
24500b57cec5SDimitry Andric   }
24510b57cec5SDimitry Andric 
24520b57cec5SDimitry Andric   // Parse out the memory address.
24530b57cec5SDimitry Andric   packet.SetFilePos(strlen("qMemoryRegionInfo:"));
24540b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
24550b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet");
24560b57cec5SDimitry Andric 
24570b57cec5SDimitry Andric   // Read the address.  Punting on validation.
24580b57cec5SDimitry Andric   const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
24590b57cec5SDimitry Andric 
24600b57cec5SDimitry Andric   StreamGDBRemote response;
24610b57cec5SDimitry Andric 
24620b57cec5SDimitry Andric   // Get the memory region info for the target address.
24630b57cec5SDimitry Andric   MemoryRegionInfo region_info;
24640b57cec5SDimitry Andric   const Status error =
24650b57cec5SDimitry Andric       m_debugged_process_up->GetMemoryRegionInfo(read_addr, region_info);
24660b57cec5SDimitry Andric   if (error.Fail()) {
24670b57cec5SDimitry Andric     // Return the error message.
24680b57cec5SDimitry Andric 
24690b57cec5SDimitry Andric     response.PutCString("error:");
24700b57cec5SDimitry Andric     response.PutStringAsRawHex8(error.AsCString());
24710b57cec5SDimitry Andric     response.PutChar(';');
24720b57cec5SDimitry Andric   } else {
24730b57cec5SDimitry Andric     // Range start and size.
24740b57cec5SDimitry Andric     response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";",
24750b57cec5SDimitry Andric                     region_info.GetRange().GetRangeBase(),
24760b57cec5SDimitry Andric                     region_info.GetRange().GetByteSize());
24770b57cec5SDimitry Andric 
24780b57cec5SDimitry Andric     // Permissions.
24790b57cec5SDimitry Andric     if (region_info.GetReadable() || region_info.GetWritable() ||
24800b57cec5SDimitry Andric         region_info.GetExecutable()) {
24810b57cec5SDimitry Andric       // Write permissions info.
24820b57cec5SDimitry Andric       response.PutCString("permissions:");
24830b57cec5SDimitry Andric 
24840b57cec5SDimitry Andric       if (region_info.GetReadable())
24850b57cec5SDimitry Andric         response.PutChar('r');
24860b57cec5SDimitry Andric       if (region_info.GetWritable())
24870b57cec5SDimitry Andric         response.PutChar('w');
24880b57cec5SDimitry Andric       if (region_info.GetExecutable())
24890b57cec5SDimitry Andric         response.PutChar('x');
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric       response.PutChar(';');
24920b57cec5SDimitry Andric     }
24930b57cec5SDimitry Andric 
24940b57cec5SDimitry Andric     // Name
24950b57cec5SDimitry Andric     ConstString name = region_info.GetName();
24960b57cec5SDimitry Andric     if (name) {
24970b57cec5SDimitry Andric       response.PutCString("name:");
24985ffd83dbSDimitry Andric       response.PutStringAsRawHex8(name.GetStringRef());
24990b57cec5SDimitry Andric       response.PutChar(';');
25000b57cec5SDimitry Andric     }
25010b57cec5SDimitry Andric   }
25020b57cec5SDimitry Andric 
25030b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
25040b57cec5SDimitry Andric }
25050b57cec5SDimitry Andric 
25060b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
25070b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
25080b57cec5SDimitry Andric   // Ensure we have a process.
25090b57cec5SDimitry Andric   if (!m_debugged_process_up ||
25100b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
25110b57cec5SDimitry Andric     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
25120b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
25130b57cec5SDimitry Andric     return SendErrorResponse(0x15);
25140b57cec5SDimitry Andric   }
25150b57cec5SDimitry Andric 
25160b57cec5SDimitry Andric   // Parse out software or hardware breakpoint or watchpoint requested.
25170b57cec5SDimitry Andric   packet.SetFilePos(strlen("Z"));
25180b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
25190b57cec5SDimitry Andric     return SendIllFormedResponse(
25200b57cec5SDimitry Andric         packet, "Too short Z packet, missing software/hardware specifier");
25210b57cec5SDimitry Andric 
25220b57cec5SDimitry Andric   bool want_breakpoint = true;
25230b57cec5SDimitry Andric   bool want_hardware = false;
25240b57cec5SDimitry Andric   uint32_t watch_flags = 0;
25250b57cec5SDimitry Andric 
25260b57cec5SDimitry Andric   const GDBStoppointType stoppoint_type =
25270b57cec5SDimitry Andric       GDBStoppointType(packet.GetS32(eStoppointInvalid));
25280b57cec5SDimitry Andric   switch (stoppoint_type) {
25290b57cec5SDimitry Andric   case eBreakpointSoftware:
25300b57cec5SDimitry Andric     want_hardware = false;
25310b57cec5SDimitry Andric     want_breakpoint = true;
25320b57cec5SDimitry Andric     break;
25330b57cec5SDimitry Andric   case eBreakpointHardware:
25340b57cec5SDimitry Andric     want_hardware = true;
25350b57cec5SDimitry Andric     want_breakpoint = true;
25360b57cec5SDimitry Andric     break;
25370b57cec5SDimitry Andric   case eWatchpointWrite:
25380b57cec5SDimitry Andric     watch_flags = 1;
25390b57cec5SDimitry Andric     want_hardware = true;
25400b57cec5SDimitry Andric     want_breakpoint = false;
25410b57cec5SDimitry Andric     break;
25420b57cec5SDimitry Andric   case eWatchpointRead:
25430b57cec5SDimitry Andric     watch_flags = 2;
25440b57cec5SDimitry Andric     want_hardware = true;
25450b57cec5SDimitry Andric     want_breakpoint = false;
25460b57cec5SDimitry Andric     break;
25470b57cec5SDimitry Andric   case eWatchpointReadWrite:
25480b57cec5SDimitry Andric     watch_flags = 3;
25490b57cec5SDimitry Andric     want_hardware = true;
25500b57cec5SDimitry Andric     want_breakpoint = false;
25510b57cec5SDimitry Andric     break;
25520b57cec5SDimitry Andric   case eStoppointInvalid:
25530b57cec5SDimitry Andric     return SendIllFormedResponse(
25540b57cec5SDimitry Andric         packet, "Z packet had invalid software/hardware specifier");
25550b57cec5SDimitry Andric   }
25560b57cec5SDimitry Andric 
25570b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
25580b57cec5SDimitry Andric     return SendIllFormedResponse(
25590b57cec5SDimitry Andric         packet, "Malformed Z packet, expecting comma after stoppoint type");
25600b57cec5SDimitry Andric 
25610b57cec5SDimitry Andric   // Parse out the stoppoint address.
25620b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
25630b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short Z packet, missing address");
25640b57cec5SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
25650b57cec5SDimitry Andric 
25660b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
25670b57cec5SDimitry Andric     return SendIllFormedResponse(
25680b57cec5SDimitry Andric         packet, "Malformed Z packet, expecting comma after address");
25690b57cec5SDimitry Andric 
25700b57cec5SDimitry Andric   // Parse out the stoppoint size (i.e. size hint for opcode size).
25710b57cec5SDimitry Andric   const uint32_t size =
25720b57cec5SDimitry Andric       packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
25730b57cec5SDimitry Andric   if (size == std::numeric_limits<uint32_t>::max())
25740b57cec5SDimitry Andric     return SendIllFormedResponse(
25750b57cec5SDimitry Andric         packet, "Malformed Z packet, failed to parse size argument");
25760b57cec5SDimitry Andric 
25770b57cec5SDimitry Andric   if (want_breakpoint) {
25780b57cec5SDimitry Andric     // Try to set the breakpoint.
25790b57cec5SDimitry Andric     const Status error =
25800b57cec5SDimitry Andric         m_debugged_process_up->SetBreakpoint(addr, size, want_hardware);
25810b57cec5SDimitry Andric     if (error.Success())
25820b57cec5SDimitry Andric       return SendOKResponse();
25830b57cec5SDimitry Andric     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
25840b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",
25850b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
25860b57cec5SDimitry Andric     return SendErrorResponse(0x09);
25870b57cec5SDimitry Andric   } else {
25880b57cec5SDimitry Andric     // Try to set the watchpoint.
25890b57cec5SDimitry Andric     const Status error = m_debugged_process_up->SetWatchpoint(
25900b57cec5SDimitry Andric         addr, size, watch_flags, want_hardware);
25910b57cec5SDimitry Andric     if (error.Success())
25920b57cec5SDimitry Andric       return SendOKResponse();
25930b57cec5SDimitry Andric     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
25940b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",
25950b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
25960b57cec5SDimitry Andric     return SendErrorResponse(0x09);
25970b57cec5SDimitry Andric   }
25980b57cec5SDimitry Andric }
25990b57cec5SDimitry Andric 
26000b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
26010b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
26020b57cec5SDimitry Andric   // Ensure we have a process.
26030b57cec5SDimitry Andric   if (!m_debugged_process_up ||
26040b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
26050b57cec5SDimitry Andric     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
26060b57cec5SDimitry Andric     LLDB_LOG(log, "failed, no process available");
26070b57cec5SDimitry Andric     return SendErrorResponse(0x15);
26080b57cec5SDimitry Andric   }
26090b57cec5SDimitry Andric 
26100b57cec5SDimitry Andric   // Parse out software or hardware breakpoint or watchpoint requested.
26110b57cec5SDimitry Andric   packet.SetFilePos(strlen("z"));
26120b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
26130b57cec5SDimitry Andric     return SendIllFormedResponse(
26140b57cec5SDimitry Andric         packet, "Too short z packet, missing software/hardware specifier");
26150b57cec5SDimitry Andric 
26160b57cec5SDimitry Andric   bool want_breakpoint = true;
26170b57cec5SDimitry Andric   bool want_hardware = false;
26180b57cec5SDimitry Andric 
26190b57cec5SDimitry Andric   const GDBStoppointType stoppoint_type =
26200b57cec5SDimitry Andric       GDBStoppointType(packet.GetS32(eStoppointInvalid));
26210b57cec5SDimitry Andric   switch (stoppoint_type) {
26220b57cec5SDimitry Andric   case eBreakpointHardware:
26230b57cec5SDimitry Andric     want_breakpoint = true;
26240b57cec5SDimitry Andric     want_hardware = true;
26250b57cec5SDimitry Andric     break;
26260b57cec5SDimitry Andric   case eBreakpointSoftware:
26270b57cec5SDimitry Andric     want_breakpoint = true;
26280b57cec5SDimitry Andric     break;
26290b57cec5SDimitry Andric   case eWatchpointWrite:
26300b57cec5SDimitry Andric     want_breakpoint = false;
26310b57cec5SDimitry Andric     break;
26320b57cec5SDimitry Andric   case eWatchpointRead:
26330b57cec5SDimitry Andric     want_breakpoint = false;
26340b57cec5SDimitry Andric     break;
26350b57cec5SDimitry Andric   case eWatchpointReadWrite:
26360b57cec5SDimitry Andric     want_breakpoint = false;
26370b57cec5SDimitry Andric     break;
26380b57cec5SDimitry Andric   default:
26390b57cec5SDimitry Andric     return SendIllFormedResponse(
26400b57cec5SDimitry Andric         packet, "z packet had invalid software/hardware specifier");
26410b57cec5SDimitry Andric   }
26420b57cec5SDimitry Andric 
26430b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
26440b57cec5SDimitry Andric     return SendIllFormedResponse(
26450b57cec5SDimitry Andric         packet, "Malformed z packet, expecting comma after stoppoint type");
26460b57cec5SDimitry Andric 
26470b57cec5SDimitry Andric   // Parse out the stoppoint address.
26480b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
26490b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Too short z packet, missing address");
26500b57cec5SDimitry Andric   const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
26510b57cec5SDimitry Andric 
26520b57cec5SDimitry Andric   if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
26530b57cec5SDimitry Andric     return SendIllFormedResponse(
26540b57cec5SDimitry Andric         packet, "Malformed z packet, expecting comma after address");
26550b57cec5SDimitry Andric 
26560b57cec5SDimitry Andric   /*
26570b57cec5SDimitry Andric   // Parse out the stoppoint size (i.e. size hint for opcode size).
26580b57cec5SDimitry Andric   const uint32_t size = packet.GetHexMaxU32 (false,
26590b57cec5SDimitry Andric   std::numeric_limits<uint32_t>::max ());
26600b57cec5SDimitry Andric   if (size == std::numeric_limits<uint32_t>::max ())
26610b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Malformed z packet, failed to parse
26620b57cec5SDimitry Andric   size argument");
26630b57cec5SDimitry Andric   */
26640b57cec5SDimitry Andric 
26650b57cec5SDimitry Andric   if (want_breakpoint) {
26660b57cec5SDimitry Andric     // Try to clear the breakpoint.
26670b57cec5SDimitry Andric     const Status error =
26680b57cec5SDimitry Andric         m_debugged_process_up->RemoveBreakpoint(addr, want_hardware);
26690b57cec5SDimitry Andric     if (error.Success())
26700b57cec5SDimitry Andric       return SendOKResponse();
26710b57cec5SDimitry Andric     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
26720b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",
26730b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
26740b57cec5SDimitry Andric     return SendErrorResponse(0x09);
26750b57cec5SDimitry Andric   } else {
26760b57cec5SDimitry Andric     // Try to clear the watchpoint.
26770b57cec5SDimitry Andric     const Status error = m_debugged_process_up->RemoveWatchpoint(addr);
26780b57cec5SDimitry Andric     if (error.Success())
26790b57cec5SDimitry Andric       return SendOKResponse();
26800b57cec5SDimitry Andric     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
26810b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",
26820b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
26830b57cec5SDimitry Andric     return SendErrorResponse(0x09);
26840b57cec5SDimitry Andric   }
26850b57cec5SDimitry Andric }
26860b57cec5SDimitry Andric 
26870b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
26880b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
26890b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
26900b57cec5SDimitry Andric 
26910b57cec5SDimitry Andric   // Ensure we have a process.
26920b57cec5SDimitry Andric   if (!m_debugged_process_up ||
26930b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
26949dba64beSDimitry Andric     LLDB_LOGF(
26959dba64beSDimitry Andric         log,
26960b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
26970b57cec5SDimitry Andric         __FUNCTION__);
26980b57cec5SDimitry Andric     return SendErrorResponse(0x32);
26990b57cec5SDimitry Andric   }
27000b57cec5SDimitry Andric 
27010b57cec5SDimitry Andric   // We first try to use a continue thread id.  If any one or any all set, use
27020b57cec5SDimitry Andric   // the current thread. Bail out if we don't have a thread id.
27030b57cec5SDimitry Andric   lldb::tid_t tid = GetContinueThreadID();
27040b57cec5SDimitry Andric   if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
27050b57cec5SDimitry Andric     tid = GetCurrentThreadID();
27060b57cec5SDimitry Andric   if (tid == LLDB_INVALID_THREAD_ID)
27070b57cec5SDimitry Andric     return SendErrorResponse(0x33);
27080b57cec5SDimitry Andric 
27090b57cec5SDimitry Andric   // Double check that we have such a thread.
27100b57cec5SDimitry Andric   // TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
27110b57cec5SDimitry Andric   NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid);
27120b57cec5SDimitry Andric   if (!thread)
27130b57cec5SDimitry Andric     return SendErrorResponse(0x33);
27140b57cec5SDimitry Andric 
27150b57cec5SDimitry Andric   // Create the step action for the given thread.
27169dba64beSDimitry Andric   ResumeAction action = {tid, eStateStepping, LLDB_INVALID_SIGNAL_NUMBER};
27170b57cec5SDimitry Andric 
27180b57cec5SDimitry Andric   // Setup the actions list.
27190b57cec5SDimitry Andric   ResumeActionList actions;
27200b57cec5SDimitry Andric   actions.Append(action);
27210b57cec5SDimitry Andric 
27220b57cec5SDimitry Andric   // All other threads stop while we're single stepping a thread.
27230b57cec5SDimitry Andric   actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
27240b57cec5SDimitry Andric   Status error = m_debugged_process_up->Resume(actions);
27250b57cec5SDimitry Andric   if (error.Fail()) {
27269dba64beSDimitry Andric     LLDB_LOGF(log,
27279dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
27280b57cec5SDimitry Andric               " tid %" PRIu64 " Resume() failed with error: %s",
27290b57cec5SDimitry Andric               __FUNCTION__, m_debugged_process_up->GetID(), tid,
27300b57cec5SDimitry Andric               error.AsCString());
27310b57cec5SDimitry Andric     return SendErrorResponse(0x49);
27320b57cec5SDimitry Andric   }
27330b57cec5SDimitry Andric 
27340b57cec5SDimitry Andric   // No response here - the stop or exit will come from the resulting action.
27350b57cec5SDimitry Andric   return PacketResult::Success;
27360b57cec5SDimitry Andric }
27370b57cec5SDimitry Andric 
27380b57cec5SDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
27395ffd83dbSDimitry Andric GDBRemoteCommunicationServerLLGS::BuildTargetXml() {
27405ffd83dbSDimitry Andric   // Ensure we have a thread.
27415ffd83dbSDimitry Andric   NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0);
27425ffd83dbSDimitry Andric   if (!thread)
27435ffd83dbSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
27445ffd83dbSDimitry Andric                                    "No thread available");
27455ffd83dbSDimitry Andric 
27465ffd83dbSDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
27475ffd83dbSDimitry Andric   // Get the register context for the first thread.
27485ffd83dbSDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
27495ffd83dbSDimitry Andric 
27505ffd83dbSDimitry Andric   StreamString response;
27515ffd83dbSDimitry Andric 
27525ffd83dbSDimitry Andric   response.Printf("<?xml version=\"1.0\"?>");
27535ffd83dbSDimitry Andric   response.Printf("<target version=\"1.0\">");
27545ffd83dbSDimitry Andric 
27555ffd83dbSDimitry Andric   response.Printf("<architecture>%s</architecture>",
27565ffd83dbSDimitry Andric                   m_debugged_process_up->GetArchitecture()
27575ffd83dbSDimitry Andric                       .GetTriple()
27585ffd83dbSDimitry Andric                       .getArchName()
27595ffd83dbSDimitry Andric                       .str()
27605ffd83dbSDimitry Andric                       .c_str());
27615ffd83dbSDimitry Andric 
27625ffd83dbSDimitry Andric   response.Printf("<feature>");
27635ffd83dbSDimitry Andric 
27645ffd83dbSDimitry Andric   const int registers_count = reg_context.GetUserRegisterCount();
27655ffd83dbSDimitry Andric   for (int reg_index = 0; reg_index < registers_count; reg_index++) {
27665ffd83dbSDimitry Andric     const RegisterInfo *reg_info =
27675ffd83dbSDimitry Andric         reg_context.GetRegisterInfoAtIndex(reg_index);
27685ffd83dbSDimitry Andric 
27695ffd83dbSDimitry Andric     if (!reg_info) {
27705ffd83dbSDimitry Andric       LLDB_LOGF(log,
27715ffd83dbSDimitry Andric                 "%s failed to get register info for register index %" PRIu32,
27725ffd83dbSDimitry Andric                 "target.xml", reg_index);
27735ffd83dbSDimitry Andric       continue;
27745ffd83dbSDimitry Andric     }
27755ffd83dbSDimitry Andric 
27765ffd83dbSDimitry Andric     response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 "\" offset=\"%" PRIu32
27775ffd83dbSDimitry Andric                     "\" regnum=\"%d\" ",
27785ffd83dbSDimitry Andric                     reg_info->name, reg_info->byte_size * 8,
27795ffd83dbSDimitry Andric                     reg_info->byte_offset, reg_index);
27805ffd83dbSDimitry Andric 
27815ffd83dbSDimitry Andric     if (reg_info->alt_name && reg_info->alt_name[0])
27825ffd83dbSDimitry Andric       response.Printf("altname=\"%s\" ", reg_info->alt_name);
27835ffd83dbSDimitry Andric 
27845ffd83dbSDimitry Andric     llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info);
27855ffd83dbSDimitry Andric     if (!encoding.empty())
27865ffd83dbSDimitry Andric       response << "encoding=\"" << encoding << "\" ";
27875ffd83dbSDimitry Andric 
27885ffd83dbSDimitry Andric     llvm::StringRef format = GetFormatNameOrEmpty(*reg_info);
27895ffd83dbSDimitry Andric     if (!format.empty())
27905ffd83dbSDimitry Andric       response << "format=\"" << format << "\" ";
27915ffd83dbSDimitry Andric 
27925ffd83dbSDimitry Andric     const char *const register_set_name =
27935ffd83dbSDimitry Andric         reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index);
27945ffd83dbSDimitry Andric     if (register_set_name)
27955ffd83dbSDimitry Andric       response << "group=\"" << register_set_name << "\" ";
27965ffd83dbSDimitry Andric 
27975ffd83dbSDimitry Andric     if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
27985ffd83dbSDimitry Andric         LLDB_INVALID_REGNUM)
27995ffd83dbSDimitry Andric       response.Printf("ehframe_regnum=\"%" PRIu32 "\" ",
28005ffd83dbSDimitry Andric                       reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
28015ffd83dbSDimitry Andric 
28025ffd83dbSDimitry Andric     if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] !=
28035ffd83dbSDimitry Andric         LLDB_INVALID_REGNUM)
28045ffd83dbSDimitry Andric       response.Printf("dwarf_regnum=\"%" PRIu32 "\" ",
28055ffd83dbSDimitry Andric                       reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
28065ffd83dbSDimitry Andric 
28075ffd83dbSDimitry Andric     llvm::StringRef kind_generic = GetKindGenericOrEmpty(*reg_info);
28085ffd83dbSDimitry Andric     if (!kind_generic.empty())
28095ffd83dbSDimitry Andric       response << "generic=\"" << kind_generic << "\" ";
28105ffd83dbSDimitry Andric 
28115ffd83dbSDimitry Andric     if (reg_info->value_regs &&
28125ffd83dbSDimitry Andric         reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
28135ffd83dbSDimitry Andric       response.PutCString("value_regnums=\"");
28145ffd83dbSDimitry Andric       CollectRegNums(reg_info->value_regs, response, false);
28155ffd83dbSDimitry Andric       response.Printf("\" ");
28165ffd83dbSDimitry Andric     }
28175ffd83dbSDimitry Andric 
28185ffd83dbSDimitry Andric     if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
28195ffd83dbSDimitry Andric       response.PutCString("invalidate_regnums=\"");
28205ffd83dbSDimitry Andric       CollectRegNums(reg_info->invalidate_regs, response, false);
28215ffd83dbSDimitry Andric       response.Printf("\" ");
28225ffd83dbSDimitry Andric     }
28235ffd83dbSDimitry Andric 
28245ffd83dbSDimitry Andric     if (reg_info->dynamic_size_dwarf_expr_bytes) {
28255ffd83dbSDimitry Andric       const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len;
28265ffd83dbSDimitry Andric       response.PutCString("dynamic_size_dwarf_expr_bytes=\"");
28275ffd83dbSDimitry Andric       for (uint32_t i = 0; i < dwarf_opcode_len; ++i)
28285ffd83dbSDimitry Andric         response.PutHex8(reg_info->dynamic_size_dwarf_expr_bytes[i]);
28295ffd83dbSDimitry Andric       response.Printf("\" ");
28305ffd83dbSDimitry Andric     }
28315ffd83dbSDimitry Andric 
28325ffd83dbSDimitry Andric     response.Printf("/>");
28335ffd83dbSDimitry Andric   }
28345ffd83dbSDimitry Andric 
28355ffd83dbSDimitry Andric   response.Printf("</feature>");
28365ffd83dbSDimitry Andric   response.Printf("</target>");
28375ffd83dbSDimitry Andric   return MemoryBuffer::getMemBufferCopy(response.GetString(), "target.xml");
28385ffd83dbSDimitry Andric }
28395ffd83dbSDimitry Andric 
28405ffd83dbSDimitry Andric llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
28410b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object,
28420b57cec5SDimitry Andric                                                  llvm::StringRef annex) {
28430b57cec5SDimitry Andric   // Make sure we have a valid process.
28440b57cec5SDimitry Andric   if (!m_debugged_process_up ||
28450b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
28460b57cec5SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
28470b57cec5SDimitry Andric                                    "No process available");
28480b57cec5SDimitry Andric   }
28490b57cec5SDimitry Andric 
28505ffd83dbSDimitry Andric   if (object == "auxv") {
28510b57cec5SDimitry Andric     // Grab the auxv data.
28520b57cec5SDimitry Andric     auto buffer_or_error = m_debugged_process_up->GetAuxvData();
28530b57cec5SDimitry Andric     if (!buffer_or_error)
28540b57cec5SDimitry Andric       return llvm::errorCodeToError(buffer_or_error.getError());
28550b57cec5SDimitry Andric     return std::move(*buffer_or_error);
28560b57cec5SDimitry Andric   }
28570b57cec5SDimitry Andric 
28589dba64beSDimitry Andric   if (object == "libraries-svr4") {
28599dba64beSDimitry Andric     auto library_list = m_debugged_process_up->GetLoadedSVR4Libraries();
28609dba64beSDimitry Andric     if (!library_list)
28619dba64beSDimitry Andric       return library_list.takeError();
28629dba64beSDimitry Andric 
28639dba64beSDimitry Andric     StreamString response;
28649dba64beSDimitry Andric     response.Printf("<library-list-svr4 version=\"1.0\">");
28659dba64beSDimitry Andric     for (auto const &library : *library_list) {
28669dba64beSDimitry Andric       response.Printf("<library name=\"%s\" ",
28679dba64beSDimitry Andric                       XMLEncodeAttributeValue(library.name.c_str()).c_str());
28689dba64beSDimitry Andric       response.Printf("lm=\"0x%" PRIx64 "\" ", library.link_map);
28699dba64beSDimitry Andric       response.Printf("l_addr=\"0x%" PRIx64 "\" ", library.base_addr);
28709dba64beSDimitry Andric       response.Printf("l_ld=\"0x%" PRIx64 "\" />", library.ld_addr);
28719dba64beSDimitry Andric     }
28729dba64beSDimitry Andric     response.Printf("</library-list-svr4>");
28739dba64beSDimitry Andric     return MemoryBuffer::getMemBufferCopy(response.GetString(), __FUNCTION__);
28749dba64beSDimitry Andric   }
28759dba64beSDimitry Andric 
28765ffd83dbSDimitry Andric   if (object == "features" && annex == "target.xml")
28775ffd83dbSDimitry Andric     return BuildTargetXml();
28785ffd83dbSDimitry Andric 
28790b57cec5SDimitry Andric   return llvm::make_error<PacketUnimplementedError>(
28800b57cec5SDimitry Andric       "Xfer object not supported");
28810b57cec5SDimitry Andric }
28820b57cec5SDimitry Andric 
28830b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
28840b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qXfer(
28850b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
28860b57cec5SDimitry Andric   SmallVector<StringRef, 5> fields;
28870b57cec5SDimitry Andric   // The packet format is "qXfer:<object>:<action>:<annex>:offset,length"
28880b57cec5SDimitry Andric   StringRef(packet.GetStringRef()).split(fields, ':', 4);
28890b57cec5SDimitry Andric   if (fields.size() != 5)
28900b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "malformed qXfer packet");
28910b57cec5SDimitry Andric   StringRef &xfer_object = fields[1];
28920b57cec5SDimitry Andric   StringRef &xfer_action = fields[2];
28930b57cec5SDimitry Andric   StringRef &xfer_annex = fields[3];
28940b57cec5SDimitry Andric   StringExtractor offset_data(fields[4]);
28950b57cec5SDimitry Andric   if (xfer_action != "read")
28960b57cec5SDimitry Andric     return SendUnimplementedResponse("qXfer action not supported");
28970b57cec5SDimitry Andric   // Parse offset.
28980b57cec5SDimitry Andric   const uint64_t xfer_offset =
28990b57cec5SDimitry Andric       offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
29000b57cec5SDimitry Andric   if (xfer_offset == std::numeric_limits<uint64_t>::max())
29010b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "qXfer packet missing offset");
29020b57cec5SDimitry Andric   // Parse out comma.
29030b57cec5SDimitry Andric   if (offset_data.GetChar() != ',')
29040b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
29050b57cec5SDimitry Andric                                  "qXfer packet missing comma after offset");
29060b57cec5SDimitry Andric   // Parse out the length.
29070b57cec5SDimitry Andric   const uint64_t xfer_length =
29080b57cec5SDimitry Andric       offset_data.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
29090b57cec5SDimitry Andric   if (xfer_length == std::numeric_limits<uint64_t>::max())
29100b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "qXfer packet missing length");
29110b57cec5SDimitry Andric 
29120b57cec5SDimitry Andric   // Get a previously constructed buffer if it exists or create it now.
29130b57cec5SDimitry Andric   std::string buffer_key = (xfer_object + xfer_action + xfer_annex).str();
29140b57cec5SDimitry Andric   auto buffer_it = m_xfer_buffer_map.find(buffer_key);
29150b57cec5SDimitry Andric   if (buffer_it == m_xfer_buffer_map.end()) {
29160b57cec5SDimitry Andric     auto buffer_up = ReadXferObject(xfer_object, xfer_annex);
29170b57cec5SDimitry Andric     if (!buffer_up)
29180b57cec5SDimitry Andric       return SendErrorResponse(buffer_up.takeError());
29190b57cec5SDimitry Andric     buffer_it = m_xfer_buffer_map
29200b57cec5SDimitry Andric                     .insert(std::make_pair(buffer_key, std::move(*buffer_up)))
29210b57cec5SDimitry Andric                     .first;
29220b57cec5SDimitry Andric   }
29230b57cec5SDimitry Andric 
29240b57cec5SDimitry Andric   // Send back the response
29250b57cec5SDimitry Andric   StreamGDBRemote response;
29260b57cec5SDimitry Andric   bool done_with_buffer = false;
29270b57cec5SDimitry Andric   llvm::StringRef buffer = buffer_it->second->getBuffer();
29280b57cec5SDimitry Andric   if (xfer_offset >= buffer.size()) {
29290b57cec5SDimitry Andric     // We have nothing left to send.  Mark the buffer as complete.
29300b57cec5SDimitry Andric     response.PutChar('l');
29310b57cec5SDimitry Andric     done_with_buffer = true;
29320b57cec5SDimitry Andric   } else {
29330b57cec5SDimitry Andric     // Figure out how many bytes are available starting at the given offset.
29340b57cec5SDimitry Andric     buffer = buffer.drop_front(xfer_offset);
29350b57cec5SDimitry Andric     // Mark the response type according to whether we're reading the remainder
29360b57cec5SDimitry Andric     // of the data.
29370b57cec5SDimitry Andric     if (xfer_length >= buffer.size()) {
29380b57cec5SDimitry Andric       // There will be nothing left to read after this
29390b57cec5SDimitry Andric       response.PutChar('l');
29400b57cec5SDimitry Andric       done_with_buffer = true;
29410b57cec5SDimitry Andric     } else {
29420b57cec5SDimitry Andric       // There will still be bytes to read after this request.
29430b57cec5SDimitry Andric       response.PutChar('m');
29440b57cec5SDimitry Andric       buffer = buffer.take_front(xfer_length);
29450b57cec5SDimitry Andric     }
29460b57cec5SDimitry Andric     // Now write the data in encoded binary form.
29470b57cec5SDimitry Andric     response.PutEscapedBytes(buffer.data(), buffer.size());
29480b57cec5SDimitry Andric   }
29490b57cec5SDimitry Andric 
29500b57cec5SDimitry Andric   if (done_with_buffer)
29510b57cec5SDimitry Andric     m_xfer_buffer_map.erase(buffer_it);
29520b57cec5SDimitry Andric 
29530b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
29540b57cec5SDimitry Andric }
29550b57cec5SDimitry Andric 
29560b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
29570b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
29580b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
29590b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
29600b57cec5SDimitry Andric 
29610b57cec5SDimitry Andric   // Move past packet name.
29620b57cec5SDimitry Andric   packet.SetFilePos(strlen("QSaveRegisterState"));
29630b57cec5SDimitry Andric 
29640b57cec5SDimitry Andric   // Get the thread to use.
29650b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
29660b57cec5SDimitry Andric   if (!thread) {
29670b57cec5SDimitry Andric     if (m_thread_suffix_supported)
29680b57cec5SDimitry Andric       return SendIllFormedResponse(
29690b57cec5SDimitry Andric           packet, "No thread specified in QSaveRegisterState packet");
29700b57cec5SDimitry Andric     else
29710b57cec5SDimitry Andric       return SendIllFormedResponse(packet,
29720b57cec5SDimitry Andric                                    "No thread was is set with the Hg packet");
29730b57cec5SDimitry Andric   }
29740b57cec5SDimitry Andric 
29750b57cec5SDimitry Andric   // Grab the register context for the thread.
29760b57cec5SDimitry Andric   NativeRegisterContext& reg_context = thread->GetRegisterContext();
29770b57cec5SDimitry Andric 
29780b57cec5SDimitry Andric   // Save registers to a buffer.
29790b57cec5SDimitry Andric   DataBufferSP register_data_sp;
29800b57cec5SDimitry Andric   Status error = reg_context.ReadAllRegisterValues(register_data_sp);
29810b57cec5SDimitry Andric   if (error.Fail()) {
29820b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to save all register values: {1}",
29830b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
29840b57cec5SDimitry Andric     return SendErrorResponse(0x75);
29850b57cec5SDimitry Andric   }
29860b57cec5SDimitry Andric 
29870b57cec5SDimitry Andric   // Allocate a new save id.
29880b57cec5SDimitry Andric   const uint32_t save_id = GetNextSavedRegistersID();
29890b57cec5SDimitry Andric   assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) &&
29900b57cec5SDimitry Andric          "GetNextRegisterSaveID() returned an existing register save id");
29910b57cec5SDimitry Andric 
29920b57cec5SDimitry Andric   // Save the register data buffer under the save id.
29930b57cec5SDimitry Andric   {
29940b57cec5SDimitry Andric     std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
29950b57cec5SDimitry Andric     m_saved_registers_map[save_id] = register_data_sp;
29960b57cec5SDimitry Andric   }
29970b57cec5SDimitry Andric 
29980b57cec5SDimitry Andric   // Write the response.
29990b57cec5SDimitry Andric   StreamGDBRemote response;
30000b57cec5SDimitry Andric   response.Printf("%" PRIu32, save_id);
30010b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
30020b57cec5SDimitry Andric }
30030b57cec5SDimitry Andric 
30040b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
30050b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
30060b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
30070b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
30080b57cec5SDimitry Andric 
30090b57cec5SDimitry Andric   // Parse out save id.
30100b57cec5SDimitry Andric   packet.SetFilePos(strlen("QRestoreRegisterState:"));
30110b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1)
30120b57cec5SDimitry Andric     return SendIllFormedResponse(
30130b57cec5SDimitry Andric         packet, "QRestoreRegisterState packet missing register save id");
30140b57cec5SDimitry Andric 
30150b57cec5SDimitry Andric   const uint32_t save_id = packet.GetU32(0);
30160b57cec5SDimitry Andric   if (save_id == 0) {
30170b57cec5SDimitry Andric     LLDB_LOG(log, "QRestoreRegisterState packet has malformed save id, "
30180b57cec5SDimitry Andric                   "expecting decimal uint32_t");
30190b57cec5SDimitry Andric     return SendErrorResponse(0x76);
30200b57cec5SDimitry Andric   }
30210b57cec5SDimitry Andric 
30220b57cec5SDimitry Andric   // Get the thread to use.
30230b57cec5SDimitry Andric   NativeThreadProtocol *thread = GetThreadFromSuffix(packet);
30240b57cec5SDimitry Andric   if (!thread) {
30250b57cec5SDimitry Andric     if (m_thread_suffix_supported)
30260b57cec5SDimitry Andric       return SendIllFormedResponse(
30270b57cec5SDimitry Andric           packet, "No thread specified in QRestoreRegisterState packet");
30280b57cec5SDimitry Andric     else
30290b57cec5SDimitry Andric       return SendIllFormedResponse(packet,
30300b57cec5SDimitry Andric                                    "No thread was is set with the Hg packet");
30310b57cec5SDimitry Andric   }
30320b57cec5SDimitry Andric 
30330b57cec5SDimitry Andric   // Grab the register context for the thread.
30340b57cec5SDimitry Andric   NativeRegisterContext &reg_context = thread->GetRegisterContext();
30350b57cec5SDimitry Andric 
30360b57cec5SDimitry Andric   // Retrieve register state buffer, then remove from the list.
30370b57cec5SDimitry Andric   DataBufferSP register_data_sp;
30380b57cec5SDimitry Andric   {
30390b57cec5SDimitry Andric     std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
30400b57cec5SDimitry Andric 
30410b57cec5SDimitry Andric     // Find the register set buffer for the given save id.
30420b57cec5SDimitry Andric     auto it = m_saved_registers_map.find(save_id);
30430b57cec5SDimitry Andric     if (it == m_saved_registers_map.end()) {
30440b57cec5SDimitry Andric       LLDB_LOG(log,
30450b57cec5SDimitry Andric                "pid {0} does not have a register set save buffer for id {1}",
30460b57cec5SDimitry Andric                m_debugged_process_up->GetID(), save_id);
30470b57cec5SDimitry Andric       return SendErrorResponse(0x77);
30480b57cec5SDimitry Andric     }
30490b57cec5SDimitry Andric     register_data_sp = it->second;
30500b57cec5SDimitry Andric 
30510b57cec5SDimitry Andric     // Remove it from the map.
30520b57cec5SDimitry Andric     m_saved_registers_map.erase(it);
30530b57cec5SDimitry Andric   }
30540b57cec5SDimitry Andric 
30550b57cec5SDimitry Andric   Status error = reg_context.WriteAllRegisterValues(register_data_sp);
30560b57cec5SDimitry Andric   if (error.Fail()) {
30570b57cec5SDimitry Andric     LLDB_LOG(log, "pid {0} failed to restore all register values: {1}",
30580b57cec5SDimitry Andric              m_debugged_process_up->GetID(), error);
30590b57cec5SDimitry Andric     return SendErrorResponse(0x77);
30600b57cec5SDimitry Andric   }
30610b57cec5SDimitry Andric 
30620b57cec5SDimitry Andric   return SendOKResponse();
30630b57cec5SDimitry Andric }
30640b57cec5SDimitry Andric 
30650b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
30660b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_vAttach(
30670b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
30680b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
30690b57cec5SDimitry Andric 
30700b57cec5SDimitry Andric   // Consume the ';' after vAttach.
30710b57cec5SDimitry Andric   packet.SetFilePos(strlen("vAttach"));
30720b57cec5SDimitry Andric   if (!packet.GetBytesLeft() || packet.GetChar() != ';')
30730b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "vAttach missing expected ';'");
30740b57cec5SDimitry Andric 
30750b57cec5SDimitry Andric   // Grab the PID to which we will attach (assume hex encoding).
30760b57cec5SDimitry Andric   lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
30770b57cec5SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
30780b57cec5SDimitry Andric     return SendIllFormedResponse(packet,
30790b57cec5SDimitry Andric                                  "vAttach failed to parse the process id");
30800b57cec5SDimitry Andric 
30810b57cec5SDimitry Andric   // Attempt to attach.
30829dba64beSDimitry Andric   LLDB_LOGF(log,
30839dba64beSDimitry Andric             "GDBRemoteCommunicationServerLLGS::%s attempting to attach to "
30840b57cec5SDimitry Andric             "pid %" PRIu64,
30850b57cec5SDimitry Andric             __FUNCTION__, pid);
30860b57cec5SDimitry Andric 
30870b57cec5SDimitry Andric   Status error = AttachToProcess(pid);
30880b57cec5SDimitry Andric 
30890b57cec5SDimitry Andric   if (error.Fail()) {
30909dba64beSDimitry Andric     LLDB_LOGF(log,
30919dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to attach to "
30920b57cec5SDimitry Andric               "pid %" PRIu64 ": %s\n",
30930b57cec5SDimitry Andric               __FUNCTION__, pid, error.AsCString());
30940b57cec5SDimitry Andric     return SendErrorResponse(error);
30950b57cec5SDimitry Andric   }
30960b57cec5SDimitry Andric 
30970b57cec5SDimitry Andric   // Notify we attached by sending a stop packet.
30980b57cec5SDimitry Andric   return SendStopReasonForState(m_debugged_process_up->GetState());
30990b57cec5SDimitry Andric }
31000b57cec5SDimitry Andric 
31010b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
31020b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
31030b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
31040b57cec5SDimitry Andric 
31050b57cec5SDimitry Andric   StopSTDIOForwarding();
31060b57cec5SDimitry Andric 
31070b57cec5SDimitry Andric   // Fail if we don't have a current process.
31080b57cec5SDimitry Andric   if (!m_debugged_process_up ||
31090b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) {
31109dba64beSDimitry Andric     LLDB_LOGF(
31119dba64beSDimitry Andric         log,
31120b57cec5SDimitry Andric         "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
31130b57cec5SDimitry Andric         __FUNCTION__);
31140b57cec5SDimitry Andric     return SendErrorResponse(0x15);
31150b57cec5SDimitry Andric   }
31160b57cec5SDimitry Andric 
31170b57cec5SDimitry Andric   lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
31180b57cec5SDimitry Andric 
31190b57cec5SDimitry Andric   // Consume the ';' after D.
31200b57cec5SDimitry Andric   packet.SetFilePos(1);
31210b57cec5SDimitry Andric   if (packet.GetBytesLeft()) {
31220b57cec5SDimitry Andric     if (packet.GetChar() != ';')
31230b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "D missing expected ';'");
31240b57cec5SDimitry Andric 
31250b57cec5SDimitry Andric     // Grab the PID from which we will detach (assume hex encoding).
31260b57cec5SDimitry Andric     pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
31270b57cec5SDimitry Andric     if (pid == LLDB_INVALID_PROCESS_ID)
31280b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "D failed to parse the process id");
31290b57cec5SDimitry Andric   }
31300b57cec5SDimitry Andric 
31310b57cec5SDimitry Andric   if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_up->GetID() != pid) {
31320b57cec5SDimitry Andric     return SendIllFormedResponse(packet, "Invalid pid");
31330b57cec5SDimitry Andric   }
31340b57cec5SDimitry Andric 
31350b57cec5SDimitry Andric   const Status error = m_debugged_process_up->Detach();
31360b57cec5SDimitry Andric   if (error.Fail()) {
31379dba64beSDimitry Andric     LLDB_LOGF(log,
31389dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed to detach from "
31390b57cec5SDimitry Andric               "pid %" PRIu64 ": %s\n",
31409dba64beSDimitry Andric               __FUNCTION__, m_debugged_process_up->GetID(), error.AsCString());
31410b57cec5SDimitry Andric     return SendErrorResponse(0x01);
31420b57cec5SDimitry Andric   }
31430b57cec5SDimitry Andric 
31440b57cec5SDimitry Andric   return SendOKResponse();
31450b57cec5SDimitry Andric }
31460b57cec5SDimitry Andric 
31470b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
31480b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
31490b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
31500b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
31510b57cec5SDimitry Andric 
31520b57cec5SDimitry Andric   packet.SetFilePos(strlen("qThreadStopInfo"));
31530b57cec5SDimitry Andric   const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
31540b57cec5SDimitry Andric   if (tid == LLDB_INVALID_THREAD_ID) {
31559dba64beSDimitry Andric     LLDB_LOGF(log,
31569dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s failed, could not "
31570b57cec5SDimitry Andric               "parse thread id from request \"%s\"",
31589dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
31590b57cec5SDimitry Andric     return SendErrorResponse(0x15);
31600b57cec5SDimitry Andric   }
31610b57cec5SDimitry Andric   return SendStopReplyPacketForThread(tid);
31620b57cec5SDimitry Andric }
31630b57cec5SDimitry Andric 
31640b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
31650b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
31660b57cec5SDimitry Andric     StringExtractorGDBRemote &) {
31670b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
31680b57cec5SDimitry Andric 
31690b57cec5SDimitry Andric   // Ensure we have a debugged process.
31700b57cec5SDimitry Andric   if (!m_debugged_process_up ||
31710b57cec5SDimitry Andric       (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
31720b57cec5SDimitry Andric     return SendErrorResponse(50);
31730b57cec5SDimitry Andric   LLDB_LOG(log, "preparing packet for pid {0}", m_debugged_process_up->GetID());
31740b57cec5SDimitry Andric 
31750b57cec5SDimitry Andric   StreamString response;
31760b57cec5SDimitry Andric   const bool threads_with_valid_stop_info_only = false;
31779dba64beSDimitry Andric   llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo(
31780b57cec5SDimitry Andric       *m_debugged_process_up, threads_with_valid_stop_info_only);
31799dba64beSDimitry Andric   if (!threads_info) {
3180480093f4SDimitry Andric     LLDB_LOG_ERROR(log, threads_info.takeError(),
3181480093f4SDimitry Andric                    "failed to prepare a packet for pid {1}: {0}",
3182480093f4SDimitry Andric                    m_debugged_process_up->GetID());
31830b57cec5SDimitry Andric     return SendErrorResponse(52);
31840b57cec5SDimitry Andric   }
31850b57cec5SDimitry Andric 
31869dba64beSDimitry Andric   response.AsRawOstream() << *threads_info;
31870b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
31880b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
31890b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
31900b57cec5SDimitry Andric }
31910b57cec5SDimitry Andric 
31920b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
31930b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
31940b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
31950b57cec5SDimitry Andric   // Fail if we don't have a current process.
31960b57cec5SDimitry Andric   if (!m_debugged_process_up ||
31970b57cec5SDimitry Andric       m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
31980b57cec5SDimitry Andric     return SendErrorResponse(68);
31990b57cec5SDimitry Andric 
32000b57cec5SDimitry Andric   packet.SetFilePos(strlen("qWatchpointSupportInfo"));
32010b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0)
32020b57cec5SDimitry Andric     return SendOKResponse();
32030b57cec5SDimitry Andric   if (packet.GetChar() != ':')
32040b57cec5SDimitry Andric     return SendErrorResponse(67);
32050b57cec5SDimitry Andric 
32060b57cec5SDimitry Andric   auto hw_debug_cap = m_debugged_process_up->GetHardwareDebugSupportInfo();
32070b57cec5SDimitry Andric 
32080b57cec5SDimitry Andric   StreamGDBRemote response;
32090b57cec5SDimitry Andric   if (hw_debug_cap == llvm::None)
32100b57cec5SDimitry Andric     response.Printf("num:0;");
32110b57cec5SDimitry Andric   else
32120b57cec5SDimitry Andric     response.Printf("num:%d;", hw_debug_cap->second);
32130b57cec5SDimitry Andric 
32140b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
32150b57cec5SDimitry Andric }
32160b57cec5SDimitry Andric 
32170b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
32180b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
32190b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
32200b57cec5SDimitry Andric   // Fail if we don't have a current process.
32210b57cec5SDimitry Andric   if (!m_debugged_process_up ||
32220b57cec5SDimitry Andric       m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
32230b57cec5SDimitry Andric     return SendErrorResponse(67);
32240b57cec5SDimitry Andric 
32250b57cec5SDimitry Andric   packet.SetFilePos(strlen("qFileLoadAddress:"));
32260b57cec5SDimitry Andric   if (packet.GetBytesLeft() == 0)
32270b57cec5SDimitry Andric     return SendErrorResponse(68);
32280b57cec5SDimitry Andric 
32290b57cec5SDimitry Andric   std::string file_name;
32300b57cec5SDimitry Andric   packet.GetHexByteString(file_name);
32310b57cec5SDimitry Andric 
32320b57cec5SDimitry Andric   lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
32330b57cec5SDimitry Andric   Status error =
32340b57cec5SDimitry Andric       m_debugged_process_up->GetFileLoadAddress(file_name, file_load_address);
32350b57cec5SDimitry Andric   if (error.Fail())
32360b57cec5SDimitry Andric     return SendErrorResponse(69);
32370b57cec5SDimitry Andric 
32380b57cec5SDimitry Andric   if (file_load_address == LLDB_INVALID_ADDRESS)
32390b57cec5SDimitry Andric     return SendErrorResponse(1); // File not loaded
32400b57cec5SDimitry Andric 
32410b57cec5SDimitry Andric   StreamGDBRemote response;
32420b57cec5SDimitry Andric   response.PutHex64(file_load_address);
32430b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
32440b57cec5SDimitry Andric }
32450b57cec5SDimitry Andric 
32460b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
32470b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
32480b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
32490b57cec5SDimitry Andric   std::vector<int> signals;
32500b57cec5SDimitry Andric   packet.SetFilePos(strlen("QPassSignals:"));
32510b57cec5SDimitry Andric 
32520b57cec5SDimitry Andric   // Read sequence of hex signal numbers divided by a semicolon and optionally
32530b57cec5SDimitry Andric   // spaces.
32540b57cec5SDimitry Andric   while (packet.GetBytesLeft() > 0) {
32550b57cec5SDimitry Andric     int signal = packet.GetS32(-1, 16);
32560b57cec5SDimitry Andric     if (signal < 0)
32570b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Failed to parse signal number.");
32580b57cec5SDimitry Andric     signals.push_back(signal);
32590b57cec5SDimitry Andric 
32600b57cec5SDimitry Andric     packet.SkipSpaces();
32610b57cec5SDimitry Andric     char separator = packet.GetChar();
32620b57cec5SDimitry Andric     if (separator == '\0')
32630b57cec5SDimitry Andric       break; // End of string
32640b57cec5SDimitry Andric     if (separator != ';')
32650b57cec5SDimitry Andric       return SendIllFormedResponse(packet, "Invalid separator,"
32660b57cec5SDimitry Andric                                             " expected semicolon.");
32670b57cec5SDimitry Andric   }
32680b57cec5SDimitry Andric 
32690b57cec5SDimitry Andric   // Fail if we don't have a current process.
32700b57cec5SDimitry Andric   if (!m_debugged_process_up)
32710b57cec5SDimitry Andric     return SendErrorResponse(68);
32720b57cec5SDimitry Andric 
32730b57cec5SDimitry Andric   Status error = m_debugged_process_up->IgnoreSignals(signals);
32740b57cec5SDimitry Andric   if (error.Fail())
32750b57cec5SDimitry Andric     return SendErrorResponse(69);
32760b57cec5SDimitry Andric 
32770b57cec5SDimitry Andric   return SendOKResponse();
32780b57cec5SDimitry Andric }
32790b57cec5SDimitry Andric 
32800b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
32810b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
32820b57cec5SDimitry Andric 
32830b57cec5SDimitry Andric   // Tell the stdio connection to shut down.
32840b57cec5SDimitry Andric   if (m_stdio_communication.IsConnected()) {
32850b57cec5SDimitry Andric     auto connection = m_stdio_communication.GetConnection();
32860b57cec5SDimitry Andric     if (connection) {
32870b57cec5SDimitry Andric       Status error;
32880b57cec5SDimitry Andric       connection->Disconnect(&error);
32890b57cec5SDimitry Andric 
32900b57cec5SDimitry Andric       if (error.Success()) {
32919dba64beSDimitry Andric         LLDB_LOGF(log,
32929dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s disconnect process "
32930b57cec5SDimitry Andric                   "terminal stdio - SUCCESS",
32940b57cec5SDimitry Andric                   __FUNCTION__);
32950b57cec5SDimitry Andric       } else {
32969dba64beSDimitry Andric         LLDB_LOGF(log,
32979dba64beSDimitry Andric                   "GDBRemoteCommunicationServerLLGS::%s disconnect process "
32980b57cec5SDimitry Andric                   "terminal stdio - FAIL: %s",
32990b57cec5SDimitry Andric                   __FUNCTION__, error.AsCString());
33000b57cec5SDimitry Andric       }
33010b57cec5SDimitry Andric     }
33020b57cec5SDimitry Andric   }
33030b57cec5SDimitry Andric }
33040b57cec5SDimitry Andric 
33050b57cec5SDimitry Andric NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
33060b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
33070b57cec5SDimitry Andric   // We have no thread if we don't have a process.
33080b57cec5SDimitry Andric   if (!m_debugged_process_up ||
33090b57cec5SDimitry Andric       m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)
33100b57cec5SDimitry Andric     return nullptr;
33110b57cec5SDimitry Andric 
33120b57cec5SDimitry Andric   // If the client hasn't asked for thread suffix support, there will not be a
33130b57cec5SDimitry Andric   // thread suffix. Use the current thread in that case.
33140b57cec5SDimitry Andric   if (!m_thread_suffix_supported) {
33150b57cec5SDimitry Andric     const lldb::tid_t current_tid = GetCurrentThreadID();
33160b57cec5SDimitry Andric     if (current_tid == LLDB_INVALID_THREAD_ID)
33170b57cec5SDimitry Andric       return nullptr;
33180b57cec5SDimitry Andric     else if (current_tid == 0) {
33190b57cec5SDimitry Andric       // Pick a thread.
33200b57cec5SDimitry Andric       return m_debugged_process_up->GetThreadAtIndex(0);
33210b57cec5SDimitry Andric     } else
33220b57cec5SDimitry Andric       return m_debugged_process_up->GetThreadByID(current_tid);
33230b57cec5SDimitry Andric   }
33240b57cec5SDimitry Andric 
33250b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
33260b57cec5SDimitry Andric 
33270b57cec5SDimitry Andric   // Parse out the ';'.
33280b57cec5SDimitry Andric   if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') {
33299dba64beSDimitry Andric     LLDB_LOGF(log,
33309dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
33310b57cec5SDimitry Andric               "error: expected ';' prior to start of thread suffix: packet "
33320b57cec5SDimitry Andric               "contents = '%s'",
33339dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
33340b57cec5SDimitry Andric     return nullptr;
33350b57cec5SDimitry Andric   }
33360b57cec5SDimitry Andric 
33370b57cec5SDimitry Andric   if (!packet.GetBytesLeft())
33380b57cec5SDimitry Andric     return nullptr;
33390b57cec5SDimitry Andric 
33400b57cec5SDimitry Andric   // Parse out thread: portion.
33410b57cec5SDimitry Andric   if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) {
33429dba64beSDimitry Andric     LLDB_LOGF(log,
33439dba64beSDimitry Andric               "GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
33440b57cec5SDimitry Andric               "error: expected 'thread:' but not found, packet contents = "
33450b57cec5SDimitry Andric               "'%s'",
33469dba64beSDimitry Andric               __FUNCTION__, packet.GetStringRef().data());
33470b57cec5SDimitry Andric     return nullptr;
33480b57cec5SDimitry Andric   }
33490b57cec5SDimitry Andric   packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
33500b57cec5SDimitry Andric   const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
33510b57cec5SDimitry Andric   if (tid != 0)
33520b57cec5SDimitry Andric     return m_debugged_process_up->GetThreadByID(tid);
33530b57cec5SDimitry Andric 
33540b57cec5SDimitry Andric   return nullptr;
33550b57cec5SDimitry Andric }
33560b57cec5SDimitry Andric 
33570b57cec5SDimitry Andric lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
33580b57cec5SDimitry Andric   if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
33590b57cec5SDimitry Andric     // Use whatever the debug process says is the current thread id since the
33600b57cec5SDimitry Andric     // protocol either didn't specify or specified we want any/all threads
33610b57cec5SDimitry Andric     // marked as the current thread.
33620b57cec5SDimitry Andric     if (!m_debugged_process_up)
33630b57cec5SDimitry Andric       return LLDB_INVALID_THREAD_ID;
33640b57cec5SDimitry Andric     return m_debugged_process_up->GetCurrentThreadID();
33650b57cec5SDimitry Andric   }
33660b57cec5SDimitry Andric   // Use the specific current thread id set by the gdb remote protocol.
33670b57cec5SDimitry Andric   return m_current_tid;
33680b57cec5SDimitry Andric }
33690b57cec5SDimitry Andric 
33700b57cec5SDimitry Andric uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() {
33710b57cec5SDimitry Andric   std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
33720b57cec5SDimitry Andric   return m_next_saved_registers_id++;
33730b57cec5SDimitry Andric }
33740b57cec5SDimitry Andric 
33750b57cec5SDimitry Andric void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
33760b57cec5SDimitry Andric   Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
33770b57cec5SDimitry Andric 
33780b57cec5SDimitry Andric   LLDB_LOG(log, "clearing {0} xfer buffers", m_xfer_buffer_map.size());
33790b57cec5SDimitry Andric   m_xfer_buffer_map.clear();
33800b57cec5SDimitry Andric }
33810b57cec5SDimitry Andric 
33820b57cec5SDimitry Andric FileSpec
33830b57cec5SDimitry Andric GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
33840b57cec5SDimitry Andric                                                  const ArchSpec &arch) {
33850b57cec5SDimitry Andric   if (m_debugged_process_up) {
33860b57cec5SDimitry Andric     FileSpec file_spec;
33870b57cec5SDimitry Andric     if (m_debugged_process_up
33880b57cec5SDimitry Andric             ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
33890b57cec5SDimitry Andric             .Success()) {
33900b57cec5SDimitry Andric       if (FileSystem::Instance().Exists(file_spec))
33910b57cec5SDimitry Andric         return file_spec;
33920b57cec5SDimitry Andric     }
33930b57cec5SDimitry Andric   }
33940b57cec5SDimitry Andric 
33950b57cec5SDimitry Andric   return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch);
33960b57cec5SDimitry Andric }
33979dba64beSDimitry Andric 
33989dba64beSDimitry Andric std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue(
33999dba64beSDimitry Andric     llvm::StringRef value) {
34009dba64beSDimitry Andric   std::string result;
34019dba64beSDimitry Andric   for (const char &c : value) {
34029dba64beSDimitry Andric     switch (c) {
34039dba64beSDimitry Andric     case '\'':
34049dba64beSDimitry Andric       result += "&apos;";
34059dba64beSDimitry Andric       break;
34069dba64beSDimitry Andric     case '"':
34079dba64beSDimitry Andric       result += "&quot;";
34089dba64beSDimitry Andric       break;
34099dba64beSDimitry Andric     case '<':
34109dba64beSDimitry Andric       result += "&lt;";
34119dba64beSDimitry Andric       break;
34129dba64beSDimitry Andric     case '>':
34139dba64beSDimitry Andric       result += "&gt;";
34149dba64beSDimitry Andric       break;
34159dba64beSDimitry Andric     default:
34169dba64beSDimitry Andric       result += c;
34179dba64beSDimitry Andric       break;
34189dba64beSDimitry Andric     }
34199dba64beSDimitry Andric   }
34209dba64beSDimitry Andric   return result;
34219dba64beSDimitry Andric }
3422