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