xref: /llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp (revision 5d2b3378758b42391e90b1adf936537a66b038b6)
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 
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 
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>
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 
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 
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 
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 
108 bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const {
109   return m_port_map.empty();
110 }
111 
112 // GDBRemoteCommunicationServerPlatform constructor
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 = Status::FromErrorString("interrupt received");
153                           interrupt = true;
154                           return PacketResult::Success;
155                         });
156 }
157 
158 // Destructor
159 GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
160     default;
161 
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::FromError(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(url.str().c_str(), nullptr,
212                                          debugserver_launch_info, port_ptr,
213                                          &args, SharedSocket::kInvalidFD);
214 
215   pid = debugserver_launch_info.GetProcessID();
216   if (pid != LLDB_INVALID_PROCESS_ID) {
217     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
218     m_spawned_pids.insert(pid);
219     if (*port > 0)
220       m_port_map.AssociatePortWithProcess(*port, pid);
221   } else {
222     if (*port > 0)
223       m_port_map.FreePort(*port);
224   }
225   return error;
226 }
227 
228 GDBRemoteCommunication::PacketResult
229 GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
230     StringExtractorGDBRemote &packet) {
231   // Spawn a local debugserver as a platform so we can then attach or launch a
232   // process...
233 
234   Log *log = GetLog(LLDBLog::Platform);
235   LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
236             __FUNCTION__);
237 
238   ConnectionFileDescriptor file_conn;
239   std::string hostname;
240   packet.SetFilePos(::strlen("qLaunchGDBServer;"));
241   llvm::StringRef name;
242   llvm::StringRef value;
243   std::optional<uint16_t> port;
244   while (packet.GetNameColonValue(name, value)) {
245     if (name == "host")
246       hostname = std::string(value);
247     else if (name == "port") {
248       // Make the Optional valid so we can use its value
249       port = 0;
250       value.getAsInteger(0, *port);
251     }
252   }
253 
254   lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
255   std::string socket_name;
256   Status error =
257       LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
258   if (error.Fail()) {
259     LLDB_LOGF(log,
260               "GDBRemoteCommunicationServerPlatform::%s() debugserver "
261               "launch failed: %s",
262               __FUNCTION__, error.AsCString());
263     return SendErrorResponse(9);
264   }
265 
266   LLDB_LOGF(log,
267             "GDBRemoteCommunicationServerPlatform::%s() debugserver "
268             "launched successfully as pid %" PRIu64,
269             __FUNCTION__, debugserver_pid);
270 
271   StreamGDBRemote response;
272   assert(port);
273   response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
274                   *port + m_port_offset);
275   if (!socket_name.empty()) {
276     response.PutCString("socket_name:");
277     response.PutStringAsRawHex8(socket_name);
278     response.PutChar(';');
279   }
280 
281   PacketResult packet_result = SendPacketNoLock(response.GetString());
282   if (packet_result != PacketResult::Success) {
283     if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
284       Host::Kill(debugserver_pid, SIGINT);
285   }
286   return packet_result;
287 }
288 
289 GDBRemoteCommunication::PacketResult
290 GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
291     StringExtractorGDBRemote &packet) {
292   namespace json = llvm::json;
293 
294   if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
295     return SendErrorResponse(4);
296 
297   json::Object server{{"port", m_pending_gdb_server.port}};
298 
299   if (!m_pending_gdb_server.socket_name.empty())
300     server.try_emplace("socket_name", m_pending_gdb_server.socket_name);
301 
302   json::Array server_list;
303   server_list.push_back(std::move(server));
304 
305   StreamGDBRemote response;
306   response.AsRawOstream() << std::move(server_list);
307 
308   StreamGDBRemote escaped_response;
309   escaped_response.PutEscapedBytes(response.GetString().data(),
310                                    response.GetSize());
311   return SendPacketNoLock(escaped_response.GetString());
312 }
313 
314 GDBRemoteCommunication::PacketResult
315 GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
316     StringExtractorGDBRemote &packet) {
317   packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
318 
319   lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
320 
321   // verify that we know anything about this pid. Scope for locker
322   {
323     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
324     if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
325       // not a pid we know about
326       return SendErrorResponse(10);
327     }
328   }
329 
330   // go ahead and attempt to kill the spawned process
331   if (KillSpawnedProcess(pid))
332     return SendOKResponse();
333   else
334     return SendErrorResponse(11);
335 }
336 
337 bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
338   // make sure we know about this process
339   {
340     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
341     if (m_spawned_pids.find(pid) == m_spawned_pids.end())
342       return false;
343   }
344 
345   // first try a SIGTERM (standard kill)
346   Host::Kill(pid, SIGTERM);
347 
348   // check if that worked
349   for (size_t i = 0; i < 10; ++i) {
350     {
351       std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
352       if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
353         // it is now killed
354         return true;
355       }
356     }
357     std::this_thread::sleep_for(std::chrono::milliseconds(10));
358   }
359 
360   {
361     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
362     if (m_spawned_pids.find(pid) == m_spawned_pids.end())
363       return true;
364   }
365 
366   // the launched process still lives.  Now try killing it again, this time
367   // with an unblockable signal.
368   Host::Kill(pid, SIGKILL);
369 
370   for (size_t i = 0; i < 10; ++i) {
371     {
372       std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
373       if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
374         // it is now killed
375         return true;
376       }
377     }
378     std::this_thread::sleep_for(std::chrono::milliseconds(10));
379   }
380 
381   // check one more time after the final sleep
382   {
383     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
384     if (m_spawned_pids.find(pid) == m_spawned_pids.end())
385       return true;
386   }
387 
388   // no luck - the process still lives
389   return false;
390 }
391 
392 GDBRemoteCommunication::PacketResult
393 GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
394     StringExtractorGDBRemote &packet) {
395   lldb::pid_t pid = m_process_launch_info.GetProcessID();
396   m_process_launch_info.Clear();
397 
398   if (pid == LLDB_INVALID_PROCESS_ID)
399     return SendErrorResponse(1);
400 
401   ProcessInstanceInfo proc_info;
402   if (!Host::GetProcessInfo(pid, proc_info))
403     return SendErrorResponse(1);
404 
405   StreamString response;
406   CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
407   return SendPacketNoLock(response.GetString());
408 }
409 
410 GDBRemoteCommunication::PacketResult
411 GDBRemoteCommunicationServerPlatform::Handle_qPathComplete(
412     StringExtractorGDBRemote &packet) {
413   packet.SetFilePos(::strlen("qPathComplete:"));
414   const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1);
415   if (packet.GetChar() != ',')
416     return SendErrorResponse(85);
417   std::string path;
418   packet.GetHexByteString(path);
419 
420   StringList matches;
421   StandardTildeExpressionResolver resolver;
422   if (only_dir)
423     CommandCompletions::DiskDirectories(path, matches, resolver);
424   else
425     CommandCompletions::DiskFiles(path, matches, resolver);
426 
427   StreamString response;
428   response.PutChar('M');
429   llvm::StringRef separator;
430   std::sort(matches.begin(), matches.end());
431   for (const auto &match : matches) {
432     response << separator;
433     separator = ",";
434     // encode result strings into hex bytes to avoid unexpected error caused by
435     // special characters like '$'.
436     response.PutStringAsRawHex8(match.c_str());
437   }
438 
439   return SendPacketNoLock(response.GetString());
440 }
441 
442 GDBRemoteCommunication::PacketResult
443 GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
444     StringExtractorGDBRemote &packet) {
445 
446   llvm::SmallString<64> cwd;
447   if (std::error_code ec = llvm::sys::fs::current_path(cwd))
448     return SendErrorResponse(ec.value());
449 
450   StreamString response;
451   response.PutBytesAsRawHex8(cwd.data(), cwd.size());
452   return SendPacketNoLock(response.GetString());
453 }
454 
455 GDBRemoteCommunication::PacketResult
456 GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
457     StringExtractorGDBRemote &packet) {
458   packet.SetFilePos(::strlen("QSetWorkingDir:"));
459   std::string path;
460   packet.GetHexByteString(path);
461 
462   if (std::error_code ec = llvm::sys::fs::set_current_path(path))
463     return SendErrorResponse(ec.value());
464   return SendOKResponse();
465 }
466 
467 GDBRemoteCommunication::PacketResult
468 GDBRemoteCommunicationServerPlatform::Handle_qC(
469     StringExtractorGDBRemote &packet) {
470   // NOTE: lldb should now be using qProcessInfo for process IDs.  This path
471   // here
472   // should not be used.  It is reporting process id instead of thread id.  The
473   // correct answer doesn't seem to make much sense for lldb-platform.
474   // CONSIDER: flip to "unsupported".
475   lldb::pid_t pid = m_process_launch_info.GetProcessID();
476 
477   StreamString response;
478   response.Printf("QC%" PRIx64, pid);
479 
480   // If we launch a process and this GDB server is acting as a platform, then
481   // we need to clear the process launch state so we can start launching
482   // another process. In order to launch a process a bunch or packets need to
483   // be sent: environment packets, working directory, disable ASLR, and many
484   // more settings. When we launch a process we then need to know when to clear
485   // this information. Currently we are selecting the 'qC' packet as that
486   // packet which seems to make the most sense.
487   if (pid != LLDB_INVALID_PROCESS_ID) {
488     m_process_launch_info.Clear();
489   }
490 
491   return SendPacketNoLock(response.GetString());
492 }
493 
494 GDBRemoteCommunication::PacketResult
495 GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
496     StringExtractorGDBRemote &packet) {
497   StructuredData::Array signal_array;
498 
499   lldb::UnixSignalsSP signals = UnixSignals::CreateForHost();
500   for (auto signo = signals->GetFirstSignalNumber();
501        signo != LLDB_INVALID_SIGNAL_NUMBER;
502        signo = signals->GetNextSignalNumber(signo)) {
503     auto dictionary = std::make_shared<StructuredData::Dictionary>();
504 
505     dictionary->AddIntegerItem("signo", signo);
506     dictionary->AddStringItem("name", signals->GetSignalAsStringRef(signo));
507 
508     bool suppress, stop, notify;
509     signals->GetSignalInfo(signo, suppress, stop, notify);
510     dictionary->AddBooleanItem("suppress", suppress);
511     dictionary->AddBooleanItem("stop", stop);
512     dictionary->AddBooleanItem("notify", notify);
513 
514     signal_array.Push(dictionary);
515   }
516 
517   StreamString response;
518   signal_array.Dump(response);
519   return SendPacketNoLock(response.GetString());
520 }
521 
522 void GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
523     lldb::pid_t pid) {
524   std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
525   m_port_map.FreePortForProcess(pid);
526   m_spawned_pids.erase(pid);
527 }
528 
529 Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
530   if (!m_process_launch_info.GetArguments().GetArgumentCount())
531     return Status::FromErrorStringWithFormat(
532         "%s: no process command line specified to launch", __FUNCTION__);
533 
534   // specify the process monitor if not already set.  This should generally be
535   // what happens since we need to reap started processes.
536   if (!m_process_launch_info.GetMonitorProcessCallback())
537     m_process_launch_info.SetMonitorProcessCallback(std::bind(
538         &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this,
539         std::placeholders::_1));
540 
541   Status error = Host::LaunchProcess(m_process_launch_info);
542   if (!error.Success()) {
543     fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
544             m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
545     return error;
546   }
547 
548   printf("Launched '%s' as process %" PRIu64 "...\n",
549          m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
550          m_process_launch_info.GetProcessID());
551 
552   // add to list of spawned processes.  On an lldb-gdbserver, we would expect
553   // there to be only one.
554   const auto pid = m_process_launch_info.GetProcessID();
555   if (pid != LLDB_INVALID_PROCESS_ID) {
556     // add to spawned pids
557     std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
558     m_spawned_pids.insert(pid);
559   }
560 
561   return error;
562 }
563 
564 void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
565   m_port_map = std::move(port_map);
566 }
567 
568 const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
569   static FileSpec g_domainsocket_dir;
570   static llvm::once_flag g_once_flag;
571 
572   llvm::call_once(g_once_flag, []() {
573     const char *domainsocket_dir_env =
574         ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
575     if (domainsocket_dir_env != nullptr)
576       g_domainsocket_dir = FileSpec(domainsocket_dir_env);
577     else
578       g_domainsocket_dir = HostInfo::GetProcessTempDir();
579   });
580 
581   return g_domainsocket_dir;
582 }
583 
584 FileSpec
585 GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
586   llvm::SmallString<128> socket_path;
587   llvm::SmallString<128> socket_name(
588       (llvm::StringRef(prefix) + ".%%%%%%").str());
589 
590   FileSpec socket_path_spec(GetDomainSocketDir());
591   socket_path_spec.AppendPathComponent(socket_name.c_str());
592 
593   llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(),
594                                   socket_path);
595   return FileSpec(socket_path.c_str());
596 }
597 
598 void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
599   m_port_offset = port_offset;
600 }
601 
602 void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
603     lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
604   m_pending_gdb_server.pid = pid;
605   m_pending_gdb_server.port = port;
606   m_pending_gdb_server.socket_name = socket_name;
607 }
608