1 //===-- GDBRemoteCommunicationServerPlatform.cpp --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "GDBRemoteCommunicationServerPlatform.h"
10
11 #include <cerrno>
12
13 #include <chrono>
14 #include <csignal>
15 #include <cstring>
16 #include <mutex>
17 #include <optional>
18 #include <sstream>
19 #include <thread>
20
21 #include "llvm/Support/FileSystem.h"
22 #include "llvm/Support/JSON.h"
23 #include "llvm/Support/Threading.h"
24
25 #include "lldb/Host/Config.h"
26 #include "lldb/Host/ConnectionFileDescriptor.h"
27 #include "lldb/Host/FileAction.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Host/HostInfo.h"
30 #include "lldb/Interpreter/CommandCompletions.h"
31 #include "lldb/Target/Platform.h"
32 #include "lldb/Target/UnixSignals.h"
33 #include "lldb/Utility/GDBRemote.h"
34 #include "lldb/Utility/LLDBLog.h"
35 #include "lldb/Utility/Log.h"
36 #include "lldb/Utility/StreamString.h"
37 #include "lldb/Utility/StructuredData.h"
38 #include "lldb/Utility/TildeExpressionResolver.h"
39 #include "lldb/Utility/UriParser.h"
40
41 #include "lldb/Utility/StringExtractorGDBRemote.h"
42
43 using namespace lldb;
44 using namespace lldb_private::process_gdb_remote;
45 using namespace lldb_private;
46
PortMap(uint16_t min_port,uint16_t max_port)47 GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
48 uint16_t max_port) {
49 assert(min_port);
50 for (; min_port < max_port; ++min_port)
51 m_port_map[min_port] = LLDB_INVALID_PROCESS_ID;
52 }
53
AllowPort(uint16_t port)54 void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) {
55 assert(port);
56 // Do not modify existing mappings
57 m_port_map.insert({port, LLDB_INVALID_PROCESS_ID});
58 }
59
60 llvm::Expected<uint16_t>
GetNextAvailablePort()61 GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() {
62 if (m_port_map.empty())
63 return 0; // Bind to port zero and get a port, we didn't have any
64 // limitations
65
66 for (auto &pair : m_port_map) {
67 if (pair.second == LLDB_INVALID_PROCESS_ID) {
68 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
69 return pair.first;
70 }
71 }
72 return llvm::createStringError(llvm::inconvertibleErrorCode(),
73 "No free port found in port map");
74 }
75
AssociatePortWithProcess(uint16_t port,lldb::pid_t pid)76 bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess(
77 uint16_t port, lldb::pid_t pid) {
78 auto pos = m_port_map.find(port);
79 if (pos != m_port_map.end()) {
80 pos->second = pid;
81 return true;
82 }
83 return false;
84 }
85
FreePort(uint16_t port)86 bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) {
87 std::map<uint16_t, lldb::pid_t>::iterator pos = m_port_map.find(port);
88 if (pos != m_port_map.end()) {
89 pos->second = LLDB_INVALID_PROCESS_ID;
90 return true;
91 }
92 return false;
93 }
94
FreePortForProcess(lldb::pid_t pid)95 bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess(
96 lldb::pid_t pid) {
97 if (!m_port_map.empty()) {
98 for (auto &pair : m_port_map) {
99 if (pair.second == pid) {
100 pair.second = LLDB_INVALID_PROCESS_ID;
101 return true;
102 }
103 }
104 }
105 return false;
106 }
107
empty() const108 bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const {
109 return m_port_map.empty();
110 }
111
112 // GDBRemoteCommunicationServerPlatform constructor
GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,const char * socket_scheme)113 GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
114 const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
115 : GDBRemoteCommunicationServerCommon(),
116 m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
117 m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
118 m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
119 m_pending_gdb_server.port = 0;
120
121 RegisterMemberFunctionHandler(
122 StringExtractorGDBRemote::eServerPacketType_qC,
123 &GDBRemoteCommunicationServerPlatform::Handle_qC);
124 RegisterMemberFunctionHandler(
125 StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
126 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
127 RegisterMemberFunctionHandler(
128 StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
129 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
130 RegisterMemberFunctionHandler(
131 StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
132 &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
133 RegisterMemberFunctionHandler(
134 StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
135 &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
136 RegisterMemberFunctionHandler(
137 StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
138 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
139 RegisterMemberFunctionHandler(
140 StringExtractorGDBRemote::eServerPacketType_qPathComplete,
141 &GDBRemoteCommunicationServerPlatform::Handle_qPathComplete);
142 RegisterMemberFunctionHandler(
143 StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
144 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
145 RegisterMemberFunctionHandler(
146 StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
147 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
148
149 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
150 [](StringExtractorGDBRemote packet, Status &error,
151 bool &interrupt, bool &quit) {
152 error.SetErrorString("interrupt received");
153 interrupt = true;
154 return PacketResult::Success;
155 });
156 }
157
158 // Destructor
159 GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
160 default;
161
LaunchGDBServer(const lldb_private::Args & args,std::string hostname,lldb::pid_t & pid,std::optional<uint16_t> & port,std::string & socket_name)162 Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
163 const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
164 std::optional<uint16_t> &port, std::string &socket_name) {
165 if (!port) {
166 llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort();
167 if (available_port)
168 port = *available_port;
169 else
170 return Status(available_port.takeError());
171 }
172
173 // Spawn a new thread to accept the port that gets bound after binding to
174 // port 0 (zero).
175
176 // ignore the hostname send from the remote end, just use the ip address that
177 // we're currently communicating with as the hostname
178
179 // Spawn a debugserver and try to get the port it listens to.
180 ProcessLaunchInfo debugserver_launch_info;
181 if (hostname.empty())
182 hostname = "127.0.0.1";
183
184 Log *log = GetLog(LLDBLog::Platform);
185 LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(),
186 *port);
187
188 // Do not run in a new session so that it can not linger after the platform
189 // closes.
190 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
191 debugserver_launch_info.SetMonitorProcessCallback(
192 std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
193 this, std::placeholders::_1));
194
195 std::ostringstream url;
196 // debugserver does not accept the URL scheme prefix.
197 #if !defined(__APPLE__)
198 url << m_socket_scheme << "://";
199 #endif
200 uint16_t *port_ptr = &*port;
201 if (m_socket_protocol == Socket::ProtocolTcp) {
202 std::string platform_uri = GetConnection()->GetURI();
203 std::optional<URI> parsed_uri = URI::Parse(platform_uri);
204 url << '[' << parsed_uri->hostname.str() << "]:" << *port;
205 } else {
206 socket_name = GetDomainSocketPath("gdbserver").GetPath();
207 url << socket_name;
208 port_ptr = nullptr;
209 }
210
211 Status error = StartDebugserverProcess(
212 url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
213
214 pid = debugserver_launch_info.GetProcessID();
215 if (pid != LLDB_INVALID_PROCESS_ID) {
216 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
217 m_spawned_pids.insert(pid);
218 if (*port > 0)
219 m_port_map.AssociatePortWithProcess(*port, pid);
220 } else {
221 if (*port > 0)
222 m_port_map.FreePort(*port);
223 }
224 return error;
225 }
226
227 GDBRemoteCommunication::PacketResult
Handle_qLaunchGDBServer(StringExtractorGDBRemote & packet)228 GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
229 StringExtractorGDBRemote &packet) {
230 // Spawn a local debugserver as a platform so we can then attach or launch a
231 // process...
232
233 Log *log = GetLog(LLDBLog::Platform);
234 LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
235 __FUNCTION__);
236
237 ConnectionFileDescriptor file_conn;
238 std::string hostname;
239 packet.SetFilePos(::strlen("qLaunchGDBServer;"));
240 llvm::StringRef name;
241 llvm::StringRef value;
242 std::optional<uint16_t> port;
243 while (packet.GetNameColonValue(name, value)) {
244 if (name == "host")
245 hostname = std::string(value);
246 else if (name == "port") {
247 // Make the Optional valid so we can use its value
248 port = 0;
249 value.getAsInteger(0, *port);
250 }
251 }
252
253 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
254 std::string socket_name;
255 Status error =
256 LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
257 if (error.Fail()) {
258 LLDB_LOGF(log,
259 "GDBRemoteCommunicationServerPlatform::%s() debugserver "
260 "launch failed: %s",
261 __FUNCTION__, error.AsCString());
262 return SendErrorResponse(9);
263 }
264
265 LLDB_LOGF(log,
266 "GDBRemoteCommunicationServerPlatform::%s() debugserver "
267 "launched successfully as pid %" PRIu64,
268 __FUNCTION__, debugserver_pid);
269
270 StreamGDBRemote response;
271 assert(port);
272 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
273 *port + m_port_offset);
274 if (!socket_name.empty()) {
275 response.PutCString("socket_name:");
276 response.PutStringAsRawHex8(socket_name);
277 response.PutChar(';');
278 }
279
280 PacketResult packet_result = SendPacketNoLock(response.GetString());
281 if (packet_result != PacketResult::Success) {
282 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
283 Host::Kill(debugserver_pid, SIGINT);
284 }
285 return packet_result;
286 }
287
288 GDBRemoteCommunication::PacketResult
Handle_qQueryGDBServer(StringExtractorGDBRemote & packet)289 GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
290 StringExtractorGDBRemote &packet) {
291 namespace json = llvm::json;
292
293 if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
294 return SendErrorResponse(4);
295
296 json::Object server{{"port", m_pending_gdb_server.port}};
297
298 if (!m_pending_gdb_server.socket_name.empty())
299 server.try_emplace("socket_name", m_pending_gdb_server.socket_name);
300
301 json::Array server_list;
302 server_list.push_back(std::move(server));
303
304 StreamGDBRemote response;
305 response.AsRawOstream() << std::move(server_list);
306
307 StreamGDBRemote escaped_response;
308 escaped_response.PutEscapedBytes(response.GetString().data(),
309 response.GetSize());
310 return SendPacketNoLock(escaped_response.GetString());
311 }
312
313 GDBRemoteCommunication::PacketResult
Handle_qKillSpawnedProcess(StringExtractorGDBRemote & packet)314 GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
315 StringExtractorGDBRemote &packet) {
316 packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
317
318 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
319
320 // verify that we know anything about this pid. Scope for locker
321 {
322 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
323 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
324 // not a pid we know about
325 return SendErrorResponse(10);
326 }
327 }
328
329 // go ahead and attempt to kill the spawned process
330 if (KillSpawnedProcess(pid))
331 return SendOKResponse();
332 else
333 return SendErrorResponse(11);
334 }
335
KillSpawnedProcess(lldb::pid_t pid)336 bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
337 // make sure we know about this process
338 {
339 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
340 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
341 return false;
342 }
343
344 // first try a SIGTERM (standard kill)
345 Host::Kill(pid, SIGTERM);
346
347 // check if that worked
348 for (size_t i = 0; i < 10; ++i) {
349 {
350 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
351 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
352 // it is now killed
353 return true;
354 }
355 }
356 std::this_thread::sleep_for(std::chrono::milliseconds(10));
357 }
358
359 {
360 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
361 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
362 return true;
363 }
364
365 // the launched process still lives. Now try killing it again, this time
366 // with an unblockable signal.
367 Host::Kill(pid, SIGKILL);
368
369 for (size_t i = 0; i < 10; ++i) {
370 {
371 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
372 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
373 // it is now killed
374 return true;
375 }
376 }
377 std::this_thread::sleep_for(std::chrono::milliseconds(10));
378 }
379
380 // check one more time after the final sleep
381 {
382 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
383 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
384 return true;
385 }
386
387 // no luck - the process still lives
388 return false;
389 }
390
391 GDBRemoteCommunication::PacketResult
Handle_qProcessInfo(StringExtractorGDBRemote & packet)392 GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
393 StringExtractorGDBRemote &packet) {
394 lldb::pid_t pid = m_process_launch_info.GetProcessID();
395 m_process_launch_info.Clear();
396
397 if (pid == LLDB_INVALID_PROCESS_ID)
398 return SendErrorResponse(1);
399
400 ProcessInstanceInfo proc_info;
401 if (!Host::GetProcessInfo(pid, proc_info))
402 return SendErrorResponse(1);
403
404 StreamString response;
405 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
406 return SendPacketNoLock(response.GetString());
407 }
408
409 GDBRemoteCommunication::PacketResult
Handle_qPathComplete(StringExtractorGDBRemote & packet)410 GDBRemoteCommunicationServerPlatform::Handle_qPathComplete(
411 StringExtractorGDBRemote &packet) {
412 packet.SetFilePos(::strlen("qPathComplete:"));
413 const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1);
414 if (packet.GetChar() != ',')
415 return SendErrorResponse(85);
416 std::string path;
417 packet.GetHexByteString(path);
418
419 StringList matches;
420 StandardTildeExpressionResolver resolver;
421 if (only_dir)
422 CommandCompletions::DiskDirectories(path, matches, resolver);
423 else
424 CommandCompletions::DiskFiles(path, matches, resolver);
425
426 StreamString response;
427 response.PutChar('M');
428 llvm::StringRef separator;
429 std::sort(matches.begin(), matches.end());
430 for (const auto &match : matches) {
431 response << separator;
432 separator = ",";
433 // encode result strings into hex bytes to avoid unexpected error caused by
434 // special characters like '$'.
435 response.PutStringAsRawHex8(match.c_str());
436 }
437
438 return SendPacketNoLock(response.GetString());
439 }
440
441 GDBRemoteCommunication::PacketResult
Handle_qGetWorkingDir(StringExtractorGDBRemote & packet)442 GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
443 StringExtractorGDBRemote &packet) {
444
445 llvm::SmallString<64> cwd;
446 if (std::error_code ec = llvm::sys::fs::current_path(cwd))
447 return SendErrorResponse(ec.value());
448
449 StreamString response;
450 response.PutBytesAsRawHex8(cwd.data(), cwd.size());
451 return SendPacketNoLock(response.GetString());
452 }
453
454 GDBRemoteCommunication::PacketResult
Handle_QSetWorkingDir(StringExtractorGDBRemote & packet)455 GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
456 StringExtractorGDBRemote &packet) {
457 packet.SetFilePos(::strlen("QSetWorkingDir:"));
458 std::string path;
459 packet.GetHexByteString(path);
460
461 if (std::error_code ec = llvm::sys::fs::set_current_path(path))
462 return SendErrorResponse(ec.value());
463 return SendOKResponse();
464 }
465
466 GDBRemoteCommunication::PacketResult
Handle_qC(StringExtractorGDBRemote & packet)467 GDBRemoteCommunicationServerPlatform::Handle_qC(
468 StringExtractorGDBRemote &packet) {
469 // NOTE: lldb should now be using qProcessInfo for process IDs. This path
470 // here
471 // should not be used. It is reporting process id instead of thread id. The
472 // correct answer doesn't seem to make much sense for lldb-platform.
473 // CONSIDER: flip to "unsupported".
474 lldb::pid_t pid = m_process_launch_info.GetProcessID();
475
476 StreamString response;
477 response.Printf("QC%" PRIx64, pid);
478
479 // If we launch a process and this GDB server is acting as a platform, then
480 // we need to clear the process launch state so we can start launching
481 // another process. In order to launch a process a bunch or packets need to
482 // be sent: environment packets, working directory, disable ASLR, and many
483 // more settings. When we launch a process we then need to know when to clear
484 // this information. Currently we are selecting the 'qC' packet as that
485 // packet which seems to make the most sense.
486 if (pid != LLDB_INVALID_PROCESS_ID) {
487 m_process_launch_info.Clear();
488 }
489
490 return SendPacketNoLock(response.GetString());
491 }
492
493 GDBRemoteCommunication::PacketResult
Handle_jSignalsInfo(StringExtractorGDBRemote & packet)494 GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
495 StringExtractorGDBRemote &packet) {
496 StructuredData::Array signal_array;
497
498 lldb::UnixSignalsSP signals = UnixSignals::CreateForHost();
499 for (auto signo = signals->GetFirstSignalNumber();
500 signo != LLDB_INVALID_SIGNAL_NUMBER;
501 signo = signals->GetNextSignalNumber(signo)) {
502 auto dictionary = std::make_shared<StructuredData::Dictionary>();
503
504 dictionary->AddIntegerItem("signo", signo);
505 dictionary->AddStringItem("name", signals->GetSignalAsStringRef(signo));
506
507 bool suppress, stop, notify;
508 signals->GetSignalInfo(signo, suppress, stop, notify);
509 dictionary->AddBooleanItem("suppress", suppress);
510 dictionary->AddBooleanItem("stop", stop);
511 dictionary->AddBooleanItem("notify", notify);
512
513 signal_array.Push(dictionary);
514 }
515
516 StreamString response;
517 signal_array.Dump(response);
518 return SendPacketNoLock(response.GetString());
519 }
520
DebugserverProcessReaped(lldb::pid_t pid)521 void GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
522 lldb::pid_t pid) {
523 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
524 m_port_map.FreePortForProcess(pid);
525 m_spawned_pids.erase(pid);
526 }
527
LaunchProcess()528 Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
529 if (!m_process_launch_info.GetArguments().GetArgumentCount())
530 return Status("%s: no process command line specified to launch",
531 __FUNCTION__);
532
533 // specify the process monitor if not already set. This should generally be
534 // what happens since we need to reap started processes.
535 if (!m_process_launch_info.GetMonitorProcessCallback())
536 m_process_launch_info.SetMonitorProcessCallback(std::bind(
537 &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this,
538 std::placeholders::_1));
539
540 Status error = Host::LaunchProcess(m_process_launch_info);
541 if (!error.Success()) {
542 fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
543 m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
544 return error;
545 }
546
547 printf("Launched '%s' as process %" PRIu64 "...\n",
548 m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
549 m_process_launch_info.GetProcessID());
550
551 // add to list of spawned processes. On an lldb-gdbserver, we would expect
552 // there to be only one.
553 const auto pid = m_process_launch_info.GetProcessID();
554 if (pid != LLDB_INVALID_PROCESS_ID) {
555 // add to spawned pids
556 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
557 m_spawned_pids.insert(pid);
558 }
559
560 return error;
561 }
562
SetPortMap(PortMap && port_map)563 void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
564 m_port_map = std::move(port_map);
565 }
566
GetDomainSocketDir()567 const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
568 static FileSpec g_domainsocket_dir;
569 static llvm::once_flag g_once_flag;
570
571 llvm::call_once(g_once_flag, []() {
572 const char *domainsocket_dir_env =
573 ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
574 if (domainsocket_dir_env != nullptr)
575 g_domainsocket_dir = FileSpec(domainsocket_dir_env);
576 else
577 g_domainsocket_dir = HostInfo::GetProcessTempDir();
578 });
579
580 return g_domainsocket_dir;
581 }
582
583 FileSpec
GetDomainSocketPath(const char * prefix)584 GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
585 llvm::SmallString<128> socket_path;
586 llvm::SmallString<128> socket_name(
587 (llvm::StringRef(prefix) + ".%%%%%%").str());
588
589 FileSpec socket_path_spec(GetDomainSocketDir());
590 socket_path_spec.AppendPathComponent(socket_name.c_str());
591
592 llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(),
593 socket_path);
594 return FileSpec(socket_path.c_str());
595 }
596
SetPortOffset(uint16_t port_offset)597 void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
598 m_port_offset = port_offset;
599 }
600
SetPendingGdbServer(lldb::pid_t pid,uint16_t port,const std::string & socket_name)601 void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
602 lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
603 m_pending_gdb_server.pid = pid;
604 m_pending_gdb_server.port = port;
605 m_pending_gdb_server.socket_name = socket_name;
606 }
607