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