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