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