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