GDBRemoteCommunication.cpp revision ae932359b80098532f3c3766fa9e6527352fbb67
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/StreamFile.h" 21#include "lldb/Core/StreamString.h" 22#include "lldb/Host/FileSpec.h" 23#include "lldb/Host/Host.h" 24#include "lldb/Host/TimeValue.h" 25#include "lldb/Target/Process.h" 26 27// Project includes 28#include "ProcessGDBRemoteLog.h" 29 30#define DEBUGSERVER_BASENAME "debugserver" 31 32using namespace lldb; 33using namespace lldb_private; 34 35GDBRemoteCommunication::History::History (uint32_t size) : 36 m_packets(), 37 m_curr_idx (0), 38 m_total_packet_count (0), 39 m_dumped_to_log (false) 40{ 41 m_packets.resize(size); 42} 43 44GDBRemoteCommunication::History::~History () 45{ 46} 47 48void 49GDBRemoteCommunication::History::Dump (lldb_private::Stream &strm) const 50{ 51 const uint32_t size = GetNumPacketsInHistory (); 52 const uint32_t first_idx = GetFirstSavedPacketIndex (); 53 const uint32_t stop_idx = m_curr_idx + size; 54 for (uint32_t i = first_idx; i < stop_idx; ++i) 55 { 56 const uint32_t idx = NormalizeIndex (i); 57 const Entry &entry = m_packets[idx]; 58 if (entry.type == ePacketTypeInvalid || entry.packet.empty()) 59 break; 60 strm.Printf ("history[%u] <%4u> %s packet: %s\n", 61 entry.packet_idx, 62 entry.bytes_transmitted, 63 (entry.type == ePacketTypeSend) ? "send" : "read", 64 entry.packet.c_str()); 65 } 66} 67 68void 69GDBRemoteCommunication::History::Dump (lldb_private::Log *log) const 70{ 71 if (log && !m_dumped_to_log) 72 { 73 m_dumped_to_log = true; 74 const uint32_t size = GetNumPacketsInHistory (); 75 const uint32_t first_idx = GetFirstSavedPacketIndex (); 76 const uint32_t stop_idx = m_curr_idx + size; 77 for (uint32_t i = first_idx; i < stop_idx; ++i) 78 { 79 const uint32_t idx = NormalizeIndex (i); 80 const Entry &entry = m_packets[idx]; 81 if (entry.type == ePacketTypeInvalid || entry.packet.empty()) 82 break; 83 log->Printf ("history[%u] <%4u> %s packet: %s", 84 entry.packet_idx, 85 entry.bytes_transmitted, 86 (entry.type == ePacketTypeSend) ? "send" : "read", 87 entry.packet.c_str()); 88 } 89 } 90} 91 92//---------------------------------------------------------------------- 93// GDBRemoteCommunication constructor 94//---------------------------------------------------------------------- 95GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, 96 const char *listener_name, 97 bool is_platform) : 98 Communication(comm_name), 99 m_packet_timeout (1), 100 m_sequence_mutex (Mutex::eMutexTypeRecursive), 101 m_public_is_running (false), 102 m_private_is_running (false), 103 m_history (512), 104 m_send_acks (true), 105 m_is_platform (is_platform) 106{ 107} 108 109//---------------------------------------------------------------------- 110// Destructor 111//---------------------------------------------------------------------- 112GDBRemoteCommunication::~GDBRemoteCommunication() 113{ 114 if (IsConnected()) 115 { 116 Disconnect(); 117 } 118} 119 120char 121GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length) 122{ 123 int checksum = 0; 124 125 // We only need to compute the checksum if we are sending acks 126 if (GetSendAcks ()) 127 { 128 for (size_t i = 0; i < payload_length; ++i) 129 checksum += payload[i]; 130 } 131 return checksum & 255; 132} 133 134size_t 135GDBRemoteCommunication::SendAck () 136{ 137 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 138 ConnectionStatus status = eConnectionStatusSuccess; 139 char ch = '+'; 140 const size_t bytes_written = Write (&ch, 1, status, NULL); 141 if (log) 142 log->Printf ("<%4zu> send packet: %c", bytes_written, ch); 143 m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written); 144 return bytes_written; 145} 146 147size_t 148GDBRemoteCommunication::SendNack () 149{ 150 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 151 ConnectionStatus status = eConnectionStatusSuccess; 152 char ch = '-'; 153 const size_t bytes_written = Write (&ch, 1, status, NULL); 154 if (log) 155 log->Printf ("<%4zu> send packet: %c", bytes_written, ch); 156 m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written); 157 return bytes_written; 158} 159 160size_t 161GDBRemoteCommunication::SendPacket (lldb_private::StreamString &payload) 162{ 163 Mutex::Locker locker(m_sequence_mutex); 164 const std::string &p (payload.GetString()); 165 return SendPacketNoLock (p.c_str(), p.size()); 166} 167 168size_t 169GDBRemoteCommunication::SendPacket (const char *payload) 170{ 171 Mutex::Locker locker(m_sequence_mutex); 172 return SendPacketNoLock (payload, ::strlen (payload)); 173} 174 175size_t 176GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length) 177{ 178 Mutex::Locker locker(m_sequence_mutex); 179 return SendPacketNoLock (payload, payload_length); 180} 181 182size_t 183GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length) 184{ 185 if (IsConnected()) 186 { 187 StreamString packet(0, 4, eByteOrderBig); 188 189 packet.PutChar('$'); 190 packet.Write (payload, payload_length); 191 packet.PutChar('#'); 192 packet.PutHex8(CalculcateChecksum (payload, payload_length)); 193 194 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 195 ConnectionStatus status = eConnectionStatusSuccess; 196 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); 197 if (log) 198 { 199 // If logging was just enabled and we have history, then dump out what 200 // we have to the log so we get the historical context. The Dump() call that 201 // logs all of the packet will set a boolean so that we don't dump this more 202 // than once 203 if (!m_history.DidDumpToLog ()) 204 m_history.Dump (log.get()); 205 206 log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData()); 207 } 208 209 m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written); 210 211 212 if (bytes_written == packet.GetSize()) 213 { 214 if (GetSendAcks ()) 215 { 216 if (GetAck () != '+') 217 { 218 printf("get ack failed..."); 219 return 0; 220 } 221 } 222 } 223 else 224 { 225 if (log) 226 log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData()); 227 } 228 return bytes_written; 229 } 230 return 0; 231} 232 233char 234GDBRemoteCommunication::GetAck () 235{ 236 StringExtractorGDBRemote packet; 237 if (WaitForPacketWithTimeoutMicroSeconds (packet, GetPacketTimeoutInMicroSeconds ()) == 1) 238 return packet.GetChar(); 239 return 0; 240} 241 242bool 243GDBRemoteCommunication::TryLockSequenceMutex (Mutex::Locker& locker) 244{ 245 return locker.TryLock (m_sequence_mutex.GetMutex()); 246} 247 248 249bool 250GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr) 251{ 252 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL); 253} 254 255size_t 256GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSeconds (StringExtractorGDBRemote &packet, uint32_t timeout_usec) 257{ 258 Mutex::Locker locker(m_sequence_mutex); 259 return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); 260} 261 262size_t 263GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec) 264{ 265 uint8_t buffer[8192]; 266 Error error; 267 268 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE)); 269 270 // Check for a packet from our cache first without trying any reading... 271 if (CheckForPacket (NULL, 0, packet)) 272 return packet.GetStringRef().size(); 273 274 bool timed_out = false; 275 while (IsConnected() && !timed_out) 276 { 277 lldb::ConnectionStatus status = eConnectionStatusNoConnection; 278 size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); 279 280 if (log) 281 log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu", 282 __PRETTY_FUNCTION__, 283 timeout_usec, 284 Communication::ConnectionStatusAsCString (status), 285 error.AsCString(), 286 bytes_read); 287 288 if (bytes_read > 0) 289 { 290 if (CheckForPacket (buffer, bytes_read, packet)) 291 return packet.GetStringRef().size(); 292 } 293 else 294 { 295 switch (status) 296 { 297 case eConnectionStatusTimedOut: 298 timed_out = true; 299 break; 300 case eConnectionStatusSuccess: 301 //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); 302 break; 303 304 case eConnectionStatusEndOfFile: 305 case eConnectionStatusNoConnection: 306 case eConnectionStatusLostConnection: 307 case eConnectionStatusError: 308 Disconnect(); 309 break; 310 } 311 } 312 } 313 packet.Clear (); 314 return 0; 315} 316 317bool 318GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet) 319{ 320 // Put the packet data into the buffer in a thread safe fashion 321 Mutex::Locker locker(m_bytes_mutex); 322 323 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 324 325 if (src && src_len > 0) 326 { 327 if (log && log->GetVerbose()) 328 { 329 StreamString s; 330 log->Printf ("GDBRemoteCommunication::%s adding %u bytes: %.*s", 331 __FUNCTION__, 332 (uint32_t)src_len, 333 (uint32_t)src_len, 334 src); 335 } 336 m_bytes.append ((const char *)src, src_len); 337 } 338 339 // Parse up the packets into gdb remote packets 340 if (!m_bytes.empty()) 341 { 342 // end_idx must be one past the last valid packet byte. Start 343 // it off with an invalid value that is the same as the current 344 // index. 345 size_t content_start = 0; 346 size_t content_length = 0; 347 size_t total_length = 0; 348 size_t checksum_idx = std::string::npos; 349 350 switch (m_bytes[0]) 351 { 352 case '+': // Look for ack 353 case '-': // Look for cancel 354 case '\x03': // ^C to halt target 355 content_length = total_length = 1; // The command is one byte long... 356 break; 357 358 case '$': 359 // Look for a standard gdb packet? 360 { 361 size_t hash_pos = m_bytes.find('#'); 362 if (hash_pos != std::string::npos) 363 { 364 if (hash_pos + 2 < m_bytes.size()) 365 { 366 checksum_idx = hash_pos + 1; 367 // Skip the dollar sign 368 content_start = 1; 369 // Don't include the # in the content or the $ in the content length 370 content_length = hash_pos - 1; 371 372 total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes 373 } 374 else 375 { 376 // Checksum bytes aren't all here yet 377 content_length = std::string::npos; 378 } 379 } 380 } 381 break; 382 383 default: 384 { 385 // We have an unexpected byte and we need to flush all bad 386 // data that is in m_bytes, so we need to find the first 387 // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt), 388 // or '$' character (start of packet header) or of course, 389 // the end of the data in m_bytes... 390 const size_t bytes_len = m_bytes.size(); 391 bool done = false; 392 uint32_t idx; 393 for (idx = 1; !done && idx < bytes_len; ++idx) 394 { 395 switch (m_bytes[idx]) 396 { 397 case '+': 398 case '-': 399 case '\x03': 400 case '$': 401 done = true; 402 break; 403 404 default: 405 break; 406 } 407 } 408 if (log) 409 log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", 410 __FUNCTION__, idx, idx, m_bytes.c_str()); 411 m_bytes.erase(0, idx); 412 } 413 break; 414 } 415 416 if (content_length == std::string::npos) 417 { 418 packet.Clear(); 419 return false; 420 } 421 else if (total_length > 0) 422 { 423 424 // We have a valid packet... 425 assert (content_length <= m_bytes.size()); 426 assert (total_length <= m_bytes.size()); 427 assert (content_length <= total_length); 428 429 bool success = true; 430 std::string &packet_str = packet.GetStringRef(); 431 432 433 if (log) 434 { 435 // If logging was just enabled and we have history, then dump out what 436 // we have to the log so we get the historical context. The Dump() call that 437 // logs all of the packet will set a boolean so that we don't dump this more 438 // than once 439 if (!m_history.DidDumpToLog ()) 440 m_history.Dump (log.get()); 441 442 log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str()); 443 } 444 445 m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length); 446 447 packet_str.assign (m_bytes, content_start, content_length); 448 449 if (m_bytes[0] == '$') 450 { 451 assert (checksum_idx < m_bytes.size()); 452 if (::isxdigit (m_bytes[checksum_idx+0]) || 453 ::isxdigit (m_bytes[checksum_idx+1])) 454 { 455 if (GetSendAcks ()) 456 { 457 const char *packet_checksum_cstr = &m_bytes[checksum_idx]; 458 char packet_checksum = strtol (packet_checksum_cstr, NULL, 16); 459 char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size()); 460 success = packet_checksum == actual_checksum; 461 if (!success) 462 { 463 if (log) 464 log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", 465 (int)(total_length), 466 m_bytes.c_str(), 467 (uint8_t)packet_checksum, 468 (uint8_t)actual_checksum); 469 } 470 // Send the ack or nack if needed 471 if (!success) 472 SendNack(); 473 else 474 SendAck(); 475 } 476 } 477 else 478 { 479 success = false; 480 if (log) 481 log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str()); 482 } 483 } 484 485 m_bytes.erase(0, total_length); 486 packet.SetFilePos(0); 487 return success; 488 } 489 } 490 packet.Clear(); 491 return false; 492} 493 494Error 495GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url, 496 const char *unix_socket_name, // For handshaking 497 lldb_private::ProcessLaunchInfo &launch_info) 498{ 499 Error error; 500 // If we locate debugserver, keep that located version around 501 static FileSpec g_debugserver_file_spec; 502 503 // This function will fill in the launch information for the debugserver 504 // instance that gets launched. 505 launch_info.Clear(); 506 507 char debugserver_path[PATH_MAX]; 508 FileSpec &debugserver_file_spec = launch_info.GetExecutableFile(); 509 510 // Always check to see if we have an environment override for the path 511 // to the debugserver to use and use it if we do. 512 const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH"); 513 if (env_debugserver_path) 514 debugserver_file_spec.SetFile (env_debugserver_path, false); 515 else 516 debugserver_file_spec = g_debugserver_file_spec; 517 bool debugserver_exists = debugserver_file_spec.Exists(); 518 if (!debugserver_exists) 519 { 520 // The debugserver binary is in the LLDB.framework/Resources 521 // directory. 522 if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec)) 523 { 524 debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME); 525 debugserver_exists = debugserver_file_spec.Exists(); 526 if (debugserver_exists) 527 { 528 g_debugserver_file_spec = debugserver_file_spec; 529 } 530 else 531 { 532 g_debugserver_file_spec.Clear(); 533 debugserver_file_spec.Clear(); 534 } 535 } 536 } 537 538 if (debugserver_exists) 539 { 540 debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path)); 541 542 Args &debugserver_args = launch_info.GetArguments(); 543 debugserver_args.Clear(); 544 char arg_cstr[PATH_MAX]; 545 546 // Start args with "debugserver /file/path -r --" 547 debugserver_args.AppendArgument(debugserver_path); 548 debugserver_args.AppendArgument(debugserver_url); 549 // use native registers, not the GDB registers 550 debugserver_args.AppendArgument("--native-regs"); 551 // make debugserver run in its own session so signals generated by 552 // special terminal key sequences (^C) don't affect debugserver 553 debugserver_args.AppendArgument("--setsid"); 554 555 if (unix_socket_name && unix_socket_name[0]) 556 { 557 debugserver_args.AppendArgument("--unix-socket"); 558 debugserver_args.AppendArgument(unix_socket_name); 559 } 560 561 const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE"); 562 if (env_debugserver_log_file) 563 { 564 ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file); 565 debugserver_args.AppendArgument(arg_cstr); 566 } 567 568 const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS"); 569 if (env_debugserver_log_flags) 570 { 571 ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags); 572 debugserver_args.AppendArgument(arg_cstr); 573 } 574 // debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt"); 575 // debugserver_args.AppendArgument("--log-flags=0x802e0e"); 576 577 // We currently send down all arguments, attach pids, or attach 578 // process names in dedicated GDB server packets, so we don't need 579 // to pass them as arguments. This is currently because of all the 580 // things we need to setup prior to launching: the environment, 581 // current working dir, file actions, etc. 582#if 0 583 // Now append the program arguments 584 if (inferior_argv) 585 { 586 // Terminate the debugserver args so we can now append the inferior args 587 debugserver_args.AppendArgument("--"); 588 589 for (int i = 0; inferior_argv[i] != NULL; ++i) 590 debugserver_args.AppendArgument (inferior_argv[i]); 591 } 592 else if (attach_pid != LLDB_INVALID_PROCESS_ID) 593 { 594 ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid); 595 debugserver_args.AppendArgument (arg_cstr); 596 } 597 else if (attach_name && attach_name[0]) 598 { 599 if (wait_for_launch) 600 debugserver_args.AppendArgument ("--waitfor"); 601 else 602 debugserver_args.AppendArgument ("--attach"); 603 debugserver_args.AppendArgument (attach_name); 604 } 605#endif 606 607 // Close STDIN, STDOUT and STDERR. We might need to redirect them 608 // to "/dev/null" if we run into any problems. 609// launch_info.AppendCloseFileAction (STDIN_FILENO); 610// launch_info.AppendCloseFileAction (STDOUT_FILENO); 611// launch_info.AppendCloseFileAction (STDERR_FILENO); 612 613 error = Host::LaunchProcess(launch_info); 614 } 615 else 616 { 617 error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME ); 618 } 619 return error; 620} 621 622void 623GDBRemoteCommunication::DumpHistory(const char *path) 624{ 625 StreamFile strm; 626 Error error (strm.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate)); 627 if (error.Success()) 628 m_history.Dump (strm); 629 else 630 fprintf (stderr, "error: unable to open '%s' -- %s\n", path, error.AsCString()); 631} 632