blob: d6900c27293c7583e9bee70a4afe76b4ba1e3d2f [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
16#include <cstring>
17#include <chrono>
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"
23
Tamas Berghammere13c2732015-02-11 10:29:30 +000024#include "lldb/Core/Log.h"
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000025#include "lldb/Core/StreamGDBRemote.h"
Tamas Berghammere13c2732015-02-11 10:29:30 +000026#include "lldb/Core/StreamString.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"
Tamas Berghammere13c2732015-02-11 10:29:30 +000038
39// Project includes
40#include "Utility/StringExtractorGDBRemote.h"
41#include "Utility/UriParser.h"
42
43using namespace lldb;
44using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000045using namespace lldb_private::process_gdb_remote;
Tamas Berghammere13c2732015-02-11 10:29:30 +000046
47//----------------------------------------------------------------------
48// GDBRemoteCommunicationServerPlatform constructor
49//----------------------------------------------------------------------
Oleksiy Vyalov14857122015-10-28 19:49:50 +000050GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000051 const char *socket_scheme)
52 : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"),
53 m_socket_protocol(socket_protocol),
54 m_socket_scheme(socket_scheme),
55 m_spawned_pids_mutex(),
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000056 m_port_map(),
57 m_port_offset(0)
Tamas Berghammere13c2732015-02-11 10:29:30 +000058{
Tamas Berghammer372810f2015-12-08 14:27:40 +000059 m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
60 m_pending_gdb_server.port = 0;
61
Tamas Berghammere13c2732015-02-11 10:29:30 +000062 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
63 &GDBRemoteCommunicationServerPlatform::Handle_qC);
64 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
65 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
66 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
67 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000068 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
69 &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
Pavel Labath6e4f19d2015-07-29 12:33:31 +000070 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
71 &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
Tamas Berghammere13c2732015-02-11 10:29:30 +000072 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
73 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
74 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
75 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
Chaoren Lin98d0a4b2015-07-14 01:09:28 +000076 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
77 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
Tamas Berghammere13c2732015-02-11 10:29:30 +000078
79 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000080 [this](StringExtractorGDBRemote packet, Error &error, bool &interrupt, bool &quit) {
Tamas Berghammere13c2732015-02-11 10:29:30 +000081 error.SetErrorString("interrupt received");
82 interrupt = true;
83 return PacketResult::Success;
84 });
85}
86
87//----------------------------------------------------------------------
88// Destructor
89//----------------------------------------------------------------------
90GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
91{
92}
93
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000094Error
95GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& args,
96 std::string hostname,
97 lldb::pid_t& pid,
98 uint16_t& port,
99 std::string& socket_name)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000100{
Tamas Berghammere13c2732015-02-11 10:29:30 +0000101 if (port == UINT16_MAX)
102 port = GetNextAvailablePort();
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000103
Tamas Berghammere13c2732015-02-11 10:29:30 +0000104 // Spawn a new thread to accept the port that gets bound after
105 // binding to port 0 (zero).
106
107 // ignore the hostname send from the remote end, just use the ip address
108 // that we're currently communicating with as the hostname
109
110 // Spawn a debugserver and try to get the port it listens to.
111 ProcessLaunchInfo debugserver_launch_info;
112 if (hostname.empty())
113 hostname = "127.0.0.1";
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000114
115 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
Tamas Berghammere13c2732015-02-11 10:29:30 +0000116 if (log)
Vince Harron8b335672015-05-12 01:10:56 +0000117 log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000118
119 // Do not run in a new session so that it can not linger after the
120 // platform closes.
121 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
Pavel Labath998bdc52016-05-11 16:59:04 +0000122 debugserver_launch_info.SetMonitorProcessCallback(
123 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), false);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000124
125 std::string platform_scheme;
126 std::string platform_ip;
127 int platform_port;
128 std::string platform_path;
129 bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
Bruce Mitchener8a67bf72015-07-24 00:23:29 +0000130 UNUSED_IF_ASSERT_DISABLED(ok);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000131 assert(ok);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000132
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000133 std::ostringstream url;
Todd Fiala873a2ab2016-05-27 04:04:52 +0000134 // debugserver does not accept the URL scheme prefix.
135#if !defined(__APPLE__)
Oleksiy Vyalove5510512016-02-03 22:02:43 +0000136 url << m_socket_scheme << "://";
Todd Fiala873a2ab2016-05-27 04:04:52 +0000137#endif
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000138 uint16_t* port_ptr = &port;
139 if (m_socket_protocol == Socket::ProtocolTcp)
140 url << platform_ip << ":" << port;
141 else
142 {
143 socket_name = GetDomainSocketPath("gdbserver").GetPath();
144 url << socket_name;
145 port_ptr = nullptr;
146 }
147
148 Error error = StartDebugserverProcess (url.str().c_str(),
Greg Clayton6988abc2015-10-19 20:44:01 +0000149 nullptr,
150 debugserver_launch_info,
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000151 port_ptr,
152 args);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000153
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000154 pid = debugserver_launch_info.GetProcessID();
155 if (pid != LLDB_INVALID_PROCESS_ID)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000156 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000157 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000158 m_spawned_pids.insert(pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000159 if (port > 0)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000160 AssociatePortWithProcess(port, pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000161 }
162 else
163 {
164 if (port > 0)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000165 FreePort(port);
166 }
167 return error;
168}
169
170GDBRemoteCommunication::PacketResult
171GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
172{
173#ifdef _WIN32
174 return SendErrorResponse(9);
175#else
176 // Spawn a local debugserver as a platform so we can then attach or launch
177 // a process...
178
179 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
180 if (log)
181 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
182
183 ConnectionFileDescriptor file_conn;
184 std::string hostname;
185 packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
186 std::string name;
187 std::string value;
188 uint16_t port = UINT16_MAX;
189 while (packet.GetNameColonValue(name, value))
190 {
191 if (name.compare ("host") == 0)
192 hostname.swap(value);
193 else if (name.compare ("port") == 0)
194 port = StringConvert::ToUInt32(value.c_str(), 0, 0);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000195 }
196
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000197 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
198 std::string socket_name;
199 Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
200 if (error.Fail())
Tamas Berghammere13c2732015-02-11 10:29:30 +0000201 {
202 if (log)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000203 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
204 return SendErrorResponse(9);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000205 }
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000206
207 if (log)
208 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
209
210 StreamGDBRemote response;
211 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
212 if (!socket_name.empty())
Tamas Berghammere13c2732015-02-11 10:29:30 +0000213 {
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000214 response.PutCString("socket_name:");
215 response.PutCStringAsRawHex8(socket_name.c_str());
216 response.PutChar(';');
Tamas Berghammere13c2732015-02-11 10:29:30 +0000217 }
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000218
219 PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize());
220 if (packet_result != PacketResult::Success)
221 {
222 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
223 ::kill (debugserver_pid, SIGINT);
224 }
225 return packet_result;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000226#endif
227}
228
229GDBRemoteCommunication::PacketResult
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000230GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet)
231{
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", std::make_shared<JSONNumber>(m_pending_gdb_server.port));
237 if (!m_pending_gdb_server.socket_name.empty())
238 server_sp->SetObject("socket_name",
239 std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
240
241 JSONArray server_list;
242 server_list.AppendObject(server_sp);
243
244 StreamGDBRemote response;
245 server_list.Write(response);
246
247 StreamGDBRemote escaped_response;
248 escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
249 return SendPacketNoLock(escaped_response.GetData(), escaped_response.GetSize());
250}
251
252GDBRemoteCommunication::PacketResult
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000253GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
254{
255 packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
256
257 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
258
259 // verify that we know anything about this pid.
260 // Scope for locker
261 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000262 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000263 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
264 {
265 // not a pid we know about
266 return SendErrorResponse (10);
267 }
268 }
269
270 // go ahead and attempt to kill the spawned process
271 if (KillSpawnedProcess (pid))
272 return SendOKResponse ();
273 else
274 return SendErrorResponse (11);
275}
276
277bool
278GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid)
279{
280 // make sure we know about this process
281 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000282 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000283 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)
292 {
293 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000294 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000295 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
296 {
297 // it is now killed
298 return true;
299 }
300 }
301 usleep (10000);
302 }
303
304 // check one more time after the final usleep
305 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000306 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000307 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
308 return true;
309 }
310
311 // the launched process still lives. Now try killing it again,
312 // this time with an unblockable signal.
313 Host::Kill (pid, SIGKILL);
314
315 for (size_t i=0; i<10; ++i)
316 {
317 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000318 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000319 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
320 {
321 // it is now killed
322 return true;
323 }
324 }
325 usleep (10000);
326 }
327
328 // check one more time after the final usleep
329 // Scope for locker
330 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000331 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000332 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
333 return true;
334 }
335
336 // no luck - the process still lives
337 return false;
338}
339
340GDBRemoteCommunication::PacketResult
Tamas Berghammere13c2732015-02-11 10:29:30 +0000341GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
342{
343 lldb::pid_t pid = m_process_launch_info.GetProcessID ();
344 m_process_launch_info.Clear ();
345
346 if (pid == LLDB_INVALID_PROCESS_ID)
347 return SendErrorResponse (1);
348
349 ProcessInstanceInfo proc_info;
350 if (!Host::GetProcessInfo (pid, proc_info))
351 return SendErrorResponse (1);
352
353 StreamString response;
354 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
355 return SendPacketNoLock (response.GetData (), response.GetSize ());
356}
357
358GDBRemoteCommunication::PacketResult
359GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
360{
361 // If this packet is sent to a platform, then change the current working directory
362
363 char cwd[PATH_MAX];
364 if (getcwd(cwd, sizeof(cwd)) == NULL)
365 return SendErrorResponse(errno);
366
367 StreamString response;
368 response.PutBytesAsRawHex8(cwd, strlen(cwd));
369 return SendPacketNoLock(response.GetData(), response.GetSize());
370}
371
372GDBRemoteCommunication::PacketResult
373GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
374{
375 packet.SetFilePos (::strlen ("QSetWorkingDir:"));
376 std::string path;
377 packet.GetHexByteString (path);
378
Tamas Berghammere13c2732015-02-11 10:29:30 +0000379 // If this packet is sent to a platform, then change the current working directory
380 if (::chdir(path.c_str()) != 0)
381 return SendErrorResponse (errno);
382 return SendOKResponse ();
Tamas Berghammere13c2732015-02-11 10:29:30 +0000383}
384
385GDBRemoteCommunication::PacketResult
386GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet)
387{
388 // NOTE: lldb should now be using qProcessInfo for process IDs. This path here
389 // should not be used. It is reporting process id instead of thread id. The
390 // correct answer doesn't seem to make much sense for lldb-platform.
391 // CONSIDER: flip to "unsupported".
392 lldb::pid_t pid = m_process_launch_info.GetProcessID();
393
394 StreamString response;
395 response.Printf("QC%" PRIx64, pid);
396
397 // If we launch a process and this GDB server is acting as a platform,
398 // then we need to clear the process launch state so we can start
399 // launching another process. In order to launch a process a bunch or
400 // packets need to be sent: environment packets, working directory,
401 // disable ASLR, and many more settings. When we launch a process we
402 // then need to know when to clear this information. Currently we are
403 // selecting the 'qC' packet as that packet which seems to make the most
404 // sense.
405 if (pid != LLDB_INVALID_PROCESS_ID)
406 {
407 m_process_launch_info.Clear();
408 }
409
410 return SendPacketNoLock (response.GetData(), response.GetSize());
411}
412
Chaoren Lin98d0a4b2015-07-14 01:09:28 +0000413GDBRemoteCommunication::PacketResult
414GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet)
415{
416 StructuredData::Array signal_array;
417
418 const auto &signals = Host::GetUnixSignals();
419 for (auto signo = signals->GetFirstSignalNumber();
420 signo != LLDB_INVALID_SIGNAL_NUMBER;
421 signo = signals->GetNextSignalNumber(signo))
422 {
423 auto dictionary = std::make_shared<StructuredData::Dictionary>();
424
425 dictionary->AddIntegerItem("signo", signo);
426 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
427
428 bool suppress, stop, notify;
429 signals->GetSignalInfo(signo, suppress, stop, notify);
430 dictionary->AddBooleanItem("suppress", suppress);
431 dictionary->AddBooleanItem("stop", stop);
432 dictionary->AddBooleanItem("notify", notify);
433
434 signal_array.Push(dictionary);
435 }
436
437 StreamString response;
438 signal_array.Dump(response);
439 return SendPacketNoLock(response.GetData(), response.GetSize());
440}
441
Tamas Berghammere13c2732015-02-11 10:29:30 +0000442bool
443GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
444{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000445 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000446 FreePortForProcess(pid);
Pavel Labath998bdc52016-05-11 16:59:04 +0000447 m_spawned_pids.erase(pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000448 return true;
449}
450
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000451Error
Tamas Berghammere13c2732015-02-11 10:29:30 +0000452GDBRemoteCommunicationServerPlatform::LaunchProcess ()
453{
454 if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000455 return Error ("%s: no process command line specified to launch", __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000456
457 // specify the process monitor if not already set. This should
458 // generally be what happens since we need to reap started
459 // processes.
460 if (!m_process_launch_info.GetMonitorProcessCallback ())
Pavel Labath998bdc52016-05-11 16:59:04 +0000461 m_process_launch_info.SetMonitorProcessCallback(
462 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1),
463 false);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000464
Pavel Labathf1763532016-06-29 13:58:27 +0000465 Error error = Host::LaunchProcess(m_process_launch_info);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000466 if (!error.Success ())
467 {
468 fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
469 return error;
470 }
471
472 printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
473
474 // add to list of spawned processes. On an lldb-gdbserver, we
475 // would expect there to be only one.
476 const auto pid = m_process_launch_info.GetProcessID();
477 if (pid != LLDB_INVALID_PROCESS_ID)
478 {
479 // add to spawned pids
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000480 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000481 m_spawned_pids.insert(pid);
482 }
483
484 return error;
485}
486
487void
488GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map)
489{
490 m_port_map = port_map;
491}
492
493uint16_t
494GDBRemoteCommunicationServerPlatform::GetNextAvailablePort ()
495{
496 if (m_port_map.empty())
497 return 0; // Bind to port zero and get a port, we didn't have any limitations
498
499 for (auto &pair : m_port_map)
500 {
501 if (pair.second == LLDB_INVALID_PROCESS_ID)
502 {
503 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
504 return pair.first;
505 }
506 }
507 return UINT16_MAX;
508}
509
510bool
511GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
512{
513 PortMap::iterator pos = m_port_map.find(port);
514 if (pos != m_port_map.end())
515 {
516 pos->second = pid;
517 return true;
518 }
519 return false;
520}
521
522bool
523GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port)
524{
525 PortMap::iterator pos = m_port_map.find(port);
526 if (pos != m_port_map.end())
527 {
528 pos->second = LLDB_INVALID_PROCESS_ID;
529 return true;
530 }
531 return false;
532}
533
534bool
535GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
536{
537 if (!m_port_map.empty())
538 {
539 for (auto &pair : m_port_map)
540 {
541 if (pair.second == pid)
542 {
543 pair.second = LLDB_INVALID_PROCESS_ID;
544 return true;
545 }
546 }
547 }
548 return false;
549}
550
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000551const FileSpec&
552GDBRemoteCommunicationServerPlatform::GetDomainSocketDir()
553{
554 static FileSpec g_domainsocket_dir;
555 static std::once_flag g_once_flag;
556
557 std::call_once(g_once_flag, []() {
558 const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
559 if (domainsocket_dir_env != nullptr)
560 g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
561 else
562 HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
563 });
564
565 return g_domainsocket_dir;
566}
567
568FileSpec
569GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix)
570{
571 llvm::SmallString<PATH_MAX> socket_path;
572 llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str());
573
574 FileSpec socket_path_spec(GetDomainSocketDir());
575 socket_path_spec.AppendPathComponent(socket_name.c_str());
576
577 llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
578 return FileSpec(socket_path.c_str(), false);
579}
580
Tamas Berghammere13c2732015-02-11 10:29:30 +0000581void
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000582GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000583{
584 m_port_offset = port_offset;
585}
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000586
587void
588GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid,
589 uint16_t port,
590 const std::string& socket_name)
591{
592 m_pending_gdb_server.pid = pid;
593 m_pending_gdb_server.port = port;
594 m_pending_gdb_server.socket_name = socket_name;
595}