blob: eba237c17c99a2600ff77fd0270c7617b9ae9d39 [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(),
56 m_platform_sp(Platform::GetHostPlatform()),
57 m_port_map(),
58 m_port_offset(0)
Tamas Berghammere13c2732015-02-11 10:29:30 +000059{
Tamas Berghammer372810f2015-12-08 14:27:40 +000060 m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
61 m_pending_gdb_server.port = 0;
62
Tamas Berghammere13c2732015-02-11 10:29:30 +000063 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
64 &GDBRemoteCommunicationServerPlatform::Handle_qC);
65 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
66 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
67 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
68 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000069 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
70 &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
Pavel Labath6e4f19d2015-07-29 12:33:31 +000071 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
72 &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
Tamas Berghammere13c2732015-02-11 10:29:30 +000073 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
74 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
75 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
76 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
Chaoren Lin98d0a4b2015-07-14 01:09:28 +000077 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
78 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
Tamas Berghammere13c2732015-02-11 10:29:30 +000079
80 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000081 [this](StringExtractorGDBRemote packet, Error &error, bool &interrupt, bool &quit) {
Tamas Berghammere13c2732015-02-11 10:29:30 +000082 error.SetErrorString("interrupt received");
83 interrupt = true;
84 return PacketResult::Success;
85 });
86}
87
88//----------------------------------------------------------------------
89// Destructor
90//----------------------------------------------------------------------
91GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
92{
93}
94
Tamas Berghammerccd6cff2015-12-08 14:08:19 +000095Error
96GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& args,
97 std::string hostname,
98 lldb::pid_t& pid,
99 uint16_t& port,
100 std::string& socket_name)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000101{
Tamas Berghammere13c2732015-02-11 10:29:30 +0000102 if (port == UINT16_MAX)
103 port = GetNextAvailablePort();
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000104
Tamas Berghammere13c2732015-02-11 10:29:30 +0000105 // Spawn a new thread to accept the port that gets bound after
106 // binding to port 0 (zero).
107
108 // ignore the hostname send from the remote end, just use the ip address
109 // that we're currently communicating with as the hostname
110
111 // 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 Berghammerccd6cff2015-12-08 14:08:19 +0000115
116 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
Tamas Berghammere13c2732015-02-11 10:29:30 +0000117 if (log)
Vince Harron8b335672015-05-12 01:10:56 +0000118 log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000119
120 // Do not run in a new session so that it can not linger after the
121 // platform closes.
122 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
Pavel Labath998bdc52016-05-11 16:59:04 +0000123 debugserver_launch_info.SetMonitorProcessCallback(
124 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), false);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000125
126 std::string platform_scheme;
127 std::string platform_ip;
128 int platform_port;
129 std::string platform_path;
130 bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
Bruce Mitchener8a67bf72015-07-24 00:23:29 +0000131 UNUSED_IF_ASSERT_DISABLED(ok);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000132 assert(ok);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000133
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000134 std::ostringstream url;
Todd Fiala873a2ab2016-05-27 04:04:52 +0000135 // debugserver does not accept the URL scheme prefix.
136#if !defined(__APPLE__)
Oleksiy Vyalove5510512016-02-03 22:02:43 +0000137 url << m_socket_scheme << "://";
Todd Fiala873a2ab2016-05-27 04:04:52 +0000138#endif
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000139 uint16_t* port_ptr = &port;
140 if (m_socket_protocol == Socket::ProtocolTcp)
141 url << platform_ip << ":" << port;
142 else
143 {
144 socket_name = GetDomainSocketPath("gdbserver").GetPath();
145 url << socket_name;
146 port_ptr = nullptr;
147 }
148
149 Error error = StartDebugserverProcess (url.str().c_str(),
Greg Clayton6988abc2015-10-19 20:44:01 +0000150 nullptr,
151 debugserver_launch_info,
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000152 port_ptr,
153 args);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000154
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000155 pid = debugserver_launch_info.GetProcessID();
156 if (pid != LLDB_INVALID_PROCESS_ID)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000157 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000158 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000159 m_spawned_pids.insert(pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000160 if (port > 0)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000161 AssociatePortWithProcess(port, pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000162 }
163 else
164 {
165 if (port > 0)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000166 FreePort(port);
167 }
168 return error;
169}
170
171GDBRemoteCommunication::PacketResult
172GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
173{
174#ifdef _WIN32
175 return SendErrorResponse(9);
176#else
177 // Spawn a local debugserver as a platform so we can then attach or launch
178 // a process...
179
180 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
181 if (log)
182 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
183
184 ConnectionFileDescriptor file_conn;
185 std::string hostname;
186 packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
187 std::string name;
188 std::string value;
189 uint16_t port = UINT16_MAX;
190 while (packet.GetNameColonValue(name, value))
191 {
192 if (name.compare ("host") == 0)
193 hostname.swap(value);
194 else if (name.compare ("port") == 0)
195 port = StringConvert::ToUInt32(value.c_str(), 0, 0);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000196 }
197
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000198 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
199 std::string socket_name;
200 Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
201 if (error.Fail())
Tamas Berghammere13c2732015-02-11 10:29:30 +0000202 {
203 if (log)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000204 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
205 return SendErrorResponse(9);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000206 }
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000207
208 if (log)
209 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
210
211 StreamGDBRemote response;
212 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
213 if (!socket_name.empty())
Tamas Berghammere13c2732015-02-11 10:29:30 +0000214 {
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000215 response.PutCString("socket_name:");
216 response.PutCStringAsRawHex8(socket_name.c_str());
217 response.PutChar(';');
Tamas Berghammere13c2732015-02-11 10:29:30 +0000218 }
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000219
220 PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize());
221 if (packet_result != PacketResult::Success)
222 {
223 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
224 ::kill (debugserver_pid, SIGINT);
225 }
226 return packet_result;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000227#endif
228}
229
230GDBRemoteCommunication::PacketResult
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000231GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet)
232{
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", std::make_shared<JSONNumber>(m_pending_gdb_server.port));
238 if (!m_pending_gdb_server.socket_name.empty())
239 server_sp->SetObject("socket_name",
240 std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
241
242 JSONArray server_list;
243 server_list.AppendObject(server_sp);
244
245 StreamGDBRemote response;
246 server_list.Write(response);
247
248 StreamGDBRemote escaped_response;
249 escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
250 return SendPacketNoLock(escaped_response.GetData(), escaped_response.GetSize());
251}
252
253GDBRemoteCommunication::PacketResult
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000254GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
255{
256 packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
257
258 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
259
260 // verify that we know anything about this pid.
261 // Scope for locker
262 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000263 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000264 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
265 {
266 // not a pid we know about
267 return SendErrorResponse (10);
268 }
269 }
270
271 // go ahead and attempt to kill the spawned process
272 if (KillSpawnedProcess (pid))
273 return SendOKResponse ();
274 else
275 return SendErrorResponse (11);
276}
277
278bool
279GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid)
280{
281 // make sure we know about this process
282 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000283 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000284 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
285 return false;
286 }
287
288 // first try a SIGTERM (standard kill)
289 Host::Kill (pid, SIGTERM);
290
291 // check if that worked
292 for (size_t i=0; i<10; ++i)
293 {
294 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000295 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000296 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
297 {
298 // it is now killed
299 return true;
300 }
301 }
302 usleep (10000);
303 }
304
305 // check one more time after the final usleep
306 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000307 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000308 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
309 return true;
310 }
311
312 // the launched process still lives. Now try killing it again,
313 // this time with an unblockable signal.
314 Host::Kill (pid, SIGKILL);
315
316 for (size_t i=0; i<10; ++i)
317 {
318 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000319 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000320 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
321 {
322 // it is now killed
323 return true;
324 }
325 }
326 usleep (10000);
327 }
328
329 // check one more time after the final usleep
330 // Scope for locker
331 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000332 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000333 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
334 return true;
335 }
336
337 // no luck - the process still lives
338 return false;
339}
340
341GDBRemoteCommunication::PacketResult
Tamas Berghammere13c2732015-02-11 10:29:30 +0000342GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
343{
344 lldb::pid_t pid = m_process_launch_info.GetProcessID ();
345 m_process_launch_info.Clear ();
346
347 if (pid == LLDB_INVALID_PROCESS_ID)
348 return SendErrorResponse (1);
349
350 ProcessInstanceInfo proc_info;
351 if (!Host::GetProcessInfo (pid, proc_info))
352 return SendErrorResponse (1);
353
354 StreamString response;
355 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
356 return SendPacketNoLock (response.GetData (), response.GetSize ());
357}
358
359GDBRemoteCommunication::PacketResult
360GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
361{
362 // If this packet is sent to a platform, then change the current working directory
363
364 char cwd[PATH_MAX];
365 if (getcwd(cwd, sizeof(cwd)) == NULL)
366 return SendErrorResponse(errno);
367
368 StreamString response;
369 response.PutBytesAsRawHex8(cwd, strlen(cwd));
370 return SendPacketNoLock(response.GetData(), response.GetSize());
371}
372
373GDBRemoteCommunication::PacketResult
374GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
375{
376 packet.SetFilePos (::strlen ("QSetWorkingDir:"));
377 std::string path;
378 packet.GetHexByteString (path);
379
Tamas Berghammere13c2732015-02-11 10:29:30 +0000380 // If this packet is sent to a platform, then change the current working directory
381 if (::chdir(path.c_str()) != 0)
382 return SendErrorResponse (errno);
383 return SendOKResponse ();
Tamas Berghammere13c2732015-02-11 10:29:30 +0000384}
385
386GDBRemoteCommunication::PacketResult
387GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet)
388{
389 // NOTE: lldb should now be using qProcessInfo for process IDs. This path here
390 // should not be used. It is reporting process id instead of thread id. The
391 // correct answer doesn't seem to make much sense for lldb-platform.
392 // CONSIDER: flip to "unsupported".
393 lldb::pid_t pid = m_process_launch_info.GetProcessID();
394
395 StreamString response;
396 response.Printf("QC%" PRIx64, pid);
397
398 // If we launch a process and this GDB server is acting as a platform,
399 // then we need to clear the process launch state so we can start
400 // launching another process. In order to launch a process a bunch or
401 // packets need to be sent: environment packets, working directory,
402 // disable ASLR, and many more settings. When we launch a process we
403 // then need to know when to clear this information. Currently we are
404 // selecting the 'qC' packet as that packet which seems to make the most
405 // sense.
406 if (pid != LLDB_INVALID_PROCESS_ID)
407 {
408 m_process_launch_info.Clear();
409 }
410
411 return SendPacketNoLock (response.GetData(), response.GetSize());
412}
413
Chaoren Lin98d0a4b2015-07-14 01:09:28 +0000414GDBRemoteCommunication::PacketResult
415GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet)
416{
417 StructuredData::Array signal_array;
418
419 const auto &signals = Host::GetUnixSignals();
420 for (auto signo = signals->GetFirstSignalNumber();
421 signo != LLDB_INVALID_SIGNAL_NUMBER;
422 signo = signals->GetNextSignalNumber(signo))
423 {
424 auto dictionary = std::make_shared<StructuredData::Dictionary>();
425
426 dictionary->AddIntegerItem("signo", signo);
427 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
428
429 bool suppress, stop, notify;
430 signals->GetSignalInfo(signo, suppress, stop, notify);
431 dictionary->AddBooleanItem("suppress", suppress);
432 dictionary->AddBooleanItem("stop", stop);
433 dictionary->AddBooleanItem("notify", notify);
434
435 signal_array.Push(dictionary);
436 }
437
438 StreamString response;
439 signal_array.Dump(response);
440 return SendPacketNoLock(response.GetData(), response.GetSize());
441}
442
Tamas Berghammere13c2732015-02-11 10:29:30 +0000443bool
444GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
445{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000446 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000447 FreePortForProcess(pid);
Pavel Labath998bdc52016-05-11 16:59:04 +0000448 m_spawned_pids.erase(pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000449 return true;
450}
451
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000452Error
Tamas Berghammere13c2732015-02-11 10:29:30 +0000453GDBRemoteCommunicationServerPlatform::LaunchProcess ()
454{
455 if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000456 return Error ("%s: no process command line specified to launch", __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000457
458 // specify the process monitor if not already set. This should
459 // generally be what happens since we need to reap started
460 // processes.
461 if (!m_process_launch_info.GetMonitorProcessCallback ())
Pavel Labath998bdc52016-05-11 16:59:04 +0000462 m_process_launch_info.SetMonitorProcessCallback(
463 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1),
464 false);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000465
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000466 Error error = m_platform_sp->LaunchProcess (m_process_launch_info);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000467 if (!error.Success ())
468 {
469 fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
470 return error;
471 }
472
473 printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
474
475 // add to list of spawned processes. On an lldb-gdbserver, we
476 // would expect there to be only one.
477 const auto pid = m_process_launch_info.GetProcessID();
478 if (pid != LLDB_INVALID_PROCESS_ID)
479 {
480 // add to spawned pids
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000481 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000482 m_spawned_pids.insert(pid);
483 }
484
485 return error;
486}
487
488void
489GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map)
490{
491 m_port_map = port_map;
492}
493
494uint16_t
495GDBRemoteCommunicationServerPlatform::GetNextAvailablePort ()
496{
497 if (m_port_map.empty())
498 return 0; // Bind to port zero and get a port, we didn't have any limitations
499
500 for (auto &pair : m_port_map)
501 {
502 if (pair.second == LLDB_INVALID_PROCESS_ID)
503 {
504 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
505 return pair.first;
506 }
507 }
508 return UINT16_MAX;
509}
510
511bool
512GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
513{
514 PortMap::iterator pos = m_port_map.find(port);
515 if (pos != m_port_map.end())
516 {
517 pos->second = pid;
518 return true;
519 }
520 return false;
521}
522
523bool
524GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port)
525{
526 PortMap::iterator pos = m_port_map.find(port);
527 if (pos != m_port_map.end())
528 {
529 pos->second = LLDB_INVALID_PROCESS_ID;
530 return true;
531 }
532 return false;
533}
534
535bool
536GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
537{
538 if (!m_port_map.empty())
539 {
540 for (auto &pair : m_port_map)
541 {
542 if (pair.second == pid)
543 {
544 pair.second = LLDB_INVALID_PROCESS_ID;
545 return true;
546 }
547 }
548 }
549 return false;
550}
551
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000552const FileSpec&
553GDBRemoteCommunicationServerPlatform::GetDomainSocketDir()
554{
555 static FileSpec g_domainsocket_dir;
556 static std::once_flag g_once_flag;
557
558 std::call_once(g_once_flag, []() {
559 const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
560 if (domainsocket_dir_env != nullptr)
561 g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
562 else
563 HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
564 });
565
566 return g_domainsocket_dir;
567}
568
569FileSpec
570GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix)
571{
572 llvm::SmallString<PATH_MAX> socket_path;
573 llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str());
574
575 FileSpec socket_path_spec(GetDomainSocketDir());
576 socket_path_spec.AppendPathComponent(socket_name.c_str());
577
578 llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
579 return FileSpec(socket_path.c_str(), false);
580}
581
Tamas Berghammere13c2732015-02-11 10:29:30 +0000582void
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000583GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000584{
585 m_port_offset = port_offset;
586}
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000587
588void
589GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid,
590 uint16_t port,
591 const std::string& socket_name)
592{
593 m_pending_gdb_server.pid = pid;
594 m_pending_gdb_server.port = port;
595 m_pending_gdb_server.socket_name = socket_name;
596}