LLDB  mainline
GDBRemoteCommunicationServerPlatform.cpp
Go to the documentation of this file.
1 //===-- GDBRemoteCommunicationServerPlatform.cpp ----------------*- C++ -*-===//
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 
10 
11 #include <errno.h>
12 
13 #include <chrono>
14 #include <csignal>
15 #include <cstring>
16 #include <mutex>
17 #include <sstream>
18 
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/Threading.h"
21 
22 #include "lldb/Host/Config.h"
24 #include "lldb/Host/FileAction.h"
25 #include "lldb/Host/Host.h"
26 #include "lldb/Host/HostInfo.h"
27 #include "lldb/Target/Platform.h"
29 #include "lldb/Utility/JSON.h"
30 #include "lldb/Utility/Log.h"
34 #include "lldb/Utility/UriParser.h"
35 
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 using namespace lldb_private::process_gdb_remote;
41 
42 // GDBRemoteCommunicationServerPlatform constructor
43 GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
44  const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
45  : GDBRemoteCommunicationServerCommon("gdb-remote.server",
46  "gdb-remote.server.rx_packet"),
47  m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
48  m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
50  m_pending_gdb_server.port = 0;
51 
76 
78  [](StringExtractorGDBRemote packet, Status &error,
79  bool &interrupt, bool &quit) {
80  error.SetErrorString("interrupt received");
81  interrupt = true;
82  return PacketResult::Success;
83  });
84 }
85 
86 // Destructor
88 
90  const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
91  uint16_t &port, std::string &socket_name) {
92  if (port == UINT16_MAX)
93  port = GetNextAvailablePort();
94 
95  // Spawn a new thread to accept the port that gets bound after binding to
96  // port 0 (zero).
97 
98  // ignore the hostname send from the remote end, just use the ip address that
99  // we're currently communicating with as the hostname
100 
101  // Spawn a debugserver and try to get the port it listens to.
102  ProcessLaunchInfo debugserver_launch_info;
103  if (hostname.empty())
104  hostname = "127.0.0.1";
105 
107  if (log)
108  log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
109 
110  // Do not run in a new session so that it can not linger after the platform
111  // closes.
112  debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
113  debugserver_launch_info.SetMonitorProcessCallback(
114  std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
115  this, std::placeholders::_1),
116  false);
117 
118  llvm::StringRef platform_scheme;
119  llvm::StringRef platform_ip;
120  int platform_port;
121  llvm::StringRef platform_path;
122  std::string platform_uri = GetConnection()->GetURI();
123  bool ok = UriParser::Parse(platform_uri, platform_scheme, platform_ip,
124  platform_port, platform_path);
126  assert(ok);
127 
128  std::ostringstream url;
129 // debugserver does not accept the URL scheme prefix.
130 #if !defined(__APPLE__)
131  url << m_socket_scheme << "://";
132 #endif
133  uint16_t *port_ptr = &port;
135  url << platform_ip.str() << ":" << port;
136  else {
137  socket_name = GetDomainSocketPath("gdbserver").GetPath();
138  url << socket_name;
139  port_ptr = nullptr;
140  }
141 
143  url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
144 
145  pid = debugserver_launch_info.GetProcessID();
146  if (pid != LLDB_INVALID_PROCESS_ID) {
147  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
148  m_spawned_pids.insert(pid);
149  if (port > 0)
150  AssociatePortWithProcess(port, pid);
151  } else {
152  if (port > 0)
153  FreePort(port);
154  }
155  return error;
156 }
157 
160  StringExtractorGDBRemote &packet) {
161  // Spawn a local debugserver as a platform so we can then attach or launch a
162  // process...
163 
165  if (log)
166  log->Printf("GDBRemoteCommunicationServerPlatform::%s() called",
167  __FUNCTION__);
168 
169  ConnectionFileDescriptor file_conn;
170  std::string hostname;
171  packet.SetFilePos(::strlen("qLaunchGDBServer;"));
172  llvm::StringRef name;
173  llvm::StringRef value;
174  uint16_t port = UINT16_MAX;
175  while (packet.GetNameColonValue(name, value)) {
176  if (name.equals("host"))
177  hostname = value;
178  else if (name.equals("port"))
179  value.getAsInteger(0, port);
180  }
181 
182  lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
183  std::string socket_name;
184  Status error =
185  LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
186  if (error.Fail()) {
187  if (log)
188  log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
189  "launch failed: %s",
190  __FUNCTION__, error.AsCString());
191  return SendErrorResponse(9);
192  }
193 
194  if (log)
195  log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
196  "launched successfully as pid %" PRIu64,
197  __FUNCTION__, debugserver_pid);
198 
199  StreamGDBRemote response;
200  response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
201  port + m_port_offset);
202  if (!socket_name.empty()) {
203  response.PutCString("socket_name:");
204  response.PutStringAsRawHex8(socket_name);
205  response.PutChar(';');
206  }
207 
208  PacketResult packet_result = SendPacketNoLock(response.GetString());
209  if (packet_result != PacketResult::Success) {
210  if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
211  Host::Kill(debugserver_pid, SIGINT);
212  }
213  return packet_result;
214 }
215 
218  StringExtractorGDBRemote &packet) {
220  return SendErrorResponse(4);
221 
222  JSONObject::SP server_sp = std::make_shared<JSONObject>();
223  server_sp->SetObject("port",
224  std::make_shared<JSONNumber>(m_pending_gdb_server.port));
225  if (!m_pending_gdb_server.socket_name.empty())
226  server_sp->SetObject(
227  "socket_name",
228  std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
229 
230  JSONArray server_list;
231  server_list.AppendObject(server_sp);
232 
233  StreamGDBRemote response;
234  server_list.Write(response);
235 
236  StreamGDBRemote escaped_response;
237  escaped_response.PutEscapedBytes(response.GetString().data(),
238  response.GetSize());
239  return SendPacketNoLock(escaped_response.GetString());
240 }
241 
244  StringExtractorGDBRemote &packet) {
245  packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
246 
248 
249  // verify that we know anything about this pid. Scope for locker
250  {
251  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
252  if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
253  // not a pid we know about
254  return SendErrorResponse(10);
255  }
256  }
257 
258  // go ahead and attempt to kill the spawned process
259  if (KillSpawnedProcess(pid))
260  return SendOKResponse();
261  else
262  return SendErrorResponse(11);
263 }
264 
265 bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
266  // make sure we know about this process
267  {
268  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
269  if (m_spawned_pids.find(pid) == m_spawned_pids.end())
270  return false;
271  }
272 
273  // first try a SIGTERM (standard kill)
274  Host::Kill(pid, SIGTERM);
275 
276  // check if that worked
277  for (size_t i = 0; i < 10; ++i) {
278  {
279  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
280  if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
281  // it is now killed
282  return true;
283  }
284  }
285  usleep(10000);
286  }
287 
288  // check one more time after the final usleep
289  {
290  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
291  if (m_spawned_pids.find(pid) == m_spawned_pids.end())
292  return true;
293  }
294 
295  // the launched process still lives. Now try killing it again, this time
296  // with an unblockable signal.
297  Host::Kill(pid, SIGKILL);
298 
299  for (size_t i = 0; i < 10; ++i) {
300  {
301  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
302  if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
303  // it is now killed
304  return true;
305  }
306  }
307  usleep(10000);
308  }
309 
310  // check one more time after the final usleep Scope for locker
311  {
312  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
313  if (m_spawned_pids.find(pid) == m_spawned_pids.end())
314  return true;
315  }
316 
317  // no luck - the process still lives
318  return false;
319 }
320 
323  StringExtractorGDBRemote &packet) {
326 
327  if (pid == LLDB_INVALID_PROCESS_ID)
328  return SendErrorResponse(1);
329 
330  ProcessInstanceInfo proc_info;
331  if (!Host::GetProcessInfo(pid, proc_info))
332  return SendErrorResponse(1);
333 
334  StreamString response;
335  CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
336  return SendPacketNoLock(response.GetString());
337 }
338 
341  StringExtractorGDBRemote &packet) {
342 
343  llvm::SmallString<64> cwd;
344  if (std::error_code ec = llvm::sys::fs::current_path(cwd))
345  return SendErrorResponse(ec.value());
346 
347  StreamString response;
348  response.PutBytesAsRawHex8(cwd.data(), cwd.size());
349  return SendPacketNoLock(response.GetString());
350 }
351 
354  StringExtractorGDBRemote &packet) {
355  packet.SetFilePos(::strlen("QSetWorkingDir:"));
356  std::string path;
357  packet.GetHexByteString(path);
358 
359  if (std::error_code ec = llvm::sys::fs::set_current_path(path))
360  return SendErrorResponse(ec.value());
361  return SendOKResponse();
362 }
363 
366  StringExtractorGDBRemote &packet) {
367  // NOTE: lldb should now be using qProcessInfo for process IDs. This path
368  // here
369  // should not be used. It is reporting process id instead of thread id. The
370  // correct answer doesn't seem to make much sense for lldb-platform.
371  // CONSIDER: flip to "unsupported".
373 
374  StreamString response;
375  response.Printf("QC%" PRIx64, pid);
376 
377  // If we launch a process and this GDB server is acting as a platform, then
378  // we need to clear the process launch state so we can start launching
379  // another process. In order to launch a process a bunch or packets need to
380  // be sent: environment packets, working directory, disable ASLR, and many
381  // more settings. When we launch a process we then need to know when to clear
382  // this information. Currently we are selecting the 'qC' packet as that
383  // packet which seems to make the most sense.
384  if (pid != LLDB_INVALID_PROCESS_ID) {
386  }
387 
388  return SendPacketNoLock(response.GetString());
389 }
390 
393  StringExtractorGDBRemote &packet) {
394  StructuredData::Array signal_array;
395 
396  lldb::UnixSignalsSP signals = UnixSignals::CreateForHost();
397  for (auto signo = signals->GetFirstSignalNumber();
399  signo = signals->GetNextSignalNumber(signo)) {
400  auto dictionary = std::make_shared<StructuredData::Dictionary>();
401 
402  dictionary->AddIntegerItem("signo", signo);
403  dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
404 
405  bool suppress, stop, notify;
406  signals->GetSignalInfo(signo, suppress, stop, notify);
407  dictionary->AddBooleanItem("suppress", suppress);
408  dictionary->AddBooleanItem("stop", stop);
409  dictionary->AddBooleanItem("notify", notify);
410 
411  signal_array.Push(dictionary);
412  }
413 
414  StreamString response;
415  signal_array.Dump(response);
416  return SendPacketNoLock(response.GetString());
417 }
418 
419 bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
420  lldb::pid_t pid) {
421  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
422  FreePortForProcess(pid);
423  m_spawned_pids.erase(pid);
424  return true;
425 }
426 
429  return Status("%s: no process command line specified to launch",
430  __FUNCTION__);
431 
432  // specify the process monitor if not already set. This should generally be
433  // what happens since we need to reap started processes.
436  std::bind(
437  &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
438  this, std::placeholders::_1),
439  false);
440 
442  if (!error.Success()) {
443  fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
445  return error;
446  }
447 
448  printf("Launched '%s' as process %" PRIu64 "...\n",
451 
452  // add to list of spawned processes. On an lldb-gdbserver, we would expect
453  // there to be only one.
454  const auto pid = m_process_launch_info.GetProcessID();
455  if (pid != LLDB_INVALID_PROCESS_ID) {
456  // add to spawned pids
457  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
458  m_spawned_pids.insert(pid);
459  }
460 
461  return error;
462 }
463 
465  m_port_map = port_map;
466 }
467 
469  if (m_port_map.empty())
470  return 0; // Bind to port zero and get a port, we didn't have any
471  // limitations
472 
473  for (auto &pair : m_port_map) {
474  if (pair.second == LLDB_INVALID_PROCESS_ID) {
475  pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
476  return pair.first;
477  }
478  }
479  return UINT16_MAX;
480 }
481 
484  PortMap::iterator pos = m_port_map.find(port);
485  if (pos != m_port_map.end()) {
486  pos->second = pid;
487  return true;
488  }
489  return false;
490 }
491 
493  PortMap::iterator pos = m_port_map.find(port);
494  if (pos != m_port_map.end()) {
495  pos->second = LLDB_INVALID_PROCESS_ID;
496  return true;
497  }
498  return false;
499 }
500 
502  if (!m_port_map.empty()) {
503  for (auto &pair : m_port_map) {
504  if (pair.second == pid) {
505  pair.second = LLDB_INVALID_PROCESS_ID;
506  return true;
507  }
508  }
509  }
510  return false;
511 }
512 
513 const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
514  static FileSpec g_domainsocket_dir;
515  static llvm::once_flag g_once_flag;
516 
517  llvm::call_once(g_once_flag, []() {
518  const char *domainsocket_dir_env =
519  ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
520  if (domainsocket_dir_env != nullptr)
521  g_domainsocket_dir = FileSpec(domainsocket_dir_env);
522  else
523  g_domainsocket_dir = HostInfo::GetProcessTempDir();
524  });
525 
526  return g_domainsocket_dir;
527 }
528 
529 FileSpec
530 GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
531  llvm::SmallString<128> socket_path;
532  llvm::SmallString<128> socket_name(
533  (llvm::StringRef(prefix) + ".%%%%%%").str());
534 
535  FileSpec socket_path_spec(GetDomainSocketDir());
536  socket_path_spec.AppendPathComponent(socket_name.c_str());
537 
538  llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
539  return FileSpec(socket_path.c_str());
540 }
541 
543  m_port_offset = port_offset;
544 }
545 
547  lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
549  m_pending_gdb_server.port = port;
550  m_pending_gdb_server.socket_name = socket_name;
551 }
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
A command line argument class.
Definition: Args.h:32
#define UNUSED_IF_ASSERT_DISABLED(x)
Definition: lldb-defines.h:134
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
Status LaunchGDBServer(const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid, uint16_t &port, std::string &socket_name)
static void CreateProcessInfoResponse_DebugServerStyle(const ProcessInstanceInfo &proc_info, StreamString &response)
Status StartDebugserverProcess(const char *url, Platform *platform, ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args, int pass_comm_fd)
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:92
static void Kill(lldb::pid_t pid, int signo)
#define LLDB_INVALID_SIGNAL_NUMBER
Definition: lldb-defines.h:95
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.cpp:254
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
Host::MonitorChildProcessCallback GetMonitorProcessCallback() const
A file utility class.
Definition: FileSpec.h:55
uint64_t GetU64(uint64_t fail_value, int base=0)
virtual std::string GetURI()=0
Returns a URI that describes this connection object.
size_t GetHexByteString(std::string &str)
#define LIBLLDB_LOG_PLATFORM
Definition: Logging.h:39
static lldb::UnixSignalsSP CreateForHost()
Definition: UnixSignals.cpp:54
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx. ...
Definition: Args.cpp:256
lldb_private::Connection * GetConnection()
int usleep(uint32_t useconds)
size_t PutStringAsRawHex8(llvm::StringRef s)
Definition: Stream.cpp:432
static Status LaunchProcess(ProcessLaunchInfo &launch_info)
Launch the process specified in launch_info.
void AppendPathComponent(llvm::StringRef component)
Definition: FileSpec.cpp:463
void Dump(Stream &s, bool pretty_print=true) const override
void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type, PacketHandler handler)
void SetFilePos(uint32_t idx)
bool GetNameColonValue(llvm::StringRef &name, llvm::StringRef &value)
void SetLaunchInSeparateProcessGroup(bool separate)
llvm::StringRef GetString() const
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
void SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string &socket_name)
void Write(Stream &s) override
Definition: JSON.cpp:151
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
bool Success() const
Test for success condition.
Definition: Status.cpp:287
const char * GetCString(bool denormalize=true) const
Definition: FileSpec.cpp:392
std::shared_ptr< JSONObject > SP
Definition: JSON.h:197
#define SIGKILL
size_t PutChar(char ch)
Definition: Stream.cpp:103
struct lldb_private::process_gdb_remote::GDBRemoteCommunicationServerPlatform::@76 m_pending_gdb_server
bool AppendObject(JSONValue::SP value)
Definition: JSON.cpp:179
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
Status LaunchProcess() override
Launch a process with the current launch settings.
Log * GetLogIfAnyCategoriesSet(uint32_t mask)
Definition: Logging.cpp:61
int PutEscapedBytes(const void *s, size_t src_len)
Output a block of data to the stream performing GDB-remote escaping.
Definition: SBAddress.h:15
void RegisterMemberFunctionHandler(StringExtractorGDBRemote::ServerPacketType packet_type, PacketResult(T::*handler)(StringExtractorGDBRemote &packet))
uint64_t pid_t
Definition: lldb-types.h:85
static bool Parse(llvm::StringRef uri, llvm::StringRef &scheme, llvm::StringRef &hostname, int &port, llvm::StringRef &path)
Definition: UriParser.cpp:19
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
void SetMonitorProcessCallback(const Host::MonitorChildProcessCallback &callback, bool monitor_signals)
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
size_t PutBytesAsRawHex8(const void *src, size_t src_len, lldb::ByteOrder src_byte_order=lldb::eByteOrderInvalid, lldb::ByteOrder dst_byte_order=lldb::eByteOrderInvalid)
Definition: Stream.cpp:406
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:68
An error handling class.
Definition: Status.h:44