1dda28197Spatrick //===-- GDBRemoteCommunicationServerPlatform.cpp --------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "GDBRemoteCommunicationServerPlatform.h"
10061da546Spatrick
11be691f3bSpatrick #include <cerrno>
12061da546Spatrick
13061da546Spatrick #include <chrono>
14061da546Spatrick #include <csignal>
15061da546Spatrick #include <cstring>
16061da546Spatrick #include <mutex>
17*f6aab3d8Srobert #include <optional>
18061da546Spatrick #include <sstream>
19061da546Spatrick #include <thread>
20061da546Spatrick
21061da546Spatrick #include "llvm/Support/FileSystem.h"
22061da546Spatrick #include "llvm/Support/JSON.h"
23061da546Spatrick #include "llvm/Support/Threading.h"
24061da546Spatrick
25061da546Spatrick #include "lldb/Host/Config.h"
26061da546Spatrick #include "lldb/Host/ConnectionFileDescriptor.h"
27061da546Spatrick #include "lldb/Host/FileAction.h"
28061da546Spatrick #include "lldb/Host/Host.h"
29061da546Spatrick #include "lldb/Host/HostInfo.h"
30be691f3bSpatrick #include "lldb/Interpreter/CommandCompletions.h"
31061da546Spatrick #include "lldb/Target/Platform.h"
32061da546Spatrick #include "lldb/Target/UnixSignals.h"
33061da546Spatrick #include "lldb/Utility/GDBRemote.h"
34*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
35061da546Spatrick #include "lldb/Utility/Log.h"
36061da546Spatrick #include "lldb/Utility/StreamString.h"
37061da546Spatrick #include "lldb/Utility/StructuredData.h"
38be691f3bSpatrick #include "lldb/Utility/TildeExpressionResolver.h"
39061da546Spatrick #include "lldb/Utility/UriParser.h"
40061da546Spatrick
41061da546Spatrick #include "lldb/Utility/StringExtractorGDBRemote.h"
42061da546Spatrick
43061da546Spatrick using namespace lldb;
44061da546Spatrick using namespace lldb_private::process_gdb_remote;
45061da546Spatrick using namespace lldb_private;
46061da546Spatrick
PortMap(uint16_t min_port,uint16_t max_port)47be691f3bSpatrick GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
48be691f3bSpatrick uint16_t max_port) {
49be691f3bSpatrick for (; min_port < max_port; ++min_port)
50be691f3bSpatrick m_port_map[min_port] = LLDB_INVALID_PROCESS_ID;
51be691f3bSpatrick }
52be691f3bSpatrick
AllowPort(uint16_t port)53be691f3bSpatrick void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) {
54be691f3bSpatrick // Do not modify existing mappings
55be691f3bSpatrick m_port_map.insert({port, LLDB_INVALID_PROCESS_ID});
56be691f3bSpatrick }
57be691f3bSpatrick
58be691f3bSpatrick llvm::Expected<uint16_t>
GetNextAvailablePort()59be691f3bSpatrick GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() {
60be691f3bSpatrick if (m_port_map.empty())
61be691f3bSpatrick return 0; // Bind to port zero and get a port, we didn't have any
62be691f3bSpatrick // limitations
63be691f3bSpatrick
64be691f3bSpatrick for (auto &pair : m_port_map) {
65be691f3bSpatrick if (pair.second == LLDB_INVALID_PROCESS_ID) {
66be691f3bSpatrick pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
67be691f3bSpatrick return pair.first;
68be691f3bSpatrick }
69be691f3bSpatrick }
70be691f3bSpatrick return llvm::createStringError(llvm::inconvertibleErrorCode(),
71be691f3bSpatrick "No free port found in port map");
72be691f3bSpatrick }
73be691f3bSpatrick
AssociatePortWithProcess(uint16_t port,lldb::pid_t pid)74be691f3bSpatrick bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess(
75be691f3bSpatrick uint16_t port, lldb::pid_t pid) {
76be691f3bSpatrick auto pos = m_port_map.find(port);
77be691f3bSpatrick if (pos != m_port_map.end()) {
78be691f3bSpatrick pos->second = pid;
79be691f3bSpatrick return true;
80be691f3bSpatrick }
81be691f3bSpatrick return false;
82be691f3bSpatrick }
83be691f3bSpatrick
FreePort(uint16_t port)84be691f3bSpatrick bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) {
85be691f3bSpatrick std::map<uint16_t, lldb::pid_t>::iterator pos = m_port_map.find(port);
86be691f3bSpatrick if (pos != m_port_map.end()) {
87be691f3bSpatrick pos->second = LLDB_INVALID_PROCESS_ID;
88be691f3bSpatrick return true;
89be691f3bSpatrick }
90be691f3bSpatrick return false;
91be691f3bSpatrick }
92be691f3bSpatrick
FreePortForProcess(lldb::pid_t pid)93be691f3bSpatrick bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess(
94be691f3bSpatrick lldb::pid_t pid) {
95be691f3bSpatrick if (!m_port_map.empty()) {
96be691f3bSpatrick for (auto &pair : m_port_map) {
97be691f3bSpatrick if (pair.second == pid) {
98be691f3bSpatrick pair.second = LLDB_INVALID_PROCESS_ID;
99be691f3bSpatrick return true;
100be691f3bSpatrick }
101be691f3bSpatrick }
102be691f3bSpatrick }
103be691f3bSpatrick return false;
104be691f3bSpatrick }
105be691f3bSpatrick
empty() const106be691f3bSpatrick bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const {
107be691f3bSpatrick return m_port_map.empty();
108be691f3bSpatrick }
109be691f3bSpatrick
110061da546Spatrick // GDBRemoteCommunicationServerPlatform constructor
GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,const char * socket_scheme)111061da546Spatrick GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
112061da546Spatrick const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
113*f6aab3d8Srobert : GDBRemoteCommunicationServerCommon(),
114061da546Spatrick m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
115061da546Spatrick m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
116061da546Spatrick m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
117061da546Spatrick m_pending_gdb_server.port = 0;
118061da546Spatrick
119061da546Spatrick RegisterMemberFunctionHandler(
120061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qC,
121061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qC);
122061da546Spatrick RegisterMemberFunctionHandler(
123061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
124061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
125061da546Spatrick RegisterMemberFunctionHandler(
126061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
127061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
128061da546Spatrick RegisterMemberFunctionHandler(
129061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
130061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
131061da546Spatrick RegisterMemberFunctionHandler(
132061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
133061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
134061da546Spatrick RegisterMemberFunctionHandler(
135061da546Spatrick StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
136061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
137061da546Spatrick RegisterMemberFunctionHandler(
138be691f3bSpatrick StringExtractorGDBRemote::eServerPacketType_qPathComplete,
139be691f3bSpatrick &GDBRemoteCommunicationServerPlatform::Handle_qPathComplete);
140be691f3bSpatrick RegisterMemberFunctionHandler(
141061da546Spatrick StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
142061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
143061da546Spatrick RegisterMemberFunctionHandler(
144061da546Spatrick StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
145061da546Spatrick &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
146061da546Spatrick
147061da546Spatrick RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
148061da546Spatrick [](StringExtractorGDBRemote packet, Status &error,
149061da546Spatrick bool &interrupt, bool &quit) {
150061da546Spatrick error.SetErrorString("interrupt received");
151061da546Spatrick interrupt = true;
152061da546Spatrick return PacketResult::Success;
153061da546Spatrick });
154061da546Spatrick }
155061da546Spatrick
156061da546Spatrick // Destructor
157be691f3bSpatrick GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
158be691f3bSpatrick default;
159061da546Spatrick
LaunchGDBServer(const lldb_private::Args & args,std::string hostname,lldb::pid_t & pid,std::optional<uint16_t> & port,std::string & socket_name)160061da546Spatrick Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
161061da546Spatrick const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
162*f6aab3d8Srobert std::optional<uint16_t> &port, std::string &socket_name) {
163be691f3bSpatrick if (!port) {
164be691f3bSpatrick llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort();
165be691f3bSpatrick if (available_port)
166be691f3bSpatrick port = *available_port;
167be691f3bSpatrick else
168be691f3bSpatrick return Status(available_port.takeError());
169be691f3bSpatrick }
170061da546Spatrick
171061da546Spatrick // Spawn a new thread to accept the port that gets bound after binding to
172061da546Spatrick // port 0 (zero).
173061da546Spatrick
174061da546Spatrick // ignore the hostname send from the remote end, just use the ip address that
175061da546Spatrick // we're currently communicating with as the hostname
176061da546Spatrick
177061da546Spatrick // Spawn a debugserver and try to get the port it listens to.
178061da546Spatrick ProcessLaunchInfo debugserver_launch_info;
179061da546Spatrick if (hostname.empty())
180061da546Spatrick hostname = "127.0.0.1";
181061da546Spatrick
182*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Platform);
183061da546Spatrick LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(),
184be691f3bSpatrick *port);
185061da546Spatrick
186061da546Spatrick // Do not run in a new session so that it can not linger after the platform
187061da546Spatrick // closes.
188061da546Spatrick debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
189061da546Spatrick debugserver_launch_info.SetMonitorProcessCallback(
190061da546Spatrick std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
191*f6aab3d8Srobert this, std::placeholders::_1));
192061da546Spatrick
193061da546Spatrick std::ostringstream url;
194061da546Spatrick // debugserver does not accept the URL scheme prefix.
195061da546Spatrick #if !defined(__APPLE__)
196061da546Spatrick url << m_socket_scheme << "://";
197061da546Spatrick #endif
198*f6aab3d8Srobert uint16_t *port_ptr = &*port;
199061da546Spatrick if (m_socket_protocol == Socket::ProtocolTcp) {
200061da546Spatrick std::string platform_uri = GetConnection()->GetURI();
201*f6aab3d8Srobert std::optional<URI> parsed_uri = URI::Parse(platform_uri);
202*f6aab3d8Srobert url << '[' << parsed_uri->hostname.str() << "]:" << *port;
203061da546Spatrick } else {
204061da546Spatrick socket_name = GetDomainSocketPath("gdbserver").GetPath();
205061da546Spatrick url << socket_name;
206061da546Spatrick port_ptr = nullptr;
207061da546Spatrick }
208061da546Spatrick
209061da546Spatrick Status error = StartDebugserverProcess(
210061da546Spatrick url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
211061da546Spatrick
212061da546Spatrick pid = debugserver_launch_info.GetProcessID();
213061da546Spatrick if (pid != LLDB_INVALID_PROCESS_ID) {
214061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
215061da546Spatrick m_spawned_pids.insert(pid);
216be691f3bSpatrick if (*port > 0)
217be691f3bSpatrick m_port_map.AssociatePortWithProcess(*port, pid);
218061da546Spatrick } else {
219be691f3bSpatrick if (*port > 0)
220be691f3bSpatrick m_port_map.FreePort(*port);
221061da546Spatrick }
222061da546Spatrick return error;
223061da546Spatrick }
224061da546Spatrick
225061da546Spatrick GDBRemoteCommunication::PacketResult
Handle_qLaunchGDBServer(StringExtractorGDBRemote & packet)226061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
227061da546Spatrick StringExtractorGDBRemote &packet) {
228061da546Spatrick // Spawn a local debugserver as a platform so we can then attach or launch a
229061da546Spatrick // process...
230061da546Spatrick
231*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Platform);
232061da546Spatrick LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
233061da546Spatrick __FUNCTION__);
234061da546Spatrick
235061da546Spatrick ConnectionFileDescriptor file_conn;
236061da546Spatrick std::string hostname;
237061da546Spatrick packet.SetFilePos(::strlen("qLaunchGDBServer;"));
238061da546Spatrick llvm::StringRef name;
239061da546Spatrick llvm::StringRef value;
240*f6aab3d8Srobert std::optional<uint16_t> port;
241061da546Spatrick while (packet.GetNameColonValue(name, value)) {
242061da546Spatrick if (name.equals("host"))
243dda28197Spatrick hostname = std::string(value);
244be691f3bSpatrick else if (name.equals("port")) {
245be691f3bSpatrick // Make the Optional valid so we can use its value
246be691f3bSpatrick port = 0;
247*f6aab3d8Srobert value.getAsInteger(0, *port);
248be691f3bSpatrick }
249061da546Spatrick }
250061da546Spatrick
251061da546Spatrick lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
252061da546Spatrick std::string socket_name;
253061da546Spatrick Status error =
254061da546Spatrick LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
255061da546Spatrick if (error.Fail()) {
256061da546Spatrick LLDB_LOGF(log,
257061da546Spatrick "GDBRemoteCommunicationServerPlatform::%s() debugserver "
258061da546Spatrick "launch failed: %s",
259061da546Spatrick __FUNCTION__, error.AsCString());
260061da546Spatrick return SendErrorResponse(9);
261061da546Spatrick }
262061da546Spatrick
263061da546Spatrick LLDB_LOGF(log,
264061da546Spatrick "GDBRemoteCommunicationServerPlatform::%s() debugserver "
265061da546Spatrick "launched successfully as pid %" PRIu64,
266061da546Spatrick __FUNCTION__, debugserver_pid);
267061da546Spatrick
268061da546Spatrick StreamGDBRemote response;
269be691f3bSpatrick assert(port);
270061da546Spatrick response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
271be691f3bSpatrick *port + m_port_offset);
272061da546Spatrick if (!socket_name.empty()) {
273061da546Spatrick response.PutCString("socket_name:");
274061da546Spatrick response.PutStringAsRawHex8(socket_name);
275061da546Spatrick response.PutChar(';');
276061da546Spatrick }
277061da546Spatrick
278061da546Spatrick PacketResult packet_result = SendPacketNoLock(response.GetString());
279061da546Spatrick if (packet_result != PacketResult::Success) {
280061da546Spatrick if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
281061da546Spatrick Host::Kill(debugserver_pid, SIGINT);
282061da546Spatrick }
283061da546Spatrick return packet_result;
284061da546Spatrick }
285061da546Spatrick
286061da546Spatrick GDBRemoteCommunication::PacketResult
Handle_qQueryGDBServer(StringExtractorGDBRemote & packet)287061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
288061da546Spatrick StringExtractorGDBRemote &packet) {
289061da546Spatrick namespace json = llvm::json;
290061da546Spatrick
291061da546Spatrick if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
292061da546Spatrick return SendErrorResponse(4);
293061da546Spatrick
294061da546Spatrick json::Object server{{"port", m_pending_gdb_server.port}};
295061da546Spatrick
296061da546Spatrick if (!m_pending_gdb_server.socket_name.empty())
297061da546Spatrick server.try_emplace("socket_name", m_pending_gdb_server.socket_name);
298061da546Spatrick
299061da546Spatrick json::Array server_list;
300061da546Spatrick server_list.push_back(std::move(server));
301061da546Spatrick
302061da546Spatrick StreamGDBRemote response;
303061da546Spatrick response.AsRawOstream() << std::move(server_list);
304061da546Spatrick
305061da546Spatrick StreamGDBRemote escaped_response;
306061da546Spatrick escaped_response.PutEscapedBytes(response.GetString().data(),
307061da546Spatrick response.GetSize());
308061da546Spatrick return SendPacketNoLock(escaped_response.GetString());
309061da546Spatrick }
310061da546Spatrick
311061da546Spatrick GDBRemoteCommunication::PacketResult
Handle_qKillSpawnedProcess(StringExtractorGDBRemote & packet)312061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
313061da546Spatrick StringExtractorGDBRemote &packet) {
314061da546Spatrick packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
315061da546Spatrick
316061da546Spatrick lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
317061da546Spatrick
318061da546Spatrick // verify that we know anything about this pid. Scope for locker
319061da546Spatrick {
320061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
321061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
322061da546Spatrick // not a pid we know about
323061da546Spatrick return SendErrorResponse(10);
324061da546Spatrick }
325061da546Spatrick }
326061da546Spatrick
327061da546Spatrick // go ahead and attempt to kill the spawned process
328061da546Spatrick if (KillSpawnedProcess(pid))
329061da546Spatrick return SendOKResponse();
330061da546Spatrick else
331061da546Spatrick return SendErrorResponse(11);
332061da546Spatrick }
333061da546Spatrick
KillSpawnedProcess(lldb::pid_t pid)334061da546Spatrick bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
335061da546Spatrick // make sure we know about this process
336061da546Spatrick {
337061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
338061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end())
339061da546Spatrick return false;
340061da546Spatrick }
341061da546Spatrick
342061da546Spatrick // first try a SIGTERM (standard kill)
343061da546Spatrick Host::Kill(pid, SIGTERM);
344061da546Spatrick
345061da546Spatrick // check if that worked
346061da546Spatrick for (size_t i = 0; i < 10; ++i) {
347061da546Spatrick {
348061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
349061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
350061da546Spatrick // it is now killed
351061da546Spatrick return true;
352061da546Spatrick }
353061da546Spatrick }
354061da546Spatrick std::this_thread::sleep_for(std::chrono::milliseconds(10));
355061da546Spatrick }
356061da546Spatrick
357061da546Spatrick {
358061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
359061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end())
360061da546Spatrick return true;
361061da546Spatrick }
362061da546Spatrick
363061da546Spatrick // the launched process still lives. Now try killing it again, this time
364061da546Spatrick // with an unblockable signal.
365061da546Spatrick Host::Kill(pid, SIGKILL);
366061da546Spatrick
367061da546Spatrick for (size_t i = 0; i < 10; ++i) {
368061da546Spatrick {
369061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
370061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
371061da546Spatrick // it is now killed
372061da546Spatrick return true;
373061da546Spatrick }
374061da546Spatrick }
375061da546Spatrick std::this_thread::sleep_for(std::chrono::milliseconds(10));
376061da546Spatrick }
377061da546Spatrick
378061da546Spatrick // check one more time after the final sleep
379061da546Spatrick {
380061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
381061da546Spatrick if (m_spawned_pids.find(pid) == m_spawned_pids.end())
382061da546Spatrick return true;
383061da546Spatrick }
384061da546Spatrick
385061da546Spatrick // no luck - the process still lives
386061da546Spatrick return false;
387061da546Spatrick }
388061da546Spatrick
389061da546Spatrick GDBRemoteCommunication::PacketResult
Handle_qProcessInfo(StringExtractorGDBRemote & packet)390061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
391061da546Spatrick StringExtractorGDBRemote &packet) {
392061da546Spatrick lldb::pid_t pid = m_process_launch_info.GetProcessID();
393061da546Spatrick m_process_launch_info.Clear();
394061da546Spatrick
395061da546Spatrick if (pid == LLDB_INVALID_PROCESS_ID)
396061da546Spatrick return SendErrorResponse(1);
397061da546Spatrick
398061da546Spatrick ProcessInstanceInfo proc_info;
399061da546Spatrick if (!Host::GetProcessInfo(pid, proc_info))
400061da546Spatrick return SendErrorResponse(1);
401061da546Spatrick
402061da546Spatrick StreamString response;
403061da546Spatrick CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
404061da546Spatrick return SendPacketNoLock(response.GetString());
405061da546Spatrick }
406061da546Spatrick
407061da546Spatrick GDBRemoteCommunication::PacketResult
Handle_qPathComplete(StringExtractorGDBRemote & packet)408be691f3bSpatrick GDBRemoteCommunicationServerPlatform::Handle_qPathComplete(
409be691f3bSpatrick StringExtractorGDBRemote &packet) {
410be691f3bSpatrick packet.SetFilePos(::strlen("qPathComplete:"));
411be691f3bSpatrick const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1);
412be691f3bSpatrick if (packet.GetChar() != ',')
413be691f3bSpatrick return SendErrorResponse(85);
414be691f3bSpatrick std::string path;
415be691f3bSpatrick packet.GetHexByteString(path);
416be691f3bSpatrick
417be691f3bSpatrick StringList matches;
418be691f3bSpatrick StandardTildeExpressionResolver resolver;
419be691f3bSpatrick if (only_dir)
420be691f3bSpatrick CommandCompletions::DiskDirectories(path, matches, resolver);
421be691f3bSpatrick else
422be691f3bSpatrick CommandCompletions::DiskFiles(path, matches, resolver);
423be691f3bSpatrick
424be691f3bSpatrick StreamString response;
425be691f3bSpatrick response.PutChar('M');
426be691f3bSpatrick llvm::StringRef separator;
427be691f3bSpatrick std::sort(matches.begin(), matches.end());
428be691f3bSpatrick for (const auto &match : matches) {
429be691f3bSpatrick response << separator;
430be691f3bSpatrick separator = ",";
431be691f3bSpatrick // encode result strings into hex bytes to avoid unexpected error caused by
432be691f3bSpatrick // special characters like '$'.
433be691f3bSpatrick response.PutStringAsRawHex8(match.c_str());
434be691f3bSpatrick }
435be691f3bSpatrick
436be691f3bSpatrick return SendPacketNoLock(response.GetString());
437be691f3bSpatrick }
438be691f3bSpatrick
439be691f3bSpatrick GDBRemoteCommunication::PacketResult
Handle_qGetWorkingDir(StringExtractorGDBRemote & packet)440061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
441061da546Spatrick StringExtractorGDBRemote &packet) {
442061da546Spatrick
443061da546Spatrick llvm::SmallString<64> cwd;
444061da546Spatrick if (std::error_code ec = llvm::sys::fs::current_path(cwd))
445061da546Spatrick return SendErrorResponse(ec.value());
446061da546Spatrick
447061da546Spatrick StreamString response;
448061da546Spatrick response.PutBytesAsRawHex8(cwd.data(), cwd.size());
449061da546Spatrick return SendPacketNoLock(response.GetString());
450061da546Spatrick }
451061da546Spatrick
452061da546Spatrick GDBRemoteCommunication::PacketResult
Handle_QSetWorkingDir(StringExtractorGDBRemote & packet)453061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
454061da546Spatrick StringExtractorGDBRemote &packet) {
455061da546Spatrick packet.SetFilePos(::strlen("QSetWorkingDir:"));
456061da546Spatrick std::string path;
457061da546Spatrick packet.GetHexByteString(path);
458061da546Spatrick
459061da546Spatrick if (std::error_code ec = llvm::sys::fs::set_current_path(path))
460061da546Spatrick return SendErrorResponse(ec.value());
461061da546Spatrick return SendOKResponse();
462061da546Spatrick }
463061da546Spatrick
464061da546Spatrick GDBRemoteCommunication::PacketResult
Handle_qC(StringExtractorGDBRemote & packet)465061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_qC(
466061da546Spatrick StringExtractorGDBRemote &packet) {
467061da546Spatrick // NOTE: lldb should now be using qProcessInfo for process IDs. This path
468061da546Spatrick // here
469061da546Spatrick // should not be used. It is reporting process id instead of thread id. The
470061da546Spatrick // correct answer doesn't seem to make much sense for lldb-platform.
471061da546Spatrick // CONSIDER: flip to "unsupported".
472061da546Spatrick lldb::pid_t pid = m_process_launch_info.GetProcessID();
473061da546Spatrick
474061da546Spatrick StreamString response;
475061da546Spatrick response.Printf("QC%" PRIx64, pid);
476061da546Spatrick
477061da546Spatrick // If we launch a process and this GDB server is acting as a platform, then
478061da546Spatrick // we need to clear the process launch state so we can start launching
479061da546Spatrick // another process. In order to launch a process a bunch or packets need to
480061da546Spatrick // be sent: environment packets, working directory, disable ASLR, and many
481061da546Spatrick // more settings. When we launch a process we then need to know when to clear
482061da546Spatrick // this information. Currently we are selecting the 'qC' packet as that
483061da546Spatrick // packet which seems to make the most sense.
484061da546Spatrick if (pid != LLDB_INVALID_PROCESS_ID) {
485061da546Spatrick m_process_launch_info.Clear();
486061da546Spatrick }
487061da546Spatrick
488061da546Spatrick return SendPacketNoLock(response.GetString());
489061da546Spatrick }
490061da546Spatrick
491061da546Spatrick GDBRemoteCommunication::PacketResult
Handle_jSignalsInfo(StringExtractorGDBRemote & packet)492061da546Spatrick GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
493061da546Spatrick StringExtractorGDBRemote &packet) {
494061da546Spatrick StructuredData::Array signal_array;
495061da546Spatrick
496061da546Spatrick lldb::UnixSignalsSP signals = UnixSignals::CreateForHost();
497061da546Spatrick for (auto signo = signals->GetFirstSignalNumber();
498061da546Spatrick signo != LLDB_INVALID_SIGNAL_NUMBER;
499061da546Spatrick signo = signals->GetNextSignalNumber(signo)) {
500061da546Spatrick auto dictionary = std::make_shared<StructuredData::Dictionary>();
501061da546Spatrick
502061da546Spatrick dictionary->AddIntegerItem("signo", signo);
503061da546Spatrick dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
504061da546Spatrick
505061da546Spatrick bool suppress, stop, notify;
506061da546Spatrick signals->GetSignalInfo(signo, suppress, stop, notify);
507061da546Spatrick dictionary->AddBooleanItem("suppress", suppress);
508061da546Spatrick dictionary->AddBooleanItem("stop", stop);
509061da546Spatrick dictionary->AddBooleanItem("notify", notify);
510061da546Spatrick
511061da546Spatrick signal_array.Push(dictionary);
512061da546Spatrick }
513061da546Spatrick
514061da546Spatrick StreamString response;
515061da546Spatrick signal_array.Dump(response);
516061da546Spatrick return SendPacketNoLock(response.GetString());
517061da546Spatrick }
518061da546Spatrick
DebugserverProcessReaped(lldb::pid_t pid)519*f6aab3d8Srobert void GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
520061da546Spatrick lldb::pid_t pid) {
521061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
522be691f3bSpatrick m_port_map.FreePortForProcess(pid);
523061da546Spatrick m_spawned_pids.erase(pid);
524061da546Spatrick }
525061da546Spatrick
LaunchProcess()526061da546Spatrick Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
527061da546Spatrick if (!m_process_launch_info.GetArguments().GetArgumentCount())
528061da546Spatrick return Status("%s: no process command line specified to launch",
529061da546Spatrick __FUNCTION__);
530061da546Spatrick
531061da546Spatrick // specify the process monitor if not already set. This should generally be
532061da546Spatrick // what happens since we need to reap started processes.
533061da546Spatrick if (!m_process_launch_info.GetMonitorProcessCallback())
534*f6aab3d8Srobert m_process_launch_info.SetMonitorProcessCallback(std::bind(
535*f6aab3d8Srobert &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this,
536*f6aab3d8Srobert std::placeholders::_1));
537061da546Spatrick
538061da546Spatrick Status error = Host::LaunchProcess(m_process_launch_info);
539061da546Spatrick if (!error.Success()) {
540061da546Spatrick fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
541061da546Spatrick m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
542061da546Spatrick return error;
543061da546Spatrick }
544061da546Spatrick
545061da546Spatrick printf("Launched '%s' as process %" PRIu64 "...\n",
546061da546Spatrick m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
547061da546Spatrick m_process_launch_info.GetProcessID());
548061da546Spatrick
549061da546Spatrick // add to list of spawned processes. On an lldb-gdbserver, we would expect
550061da546Spatrick // there to be only one.
551061da546Spatrick const auto pid = m_process_launch_info.GetProcessID();
552061da546Spatrick if (pid != LLDB_INVALID_PROCESS_ID) {
553061da546Spatrick // add to spawned pids
554061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
555061da546Spatrick m_spawned_pids.insert(pid);
556061da546Spatrick }
557061da546Spatrick
558061da546Spatrick return error;
559061da546Spatrick }
560061da546Spatrick
SetPortMap(PortMap && port_map)561061da546Spatrick void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
562061da546Spatrick m_port_map = port_map;
563061da546Spatrick }
564061da546Spatrick
GetDomainSocketDir()565061da546Spatrick const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
566061da546Spatrick static FileSpec g_domainsocket_dir;
567061da546Spatrick static llvm::once_flag g_once_flag;
568061da546Spatrick
569061da546Spatrick llvm::call_once(g_once_flag, []() {
570061da546Spatrick const char *domainsocket_dir_env =
571061da546Spatrick ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
572061da546Spatrick if (domainsocket_dir_env != nullptr)
573061da546Spatrick g_domainsocket_dir = FileSpec(domainsocket_dir_env);
574061da546Spatrick else
575061da546Spatrick g_domainsocket_dir = HostInfo::GetProcessTempDir();
576061da546Spatrick });
577061da546Spatrick
578061da546Spatrick return g_domainsocket_dir;
579061da546Spatrick }
580061da546Spatrick
581061da546Spatrick FileSpec
GetDomainSocketPath(const char * prefix)582061da546Spatrick GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
583061da546Spatrick llvm::SmallString<128> socket_path;
584061da546Spatrick llvm::SmallString<128> socket_name(
585061da546Spatrick (llvm::StringRef(prefix) + ".%%%%%%").str());
586061da546Spatrick
587061da546Spatrick FileSpec socket_path_spec(GetDomainSocketDir());
588061da546Spatrick socket_path_spec.AppendPathComponent(socket_name.c_str());
589061da546Spatrick
590*f6aab3d8Srobert llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(),
591*f6aab3d8Srobert socket_path);
592061da546Spatrick return FileSpec(socket_path.c_str());
593061da546Spatrick }
594061da546Spatrick
SetPortOffset(uint16_t port_offset)595061da546Spatrick void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
596061da546Spatrick m_port_offset = port_offset;
597061da546Spatrick }
598061da546Spatrick
SetPendingGdbServer(lldb::pid_t pid,uint16_t port,const std::string & socket_name)599061da546Spatrick void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
600061da546Spatrick lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
601061da546Spatrick m_pending_gdb_server.pid = pid;
602061da546Spatrick m_pending_gdb_server.port = port;
603061da546Spatrick m_pending_gdb_server.socket_name = socket_name;
604061da546Spatrick }
605