blob: e16e9e4a3b8431a65f2cbdc9ff9b1a06ce7e619d [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;
Oleksiy Vyalove5510512016-02-03 22:02:43 +0000135 url << m_socket_scheme << "://";
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000136 uint16_t* port_ptr = &port;
137 if (m_socket_protocol == Socket::ProtocolTcp)
138 url << platform_ip << ":" << port;
139 else
140 {
141 socket_name = GetDomainSocketPath("gdbserver").GetPath();
142 url << socket_name;
143 port_ptr = nullptr;
144 }
145
146 Error error = StartDebugserverProcess (url.str().c_str(),
Greg Clayton6988abc2015-10-19 20:44:01 +0000147 nullptr,
148 debugserver_launch_info,
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000149 port_ptr,
150 args);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000151
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000152 pid = debugserver_launch_info.GetProcessID();
153 if (pid != LLDB_INVALID_PROCESS_ID)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000154 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000155 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000156 m_spawned_pids.insert(pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000157 if (port > 0)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000158 AssociatePortWithProcess(port, pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000159 }
160 else
161 {
162 if (port > 0)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000163 FreePort(port);
164 }
165 return error;
166}
167
168GDBRemoteCommunication::PacketResult
169GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
170{
171#ifdef _WIN32
172 return SendErrorResponse(9);
173#else
174 // Spawn a local debugserver as a platform so we can then attach or launch
175 // a process...
176
177 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
178 if (log)
179 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
180
181 ConnectionFileDescriptor file_conn;
182 std::string hostname;
183 packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
184 std::string name;
185 std::string value;
186 uint16_t port = UINT16_MAX;
187 while (packet.GetNameColonValue(name, value))
188 {
189 if (name.compare ("host") == 0)
190 hostname.swap(value);
191 else if (name.compare ("port") == 0)
192 port = StringConvert::ToUInt32(value.c_str(), 0, 0);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000193 }
194
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000195 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
196 std::string socket_name;
197 Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
198 if (error.Fail())
Tamas Berghammere13c2732015-02-11 10:29:30 +0000199 {
200 if (log)
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000201 log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
202 return SendErrorResponse(9);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000203 }
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000204
205 if (log)
206 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
207
208 StreamGDBRemote response;
209 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
210 if (!socket_name.empty())
Tamas Berghammere13c2732015-02-11 10:29:30 +0000211 {
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000212 response.PutCString("socket_name:");
213 response.PutCStringAsRawHex8(socket_name.c_str());
214 response.PutChar(';');
Tamas Berghammere13c2732015-02-11 10:29:30 +0000215 }
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000216
217 PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize());
218 if (packet_result != PacketResult::Success)
219 {
220 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
221 ::kill (debugserver_pid, SIGINT);
222 }
223 return packet_result;
Tamas Berghammere13c2732015-02-11 10:29:30 +0000224#endif
225}
226
227GDBRemoteCommunication::PacketResult
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000228GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet)
229{
230 if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
231 return SendErrorResponse(4);
232
233 JSONObject::SP server_sp = std::make_shared<JSONObject>();
234 server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port));
235 if (!m_pending_gdb_server.socket_name.empty())
236 server_sp->SetObject("socket_name",
237 std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
238
239 JSONArray server_list;
240 server_list.AppendObject(server_sp);
241
242 StreamGDBRemote response;
243 server_list.Write(response);
244
245 StreamGDBRemote escaped_response;
246 escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
247 return SendPacketNoLock(escaped_response.GetData(), escaped_response.GetSize());
248}
249
250GDBRemoteCommunication::PacketResult
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000251GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
252{
253 packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
254
255 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
256
257 // verify that we know anything about this pid.
258 // Scope for locker
259 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000260 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000261 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
262 {
263 // not a pid we know about
264 return SendErrorResponse (10);
265 }
266 }
267
268 // go ahead and attempt to kill the spawned process
269 if (KillSpawnedProcess (pid))
270 return SendOKResponse ();
271 else
272 return SendErrorResponse (11);
273}
274
275bool
276GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid)
277{
278 // make sure we know about this process
279 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000280 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000281 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
282 return false;
283 }
284
285 // first try a SIGTERM (standard kill)
286 Host::Kill (pid, SIGTERM);
287
288 // check if that worked
289 for (size_t i=0; i<10; ++i)
290 {
291 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000292 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000293 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
294 {
295 // it is now killed
296 return true;
297 }
298 }
299 usleep (10000);
300 }
301
302 // check one more time after the final usleep
303 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000304 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000305 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
306 return true;
307 }
308
309 // the launched process still lives. Now try killing it again,
310 // this time with an unblockable signal.
311 Host::Kill (pid, SIGKILL);
312
313 for (size_t i=0; i<10; ++i)
314 {
315 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000316 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000317 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
318 {
319 // it is now killed
320 return true;
321 }
322 }
323 usleep (10000);
324 }
325
326 // check one more time after the final usleep
327 // Scope for locker
328 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000329 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000330 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
331 return true;
332 }
333
334 // no luck - the process still lives
335 return false;
336}
337
338GDBRemoteCommunication::PacketResult
Tamas Berghammere13c2732015-02-11 10:29:30 +0000339GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
340{
341 lldb::pid_t pid = m_process_launch_info.GetProcessID ();
342 m_process_launch_info.Clear ();
343
344 if (pid == LLDB_INVALID_PROCESS_ID)
345 return SendErrorResponse (1);
346
347 ProcessInstanceInfo proc_info;
348 if (!Host::GetProcessInfo (pid, proc_info))
349 return SendErrorResponse (1);
350
351 StreamString response;
352 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
353 return SendPacketNoLock (response.GetData (), response.GetSize ());
354}
355
356GDBRemoteCommunication::PacketResult
357GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
358{
359 // If this packet is sent to a platform, then change the current working directory
360
361 char cwd[PATH_MAX];
362 if (getcwd(cwd, sizeof(cwd)) == NULL)
363 return SendErrorResponse(errno);
364
365 StreamString response;
366 response.PutBytesAsRawHex8(cwd, strlen(cwd));
367 return SendPacketNoLock(response.GetData(), response.GetSize());
368}
369
370GDBRemoteCommunication::PacketResult
371GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
372{
373 packet.SetFilePos (::strlen ("QSetWorkingDir:"));
374 std::string path;
375 packet.GetHexByteString (path);
376
Tamas Berghammere13c2732015-02-11 10:29:30 +0000377 // If this packet is sent to a platform, then change the current working directory
378 if (::chdir(path.c_str()) != 0)
379 return SendErrorResponse (errno);
380 return SendOKResponse ();
Tamas Berghammere13c2732015-02-11 10:29:30 +0000381}
382
383GDBRemoteCommunication::PacketResult
384GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet)
385{
386 // NOTE: lldb should now be using qProcessInfo for process IDs. This path here
387 // should not be used. It is reporting process id instead of thread id. The
388 // correct answer doesn't seem to make much sense for lldb-platform.
389 // CONSIDER: flip to "unsupported".
390 lldb::pid_t pid = m_process_launch_info.GetProcessID();
391
392 StreamString response;
393 response.Printf("QC%" PRIx64, pid);
394
395 // If we launch a process and this GDB server is acting as a platform,
396 // then we need to clear the process launch state so we can start
397 // launching another process. In order to launch a process a bunch or
398 // packets need to be sent: environment packets, working directory,
399 // disable ASLR, and many more settings. When we launch a process we
400 // then need to know when to clear this information. Currently we are
401 // selecting the 'qC' packet as that packet which seems to make the most
402 // sense.
403 if (pid != LLDB_INVALID_PROCESS_ID)
404 {
405 m_process_launch_info.Clear();
406 }
407
408 return SendPacketNoLock (response.GetData(), response.GetSize());
409}
410
Chaoren Lin98d0a4b2015-07-14 01:09:28 +0000411GDBRemoteCommunication::PacketResult
412GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet)
413{
414 StructuredData::Array signal_array;
415
416 const auto &signals = Host::GetUnixSignals();
417 for (auto signo = signals->GetFirstSignalNumber();
418 signo != LLDB_INVALID_SIGNAL_NUMBER;
419 signo = signals->GetNextSignalNumber(signo))
420 {
421 auto dictionary = std::make_shared<StructuredData::Dictionary>();
422
423 dictionary->AddIntegerItem("signo", signo);
424 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
425
426 bool suppress, stop, notify;
427 signals->GetSignalInfo(signo, suppress, stop, notify);
428 dictionary->AddBooleanItem("suppress", suppress);
429 dictionary->AddBooleanItem("stop", stop);
430 dictionary->AddBooleanItem("notify", notify);
431
432 signal_array.Push(dictionary);
433 }
434
435 StreamString response;
436 signal_array.Dump(response);
437 return SendPacketNoLock(response.GetData(), response.GetSize());
438}
439
Tamas Berghammere13c2732015-02-11 10:29:30 +0000440bool
441GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
442{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000443 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000444 FreePortForProcess(pid);
Pavel Labath998bdc52016-05-11 16:59:04 +0000445 m_spawned_pids.erase(pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000446 return true;
447}
448
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000449Error
Tamas Berghammere13c2732015-02-11 10:29:30 +0000450GDBRemoteCommunicationServerPlatform::LaunchProcess ()
451{
452 if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000453 return Error ("%s: no process command line specified to launch", __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000454
455 // specify the process monitor if not already set. This should
456 // generally be what happens since we need to reap started
457 // processes.
458 if (!m_process_launch_info.GetMonitorProcessCallback ())
Pavel Labath998bdc52016-05-11 16:59:04 +0000459 m_process_launch_info.SetMonitorProcessCallback(
460 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1),
461 false);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000462
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000463 Error error = m_platform_sp->LaunchProcess (m_process_launch_info);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000464 if (!error.Success ())
465 {
466 fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
467 return error;
468 }
469
470 printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
471
472 // add to list of spawned processes. On an lldb-gdbserver, we
473 // would expect there to be only one.
474 const auto pid = m_process_launch_info.GetProcessID();
475 if (pid != LLDB_INVALID_PROCESS_ID)
476 {
477 // add to spawned pids
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000478 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000479 m_spawned_pids.insert(pid);
480 }
481
482 return error;
483}
484
485void
486GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map)
487{
488 m_port_map = port_map;
489}
490
491uint16_t
492GDBRemoteCommunicationServerPlatform::GetNextAvailablePort ()
493{
494 if (m_port_map.empty())
495 return 0; // Bind to port zero and get a port, we didn't have any limitations
496
497 for (auto &pair : m_port_map)
498 {
499 if (pair.second == LLDB_INVALID_PROCESS_ID)
500 {
501 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
502 return pair.first;
503 }
504 }
505 return UINT16_MAX;
506}
507
508bool
509GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
510{
511 PortMap::iterator pos = m_port_map.find(port);
512 if (pos != m_port_map.end())
513 {
514 pos->second = pid;
515 return true;
516 }
517 return false;
518}
519
520bool
521GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port)
522{
523 PortMap::iterator pos = m_port_map.find(port);
524 if (pos != m_port_map.end())
525 {
526 pos->second = LLDB_INVALID_PROCESS_ID;
527 return true;
528 }
529 return false;
530}
531
532bool
533GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
534{
535 if (!m_port_map.empty())
536 {
537 for (auto &pair : m_port_map)
538 {
539 if (pair.second == pid)
540 {
541 pair.second = LLDB_INVALID_PROCESS_ID;
542 return true;
543 }
544 }
545 }
546 return false;
547}
548
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000549const FileSpec&
550GDBRemoteCommunicationServerPlatform::GetDomainSocketDir()
551{
552 static FileSpec g_domainsocket_dir;
553 static std::once_flag g_once_flag;
554
555 std::call_once(g_once_flag, []() {
556 const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
557 if (domainsocket_dir_env != nullptr)
558 g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
559 else
560 HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
561 });
562
563 return g_domainsocket_dir;
564}
565
566FileSpec
567GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix)
568{
569 llvm::SmallString<PATH_MAX> socket_path;
570 llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str());
571
572 FileSpec socket_path_spec(GetDomainSocketDir());
573 socket_path_spec.AppendPathComponent(socket_name.c_str());
574
575 llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
576 return FileSpec(socket_path.c_str(), false);
577}
578
Tamas Berghammere13c2732015-02-11 10:29:30 +0000579void
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000580GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset)
Tamas Berghammere13c2732015-02-11 10:29:30 +0000581{
582 m_port_offset = port_offset;
583}
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000584
585void
586GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid,
587 uint16_t port,
588 const std::string& socket_name)
589{
590 m_pending_gdb_server.pid = pid;
591 m_pending_gdb_server.port = port;
592 m_pending_gdb_server.socket_name = socket_name;
593}