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