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 <string.h> 15 16 // C++ Includes 17 // Other libraries and framework includes 18 #include "lldb/Core/Log.h" 19 #include "lldb/Core/StreamString.h" 20 #include "lldb/Host/FileSpec.h" 21 #include "lldb/Host/Host.h" 22 #include "lldb/Host/TimeValue.h" 23 #include "lldb/Target/Process.h" 24 25 // Project includes 26 #include "ProcessGDBRemoteLog.h" 27 28 #define DEBUGSERVER_BASENAME "debugserver" 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 //---------------------------------------------------------------------- 34 // GDBRemoteCommunication constructor 35 //---------------------------------------------------------------------- 36 GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, 37 const char *listener_name, 38 bool is_platform) : 39 Communication(comm_name), 40 m_packet_timeout (60), 41 m_rx_packet_listener (listener_name), 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 m_rx_packet_listener.StartListeningForEvents(this, 49 Communication::eBroadcastBitPacketAvailable | 50 Communication::eBroadcastBitReadThreadDidExit); 51 } 52 53 //---------------------------------------------------------------------- 54 // Destructor 55 //---------------------------------------------------------------------- 56 GDBRemoteCommunication::~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 68 char 69 GDBRemoteCommunication::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 74 if (GetSendAcks ()) 75 { 76 for (size_t i = 0; i < payload_length; ++i) 77 checksum += payload[i]; 78 } 79 return checksum & 255; 80 } 81 82 size_t 83 GDBRemoteCommunication::SendAck () 84 { 85 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 86 if (log) 87 log->Printf ("send packet: +"); 88 ConnectionStatus status = eConnectionStatusSuccess; 89 char ack_char = '+'; 90 return Write (&ack_char, 1, status, NULL); 91 } 92 93 size_t 94 GDBRemoteCommunication::SendNack () 95 { 96 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 97 if (log) 98 log->Printf ("send packet: -"); 99 ConnectionStatus status = eConnectionStatusSuccess; 100 char nack_char = '-'; 101 return Write (&nack_char, 1, status, NULL); 102 } 103 104 size_t 105 GDBRemoteCommunication::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()); 110 } 111 112 size_t 113 GDBRemoteCommunication::SendPacket (const char *payload) 114 { 115 Mutex::Locker locker(m_sequence_mutex); 116 return SendPacketNoLock (payload, ::strlen (payload)); 117 } 118 119 size_t 120 GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length) 121 { 122 Mutex::Locker locker(m_sequence_mutex); 123 return SendPacketNoLock (payload, payload_length); 124 } 125 126 size_t 127 GDBRemoteCommunication::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 138 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 139 if (log) 140 log->Printf ("send packet: %s", packet.GetData()); 141 ConnectionStatus status = eConnectionStatusSuccess; 142 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); 143 if (bytes_written == packet.GetSize()) 144 { 145 if (GetSendAcks ()) 146 { 147 if (GetAck () != '+') 148 { 149 printf("get ack failed..."); 150 return 0; 151 } 152 } 153 } 154 else 155 { 156 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 157 if (log) 158 log->Printf ("error: failed to send packet: %s", packet.GetData()); 159 } 160 return bytes_written; 161 } 162 return 0; 163 } 164 165 char 166 GDBRemoteCommunication::GetAck () 167 { 168 StringExtractorGDBRemote packet; 169 if (WaitForPacket (packet, m_packet_timeout) == 1) 170 return packet.GetChar(); 171 return 0; 172 } 173 174 bool 175 GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker) 176 { 177 return locker.TryLock (m_sequence_mutex.GetMutex()); 178 } 179 180 181 bool 182 GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr) 183 { 184 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL); 185 } 186 187 size_t 188 GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds) 189 { 190 Mutex::Locker locker(m_sequence_mutex); 191 TimeValue timeout_time; 192 timeout_time = TimeValue::Now(); 193 timeout_time.OffsetWithSeconds (timeout_seconds); 194 return WaitForPacketNoLock (packet, &timeout_time); 195 } 196 197 size_t 198 GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr) 199 { 200 Mutex::Locker locker(m_sequence_mutex); 201 return WaitForPacketNoLock (packet, timeout_time_ptr); 202 } 203 204 size_t 205 GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr) 206 { 207 bool checksum_error = false; 208 packet.Clear (); 209 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(); 221 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 222 if (log) 223 log->Printf ("read packet: %s", packet_data); 224 const size_t packet_size = event_bytes->GetByteSize(); 225 if (packet_data && packet_size > 0) 226 { 227 std::string &packet_str = packet.GetStringRef(); 228 if (packet_data[0] == '$') 229 { 230 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) 241 packet_str.assign (packet_data + 1, packet_size - 4); 242 if (GetSendAcks ()) 243 { 244 char packet_checksum = strtol (&packet_data[packet_size-2], NULL, 16); 245 char actual_checksum = CalculcateChecksum (&packet_str[0], packet_str.size()); 246 checksum_error = packet_checksum != actual_checksum; 247 // Send the ack or nack if needed 248 if (checksum_error || !success) 249 SendNack(); 250 else 251 SendAck(); 252 } 253 } 254 else 255 { 256 packet_str.assign (packet_data, packet_size); 257 } 258 return packet_str.size(); 259 } 260 } 261 } 262 else if (event_type | Communication::eBroadcastBitReadThreadDidExit) 263 { 264 // Our read thread exited on us so just fall through and return zero... 265 Disconnect(); 266 } 267 } 268 return 0; 269 } 270 271 void 272 GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast, 273 ConnectionStatus status) 274 { 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 339 Error 340 GDBRemoteCommunication::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 467