blob: c5e11ef33de4605504e2ee60d540fee70d795964 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
Johnny Chenf3878232011-05-13 20:07:25 +000014#include <limits.h>
Stephen Wilson50daf772011-03-25 18:16:28 +000015#include <string.h>
16
Chris Lattner24943d22010-06-08 16:52:24 +000017// C++ Includes
18// Other libraries and framework includes
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/Log.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Core/StreamString.h"
Greg Claytonb72d0f02011-04-12 05:54:46 +000021#include "lldb/Host/FileSpec.h"
22#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Host/TimeValue.h"
Greg Claytonb72d0f02011-04-12 05:54:46 +000024#include "lldb/Target/Process.h"
Chris Lattner24943d22010-06-08 16:52:24 +000025
26// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000027#include "ProcessGDBRemoteLog.h"
28
Greg Claytonb72d0f02011-04-12 05:54:46 +000029#define DEBUGSERVER_BASENAME "debugserver"
30
Chris Lattner24943d22010-06-08 16:52:24 +000031using namespace lldb;
32using namespace lldb_private;
33
34//----------------------------------------------------------------------
35// GDBRemoteCommunication constructor
36//----------------------------------------------------------------------
Greg Claytonb72d0f02011-04-12 05:54:46 +000037GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
38 const char *listener_name,
39 bool is_platform) :
Greg Clayton61d043b2011-03-22 04:00:09 +000040 Communication(comm_name),
Greg Clayton24bc5d92011-03-30 18:16:51 +000041 m_packet_timeout (60),
Greg Clayton61d043b2011-03-22 04:00:09 +000042 m_rx_packet_listener (listener_name),
Chris Lattner24943d22010-06-08 16:52:24 +000043 m_sequence_mutex (Mutex::eMutexTypeRecursive),
Greg Claytoncecf3482011-01-20 07:53:45 +000044 m_public_is_running (false),
Greg Clayton58e26e02011-03-24 04:28:38 +000045 m_private_is_running (false),
Greg Claytonb72d0f02011-04-12 05:54:46 +000046 m_send_acks (true),
47 m_is_platform (is_platform)
Chris Lattner24943d22010-06-08 16:52:24 +000048{
49 m_rx_packet_listener.StartListeningForEvents(this,
50 Communication::eBroadcastBitPacketAvailable |
51 Communication::eBroadcastBitReadThreadDidExit);
52}
53
54//----------------------------------------------------------------------
55// Destructor
56//----------------------------------------------------------------------
57GDBRemoteCommunication::~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
Chris Lattner24943d22010-06-08 16:52:24 +000069char
70GDBRemoteCommunication::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
Greg Claytonc1f45872011-02-12 06:28:37 +000075 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +000076 {
Greg Clayton54e7afa2010-07-09 20:39:50 +000077 for (size_t i = 0; i < payload_length; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000078 checksum += payload[i];
79 }
80 return checksum & 255;
81}
82
83size_t
Greg Claytona4881d02011-01-22 07:12:45 +000084GDBRemoteCommunication::SendAck ()
Chris Lattner24943d22010-06-08 16:52:24 +000085{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000086 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
87 if (log)
88 log->Printf ("send packet: +");
Chris Lattner24943d22010-06-08 16:52:24 +000089 ConnectionStatus status = eConnectionStatusSuccess;
Greg Claytona4881d02011-01-22 07:12:45 +000090 char ack_char = '+';
Greg Clayton24bc5d92011-03-30 18:16:51 +000091 return Write (&ack_char, 1, status, NULL);
Chris Lattner24943d22010-06-08 16:52:24 +000092}
93
94size_t
Greg Claytona4881d02011-01-22 07:12:45 +000095GDBRemoteCommunication::SendNack ()
96{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000097 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
98 if (log)
99 log->Printf ("send packet: -");
Greg Claytona4881d02011-01-22 07:12:45 +0000100 ConnectionStatus status = eConnectionStatusSuccess;
101 char nack_char = '-';
Greg Clayton24bc5d92011-03-30 18:16:51 +0000102 return Write (&nack_char, 1, status, NULL);
103}
104
105size_t
106GDBRemoteCommunication::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());
Greg Claytona4881d02011-01-22 07:12:45 +0000111}
112
Chris Lattner24943d22010-06-08 16:52:24 +0000113size_t
114GDBRemoteCommunication::SendPacket (const char *payload)
115{
116 Mutex::Locker locker(m_sequence_mutex);
117 return SendPacketNoLock (payload, ::strlen (payload));
118}
119
120size_t
121GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
122{
123 Mutex::Locker locker(m_sequence_mutex);
124 return SendPacketNoLock (payload, payload_length);
125}
126
127size_t
128GDBRemoteCommunication::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
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000139 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
140 if (log)
Greg Clayton139da722011-05-20 03:15:54 +0000141 log->Printf ("send packet: %.*s", (int)packet.GetSize(), packet.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000142 ConnectionStatus status = eConnectionStatusSuccess;
143 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
144 if (bytes_written == packet.GetSize())
145 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000146 if (GetSendAcks ())
Greg Clayton54e7afa2010-07-09 20:39:50 +0000147 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000148 if (GetAck () != '+')
Greg Clayton58e26e02011-03-24 04:28:38 +0000149 {
150 printf("get ack failed...");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000151 return 0;
Greg Clayton58e26e02011-03-24 04:28:38 +0000152 }
Greg Clayton54e7afa2010-07-09 20:39:50 +0000153 }
Chris Lattner24943d22010-06-08 16:52:24 +0000154 }
Johnny Chen515ea542010-09-14 22:10:43 +0000155 else
156 {
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000157 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
158 if (log)
Greg Clayton139da722011-05-20 03:15:54 +0000159 log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
Johnny Chen515ea542010-09-14 22:10:43 +0000160 }
Chris Lattner24943d22010-06-08 16:52:24 +0000161 return bytes_written;
Greg Claytoneea26402010-09-14 23:36:40 +0000162 }
Chris Lattner24943d22010-06-08 16:52:24 +0000163 return 0;
164}
165
166char
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000167GDBRemoteCommunication::GetAck ()
Chris Lattner24943d22010-06-08 16:52:24 +0000168{
Greg Clayton61d043b2011-03-22 04:00:09 +0000169 StringExtractorGDBRemote packet;
170 if (WaitForPacket (packet, m_packet_timeout) == 1)
171 return packet.GetChar();
Chris Lattner24943d22010-06-08 16:52:24 +0000172 return 0;
173}
174
175bool
176GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
177{
178 return locker.TryLock (m_sequence_mutex.GetMutex());
179}
180
Chris Lattner24943d22010-06-08 16:52:24 +0000181
Greg Clayton72e1c782011-01-22 23:43:18 +0000182bool
Greg Clayton72e1c782011-01-22 23:43:18 +0000183GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
184{
185 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
186}
187
Chris Lattner24943d22010-06-08 16:52:24 +0000188size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000189GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds)
Chris Lattner24943d22010-06-08 16:52:24 +0000190{
Greg Claytoncecf3482011-01-20 07:53:45 +0000191 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000192 TimeValue timeout_time;
193 timeout_time = TimeValue::Now();
194 timeout_time.OffsetWithSeconds (timeout_seconds);
Greg Clayton61d043b2011-03-22 04:00:09 +0000195 return WaitForPacketNoLock (packet, &timeout_time);
Chris Lattner24943d22010-06-08 16:52:24 +0000196}
197
198size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000199GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000200{
201 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton61d043b2011-03-22 04:00:09 +0000202 return WaitForPacketNoLock (packet, timeout_time_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000203}
204
205size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000206GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000207{
208 bool checksum_error = false;
Greg Clayton61d043b2011-03-22 04:00:09 +0000209 packet.Clear ();
Chris Lattner24943d22010-06-08 16:52:24 +0000210
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 {
Greg Clayton139da722011-05-20 03:15:54 +0000221 const char *packet_data = (const char *)event_bytes->GetBytes();
222 const uint32_t packet_size = event_bytes->GetByteSize();
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000223 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
224 if (log)
Greg Clayton139da722011-05-20 03:15:54 +0000225 log->Printf ("read packet: %.*s", packet_size, packet_data);
Chris Lattner24943d22010-06-08 16:52:24 +0000226 if (packet_data && packet_size > 0)
227 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000228 std::string &packet_str = packet.GetStringRef();
Chris Lattner24943d22010-06-08 16:52:24 +0000229 if (packet_data[0] == '$')
230 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000231 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)
Greg Clayton61d043b2011-03-22 04:00:09 +0000242 packet_str.assign (packet_data + 1, packet_size - 4);
Greg Claytonc1f45872011-02-12 06:28:37 +0000243 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +0000244 {
Greg Clayton139da722011-05-20 03:15:54 +0000245 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 }
Chris Lattner24943d22010-06-08 16:52:24 +0000251 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000252 if (checksum_error || !success)
Greg Claytona4881d02011-01-22 07:12:45 +0000253 SendNack();
Chris Lattner24943d22010-06-08 16:52:24 +0000254 else
Greg Claytona4881d02011-01-22 07:12:45 +0000255 SendAck();
Chris Lattner24943d22010-06-08 16:52:24 +0000256 }
257 }
258 else
259 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000260 packet_str.assign (packet_data, packet_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000261 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000262 return packet_str.size();
Chris Lattner24943d22010-06-08 16:52:24 +0000263 }
264 }
265 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000266 else if (event_type | Communication::eBroadcastBitReadThreadDidExit)
Chris Lattner24943d22010-06-08 16:52:24 +0000267 {
268 // Our read thread exited on us so just fall through and return zero...
Greg Clayton58e26e02011-03-24 04:28:38 +0000269 Disconnect();
Chris Lattner24943d22010-06-08 16:52:24 +0000270 }
271 }
272 return 0;
273}
274
275void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000276GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
277 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000278{
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
Greg Claytonb72d0f02011-04-12 05:54:46 +0000343Error
344GDBRemoteCommunication::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