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