blob: 60df07a0a3aebd89ec919e82faa24a05bc00c927 [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
Tamas Berghammere13c2732015-02-11 10:29:30 +000014#include <chrono>
Pavel Labath6b3c8bb2018-04-05 16:23:54 +000015#include <csignal>
Kate Stoneb9c1b512016-09-06 20:57:50 +000016#include <cstring>
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000017#include <mutex>
18#include <sstream>
Tamas Berghammere13c2732015-02-11 10:29:30 +000019
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000020#include "llvm/Support/FileSystem.h"
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +000021#include "llvm/Support/Threading.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000022
Tamas Berghammere13c2732015-02-11 10:29:30 +000023#include "lldb/Host/Config.h"
24#include "lldb/Host/ConnectionFileDescriptor.h"
25#include "lldb/Host/Host.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000026#include "lldb/Host/HostInfo.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000027#include "lldb/Target/FileAction.h"
28#include "lldb/Target/Platform.h"
29#include "lldb/Target/Process.h"
Chaoren Lin98d0a4b2015-07-14 01:09:28 +000030#include "lldb/Target/UnixSignals.h"
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000031#include "lldb/Utility/JSON.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000032#include "lldb/Utility/Log.h"
Zachary Turnerfb1a0a02017-03-06 18:34:25 +000033#include "lldb/Utility/StreamGDBRemote.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000034#include "lldb/Utility/StreamString.h"
Pavel Labathf2a8bcc2017-06-27 10:45:31 +000035#include "lldb/Utility/StructuredData.h"
Pavel Labath5f7e5832017-02-10 12:21:22 +000036#include "lldb/Utility/UriParser.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000037
Pavel Labath9af71b32018-03-20 16:14:00 +000038#include "lldb/Utility/StringExtractorGDBRemote.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000039
40using namespace lldb;
41using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000042using namespace lldb_private::process_gdb_remote;
Tamas Berghammere13c2732015-02-11 10:29:30 +000043
44//----------------------------------------------------------------------
45// GDBRemoteCommunicationServerPlatform constructor
46//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000047GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
48 const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
49 : GDBRemoteCommunicationServerCommon("gdb-remote.server",
50 "gdb-remote.server.rx_packet"),
51 m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
52 m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
53 m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
54 m_pending_gdb_server.port = 0;
Tamas Berghammer372810f2015-12-08 14:27:40 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 RegisterMemberFunctionHandler(
57 StringExtractorGDBRemote::eServerPacketType_qC,
58 &GDBRemoteCommunicationServerPlatform::Handle_qC);
59 RegisterMemberFunctionHandler(
60 StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
61 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
62 RegisterMemberFunctionHandler(
63 StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
64 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
65 RegisterMemberFunctionHandler(
66 StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
67 &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
68 RegisterMemberFunctionHandler(
69 StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
70 &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
71 RegisterMemberFunctionHandler(
72 StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
73 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
74 RegisterMemberFunctionHandler(
75 StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
76 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
77 RegisterMemberFunctionHandler(
78 StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
79 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
Tamas Berghammere13c2732015-02-11 10:29:30 +000080
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
Zachary Turner97206d52017-05-12 04:51:55 +000082 [](StringExtractorGDBRemote packet, Status &error,
Zachary Turner3bc714b2017-03-02 00:05:25 +000083 bool &interrupt, bool &quit) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 error.SetErrorString("interrupt received");
85 interrupt = true;
86 return PacketResult::Success;
87 });
Tamas Berghammere13c2732015-02-11 10:29:30 +000088}
89
90//----------------------------------------------------------------------
91// Destructor
92//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000093GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {}
Tamas Berghammere13c2732015-02-11 10:29:30 +000094
Zachary Turner97206d52017-05-12 04:51:55 +000095Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
Kate Stoneb9c1b512016-09-06 20:57:50 +000096 const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
97 uint16_t &port, std::string &socket_name) {
98 if (port == UINT16_MAX)
99 port = GetNextAvailablePort();
Tamas Berghammere13c2732015-02-11 10:29:30 +0000100
Adrian Prantl05097242018-04-30 16:49:04 +0000101 // Spawn a new thread to accept the port that gets bound after binding to
102 // port 0 (zero).
Tamas Berghammere13c2732015-02-11 10:29:30 +0000103
Adrian Prantl05097242018-04-30 16:49:04 +0000104 // ignore the hostname send from the remote end, just use the ip address that
105 // we're currently communicating with as the hostname
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000106
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 // Spawn a debugserver and try to get the port it listens to.
108 ProcessLaunchInfo debugserver_launch_info;
109 if (hostname.empty())
110 hostname = "127.0.0.1";
Tamas Berghammere13c2732015-02-11 10:29:30 +0000111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
113 if (log)
114 log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000115
Adrian Prantl05097242018-04-30 16:49:04 +0000116 // Do not run in a new session so that it can not linger after the platform
117 // closes.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
119 debugserver_launch_info.SetMonitorProcessCallback(
120 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
121 this, std::placeholders::_1),
122 false);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000123
Zachary Turner245f7fd2016-11-17 01:38:02 +0000124 llvm::StringRef platform_scheme;
125 llvm::StringRef platform_ip;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 int platform_port;
Zachary Turner245f7fd2016-11-17 01:38:02 +0000127 llvm::StringRef platform_path;
Pavel Labathae7dd122017-10-27 04:53:24 +0000128 std::string platform_uri = GetConnection()->GetURI();
129 bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip,
130 platform_port, platform_path);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000131 UNUSED_IF_ASSERT_DISABLED(ok);
132 assert(ok);
133
134 std::ostringstream url;
135// debugserver does not accept the URL scheme prefix.
Todd Fiala873a2ab2016-05-27 04:04:52 +0000136#if !defined(__APPLE__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137 url << m_socket_scheme << "://";
Todd Fiala873a2ab2016-05-27 04:04:52 +0000138#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 uint16_t *port_ptr = &port;
140 if (m_socket_protocol == Socket::ProtocolTcp)
Zachary Turner245f7fd2016-11-17 01:38:02 +0000141 url << platform_ip.str() << ":" << port;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142 else {
143 socket_name = GetDomainSocketPath("gdbserver").GetPath();
144 url << socket_name;
145 port_ptr = nullptr;
146 }
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000147
Zachary Turner97206d52017-05-12 04:51:55 +0000148 Status error = StartDebugserverProcess(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000150
Kate Stoneb9c1b512016-09-06 20:57:50 +0000151 pid = debugserver_launch_info.GetProcessID();
152 if (pid != LLDB_INVALID_PROCESS_ID) {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000153 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 m_spawned_pids.insert(pid);
155 if (port > 0)
156 AssociatePortWithProcess(port, pid);
157 } else {
158 if (port > 0)
159 FreePort(port);
160 }
161 return error;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000162}
163
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164GDBRemoteCommunication::PacketResult
165GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
166 StringExtractorGDBRemote &packet) {
167#ifdef _WIN32
168 return SendErrorResponse(9);
169#else
Adrian Prantl05097242018-04-30 16:49:04 +0000170 // Spawn a local debugserver as a platform so we can then attach or launch a
171 // process...
Tamas Berghammere13c2732015-02-11 10:29:30 +0000172
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
174 if (log)
175 log->Printf("GDBRemoteCommunicationServerPlatform::%s() called",
176 __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000177
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178 ConnectionFileDescriptor file_conn;
179 std::string hostname;
180 packet.SetFilePos(::strlen("qLaunchGDBServer;"));
181 llvm::StringRef name;
182 llvm::StringRef value;
183 uint16_t port = UINT16_MAX;
184 while (packet.GetNameColonValue(name, value)) {
185 if (name.equals("host"))
186 hostname = value;
187 else if (name.equals("port"))
188 value.getAsInteger(0, port);
189 }
190
191 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
192 std::string socket_name;
Zachary Turner97206d52017-05-12 04:51:55 +0000193 Status error =
Kate Stoneb9c1b512016-09-06 20:57:50 +0000194 LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
195 if (error.Fail()) {
196 if (log)
197 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
198 "launch failed: %s",
199 __FUNCTION__, error.AsCString());
200 return SendErrorResponse(9);
201 }
202
203 if (log)
204 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
205 "launched successfully as pid %" PRIu64,
206 __FUNCTION__, debugserver_pid);
207
208 StreamGDBRemote response;
209 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
210 port + m_port_offset);
211 if (!socket_name.empty()) {
212 response.PutCString("socket_name:");
213 response.PutCStringAsRawHex8(socket_name.c_str());
214 response.PutChar(';');
215 }
216
217 PacketResult packet_result = SendPacketNoLock(response.GetString());
218 if (packet_result != PacketResult::Success) {
219 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
220 ::kill(debugserver_pid, SIGINT);
221 }
222 return packet_result;
223#endif
224}
225
226GDBRemoteCommunication::PacketResult
227GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
228 StringExtractorGDBRemote &packet) {
229 if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
230 return SendErrorResponse(4);
231
232 JSONObject::SP server_sp = std::make_shared<JSONObject>();
233 server_sp->SetObject("port",
234 std::make_shared<JSONNumber>(m_pending_gdb_server.port));
235 if (!m_pending_gdb_server.socket_name.empty())
236 server_sp->SetObject(
237 "socket_name",
238 std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
239
240 JSONArray server_list;
241 server_list.AppendObject(server_sp);
242
243 StreamGDBRemote response;
244 server_list.Write(response);
245
246 StreamGDBRemote escaped_response;
Zachary Turnerc1564272016-11-16 21:15:24 +0000247 escaped_response.PutEscapedBytes(response.GetString().data(),
248 response.GetSize());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249 return SendPacketNoLock(escaped_response.GetString());
250}
251
252GDBRemoteCommunication::PacketResult
253GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
254 StringExtractorGDBRemote &packet) {
255 packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
256
257 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
258
Adrian Prantl05097242018-04-30 16:49:04 +0000259 // verify that we know anything about this pid. Scope for locker
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260 {
261 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
262 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
263 // not a pid we know about
264 return SendErrorResponse(10);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000265 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000267
Kate Stoneb9c1b512016-09-06 20:57:50 +0000268 // go ahead and attempt to kill the spawned process
269 if (KillSpawnedProcess(pid))
270 return SendOKResponse();
271 else
272 return SendErrorResponse(11);
273}
Tamas Berghammere13c2732015-02-11 10:29:30 +0000274
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
276 // make sure we know about this process
277 {
278 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
279 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
280 return false;
281 }
282
283 // first try a SIGTERM (standard kill)
284 Host::Kill(pid, SIGTERM);
285
286 // check if that worked
287 for (size_t i = 0; i < 10; ++i) {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000288 {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
290 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
291 // it is now killed
292 return true;
293 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000294 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 usleep(10000);
296 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000297
Kate Stoneb9c1b512016-09-06 20:57:50 +0000298 // check one more time after the final usleep
299 {
300 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
301 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
302 return true;
303 }
304
Adrian Prantl05097242018-04-30 16:49:04 +0000305 // the launched process still lives. Now try killing it again, this time
306 // with an unblockable signal.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000307 Host::Kill(pid, SIGKILL);
308
309 for (size_t i = 0; i < 10; ++i) {
310 {
311 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
312 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
313 // it is now killed
314 return true;
315 }
316 }
317 usleep(10000);
318 }
319
Adrian Prantl05097242018-04-30 16:49:04 +0000320 // check one more time after the final usleep Scope for locker
Kate Stoneb9c1b512016-09-06 20:57:50 +0000321 {
322 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
323 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
324 return true;
325 }
326
327 // no luck - the process still lives
328 return false;
329}
330
331GDBRemoteCommunication::PacketResult
332GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
333 StringExtractorGDBRemote &packet) {
334 lldb::pid_t pid = m_process_launch_info.GetProcessID();
335 m_process_launch_info.Clear();
336
337 if (pid == LLDB_INVALID_PROCESS_ID)
338 return SendErrorResponse(1);
339
340 ProcessInstanceInfo proc_info;
341 if (!Host::GetProcessInfo(pid, proc_info))
342 return SendErrorResponse(1);
343
344 StreamString response;
345 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
346 return SendPacketNoLock(response.GetString());
347}
348
349GDBRemoteCommunication::PacketResult
350GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
351 StringExtractorGDBRemote &packet) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000352
Pavel Labath1d5855b2017-01-23 15:56:45 +0000353 llvm::SmallString<64> cwd;
354 if (std::error_code ec = llvm::sys::fs::current_path(cwd))
355 return SendErrorResponse(ec.value());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356
357 StreamString response;
Pavel Labath1d5855b2017-01-23 15:56:45 +0000358 response.PutBytesAsRawHex8(cwd.data(), cwd.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000359 return SendPacketNoLock(response.GetString());
360}
361
362GDBRemoteCommunication::PacketResult
363GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
364 StringExtractorGDBRemote &packet) {
365 packet.SetFilePos(::strlen("QSetWorkingDir:"));
366 std::string path;
367 packet.GetHexByteString(path);
368
Pavel Labath2d0c5b02017-01-25 11:10:52 +0000369 if (std::error_code ec = llvm::sys::fs::set_current_path(path))
370 return SendErrorResponse(ec.value());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000371 return SendOKResponse();
372}
373
374GDBRemoteCommunication::PacketResult
375GDBRemoteCommunicationServerPlatform::Handle_qC(
376 StringExtractorGDBRemote &packet) {
377 // NOTE: lldb should now be using qProcessInfo for process IDs. This path
378 // here
379 // should not be used. It is reporting process id instead of thread id. The
380 // correct answer doesn't seem to make much sense for lldb-platform.
381 // CONSIDER: flip to "unsupported".
382 lldb::pid_t pid = m_process_launch_info.GetProcessID();
383
384 StreamString response;
385 response.Printf("QC%" PRIx64, pid);
386
Adrian Prantl05097242018-04-30 16:49:04 +0000387 // If we launch a process and this GDB server is acting as a platform, then
388 // we need to clear the process launch state so we can start launching
389 // another process. In order to launch a process a bunch or packets need to
390 // be sent: environment packets, working directory, disable ASLR, and many
391 // more settings. When we launch a process we then need to know when to clear
392 // this information. Currently we are selecting the 'qC' packet as that
393 // packet which seems to make the most sense.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000394 if (pid != LLDB_INVALID_PROCESS_ID) {
395 m_process_launch_info.Clear();
396 }
397
398 return SendPacketNoLock(response.GetString());
399}
400
401GDBRemoteCommunication::PacketResult
402GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
403 StringExtractorGDBRemote &packet) {
404 StructuredData::Array signal_array;
405
406 const auto &signals = Host::GetUnixSignals();
407 for (auto signo = signals->GetFirstSignalNumber();
408 signo != LLDB_INVALID_SIGNAL_NUMBER;
409 signo = signals->GetNextSignalNumber(signo)) {
410 auto dictionary = std::make_shared<StructuredData::Dictionary>();
411
412 dictionary->AddIntegerItem("signo", signo);
413 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
414
415 bool suppress, stop, notify;
416 signals->GetSignalInfo(signo, suppress, stop, notify);
417 dictionary->AddBooleanItem("suppress", suppress);
418 dictionary->AddBooleanItem("stop", stop);
419 dictionary->AddBooleanItem("notify", notify);
420
421 signal_array.Push(dictionary);
422 }
423
424 StreamString response;
425 signal_array.Dump(response);
426 return SendPacketNoLock(response.GetString());
427}
428
429bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
430 lldb::pid_t pid) {
431 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
432 FreePortForProcess(pid);
433 m_spawned_pids.erase(pid);
434 return true;
435}
436
Zachary Turner97206d52017-05-12 04:51:55 +0000437Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000438 if (!m_process_launch_info.GetArguments().GetArgumentCount())
Zachary Turner97206d52017-05-12 04:51:55 +0000439 return Status("%s: no process command line specified to launch",
440 __FUNCTION__);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441
Adrian Prantl05097242018-04-30 16:49:04 +0000442 // specify the process monitor if not already set. This should generally be
443 // what happens since we need to reap started processes.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000444 if (!m_process_launch_info.GetMonitorProcessCallback())
445 m_process_launch_info.SetMonitorProcessCallback(
446 std::bind(
447 &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
448 this, std::placeholders::_1),
449 false);
450
Zachary Turner97206d52017-05-12 04:51:55 +0000451 Status error = Host::LaunchProcess(m_process_launch_info);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000452 if (!error.Success()) {
453 fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
454 m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
Tamas Berghammere13c2732015-02-11 10:29:30 +0000455 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456 }
457
458 printf("Launched '%s' as process %" PRIu64 "...\n",
459 m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
460 m_process_launch_info.GetProcessID());
461
Adrian Prantl05097242018-04-30 16:49:04 +0000462 // add to list of spawned processes. On an lldb-gdbserver, we would expect
463 // there to be only one.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000464 const auto pid = m_process_launch_info.GetProcessID();
465 if (pid != LLDB_INVALID_PROCESS_ID) {
466 // add to spawned pids
467 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
468 m_spawned_pids.insert(pid);
469 }
470
471 return error;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000472}
473
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
475 m_port_map = port_map;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000476}
477
Kate Stoneb9c1b512016-09-06 20:57:50 +0000478uint16_t GDBRemoteCommunicationServerPlatform::GetNextAvailablePort() {
479 if (m_port_map.empty())
480 return 0; // Bind to port zero and get a port, we didn't have any
481 // limitations
Tamas Berghammere13c2732015-02-11 10:29:30 +0000482
Kate Stoneb9c1b512016-09-06 20:57:50 +0000483 for (auto &pair : m_port_map) {
484 if (pair.second == LLDB_INVALID_PROCESS_ID) {
485 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
486 return pair.first;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000487 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000488 }
489 return UINT16_MAX;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000490}
491
Kate Stoneb9c1b512016-09-06 20:57:50 +0000492bool GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess(
493 uint16_t port, lldb::pid_t pid) {
494 PortMap::iterator pos = m_port_map.find(port);
495 if (pos != m_port_map.end()) {
496 pos->second = pid;
497 return true;
498 }
499 return false;
500}
501
502bool GDBRemoteCommunicationServerPlatform::FreePort(uint16_t port) {
503 PortMap::iterator pos = m_port_map.find(port);
504 if (pos != m_port_map.end()) {
505 pos->second = LLDB_INVALID_PROCESS_ID;
506 return true;
507 }
508 return false;
509}
510
511bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) {
512 if (!m_port_map.empty()) {
513 for (auto &pair : m_port_map) {
514 if (pair.second == pid) {
515 pair.second = LLDB_INVALID_PROCESS_ID;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000516 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000517 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000518 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519 }
520 return false;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000521}
522
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
524 static FileSpec g_domainsocket_dir;
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000525 static llvm::once_flag g_once_flag;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000526
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000527 llvm::call_once(g_once_flag, []() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000528 const char *domainsocket_dir_env =
529 ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
530 if (domainsocket_dir_env != nullptr)
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000531 g_domainsocket_dir = FileSpec(domainsocket_dir_env);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000532 else
Pavel Labath60f028f2018-06-19 15:09:07 +0000533 g_domainsocket_dir = HostInfo::GetProcessTempDir();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000534 });
Tamas Berghammere13c2732015-02-11 10:29:30 +0000535
Kate Stoneb9c1b512016-09-06 20:57:50 +0000536 return g_domainsocket_dir;
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000537}
538
539FileSpec
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
Stella Stamenovab3f44ad2018-12-10 17:23:28 +0000541 llvm::SmallString<128> socket_path;
542 llvm::SmallString<128> socket_name(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000543 (llvm::StringRef(prefix) + ".%%%%%%").str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000544
Kate Stoneb9c1b512016-09-06 20:57:50 +0000545 FileSpec socket_path_spec(GetDomainSocketDir());
546 socket_path_spec.AppendPathComponent(socket_name.c_str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000547
Kate Stoneb9c1b512016-09-06 20:57:50 +0000548 llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000549 return FileSpec(socket_path.c_str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000550}
551
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
553 m_port_offset = port_offset;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000554}
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000555
Kate Stoneb9c1b512016-09-06 20:57:50 +0000556void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
557 lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
558 m_pending_gdb_server.pid = pid;
559 m_pending_gdb_server.port = port;
560 m_pending_gdb_server.socket_name = socket_name;
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000561}