15ffd83dbSDimitry Andric //===-- GDBRemoteCommunicationServerPlatform.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 "GDBRemoteCommunicationServerPlatform.h"
100b57cec5SDimitry Andric 
11fe6060f1SDimitry Andric #include <cerrno>
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include <chrono>
140b57cec5SDimitry Andric #include <csignal>
150b57cec5SDimitry Andric #include <cstring>
160b57cec5SDimitry Andric #include <mutex>
17bdd1243dSDimitry Andric #include <optional>
180b57cec5SDimitry Andric #include <sstream>
199dba64beSDimitry Andric #include <thread>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
229dba64beSDimitry Andric #include "llvm/Support/JSON.h"
230b57cec5SDimitry Andric #include "llvm/Support/Threading.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #include "lldb/Host/Config.h"
260b57cec5SDimitry Andric #include "lldb/Host/ConnectionFileDescriptor.h"
270b57cec5SDimitry Andric #include "lldb/Host/FileAction.h"
280b57cec5SDimitry Andric #include "lldb/Host/Host.h"
290b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h"
30e8d8bef9SDimitry Andric #include "lldb/Interpreter/CommandCompletions.h"
310b57cec5SDimitry Andric #include "lldb/Target/Platform.h"
320b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h"
339dba64beSDimitry Andric #include "lldb/Utility/GDBRemote.h"
3481ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
350b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
360b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
370b57cec5SDimitry Andric #include "lldb/Utility/StructuredData.h"
38e8d8bef9SDimitry Andric #include "lldb/Utility/TildeExpressionResolver.h"
390b57cec5SDimitry Andric #include "lldb/Utility/UriParser.h"
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric using namespace lldb;
440b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote;
459dba64beSDimitry Andric using namespace lldb_private;
460b57cec5SDimitry Andric 
47e8d8bef9SDimitry Andric GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
48e8d8bef9SDimitry Andric                                                        uint16_t max_port) {
49*0fca6ea1SDimitry Andric   assert(min_port);
50e8d8bef9SDimitry Andric   for (; min_port < max_port; ++min_port)
51e8d8bef9SDimitry Andric     m_port_map[min_port] = LLDB_INVALID_PROCESS_ID;
52e8d8bef9SDimitry Andric }
53e8d8bef9SDimitry Andric 
54e8d8bef9SDimitry Andric void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) {
55*0fca6ea1SDimitry Andric   assert(port);
56e8d8bef9SDimitry Andric   // Do not modify existing mappings
57e8d8bef9SDimitry Andric   m_port_map.insert({port, LLDB_INVALID_PROCESS_ID});
58e8d8bef9SDimitry Andric }
59e8d8bef9SDimitry Andric 
60e8d8bef9SDimitry Andric llvm::Expected<uint16_t>
61e8d8bef9SDimitry Andric GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() {
62e8d8bef9SDimitry Andric   if (m_port_map.empty())
63e8d8bef9SDimitry Andric     return 0; // Bind to port zero and get a port, we didn't have any
64e8d8bef9SDimitry Andric               // limitations
65e8d8bef9SDimitry Andric 
66e8d8bef9SDimitry Andric   for (auto &pair : m_port_map) {
67e8d8bef9SDimitry Andric     if (pair.second == LLDB_INVALID_PROCESS_ID) {
68e8d8bef9SDimitry Andric       pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
69e8d8bef9SDimitry Andric       return pair.first;
70e8d8bef9SDimitry Andric     }
71e8d8bef9SDimitry Andric   }
72e8d8bef9SDimitry Andric   return llvm::createStringError(llvm::inconvertibleErrorCode(),
73e8d8bef9SDimitry Andric                                  "No free port found in port map");
74e8d8bef9SDimitry Andric }
75e8d8bef9SDimitry Andric 
76e8d8bef9SDimitry Andric bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess(
77e8d8bef9SDimitry Andric     uint16_t port, lldb::pid_t pid) {
78e8d8bef9SDimitry Andric   auto pos = m_port_map.find(port);
79e8d8bef9SDimitry Andric   if (pos != m_port_map.end()) {
80e8d8bef9SDimitry Andric     pos->second = pid;
81e8d8bef9SDimitry Andric     return true;
82e8d8bef9SDimitry Andric   }
83e8d8bef9SDimitry Andric   return false;
84e8d8bef9SDimitry Andric }
85e8d8bef9SDimitry Andric 
86e8d8bef9SDimitry Andric bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) {
87e8d8bef9SDimitry Andric   std::map<uint16_t, lldb::pid_t>::iterator pos = m_port_map.find(port);
88e8d8bef9SDimitry Andric   if (pos != m_port_map.end()) {
89e8d8bef9SDimitry Andric     pos->second = LLDB_INVALID_PROCESS_ID;
90e8d8bef9SDimitry Andric     return true;
91e8d8bef9SDimitry Andric   }
92e8d8bef9SDimitry Andric   return false;
93e8d8bef9SDimitry Andric }
94e8d8bef9SDimitry Andric 
95e8d8bef9SDimitry Andric bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess(
96e8d8bef9SDimitry Andric     lldb::pid_t pid) {
97e8d8bef9SDimitry Andric   if (!m_port_map.empty()) {
98e8d8bef9SDimitry Andric     for (auto &pair : m_port_map) {
99e8d8bef9SDimitry Andric       if (pair.second == pid) {
100e8d8bef9SDimitry Andric         pair.second = LLDB_INVALID_PROCESS_ID;
101e8d8bef9SDimitry Andric         return true;
102e8d8bef9SDimitry Andric       }
103e8d8bef9SDimitry Andric     }
104e8d8bef9SDimitry Andric   }
105e8d8bef9SDimitry Andric   return false;
106e8d8bef9SDimitry Andric }
107e8d8bef9SDimitry Andric 
108e8d8bef9SDimitry Andric bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const {
109e8d8bef9SDimitry Andric   return m_port_map.empty();
110e8d8bef9SDimitry Andric }
111e8d8bef9SDimitry Andric 
1120b57cec5SDimitry Andric // GDBRemoteCommunicationServerPlatform constructor
1130b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
1140b57cec5SDimitry Andric     const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
115bdd1243dSDimitry Andric     : GDBRemoteCommunicationServerCommon(),
1160b57cec5SDimitry Andric       m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
1170b57cec5SDimitry Andric       m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
1180b57cec5SDimitry Andric   m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
1190b57cec5SDimitry Andric   m_pending_gdb_server.port = 0;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1220b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qC,
1230b57cec5SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_qC);
1240b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1250b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
1260b57cec5SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
1270b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1280b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
1290b57cec5SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
1300b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1310b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
1320b57cec5SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
1330b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1340b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
1350b57cec5SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
1360b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1370b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
1380b57cec5SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
1390b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
140e8d8bef9SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_qPathComplete,
141e8d8bef9SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_qPathComplete);
142e8d8bef9SDimitry Andric   RegisterMemberFunctionHandler(
1430b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
1440b57cec5SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
1450b57cec5SDimitry Andric   RegisterMemberFunctionHandler(
1460b57cec5SDimitry Andric       StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
1470b57cec5SDimitry Andric       &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
1500b57cec5SDimitry Andric                         [](StringExtractorGDBRemote packet, Status &error,
1510b57cec5SDimitry Andric                            bool &interrupt, bool &quit) {
1520b57cec5SDimitry Andric                           error.SetErrorString("interrupt received");
1530b57cec5SDimitry Andric                           interrupt = true;
1540b57cec5SDimitry Andric                           return PacketResult::Success;
1550b57cec5SDimitry Andric                         });
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric // Destructor
159fe6060f1SDimitry Andric GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
160fe6060f1SDimitry Andric     default;
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
1630b57cec5SDimitry Andric     const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
164bdd1243dSDimitry Andric     std::optional<uint16_t> &port, std::string &socket_name) {
165e8d8bef9SDimitry Andric   if (!port) {
166e8d8bef9SDimitry Andric     llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort();
167e8d8bef9SDimitry Andric     if (available_port)
168e8d8bef9SDimitry Andric       port = *available_port;
169e8d8bef9SDimitry Andric     else
170e8d8bef9SDimitry Andric       return Status(available_port.takeError());
171e8d8bef9SDimitry Andric   }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   // Spawn a new thread to accept the port that gets bound after binding to
1740b57cec5SDimitry Andric   // port 0 (zero).
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   // ignore the hostname send from the remote end, just use the ip address that
1770b57cec5SDimitry Andric   // we're currently communicating with as the hostname
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   // Spawn a debugserver and try to get the port it listens to.
1800b57cec5SDimitry Andric   ProcessLaunchInfo debugserver_launch_info;
1810b57cec5SDimitry Andric   if (hostname.empty())
1820b57cec5SDimitry Andric     hostname = "127.0.0.1";
1830b57cec5SDimitry Andric 
18481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Platform);
1859dba64beSDimitry Andric   LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(),
186e8d8bef9SDimitry Andric             *port);
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   // Do not run in a new session so that it can not linger after the platform
1890b57cec5SDimitry Andric   // closes.
1900b57cec5SDimitry Andric   debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
1910b57cec5SDimitry Andric   debugserver_launch_info.SetMonitorProcessCallback(
1920b57cec5SDimitry Andric       std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
19381ad6265SDimitry Andric                 this, std::placeholders::_1));
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   std::ostringstream url;
1960b57cec5SDimitry Andric // debugserver does not accept the URL scheme prefix.
1970b57cec5SDimitry Andric #if !defined(__APPLE__)
1980b57cec5SDimitry Andric   url << m_socket_scheme << "://";
1990b57cec5SDimitry Andric #endif
200bdd1243dSDimitry Andric   uint16_t *port_ptr = &*port;
2010b57cec5SDimitry Andric   if (m_socket_protocol == Socket::ProtocolTcp) {
2020b57cec5SDimitry Andric     std::string platform_uri = GetConnection()->GetURI();
203bdd1243dSDimitry Andric     std::optional<URI> parsed_uri = URI::Parse(platform_uri);
204349cc55cSDimitry Andric     url << '[' << parsed_uri->hostname.str() << "]:" << *port;
2050b57cec5SDimitry Andric   } else {
2060b57cec5SDimitry Andric     socket_name = GetDomainSocketPath("gdbserver").GetPath();
2070b57cec5SDimitry Andric     url << socket_name;
2080b57cec5SDimitry Andric     port_ptr = nullptr;
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   Status error = StartDebugserverProcess(
2120b57cec5SDimitry Andric       url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   pid = debugserver_launch_info.GetProcessID();
2150b57cec5SDimitry Andric   if (pid != LLDB_INVALID_PROCESS_ID) {
2160b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
2170b57cec5SDimitry Andric     m_spawned_pids.insert(pid);
218e8d8bef9SDimitry Andric     if (*port > 0)
219e8d8bef9SDimitry Andric       m_port_map.AssociatePortWithProcess(*port, pid);
2200b57cec5SDimitry Andric   } else {
221e8d8bef9SDimitry Andric     if (*port > 0)
222e8d8bef9SDimitry Andric       m_port_map.FreePort(*port);
2230b57cec5SDimitry Andric   }
2240b57cec5SDimitry Andric   return error;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
2280b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
2290b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
2300b57cec5SDimitry Andric   // Spawn a local debugserver as a platform so we can then attach or launch a
2310b57cec5SDimitry Andric   // process...
2320b57cec5SDimitry Andric 
23381ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Platform);
2349dba64beSDimitry Andric   LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
2350b57cec5SDimitry Andric             __FUNCTION__);
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   ConnectionFileDescriptor file_conn;
2380b57cec5SDimitry Andric   std::string hostname;
2390b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qLaunchGDBServer;"));
2400b57cec5SDimitry Andric   llvm::StringRef name;
2410b57cec5SDimitry Andric   llvm::StringRef value;
242bdd1243dSDimitry Andric   std::optional<uint16_t> port;
2430b57cec5SDimitry Andric   while (packet.GetNameColonValue(name, value)) {
244*0fca6ea1SDimitry Andric     if (name == "host")
2455ffd83dbSDimitry Andric       hostname = std::string(value);
246*0fca6ea1SDimitry Andric     else if (name == "port") {
247e8d8bef9SDimitry Andric       // Make the Optional valid so we can use its value
248e8d8bef9SDimitry Andric       port = 0;
24981ad6265SDimitry Andric       value.getAsInteger(0, *port);
250e8d8bef9SDimitry Andric     }
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
2540b57cec5SDimitry Andric   std::string socket_name;
2550b57cec5SDimitry Andric   Status error =
2560b57cec5SDimitry Andric       LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
2570b57cec5SDimitry Andric   if (error.Fail()) {
2589dba64beSDimitry Andric     LLDB_LOGF(log,
2599dba64beSDimitry Andric               "GDBRemoteCommunicationServerPlatform::%s() debugserver "
2600b57cec5SDimitry Andric               "launch failed: %s",
2610b57cec5SDimitry Andric               __FUNCTION__, error.AsCString());
2620b57cec5SDimitry Andric     return SendErrorResponse(9);
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric 
2659dba64beSDimitry Andric   LLDB_LOGF(log,
2669dba64beSDimitry Andric             "GDBRemoteCommunicationServerPlatform::%s() debugserver "
2670b57cec5SDimitry Andric             "launched successfully as pid %" PRIu64,
2680b57cec5SDimitry Andric             __FUNCTION__, debugserver_pid);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   StreamGDBRemote response;
271e8d8bef9SDimitry Andric   assert(port);
2720b57cec5SDimitry Andric   response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
273e8d8bef9SDimitry Andric                   *port + m_port_offset);
2740b57cec5SDimitry Andric   if (!socket_name.empty()) {
2750b57cec5SDimitry Andric     response.PutCString("socket_name:");
2760b57cec5SDimitry Andric     response.PutStringAsRawHex8(socket_name);
2770b57cec5SDimitry Andric     response.PutChar(';');
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   PacketResult packet_result = SendPacketNoLock(response.GetString());
2810b57cec5SDimitry Andric   if (packet_result != PacketResult::Success) {
2820b57cec5SDimitry Andric     if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
2830b57cec5SDimitry Andric       Host::Kill(debugserver_pid, SIGINT);
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric   return packet_result;
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
2890b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
2900b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
2919dba64beSDimitry Andric   namespace json = llvm::json;
2929dba64beSDimitry Andric 
2930b57cec5SDimitry Andric   if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
2940b57cec5SDimitry Andric     return SendErrorResponse(4);
2950b57cec5SDimitry Andric 
2969dba64beSDimitry Andric   json::Object server{{"port", m_pending_gdb_server.port}};
2970b57cec5SDimitry Andric 
2989dba64beSDimitry Andric   if (!m_pending_gdb_server.socket_name.empty())
2999dba64beSDimitry Andric     server.try_emplace("socket_name", m_pending_gdb_server.socket_name);
3009dba64beSDimitry Andric 
3019dba64beSDimitry Andric   json::Array server_list;
3029dba64beSDimitry Andric   server_list.push_back(std::move(server));
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   StreamGDBRemote response;
3059dba64beSDimitry Andric   response.AsRawOstream() << std::move(server_list);
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   StreamGDBRemote escaped_response;
3080b57cec5SDimitry Andric   escaped_response.PutEscapedBytes(response.GetString().data(),
3090b57cec5SDimitry Andric                                    response.GetSize());
3100b57cec5SDimitry Andric   return SendPacketNoLock(escaped_response.GetString());
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3140b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
3150b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
3160b57cec5SDimitry Andric   packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   // verify that we know anything about this pid. Scope for locker
3210b57cec5SDimitry Andric   {
3220b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
3230b57cec5SDimitry Andric     if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
3240b57cec5SDimitry Andric       // not a pid we know about
3250b57cec5SDimitry Andric       return SendErrorResponse(10);
3260b57cec5SDimitry Andric     }
3270b57cec5SDimitry Andric   }
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   // go ahead and attempt to kill the spawned process
3300b57cec5SDimitry Andric   if (KillSpawnedProcess(pid))
3310b57cec5SDimitry Andric     return SendOKResponse();
3320b57cec5SDimitry Andric   else
3330b57cec5SDimitry Andric     return SendErrorResponse(11);
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
3370b57cec5SDimitry Andric   // make sure we know about this process
3380b57cec5SDimitry Andric   {
3390b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
3400b57cec5SDimitry Andric     if (m_spawned_pids.find(pid) == m_spawned_pids.end())
3410b57cec5SDimitry Andric       return false;
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   // first try a SIGTERM (standard kill)
3450b57cec5SDimitry Andric   Host::Kill(pid, SIGTERM);
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   // check if that worked
3480b57cec5SDimitry Andric   for (size_t i = 0; i < 10; ++i) {
3490b57cec5SDimitry Andric     {
3500b57cec5SDimitry Andric       std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
3510b57cec5SDimitry Andric       if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
3520b57cec5SDimitry Andric         // it is now killed
3530b57cec5SDimitry Andric         return true;
3540b57cec5SDimitry Andric       }
3550b57cec5SDimitry Andric     }
3569dba64beSDimitry Andric     std::this_thread::sleep_for(std::chrono::milliseconds(10));
3570b57cec5SDimitry Andric   }
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   {
3600b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
3610b57cec5SDimitry Andric     if (m_spawned_pids.find(pid) == m_spawned_pids.end())
3620b57cec5SDimitry Andric       return true;
3630b57cec5SDimitry Andric   }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   // the launched process still lives.  Now try killing it again, this time
3660b57cec5SDimitry Andric   // with an unblockable signal.
3670b57cec5SDimitry Andric   Host::Kill(pid, SIGKILL);
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   for (size_t i = 0; i < 10; ++i) {
3700b57cec5SDimitry Andric     {
3710b57cec5SDimitry Andric       std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
3720b57cec5SDimitry Andric       if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
3730b57cec5SDimitry Andric         // it is now killed
3740b57cec5SDimitry Andric         return true;
3750b57cec5SDimitry Andric       }
3760b57cec5SDimitry Andric     }
3779dba64beSDimitry Andric     std::this_thread::sleep_for(std::chrono::milliseconds(10));
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric 
3809dba64beSDimitry Andric   // check one more time after the final sleep
3810b57cec5SDimitry Andric   {
3820b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
3830b57cec5SDimitry Andric     if (m_spawned_pids.find(pid) == m_spawned_pids.end())
3840b57cec5SDimitry Andric       return true;
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   // no luck - the process still lives
3880b57cec5SDimitry Andric   return false;
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
3920b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
3930b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
3940b57cec5SDimitry Andric   lldb::pid_t pid = m_process_launch_info.GetProcessID();
3950b57cec5SDimitry Andric   m_process_launch_info.Clear();
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   if (pid == LLDB_INVALID_PROCESS_ID)
3980b57cec5SDimitry Andric     return SendErrorResponse(1);
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   ProcessInstanceInfo proc_info;
4010b57cec5SDimitry Andric   if (!Host::GetProcessInfo(pid, proc_info))
4020b57cec5SDimitry Andric     return SendErrorResponse(1);
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   StreamString response;
4050b57cec5SDimitry Andric   CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
4060b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
410e8d8bef9SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_qPathComplete(
411e8d8bef9SDimitry Andric     StringExtractorGDBRemote &packet) {
412e8d8bef9SDimitry Andric   packet.SetFilePos(::strlen("qPathComplete:"));
413e8d8bef9SDimitry Andric   const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1);
414e8d8bef9SDimitry Andric   if (packet.GetChar() != ',')
415e8d8bef9SDimitry Andric     return SendErrorResponse(85);
416e8d8bef9SDimitry Andric   std::string path;
417e8d8bef9SDimitry Andric   packet.GetHexByteString(path);
418e8d8bef9SDimitry Andric 
419e8d8bef9SDimitry Andric   StringList matches;
420e8d8bef9SDimitry Andric   StandardTildeExpressionResolver resolver;
421e8d8bef9SDimitry Andric   if (only_dir)
422e8d8bef9SDimitry Andric     CommandCompletions::DiskDirectories(path, matches, resolver);
423e8d8bef9SDimitry Andric   else
424e8d8bef9SDimitry Andric     CommandCompletions::DiskFiles(path, matches, resolver);
425e8d8bef9SDimitry Andric 
426e8d8bef9SDimitry Andric   StreamString response;
427e8d8bef9SDimitry Andric   response.PutChar('M');
428e8d8bef9SDimitry Andric   llvm::StringRef separator;
429e8d8bef9SDimitry Andric   std::sort(matches.begin(), matches.end());
430e8d8bef9SDimitry Andric   for (const auto &match : matches) {
431e8d8bef9SDimitry Andric     response << separator;
432e8d8bef9SDimitry Andric     separator = ",";
433e8d8bef9SDimitry Andric     // encode result strings into hex bytes to avoid unexpected error caused by
434e8d8bef9SDimitry Andric     // special characters like '$'.
435e8d8bef9SDimitry Andric     response.PutStringAsRawHex8(match.c_str());
436e8d8bef9SDimitry Andric   }
437e8d8bef9SDimitry Andric 
438e8d8bef9SDimitry Andric   return SendPacketNoLock(response.GetString());
439e8d8bef9SDimitry Andric }
440e8d8bef9SDimitry Andric 
441e8d8bef9SDimitry Andric GDBRemoteCommunication::PacketResult
4420b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
4430b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   llvm::SmallString<64> cwd;
4460b57cec5SDimitry Andric   if (std::error_code ec = llvm::sys::fs::current_path(cwd))
4470b57cec5SDimitry Andric     return SendErrorResponse(ec.value());
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   StreamString response;
4500b57cec5SDimitry Andric   response.PutBytesAsRawHex8(cwd.data(), cwd.size());
4510b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4550b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
4560b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4570b57cec5SDimitry Andric   packet.SetFilePos(::strlen("QSetWorkingDir:"));
4580b57cec5SDimitry Andric   std::string path;
4590b57cec5SDimitry Andric   packet.GetHexByteString(path);
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   if (std::error_code ec = llvm::sys::fs::set_current_path(path))
4620b57cec5SDimitry Andric     return SendErrorResponse(ec.value());
4630b57cec5SDimitry Andric   return SendOKResponse();
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4670b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_qC(
4680b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4690b57cec5SDimitry Andric   // NOTE: lldb should now be using qProcessInfo for process IDs.  This path
4700b57cec5SDimitry Andric   // here
4710b57cec5SDimitry Andric   // should not be used.  It is reporting process id instead of thread id.  The
4720b57cec5SDimitry Andric   // correct answer doesn't seem to make much sense for lldb-platform.
4730b57cec5SDimitry Andric   // CONSIDER: flip to "unsupported".
4740b57cec5SDimitry Andric   lldb::pid_t pid = m_process_launch_info.GetProcessID();
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   StreamString response;
4770b57cec5SDimitry Andric   response.Printf("QC%" PRIx64, pid);
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   // If we launch a process and this GDB server is acting as a platform, then
4800b57cec5SDimitry Andric   // we need to clear the process launch state so we can start launching
4810b57cec5SDimitry Andric   // another process. In order to launch a process a bunch or packets need to
4820b57cec5SDimitry Andric   // be sent: environment packets, working directory, disable ASLR, and many
4830b57cec5SDimitry Andric   // more settings. When we launch a process we then need to know when to clear
4840b57cec5SDimitry Andric   // this information. Currently we are selecting the 'qC' packet as that
4850b57cec5SDimitry Andric   // packet which seems to make the most sense.
4860b57cec5SDimitry Andric   if (pid != LLDB_INVALID_PROCESS_ID) {
4870b57cec5SDimitry Andric     m_process_launch_info.Clear();
4880b57cec5SDimitry Andric   }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
4910b57cec5SDimitry Andric }
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric GDBRemoteCommunication::PacketResult
4940b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
4950b57cec5SDimitry Andric     StringExtractorGDBRemote &packet) {
4960b57cec5SDimitry Andric   StructuredData::Array signal_array;
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   lldb::UnixSignalsSP signals = UnixSignals::CreateForHost();
4990b57cec5SDimitry Andric   for (auto signo = signals->GetFirstSignalNumber();
5000b57cec5SDimitry Andric        signo != LLDB_INVALID_SIGNAL_NUMBER;
5010b57cec5SDimitry Andric        signo = signals->GetNextSignalNumber(signo)) {
5020b57cec5SDimitry Andric     auto dictionary = std::make_shared<StructuredData::Dictionary>();
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric     dictionary->AddIntegerItem("signo", signo);
5055f757f3fSDimitry Andric     dictionary->AddStringItem("name", signals->GetSignalAsStringRef(signo));
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric     bool suppress, stop, notify;
5080b57cec5SDimitry Andric     signals->GetSignalInfo(signo, suppress, stop, notify);
5090b57cec5SDimitry Andric     dictionary->AddBooleanItem("suppress", suppress);
5100b57cec5SDimitry Andric     dictionary->AddBooleanItem("stop", stop);
5110b57cec5SDimitry Andric     dictionary->AddBooleanItem("notify", notify);
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric     signal_array.Push(dictionary);
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   StreamString response;
5170b57cec5SDimitry Andric   signal_array.Dump(response);
5180b57cec5SDimitry Andric   return SendPacketNoLock(response.GetString());
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric 
52181ad6265SDimitry Andric void GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
5220b57cec5SDimitry Andric     lldb::pid_t pid) {
5230b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
524e8d8bef9SDimitry Andric   m_port_map.FreePortForProcess(pid);
5250b57cec5SDimitry Andric   m_spawned_pids.erase(pid);
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
5290b57cec5SDimitry Andric   if (!m_process_launch_info.GetArguments().GetArgumentCount())
5300b57cec5SDimitry Andric     return Status("%s: no process command line specified to launch",
5310b57cec5SDimitry Andric                   __FUNCTION__);
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   // specify the process monitor if not already set.  This should generally be
5340b57cec5SDimitry Andric   // what happens since we need to reap started processes.
5350b57cec5SDimitry Andric   if (!m_process_launch_info.GetMonitorProcessCallback())
53681ad6265SDimitry Andric     m_process_launch_info.SetMonitorProcessCallback(std::bind(
53781ad6265SDimitry Andric         &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this,
53881ad6265SDimitry Andric         std::placeholders::_1));
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric   Status error = Host::LaunchProcess(m_process_launch_info);
5410b57cec5SDimitry Andric   if (!error.Success()) {
5420b57cec5SDimitry Andric     fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
5430b57cec5SDimitry Andric             m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
5440b57cec5SDimitry Andric     return error;
5450b57cec5SDimitry Andric   }
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   printf("Launched '%s' as process %" PRIu64 "...\n",
5480b57cec5SDimitry Andric          m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
5490b57cec5SDimitry Andric          m_process_launch_info.GetProcessID());
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric   // add to list of spawned processes.  On an lldb-gdbserver, we would expect
5520b57cec5SDimitry Andric   // there to be only one.
5530b57cec5SDimitry Andric   const auto pid = m_process_launch_info.GetProcessID();
5540b57cec5SDimitry Andric   if (pid != LLDB_INVALID_PROCESS_ID) {
5550b57cec5SDimitry Andric     // add to spawned pids
5560b57cec5SDimitry Andric     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
5570b57cec5SDimitry Andric     m_spawned_pids.insert(pid);
5580b57cec5SDimitry Andric   }
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   return error;
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
56406c3fb27SDimitry Andric   m_port_map = std::move(port_map);
5650b57cec5SDimitry Andric }
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
5680b57cec5SDimitry Andric   static FileSpec g_domainsocket_dir;
5690b57cec5SDimitry Andric   static llvm::once_flag g_once_flag;
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   llvm::call_once(g_once_flag, []() {
5720b57cec5SDimitry Andric     const char *domainsocket_dir_env =
5730b57cec5SDimitry Andric         ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
5740b57cec5SDimitry Andric     if (domainsocket_dir_env != nullptr)
5750b57cec5SDimitry Andric       g_domainsocket_dir = FileSpec(domainsocket_dir_env);
5760b57cec5SDimitry Andric     else
5770b57cec5SDimitry Andric       g_domainsocket_dir = HostInfo::GetProcessTempDir();
5780b57cec5SDimitry Andric   });
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   return g_domainsocket_dir;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric FileSpec
5840b57cec5SDimitry Andric GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
5850b57cec5SDimitry Andric   llvm::SmallString<128> socket_path;
5860b57cec5SDimitry Andric   llvm::SmallString<128> socket_name(
5870b57cec5SDimitry Andric       (llvm::StringRef(prefix) + ".%%%%%%").str());
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric   FileSpec socket_path_spec(GetDomainSocketDir());
5900b57cec5SDimitry Andric   socket_path_spec.AppendPathComponent(socket_name.c_str());
5910b57cec5SDimitry Andric 
592bdd1243dSDimitry Andric   llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(),
593bdd1243dSDimitry Andric                                   socket_path);
5940b57cec5SDimitry Andric   return FileSpec(socket_path.c_str());
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
5980b57cec5SDimitry Andric   m_port_offset = port_offset;
5990b57cec5SDimitry Andric }
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
6020b57cec5SDimitry Andric     lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
6030b57cec5SDimitry Andric   m_pending_gdb_server.pid = pid;
6040b57cec5SDimitry Andric   m_pending_gdb_server.port = port;
6050b57cec5SDimitry Andric   m_pending_gdb_server.socket_name = socket_name;
6060b57cec5SDimitry Andric }
607