blob: 7157f53fb836ef4a3a5c8efb681c91107b505052 [file] [log] [blame]
Tamas Berghammere13c2732015-02-11 10:29:30 +00001//===-- GDBRemoteCommunicationServerPlatform.cpp ----------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Tamas Berghammere13c2732015-02-11 10:29:30 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "GDBRemoteCommunicationServerPlatform.h"
10
11#include <errno.h>
12
Tamas Berghammere13c2732015-02-11 10:29:30 +000013#include <chrono>
Pavel Labath6b3c8bb2018-04-05 16:23:54 +000014#include <csignal>
Kate Stoneb9c1b512016-09-06 20:57:50 +000015#include <cstring>
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000016#include <mutex>
17#include <sstream>
Tamas Berghammere13c2732015-02-11 10:29:30 +000018
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000019#include "llvm/Support/FileSystem.h"
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +000020#include "llvm/Support/Threading.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000021
Tamas Berghammere13c2732015-02-11 10:29:30 +000022#include "lldb/Host/Config.h"
23#include "lldb/Host/ConnectionFileDescriptor.h"
Pavel Labatheef758e2019-02-04 14:28:08 +000024#include "lldb/Host/FileAction.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000025#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/Platform.h"
Chaoren Lin98d0a4b2015-07-14 01:09:28 +000028#include "lldb/Target/UnixSignals.h"
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000029#include "lldb/Utility/JSON.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000030#include "lldb/Utility/Log.h"
Zachary Turnerfb1a0a02017-03-06 18:34:25 +000031#include "lldb/Utility/StreamGDBRemote.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000032#include "lldb/Utility/StreamString.h"
Pavel Labathf2a8bcc2017-06-27 10:45:31 +000033#include "lldb/Utility/StructuredData.h"
Pavel Labath5f7e5832017-02-10 12:21:22 +000034#include "lldb/Utility/UriParser.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000035
Pavel Labath9af71b32018-03-20 16:14:00 +000036#include "lldb/Utility/StringExtractorGDBRemote.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000037
38using namespace lldb;
39using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000040using namespace lldb_private::process_gdb_remote;
Tamas Berghammere13c2732015-02-11 10:29:30 +000041
Tamas Berghammere13c2732015-02-11 10:29:30 +000042// GDBRemoteCommunicationServerPlatform constructor
Kate Stoneb9c1b512016-09-06 20:57:50 +000043GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
44 const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
45 : GDBRemoteCommunicationServerCommon("gdb-remote.server",
46 "gdb-remote.server.rx_packet"),
47 m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
48 m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
49 m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
50 m_pending_gdb_server.port = 0;
Tamas Berghammer372810f2015-12-08 14:27:40 +000051
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 RegisterMemberFunctionHandler(
53 StringExtractorGDBRemote::eServerPacketType_qC,
54 &GDBRemoteCommunicationServerPlatform::Handle_qC);
55 RegisterMemberFunctionHandler(
56 StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
57 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
58 RegisterMemberFunctionHandler(
59 StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
60 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
61 RegisterMemberFunctionHandler(
62 StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
63 &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
64 RegisterMemberFunctionHandler(
65 StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
66 &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
67 RegisterMemberFunctionHandler(
68 StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
69 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
70 RegisterMemberFunctionHandler(
71 StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
72 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
73 RegisterMemberFunctionHandler(
74 StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
75 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
Tamas Berghammere13c2732015-02-11 10:29:30 +000076
Kate Stoneb9c1b512016-09-06 20:57:50 +000077 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
Zachary Turner97206d52017-05-12 04:51:55 +000078 [](StringExtractorGDBRemote packet, Status &error,
Zachary Turner3bc714b2017-03-02 00:05:25 +000079 bool &interrupt, bool &quit) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 error.SetErrorString("interrupt received");
81 interrupt = true;
82 return PacketResult::Success;
83 });
Tamas Berghammere13c2732015-02-11 10:29:30 +000084}
85
Tamas Berghammere13c2732015-02-11 10:29:30 +000086// Destructor
Kate Stoneb9c1b512016-09-06 20:57:50 +000087GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {}
Tamas Berghammere13c2732015-02-11 10:29:30 +000088
Zachary Turner97206d52017-05-12 04:51:55 +000089Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
Kate Stoneb9c1b512016-09-06 20:57:50 +000090 const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
91 uint16_t &port, std::string &socket_name) {
92 if (port == UINT16_MAX)
93 port = GetNextAvailablePort();
Tamas Berghammere13c2732015-02-11 10:29:30 +000094
Adrian Prantl05097242018-04-30 16:49:04 +000095 // Spawn a new thread to accept the port that gets bound after binding to
96 // port 0 (zero).
Tamas Berghammere13c2732015-02-11 10:29:30 +000097
Adrian Prantl05097242018-04-30 16:49:04 +000098 // ignore the hostname send from the remote end, just use the ip address that
99 // we're currently communicating with as the hostname
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000100
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101 // Spawn a debugserver and try to get the port it listens to.
102 ProcessLaunchInfo debugserver_launch_info;
103 if (hostname.empty())
104 hostname = "127.0.0.1";
Tamas Berghammere13c2732015-02-11 10:29:30 +0000105
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
107 if (log)
108 log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000109
Adrian Prantl05097242018-04-30 16:49:04 +0000110 // Do not run in a new session so that it can not linger after the platform
111 // closes.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
113 debugserver_launch_info.SetMonitorProcessCallback(
114 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
115 this, std::placeholders::_1),
116 false);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000117
Zachary Turner245f7fd2016-11-17 01:38:02 +0000118 llvm::StringRef platform_scheme;
119 llvm::StringRef platform_ip;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000120 int platform_port;
Zachary Turner245f7fd2016-11-17 01:38:02 +0000121 llvm::StringRef platform_path;
Pavel Labathae7dd122017-10-27 04:53:24 +0000122 std::string platform_uri = GetConnection()->GetURI();
123 bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip,
124 platform_port, platform_path);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000125 UNUSED_IF_ASSERT_DISABLED(ok);
126 assert(ok);
127
128 std::ostringstream url;
129// debugserver does not accept the URL scheme prefix.
Todd Fiala873a2ab2016-05-27 04:04:52 +0000130#if !defined(__APPLE__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000131 url << m_socket_scheme << "://";
Todd Fiala873a2ab2016-05-27 04:04:52 +0000132#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133 uint16_t *port_ptr = &port;
134 if (m_socket_protocol == Socket::ProtocolTcp)
Zachary Turner245f7fd2016-11-17 01:38:02 +0000135 url << platform_ip.str() << ":" << port;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000136 else {
137 socket_name = GetDomainSocketPath("gdbserver").GetPath();
138 url << socket_name;
139 port_ptr = nullptr;
140 }
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000141
Zachary Turner97206d52017-05-12 04:51:55 +0000142 Status error = StartDebugserverProcess(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000144
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 pid = debugserver_launch_info.GetProcessID();
146 if (pid != LLDB_INVALID_PROCESS_ID) {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000147 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000148 m_spawned_pids.insert(pid);
149 if (port > 0)
150 AssociatePortWithProcess(port, pid);
151 } else {
152 if (port > 0)
153 FreePort(port);
154 }
155 return error;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000156}
157
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158GDBRemoteCommunication::PacketResult
159GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
160 StringExtractorGDBRemote &packet) {
Adrian Prantl05097242018-04-30 16:49:04 +0000161 // Spawn a local debugserver as a platform so we can then attach or launch a
162 // process...
Tamas Berghammere13c2732015-02-11 10:29:30 +0000163
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
165 if (log)
166 log->Printf("GDBRemoteCommunicationServerPlatform::%s() called",
167 __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000168
Kate Stoneb9c1b512016-09-06 20:57:50 +0000169 ConnectionFileDescriptor file_conn;
170 std::string hostname;
171 packet.SetFilePos(::strlen("qLaunchGDBServer;"));
172 llvm::StringRef name;
173 llvm::StringRef value;
174 uint16_t port = UINT16_MAX;
175 while (packet.GetNameColonValue(name, value)) {
176 if (name.equals("host"))
177 hostname = value;
178 else if (name.equals("port"))
179 value.getAsInteger(0, port);
180 }
181
182 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
183 std::string socket_name;
Zachary Turner97206d52017-05-12 04:51:55 +0000184 Status error =
Kate Stoneb9c1b512016-09-06 20:57:50 +0000185 LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
186 if (error.Fail()) {
187 if (log)
188 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
189 "launch failed: %s",
190 __FUNCTION__, error.AsCString());
191 return SendErrorResponse(9);
192 }
193
194 if (log)
195 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
196 "launched successfully as pid %" PRIu64,
197 __FUNCTION__, debugserver_pid);
198
199 StreamGDBRemote response;
200 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
201 port + m_port_offset);
202 if (!socket_name.empty()) {
203 response.PutCString("socket_name:");
Pavel Labath7f815a92019-02-12 14:28:55 +0000204 response.PutStringAsRawHex8(socket_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000205 response.PutChar(';');
206 }
207
208 PacketResult packet_result = SendPacketNoLock(response.GetString());
209 if (packet_result != PacketResult::Success) {
210 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
Aaron Smithe55850b2019-01-10 00:46:09 +0000211 Host::Kill(debugserver_pid, SIGINT);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212 }
213 return packet_result;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214}
215
216GDBRemoteCommunication::PacketResult
217GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
218 StringExtractorGDBRemote &packet) {
219 if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
220 return SendErrorResponse(4);
221
222 JSONObject::SP server_sp = std::make_shared<JSONObject>();
223 server_sp->SetObject("port",
224 std::make_shared<JSONNumber>(m_pending_gdb_server.port));
225 if (!m_pending_gdb_server.socket_name.empty())
226 server_sp->SetObject(
227 "socket_name",
228 std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
229
230 JSONArray server_list;
231 server_list.AppendObject(server_sp);
232
233 StreamGDBRemote response;
234 server_list.Write(response);
235
236 StreamGDBRemote escaped_response;
Zachary Turnerc1564272016-11-16 21:15:24 +0000237 escaped_response.PutEscapedBytes(response.GetString().data(),
238 response.GetSize());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000239 return SendPacketNoLock(escaped_response.GetString());
240}
241
242GDBRemoteCommunication::PacketResult
243GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
244 StringExtractorGDBRemote &packet) {
245 packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
246
247 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
248
Adrian Prantl05097242018-04-30 16:49:04 +0000249 // verify that we know anything about this pid. Scope for locker
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250 {
251 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
252 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
253 // not a pid we know about
254 return SendErrorResponse(10);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000255 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000256 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000257
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258 // go ahead and attempt to kill the spawned process
259 if (KillSpawnedProcess(pid))
260 return SendOKResponse();
261 else
262 return SendErrorResponse(11);
263}
Tamas Berghammere13c2732015-02-11 10:29:30 +0000264
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
266 // make sure we know about this process
267 {
268 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
269 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
270 return false;
271 }
272
273 // first try a SIGTERM (standard kill)
274 Host::Kill(pid, SIGTERM);
275
276 // check if that worked
277 for (size_t i = 0; i < 10; ++i) {
Tamas Berghammere13c2732015-02-11 10:29:30 +0000278 {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
280 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
281 // it is now killed
282 return true;
283 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000284 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000285 usleep(10000);
286 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000287
Kate Stoneb9c1b512016-09-06 20:57:50 +0000288 // check one more time after the final usleep
289 {
290 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
291 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
292 return true;
293 }
294
Adrian Prantl05097242018-04-30 16:49:04 +0000295 // the launched process still lives. Now try killing it again, this time
296 // with an unblockable signal.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000297 Host::Kill(pid, SIGKILL);
298
299 for (size_t i = 0; i < 10; ++i) {
300 {
301 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
302 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
303 // it is now killed
304 return true;
305 }
306 }
307 usleep(10000);
308 }
309
Adrian Prantl05097242018-04-30 16:49:04 +0000310 // check one more time after the final usleep Scope for locker
Kate Stoneb9c1b512016-09-06 20:57:50 +0000311 {
312 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
313 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
314 return true;
315 }
316
317 // no luck - the process still lives
318 return false;
319}
320
321GDBRemoteCommunication::PacketResult
322GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
323 StringExtractorGDBRemote &packet) {
324 lldb::pid_t pid = m_process_launch_info.GetProcessID();
325 m_process_launch_info.Clear();
326
327 if (pid == LLDB_INVALID_PROCESS_ID)
328 return SendErrorResponse(1);
329
330 ProcessInstanceInfo proc_info;
331 if (!Host::GetProcessInfo(pid, proc_info))
332 return SendErrorResponse(1);
333
334 StreamString response;
335 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
336 return SendPacketNoLock(response.GetString());
337}
338
339GDBRemoteCommunication::PacketResult
340GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
341 StringExtractorGDBRemote &packet) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000342
Pavel Labath1d5855b2017-01-23 15:56:45 +0000343 llvm::SmallString<64> cwd;
344 if (std::error_code ec = llvm::sys::fs::current_path(cwd))
345 return SendErrorResponse(ec.value());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000346
347 StreamString response;
Pavel Labath1d5855b2017-01-23 15:56:45 +0000348 response.PutBytesAsRawHex8(cwd.data(), cwd.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000349 return SendPacketNoLock(response.GetString());
350}
351
352GDBRemoteCommunication::PacketResult
353GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
354 StringExtractorGDBRemote &packet) {
355 packet.SetFilePos(::strlen("QSetWorkingDir:"));
356 std::string path;
357 packet.GetHexByteString(path);
358
Pavel Labath2d0c5b02017-01-25 11:10:52 +0000359 if (std::error_code ec = llvm::sys::fs::set_current_path(path))
360 return SendErrorResponse(ec.value());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000361 return SendOKResponse();
362}
363
364GDBRemoteCommunication::PacketResult
365GDBRemoteCommunicationServerPlatform::Handle_qC(
366 StringExtractorGDBRemote &packet) {
367 // NOTE: lldb should now be using qProcessInfo for process IDs. This path
368 // here
369 // should not be used. It is reporting process id instead of thread id. The
370 // correct answer doesn't seem to make much sense for lldb-platform.
371 // CONSIDER: flip to "unsupported".
372 lldb::pid_t pid = m_process_launch_info.GetProcessID();
373
374 StreamString response;
375 response.Printf("QC%" PRIx64, pid);
376
Adrian Prantl05097242018-04-30 16:49:04 +0000377 // If we launch a process and this GDB server is acting as a platform, then
378 // we need to clear the process launch state so we can start launching
379 // another process. In order to launch a process a bunch or packets need to
380 // be sent: environment packets, working directory, disable ASLR, and many
381 // more settings. When we launch a process we then need to know when to clear
382 // this information. Currently we are selecting the 'qC' packet as that
383 // packet which seems to make the most sense.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384 if (pid != LLDB_INVALID_PROCESS_ID) {
385 m_process_launch_info.Clear();
386 }
387
388 return SendPacketNoLock(response.GetString());
389}
390
391GDBRemoteCommunication::PacketResult
392GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
393 StringExtractorGDBRemote &packet) {
394 StructuredData::Array signal_array;
395
Zachary Turnera89ce432019-03-06 18:20:23 +0000396 lldb::UnixSignalsSP signals = UnixSignals::CreateForHost();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 for (auto signo = signals->GetFirstSignalNumber();
398 signo != LLDB_INVALID_SIGNAL_NUMBER;
399 signo = signals->GetNextSignalNumber(signo)) {
400 auto dictionary = std::make_shared<StructuredData::Dictionary>();
401
402 dictionary->AddIntegerItem("signo", signo);
403 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
404
405 bool suppress, stop, notify;
406 signals->GetSignalInfo(signo, suppress, stop, notify);
407 dictionary->AddBooleanItem("suppress", suppress);
408 dictionary->AddBooleanItem("stop", stop);
409 dictionary->AddBooleanItem("notify", notify);
410
411 signal_array.Push(dictionary);
412 }
413
414 StreamString response;
415 signal_array.Dump(response);
416 return SendPacketNoLock(response.GetString());
417}
418
419bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
420 lldb::pid_t pid) {
421 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
422 FreePortForProcess(pid);
423 m_spawned_pids.erase(pid);
424 return true;
425}
426
Zachary Turner97206d52017-05-12 04:51:55 +0000427Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000428 if (!m_process_launch_info.GetArguments().GetArgumentCount())
Zachary Turner97206d52017-05-12 04:51:55 +0000429 return Status("%s: no process command line specified to launch",
430 __FUNCTION__);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000431
Adrian Prantl05097242018-04-30 16:49:04 +0000432 // specify the process monitor if not already set. This should generally be
433 // what happens since we need to reap started processes.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000434 if (!m_process_launch_info.GetMonitorProcessCallback())
435 m_process_launch_info.SetMonitorProcessCallback(
436 std::bind(
437 &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
438 this, std::placeholders::_1),
439 false);
440
Zachary Turner97206d52017-05-12 04:51:55 +0000441 Status error = Host::LaunchProcess(m_process_launch_info);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 if (!error.Success()) {
443 fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
444 m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
Tamas Berghammere13c2732015-02-11 10:29:30 +0000445 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446 }
447
448 printf("Launched '%s' as process %" PRIu64 "...\n",
449 m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
450 m_process_launch_info.GetProcessID());
451
Adrian Prantl05097242018-04-30 16:49:04 +0000452 // add to list of spawned processes. On an lldb-gdbserver, we would expect
453 // there to be only one.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000454 const auto pid = m_process_launch_info.GetProcessID();
455 if (pid != LLDB_INVALID_PROCESS_ID) {
456 // add to spawned pids
457 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
458 m_spawned_pids.insert(pid);
459 }
460
461 return error;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000462}
463
Kate Stoneb9c1b512016-09-06 20:57:50 +0000464void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
465 m_port_map = port_map;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000466}
467
Kate Stoneb9c1b512016-09-06 20:57:50 +0000468uint16_t GDBRemoteCommunicationServerPlatform::GetNextAvailablePort() {
469 if (m_port_map.empty())
470 return 0; // Bind to port zero and get a port, we didn't have any
471 // limitations
Tamas Berghammere13c2732015-02-11 10:29:30 +0000472
Kate Stoneb9c1b512016-09-06 20:57:50 +0000473 for (auto &pair : m_port_map) {
474 if (pair.second == LLDB_INVALID_PROCESS_ID) {
475 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
476 return pair.first;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000477 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000478 }
479 return UINT16_MAX;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000480}
481
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482bool GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess(
483 uint16_t port, lldb::pid_t pid) {
484 PortMap::iterator pos = m_port_map.find(port);
485 if (pos != m_port_map.end()) {
486 pos->second = pid;
487 return true;
488 }
489 return false;
490}
491
492bool GDBRemoteCommunicationServerPlatform::FreePort(uint16_t port) {
493 PortMap::iterator pos = m_port_map.find(port);
494 if (pos != m_port_map.end()) {
495 pos->second = LLDB_INVALID_PROCESS_ID;
496 return true;
497 }
498 return false;
499}
500
501bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) {
502 if (!m_port_map.empty()) {
503 for (auto &pair : m_port_map) {
504 if (pair.second == pid) {
505 pair.second = LLDB_INVALID_PROCESS_ID;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000506 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000507 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000508 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509 }
510 return false;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000511}
512
Kate Stoneb9c1b512016-09-06 20:57:50 +0000513const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
514 static FileSpec g_domainsocket_dir;
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000515 static llvm::once_flag g_once_flag;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000516
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +0000517 llvm::call_once(g_once_flag, []() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000518 const char *domainsocket_dir_env =
519 ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
520 if (domainsocket_dir_env != nullptr)
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000521 g_domainsocket_dir = FileSpec(domainsocket_dir_env);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000522 else
Pavel Labath60f028f2018-06-19 15:09:07 +0000523 g_domainsocket_dir = HostInfo::GetProcessTempDir();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000524 });
Tamas Berghammere13c2732015-02-11 10:29:30 +0000525
Kate Stoneb9c1b512016-09-06 20:57:50 +0000526 return g_domainsocket_dir;
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000527}
528
529FileSpec
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
Stella Stamenovab3f44ad2018-12-10 17:23:28 +0000531 llvm::SmallString<128> socket_path;
532 llvm::SmallString<128> socket_name(
Kate Stoneb9c1b512016-09-06 20:57:50 +0000533 (llvm::StringRef(prefix) + ".%%%%%%").str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000534
Kate Stoneb9c1b512016-09-06 20:57:50 +0000535 FileSpec socket_path_spec(GetDomainSocketDir());
536 socket_path_spec.AppendPathComponent(socket_name.c_str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000537
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538 llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000539 return FileSpec(socket_path.c_str());
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000540}
541
Kate Stoneb9c1b512016-09-06 20:57:50 +0000542void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
543 m_port_offset = port_offset;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000544}
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000545
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
547 lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
548 m_pending_gdb_server.pid = pid;
549 m_pending_gdb_server.port = port;
550 m_pending_gdb_server.socket_name = socket_name;
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000551}