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