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 //----------------------------------------------------------------------
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 //----------------------------------------------------------------------
77 GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
78 {
79 }
80 
81 GDBRemoteCommunication::PacketResult
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     UNUSED_IF_ASSERT_DISABLED(ok);
137     assert(ok);
138     Error error = StartDebugserverProcess (
139                                      platform_ip.c_str(),
140                                      port,
141                                      debugserver_launch_info,
142                                      port);
143 
144     lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
145 
146 
147     if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
148     {
149         Mutex::Locker locker (m_spawned_pids_mutex);
150         m_spawned_pids.insert(debugserver_pid);
151         if (port > 0)
152             AssociatePortWithProcess(port, debugserver_pid);
153     }
154     else
155     {
156         if (port > 0)
157             FreePort (port);
158     }
159 
160     if (error.Success())
161     {
162         if (log)
163             log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
164 
165         char response[256];
166         const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
167         assert (response_len < (int)sizeof(response));
168         PacketResult packet_result = SendPacketNoLock (response, response_len);
169 
170         if (packet_result != PacketResult::Success)
171         {
172             if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
173                 ::kill (debugserver_pid, SIGINT);
174         }
175         return packet_result;
176     }
177     else
178     {
179         if (log)
180             log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
181     }
182     return SendErrorResponse (9);
183 #endif
184 }
185 
186 GDBRemoteCommunication::PacketResult
187 GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
188 {
189     lldb::pid_t pid = m_process_launch_info.GetProcessID ();
190     m_process_launch_info.Clear ();
191 
192     if (pid == LLDB_INVALID_PROCESS_ID)
193         return SendErrorResponse (1);
194 
195     ProcessInstanceInfo proc_info;
196     if (!Host::GetProcessInfo (pid, proc_info))
197         return SendErrorResponse (1);
198 
199     StreamString response;
200     CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
201     return SendPacketNoLock (response.GetData (), response.GetSize ());
202 }
203 
204 GDBRemoteCommunication::PacketResult
205 GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
206 {
207     // If this packet is sent to a platform, then change the current working directory
208 
209     char cwd[PATH_MAX];
210     if (getcwd(cwd, sizeof(cwd)) == NULL)
211         return SendErrorResponse(errno);
212 
213     StreamString response;
214     response.PutBytesAsRawHex8(cwd, strlen(cwd));
215     return SendPacketNoLock(response.GetData(), response.GetSize());
216 }
217 
218 GDBRemoteCommunication::PacketResult
219 GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
220 {
221     packet.SetFilePos (::strlen ("QSetWorkingDir:"));
222     std::string path;
223     packet.GetHexByteString (path);
224 
225     // If this packet is sent to a platform, then change the current working directory
226     if (::chdir(path.c_str()) != 0)
227         return SendErrorResponse (errno);
228     return SendOKResponse ();
229 }
230 
231 GDBRemoteCommunication::PacketResult
232 GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet)
233 {
234     // NOTE: lldb should now be using qProcessInfo for process IDs.  This path here
235     // should not be used.  It is reporting process id instead of thread id.  The
236     // correct answer doesn't seem to make much sense for lldb-platform.
237     // CONSIDER: flip to "unsupported".
238     lldb::pid_t pid = m_process_launch_info.GetProcessID();
239 
240     StreamString response;
241     response.Printf("QC%" PRIx64, pid);
242 
243     // If we launch a process and this GDB server is acting as a platform,
244     // then we need to clear the process launch state so we can start
245     // launching another process. In order to launch a process a bunch or
246     // packets need to be sent: environment packets, working directory,
247     // disable ASLR, and many more settings. When we launch a process we
248     // then need to know when to clear this information. Currently we are
249     // selecting the 'qC' packet as that packet which seems to make the most
250     // sense.
251     if (pid != LLDB_INVALID_PROCESS_ID)
252     {
253         m_process_launch_info.Clear();
254     }
255 
256     return SendPacketNoLock (response.GetData(), response.GetSize());
257 }
258 
259 GDBRemoteCommunication::PacketResult
260 GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet)
261 {
262     StructuredData::Array signal_array;
263 
264     const auto &signals = Host::GetUnixSignals();
265     for (auto signo = signals->GetFirstSignalNumber();
266          signo != LLDB_INVALID_SIGNAL_NUMBER;
267          signo = signals->GetNextSignalNumber(signo))
268     {
269         auto dictionary = std::make_shared<StructuredData::Dictionary>();
270 
271         dictionary->AddIntegerItem("signo", signo);
272         dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
273 
274         bool suppress, stop, notify;
275         signals->GetSignalInfo(signo, suppress, stop, notify);
276         dictionary->AddBooleanItem("suppress", suppress);
277         dictionary->AddBooleanItem("stop", stop);
278         dictionary->AddBooleanItem("notify", notify);
279 
280         signal_array.Push(dictionary);
281     }
282 
283     StreamString response;
284     signal_array.Dump(response);
285     return SendPacketNoLock(response.GetData(), response.GetSize());
286 }
287 
288 bool
289 GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
290 {
291     Mutex::Locker locker (m_spawned_pids_mutex);
292     FreePortForProcess(pid);
293     return m_spawned_pids.erase(pid) > 0;
294 }
295 
296 bool
297 GDBRemoteCommunicationServerPlatform::ReapDebugserverProcess (void *callback_baton,
298                                                    lldb::pid_t pid,
299                                                    bool exited,
300                                                    int signal,    // Zero for no signal
301                                                    int status)    // Exit value of process if signal is zero
302 {
303     GDBRemoteCommunicationServerPlatform *server = (GDBRemoteCommunicationServerPlatform *)callback_baton;
304     server->DebugserverProcessReaped (pid);
305     return true;
306 }
307 
308 Error
309 GDBRemoteCommunicationServerPlatform::LaunchProcess ()
310 {
311     if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
312         return Error ("%s: no process command line specified to launch", __FUNCTION__);
313 
314     // specify the process monitor if not already set.  This should
315     // generally be what happens since we need to reap started
316     // processes.
317     if (!m_process_launch_info.GetMonitorProcessCallback ())
318         m_process_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
319 
320     Error error = m_platform_sp->LaunchProcess (m_process_launch_info);
321     if (!error.Success ())
322     {
323         fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
324         return error;
325     }
326 
327     printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
328 
329     // add to list of spawned processes.  On an lldb-gdbserver, we
330     // would expect there to be only one.
331     const auto pid = m_process_launch_info.GetProcessID();
332     if (pid != LLDB_INVALID_PROCESS_ID)
333     {
334         // add to spawned pids
335         Mutex::Locker locker (m_spawned_pids_mutex);
336         m_spawned_pids.insert(pid);
337     }
338 
339     return error;
340 }
341 
342 void
343 GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map)
344 {
345     m_port_map = port_map;
346 }
347 
348 uint16_t
349 GDBRemoteCommunicationServerPlatform::GetNextAvailablePort ()
350 {
351     if (m_port_map.empty())
352         return 0; // Bind to port zero and get a port, we didn't have any limitations
353 
354     for (auto &pair : m_port_map)
355     {
356         if (pair.second == LLDB_INVALID_PROCESS_ID)
357         {
358             pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
359             return pair.first;
360         }
361     }
362     return UINT16_MAX;
363 }
364 
365 bool
366 GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
367 {
368     PortMap::iterator pos = m_port_map.find(port);
369     if (pos != m_port_map.end())
370     {
371         pos->second = pid;
372         return true;
373     }
374     return false;
375 }
376 
377 bool
378 GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port)
379 {
380     PortMap::iterator pos = m_port_map.find(port);
381     if (pos != m_port_map.end())
382     {
383         pos->second = LLDB_INVALID_PROCESS_ID;
384         return true;
385     }
386     return false;
387 }
388 
389 bool
390 GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
391 {
392     if (!m_port_map.empty())
393     {
394         for (auto &pair : m_port_map)
395         {
396             if (pair.second == pid)
397             {
398                 pair.second = LLDB_INVALID_PROCESS_ID;
399                 return true;
400             }
401         }
402     }
403     return false;
404 }
405 
406 void
407 GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset)
408 {
409     m_port_offset = port_offset;
410 }
411