1 //===-- GDBRemoteCommunicationServerPlatform.cpp ----------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "GDBRemoteCommunicationServerPlatform.h"
11
12 #include <errno.h>
13
14 // C Includes
15 // C++ Includes
16 #include <cstring>
17 #include <chrono>
18
19 // Other libraries and framework includes
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/StreamString.h"
22 #include "lldb/Core/StructuredData.h"
23 #include "lldb/Host/Config.h"
24 #include "lldb/Host/ConnectionFileDescriptor.h"
25 #include "lldb/Host/Host.h"
26 #include "lldb/Host/StringConvert.h"
27 #include "lldb/Target/FileAction.h"
28 #include "lldb/Target/Platform.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/UnixSignals.h"
31
32 // Project includes
33 #include "Utility/StringExtractorGDBRemote.h"
34 #include "Utility/UriParser.h"
35
36 using namespace lldb;
37 using namespace lldb_private;
38 using namespace lldb_private::process_gdb_remote;
39
40 //----------------------------------------------------------------------
41 // GDBRemoteCommunicationServerPlatform constructor
42 //----------------------------------------------------------------------
GDBRemoteCommunicationServerPlatform()43 GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() :
44 GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"),
45 m_platform_sp (Platform::GetHostPlatform ()),
46 m_port_map (),
47 m_port_offset(0)
48 {
49 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
50 &GDBRemoteCommunicationServerPlatform::Handle_qC);
51 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
52 &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
53 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
54 &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
55 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
56 &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
57 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
58 &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
59 RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
60 &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
61
62 RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
63 [this](StringExtractorGDBRemote packet,
64 Error &error,
65 bool &interrupt,
66 bool &quit)
67 {
68 error.SetErrorString("interrupt received");
69 interrupt = true;
70 return PacketResult::Success;
71 });
72 }
73
74 //----------------------------------------------------------------------
75 // Destructor
76 //----------------------------------------------------------------------
~GDBRemoteCommunicationServerPlatform()77 GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
78 {
79 }
80
81 GDBRemoteCommunication::PacketResult
Handle_qLaunchGDBServer(StringExtractorGDBRemote & packet)82 GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
83 {
84 #ifdef _WIN32
85 return SendErrorResponse(9);
86 #else
87 // Spawn a local debugserver as a platform so we can then attach or launch
88 // a process...
89
90 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
91 if (log)
92 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
93
94 // Sleep and wait a bit for debugserver to start to listen...
95 ConnectionFileDescriptor file_conn;
96 std::string hostname;
97 // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
98 // with the TMPDIR environment variable
99 packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
100 std::string name;
101 std::string value;
102 uint16_t port = UINT16_MAX;
103 while (packet.GetNameColonValue(name, value))
104 {
105 if (name.compare ("host") == 0)
106 hostname.swap(value);
107 else if (name.compare ("port") == 0)
108 port = StringConvert::ToUInt32(value.c_str(), 0, 0);
109 }
110 if (port == UINT16_MAX)
111 port = GetNextAvailablePort();
112
113 // Spawn a new thread to accept the port that gets bound after
114 // binding to port 0 (zero).
115
116 // ignore the hostname send from the remote end, just use the ip address
117 // that we're currently communicating with as the hostname
118
119 // Spawn a debugserver and try to get the port it listens to.
120 ProcessLaunchInfo debugserver_launch_info;
121 if (hostname.empty())
122 hostname = "127.0.0.1";
123 if (log)
124 log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
125
126 // Do not run in a new session so that it can not linger after the
127 // platform closes.
128 debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
129 debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
130
131 std::string platform_scheme;
132 std::string platform_ip;
133 int platform_port;
134 std::string platform_path;
135 bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
136 assert(ok);
137 Error error = StartDebugserverProcess (
138 platform_ip.c_str(),
139 port,
140 debugserver_launch_info,
141 port);
142
143 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
144
145
146 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
147 {
148 Mutex::Locker locker (m_spawned_pids_mutex);
149 m_spawned_pids.insert(debugserver_pid);
150 if (port > 0)
151 AssociatePortWithProcess(port, debugserver_pid);
152 }
153 else
154 {
155 if (port > 0)
156 FreePort (port);
157 }
158
159 if (error.Success())
160 {
161 if (log)
162 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
163
164 char response[256];
165 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
166 assert (response_len < (int)sizeof(response));
167 PacketResult packet_result = SendPacketNoLock (response, response_len);
168
169 if (packet_result != PacketResult::Success)
170 {
171 if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
172 ::kill (debugserver_pid, SIGINT);
173 }
174 return packet_result;
175 }
176 else
177 {
178 if (log)
179 log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
180 }
181 return SendErrorResponse (9);
182 #endif
183 }
184
185 GDBRemoteCommunication::PacketResult
Handle_qProcessInfo(StringExtractorGDBRemote & packet)186 GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
187 {
188 lldb::pid_t pid = m_process_launch_info.GetProcessID ();
189 m_process_launch_info.Clear ();
190
191 if (pid == LLDB_INVALID_PROCESS_ID)
192 return SendErrorResponse (1);
193
194 ProcessInstanceInfo proc_info;
195 if (!Host::GetProcessInfo (pid, proc_info))
196 return SendErrorResponse (1);
197
198 StreamString response;
199 CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
200 return SendPacketNoLock (response.GetData (), response.GetSize ());
201 }
202
203 GDBRemoteCommunication::PacketResult
Handle_qGetWorkingDir(StringExtractorGDBRemote & packet)204 GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
205 {
206 // If this packet is sent to a platform, then change the current working directory
207
208 char cwd[PATH_MAX];
209 if (getcwd(cwd, sizeof(cwd)) == NULL)
210 return SendErrorResponse(errno);
211
212 StreamString response;
213 response.PutBytesAsRawHex8(cwd, strlen(cwd));
214 return SendPacketNoLock(response.GetData(), response.GetSize());
215 }
216
217 GDBRemoteCommunication::PacketResult
Handle_QSetWorkingDir(StringExtractorGDBRemote & packet)218 GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
219 {
220 packet.SetFilePos (::strlen ("QSetWorkingDir:"));
221 std::string path;
222 packet.GetHexByteString (path);
223
224 // If this packet is sent to a platform, then change the current working directory
225 if (::chdir(path.c_str()) != 0)
226 return SendErrorResponse (errno);
227 return SendOKResponse ();
228 }
229
230 GDBRemoteCommunication::PacketResult
Handle_qC(StringExtractorGDBRemote & packet)231 GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet)
232 {
233 // NOTE: lldb should now be using qProcessInfo for process IDs. This path here
234 // should not be used. It is reporting process id instead of thread id. The
235 // correct answer doesn't seem to make much sense for lldb-platform.
236 // CONSIDER: flip to "unsupported".
237 lldb::pid_t pid = m_process_launch_info.GetProcessID();
238
239 StreamString response;
240 response.Printf("QC%" PRIx64, pid);
241
242 // If we launch a process and this GDB server is acting as a platform,
243 // then we need to clear the process launch state so we can start
244 // launching another process. In order to launch a process a bunch or
245 // packets need to be sent: environment packets, working directory,
246 // disable ASLR, and many more settings. When we launch a process we
247 // then need to know when to clear this information. Currently we are
248 // selecting the 'qC' packet as that packet which seems to make the most
249 // sense.
250 if (pid != LLDB_INVALID_PROCESS_ID)
251 {
252 m_process_launch_info.Clear();
253 }
254
255 return SendPacketNoLock (response.GetData(), response.GetSize());
256 }
257
258 GDBRemoteCommunication::PacketResult
Handle_jSignalsInfo(StringExtractorGDBRemote & packet)259 GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet)
260 {
261 StructuredData::Array signal_array;
262
263 const auto &signals = Host::GetUnixSignals();
264 for (auto signo = signals->GetFirstSignalNumber();
265 signo != LLDB_INVALID_SIGNAL_NUMBER;
266 signo = signals->GetNextSignalNumber(signo))
267 {
268 auto dictionary = std::make_shared<StructuredData::Dictionary>();
269
270 dictionary->AddIntegerItem("signo", signo);
271 dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
272
273 bool suppress, stop, notify;
274 signals->GetSignalInfo(signo, suppress, stop, notify);
275 dictionary->AddBooleanItem("suppress", suppress);
276 dictionary->AddBooleanItem("stop", stop);
277 dictionary->AddBooleanItem("notify", notify);
278
279 signal_array.Push(dictionary);
280 }
281
282 StreamString response;
283 signal_array.Dump(response);
284 return SendPacketNoLock(response.GetData(), response.GetSize());
285 }
286
287 bool
DebugserverProcessReaped(lldb::pid_t pid)288 GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
289 {
290 Mutex::Locker locker (m_spawned_pids_mutex);
291 FreePortForProcess(pid);
292 return m_spawned_pids.erase(pid) > 0;
293 }
294
295 bool
ReapDebugserverProcess(void * callback_baton,lldb::pid_t pid,bool exited,int signal,int status)296 GDBRemoteCommunicationServerPlatform::ReapDebugserverProcess (void *callback_baton,
297 lldb::pid_t pid,
298 bool exited,
299 int signal, // Zero for no signal
300 int status) // Exit value of process if signal is zero
301 {
302 GDBRemoteCommunicationServerPlatform *server = (GDBRemoteCommunicationServerPlatform *)callback_baton;
303 server->DebugserverProcessReaped (pid);
304 return true;
305 }
306
307 Error
LaunchProcess()308 GDBRemoteCommunicationServerPlatform::LaunchProcess ()
309 {
310 if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
311 return Error ("%s: no process command line specified to launch", __FUNCTION__);
312
313 // specify the process monitor if not already set. This should
314 // generally be what happens since we need to reap started
315 // processes.
316 if (!m_process_launch_info.GetMonitorProcessCallback ())
317 m_process_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
318
319 Error error = m_platform_sp->LaunchProcess (m_process_launch_info);
320 if (!error.Success ())
321 {
322 fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
323 return error;
324 }
325
326 printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
327
328 // add to list of spawned processes. On an lldb-gdbserver, we
329 // would expect there to be only one.
330 const auto pid = m_process_launch_info.GetProcessID();
331 if (pid != LLDB_INVALID_PROCESS_ID)
332 {
333 // add to spawned pids
334 Mutex::Locker locker (m_spawned_pids_mutex);
335 m_spawned_pids.insert(pid);
336 }
337
338 return error;
339 }
340
341 void
SetPortMap(PortMap && port_map)342 GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map)
343 {
344 m_port_map = port_map;
345 }
346
347 uint16_t
GetNextAvailablePort()348 GDBRemoteCommunicationServerPlatform::GetNextAvailablePort ()
349 {
350 if (m_port_map.empty())
351 return 0; // Bind to port zero and get a port, we didn't have any limitations
352
353 for (auto &pair : m_port_map)
354 {
355 if (pair.second == LLDB_INVALID_PROCESS_ID)
356 {
357 pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
358 return pair.first;
359 }
360 }
361 return UINT16_MAX;
362 }
363
364 bool
AssociatePortWithProcess(uint16_t port,lldb::pid_t pid)365 GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
366 {
367 PortMap::iterator pos = m_port_map.find(port);
368 if (pos != m_port_map.end())
369 {
370 pos->second = pid;
371 return true;
372 }
373 return false;
374 }
375
376 bool
FreePort(uint16_t port)377 GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port)
378 {
379 PortMap::iterator pos = m_port_map.find(port);
380 if (pos != m_port_map.end())
381 {
382 pos->second = LLDB_INVALID_PROCESS_ID;
383 return true;
384 }
385 return false;
386 }
387
388 bool
FreePortForProcess(lldb::pid_t pid)389 GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
390 {
391 if (!m_port_map.empty())
392 {
393 for (auto &pair : m_port_map)
394 {
395 if (pair.second == pid)
396 {
397 pair.second = LLDB_INVALID_PROCESS_ID;
398 return true;
399 }
400 }
401 }
402 return false;
403 }
404
405 void
SetPortOffset(uint16_t port_offset)406 GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset)
407 {
408 m_port_offset = port_offset;
409 }
410