blob: 3f8e34a58b0d8b45bc9638a308442cf8b465065c [file] [log] [blame]
Tamas Berghammere13c2732015-02-11 10:29:30 +00001//===-- GDBRemoteCommunicationServerPlatform.cpp ----------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "GDBRemoteCommunicationServerPlatform.h"
11
12#include <errno.h>
13
14// C Includes
15// C++ Includes
Tamas Berghammere13c2732015-02-11 10:29:30 +000016#include <chrono>
Kate Stoneb9c1b512016-09-06 20:57:50 +000017#include <cstring>
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000018#include <mutex>
19#include <sstream>
Tamas Berghammere13c2732015-02-11 10:29:30 +000020
21// Other libraries and framework includes
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000022#include "llvm/Support/FileSystem.h"
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +000023#include "llvm/Support/Threading.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000024
Tamas Berghammere13c2732015-02-11 10:29:30 +000025#include "lldb/Core/Log.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000026#include "lldb/Core/StreamGDBRemote.h"
Chaoren Lin98d0a4b2015-07-14 01:09:28 +000027#include "lldb/Core/StructuredData.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000028#include "lldb/Host/Config.h"
29#include "lldb/Host/ConnectionFileDescriptor.h"
30#include "lldb/Host/Host.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000031#include "lldb/Host/HostInfo.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000032#include "lldb/Host/StringConvert.h"
33#include "lldb/Target/FileAction.h"
34#include "lldb/Target/Platform.h"
35#include "lldb/Target/Process.h"
Chaoren Lin98d0a4b2015-07-14 01:09:28 +000036#include "lldb/Target/UnixSignals.h"
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000037#include "lldb/Utility/JSON.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000038#include "lldb/Utility/StreamString.h"
Pavel Labath5f7e5832017-02-10 12:21:22 +000039#include "lldb/Utility/UriParser.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000040
41// Project includes
42#include "Utility/StringExtractorGDBRemote.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000043
44using namespace lldb;
45using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000046using namespace lldb_private::process_gdb_remote;
Tamas Berghammere13c2732015-02-11 10:29:30 +000047
48//----------------------------------------------------------------------
49// GDBRemoteCommunicationServerPlatform constructor
50//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000051GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
52 const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
53 : GDBRemoteCommunicationServerCommon("gdb-remote.server",
54 "gdb-remote.server.rx_packet"),
55 m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
56 m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
57 m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
58 m_pending_gdb_server.port = 0;
Tamas Berghammer372810f2015-12-08 14:27:40 +000059
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 RegisterMemberFunctionHandler(
61 StringExtractorGDBRemote::eServerPacketType_qC,
62 &GDBRemoteCommunicationServerPlatform::Handle_qC);
63 RegisterMemberFunctionHandler(
64 StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
65 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
66 RegisterMemberFunctionHandler(
67 StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
68 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
69 RegisterMemberFunctionHandler(
70 StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
71 &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
72 RegisterMemberFunctionHandler(
73 StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
74 &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
75 RegisterMemberFunctionHandler(
76 StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
77 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
78 RegisterMemberFunctionHandler(
79 StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
80 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
81 RegisterMemberFunctionHandler(
82 StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
83 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
Tamas Berghammere13c2732015-02-11 10:29:30 +000084
Kate Stoneb9c1b512016-09-06 20:57:50 +000085 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
Zachary Turner3bc714b2017-03-02 00:05:25 +000086 [](StringExtractorGDBRemote packet, Error &error,
87 bool &interrupt, bool &quit) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000088 error.SetErrorString("interrupt received");
89 interrupt = true;
90 return PacketResult::Success;
91 });
Tamas Berghammere13c2732015-02-11 10:29:30 +000092}
93
94//----------------------------------------------------------------------
95// Destructor
96//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000097GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {}
Tamas Berghammere13c2732015-02-11 10:29:30 +000098
Kate Stoneb9c1b512016-09-06 20:57:50 +000099Error GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
100 const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
101 uint16_t &port, std::string &socket_name) {
102 if (port == UINT16_MAX)
103 port = GetNextAvailablePort();
Tamas Berghammere13c2732015-02-11 10:29:30 +0000104
Kate Stoneb9c1b512016-09-06 20:57:50 +0000105 // Spawn a new thread to accept the port that gets bound after
106 // binding to port 0 (zero).
Tamas Berghammere13c2732015-02-11 10:29:30 +0000107
Kate Stoneb9c1b512016-09-06 20:57:50 +0000108 // ignore the hostname send from the remote end, just use the ip address
109 // that we're currently communicating with as the hostname
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000110
Kate Stoneb9c1b512016-09-06 20:57:50 +0000111 // Spawn a debugserver and try to get the port it listens to.
112 ProcessLaunchInfo debugserver_launch_info;
113 if (hostname.empty())
114 hostname = "127.0.0.1";
Tamas Berghammere13c2732015-02-11 10:29:30 +0000115
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
117 if (log)
118 log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000119
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120 // Do not run in a new session so that it can not linger after the
121 // platform closes.
122 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
123 debugserver_launch_info.SetMonitorProcessCallback(
124 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
125 this, std::placeholders::_1),
126 false);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000127
Zachary Turner245f7fd2016-11-17 01:38:02 +0000128 llvm::StringRef platform_scheme;
129 llvm::StringRef platform_ip;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000130 int platform_port;
Zachary Turner245f7fd2016-11-17 01:38:02 +0000131 llvm::StringRef platform_path;
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000132 bool ok = UriParser::Parse(GetConnection()->GetURI(), platform_scheme,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133 platform_ip, platform_port, platform_path);
134 UNUSED_IF_ASSERT_DISABLED(ok);
135 assert(ok);
136
137 std::ostringstream url;
138// debugserver does not accept the URL scheme prefix.
Todd Fiala873a2ab2016-05-27 04:04:52 +0000139#if !defined(__APPLE__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140 url << m_socket_scheme << "://";
Todd Fiala873a2ab2016-05-27 04:04:52 +0000141#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142 uint16_t *port_ptr = &port;
143 if (m_socket_protocol == Socket::ProtocolTcp)
Zachary Turner245f7fd2016-11-17 01:38:02 +0000144 url << platform_ip.str() << ":" << port;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 else {
146 socket_name = GetDomainSocketPath("gdbserver").GetPath();
147 url << socket_name;
148 port_ptr = nullptr;
149 }
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000150
Kate Stoneb9c1b512016-09-06 20:57:50 +0000151 Error error = StartDebugserverProcess(
152 url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000153
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 pid = debugserver_launch_info.GetProcessID();
155 if (pid != LLDB_INVALID_PROCESS_ID) {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000156 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 m_spawned_pids.insert(pid);
158 if (port > 0)
159 AssociatePortWithProcess(port, pid);
160 } else {
161 if (port > 0)
162 FreePort(port);
163 }
164 return error;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000165}
166
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167GDBRemoteCommunication::PacketResult
168GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
169 StringExtractorGDBRemote &packet) {
170#ifdef _WIN32
171 return SendErrorResponse(9);
172#else
173 // Spawn a local debugserver as a platform so we can then attach or launch
174 // a process...
Tamas Berghammere13c2732015-02-11 10:29:30 +0000175
Kate Stoneb9c1b512016-09-06 20:57:50 +0000176 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
177 if (log)
178 log->Printf("GDBRemoteCommunicationServerPlatform::%s() called",
179 __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000180
Kate Stoneb9c1b512016-09-06 20:57:50 +0000181 ConnectionFileDescriptor file_conn;
182 std::string hostname;
183 packet.SetFilePos(::strlen("qLaunchGDBServer;"));
184 llvm::StringRef name;
185 llvm::StringRef value;
186 uint16_t port = UINT16_MAX;
187 while (packet.GetNameColonValue(name, value)) {
188 if (name.equals("host"))
189 hostname = value;
190 else if (name.equals("port"))
191 value.getAsInteger(0, port);
192 }
193
194 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
195 std::string socket_name;
196 Error error =
197 LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
198 if (error.Fail()) {
199 if (log)
200 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
201 "launch failed: %s",
202 __FUNCTION__, error.AsCString());
203 return SendErrorResponse(9);
204 }
205
206 if (log)
207 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
208 "launched successfully as pid %" PRIu64,
209 __FUNCTION__, debugserver_pid);
210
211 StreamGDBRemote response;
212 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
213 port + m_port_offset);
214 if (!socket_name.empty()) {
215 response.PutCString("socket_name:");
216 response.PutCStringAsRawHex8(socket_name.c_str());
217 response.PutChar(';');
218 }
219
220 PacketResult packet_result = SendPacketNoLock(response.GetString());
221 if (packet_result != PacketResult::Success) {
222 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
223 ::kill(debugserver_pid, SIGINT);
224 }
225 return packet_result;
226#endif
227}
228
229GDBRemoteCommunication::PacketResult
230GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
231 StringExtractorGDBRemote &packet) {
232 if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
233 return SendErrorResponse(4);
234
235 JSONObject::SP server_sp = std::make_shared<JSONObject>();
236 server_sp->SetObject("port",
237 std::make_shared<JSONNumber>(m_pending_gdb_server.port));
238 if (!m_pending_gdb_server.socket_name.empty())
239 server_sp->SetObject(
240 "socket_name",
241 std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
242
243 JSONArray server_list;
244 server_list.AppendObject(server_sp);
245
246 StreamGDBRemote response;
247 server_list.Write(response);
248
249 StreamGDBRemote escaped_response;
Zachary Turnerc1564272016-11-16 21:15:24 +0000250 escaped_response.PutEscapedBytes(response.GetString().data(),
251 response.GetSize());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 return SendPacketNoLock(escaped_response.GetString());
253}
254
255GDBRemoteCommunication::PacketResult
256GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
257 StringExtractorGDBRemote &packet) {
258 packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
259
260 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
261
262 // verify that we know anything about this pid.
263 // Scope for locker
264 {
265 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
266 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
267 // not a pid we know about
268 return SendErrorResponse(10);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000269 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000270 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000271
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272 // go ahead and attempt to kill the spawned process
273 if (KillSpawnedProcess(pid))
274 return SendOKResponse();
275 else
276 return SendErrorResponse(11);
277}
Tamas Berghammere13c2732015-02-11 10:29:30 +0000278
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
280 // make sure we know about this process
281 {
282 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
283 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
284 return false;
285 }
286
287 // first try a SIGTERM (standard kill)
288 Host::Kill(pid, SIGTERM);
289
290 // check if that worked
291 for (size_t i = 0; i < 10; ++i) {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000292 {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
294 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
295 // it is now killed
296 return true;
297 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000298 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299 usleep(10000);
300 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000301
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302 // check one more time after the final usleep
303 {
304 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
305 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
306 return true;
307 }
308
309 // the launched process still lives. Now try killing it again,
310 // this time with an unblockable signal.
311 Host::Kill(pid, SIGKILL);
312
313 for (size_t i = 0; i < 10; ++i) {
314 {
315 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
316 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
317 // it is now killed
318 return true;
319 }
320 }
321 usleep(10000);
322 }
323
324 // check one more time after the final usleep
325 // Scope for locker
326 {
327 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
328 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
329 return true;
330 }
331
332 // no luck - the process still lives
333 return false;
334}
335
336GDBRemoteCommunication::PacketResult
337GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
338 StringExtractorGDBRemote &packet) {
339 lldb::pid_t pid = m_process_launch_info.GetProcessID();
340 m_process_launch_info.Clear();
341
342 if (pid == LLDB_INVALID_PROCESS_ID)
343 return SendErrorResponse(1);
344
345 ProcessInstanceInfo proc_info;
346 if (!Host::GetProcessInfo(pid, proc_info))
347 return SendErrorResponse(1);
348
349 StreamString response;
350 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
351 return SendPacketNoLock(response.GetString());
352}
353
354GDBRemoteCommunication::PacketResult
355GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
356 StringExtractorGDBRemote &packet) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357
Pavel Labath1d5855b2017-01-23 15:56:45 +0000358 llvm::SmallString<64> cwd;
359 if (std::error_code ec = llvm::sys::fs::current_path(cwd))
360 return SendErrorResponse(ec.value());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000361
362 StreamString response;
Pavel Labath1d5855b2017-01-23 15:56:45 +0000363 response.PutBytesAsRawHex8(cwd.data(), cwd.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364 return SendPacketNoLock(response.GetString());
365}
366
367GDBRemoteCommunication::PacketResult
368GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
369 StringExtractorGDBRemote &packet) {
370 packet.SetFilePos(::strlen("QSetWorkingDir:"));
371 std::string path;
372 packet.GetHexByteString(path);
373
Pavel Labath2d0c5b02017-01-25 11:10:52 +0000374 if (std::error_code ec = llvm::sys::fs::set_current_path(path))
375 return SendErrorResponse(ec.value());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000376 return SendOKResponse();
377}
378
379GDBRemoteCommunication::PacketResult
380GDBRemoteCommunicationServerPlatform::Handle_qC(
381 StringExtractorGDBRemote &packet) {
382 // NOTE: lldb should now be using qProcessInfo for process IDs. This path
383 // here
384 // should not be used. It is reporting process id instead of thread id. The
385 // correct answer doesn't seem to make much sense for lldb-platform.
386 // CONSIDER: flip to "unsupported".
387 lldb::pid_t pid = m_process_launch_info.GetProcessID();
388
389 StreamString response;
390 response.Printf("QC%" PRIx64, pid);
391
392 // If we launch a process and this GDB server is acting as a platform,
393 // then we need to clear the process launch state so we can start
394 // launching another process. In order to launch a process a bunch or
395 // packets need to be sent: environment packets, working directory,
396 // disable ASLR, and many more settings. When we launch a process we
397 // then need to know when to clear this information. Currently we are
398 // selecting the 'qC' packet as that packet which seems to make the most
399 // sense.
400 if (pid != LLDB_INVALID_PROCESS_ID) {
401 m_process_launch_info.Clear();
402 }
403
404 return SendPacketNoLock(response.GetString());
405}
406
407GDBRemoteCommunication::PacketResult
408GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
409 StringExtractorGDBRemote &packet) {
410 StructuredData::Array signal_array;
411
412 const auto &signals = Host::GetUnixSignals();
413 for (auto signo = signals->GetFirstSignalNumber();
414 signo != LLDB_INVALID_SIGNAL_NUMBER;
415 signo = signals->GetNextSignalNumber(signo)) {
416 auto dictionary = std::make_shared<StructuredData::Dictionary>();
417
418 dictionary->AddIntegerItem("signo", signo);
419 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
420
421 bool suppress, stop, notify;
422 signals->GetSignalInfo(signo, suppress, stop, notify);
423 dictionary->AddBooleanItem("suppress", suppress);
424 dictionary->AddBooleanItem("stop", stop);
425 dictionary->AddBooleanItem("notify", notify);
426
427 signal_array.Push(dictionary);
428 }
429
430 StreamString response;
431 signal_array.Dump(response);
432 return SendPacketNoLock(response.GetString());
433}
434
435bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
436 lldb::pid_t pid) {
437 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
438 FreePortForProcess(pid);
439 m_spawned_pids.erase(pid);
440 return true;
441}
442
443Error GDBRemoteCommunicationServerPlatform::LaunchProcess() {
444 if (!m_process_launch_info.GetArguments().GetArgumentCount())
445 return Error("%s: no process command line specified to launch",
446 __FUNCTION__);
447
448 // specify the process monitor if not already set. This should
449 // generally be what happens since we need to reap started
450 // processes.
451 if (!m_process_launch_info.GetMonitorProcessCallback())
452 m_process_launch_info.SetMonitorProcessCallback(
453 std::bind(
454 &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
455 this, std::placeholders::_1),
456 false);
457
458 Error error = Host::LaunchProcess(m_process_launch_info);
459 if (!error.Success()) {
460 fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
461 m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
Tamas Berghammere13c2732015-02-11 10:29:30 +0000462 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000463 }
464
465 printf("Launched '%s' as process %" PRIu64 "...\n",
466 m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
467 m_process_launch_info.GetProcessID());
468
469 // add to list of spawned processes. On an lldb-gdbserver, we
470 // would expect there to be only one.
471 const auto pid = m_process_launch_info.GetProcessID();
472 if (pid != LLDB_INVALID_PROCESS_ID) {
473 // add to spawned pids
474 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
475 m_spawned_pids.insert(pid);
476 }
477
478 return error;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000479}
480
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
482 m_port_map = port_map;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000483}
484
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485uint16_t GDBRemoteCommunicationServerPlatform::GetNextAvailablePort() {
486 if (m_port_map.empty())
487 return 0; // Bind to port zero and get a port, we didn't have any
488 // limitations
Tamas Berghammere13c2732015-02-11 10:29:30 +0000489
Kate Stoneb9c1b512016-09-06 20:57:50 +0000490 for (auto &pair : m_port_map) {
491 if (pair.second == LLDB_INVALID_PROCESS_ID) {
492 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
493 return pair.first;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000494 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000495 }
496 return UINT16_MAX;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000497}
498
Kate Stoneb9c1b512016-09-06 20:57:50 +0000499bool GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess(
500 uint16_t port, lldb::pid_t pid) {
501 PortMap::iterator pos = m_port_map.find(port);
502 if (pos != m_port_map.end()) {
503 pos->second = pid;
504 return true;
505 }
506 return false;
507}
508
509bool GDBRemoteCommunicationServerPlatform::FreePort(uint16_t port) {
510 PortMap::iterator pos = m_port_map.find(port);
511 if (pos != m_port_map.end()) {
512 pos->second = LLDB_INVALID_PROCESS_ID;
513 return true;
514 }
515 return false;
516}
517
518bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) {
519 if (!m_port_map.empty()) {
520 for (auto &pair : m_port_map) {
521 if (pair.second == pid) {
522 pair.second = LLDB_INVALID_PROCESS_ID;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000523 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000524 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000525 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000526 }
527 return false;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000528}
529
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
531 static FileSpec g_domainsocket_dir;
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000532 static llvm::once_flag g_once_flag;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000533
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000534 llvm::call_once(g_once_flag, []() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000535 const char *domainsocket_dir_env =
536 ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
537 if (domainsocket_dir_env != nullptr)
538 g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
539 else
540 HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
541 });
Tamas Berghammere13c2732015-02-11 10:29:30 +0000542
Kate Stoneb9c1b512016-09-06 20:57:50 +0000543 return g_domainsocket_dir;
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000544}
545
546FileSpec
Kate Stoneb9c1b512016-09-06 20:57:50 +0000547GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
548 llvm::SmallString<PATH_MAX> socket_path;
549 llvm::SmallString<PATH_MAX> socket_name(
550 (llvm::StringRef(prefix) + ".%%%%%%").str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000551
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552 FileSpec socket_path_spec(GetDomainSocketDir());
553 socket_path_spec.AppendPathComponent(socket_name.c_str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000554
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555 llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
556 return FileSpec(socket_path.c_str(), false);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000557}
558
Kate Stoneb9c1b512016-09-06 20:57:50 +0000559void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
560 m_port_offset = port_offset;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000561}
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000562
Kate Stoneb9c1b512016-09-06 20:57:50 +0000563void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
564 lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
565 m_pending_gdb_server.pid = pid;
566 m_pending_gdb_server.port = port;
567 m_pending_gdb_server.socket_name = socket_name;
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000568}