blob: 93e4166af2c849fe74e7c0ccf1cc9bd313d32516 [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
Stephen Wilson50daf772011-03-25 18:16:28 +000014#include <string.h>
15
Chris Lattner24943d22010-06-08 16:52:24 +000016// C++ Includes
17// Other libraries and framework includes
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/Log.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Greg Claytonb72d0f02011-04-12 05:54:46 +000020#include "lldb/Host/FileSpec.h"
21#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Host/TimeValue.h"
Greg Claytonb72d0f02011-04-12 05:54:46 +000023#include "lldb/Target/Process.h"
Chris Lattner24943d22010-06-08 16:52:24 +000024
25// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000026#include "ProcessGDBRemoteLog.h"
27
Greg Claytonb72d0f02011-04-12 05:54:46 +000028#define DEBUGSERVER_BASENAME "debugserver"
29
Chris Lattner24943d22010-06-08 16:52:24 +000030using namespace lldb;
31using namespace lldb_private;
32
33//----------------------------------------------------------------------
34// GDBRemoteCommunication constructor
35//----------------------------------------------------------------------
Greg Claytonb72d0f02011-04-12 05:54:46 +000036GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
37 const char *listener_name,
38 bool is_platform) :
Greg Clayton61d043b2011-03-22 04:00:09 +000039 Communication(comm_name),
Greg Clayton24bc5d92011-03-30 18:16:51 +000040 m_packet_timeout (60),
Greg Clayton61d043b2011-03-22 04:00:09 +000041 m_rx_packet_listener (listener_name),
Chris Lattner24943d22010-06-08 16:52:24 +000042 m_sequence_mutex (Mutex::eMutexTypeRecursive),
Greg Claytoncecf3482011-01-20 07:53:45 +000043 m_public_is_running (false),
Greg Clayton58e26e02011-03-24 04:28:38 +000044 m_private_is_running (false),
Greg Claytonb72d0f02011-04-12 05:54:46 +000045 m_send_acks (true),
46 m_is_platform (is_platform)
Chris Lattner24943d22010-06-08 16:52:24 +000047{
48 m_rx_packet_listener.StartListeningForEvents(this,
49 Communication::eBroadcastBitPacketAvailable |
50 Communication::eBroadcastBitReadThreadDidExit);
51}
52
53//----------------------------------------------------------------------
54// Destructor
55//----------------------------------------------------------------------
56GDBRemoteCommunication::~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
Chris Lattner24943d22010-06-08 16:52:24 +000068char
69GDBRemoteCommunication::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
Greg Claytonc1f45872011-02-12 06:28:37 +000074 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +000075 {
Greg Clayton54e7afa2010-07-09 20:39:50 +000076 for (size_t i = 0; i < payload_length; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +000077 checksum += payload[i];
78 }
79 return checksum & 255;
80}
81
82size_t
Greg Claytona4881d02011-01-22 07:12:45 +000083GDBRemoteCommunication::SendAck ()
Chris Lattner24943d22010-06-08 16:52:24 +000084{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000085 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
86 if (log)
87 log->Printf ("send packet: +");
Chris Lattner24943d22010-06-08 16:52:24 +000088 ConnectionStatus status = eConnectionStatusSuccess;
Greg Claytona4881d02011-01-22 07:12:45 +000089 char ack_char = '+';
Greg Clayton24bc5d92011-03-30 18:16:51 +000090 return Write (&ack_char, 1, status, NULL);
Chris Lattner24943d22010-06-08 16:52:24 +000091}
92
93size_t
Greg Claytona4881d02011-01-22 07:12:45 +000094GDBRemoteCommunication::SendNack ()
95{
Greg Clayton0bfda0b2011-02-05 02:25:06 +000096 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
97 if (log)
98 log->Printf ("send packet: -");
Greg Claytona4881d02011-01-22 07:12:45 +000099 ConnectionStatus status = eConnectionStatusSuccess;
100 char nack_char = '-';
Greg Clayton24bc5d92011-03-30 18:16:51 +0000101 return Write (&nack_char, 1, status, NULL);
102}
103
104size_t
105GDBRemoteCommunication::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());
Greg Claytona4881d02011-01-22 07:12:45 +0000110}
111
Chris Lattner24943d22010-06-08 16:52:24 +0000112size_t
113GDBRemoteCommunication::SendPacket (const char *payload)
114{
115 Mutex::Locker locker(m_sequence_mutex);
116 return SendPacketNoLock (payload, ::strlen (payload));
117}
118
119size_t
120GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
121{
122 Mutex::Locker locker(m_sequence_mutex);
123 return SendPacketNoLock (payload, payload_length);
124}
125
126size_t
127GDBRemoteCommunication::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
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000138 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
139 if (log)
140 log->Printf ("send packet: %s", packet.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000141 ConnectionStatus status = eConnectionStatusSuccess;
142 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
143 if (bytes_written == packet.GetSize())
144 {
Greg Claytonc1f45872011-02-12 06:28:37 +0000145 if (GetSendAcks ())
Greg Clayton54e7afa2010-07-09 20:39:50 +0000146 {
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000147 if (GetAck () != '+')
Greg Clayton58e26e02011-03-24 04:28:38 +0000148 {
149 printf("get ack failed...");
Greg Clayton54e7afa2010-07-09 20:39:50 +0000150 return 0;
Greg Clayton58e26e02011-03-24 04:28:38 +0000151 }
Greg Clayton54e7afa2010-07-09 20:39:50 +0000152 }
Chris Lattner24943d22010-06-08 16:52:24 +0000153 }
Johnny Chen515ea542010-09-14 22:10:43 +0000154 else
155 {
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000156 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
157 if (log)
158 log->Printf ("error: failed to send packet: %s", packet.GetData());
Johnny Chen515ea542010-09-14 22:10:43 +0000159 }
Chris Lattner24943d22010-06-08 16:52:24 +0000160 return bytes_written;
Greg Claytoneea26402010-09-14 23:36:40 +0000161 }
Chris Lattner24943d22010-06-08 16:52:24 +0000162 return 0;
163}
164
165char
Greg Claytonc97bfdb2011-03-10 02:26:48 +0000166GDBRemoteCommunication::GetAck ()
Chris Lattner24943d22010-06-08 16:52:24 +0000167{
Greg Clayton61d043b2011-03-22 04:00:09 +0000168 StringExtractorGDBRemote packet;
169 if (WaitForPacket (packet, m_packet_timeout) == 1)
170 return packet.GetChar();
Chris Lattner24943d22010-06-08 16:52:24 +0000171 return 0;
172}
173
174bool
175GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker)
176{
177 return locker.TryLock (m_sequence_mutex.GetMutex());
178}
179
Chris Lattner24943d22010-06-08 16:52:24 +0000180
Greg Clayton72e1c782011-01-22 23:43:18 +0000181bool
Greg Clayton72e1c782011-01-22 23:43:18 +0000182GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
183{
184 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
185}
186
Chris Lattner24943d22010-06-08 16:52:24 +0000187size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000188GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds)
Chris Lattner24943d22010-06-08 16:52:24 +0000189{
Greg Claytoncecf3482011-01-20 07:53:45 +0000190 Mutex::Locker locker(m_sequence_mutex);
Chris Lattner24943d22010-06-08 16:52:24 +0000191 TimeValue timeout_time;
192 timeout_time = TimeValue::Now();
193 timeout_time.OffsetWithSeconds (timeout_seconds);
Greg Clayton61d043b2011-03-22 04:00:09 +0000194 return WaitForPacketNoLock (packet, &timeout_time);
Chris Lattner24943d22010-06-08 16:52:24 +0000195}
196
197size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000198GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000199{
200 Mutex::Locker locker(m_sequence_mutex);
Greg Clayton61d043b2011-03-22 04:00:09 +0000201 return WaitForPacketNoLock (packet, timeout_time_ptr);
Chris Lattner24943d22010-06-08 16:52:24 +0000202}
203
204size_t
Greg Clayton61d043b2011-03-22 04:00:09 +0000205GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000206{
207 bool checksum_error = false;
Greg Clayton61d043b2011-03-22 04:00:09 +0000208 packet.Clear ();
Chris Lattner24943d22010-06-08 16:52:24 +0000209
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();
Greg Clayton0bfda0b2011-02-05 02:25:06 +0000221 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
222 if (log)
223 log->Printf ("read packet: %s", packet_data);
Chris Lattner24943d22010-06-08 16:52:24 +0000224 const size_t packet_size = event_bytes->GetByteSize();
225 if (packet_data && packet_size > 0)
226 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000227 std::string &packet_str = packet.GetStringRef();
Chris Lattner24943d22010-06-08 16:52:24 +0000228 if (packet_data[0] == '$')
229 {
Greg Clayton4862fa22011-01-08 03:17:57 +0000230 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)
Greg Clayton61d043b2011-03-22 04:00:09 +0000241 packet_str.assign (packet_data + 1, packet_size - 4);
Greg Claytonc1f45872011-02-12 06:28:37 +0000242 if (GetSendAcks ())
Chris Lattner24943d22010-06-08 16:52:24 +0000243 {
244 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16);
Greg Clayton61d043b2011-03-22 04:00:09 +0000245 char actual_checksum = CalculcateChecksum (&packet_str[0], packet_str.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000246 checksum_error = packet_checksum != actual_checksum;
247 // Send the ack or nack if needed
Greg Clayton4862fa22011-01-08 03:17:57 +0000248 if (checksum_error || !success)
Greg Claytona4881d02011-01-22 07:12:45 +0000249 SendNack();
Chris Lattner24943d22010-06-08 16:52:24 +0000250 else
Greg Claytona4881d02011-01-22 07:12:45 +0000251 SendAck();
Chris Lattner24943d22010-06-08 16:52:24 +0000252 }
253 }
254 else
255 {
Greg Clayton61d043b2011-03-22 04:00:09 +0000256 packet_str.assign (packet_data, packet_size);
Chris Lattner24943d22010-06-08 16:52:24 +0000257 }
Greg Clayton61d043b2011-03-22 04:00:09 +0000258 return packet_str.size();
Chris Lattner24943d22010-06-08 16:52:24 +0000259 }
260 }
261 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000262 else if (event_type | Communication::eBroadcastBitReadThreadDidExit)
Chris Lattner24943d22010-06-08 16:52:24 +0000263 {
264 // Our read thread exited on us so just fall through and return zero...
Greg Clayton58e26e02011-03-24 04:28:38 +0000265 Disconnect();
Chris Lattner24943d22010-06-08 16:52:24 +0000266 }
267 }
268 return 0;
269}
270
271void
Caroline Ticec4f55fe2010-11-19 20:47:54 +0000272GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast,
273 ConnectionStatus status)
Chris Lattner24943d22010-06-08 16:52:24 +0000274{
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
Greg Claytonb72d0f02011-04-12 05:54:46 +0000339Error
340GDBRemoteCommunication::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