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