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"
34#include "lldb/Utility/Log.h"
39
41
42using namespace lldb;
44using namespace lldb_private;
45
46// GDBRemoteCommunicationServerPlatform constructor
48 FileSpec debugserver_path, const Socket::SocketProtocol socket_protocol,
49 uint16_t gdbserver_port)
50 : GDBRemoteCommunicationServerCommon("lldb-platform.server"),
51 m_debugserver_path(std::move(debugserver_path)),
52 m_socket_protocol(socket_protocol), m_gdbserver_port(gdbserver_port) {
53
78
81 bool &interrupt, bool &quit) {
82 error = Status::FromErrorString("interrupt received");
83 interrupt = true;
85 });
86}
87
88// Destructor
90 default;
91
93 const lldb_private::Args &args, lldb::pid_t &pid, std::string &socket_name,
94 shared_fd_t fd) {
96
97 ProcessLaunchInfo debugserver_launch_info;
98 // Do not run in a new session so that it can not linger after the platform
99 // closes.
100 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
101 debugserver_launch_info.SetMonitorProcessCallback(
102 [](lldb::pid_t, int, int) {});
104 return Status::FromErrorString("debugserver does not exist");
105 debugserver_launch_info.SetExecutableFile(m_debugserver_path,
106 /*add_exe_file_as_first_arg=*/true);
107
109 if (fd == SharedSocket::kInvalidFD) {
111 // The server will be launched after accepting the connection.
112 return Status();
113 }
114
115 std::ostringstream url;
116 // debugserver does not accept the URL scheme prefix.
117#if !defined(__APPLE__)
119#endif
120 socket_name = GetDomainSocketPath("gdbserver").GetPath();
121 url << socket_name;
122 error = StartDebugserverProcess(url.str(), debugserver_launch_info, &args);
123 } else {
125 return Status::FromErrorString("protocol must be tcp");
126 error = StartDebugserverProcess(fd, debugserver_launch_info, &args);
127 }
128
129 if (error.Success()) {
130 pid = debugserver_launch_info.GetProcessID();
132 LLDB_LOGF(log,
133 "GDBRemoteCommunicationServerPlatform::%s() "
134 "debugserver launched successfully as pid %" PRIu64,
135 __FUNCTION__, pid);
136 } else {
137 LLDB_LOGF(log,
138 "GDBRemoteCommunicationServerPlatform::%s() "
139 "debugserver launch failed: %s",
140 __FUNCTION__, error.AsCString());
141 }
142 return error;
143}
144
147 StringExtractorGDBRemote &packet) {
148 // Spawn a local debugserver as a platform so we can then attach or launch a
149 // process...
150
152 LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
153 __FUNCTION__);
154
155 ConnectionFileDescriptor file_conn;
156 packet.SetFilePos(::strlen("qLaunchGDBServer;"));
157 llvm::StringRef name;
158 llvm::StringRef value;
159 std::optional<uint16_t> port;
160 while (packet.GetNameColonValue(name, value)) {
161 if (name == "port") {
162 // Make the Optional valid so we can use its value
163 port = 0;
164 value.getAsInteger(BASE_10, *port);
165 }
166 }
167
168 // Ignore client's hostname and the port.
169
170 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
171 std::string socket_name;
172 Status error = LaunchGDBServer(Args(), debugserver_pid, socket_name,
174 if (error.Fail())
175 return SendErrorResponse(9); // EBADF
176
177 StreamGDBRemote response;
178 uint16_t gdbserver_port = socket_name.empty() ? m_gdbserver_port : 0;
179 response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, gdbserver_port);
180 if (!socket_name.empty()) {
181 response.PutCString("socket_name:");
182 response.PutStringAsRawHex8(socket_name);
183 response.PutChar(';');
184 }
185
186 PacketResult packet_result = SendPacketNoLock(response.GetString());
187 if (packet_result != PacketResult::Success) {
188 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
189 Host::Kill(debugserver_pid, SIGINT);
190 }
191 return packet_result;
192}
193
196 StringExtractorGDBRemote &packet) {
197 namespace json = llvm::json;
198
200 return SendErrorResponse(4);
201
202 json::Object server{{"port", m_pending_gdb_server_socket_name->empty()
204 : 0}};
205
207 server.try_emplace("socket_name", *m_pending_gdb_server_socket_name);
208
209 json::Array server_list;
210 server_list.push_back(std::move(server));
211
212 StreamGDBRemote response;
213 response.AsRawOstream() << std::move(server_list);
214
215 StreamGDBRemote escaped_response;
216 escaped_response.PutEscapedBytes(response.GetString().data(),
217 response.GetSize());
218 return SendPacketNoLock(escaped_response.GetString());
219}
220
223 StringExtractorGDBRemote &packet) {
224 packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
225
227
228 // verify that we know anything about this pid.
229 if (!SpawnedProcessIsRunning(pid)) {
230 // not a pid we know about
231 return SendErrorResponse(10);
232 }
233
234 // go ahead and attempt to kill the spawned process
235 if (KillSpawnedProcess(pid))
236 return SendOKResponse();
237 else
238 return SendErrorResponse(11);
239}
240
242 assert(pid != LLDB_INVALID_PROCESS_ID);
243 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
244 m_spawned_pids.insert(pid);
245}
246
248 lldb::pid_t pid) {
249 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
250 return (m_spawned_pids.find(pid) != m_spawned_pids.end());
251}
252
254 // make sure we know about this process
255 if (!SpawnedProcessIsRunning(pid)) {
256 // it seems the process has been finished recently
257 return true;
258 }
259
260 // first try a SIGTERM (standard kill)
261 Host::Kill(pid, SIGTERM);
262
263 // check if that worked
264 for (size_t i = 0; i < 10; ++i) {
265 if (!SpawnedProcessIsRunning(pid)) {
266 // it is now killed
267 return true;
268 }
269 std::this_thread::sleep_for(std::chrono::milliseconds(10));
270 }
271
272 if (!SpawnedProcessIsRunning(pid))
273 return true;
274
275 // the launched process still lives. Now try killing it again, this time
276 // with an unblockable signal.
277 Host::Kill(pid, SIGKILL);
278
279 for (size_t i = 0; i < 10; ++i) {
280 if (!SpawnedProcessIsRunning(pid)) {
281 // it is now killed
282 return true;
283 }
284 std::this_thread::sleep_for(std::chrono::milliseconds(10));
285 }
286
287 // check one more time after the final sleep
288 return !SpawnedProcessIsRunning(pid);
289}
290
293 StringExtractorGDBRemote &packet) {
294 lldb::pid_t pid = m_process_launch_info.GetProcessID();
295 m_process_launch_info.Clear();
296
297 if (pid == LLDB_INVALID_PROCESS_ID)
298 return SendErrorResponse(1);
299
300 ProcessInstanceInfo proc_info;
301 if (!Host::GetProcessInfo(pid, proc_info))
302 return SendErrorResponse(1);
303
304 StreamString response;
306 return SendPacketNoLock(response.GetString());
307}
308
311 StringExtractorGDBRemote &packet) {
312 packet.SetFilePos(::strlen("qPathComplete:"));
313 const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1);
314 if (packet.GetChar() != ',')
315 return SendErrorResponse(85);
316 std::string path;
317 packet.GetHexByteString(path);
318
319 StringList matches;
321 if (only_dir)
322 CommandCompletions::DiskDirectories(path, matches, resolver);
323 else
324 CommandCompletions::DiskFiles(path, matches, resolver);
325
326 StreamString response;
327 response.PutChar('M');
328 llvm::StringRef separator;
329 std::sort(matches.begin(), matches.end());
330 for (const auto &match : matches) {
331 response << separator;
332 separator = ",";
333 // encode result strings into hex bytes to avoid unexpected error caused by
334 // special characters like '$'.
335 response.PutStringAsRawHex8(match.c_str());
336 }
337
338 return SendPacketNoLock(response.GetString());
339}
340
343 StringExtractorGDBRemote &packet) {
344
345 llvm::SmallString<64> cwd;
346 if (std::error_code ec = llvm::sys::fs::current_path(cwd))
347 return SendErrorResponse(ec.value());
348
349 StreamString response;
350 response.PutBytesAsRawHex8(cwd.data(), cwd.size());
351 return SendPacketNoLock(response.GetString());
352}
353
356 StringExtractorGDBRemote &packet) {
357 packet.SetFilePos(::strlen("QSetWorkingDir:"));
358 std::string path;
359 packet.GetHexByteString(path);
360
361 if (std::error_code ec = llvm::sys::fs::set_current_path(path))
362 return SendErrorResponse(ec.value());
363 return SendOKResponse();
364}
365
368 StringExtractorGDBRemote &packet) {
369 // NOTE: lldb should now be using qProcessInfo for process IDs. This path
370 // here
371 // should not be used. It is reporting process id instead of thread id. The
372 // correct answer doesn't seem to make much sense for lldb-platform.
373 // CONSIDER: flip to "unsupported".
374 lldb::pid_t pid = m_process_launch_info.GetProcessID();
375
376 StreamString response;
377 response.Printf("QC%" PRIx64, pid);
378
379 // If we launch a process and this GDB server is acting as a platform, then
380 // we need to clear the process launch state so we can start launching
381 // another process. In order to launch a process a bunch or packets need to
382 // be sent: environment packets, working directory, disable ASLR, and many
383 // more settings. When we launch a process we then need to know when to clear
384 // this information. Currently we are selecting the 'qC' packet as that
385 // packet which seems to make the most sense.
386 if (pid != LLDB_INVALID_PROCESS_ID) {
387 m_process_launch_info.Clear();
388 }
389
390 return SendPacketNoLock(response.GetString());
391}
392
394 lldb::pid_t pid) {
395 std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
396 m_spawned_pids.erase(pid);
397}
398
400 if (!m_process_launch_info.GetArguments().GetArgumentCount())
402 "%s: no process command line specified to launch", __FUNCTION__);
403
404 // specify the process monitor if not already set. This should generally be
405 // what happens since we need to reap started processes.
406 if (!m_process_launch_info.GetMonitorProcessCallback())
407 m_process_launch_info.SetMonitorProcessCallback(std::bind(
409 std::placeholders::_1));
410
412 if (!error.Success()) {
413 fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
414 m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
415 return error;
416 }
417
418 printf("Launched '%s' as process %" PRIu64 "...\n",
419 m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
420 m_process_launch_info.GetProcessID());
421
422 // add to list of spawned processes. On an lldb-gdbserver, we would expect
423 // there to be only one.
424 const auto pid = m_process_launch_info.GetProcessID();
426
427 return error;
428}
429
431 static FileSpec g_domainsocket_dir;
432 static llvm::once_flag g_once_flag;
433
434 llvm::call_once(g_once_flag, []() {
435 const char *domainsocket_dir_env =
436 ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
437 if (domainsocket_dir_env != nullptr)
438 g_domainsocket_dir = FileSpec(domainsocket_dir_env);
439 else
440 g_domainsocket_dir = HostInfo::GetProcessTempDir();
441 });
442
443 return g_domainsocket_dir;
444}
445
448 llvm::SmallString<128> socket_path;
449 llvm::SmallString<128> socket_name(
450 (llvm::StringRef(prefix) + ".%%%%%%").str());
451
452 FileSpec socket_path_spec(GetDomainSocketDir());
453 socket_path_spec.AppendPathComponent(socket_name.c_str());
454
455 llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(),
456 socket_path);
457 return FileSpec(socket_path.c_str());
458}
459
461 const std::string &socket_name) {
463}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition Log.h:389
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
static void DiskDirectories(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
static void DiskFiles(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
A file utility class.
Definition FileSpec.h:56
void AppendPathComponent(llvm::StringRef component)
Definition FileSpec.cpp:454
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
static FileSystem & Instance()
static Status LaunchProcess(ProcessLaunchInfo &launch_info)
Launch the process specified in launch_info.
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
Definition aix/Host.cpp:211
static void Kill(lldb::pid_t pid, int signo)
void SetExecutableFile(const FileSpec &exe_file, bool add_exe_file_as_first_arg)
lldb::pid_t GetProcessID() const
Definition ProcessInfo.h:66
void SetMonitorProcessCallback(Host::MonitorChildProcessCallback callback)
void SetLaunchInSeparateProcessGroup(bool separate)
static const shared_fd_t kInvalidFD
Definition Socket.h:50
static const char * FindSchemeByProtocol(const SocketProtocol protocol)
Definition Socket.cpp:151
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
int PutEscapedBytes(const void *s, size_t src_len)
Output a block of data to the stream performing GDB-remote escaping.
Definition GDBRemote.cpp:31
llvm::StringRef GetString() const
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition Stream.h:405
size_t PutStringAsRawHex8(llvm::StringRef s)
Definition Stream.cpp:418
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:63
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:391
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, lldb::pid_t &pid, std::string &socket_name, shared_fd_t fd)
Status LaunchProcess() override
Launch a process with the current launch settings.
GDBRemoteCommunicationServerPlatform(FileSpec debugserver_path, const Socket::SocketProtocol socket_protocol, uint16_t gdbserver_port)
void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type, PacketHandler handler)
static Status StartDebugserverProcess(std::variant< llvm::StringRef, shared_fd_t > comm, ProcessLaunchInfo &launch_info, const Args *inferior_args)
#define LLDB_INVALID_PROCESS_ID
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:338
NativeSocket shared_fd_t
Definition Socket.h:42
uint64_t pid_t
Definition lldb-types.h:84
#define SIGKILL