1*dda28197Spatrick //===-- GDBRemoteCommunicationServerPlatform.cpp --------------------------===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "GDBRemoteCommunicationServerPlatform.h" 10061da546Spatrick 11061da546Spatrick #include <errno.h> 12061da546Spatrick 13061da546Spatrick #include <chrono> 14061da546Spatrick #include <csignal> 15061da546Spatrick #include <cstring> 16061da546Spatrick #include <mutex> 17061da546Spatrick #include <sstream> 18061da546Spatrick #include <thread> 19061da546Spatrick 20061da546Spatrick #include "llvm/Support/FileSystem.h" 21061da546Spatrick #include "llvm/Support/JSON.h" 22061da546Spatrick #include "llvm/Support/Threading.h" 23061da546Spatrick 24061da546Spatrick #include "lldb/Host/Config.h" 25061da546Spatrick #include "lldb/Host/ConnectionFileDescriptor.h" 26061da546Spatrick #include "lldb/Host/FileAction.h" 27061da546Spatrick #include "lldb/Host/Host.h" 28061da546Spatrick #include "lldb/Host/HostInfo.h" 29061da546Spatrick #include "lldb/Target/Platform.h" 30061da546Spatrick #include "lldb/Target/UnixSignals.h" 31061da546Spatrick #include "lldb/Utility/GDBRemote.h" 32061da546Spatrick #include "lldb/Utility/Log.h" 33061da546Spatrick #include "lldb/Utility/StreamString.h" 34061da546Spatrick #include "lldb/Utility/StructuredData.h" 35061da546Spatrick #include "lldb/Utility/UriParser.h" 36061da546Spatrick 37061da546Spatrick #include "lldb/Utility/StringExtractorGDBRemote.h" 38061da546Spatrick 39061da546Spatrick using namespace lldb; 40061da546Spatrick using namespace lldb_private::process_gdb_remote; 41061da546Spatrick using namespace lldb_private; 42061da546Spatrick 43061da546Spatrick // GDBRemoteCommunicationServerPlatform constructor 44061da546Spatrick GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( 45061da546Spatrick const Socket::SocketProtocol socket_protocol, const char *socket_scheme) 46061da546Spatrick : GDBRemoteCommunicationServerCommon("gdb-remote.server", 47061da546Spatrick "gdb-remote.server.rx_packet"), 48061da546Spatrick m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme), 49061da546Spatrick m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) { 50061da546Spatrick m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; 51061da546Spatrick m_pending_gdb_server.port = 0; 52061da546Spatrick 53061da546Spatrick RegisterMemberFunctionHandler( 54061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qC, 55061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qC); 56061da546Spatrick RegisterMemberFunctionHandler( 57061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, 58061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir); 59061da546Spatrick RegisterMemberFunctionHandler( 60061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer, 61061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer); 62061da546Spatrick RegisterMemberFunctionHandler( 63061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer, 64061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer); 65061da546Spatrick RegisterMemberFunctionHandler( 66061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess, 67061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess); 68061da546Spatrick RegisterMemberFunctionHandler( 69061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qProcessInfo, 70061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo); 71061da546Spatrick RegisterMemberFunctionHandler( 72061da546Spatrick StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, 73061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir); 74061da546Spatrick RegisterMemberFunctionHandler( 75061da546Spatrick StringExtractorGDBRemote::eServerPacketType_jSignalsInfo, 76061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo); 77061da546Spatrick 78061da546Spatrick RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, 79061da546Spatrick [](StringExtractorGDBRemote packet, Status &error, 80061da546Spatrick bool &interrupt, bool &quit) { 81061da546Spatrick error.SetErrorString("interrupt received"); 82061da546Spatrick interrupt = true; 83061da546Spatrick return PacketResult::Success; 84061da546Spatrick }); 85061da546Spatrick } 86061da546Spatrick 87061da546Spatrick // Destructor 88061da546Spatrick GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {} 89061da546Spatrick 90061da546Spatrick Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( 91061da546Spatrick const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid, 92061da546Spatrick uint16_t &port, std::string &socket_name) { 93061da546Spatrick if (port == UINT16_MAX) 94061da546Spatrick port = GetNextAvailablePort(); 95061da546Spatrick 96061da546Spatrick // Spawn a new thread to accept the port that gets bound after binding to 97061da546Spatrick // port 0 (zero). 98061da546Spatrick 99061da546Spatrick // ignore the hostname send from the remote end, just use the ip address that 100061da546Spatrick // we're currently communicating with as the hostname 101061da546Spatrick 102061da546Spatrick // Spawn a debugserver and try to get the port it listens to. 103061da546Spatrick ProcessLaunchInfo debugserver_launch_info; 104061da546Spatrick if (hostname.empty()) 105061da546Spatrick hostname = "127.0.0.1"; 106061da546Spatrick 107061da546Spatrick Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 108061da546Spatrick LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(), 109061da546Spatrick port); 110061da546Spatrick 111061da546Spatrick // Do not run in a new session so that it can not linger after the platform 112061da546Spatrick // closes. 113061da546Spatrick debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); 114061da546Spatrick debugserver_launch_info.SetMonitorProcessCallback( 115061da546Spatrick std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, 116061da546Spatrick this, std::placeholders::_1), 117061da546Spatrick false); 118061da546Spatrick 119061da546Spatrick std::ostringstream url; 120061da546Spatrick // debugserver does not accept the URL scheme prefix. 121061da546Spatrick #if !defined(__APPLE__) 122061da546Spatrick url << m_socket_scheme << "://"; 123061da546Spatrick #endif 124061da546Spatrick uint16_t *port_ptr = &port; 125061da546Spatrick if (m_socket_protocol == Socket::ProtocolTcp) { 126061da546Spatrick llvm::StringRef platform_scheme; 127061da546Spatrick llvm::StringRef platform_ip; 128061da546Spatrick int platform_port; 129061da546Spatrick llvm::StringRef platform_path; 130061da546Spatrick std::string platform_uri = GetConnection()->GetURI(); 131061da546Spatrick bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip, 132061da546Spatrick platform_port, platform_path); 133061da546Spatrick UNUSED_IF_ASSERT_DISABLED(ok); 134061da546Spatrick assert(ok); 135061da546Spatrick url << platform_ip.str() << ":" << port; 136061da546Spatrick } else { 137061da546Spatrick socket_name = GetDomainSocketPath("gdbserver").GetPath(); 138061da546Spatrick url << socket_name; 139061da546Spatrick port_ptr = nullptr; 140061da546Spatrick } 141061da546Spatrick 142061da546Spatrick Status error = StartDebugserverProcess( 143061da546Spatrick url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1); 144061da546Spatrick 145061da546Spatrick pid = debugserver_launch_info.GetProcessID(); 146061da546Spatrick if (pid != LLDB_INVALID_PROCESS_ID) { 147061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 148061da546Spatrick m_spawned_pids.insert(pid); 149061da546Spatrick if (port > 0) 150061da546Spatrick AssociatePortWithProcess(port, pid); 151061da546Spatrick } else { 152061da546Spatrick if (port > 0) 153061da546Spatrick FreePort(port); 154061da546Spatrick } 155061da546Spatrick return error; 156061da546Spatrick } 157061da546Spatrick 158061da546Spatrick GDBRemoteCommunication::PacketResult 159061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer( 160061da546Spatrick StringExtractorGDBRemote &packet) { 161061da546Spatrick // Spawn a local debugserver as a platform so we can then attach or launch a 162061da546Spatrick // process... 163061da546Spatrick 164061da546Spatrick Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 165061da546Spatrick LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called", 166061da546Spatrick __FUNCTION__); 167061da546Spatrick 168061da546Spatrick ConnectionFileDescriptor file_conn; 169061da546Spatrick std::string hostname; 170061da546Spatrick packet.SetFilePos(::strlen("qLaunchGDBServer;")); 171061da546Spatrick llvm::StringRef name; 172061da546Spatrick llvm::StringRef value; 173061da546Spatrick uint16_t port = UINT16_MAX; 174061da546Spatrick while (packet.GetNameColonValue(name, value)) { 175061da546Spatrick if (name.equals("host")) 176*dda28197Spatrick hostname = std::string(value); 177061da546Spatrick else if (name.equals("port")) 178061da546Spatrick value.getAsInteger(0, port); 179061da546Spatrick } 180061da546Spatrick 181061da546Spatrick lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 182061da546Spatrick std::string socket_name; 183061da546Spatrick Status error = 184061da546Spatrick LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); 185061da546Spatrick if (error.Fail()) { 186061da546Spatrick LLDB_LOGF(log, 187061da546Spatrick "GDBRemoteCommunicationServerPlatform::%s() debugserver " 188061da546Spatrick "launch failed: %s", 189061da546Spatrick __FUNCTION__, error.AsCString()); 190061da546Spatrick return SendErrorResponse(9); 191061da546Spatrick } 192061da546Spatrick 193061da546Spatrick LLDB_LOGF(log, 194061da546Spatrick "GDBRemoteCommunicationServerPlatform::%s() debugserver " 195061da546Spatrick "launched successfully as pid %" PRIu64, 196061da546Spatrick __FUNCTION__, debugserver_pid); 197061da546Spatrick 198061da546Spatrick StreamGDBRemote response; 199061da546Spatrick response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, 200061da546Spatrick port + m_port_offset); 201061da546Spatrick if (!socket_name.empty()) { 202061da546Spatrick response.PutCString("socket_name:"); 203061da546Spatrick response.PutStringAsRawHex8(socket_name); 204061da546Spatrick response.PutChar(';'); 205061da546Spatrick } 206061da546Spatrick 207061da546Spatrick PacketResult packet_result = SendPacketNoLock(response.GetString()); 208061da546Spatrick if (packet_result != PacketResult::Success) { 209061da546Spatrick if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 210061da546Spatrick Host::Kill(debugserver_pid, SIGINT); 211061da546Spatrick } 212061da546Spatrick return packet_result; 213061da546Spatrick } 214061da546Spatrick 215061da546Spatrick GDBRemoteCommunication::PacketResult 216061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer( 217061da546Spatrick StringExtractorGDBRemote &packet) { 218061da546Spatrick namespace json = llvm::json; 219061da546Spatrick 220061da546Spatrick if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) 221061da546Spatrick return SendErrorResponse(4); 222061da546Spatrick 223061da546Spatrick json::Object server{{"port", m_pending_gdb_server.port}}; 224061da546Spatrick 225061da546Spatrick if (!m_pending_gdb_server.socket_name.empty()) 226061da546Spatrick server.try_emplace("socket_name", m_pending_gdb_server.socket_name); 227061da546Spatrick 228061da546Spatrick json::Array server_list; 229061da546Spatrick server_list.push_back(std::move(server)); 230061da546Spatrick 231061da546Spatrick StreamGDBRemote response; 232061da546Spatrick response.AsRawOstream() << std::move(server_list); 233061da546Spatrick 234061da546Spatrick StreamGDBRemote escaped_response; 235061da546Spatrick escaped_response.PutEscapedBytes(response.GetString().data(), 236061da546Spatrick response.GetSize()); 237061da546Spatrick return SendPacketNoLock(escaped_response.GetString()); 238061da546Spatrick } 239061da546Spatrick 240061da546Spatrick GDBRemoteCommunication::PacketResult 241061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess( 242061da546Spatrick StringExtractorGDBRemote &packet) { 243061da546Spatrick packet.SetFilePos(::strlen("qKillSpawnedProcess:")); 244061da546Spatrick 245061da546Spatrick lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); 246061da546Spatrick 247061da546Spatrick // verify that we know anything about this pid. Scope for locker 248061da546Spatrick { 249061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 250061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { 251061da546Spatrick // not a pid we know about 252061da546Spatrick return SendErrorResponse(10); 253061da546Spatrick } 254061da546Spatrick } 255061da546Spatrick 256061da546Spatrick // go ahead and attempt to kill the spawned process 257061da546Spatrick if (KillSpawnedProcess(pid)) 258061da546Spatrick return SendOKResponse(); 259061da546Spatrick else 260061da546Spatrick return SendErrorResponse(11); 261061da546Spatrick } 262061da546Spatrick 263061da546Spatrick bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) { 264061da546Spatrick // make sure we know about this process 265061da546Spatrick { 266061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 267061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 268061da546Spatrick return false; 269061da546Spatrick } 270061da546Spatrick 271061da546Spatrick // first try a SIGTERM (standard kill) 272061da546Spatrick Host::Kill(pid, SIGTERM); 273061da546Spatrick 274061da546Spatrick // check if that worked 275061da546Spatrick for (size_t i = 0; i < 10; ++i) { 276061da546Spatrick { 277061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 278061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { 279061da546Spatrick // it is now killed 280061da546Spatrick return true; 281061da546Spatrick } 282061da546Spatrick } 283061da546Spatrick std::this_thread::sleep_for(std::chrono::milliseconds(10)); 284061da546Spatrick } 285061da546Spatrick 286061da546Spatrick { 287061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 288061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 289061da546Spatrick return true; 290061da546Spatrick } 291061da546Spatrick 292061da546Spatrick // the launched process still lives. Now try killing it again, this time 293061da546Spatrick // with an unblockable signal. 294061da546Spatrick Host::Kill(pid, SIGKILL); 295061da546Spatrick 296061da546Spatrick for (size_t i = 0; i < 10; ++i) { 297061da546Spatrick { 298061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 299061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { 300061da546Spatrick // it is now killed 301061da546Spatrick return true; 302061da546Spatrick } 303061da546Spatrick } 304061da546Spatrick std::this_thread::sleep_for(std::chrono::milliseconds(10)); 305061da546Spatrick } 306061da546Spatrick 307061da546Spatrick // check one more time after the final sleep 308061da546Spatrick { 309061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 310061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 311061da546Spatrick return true; 312061da546Spatrick } 313061da546Spatrick 314061da546Spatrick // no luck - the process still lives 315061da546Spatrick return false; 316061da546Spatrick } 317061da546Spatrick 318061da546Spatrick GDBRemoteCommunication::PacketResult 319061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo( 320061da546Spatrick StringExtractorGDBRemote &packet) { 321061da546Spatrick lldb::pid_t pid = m_process_launch_info.GetProcessID(); 322061da546Spatrick m_process_launch_info.Clear(); 323061da546Spatrick 324061da546Spatrick if (pid == LLDB_INVALID_PROCESS_ID) 325061da546Spatrick return SendErrorResponse(1); 326061da546Spatrick 327061da546Spatrick ProcessInstanceInfo proc_info; 328061da546Spatrick if (!Host::GetProcessInfo(pid, proc_info)) 329061da546Spatrick return SendErrorResponse(1); 330061da546Spatrick 331061da546Spatrick StreamString response; 332061da546Spatrick CreateProcessInfoResponse_DebugServerStyle(proc_info, response); 333061da546Spatrick return SendPacketNoLock(response.GetString()); 334061da546Spatrick } 335061da546Spatrick 336061da546Spatrick GDBRemoteCommunication::PacketResult 337061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir( 338061da546Spatrick StringExtractorGDBRemote &packet) { 339061da546Spatrick 340061da546Spatrick llvm::SmallString<64> cwd; 341061da546Spatrick if (std::error_code ec = llvm::sys::fs::current_path(cwd)) 342061da546Spatrick return SendErrorResponse(ec.value()); 343061da546Spatrick 344061da546Spatrick StreamString response; 345061da546Spatrick response.PutBytesAsRawHex8(cwd.data(), cwd.size()); 346061da546Spatrick return SendPacketNoLock(response.GetString()); 347061da546Spatrick } 348061da546Spatrick 349061da546Spatrick GDBRemoteCommunication::PacketResult 350061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir( 351061da546Spatrick StringExtractorGDBRemote &packet) { 352061da546Spatrick packet.SetFilePos(::strlen("QSetWorkingDir:")); 353061da546Spatrick std::string path; 354061da546Spatrick packet.GetHexByteString(path); 355061da546Spatrick 356061da546Spatrick if (std::error_code ec = llvm::sys::fs::set_current_path(path)) 357061da546Spatrick return SendErrorResponse(ec.value()); 358061da546Spatrick return SendOKResponse(); 359061da546Spatrick } 360061da546Spatrick 361061da546Spatrick GDBRemoteCommunication::PacketResult 362061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qC( 363061da546Spatrick StringExtractorGDBRemote &packet) { 364061da546Spatrick // NOTE: lldb should now be using qProcessInfo for process IDs. This path 365061da546Spatrick // here 366061da546Spatrick // should not be used. It is reporting process id instead of thread id. The 367061da546Spatrick // correct answer doesn't seem to make much sense for lldb-platform. 368061da546Spatrick // CONSIDER: flip to "unsupported". 369061da546Spatrick lldb::pid_t pid = m_process_launch_info.GetProcessID(); 370061da546Spatrick 371061da546Spatrick StreamString response; 372061da546Spatrick response.Printf("QC%" PRIx64, pid); 373061da546Spatrick 374061da546Spatrick // If we launch a process and this GDB server is acting as a platform, then 375061da546Spatrick // we need to clear the process launch state so we can start launching 376061da546Spatrick // another process. In order to launch a process a bunch or packets need to 377061da546Spatrick // be sent: environment packets, working directory, disable ASLR, and many 378061da546Spatrick // more settings. When we launch a process we then need to know when to clear 379061da546Spatrick // this information. Currently we are selecting the 'qC' packet as that 380061da546Spatrick // packet which seems to make the most sense. 381061da546Spatrick if (pid != LLDB_INVALID_PROCESS_ID) { 382061da546Spatrick m_process_launch_info.Clear(); 383061da546Spatrick } 384061da546Spatrick 385061da546Spatrick return SendPacketNoLock(response.GetString()); 386061da546Spatrick } 387061da546Spatrick 388061da546Spatrick GDBRemoteCommunication::PacketResult 389061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo( 390061da546Spatrick StringExtractorGDBRemote &packet) { 391061da546Spatrick StructuredData::Array signal_array; 392061da546Spatrick 393061da546Spatrick lldb::UnixSignalsSP signals = UnixSignals::CreateForHost(); 394061da546Spatrick for (auto signo = signals->GetFirstSignalNumber(); 395061da546Spatrick signo != LLDB_INVALID_SIGNAL_NUMBER; 396061da546Spatrick signo = signals->GetNextSignalNumber(signo)) { 397061da546Spatrick auto dictionary = std::make_shared<StructuredData::Dictionary>(); 398061da546Spatrick 399061da546Spatrick dictionary->AddIntegerItem("signo", signo); 400061da546Spatrick dictionary->AddStringItem("name", signals->GetSignalAsCString(signo)); 401061da546Spatrick 402061da546Spatrick bool suppress, stop, notify; 403061da546Spatrick signals->GetSignalInfo(signo, suppress, stop, notify); 404061da546Spatrick dictionary->AddBooleanItem("suppress", suppress); 405061da546Spatrick dictionary->AddBooleanItem("stop", stop); 406061da546Spatrick dictionary->AddBooleanItem("notify", notify); 407061da546Spatrick 408061da546Spatrick signal_array.Push(dictionary); 409061da546Spatrick } 410061da546Spatrick 411061da546Spatrick StreamString response; 412061da546Spatrick signal_array.Dump(response); 413061da546Spatrick return SendPacketNoLock(response.GetString()); 414061da546Spatrick } 415061da546Spatrick 416061da546Spatrick bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped( 417061da546Spatrick lldb::pid_t pid) { 418061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 419061da546Spatrick FreePortForProcess(pid); 420061da546Spatrick m_spawned_pids.erase(pid); 421061da546Spatrick return true; 422061da546Spatrick } 423061da546Spatrick 424061da546Spatrick Status GDBRemoteCommunicationServerPlatform::LaunchProcess() { 425061da546Spatrick if (!m_process_launch_info.GetArguments().GetArgumentCount()) 426061da546Spatrick return Status("%s: no process command line specified to launch", 427061da546Spatrick __FUNCTION__); 428061da546Spatrick 429061da546Spatrick // specify the process monitor if not already set. This should generally be 430061da546Spatrick // what happens since we need to reap started processes. 431061da546Spatrick if (!m_process_launch_info.GetMonitorProcessCallback()) 432061da546Spatrick m_process_launch_info.SetMonitorProcessCallback( 433061da546Spatrick std::bind( 434061da546Spatrick &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, 435061da546Spatrick this, std::placeholders::_1), 436061da546Spatrick false); 437061da546Spatrick 438061da546Spatrick Status error = Host::LaunchProcess(m_process_launch_info); 439061da546Spatrick if (!error.Success()) { 440061da546Spatrick fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__, 441061da546Spatrick m_process_launch_info.GetArguments().GetArgumentAtIndex(0)); 442061da546Spatrick return error; 443061da546Spatrick } 444061da546Spatrick 445061da546Spatrick printf("Launched '%s' as process %" PRIu64 "...\n", 446061da546Spatrick m_process_launch_info.GetArguments().GetArgumentAtIndex(0), 447061da546Spatrick m_process_launch_info.GetProcessID()); 448061da546Spatrick 449061da546Spatrick // add to list of spawned processes. On an lldb-gdbserver, we would expect 450061da546Spatrick // there to be only one. 451061da546Spatrick const auto pid = m_process_launch_info.GetProcessID(); 452061da546Spatrick if (pid != LLDB_INVALID_PROCESS_ID) { 453061da546Spatrick // add to spawned pids 454061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); 455061da546Spatrick m_spawned_pids.insert(pid); 456061da546Spatrick } 457061da546Spatrick 458061da546Spatrick return error; 459061da546Spatrick } 460061da546Spatrick 461061da546Spatrick void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) { 462061da546Spatrick m_port_map = port_map; 463061da546Spatrick } 464061da546Spatrick 465061da546Spatrick uint16_t GDBRemoteCommunicationServerPlatform::GetNextAvailablePort() { 466061da546Spatrick if (m_port_map.empty()) 467061da546Spatrick return 0; // Bind to port zero and get a port, we didn't have any 468061da546Spatrick // limitations 469061da546Spatrick 470061da546Spatrick for (auto &pair : m_port_map) { 471061da546Spatrick if (pair.second == LLDB_INVALID_PROCESS_ID) { 472061da546Spatrick pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID; 473061da546Spatrick return pair.first; 474061da546Spatrick } 475061da546Spatrick } 476061da546Spatrick return UINT16_MAX; 477061da546Spatrick } 478061da546Spatrick 479061da546Spatrick bool GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess( 480061da546Spatrick uint16_t port, lldb::pid_t pid) { 481061da546Spatrick PortMap::iterator pos = m_port_map.find(port); 482061da546Spatrick if (pos != m_port_map.end()) { 483061da546Spatrick pos->second = pid; 484061da546Spatrick return true; 485061da546Spatrick } 486061da546Spatrick return false; 487061da546Spatrick } 488061da546Spatrick 489061da546Spatrick bool GDBRemoteCommunicationServerPlatform::FreePort(uint16_t port) { 490061da546Spatrick PortMap::iterator pos = m_port_map.find(port); 491061da546Spatrick if (pos != m_port_map.end()) { 492061da546Spatrick pos->second = LLDB_INVALID_PROCESS_ID; 493061da546Spatrick return true; 494061da546Spatrick } 495061da546Spatrick return false; 496061da546Spatrick } 497061da546Spatrick 498061da546Spatrick bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) { 499061da546Spatrick if (!m_port_map.empty()) { 500061da546Spatrick for (auto &pair : m_port_map) { 501061da546Spatrick if (pair.second == pid) { 502061da546Spatrick pair.second = LLDB_INVALID_PROCESS_ID; 503061da546Spatrick return true; 504061da546Spatrick } 505061da546Spatrick } 506061da546Spatrick } 507061da546Spatrick return false; 508061da546Spatrick } 509061da546Spatrick 510061da546Spatrick const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() { 511061da546Spatrick static FileSpec g_domainsocket_dir; 512061da546Spatrick static llvm::once_flag g_once_flag; 513061da546Spatrick 514061da546Spatrick llvm::call_once(g_once_flag, []() { 515061da546Spatrick const char *domainsocket_dir_env = 516061da546Spatrick ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR"); 517061da546Spatrick if (domainsocket_dir_env != nullptr) 518061da546Spatrick g_domainsocket_dir = FileSpec(domainsocket_dir_env); 519061da546Spatrick else 520061da546Spatrick g_domainsocket_dir = HostInfo::GetProcessTempDir(); 521061da546Spatrick }); 522061da546Spatrick 523061da546Spatrick return g_domainsocket_dir; 524061da546Spatrick } 525061da546Spatrick 526061da546Spatrick FileSpec 527061da546Spatrick GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) { 528061da546Spatrick llvm::SmallString<128> socket_path; 529061da546Spatrick llvm::SmallString<128> socket_name( 530061da546Spatrick (llvm::StringRef(prefix) + ".%%%%%%").str()); 531061da546Spatrick 532061da546Spatrick FileSpec socket_path_spec(GetDomainSocketDir()); 533061da546Spatrick socket_path_spec.AppendPathComponent(socket_name.c_str()); 534061da546Spatrick 535061da546Spatrick llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path); 536061da546Spatrick return FileSpec(socket_path.c_str()); 537061da546Spatrick } 538061da546Spatrick 539061da546Spatrick void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) { 540061da546Spatrick m_port_offset = port_offset; 541061da546Spatrick } 542061da546Spatrick 543061da546Spatrick void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer( 544061da546Spatrick lldb::pid_t pid, uint16_t port, const std::string &socket_name) { 545061da546Spatrick m_pending_gdb_server.pid = pid; 546061da546Spatrick m_pending_gdb_server.port = port; 547061da546Spatrick m_pending_gdb_server.socket_name = socket_name; 548061da546Spatrick } 549