GDBRemoteCommunication.cpp revision 139da72165577f073c14f2d5b86191e2c7b21d4c
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 31using namespace lldb; 32using namespace lldb_private; 33 34//---------------------------------------------------------------------- 35// GDBRemoteCommunication constructor 36//---------------------------------------------------------------------- 37GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, 38 const char *listener_name, 39 bool is_platform) : 40 Communication(comm_name), 41 m_packet_timeout (60), 42 m_rx_packet_listener (listener_name), 43 m_sequence_mutex (Mutex::eMutexTypeRecursive), 44 m_public_is_running (false), 45 m_private_is_running (false), 46 m_send_acks (true), 47 m_is_platform (is_platform) 48{ 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 69char 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 75 if (GetSendAcks ()) 76 { 77 for (size_t i = 0; i < payload_length; ++i) 78 checksum += payload[i]; 79 } 80 return checksum & 255; 81} 82 83size_t 84GDBRemoteCommunication::SendAck () 85{ 86 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 87 if (log) 88 log->Printf ("send packet: +"); 89 ConnectionStatus status = eConnectionStatusSuccess; 90 char ack_char = '+'; 91 return Write (&ack_char, 1, status, NULL); 92} 93 94size_t 95GDBRemoteCommunication::SendNack () 96{ 97 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 98 if (log) 99 log->Printf ("send packet: -"); 100 ConnectionStatus status = eConnectionStatusSuccess; 101 char nack_char = '-'; 102 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()); 111} 112 113size_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 139 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 140 if (log) 141 log->Printf ("send packet: %.*s", (int)packet.GetSize(), packet.GetData()); 142 ConnectionStatus status = eConnectionStatusSuccess; 143 size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); 144 if (bytes_written == packet.GetSize()) 145 { 146 if (GetSendAcks ()) 147 { 148 if (GetAck () != '+') 149 { 150 printf("get ack failed..."); 151 return 0; 152 } 153 } 154 } 155 else 156 { 157 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 158 if (log) 159 log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData()); 160 } 161 return bytes_written; 162 } 163 return 0; 164} 165 166char 167GDBRemoteCommunication::GetAck () 168{ 169 StringExtractorGDBRemote packet; 170 if (WaitForPacket (packet, m_packet_timeout) == 1) 171 return packet.GetChar(); 172 return 0; 173} 174 175bool 176GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker) 177{ 178 return locker.TryLock (m_sequence_mutex.GetMutex()); 179} 180 181 182bool 183GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr) 184{ 185 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL); 186} 187 188size_t 189GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, uint32_t timeout_seconds) 190{ 191 Mutex::Locker locker(m_sequence_mutex); 192 TimeValue timeout_time; 193 timeout_time = TimeValue::Now(); 194 timeout_time.OffsetWithSeconds (timeout_seconds); 195 return WaitForPacketNoLock (packet, &timeout_time); 196} 197 198size_t 199GDBRemoteCommunication::WaitForPacket (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr) 200{ 201 Mutex::Locker locker(m_sequence_mutex); 202 return WaitForPacketNoLock (packet, timeout_time_ptr); 203} 204 205size_t 206GDBRemoteCommunication::WaitForPacketNoLock (StringExtractorGDBRemote &packet, const TimeValue* timeout_time_ptr) 207{ 208 bool checksum_error = false; 209 packet.Clear (); 210 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 { 221 const char *packet_data = (const char *)event_bytes->GetBytes(); 222 const uint32_t packet_size = event_bytes->GetByteSize(); 223 LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 224 if (log) 225 log->Printf ("read packet: %.*s", packet_size, packet_data); 226 if (packet_data && packet_size > 0) 227 { 228 std::string &packet_str = packet.GetStringRef(); 229 if (packet_data[0] == '$') 230 { 231 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) 242 packet_str.assign (packet_data + 1, packet_size - 4); 243 if (GetSendAcks ()) 244 { 245 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 } 251 // Send the ack or nack if needed 252 if (checksum_error || !success) 253 SendNack(); 254 else 255 SendAck(); 256 } 257 } 258 else 259 { 260 packet_str.assign (packet_data, packet_size); 261 } 262 return packet_str.size(); 263 } 264 } 265 } 266 else if (event_type | Communication::eBroadcastBitReadThreadDidExit) 267 { 268 // Our read thread exited on us so just fall through and return zero... 269 Disconnect(); 270 } 271 } 272 return 0; 273} 274 275void 276GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast, 277 ConnectionStatus status) 278{ 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 343Error 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 471