LLDB mainline
GDBRemoteCommunicationServerPlatform.cpp
Go to the documentation of this file.
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
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"
28#include "lldb/Host/Host.h"
29#include "lldb/Host/HostInfo.h"
35#include "lldb/Utility/Log.h"
40
42
43using namespace lldb;
45using namespace lldb_private;
46
48 uint16_t max_port) {
49 assert(min_port);
50 for (; min_port < max_port; ++min_port)
52}
53
55 assert(port);
56 // Do not modify existing mappings
58}
59
60llvm::Expected<uint16_t>
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) {
69 return pair.first;
70 }
71 }
72 return llvm::createStringError(llvm::inconvertibleErrorCode(),
73 "No free port found in port map");
74}
75
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
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
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
109 return m_port_map.empty();
110}
111
112// GDBRemoteCommunicationServerPlatform constructor
114 const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
116 m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
119 m_pending_gdb_server.port = 0;
120
148
151 bool &interrupt, bool &quit) {
152 error.SetErrorString("interrupt received");
153 interrupt = true;
155 });
156}
157
158// Destructor
160 default;
161
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(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
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(
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;
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
212 url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
213
214 pid = debugserver_launch_info.GetProcessID();
216 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
217 m_spawned_pids.insert(pid);
218 if (*port > 0)
220 } else {
221 if (*port > 0)
223 }
224 return error;
225}
226
229 StringExtractorGDBRemote &packet) {
230 // Spawn a local debugserver as a platform so we can then attach or launch a
231 // process...
232
234 LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
235 __FUNCTION__);
236
237 ConnectionFileDescriptor file_conn;
238 std::string hostname;
239 packet.SetFilePos(::strlen("qLaunchGDBServer;"));
240 llvm::StringRef name;
241 llvm::StringRef value;
242 std::optional<uint16_t> port;
243 while (packet.GetNameColonValue(name, value)) {
244 if (name == "host")
245 hostname = std::string(value);
246 else if (name == "port") {
247 // Make the Optional valid so we can use its value
248 port = 0;
249 value.getAsInteger(0, *port);
250 }
251 }
252
253 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
254 std::string socket_name;
255 Status error =
256 LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
257 if (error.Fail()) {
258 LLDB_LOGF(log,
259 "GDBRemoteCommunicationServerPlatform::%s() debugserver "
260 "launch failed: %s",
261 __FUNCTION__, error.AsCString());
262 return SendErrorResponse(9);
263 }
264
265 LLDB_LOGF(log,
266 "GDBRemoteCommunicationServerPlatform::%s() debugserver "
267 "launched successfully as pid %" PRIu64,
268 __FUNCTION__, debugserver_pid);
269
270 StreamGDBRemote response;
271 assert(port);
272 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
274 if (!socket_name.empty()) {
275 response.PutCString("socket_name:");
277 response.PutChar(';');
278 }
279
280 PacketResult packet_result = SendPacketNoLock(response.GetString());
281 if (packet_result != PacketResult::Success) {
282 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
283 Host::Kill(debugserver_pid, SIGINT);
284 }
285 return packet_result;
286}
287
290 StringExtractorGDBRemote &packet) {
291 namespace json = llvm::json;
292
294 return SendErrorResponse(4);
295
296 json::Object server{{"port", m_pending_gdb_server.port}};
297
298 if (!m_pending_gdb_server.socket_name.empty())
299 server.try_emplace("socket_name", m_pending_gdb_server.socket_name);
300
301 json::Array server_list;
302 server_list.push_back(std::move(server));
303
304 StreamGDBRemote response;
305 response.AsRawOstream() << std::move(server_list);
306
307 StreamGDBRemote escaped_response;
308 escaped_response.PutEscapedBytes(response.GetString().data(),
309 response.GetSize());
310 return SendPacketNoLock(escaped_response.GetString());
311}
312
315 StringExtractorGDBRemote &packet) {
316 packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
317
319
320 // verify that we know anything about this pid. Scope for locker
321 {
322 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
323 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
324 // not a pid we know about
325 return SendErrorResponse(10);
326 }
327 }
328
329 // go ahead and attempt to kill the spawned process
331 return SendOKResponse();
332 else
333 return SendErrorResponse(11);
334}
335
337 // make sure we know about this process
338 {
339 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
340 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
341 return false;
342 }
343
344 // first try a SIGTERM (standard kill)
345 Host::Kill(pid, SIGTERM);
346
347 // check if that worked
348 for (size_t i = 0; i < 10; ++i) {
349 {
350 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
351 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
352 // it is now killed
353 return true;
354 }
355 }
356 std::this_thread::sleep_for(std::chrono::milliseconds(10));
357 }
358
359 {
360 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
361 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
362 return true;
363 }
364
365 // the launched process still lives. Now try killing it again, this time
366 // with an unblockable signal.
368
369 for (size_t i = 0; i < 10; ++i) {
370 {
371 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
372 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
373 // it is now killed
374 return true;
375 }
376 }
377 std::this_thread::sleep_for(std::chrono::milliseconds(10));
378 }
379
380 // check one more time after the final sleep
381 {
382 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
383 if (m_spawned_pids.find(pid) == m_spawned_pids.end())
384 return true;
385 }
386
387 // no luck - the process still lives
388 return false;
389}
390
393 StringExtractorGDBRemote &packet) {
396
398 return SendErrorResponse(1);
399
400 ProcessInstanceInfo proc_info;
401 if (!Host::GetProcessInfo(pid, proc_info))
402 return SendErrorResponse(1);
403
404 StreamString response;
406 return SendPacketNoLock(response.GetString());
407}
408
411 StringExtractorGDBRemote &packet) {
412 packet.SetFilePos(::strlen("qPathComplete:"));
413 const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1);
414 if (packet.GetChar() != ',')
415 return SendErrorResponse(85);
416 std::string path;
417 packet.GetHexByteString(path);
418
419 StringList matches;
421 if (only_dir)
422 CommandCompletions::DiskDirectories(path, matches, resolver);
423 else
424 CommandCompletions::DiskFiles(path, matches, resolver);
425
426 StreamString response;
427 response.PutChar('M');
428 llvm::StringRef separator;
429 std::sort(matches.begin(), matches.end());
430 for (const auto &match : matches) {
431 response << separator;
432 separator = ",";
433 // encode result strings into hex bytes to avoid unexpected error caused by
434 // special characters like '$'.
435 response.PutStringAsRawHex8(match.c_str());
436 }
437
438 return SendPacketNoLock(response.GetString());
439}
440
443 StringExtractorGDBRemote &packet) {
444
445 llvm::SmallString<64> cwd;
446 if (std::error_code ec = llvm::sys::fs::current_path(cwd))
447 return SendErrorResponse(ec.value());
448
449 StreamString response;
450 response.PutBytesAsRawHex8(cwd.data(), cwd.size());
451 return SendPacketNoLock(response.GetString());
452}
453
456 StringExtractorGDBRemote &packet) {
457 packet.SetFilePos(::strlen("QSetWorkingDir:"));
458 std::string path;
459 packet.GetHexByteString(path);
460
461 if (std::error_code ec = llvm::sys::fs::set_current_path(path))
462 return SendErrorResponse(ec.value());
463 return SendOKResponse();
464}
465
468 StringExtractorGDBRemote &packet) {
469 // NOTE: lldb should now be using qProcessInfo for process IDs. This path
470 // here
471 // should not be used. It is reporting process id instead of thread id. The
472 // correct answer doesn't seem to make much sense for lldb-platform.
473 // CONSIDER: flip to "unsupported".
475
476 StreamString response;
477 response.Printf("QC%" PRIx64, pid);
478
479 // If we launch a process and this GDB server is acting as a platform, then
480 // we need to clear the process launch state so we can start launching
481 // another process. In order to launch a process a bunch or packets need to
482 // be sent: environment packets, working directory, disable ASLR, and many
483 // more settings. When we launch a process we then need to know when to clear
484 // this information. Currently we are selecting the 'qC' packet as that
485 // packet which seems to make the most sense.
488 }
489
490 return SendPacketNoLock(response.GetString());
491}
492
495 StringExtractorGDBRemote &packet) {
496 StructuredData::Array signal_array;
497
499 for (auto signo = signals->GetFirstSignalNumber();
501 signo = signals->GetNextSignalNumber(signo)) {
502 auto dictionary = std::make_shared<StructuredData::Dictionary>();
503
504 dictionary->AddIntegerItem("signo", signo);
505 dictionary->AddStringItem("name", signals->GetSignalAsStringRef(signo));
506
507 bool suppress, stop, notify;
508 signals->GetSignalInfo(signo, suppress, stop, notify);
509 dictionary->AddBooleanItem("suppress", suppress);
510 dictionary->AddBooleanItem("stop", stop);
511 dictionary->AddBooleanItem("notify", notify);
512
513 signal_array.Push(dictionary);
514 }
515
516 StreamString response;
517 signal_array.Dump(response);
518 return SendPacketNoLock(response.GetString());
519}
520
522 lldb::pid_t pid) {
523 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
525 m_spawned_pids.erase(pid);
526}
527
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.
538 std::placeholders::_1));
539
541 if (!error.Success()) {
542 fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
544 return error;
545 }
546
547 printf("Launched '%s' as process %" PRIu64 "...\n",
550
551 // add to list of spawned processes. On an lldb-gdbserver, we would expect
552 // there to be only one.
555 // add to spawned pids
556 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
557 m_spawned_pids.insert(pid);
558 }
559
560 return error;
561}
562
564 m_port_map = std::move(port_map);
565}
566
568 static FileSpec g_domainsocket_dir;
569 static llvm::once_flag g_once_flag;
570
571 llvm::call_once(g_once_flag, []() {
572 const char *domainsocket_dir_env =
573 ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
574 if (domainsocket_dir_env != nullptr)
575 g_domainsocket_dir = FileSpec(domainsocket_dir_env);
576 else
577 g_domainsocket_dir = HostInfo::GetProcessTempDir();
578 });
579
580 return g_domainsocket_dir;
581}
582
585 llvm::SmallString<128> socket_path;
586 llvm::SmallString<128> socket_name(
587 (llvm::StringRef(prefix) + ".%%%%%%").str());
588
589 FileSpec socket_path_spec(GetDomainSocketDir());
590 socket_path_spec.AppendPathComponent(socket_name.c_str());
591
592 llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(),
593 socket_path);
594 return FileSpec(socket_path.c_str());
595}
596
598 m_port_offset = port_offset;
599}
600
602 lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
605 m_pending_gdb_server.socket_name = socket_name;
606}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition: Log.h:366
void SetFilePos(uint32_t idx)
uint32_t GetHexMaxU32(bool little_endian, uint32_t fail_value)
bool GetNameColonValue(llvm::StringRef &name, llvm::StringRef &value)
uint64_t GetU64(uint64_t fail_value, int base=0)
size_t GetHexByteString(std::string &str)
char GetChar(char fail_value='\0')
A command line argument class.
Definition: Args.h:33
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:116
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:263
static void DiskDirectories(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void DiskFiles(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
lldb_private::Connection * GetConnection()
Definition: Communication.h:87
virtual std::string GetURI()=0
Returns a URI that describes this connection object.
A file utility class.
Definition: FileSpec.h:56
void AppendPathComponent(llvm::StringRef component)
Definition: FileSpec.cpp:447
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:367
static Status LaunchProcess(ProcessLaunchInfo &launch_info)
Launch the process specified in launch_info.
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
static void Kill(lldb::pid_t pid, int signo)
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:68
const Host::MonitorChildProcessCallback & GetMonitorProcessCallback() const
void SetMonitorProcessCallback(Host::MonitorChildProcessCallback callback)
void SetLaunchInSeparateProcessGroup(bool separate)
An error handling class.
Definition: Status.h:44
int PutEscapedBytes(const void *s, size_t src_len)
Output a block of data to the stream performing GDB-remote escaping.
Definition: GDBRemote.cpp:28
llvm::StringRef GetString() const
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition: Stream.h:401
size_t PutStringAsRawHex8(llvm::StringRef s)
Definition: Stream.cpp:410
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:65
size_t PutChar(char ch)
Definition: Stream.cpp:131
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:383
void Push(const ObjectSP &item)
void Dump(lldb_private::Stream &s, bool pretty_print=true) const
static lldb::UnixSignalsSP CreateForHost()
Definition: UnixSignals.cpp:44
void RegisterMemberFunctionHandler(StringExtractorGDBRemote::ServerPacketType packet_type, PacketResult(T::*handler)(StringExtractorGDBRemote &packet))
static void CreateProcessInfoResponse_DebugServerStyle(const ProcessInstanceInfo &proc_info, StreamString &response)
Status LaunchGDBServer(const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid, std::optional< uint16_t > &port, std::string &socket_name)
void SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string &socket_name)
struct lldb_private::process_gdb_remote::GDBRemoteCommunicationServerPlatform::@76 m_pending_gdb_server
GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
Status LaunchProcess() override
Launch a process with the current launch settings.
void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type, PacketHandler handler)
Status StartDebugserverProcess(const char *url, Platform *platform, ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args, int pass_comm_fd)
#define LLDB_INVALID_SIGNAL_NUMBER
Definition: lldb-defines.h:92
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:89
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:331
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::UnixSignals > UnixSignalsSP
Definition: lldb-forward.h:475
uint64_t pid_t
Definition: lldb-types.h:83
static std::optional< URI > Parse(llvm::StringRef uri)
Definition: UriParser.cpp:28
#define SIGKILL