blob: 19a29b4654abd515d204e58fd2278f8f37045c6b [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 Berghammere13c2732015-02-11 10:29:30 +000037
38// Project includes
39#include "Utility/StringExtractorGDBRemote.h"
40#include "Utility/UriParser.h"
41
42using namespace lldb;
43using namespace lldb_private;
Tamas Berghammerdb264a62015-03-31 09:52:22 +000044using namespace lldb_private::process_gdb_remote;
Tamas Berghammere13c2732015-02-11 10:29:30 +000045
46//----------------------------------------------------------------------
47// GDBRemoteCommunicationServerPlatform constructor
48//----------------------------------------------------------------------
Oleksiy Vyalov14857122015-10-28 19:49:50 +000049GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,
50 const char* socket_scheme) :
Tamas Berghammere13c2732015-02-11 10:29:30 +000051 GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"),
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +000052 m_socket_protocol(socket_protocol),
Oleksiy Vyalov14857122015-10-28 19:49:50 +000053 m_socket_scheme(socket_scheme),
Pavel Labath6e4f19d2015-07-29 12:33:31 +000054 m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
Tamas Berghammere13c2732015-02-11 10:29:30 +000055 m_platform_sp (Platform::GetHostPlatform ()),
56 m_port_map (),
57 m_port_offset(0)
58{
59 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
60 &GDBRemoteCommunicationServerPlatform::Handle_qC);
61 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
62 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
63 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
64 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
Pavel Labath6e4f19d2015-07-29 12:33:31 +000065 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
66 &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
Tamas Berghammere13c2732015-02-11 10:29:30 +000067 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
68 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
69 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
70 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
Chaoren Lin98d0a4b2015-07-14 01:09:28 +000071 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
72 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
Tamas Berghammere13c2732015-02-11 10:29:30 +000073
74 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
75 [this](StringExtractorGDBRemote packet,
76 Error &error,
77 bool &interrupt,
78 bool &quit)
79 {
80 error.SetErrorString("interrupt received");
81 interrupt = true;
82 return PacketResult::Success;
83 });
84}
85
86//----------------------------------------------------------------------
87// Destructor
88//----------------------------------------------------------------------
89GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
90{
91}
92
93GDBRemoteCommunication::PacketResult
94GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
95{
96#ifdef _WIN32
97 return SendErrorResponse(9);
98#else
99 // Spawn a local debugserver as a platform so we can then attach or launch
100 // a process...
101
102 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
103 if (log)
Oleksiy Vyalovc282ebd2015-02-24 22:23:39 +0000104 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000105
106 // Sleep and wait a bit for debugserver to start to listen...
107 ConnectionFileDescriptor file_conn;
108 std::string hostname;
109 // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
110 // with the TMPDIR environment variable
Oleksiy Vyalovc282ebd2015-02-24 22:23:39 +0000111 packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
Tamas Berghammere13c2732015-02-11 10:29:30 +0000112 std::string name;
113 std::string value;
114 uint16_t port = UINT16_MAX;
115 while (packet.GetNameColonValue(name, value))
116 {
117 if (name.compare ("host") == 0)
118 hostname.swap(value);
119 else if (name.compare ("port") == 0)
120 port = StringConvert::ToUInt32(value.c_str(), 0, 0);
121 }
122 if (port == UINT16_MAX)
123 port = GetNextAvailablePort();
124
125 // Spawn a new thread to accept the port that gets bound after
126 // binding to port 0 (zero).
127
128 // ignore the hostname send from the remote end, just use the ip address
129 // that we're currently communicating with as the hostname
130
131 // Spawn a debugserver and try to get the port it listens to.
132 ProcessLaunchInfo debugserver_launch_info;
133 if (hostname.empty())
134 hostname = "127.0.0.1";
135 if (log)
Vince Harron8b335672015-05-12 01:10:56 +0000136 log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000137
138 // Do not run in a new session so that it can not linger after the
139 // platform closes.
140 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
141 debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
142
143 std::string platform_scheme;
144 std::string platform_ip;
145 int platform_port;
146 std::string platform_path;
147 bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
Bruce Mitchener8a67bf72015-07-24 00:23:29 +0000148 UNUSED_IF_ASSERT_DISABLED(ok);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000149 assert(ok);
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000150
151 std::string socket_name;
152 std::ostringstream url;
153
154 uint16_t* port_ptr = &port;
Oleksiy Vyalov14857122015-10-28 19:49:50 +0000155 url << m_socket_scheme << "://";
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000156 if (m_socket_protocol == Socket::ProtocolTcp)
157 url << platform_ip << ":" << port;
158 else
159 {
160 socket_name = GetDomainSocketPath("gdbserver").GetPath();
161 url << socket_name;
162 port_ptr = nullptr;
163 }
164
165 Error error = StartDebugserverProcess (url.str().c_str(),
Greg Clayton6988abc2015-10-19 20:44:01 +0000166 nullptr,
167 debugserver_launch_info,
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000168 port_ptr);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000169
170 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
171
172
173 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
174 {
175 Mutex::Locker locker (m_spawned_pids_mutex);
176 m_spawned_pids.insert(debugserver_pid);
177 if (port > 0)
178 AssociatePortWithProcess(port, debugserver_pid);
179 }
180 else
181 {
182 if (port > 0)
183 FreePort (port);
184 }
185
186 if (error.Success())
187 {
188 if (log)
Oleksiy Vyalov946e39a2015-02-25 01:11:38 +0000189 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000190
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000191 StreamGDBRemote response;
192 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
193 if (!socket_name.empty())
194 {
195 response.PutCString("socket_name:");
196 response.PutCStringAsRawHex8(socket_name.c_str());
197 response.PutChar(';');
198 }
Tamas Berghammere13c2732015-02-11 10:29:30 +0000199
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000200 PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize());
Tamas Berghammere13c2732015-02-11 10:29:30 +0000201 if (packet_result != PacketResult::Success)
202 {
203 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
204 ::kill (debugserver_pid, SIGINT);
205 }
206 return packet_result;
207 }
208 else
209 {
210 if (log)
Oleksiy Vyalov946e39a2015-02-25 01:11:38 +0000211 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
Tamas Berghammere13c2732015-02-11 10:29:30 +0000212 }
213 return SendErrorResponse (9);
214#endif
215}
216
217GDBRemoteCommunication::PacketResult
Pavel Labath6e4f19d2015-07-29 12:33:31 +0000218GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
219{
220 packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
221
222 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
223
224 // verify that we know anything about this pid.
225 // Scope for locker
226 {
227 Mutex::Locker locker (m_spawned_pids_mutex);
228 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
229 {
230 // not a pid we know about
231 return SendErrorResponse (10);
232 }
233 }
234
235 // go ahead and attempt to kill the spawned process
236 if (KillSpawnedProcess (pid))
237 return SendOKResponse ();
238 else
239 return SendErrorResponse (11);
240}
241
242bool
243GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid)
244{
245 // make sure we know about this process
246 {
247 Mutex::Locker locker (m_spawned_pids_mutex);
248 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
249 return false;
250 }
251
252 // first try a SIGTERM (standard kill)
253 Host::Kill (pid, SIGTERM);
254
255 // check if that worked
256 for (size_t i=0; i<10; ++i)
257 {
258 {
259 Mutex::Locker locker (m_spawned_pids_mutex);
260 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
261 {
262 // it is now killed
263 return true;
264 }
265 }
266 usleep (10000);
267 }
268
269 // check one more time after the final usleep
270 {
271 Mutex::Locker locker (m_spawned_pids_mutex);
272 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
273 return true;
274 }
275
276 // the launched process still lives. Now try killing it again,
277 // this time with an unblockable signal.
278 Host::Kill (pid, SIGKILL);
279
280 for (size_t i=0; i<10; ++i)
281 {
282 {
283 Mutex::Locker locker (m_spawned_pids_mutex);
284 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
285 {
286 // it is now killed
287 return true;
288 }
289 }
290 usleep (10000);
291 }
292
293 // check one more time after the final usleep
294 // Scope for locker
295 {
296 Mutex::Locker locker (m_spawned_pids_mutex);
297 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
298 return true;
299 }
300
301 // no luck - the process still lives
302 return false;
303}
304
305GDBRemoteCommunication::PacketResult
Tamas Berghammere13c2732015-02-11 10:29:30 +0000306GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
307{
308 lldb::pid_t pid = m_process_launch_info.GetProcessID ();
309 m_process_launch_info.Clear ();
310
311 if (pid == LLDB_INVALID_PROCESS_ID)
312 return SendErrorResponse (1);
313
314 ProcessInstanceInfo proc_info;
315 if (!Host::GetProcessInfo (pid, proc_info))
316 return SendErrorResponse (1);
317
318 StreamString response;
319 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
320 return SendPacketNoLock (response.GetData (), response.GetSize ());
321}
322
323GDBRemoteCommunication::PacketResult
324GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
325{
326 // If this packet is sent to a platform, then change the current working directory
327
328 char cwd[PATH_MAX];
329 if (getcwd(cwd, sizeof(cwd)) == NULL)
330 return SendErrorResponse(errno);
331
332 StreamString response;
333 response.PutBytesAsRawHex8(cwd, strlen(cwd));
334 return SendPacketNoLock(response.GetData(), response.GetSize());
335}
336
337GDBRemoteCommunication::PacketResult
338GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
339{
340 packet.SetFilePos (::strlen ("QSetWorkingDir:"));
341 std::string path;
342 packet.GetHexByteString (path);
343
Tamas Berghammere13c2732015-02-11 10:29:30 +0000344 // If this packet is sent to a platform, then change the current working directory
345 if (::chdir(path.c_str()) != 0)
346 return SendErrorResponse (errno);
347 return SendOKResponse ();
Tamas Berghammere13c2732015-02-11 10:29:30 +0000348}
349
350GDBRemoteCommunication::PacketResult
351GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet)
352{
353 // NOTE: lldb should now be using qProcessInfo for process IDs. This path here
354 // should not be used. It is reporting process id instead of thread id. The
355 // correct answer doesn't seem to make much sense for lldb-platform.
356 // CONSIDER: flip to "unsupported".
357 lldb::pid_t pid = m_process_launch_info.GetProcessID();
358
359 StreamString response;
360 response.Printf("QC%" PRIx64, pid);
361
362 // If we launch a process and this GDB server is acting as a platform,
363 // then we need to clear the process launch state so we can start
364 // launching another process. In order to launch a process a bunch or
365 // packets need to be sent: environment packets, working directory,
366 // disable ASLR, and many more settings. When we launch a process we
367 // then need to know when to clear this information. Currently we are
368 // selecting the 'qC' packet as that packet which seems to make the most
369 // sense.
370 if (pid != LLDB_INVALID_PROCESS_ID)
371 {
372 m_process_launch_info.Clear();
373 }
374
375 return SendPacketNoLock (response.GetData(), response.GetSize());
376}
377
Chaoren Lin98d0a4b2015-07-14 01:09:28 +0000378GDBRemoteCommunication::PacketResult
379GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet)
380{
381 StructuredData::Array signal_array;
382
383 const auto &signals = Host::GetUnixSignals();
384 for (auto signo = signals->GetFirstSignalNumber();
385 signo != LLDB_INVALID_SIGNAL_NUMBER;
386 signo = signals->GetNextSignalNumber(signo))
387 {
388 auto dictionary = std::make_shared<StructuredData::Dictionary>();
389
390 dictionary->AddIntegerItem("signo", signo);
391 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
392
393 bool suppress, stop, notify;
394 signals->GetSignalInfo(signo, suppress, stop, notify);
395 dictionary->AddBooleanItem("suppress", suppress);
396 dictionary->AddBooleanItem("stop", stop);
397 dictionary->AddBooleanItem("notify", notify);
398
399 signal_array.Push(dictionary);
400 }
401
402 StreamString response;
403 signal_array.Dump(response);
404 return SendPacketNoLock(response.GetData(), response.GetSize());
405}
406
Tamas Berghammere13c2732015-02-11 10:29:30 +0000407bool
408GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
409{
410 Mutex::Locker locker (m_spawned_pids_mutex);
411 FreePortForProcess(pid);
412 return m_spawned_pids.erase(pid) > 0;
413}
414
415bool
416GDBRemoteCommunicationServerPlatform::ReapDebugserverProcess (void *callback_baton,
417 lldb::pid_t pid,
418 bool exited,
419 int signal, // Zero for no signal
420 int status) // Exit value of process if signal is zero
421{
422 GDBRemoteCommunicationServerPlatform *server = (GDBRemoteCommunicationServerPlatform *)callback_baton;
423 server->DebugserverProcessReaped (pid);
424 return true;
425}
426
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000427Error
Tamas Berghammere13c2732015-02-11 10:29:30 +0000428GDBRemoteCommunicationServerPlatform::LaunchProcess ()
429{
430 if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000431 return Error ("%s: no process command line specified to launch", __FUNCTION__);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000432
433 // specify the process monitor if not already set. This should
434 // generally be what happens since we need to reap started
435 // processes.
436 if (!m_process_launch_info.GetMonitorProcessCallback ())
437 m_process_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
438
Tamas Berghammerdb264a62015-03-31 09:52:22 +0000439 Error error = m_platform_sp->LaunchProcess (m_process_launch_info);
Tamas Berghammere13c2732015-02-11 10:29:30 +0000440 if (!error.Success ())
441 {
442 fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
443 return error;
444 }
445
446 printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
447
448 // add to list of spawned processes. On an lldb-gdbserver, we
449 // would expect there to be only one.
450 const auto pid = m_process_launch_info.GetProcessID();
451 if (pid != LLDB_INVALID_PROCESS_ID)
452 {
453 // add to spawned pids
454 Mutex::Locker locker (m_spawned_pids_mutex);
455 m_spawned_pids.insert(pid);
456 }
457
458 return error;
459}
460
461void
462GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map)
463{
464 m_port_map = port_map;
465}
466
467uint16_t
468GDBRemoteCommunicationServerPlatform::GetNextAvailablePort ()
469{
470 if (m_port_map.empty())
471 return 0; // Bind to port zero and get a port, we didn't have any limitations
472
473 for (auto &pair : m_port_map)
474 {
475 if (pair.second == LLDB_INVALID_PROCESS_ID)
476 {
477 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
478 return pair.first;
479 }
480 }
481 return UINT16_MAX;
482}
483
484bool
485GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
486{
487 PortMap::iterator pos = m_port_map.find(port);
488 if (pos != m_port_map.end())
489 {
490 pos->second = pid;
491 return true;
492 }
493 return false;
494}
495
496bool
497GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port)
498{
499 PortMap::iterator pos = m_port_map.find(port);
500 if (pos != m_port_map.end())
501 {
502 pos->second = LLDB_INVALID_PROCESS_ID;
503 return true;
504 }
505 return false;
506}
507
508bool
509GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
510{
511 if (!m_port_map.empty())
512 {
513 for (auto &pair : m_port_map)
514 {
515 if (pair.second == pid)
516 {
517 pair.second = LLDB_INVALID_PROCESS_ID;
518 return true;
519 }
520 }
521 }
522 return false;
523}
524
Oleksiy Vyalov9fe526c2015-10-21 19:34:26 +0000525const FileSpec&
526GDBRemoteCommunicationServerPlatform::GetDomainSocketDir()
527{
528 static FileSpec g_domainsocket_dir;
529 static std::once_flag g_once_flag;
530
531 std::call_once(g_once_flag, []() {
532 const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
533 if (domainsocket_dir_env != nullptr)
534 g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
535 else
536 HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
537 });
538
539 return g_domainsocket_dir;
540}
541
542FileSpec
543GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix)
544{
545 llvm::SmallString<PATH_MAX> socket_path;
546 llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str());
547
548 FileSpec socket_path_spec(GetDomainSocketDir());
549 socket_path_spec.AppendPathComponent(socket_name.c_str());
550
551 llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
552 return FileSpec(socket_path.c_str(), false);
553}
554
Tamas Berghammere13c2732015-02-11 10:29:30 +0000555void
556GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset)
557{
558 m_port_offset = port_offset;
559}