blob: 26e28a900320adce7c43f8322b3dae8993c5f88d [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>
Pavel Labath6b3c8bb2018-04-05 16:23:54 +000017#include <csignal>
Kate Stoneb9c1b512016-09-06 20:57:50 +000018#include <cstring>
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000019#include <mutex>
20#include <sstream>
Tamas Berghammere13c2732015-02-11 10:29:30 +000021
22// Other libraries and framework includes
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000023#include "llvm/Support/FileSystem.h"
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +000024#include "llvm/Support/Threading.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000025
Tamas Berghammere13c2732015-02-11 10:29:30 +000026#include "lldb/Host/Config.h"
27#include "lldb/Host/ConnectionFileDescriptor.h"
28#include "lldb/Host/Host.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000029#include "lldb/Host/HostInfo.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000030#include "lldb/Target/FileAction.h"
31#include "lldb/Target/Platform.h"
32#include "lldb/Target/Process.h"
Chaoren Lin98d0a4b2015-07-14 01:09:28 +000033#include "lldb/Target/UnixSignals.h"
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000034#include "lldb/Utility/JSON.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000035#include "lldb/Utility/Log.h"
Zachary Turnerfb1a0a02017-03-06 18:34:25 +000036#include "lldb/Utility/StreamGDBRemote.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000037#include "lldb/Utility/StreamString.h"
Pavel Labathf2a8bcc2017-06-27 10:45:31 +000038#include "lldb/Utility/StructuredData.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
Pavel Labath9af71b32018-03-20 16:14:00 +000042#include "lldb/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 Turner97206d52017-05-12 04:51:55 +000086 [](StringExtractorGDBRemote packet, Status &error,
Zachary Turner3bc714b2017-03-02 00:05:25 +000087 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
Zachary Turner97206d52017-05-12 04:51:55 +000099Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100 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
Adrian Prantl05097242018-04-30 16:49:04 +0000105 // Spawn a new thread to accept the port that gets bound after binding to
106 // port 0 (zero).
Tamas Berghammere13c2732015-02-11 10:29:30 +0000107
Adrian Prantl05097242018-04-30 16:49:04 +0000108 // ignore the hostname send from the remote end, just use the ip address that
109 // 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
Adrian Prantl05097242018-04-30 16:49:04 +0000120 // Do not run in a new session so that it can not linger after the platform
121 // closes.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000122 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;
Pavel Labathae7dd122017-10-27 04:53:24 +0000132 std::string platform_uri = GetConnection()->GetURI();
133 bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip,
134 platform_port, platform_path);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000135 UNUSED_IF_ASSERT_DISABLED(ok);
136 assert(ok);
137
138 std::ostringstream url;
139// debugserver does not accept the URL scheme prefix.
Todd Fiala873a2ab2016-05-27 04:04:52 +0000140#if !defined(__APPLE__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 url << m_socket_scheme << "://";
Todd Fiala873a2ab2016-05-27 04:04:52 +0000142#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 uint16_t *port_ptr = &port;
144 if (m_socket_protocol == Socket::ProtocolTcp)
Zachary Turner245f7fd2016-11-17 01:38:02 +0000145 url << platform_ip.str() << ":" << port;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 else {
147 socket_name = GetDomainSocketPath("gdbserver").GetPath();
148 url << socket_name;
149 port_ptr = nullptr;
150 }
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000151
Zachary Turner97206d52017-05-12 04:51:55 +0000152 Status error = StartDebugserverProcess(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000153 url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000154
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 pid = debugserver_launch_info.GetProcessID();
156 if (pid != LLDB_INVALID_PROCESS_ID) {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000157 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158 m_spawned_pids.insert(pid);
159 if (port > 0)
160 AssociatePortWithProcess(port, pid);
161 } else {
162 if (port > 0)
163 FreePort(port);
164 }
165 return error;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000166}
167
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168GDBRemoteCommunication::PacketResult
169GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
170 StringExtractorGDBRemote &packet) {
171#ifdef _WIN32
172 return SendErrorResponse(9);
173#else
Adrian Prantl05097242018-04-30 16:49:04 +0000174 // Spawn a local debugserver as a platform so we can then attach or launch a
175 // process...
Tamas Berghammere13c2732015-02-11 10:29:30 +0000176
Kate Stoneb9c1b512016-09-06 20:57:50 +0000177 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
178 if (log)
179 log->Printf("GDBRemoteCommunicationServerPlatform::%s() called",
180 __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000181
Kate Stoneb9c1b512016-09-06 20:57:50 +0000182 ConnectionFileDescriptor file_conn;
183 std::string hostname;
184 packet.SetFilePos(::strlen("qLaunchGDBServer;"));
185 llvm::StringRef name;
186 llvm::StringRef value;
187 uint16_t port = UINT16_MAX;
188 while (packet.GetNameColonValue(name, value)) {
189 if (name.equals("host"))
190 hostname = value;
191 else if (name.equals("port"))
192 value.getAsInteger(0, port);
193 }
194
195 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
196 std::string socket_name;
Zachary Turner97206d52017-05-12 04:51:55 +0000197 Status error =
Kate Stoneb9c1b512016-09-06 20:57:50 +0000198 LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
199 if (error.Fail()) {
200 if (log)
201 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
202 "launch failed: %s",
203 __FUNCTION__, error.AsCString());
204 return SendErrorResponse(9);
205 }
206
207 if (log)
208 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
209 "launched successfully as pid %" PRIu64,
210 __FUNCTION__, debugserver_pid);
211
212 StreamGDBRemote response;
213 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
214 port + m_port_offset);
215 if (!socket_name.empty()) {
216 response.PutCString("socket_name:");
217 response.PutCStringAsRawHex8(socket_name.c_str());
218 response.PutChar(';');
219 }
220
221 PacketResult packet_result = SendPacketNoLock(response.GetString());
222 if (packet_result != PacketResult::Success) {
223 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
224 ::kill(debugserver_pid, SIGINT);
225 }
226 return packet_result;
227#endif
228}
229
230GDBRemoteCommunication::PacketResult
231GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
232 StringExtractorGDBRemote &packet) {
233 if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
234 return SendErrorResponse(4);
235
236 JSONObject::SP server_sp = std::make_shared<JSONObject>();
237 server_sp->SetObject("port",
238 std::make_shared<JSONNumber>(m_pending_gdb_server.port));
239 if (!m_pending_gdb_server.socket_name.empty())
240 server_sp->SetObject(
241 "socket_name",
242 std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
243
244 JSONArray server_list;
245 server_list.AppendObject(server_sp);
246
247 StreamGDBRemote response;
248 server_list.Write(response);
249
250 StreamGDBRemote escaped_response;
Zachary Turnerc1564272016-11-16 21:15:24 +0000251 escaped_response.PutEscapedBytes(response.GetString().data(),
252 response.GetSize());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000253 return SendPacketNoLock(escaped_response.GetString());
254}
255
256GDBRemoteCommunication::PacketResult
257GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
258 StringExtractorGDBRemote &packet) {
259 packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
260
261 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
262
Adrian Prantl05097242018-04-30 16:49:04 +0000263 // verify that we know anything about this pid. Scope for locker
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264 {
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
Adrian Prantl05097242018-04-30 16:49:04 +0000309 // the launched process still lives. Now try killing it again, this time
310 // with an unblockable signal.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000311 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
Adrian Prantl05097242018-04-30 16:49:04 +0000324 // check one more time after the final usleep Scope for locker
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325 {
326 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
327 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
328 return true;
329 }
330
331 // no luck - the process still lives
332 return false;
333}
334
335GDBRemoteCommunication::PacketResult
336GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
337 StringExtractorGDBRemote &packet) {
338 lldb::pid_t pid = m_process_launch_info.GetProcessID();
339 m_process_launch_info.Clear();
340
341 if (pid == LLDB_INVALID_PROCESS_ID)
342 return SendErrorResponse(1);
343
344 ProcessInstanceInfo proc_info;
345 if (!Host::GetProcessInfo(pid, proc_info))
346 return SendErrorResponse(1);
347
348 StreamString response;
349 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
350 return SendPacketNoLock(response.GetString());
351}
352
353GDBRemoteCommunication::PacketResult
354GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
355 StringExtractorGDBRemote &packet) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356
Pavel Labath1d5855b2017-01-23 15:56:45 +0000357 llvm::SmallString<64> cwd;
358 if (std::error_code ec = llvm::sys::fs::current_path(cwd))
359 return SendErrorResponse(ec.value());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000360
361 StreamString response;
Pavel Labath1d5855b2017-01-23 15:56:45 +0000362 response.PutBytesAsRawHex8(cwd.data(), cwd.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363 return SendPacketNoLock(response.GetString());
364}
365
366GDBRemoteCommunication::PacketResult
367GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
368 StringExtractorGDBRemote &packet) {
369 packet.SetFilePos(::strlen("QSetWorkingDir:"));
370 std::string path;
371 packet.GetHexByteString(path);
372
Pavel Labath2d0c5b02017-01-25 11:10:52 +0000373 if (std::error_code ec = llvm::sys::fs::set_current_path(path))
374 return SendErrorResponse(ec.value());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375 return SendOKResponse();
376}
377
378GDBRemoteCommunication::PacketResult
379GDBRemoteCommunicationServerPlatform::Handle_qC(
380 StringExtractorGDBRemote &packet) {
381 // NOTE: lldb should now be using qProcessInfo for process IDs. This path
382 // here
383 // should not be used. It is reporting process id instead of thread id. The
384 // correct answer doesn't seem to make much sense for lldb-platform.
385 // CONSIDER: flip to "unsupported".
386 lldb::pid_t pid = m_process_launch_info.GetProcessID();
387
388 StreamString response;
389 response.Printf("QC%" PRIx64, pid);
390
Adrian Prantl05097242018-04-30 16:49:04 +0000391 // If we launch a process and this GDB server is acting as a platform, then
392 // we need to clear the process launch state so we can start launching
393 // another process. In order to launch a process a bunch or packets need to
394 // be sent: environment packets, working directory, disable ASLR, and many
395 // more settings. When we launch a process we then need to know when to clear
396 // this information. Currently we are selecting the 'qC' packet as that
397 // packet which seems to make the most sense.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000398 if (pid != LLDB_INVALID_PROCESS_ID) {
399 m_process_launch_info.Clear();
400 }
401
402 return SendPacketNoLock(response.GetString());
403}
404
405GDBRemoteCommunication::PacketResult
406GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
407 StringExtractorGDBRemote &packet) {
408 StructuredData::Array signal_array;
409
410 const auto &signals = Host::GetUnixSignals();
411 for (auto signo = signals->GetFirstSignalNumber();
412 signo != LLDB_INVALID_SIGNAL_NUMBER;
413 signo = signals->GetNextSignalNumber(signo)) {
414 auto dictionary = std::make_shared<StructuredData::Dictionary>();
415
416 dictionary->AddIntegerItem("signo", signo);
417 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
418
419 bool suppress, stop, notify;
420 signals->GetSignalInfo(signo, suppress, stop, notify);
421 dictionary->AddBooleanItem("suppress", suppress);
422 dictionary->AddBooleanItem("stop", stop);
423 dictionary->AddBooleanItem("notify", notify);
424
425 signal_array.Push(dictionary);
426 }
427
428 StreamString response;
429 signal_array.Dump(response);
430 return SendPacketNoLock(response.GetString());
431}
432
433bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
434 lldb::pid_t pid) {
435 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
436 FreePortForProcess(pid);
437 m_spawned_pids.erase(pid);
438 return true;
439}
440
Zachary Turner97206d52017-05-12 04:51:55 +0000441Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 if (!m_process_launch_info.GetArguments().GetArgumentCount())
Zachary Turner97206d52017-05-12 04:51:55 +0000443 return Status("%s: no process command line specified to launch",
444 __FUNCTION__);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000445
Adrian Prantl05097242018-04-30 16:49:04 +0000446 // specify the process monitor if not already set. This should generally be
447 // what happens since we need to reap started processes.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 if (!m_process_launch_info.GetMonitorProcessCallback())
449 m_process_launch_info.SetMonitorProcessCallback(
450 std::bind(
451 &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
452 this, std::placeholders::_1),
453 false);
454
Zachary Turner97206d52017-05-12 04:51:55 +0000455 Status error = Host::LaunchProcess(m_process_launch_info);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456 if (!error.Success()) {
457 fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
458 m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
Tamas Berghammere13c2732015-02-11 10:29:30 +0000459 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000460 }
461
462 printf("Launched '%s' as process %" PRIu64 "...\n",
463 m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
464 m_process_launch_info.GetProcessID());
465
Adrian Prantl05097242018-04-30 16:49:04 +0000466 // add to list of spawned processes. On an lldb-gdbserver, we would expect
467 // there to be only one.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000468 const auto pid = m_process_launch_info.GetProcessID();
469 if (pid != LLDB_INVALID_PROCESS_ID) {
470 // add to spawned pids
471 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
472 m_spawned_pids.insert(pid);
473 }
474
475 return error;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000476}
477
Kate Stoneb9c1b512016-09-06 20:57:50 +0000478void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
479 m_port_map = port_map;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000480}
481
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482uint16_t GDBRemoteCommunicationServerPlatform::GetNextAvailablePort() {
483 if (m_port_map.empty())
484 return 0; // Bind to port zero and get a port, we didn't have any
485 // limitations
Tamas Berghammere13c2732015-02-11 10:29:30 +0000486
Kate Stoneb9c1b512016-09-06 20:57:50 +0000487 for (auto &pair : m_port_map) {
488 if (pair.second == LLDB_INVALID_PROCESS_ID) {
489 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
490 return pair.first;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000491 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000492 }
493 return UINT16_MAX;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000494}
495
Kate Stoneb9c1b512016-09-06 20:57:50 +0000496bool GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess(
497 uint16_t port, lldb::pid_t pid) {
498 PortMap::iterator pos = m_port_map.find(port);
499 if (pos != m_port_map.end()) {
500 pos->second = pid;
501 return true;
502 }
503 return false;
504}
505
506bool GDBRemoteCommunicationServerPlatform::FreePort(uint16_t port) {
507 PortMap::iterator pos = m_port_map.find(port);
508 if (pos != m_port_map.end()) {
509 pos->second = LLDB_INVALID_PROCESS_ID;
510 return true;
511 }
512 return false;
513}
514
515bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) {
516 if (!m_port_map.empty()) {
517 for (auto &pair : m_port_map) {
518 if (pair.second == pid) {
519 pair.second = LLDB_INVALID_PROCESS_ID;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000520 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000521 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000522 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523 }
524 return false;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000525}
526
Kate Stoneb9c1b512016-09-06 20:57:50 +0000527const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
528 static FileSpec g_domainsocket_dir;
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000529 static llvm::once_flag g_once_flag;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000530
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000531 llvm::call_once(g_once_flag, []() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000532 const char *domainsocket_dir_env =
533 ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
534 if (domainsocket_dir_env != nullptr)
535 g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
536 else
Pavel Labath60f028f2018-06-19 15:09:07 +0000537 g_domainsocket_dir = HostInfo::GetProcessTempDir();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538 });
Tamas Berghammere13c2732015-02-11 10:29:30 +0000539
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540 return g_domainsocket_dir;
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000541}
542
543FileSpec
Kate Stoneb9c1b512016-09-06 20:57:50 +0000544GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
545 llvm::SmallString<PATH_MAX> socket_path;
546 llvm::SmallString<PATH_MAX> socket_name(
547 (llvm::StringRef(prefix) + ".%%%%%%").str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000548
Kate Stoneb9c1b512016-09-06 20:57:50 +0000549 FileSpec socket_path_spec(GetDomainSocketDir());
550 socket_path_spec.AppendPathComponent(socket_name.c_str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000551
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552 llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
553 return FileSpec(socket_path.c_str(), false);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000554}
555
Kate Stoneb9c1b512016-09-06 20:57:50 +0000556void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
557 m_port_offset = port_offset;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000558}
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000559
Kate Stoneb9c1b512016-09-06 20:57:50 +0000560void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
561 lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
562 m_pending_gdb_server.pid = pid;
563 m_pending_gdb_server.port = port;
564 m_pending_gdb_server.socket_name = socket_name;
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000565}