1254721Semaste//===-- GDBRemoteCommunication.cpp ------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste 11254721Semaste#include "GDBRemoteCommunication.h" 12254721Semaste 13254721Semaste// C Includes 14254721Semaste#include <limits.h> 15254721Semaste#include <string.h> 16269024Semaste#include <sys/stat.h> 17254721Semaste 18254721Semaste// C++ Includes 19254721Semaste// Other libraries and framework includes 20269024Semaste#include "lldb/Core/ConnectionFileDescriptor.h" 21254721Semaste#include "lldb/Core/Log.h" 22254721Semaste#include "lldb/Core/StreamFile.h" 23254721Semaste#include "lldb/Core/StreamString.h" 24254721Semaste#include "lldb/Host/FileSpec.h" 25254721Semaste#include "lldb/Host/Host.h" 26254721Semaste#include "lldb/Host/TimeValue.h" 27254721Semaste#include "lldb/Target/Process.h" 28254721Semaste 29254721Semaste// Project includes 30254721Semaste#include "ProcessGDBRemoteLog.h" 31254721Semaste 32254721Semaste#define DEBUGSERVER_BASENAME "debugserver" 33254721Semaste 34254721Semasteusing namespace lldb; 35254721Semasteusing namespace lldb_private; 36254721Semaste 37254721SemasteGDBRemoteCommunication::History::History (uint32_t size) : 38254721Semaste m_packets(), 39254721Semaste m_curr_idx (0), 40254721Semaste m_total_packet_count (0), 41254721Semaste m_dumped_to_log (false) 42254721Semaste{ 43254721Semaste m_packets.resize(size); 44254721Semaste} 45254721Semaste 46254721SemasteGDBRemoteCommunication::History::~History () 47254721Semaste{ 48254721Semaste} 49254721Semaste 50254721Semastevoid 51254721SemasteGDBRemoteCommunication::History::AddPacket (char packet_char, 52254721Semaste PacketType type, 53254721Semaste uint32_t bytes_transmitted) 54254721Semaste{ 55254721Semaste const size_t size = m_packets.size(); 56254721Semaste if (size > 0) 57254721Semaste { 58254721Semaste const uint32_t idx = GetNextIndex(); 59254721Semaste m_packets[idx].packet.assign (1, packet_char); 60254721Semaste m_packets[idx].type = type; 61254721Semaste m_packets[idx].bytes_transmitted = bytes_transmitted; 62254721Semaste m_packets[idx].packet_idx = m_total_packet_count; 63254721Semaste m_packets[idx].tid = Host::GetCurrentThreadID(); 64254721Semaste } 65254721Semaste} 66254721Semaste 67254721Semastevoid 68254721SemasteGDBRemoteCommunication::History::AddPacket (const std::string &src, 69254721Semaste uint32_t src_len, 70254721Semaste PacketType type, 71254721Semaste uint32_t bytes_transmitted) 72254721Semaste{ 73254721Semaste const size_t size = m_packets.size(); 74254721Semaste if (size > 0) 75254721Semaste { 76254721Semaste const uint32_t idx = GetNextIndex(); 77254721Semaste m_packets[idx].packet.assign (src, 0, src_len); 78254721Semaste m_packets[idx].type = type; 79254721Semaste m_packets[idx].bytes_transmitted = bytes_transmitted; 80254721Semaste m_packets[idx].packet_idx = m_total_packet_count; 81254721Semaste m_packets[idx].tid = Host::GetCurrentThreadID(); 82254721Semaste } 83254721Semaste} 84254721Semaste 85254721Semastevoid 86254721SemasteGDBRemoteCommunication::History::Dump (lldb_private::Stream &strm) const 87254721Semaste{ 88254721Semaste const uint32_t size = GetNumPacketsInHistory (); 89254721Semaste const uint32_t first_idx = GetFirstSavedPacketIndex (); 90254721Semaste const uint32_t stop_idx = m_curr_idx + size; 91254721Semaste for (uint32_t i = first_idx; i < stop_idx; ++i) 92254721Semaste { 93254721Semaste const uint32_t idx = NormalizeIndex (i); 94254721Semaste const Entry &entry = m_packets[idx]; 95254721Semaste if (entry.type == ePacketTypeInvalid || entry.packet.empty()) 96254721Semaste break; 97254721Semaste strm.Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", 98254721Semaste entry.packet_idx, 99254721Semaste entry.tid, 100254721Semaste entry.bytes_transmitted, 101254721Semaste (entry.type == ePacketTypeSend) ? "send" : "read", 102254721Semaste entry.packet.c_str()); 103254721Semaste } 104254721Semaste} 105254721Semaste 106254721Semastevoid 107254721SemasteGDBRemoteCommunication::History::Dump (lldb_private::Log *log) const 108254721Semaste{ 109254721Semaste if (log && !m_dumped_to_log) 110254721Semaste { 111254721Semaste m_dumped_to_log = true; 112254721Semaste const uint32_t size = GetNumPacketsInHistory (); 113254721Semaste const uint32_t first_idx = GetFirstSavedPacketIndex (); 114254721Semaste const uint32_t stop_idx = m_curr_idx + size; 115254721Semaste for (uint32_t i = first_idx; i < stop_idx; ++i) 116254721Semaste { 117254721Semaste const uint32_t idx = NormalizeIndex (i); 118254721Semaste const Entry &entry = m_packets[idx]; 119254721Semaste if (entry.type == ePacketTypeInvalid || entry.packet.empty()) 120254721Semaste break; 121254721Semaste log->Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", 122254721Semaste entry.packet_idx, 123254721Semaste entry.tid, 124254721Semaste entry.bytes_transmitted, 125254721Semaste (entry.type == ePacketTypeSend) ? "send" : "read", 126254721Semaste entry.packet.c_str()); 127254721Semaste } 128254721Semaste } 129254721Semaste} 130254721Semaste 131254721Semaste//---------------------------------------------------------------------- 132254721Semaste// GDBRemoteCommunication constructor 133254721Semaste//---------------------------------------------------------------------- 134254721SemasteGDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, 135254721Semaste const char *listener_name, 136254721Semaste bool is_platform) : 137254721Semaste Communication(comm_name), 138263363Semaste#ifdef LLDB_CONFIGURATION_DEBUG 139263363Semaste m_packet_timeout (1000), 140263363Semaste#else 141254721Semaste m_packet_timeout (1), 142263363Semaste#endif 143254721Semaste m_sequence_mutex (Mutex::eMutexTypeRecursive), 144254721Semaste m_public_is_running (false), 145254721Semaste m_private_is_running (false), 146254721Semaste m_history (512), 147254721Semaste m_send_acks (true), 148269024Semaste m_is_platform (is_platform), 149269024Semaste m_listen_thread (LLDB_INVALID_HOST_THREAD), 150269024Semaste m_listen_url () 151254721Semaste{ 152254721Semaste} 153254721Semaste 154254721Semaste//---------------------------------------------------------------------- 155254721Semaste// Destructor 156254721Semaste//---------------------------------------------------------------------- 157254721SemasteGDBRemoteCommunication::~GDBRemoteCommunication() 158254721Semaste{ 159254721Semaste if (IsConnected()) 160254721Semaste { 161254721Semaste Disconnect(); 162254721Semaste } 163254721Semaste} 164254721Semaste 165254721Semastechar 166254721SemasteGDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length) 167254721Semaste{ 168254721Semaste int checksum = 0; 169254721Semaste 170254721Semaste for (size_t i = 0; i < payload_length; ++i) 171254721Semaste checksum += payload[i]; 172254721Semaste 173254721Semaste return checksum & 255; 174254721Semaste} 175254721Semaste 176254721Semastesize_t 177254721SemasteGDBRemoteCommunication::SendAck () 178254721Semaste{ 179254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 180254721Semaste ConnectionStatus status = eConnectionStatusSuccess; 181254721Semaste char ch = '+'; 182254721Semaste const size_t bytes_written = Write (&ch, 1, status, NULL); 183254721Semaste if (log) 184263363Semaste log->Printf ("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); 185254721Semaste m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written); 186254721Semaste return bytes_written; 187254721Semaste} 188254721Semaste 189254721Semastesize_t 190254721SemasteGDBRemoteCommunication::SendNack () 191254721Semaste{ 192254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 193254721Semaste ConnectionStatus status = eConnectionStatusSuccess; 194254721Semaste char ch = '-'; 195254721Semaste const size_t bytes_written = Write (&ch, 1, status, NULL); 196254721Semaste if (log) 197263363Semaste log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch); 198254721Semaste m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written); 199254721Semaste return bytes_written; 200254721Semaste} 201254721Semaste 202269024SemasteGDBRemoteCommunication::PacketResult 203254721SemasteGDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length) 204254721Semaste{ 205254721Semaste Mutex::Locker locker(m_sequence_mutex); 206254721Semaste return SendPacketNoLock (payload, payload_length); 207254721Semaste} 208254721Semaste 209269024SemasteGDBRemoteCommunication::PacketResult 210254721SemasteGDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length) 211254721Semaste{ 212254721Semaste if (IsConnected()) 213254721Semaste { 214254721Semaste StreamString packet(0, 4, eByteOrderBig); 215254721Semaste 216254721Semaste packet.PutChar('$'); 217254721Semaste packet.Write (payload, payload_length); 218254721Semaste packet.PutChar('#'); 219254721Semaste packet.PutHex8(CalculcateChecksum (payload, payload_length)); 220254721Semaste 221254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 222254721Semaste ConnectionStatus status = eConnectionStatusSuccess; 223254721Semaste size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); 224254721Semaste if (log) 225254721Semaste { 226254721Semaste // If logging was just enabled and we have history, then dump out what 227254721Semaste // we have to the log so we get the historical context. The Dump() call that 228254721Semaste // logs all of the packet will set a boolean so that we don't dump this more 229254721Semaste // than once 230254721Semaste if (!m_history.DidDumpToLog ()) 231254721Semaste m_history.Dump (log); 232254721Semaste 233263363Semaste log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet.GetSize(), packet.GetData()); 234254721Semaste } 235254721Semaste 236254721Semaste m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written); 237254721Semaste 238254721Semaste 239254721Semaste if (bytes_written == packet.GetSize()) 240254721Semaste { 241254721Semaste if (GetSendAcks ()) 242269024Semaste return GetAck (); 243269024Semaste else 244269024Semaste return PacketResult::Success; 245254721Semaste } 246254721Semaste else 247254721Semaste { 248254721Semaste if (log) 249254721Semaste log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData()); 250254721Semaste } 251254721Semaste } 252269024Semaste return PacketResult::ErrorSendFailed; 253254721Semaste} 254254721Semaste 255269024SemasteGDBRemoteCommunication::PacketResult 256254721SemasteGDBRemoteCommunication::GetAck () 257254721Semaste{ 258254721Semaste StringExtractorGDBRemote packet; 259269024Semaste PacketResult result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds ()); 260269024Semaste if (result == PacketResult::Success) 261269024Semaste { 262269024Semaste if (packet.GetResponseType() == StringExtractorGDBRemote::ResponseType::eAck) 263269024Semaste return PacketResult::Success; 264269024Semaste else 265269024Semaste return PacketResult::ErrorSendAck; 266269024Semaste } 267269024Semaste return result; 268254721Semaste} 269254721Semaste 270254721Semastebool 271254721SemasteGDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker, const char *failure_message) 272254721Semaste{ 273254721Semaste if (IsRunning()) 274254721Semaste return locker.TryLock (m_sequence_mutex, failure_message); 275254721Semaste 276254721Semaste locker.Lock (m_sequence_mutex); 277254721Semaste return true; 278254721Semaste} 279254721Semaste 280254721Semaste 281254721Semastebool 282254721SemasteGDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr) 283254721Semaste{ 284254721Semaste return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL); 285254721Semaste} 286254721Semaste 287269024SemasteGDBRemoteCommunication::PacketResult 288254721SemasteGDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec) 289254721Semaste{ 290254721Semaste uint8_t buffer[8192]; 291254721Semaste Error error; 292254721Semaste 293254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE)); 294254721Semaste 295254721Semaste // Check for a packet from our cache first without trying any reading... 296254721Semaste if (CheckForPacket (NULL, 0, packet)) 297269024Semaste return PacketResult::Success; 298254721Semaste 299254721Semaste bool timed_out = false; 300269024Semaste bool disconnected = false; 301254721Semaste while (IsConnected() && !timed_out) 302254721Semaste { 303254721Semaste lldb::ConnectionStatus status = eConnectionStatusNoConnection; 304254721Semaste size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); 305254721Semaste 306254721Semaste if (log) 307254721Semaste log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64, 308254721Semaste __PRETTY_FUNCTION__, 309254721Semaste timeout_usec, 310254721Semaste Communication::ConnectionStatusAsCString (status), 311254721Semaste error.AsCString(), 312254721Semaste (uint64_t)bytes_read); 313254721Semaste 314254721Semaste if (bytes_read > 0) 315254721Semaste { 316254721Semaste if (CheckForPacket (buffer, bytes_read, packet)) 317269024Semaste return PacketResult::Success; 318254721Semaste } 319254721Semaste else 320254721Semaste { 321254721Semaste switch (status) 322254721Semaste { 323254721Semaste case eConnectionStatusTimedOut: 324254721Semaste timed_out = true; 325254721Semaste break; 326254721Semaste case eConnectionStatusSuccess: 327254721Semaste //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); 328254721Semaste break; 329254721Semaste 330254721Semaste case eConnectionStatusEndOfFile: 331254721Semaste case eConnectionStatusNoConnection: 332254721Semaste case eConnectionStatusLostConnection: 333254721Semaste case eConnectionStatusError: 334269024Semaste disconnected = true; 335254721Semaste Disconnect(); 336254721Semaste break; 337254721Semaste } 338254721Semaste } 339254721Semaste } 340269024Semaste packet.Clear (); 341269024Semaste if (disconnected) 342269024Semaste return PacketResult::ErrorDisconnected; 343269024Semaste if (timed_out) 344269024Semaste return PacketResult::ErrorReplyTimeout; 345269024Semaste else 346269024Semaste return PacketResult::ErrorReplyFailed; 347254721Semaste} 348254721Semaste 349254721Semastebool 350254721SemasteGDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet) 351254721Semaste{ 352254721Semaste // Put the packet data into the buffer in a thread safe fashion 353254721Semaste Mutex::Locker locker(m_bytes_mutex); 354254721Semaste 355254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 356254721Semaste 357254721Semaste if (src && src_len > 0) 358254721Semaste { 359254721Semaste if (log && log->GetVerbose()) 360254721Semaste { 361254721Semaste StreamString s; 362254721Semaste log->Printf ("GDBRemoteCommunication::%s adding %u bytes: %.*s", 363254721Semaste __FUNCTION__, 364254721Semaste (uint32_t)src_len, 365254721Semaste (uint32_t)src_len, 366254721Semaste src); 367254721Semaste } 368254721Semaste m_bytes.append ((const char *)src, src_len); 369254721Semaste } 370254721Semaste 371254721Semaste // Parse up the packets into gdb remote packets 372254721Semaste if (!m_bytes.empty()) 373254721Semaste { 374254721Semaste // end_idx must be one past the last valid packet byte. Start 375254721Semaste // it off with an invalid value that is the same as the current 376254721Semaste // index. 377254721Semaste size_t content_start = 0; 378254721Semaste size_t content_length = 0; 379254721Semaste size_t total_length = 0; 380254721Semaste size_t checksum_idx = std::string::npos; 381254721Semaste 382254721Semaste switch (m_bytes[0]) 383254721Semaste { 384254721Semaste case '+': // Look for ack 385254721Semaste case '-': // Look for cancel 386254721Semaste case '\x03': // ^C to halt target 387254721Semaste content_length = total_length = 1; // The command is one byte long... 388254721Semaste break; 389254721Semaste 390254721Semaste case '$': 391254721Semaste // Look for a standard gdb packet? 392254721Semaste { 393254721Semaste size_t hash_pos = m_bytes.find('#'); 394254721Semaste if (hash_pos != std::string::npos) 395254721Semaste { 396254721Semaste if (hash_pos + 2 < m_bytes.size()) 397254721Semaste { 398254721Semaste checksum_idx = hash_pos + 1; 399254721Semaste // Skip the dollar sign 400254721Semaste content_start = 1; 401254721Semaste // Don't include the # in the content or the $ in the content length 402254721Semaste content_length = hash_pos - 1; 403254721Semaste 404254721Semaste total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes 405254721Semaste } 406254721Semaste else 407254721Semaste { 408254721Semaste // Checksum bytes aren't all here yet 409254721Semaste content_length = std::string::npos; 410254721Semaste } 411254721Semaste } 412254721Semaste } 413254721Semaste break; 414254721Semaste 415254721Semaste default: 416254721Semaste { 417254721Semaste // We have an unexpected byte and we need to flush all bad 418254721Semaste // data that is in m_bytes, so we need to find the first 419254721Semaste // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt), 420254721Semaste // or '$' character (start of packet header) or of course, 421254721Semaste // the end of the data in m_bytes... 422254721Semaste const size_t bytes_len = m_bytes.size(); 423254721Semaste bool done = false; 424254721Semaste uint32_t idx; 425254721Semaste for (idx = 1; !done && idx < bytes_len; ++idx) 426254721Semaste { 427254721Semaste switch (m_bytes[idx]) 428254721Semaste { 429254721Semaste case '+': 430254721Semaste case '-': 431254721Semaste case '\x03': 432254721Semaste case '$': 433254721Semaste done = true; 434254721Semaste break; 435254721Semaste 436254721Semaste default: 437254721Semaste break; 438254721Semaste } 439254721Semaste } 440254721Semaste if (log) 441254721Semaste log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", 442254721Semaste __FUNCTION__, idx, idx, m_bytes.c_str()); 443254721Semaste m_bytes.erase(0, idx); 444254721Semaste } 445254721Semaste break; 446254721Semaste } 447254721Semaste 448254721Semaste if (content_length == std::string::npos) 449254721Semaste { 450254721Semaste packet.Clear(); 451254721Semaste return false; 452254721Semaste } 453254721Semaste else if (total_length > 0) 454254721Semaste { 455254721Semaste 456254721Semaste // We have a valid packet... 457254721Semaste assert (content_length <= m_bytes.size()); 458254721Semaste assert (total_length <= m_bytes.size()); 459254721Semaste assert (content_length <= total_length); 460254721Semaste 461254721Semaste bool success = true; 462254721Semaste std::string &packet_str = packet.GetStringRef(); 463254721Semaste 464254721Semaste 465254721Semaste if (log) 466254721Semaste { 467254721Semaste // If logging was just enabled and we have history, then dump out what 468254721Semaste // we have to the log so we get the historical context. The Dump() call that 469254721Semaste // logs all of the packet will set a boolean so that we don't dump this more 470254721Semaste // than once 471254721Semaste if (!m_history.DidDumpToLog ()) 472254721Semaste m_history.Dump (log); 473254721Semaste 474263363Semaste log->Printf("<%4" PRIu64 "> read packet: %.*s", (uint64_t)total_length, (int)(total_length), m_bytes.c_str()); 475254721Semaste } 476254721Semaste 477254721Semaste m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length); 478254721Semaste 479263363Semaste // Clear packet_str in case there is some existing data in it. 480263363Semaste packet_str.clear(); 481263363Semaste // Copy the packet from m_bytes to packet_str expanding the 482263363Semaste // run-length encoding in the process. 483263363Semaste // Reserve enough byte for the most common case (no RLE used) 484263363Semaste packet_str.reserve(m_bytes.length()); 485263363Semaste for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_start + content_length; ++c) 486263363Semaste { 487263363Semaste if (*c == '*') 488263363Semaste { 489263363Semaste // '*' indicates RLE. Next character will give us the 490263363Semaste // repeat count and previous character is what is to be 491263363Semaste // repeated. 492263363Semaste char char_to_repeat = packet_str.back(); 493263363Semaste // Number of time the previous character is repeated 494263363Semaste int repeat_count = *++c + 3 - ' '; 495263363Semaste // We have the char_to_repeat and repeat_count. Now push 496263363Semaste // it in the packet. 497263363Semaste for (int i = 0; i < repeat_count; ++i) 498263363Semaste packet_str.push_back(char_to_repeat); 499263363Semaste } 500269024Semaste else if (*c == 0x7d) 501269024Semaste { 502269024Semaste // 0x7d is the escape character. The next character is to 503269024Semaste // be XOR'd with 0x20. 504269024Semaste char escapee = *++c ^ 0x20; 505269024Semaste packet_str.push_back(escapee); 506269024Semaste } 507263363Semaste else 508263363Semaste { 509263363Semaste packet_str.push_back(*c); 510263363Semaste } 511263363Semaste } 512263363Semaste 513254721Semaste if (m_bytes[0] == '$') 514254721Semaste { 515254721Semaste assert (checksum_idx < m_bytes.size()); 516254721Semaste if (::isxdigit (m_bytes[checksum_idx+0]) || 517254721Semaste ::isxdigit (m_bytes[checksum_idx+1])) 518254721Semaste { 519254721Semaste if (GetSendAcks ()) 520254721Semaste { 521254721Semaste const char *packet_checksum_cstr = &m_bytes[checksum_idx]; 522254721Semaste char packet_checksum = strtol (packet_checksum_cstr, NULL, 16); 523254721Semaste char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size()); 524254721Semaste success = packet_checksum == actual_checksum; 525254721Semaste if (!success) 526254721Semaste { 527254721Semaste if (log) 528254721Semaste log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", 529254721Semaste (int)(total_length), 530254721Semaste m_bytes.c_str(), 531254721Semaste (uint8_t)packet_checksum, 532254721Semaste (uint8_t)actual_checksum); 533254721Semaste } 534254721Semaste // Send the ack or nack if needed 535254721Semaste if (!success) 536254721Semaste SendNack(); 537254721Semaste else 538254721Semaste SendAck(); 539254721Semaste } 540254721Semaste } 541254721Semaste else 542254721Semaste { 543254721Semaste success = false; 544254721Semaste if (log) 545254721Semaste log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str()); 546254721Semaste } 547254721Semaste } 548254721Semaste 549254721Semaste m_bytes.erase(0, total_length); 550254721Semaste packet.SetFilePos(0); 551254721Semaste return success; 552254721Semaste } 553254721Semaste } 554254721Semaste packet.Clear(); 555254721Semaste return false; 556254721Semaste} 557254721Semaste 558254721SemasteError 559269024SemasteGDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port) 560254721Semaste{ 561254721Semaste Error error; 562269024Semaste if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread)) 563269024Semaste { 564269024Semaste error.SetErrorString("listen thread already running"); 565269024Semaste } 566269024Semaste else 567269024Semaste { 568269024Semaste char listen_url[512]; 569269024Semaste if (hostname && hostname[0]) 570269024Semaste snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port); 571269024Semaste else 572269024Semaste snprintf(listen_url, sizeof(listen_url), "listen://%i", port); 573269024Semaste m_listen_url = listen_url; 574269024Semaste SetConnection(new ConnectionFileDescriptor()); 575269024Semaste m_listen_thread = Host::ThreadCreate (listen_url, GDBRemoteCommunication::ListenThread, this, &error); 576269024Semaste } 577269024Semaste return error; 578269024Semaste} 579269024Semaste 580269024Semastebool 581269024SemasteGDBRemoteCommunication::JoinListenThread () 582269024Semaste{ 583269024Semaste if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread)) 584269024Semaste { 585269024Semaste Host::ThreadJoin(m_listen_thread, NULL, NULL); 586269024Semaste m_listen_thread = LLDB_INVALID_HOST_THREAD; 587269024Semaste } 588269024Semaste return true; 589269024Semaste} 590269024Semaste 591269024Semastelldb::thread_result_t 592269024SemasteGDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg) 593269024Semaste{ 594269024Semaste GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg; 595269024Semaste Error error; 596269024Semaste ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)comm->GetConnection (); 597269024Semaste 598269024Semaste if (connection) 599269024Semaste { 600269024Semaste // Do the listen on another thread so we can continue on... 601269024Semaste if (connection->Connect(comm->m_listen_url.c_str(), &error) != eConnectionStatusSuccess) 602269024Semaste comm->SetConnection(NULL); 603269024Semaste } 604269024Semaste return NULL; 605269024Semaste} 606269024Semaste 607269024SemasteError 608269024SemasteGDBRemoteCommunication::StartDebugserverProcess (const char *hostname, 609269024Semaste uint16_t in_port, 610269024Semaste lldb_private::ProcessLaunchInfo &launch_info, 611269024Semaste uint16_t &out_port) 612269024Semaste{ 613269024Semaste out_port = in_port; 614269024Semaste Error error; 615254721Semaste // If we locate debugserver, keep that located version around 616254721Semaste static FileSpec g_debugserver_file_spec; 617254721Semaste 618254721Semaste char debugserver_path[PATH_MAX]; 619254721Semaste FileSpec &debugserver_file_spec = launch_info.GetExecutableFile(); 620254721Semaste 621254721Semaste // Always check to see if we have an environment override for the path 622254721Semaste // to the debugserver to use and use it if we do. 623254721Semaste const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH"); 624254721Semaste if (env_debugserver_path) 625254721Semaste debugserver_file_spec.SetFile (env_debugserver_path, false); 626254721Semaste else 627254721Semaste debugserver_file_spec = g_debugserver_file_spec; 628254721Semaste bool debugserver_exists = debugserver_file_spec.Exists(); 629254721Semaste if (!debugserver_exists) 630254721Semaste { 631254721Semaste // The debugserver binary is in the LLDB.framework/Resources 632254721Semaste // directory. 633254721Semaste if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec)) 634254721Semaste { 635254721Semaste debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME); 636254721Semaste debugserver_exists = debugserver_file_spec.Exists(); 637254721Semaste if (debugserver_exists) 638254721Semaste { 639254721Semaste g_debugserver_file_spec = debugserver_file_spec; 640254721Semaste } 641254721Semaste else 642254721Semaste { 643254721Semaste g_debugserver_file_spec.Clear(); 644254721Semaste debugserver_file_spec.Clear(); 645254721Semaste } 646254721Semaste } 647254721Semaste } 648254721Semaste 649254721Semaste if (debugserver_exists) 650254721Semaste { 651254721Semaste debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path)); 652254721Semaste 653254721Semaste Args &debugserver_args = launch_info.GetArguments(); 654254721Semaste debugserver_args.Clear(); 655254721Semaste char arg_cstr[PATH_MAX]; 656254721Semaste 657254721Semaste // Start args with "debugserver /file/path -r --" 658254721Semaste debugserver_args.AppendArgument(debugserver_path); 659269024Semaste 660269024Semaste // If a host and port is supplied then use it 661269024Semaste char host_and_port[128]; 662269024Semaste if (hostname) 663269024Semaste { 664269024Semaste snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port); 665269024Semaste debugserver_args.AppendArgument(host_and_port); 666269024Semaste } 667269024Semaste else 668269024Semaste { 669269024Semaste host_and_port[0] = '\0'; 670269024Semaste } 671269024Semaste 672254721Semaste // use native registers, not the GDB registers 673254721Semaste debugserver_args.AppendArgument("--native-regs"); 674254721Semaste // make debugserver run in its own session so signals generated by 675254721Semaste // special terminal key sequences (^C) don't affect debugserver 676254721Semaste debugserver_args.AppendArgument("--setsid"); 677269024Semaste 678269024Semaste char named_pipe_path[PATH_MAX]; 679269024Semaste named_pipe_path[0] = '\0'; 680269024Semaste 681269024Semaste bool listen = false; 682269024Semaste if (host_and_port[0]) 683254721Semaste { 684269024Semaste // Create a temporary file to get the stdout/stderr and redirect the 685269024Semaste // output of the command into this file. We will later read this file 686269024Semaste // if all goes well and fill the data into "command_output_ptr" 687269024Semaste 688269024Semaste if (in_port == 0) 689269024Semaste { 690269024Semaste // Binding to port zero, we need to figure out what port it ends up 691269024Semaste // using using a named pipe... 692269024Semaste FileSpec tmpdir_file_spec; 693269024Semaste if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) 694269024Semaste { 695269024Semaste tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX"); 696269024Semaste strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path)); 697269024Semaste } 698269024Semaste else 699269024Semaste { 700269024Semaste strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path)); 701269024Semaste } 702269024Semaste 703269024Semaste if (::mktemp (named_pipe_path)) 704269024Semaste { 705269024Semaste#if defined(_MSC_VER) 706269024Semaste if ( false ) 707269024Semaste#else 708269024Semaste if (::mkfifo(named_pipe_path, 0600) == 0) 709269024Semaste#endif 710269024Semaste { 711269024Semaste debugserver_args.AppendArgument("--named-pipe"); 712269024Semaste debugserver_args.AppendArgument(named_pipe_path); 713269024Semaste } 714269024Semaste } 715269024Semaste } 716269024Semaste else 717269024Semaste { 718269024Semaste listen = true; 719269024Semaste } 720254721Semaste } 721269024Semaste else 722269024Semaste { 723269024Semaste // No host and port given, so lets listen on our end and make the debugserver 724269024Semaste // connect to us.. 725269024Semaste error = StartListenThread ("localhost", 0); 726269024Semaste if (error.Fail()) 727269024Semaste return error; 728254721Semaste 729269024Semaste ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection (); 730269024Semaste out_port = connection->GetBoundPort(3); 731269024Semaste assert (out_port != 0); 732269024Semaste char port_cstr[32]; 733269024Semaste snprintf(port_cstr, sizeof(port_cstr), "localhost:%i", out_port); 734269024Semaste // Send the host and port down that debugserver and specify an option 735269024Semaste // so that it connects back to the port we are listening to in this process 736269024Semaste debugserver_args.AppendArgument("--reverse-connect"); 737269024Semaste debugserver_args.AppendArgument(port_cstr); 738269024Semaste } 739269024Semaste 740269024Semaste 741254721Semaste const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE"); 742254721Semaste if (env_debugserver_log_file) 743254721Semaste { 744254721Semaste ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file); 745254721Semaste debugserver_args.AppendArgument(arg_cstr); 746254721Semaste } 747254721Semaste 748254721Semaste const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS"); 749254721Semaste if (env_debugserver_log_flags) 750254721Semaste { 751254721Semaste ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags); 752254721Semaste debugserver_args.AppendArgument(arg_cstr); 753254721Semaste } 754254721Semaste 755269024Semaste // Close STDIN, STDOUT and STDERR. We might need to redirect them 756269024Semaste // to "/dev/null" if we run into any problems. 757269024Semaste launch_info.AppendCloseFileAction (STDIN_FILENO); 758269024Semaste launch_info.AppendCloseFileAction (STDOUT_FILENO); 759269024Semaste launch_info.AppendCloseFileAction (STDERR_FILENO); 760269024Semaste 761269024Semaste error = Host::LaunchProcess(launch_info); 762269024Semaste 763269024Semaste if (named_pipe_path[0]) 764254721Semaste { 765269024Semaste File name_pipe_file; 766269024Semaste error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead); 767269024Semaste if (error.Success()) 768269024Semaste { 769269024Semaste char port_cstr[256]; 770269024Semaste port_cstr[0] = '\0'; 771269024Semaste size_t num_bytes = sizeof(port_cstr); 772269024Semaste error = name_pipe_file.Read(port_cstr, num_bytes); 773269024Semaste assert (error.Success()); 774269024Semaste assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); 775269024Semaste out_port = Args::StringToUInt32(port_cstr, 0); 776269024Semaste name_pipe_file.Close(); 777269024Semaste } 778269024Semaste Host::Unlink(named_pipe_path); 779254721Semaste } 780269024Semaste else if (listen) 781254721Semaste { 782269024Semaste 783254721Semaste } 784269024Semaste else 785254721Semaste { 786269024Semaste // Make sure we actually connect with the debugserver... 787269024Semaste JoinListenThread(); 788254721Semaste } 789254721Semaste } 790254721Semaste else 791254721Semaste { 792254721Semaste error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME ); 793254721Semaste } 794254721Semaste return error; 795254721Semaste} 796254721Semaste 797254721Semastevoid 798254721SemasteGDBRemoteCommunication::DumpHistory(Stream &strm) 799254721Semaste{ 800254721Semaste m_history.Dump (strm); 801254721Semaste} 802