1 //===-- GDBRemoteCommunication.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 
11 #include "GDBRemoteCommunication.h"
12 
13 // C Includes
14 #include <string.h>
15 
16 // C++ Includes
17 // Other libraries and framework includes
18 #include "lldb/Core/Log.h"
19 #include "lldb/Core/StreamString.h"
20 #include "lldb/Host/FileSpec.h"
21 #include "lldb/Host/Host.h"
22 #include "lldb/Host/TimeValue.h"
23 #include "lldb/Target/Process.h"
24 
25 // Project includes
26 #include "ProcessGDBRemoteLog.h"
27 
28 #define DEBUGSERVER_BASENAME    "debugserver"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 //----------------------------------------------------------------------
34 // GDBRemoteCommunication constructor
35 //----------------------------------------------------------------------
36 GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
37                                                const char *listener_name,
38                                                bool is_platform) :
39     Communication(comm_name),
40     m_packet_timeout (60),
41     m_rx_packet_listener (listener_name),
42     m_sequence_mutex (Mutex::eMutexTypeRecursive),
43     m_public_is_running (false),
44     m_private_is_running (false),
45     m_send_acks (true),
46     m_is_platform (is_platform)
47 {
48     m_rx_packet_listener.StartListeningForEvents(this,
49                                                  Communication::eBroadcastBitPacketAvailable  |
50                                                  Communication::eBroadcastBitReadThreadDidExit);
51 }
52 
53 //----------------------------------------------------------------------
54 // Destructor
55 //----------------------------------------------------------------------
56 GDBRemoteCommunication::~GDBRemoteCommunication()
57 {
58     m_rx_packet_listener.StopListeningForEvents(this,
59                                                 Communication::eBroadcastBitPacketAvailable  |
60                                                 Communication::eBroadcastBitReadThreadDidExit);
61     if (IsConnected())
62     {
63         StopReadThread();
64         Disconnect();
65     }
66 }
67 
68 char
69 GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
70 {
71     int checksum = 0;
72 
73     // We only need to compute the checksum if we are sending acks
74     if (GetSendAcks ())
75     {
76         for (size_t i = 0; i < payload_length; ++i)
77             checksum += payload[i];
78     }
79     return checksum & 255;
80 }
81 
82 size_t
83 GDBRemoteCommunication::SendAck ()
84 {
85     LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
86     if (log)
87         log->Printf ("send packet: +");
88     ConnectionStatus status = eConnectionStatusSuccess;
89     char ack_char = '+';
90     return Write (&ack_char, 1, status, NULL);
91 }
92 
93 size_t
94 GDBRemoteCommunication::SendNack ()
95 {
96     LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
97     if (log)
98         log->Printf ("send packet: -");
99     ConnectionStatus status = eConnectionStatusSuccess;
100     char nack_char = '-';
101     return Write (&nack_char, 1, status, NULL);
102 }
103 
104 size_t
105 GDBRemoteCommunication::SendPacket (lldb_private::StreamString &payload)
106 {
107     Mutex::Locker locker(m_sequence_mutex);
108     const std::string &p (payload.GetString());
109     return SendPacketNoLock (p.c_str(), p.size());
110 }
111 
112 size_t
113 GDBRemoteCommunication::SendPacket (const char *payload)
114 {
115     Mutex::Locker locker(m_sequence_mutex);
116     return SendPacketNoLock (payload, ::strlen (payload));
117 }
118 
119 size_t
120 GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
121 {
122     Mutex::Locker locker(m_sequence_mutex);
123     return SendPacketNoLock (payload, payload_length);
124 }
125 
126 size_t
127 GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
128 {
129     if (IsConnected())
130     {
131         StreamString packet(0, 4, eByteOrderBig);
132 
133         packet.PutChar('$');
134         packet.Write (payload, payload_length);
135         packet.PutChar('#');
136         packet.PutHex8(CalculcateChecksum (payload, payload_length));
137 
138         LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
139         if (log)
140             log->Printf ("send packet: %s", packet.GetData());
141         ConnectionStatus status = eConnectionStatusSuccess;
142         size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
143         if (bytes_written == packet.GetSize())
144         {
145             if (GetSendAcks ())
146             {
147                 if (GetAck () != '+')
148                 {
149                     printf("get ack failed...");
150                     return 0;
151                 }
152             }
153         }
154         else
155         {
156             LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
157             if (log)
158                 log->Printf ("error: failed to send packet: %s", packet.GetData());
159         }
160         return bytes_written;
161     }
162     return 0;
163 }
164 
165 char
166 GDBRemoteCommunication::GetAck ()
167 {
168     StringExtractorGDBRemote packet;
169     if (WaitForPacket (packet, m_packet_timeout) == 1)
170         return packet.GetChar();
171     return 0;
172 }
173 
174 bool
175 GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
176 {
177     return locker.TryLock (m_sequence_mutex.GetMutex());
178 }
179 
180 
181 bool
182 GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
183 {
184     return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
185 }
186 
187 size_t
188 GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds)
189 {
190     Mutex::Locker locker(m_sequence_mutex);
191     TimeValue timeout_time;
192     timeout_time = TimeValue::Now();
193     timeout_time.OffsetWithSeconds (timeout_seconds);
194     return WaitForPacketNoLock (packet, &timeout_time);
195 }
196 
197 size_t
198 GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
199 {
200     Mutex::Locker locker(m_sequence_mutex);
201     return WaitForPacketNoLock (packet, timeout_time_ptr);
202 }
203 
204 size_t
205 GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
206 {
207     bool checksum_error = false;
208     packet.Clear ();
209 
210     EventSP event_sp;
211 
212     if (m_rx_packet_listener.WaitForEvent (timeout_time_ptr, event_sp))
213     {
214         const uint32_t event_type = event_sp->GetType();
215         if (event_type | Communication::eBroadcastBitPacketAvailable)
216         {
217             const EventDataBytes *event_bytes = EventDataBytes::GetEventDataFromEvent(event_sp.get());
218             if (event_bytes)
219             {
220                 const char * packet_data =  (const char *)event_bytes->GetBytes();
221                 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
222                 if (log)
223                     log->Printf ("read packet: %s", packet_data);
224                 const size_t packet_size =  event_bytes->GetByteSize();
225                 if (packet_data && packet_size > 0)
226                 {
227                     std::string &packet_str = packet.GetStringRef();
228                     if (packet_data[0] == '$')
229                     {
230                         bool success = false;
231                         if (packet_size < 4)
232                             ::fprintf (stderr, "Packet that starts with $ is too short: '%s'\n", packet_data);
233                         else if (packet_data[packet_size-3] != '#' ||
234                                  !::isxdigit (packet_data[packet_size-2]) ||
235                                  !::isxdigit (packet_data[packet_size-1]))
236                             ::fprintf (stderr, "Invalid checksum footer for packet: '%s'\n", packet_data);
237                         else
238                             success = true;
239 
240                         if (success)
241                             packet_str.assign (packet_data + 1, packet_size - 4);
242                         if (GetSendAcks ())
243                         {
244                             char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
245                             char actual_checksum = CalculcateChecksum (&packet_str[0], packet_str.size());
246                             checksum_error = packet_checksum != actual_checksum;
247                             // Send the ack or nack if needed
248                             if (checksum_error || !success)
249                                 SendNack();
250                             else
251                                 SendAck();
252                         }
253                     }
254                     else
255                     {
256                         packet_str.assign (packet_data, packet_size);
257                     }
258                     return packet_str.size();
259                 }
260             }
261         }
262         else if (event_type | Communication::eBroadcastBitReadThreadDidExit)
263         {
264             // Our read thread exited on us so just fall through and return zero...
265             Disconnect();
266         }
267     }
268     return 0;
269 }
270 
271 void
272 GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
273                                             ConnectionStatus status)
274 {
275     // Put the packet data into the buffer in a thread safe fashion
276     Mutex::Locker locker(m_bytes_mutex);
277     m_bytes.append ((const char *)src, src_len);
278 
279     // Parse up the packets into gdb remote packets
280     while (!m_bytes.empty())
281     {
282         // end_idx must be one past the last valid packet byte. Start
283         // it off with an invalid value that is the same as the current
284         // index.
285         size_t end_idx = 0;
286 
287         switch (m_bytes[0])
288         {
289             case '+':       // Look for ack
290             case '-':       // Look for cancel
291             case '\x03':    // ^C to halt target
292                 end_idx = 1;  // The command is one byte long...
293                 break;
294 
295             case '$':
296                 // Look for a standard gdb packet?
297                 end_idx = m_bytes.find('#');
298                 if (end_idx != std::string::npos)
299                 {
300                     if (end_idx + 2 < m_bytes.size())
301                     {
302                         end_idx += 3;
303                     }
304                     else
305                     {
306                         // Checksum bytes aren't all here yet
307                         end_idx = std::string::npos;
308                     }
309                 }
310                 break;
311 
312             default:
313                 break;
314         }
315 
316         if (end_idx == std::string::npos)
317         {
318             //ProcessGDBRemoteLog::LogIf (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE, "GDBRemoteCommunication::%s packet not yet complete: '%s'",__FUNCTION__, m_bytes.c_str());
319             return;
320         }
321         else if (end_idx > 0)
322         {
323             // We have a valid packet...
324             assert (end_idx <= m_bytes.size());
325             std::auto_ptr<EventDataBytes> event_bytes_ap (new EventDataBytes (&m_bytes[0], end_idx));
326             ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "got full packet: %s", event_bytes_ap->GetBytes());
327             BroadcastEvent (eBroadcastBitPacketAvailable, event_bytes_ap.release());
328             m_bytes.erase(0, end_idx);
329         }
330         else
331         {
332             assert (1 <= m_bytes.size());
333             ProcessGDBRemoteLog::LogIf (GDBR_LOG_COMM, "GDBRemoteCommunication::%s tossing junk byte at %c",__FUNCTION__, m_bytes[0]);
334             m_bytes.erase(0, 1);
335         }
336     }
337 }
338 
339 Error
340 GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
341                                                  const char *unix_socket_name,  // For handshaking
342                                                  lldb_private::ProcessLaunchInfo &launch_info)
343 {
344     Error error;
345     // If we locate debugserver, keep that located version around
346     static FileSpec g_debugserver_file_spec;
347 
348     // This function will fill in the launch information for the debugserver
349     // instance that gets launched.
350     launch_info.Clear();
351 
352     char debugserver_path[PATH_MAX];
353     FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
354 
355     // Always check to see if we have an environment override for the path
356     // to the debugserver to use and use it if we do.
357     const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
358     if (env_debugserver_path)
359         debugserver_file_spec.SetFile (env_debugserver_path, false);
360     else
361         debugserver_file_spec = g_debugserver_file_spec;
362     bool debugserver_exists = debugserver_file_spec.Exists();
363     if (!debugserver_exists)
364     {
365         // The debugserver binary is in the LLDB.framework/Resources
366         // directory.
367         if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
368         {
369             debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
370             debugserver_exists = debugserver_file_spec.Exists();
371             if (debugserver_exists)
372             {
373                 g_debugserver_file_spec = debugserver_file_spec;
374             }
375             else
376             {
377                 g_debugserver_file_spec.Clear();
378                 debugserver_file_spec.Clear();
379             }
380         }
381     }
382 
383     if (debugserver_exists)
384     {
385         debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
386 
387         Args &debugserver_args = launch_info.GetArguments();
388         debugserver_args.Clear();
389         char arg_cstr[PATH_MAX];
390 
391         // Start args with "debugserver /file/path -r --"
392         debugserver_args.AppendArgument(debugserver_path);
393         debugserver_args.AppendArgument(debugserver_url);
394         // use native registers, not the GDB registers
395         debugserver_args.AppendArgument("--native-regs");
396         // make debugserver run in its own session so signals generated by
397         // special terminal key sequences (^C) don't affect debugserver
398         debugserver_args.AppendArgument("--setsid");
399 
400         if (unix_socket_name && unix_socket_name[0])
401         {
402             debugserver_args.AppendArgument("--unix-socket");
403             debugserver_args.AppendArgument(unix_socket_name);
404         }
405 
406         const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
407         if (env_debugserver_log_file)
408         {
409             ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
410             debugserver_args.AppendArgument(arg_cstr);
411         }
412 
413         const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
414         if (env_debugserver_log_flags)
415         {
416             ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
417             debugserver_args.AppendArgument(arg_cstr);
418         }
419         //            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
420         //            debugserver_args.AppendArgument("--log-flags=0x802e0e");
421 
422         // We currently send down all arguments, attach pids, or attach
423         // process names in dedicated GDB server packets, so we don't need
424         // to pass them as arguments. This is currently because of all the
425         // things we need to setup prior to launching: the environment,
426         // current working dir, file actions, etc.
427 #if 0
428         // Now append the program arguments
429         if (inferior_argv)
430         {
431             // Terminate the debugserver args so we can now append the inferior args
432             debugserver_args.AppendArgument("--");
433 
434             for (int i = 0; inferior_argv[i] != NULL; ++i)
435                 debugserver_args.AppendArgument (inferior_argv[i]);
436         }
437         else if (attach_pid != LLDB_INVALID_PROCESS_ID)
438         {
439             ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
440             debugserver_args.AppendArgument (arg_cstr);
441         }
442         else if (attach_name && attach_name[0])
443         {
444             if (wait_for_launch)
445                 debugserver_args.AppendArgument ("--waitfor");
446             else
447                 debugserver_args.AppendArgument ("--attach");
448             debugserver_args.AppendArgument (attach_name);
449         }
450 #endif
451 
452         // Close STDIN, STDOUT and STDERR. We might need to redirect them
453         // to "/dev/null" if we run into any problems.
454 //        launch_info.AppendCloseFileAction (STDIN_FILENO);
455 //        launch_info.AppendCloseFileAction (STDOUT_FILENO);
456 //        launch_info.AppendCloseFileAction (STDERR_FILENO);
457 
458         error = Host::LaunchProcess(launch_info);
459     }
460     else
461     {
462         error.SetErrorStringWithFormat ("Unable to locate " DEBUGSERVER_BASENAME ".\n");
463     }
464     return error;
465 }
466 
467