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> 16254721Semaste 17254721Semaste// C++ Includes 18254721Semaste// Other libraries and framework includes 19254721Semaste#include "lldb/Core/Log.h" 20254721Semaste#include "lldb/Core/StreamFile.h" 21254721Semaste#include "lldb/Core/StreamString.h" 22254721Semaste#include "lldb/Host/FileSpec.h" 23254721Semaste#include "lldb/Host/Host.h" 24254721Semaste#include "lldb/Host/TimeValue.h" 25254721Semaste#include "lldb/Target/Process.h" 26254721Semaste 27254721Semaste// Project includes 28254721Semaste#include "ProcessGDBRemoteLog.h" 29254721Semaste 30254721Semaste#define DEBUGSERVER_BASENAME "debugserver" 31254721Semaste 32254721Semasteusing namespace lldb; 33254721Semasteusing namespace lldb_private; 34254721Semaste 35254721SemasteGDBRemoteCommunication::History::History (uint32_t size) : 36254721Semaste m_packets(), 37254721Semaste m_curr_idx (0), 38254721Semaste m_total_packet_count (0), 39254721Semaste m_dumped_to_log (false) 40254721Semaste{ 41254721Semaste m_packets.resize(size); 42254721Semaste} 43254721Semaste 44254721SemasteGDBRemoteCommunication::History::~History () 45254721Semaste{ 46254721Semaste} 47254721Semaste 48254721Semastevoid 49254721SemasteGDBRemoteCommunication::History::AddPacket (char packet_char, 50254721Semaste PacketType type, 51254721Semaste uint32_t bytes_transmitted) 52254721Semaste{ 53254721Semaste const size_t size = m_packets.size(); 54254721Semaste if (size > 0) 55254721Semaste { 56254721Semaste const uint32_t idx = GetNextIndex(); 57254721Semaste m_packets[idx].packet.assign (1, packet_char); 58254721Semaste m_packets[idx].type = type; 59254721Semaste m_packets[idx].bytes_transmitted = bytes_transmitted; 60254721Semaste m_packets[idx].packet_idx = m_total_packet_count; 61254721Semaste m_packets[idx].tid = Host::GetCurrentThreadID(); 62254721Semaste } 63254721Semaste} 64254721Semaste 65254721Semastevoid 66254721SemasteGDBRemoteCommunication::History::AddPacket (const std::string &src, 67254721Semaste uint32_t src_len, 68254721Semaste PacketType type, 69254721Semaste uint32_t bytes_transmitted) 70254721Semaste{ 71254721Semaste const size_t size = m_packets.size(); 72254721Semaste if (size > 0) 73254721Semaste { 74254721Semaste const uint32_t idx = GetNextIndex(); 75254721Semaste m_packets[idx].packet.assign (src, 0, src_len); 76254721Semaste m_packets[idx].type = type; 77254721Semaste m_packets[idx].bytes_transmitted = bytes_transmitted; 78254721Semaste m_packets[idx].packet_idx = m_total_packet_count; 79254721Semaste m_packets[idx].tid = Host::GetCurrentThreadID(); 80254721Semaste } 81254721Semaste} 82254721Semaste 83254721Semastevoid 84254721SemasteGDBRemoteCommunication::History::Dump (lldb_private::Stream &strm) const 85254721Semaste{ 86254721Semaste const uint32_t size = GetNumPacketsInHistory (); 87254721Semaste const uint32_t first_idx = GetFirstSavedPacketIndex (); 88254721Semaste const uint32_t stop_idx = m_curr_idx + size; 89254721Semaste for (uint32_t i = first_idx; i < stop_idx; ++i) 90254721Semaste { 91254721Semaste const uint32_t idx = NormalizeIndex (i); 92254721Semaste const Entry &entry = m_packets[idx]; 93254721Semaste if (entry.type == ePacketTypeInvalid || entry.packet.empty()) 94254721Semaste break; 95254721Semaste strm.Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n", 96254721Semaste entry.packet_idx, 97254721Semaste entry.tid, 98254721Semaste entry.bytes_transmitted, 99254721Semaste (entry.type == ePacketTypeSend) ? "send" : "read", 100254721Semaste entry.packet.c_str()); 101254721Semaste } 102254721Semaste} 103254721Semaste 104254721Semastevoid 105254721SemasteGDBRemoteCommunication::History::Dump (lldb_private::Log *log) const 106254721Semaste{ 107254721Semaste if (log && !m_dumped_to_log) 108254721Semaste { 109254721Semaste m_dumped_to_log = true; 110254721Semaste const uint32_t size = GetNumPacketsInHistory (); 111254721Semaste const uint32_t first_idx = GetFirstSavedPacketIndex (); 112254721Semaste const uint32_t stop_idx = m_curr_idx + size; 113254721Semaste for (uint32_t i = first_idx; i < stop_idx; ++i) 114254721Semaste { 115254721Semaste const uint32_t idx = NormalizeIndex (i); 116254721Semaste const Entry &entry = m_packets[idx]; 117254721Semaste if (entry.type == ePacketTypeInvalid || entry.packet.empty()) 118254721Semaste break; 119254721Semaste log->Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s", 120254721Semaste entry.packet_idx, 121254721Semaste entry.tid, 122254721Semaste entry.bytes_transmitted, 123254721Semaste (entry.type == ePacketTypeSend) ? "send" : "read", 124254721Semaste entry.packet.c_str()); 125254721Semaste } 126254721Semaste } 127254721Semaste} 128254721Semaste 129254721Semaste//---------------------------------------------------------------------- 130254721Semaste// GDBRemoteCommunication constructor 131254721Semaste//---------------------------------------------------------------------- 132254721SemasteGDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, 133254721Semaste const char *listener_name, 134254721Semaste bool is_platform) : 135254721Semaste Communication(comm_name), 136254721Semaste m_packet_timeout (1), 137254721Semaste m_sequence_mutex (Mutex::eMutexTypeRecursive), 138254721Semaste m_public_is_running (false), 139254721Semaste m_private_is_running (false), 140254721Semaste m_history (512), 141254721Semaste m_send_acks (true), 142254721Semaste m_is_platform (is_platform) 143254721Semaste{ 144254721Semaste} 145254721Semaste 146254721Semaste//---------------------------------------------------------------------- 147254721Semaste// Destructor 148254721Semaste//---------------------------------------------------------------------- 149254721SemasteGDBRemoteCommunication::~GDBRemoteCommunication() 150254721Semaste{ 151254721Semaste if (IsConnected()) 152254721Semaste { 153254721Semaste Disconnect(); 154254721Semaste } 155254721Semaste} 156254721Semaste 157254721Semastechar 158254721SemasteGDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length) 159254721Semaste{ 160254721Semaste int checksum = 0; 161254721Semaste 162254721Semaste for (size_t i = 0; i < payload_length; ++i) 163254721Semaste checksum += payload[i]; 164254721Semaste 165254721Semaste return checksum & 255; 166254721Semaste} 167254721Semaste 168254721Semastesize_t 169254721SemasteGDBRemoteCommunication::SendAck () 170254721Semaste{ 171254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 172254721Semaste ConnectionStatus status = eConnectionStatusSuccess; 173254721Semaste char ch = '+'; 174254721Semaste const size_t bytes_written = Write (&ch, 1, status, NULL); 175254721Semaste if (log) 176254721Semaste log->Printf ("<%4zu> send packet: %c", bytes_written, ch); 177254721Semaste m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written); 178254721Semaste return bytes_written; 179254721Semaste} 180254721Semaste 181254721Semastesize_t 182254721SemasteGDBRemoteCommunication::SendNack () 183254721Semaste{ 184254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 185254721Semaste ConnectionStatus status = eConnectionStatusSuccess; 186254721Semaste char ch = '-'; 187254721Semaste const size_t bytes_written = Write (&ch, 1, status, NULL); 188254721Semaste if (log) 189254721Semaste log->Printf ("<%4zu> send packet: %c", bytes_written, ch); 190254721Semaste m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written); 191254721Semaste return bytes_written; 192254721Semaste} 193254721Semaste 194254721Semastesize_t 195254721SemasteGDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length) 196254721Semaste{ 197254721Semaste Mutex::Locker locker(m_sequence_mutex); 198254721Semaste return SendPacketNoLock (payload, payload_length); 199254721Semaste} 200254721Semaste 201254721Semastesize_t 202254721SemasteGDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length) 203254721Semaste{ 204254721Semaste if (IsConnected()) 205254721Semaste { 206254721Semaste StreamString packet(0, 4, eByteOrderBig); 207254721Semaste 208254721Semaste packet.PutChar('$'); 209254721Semaste packet.Write (payload, payload_length); 210254721Semaste packet.PutChar('#'); 211254721Semaste packet.PutHex8(CalculcateChecksum (payload, payload_length)); 212254721Semaste 213254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 214254721Semaste ConnectionStatus status = eConnectionStatusSuccess; 215254721Semaste size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); 216254721Semaste if (log) 217254721Semaste { 218254721Semaste // If logging was just enabled and we have history, then dump out what 219254721Semaste // we have to the log so we get the historical context. The Dump() call that 220254721Semaste // logs all of the packet will set a boolean so that we don't dump this more 221254721Semaste // than once 222254721Semaste if (!m_history.DidDumpToLog ()) 223254721Semaste m_history.Dump (log); 224254721Semaste 225254721Semaste log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData()); 226254721Semaste } 227254721Semaste 228254721Semaste m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written); 229254721Semaste 230254721Semaste 231254721Semaste if (bytes_written == packet.GetSize()) 232254721Semaste { 233254721Semaste if (GetSendAcks ()) 234254721Semaste { 235254721Semaste if (GetAck () != '+') 236254721Semaste { 237254721Semaste if (log) 238254721Semaste log->Printf("get ack failed..."); 239254721Semaste return 0; 240254721Semaste } 241254721Semaste } 242254721Semaste } 243254721Semaste else 244254721Semaste { 245254721Semaste if (log) 246254721Semaste log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData()); 247254721Semaste } 248254721Semaste return bytes_written; 249254721Semaste } 250254721Semaste return 0; 251254721Semaste} 252254721Semaste 253254721Semastechar 254254721SemasteGDBRemoteCommunication::GetAck () 255254721Semaste{ 256254721Semaste StringExtractorGDBRemote packet; 257254721Semaste if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds ()) == 1) 258254721Semaste return packet.GetChar(); 259254721Semaste return 0; 260254721Semaste} 261254721Semaste 262254721Semastebool 263254721SemasteGDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker, const char *failure_message) 264254721Semaste{ 265254721Semaste if (IsRunning()) 266254721Semaste return locker.TryLock (m_sequence_mutex, failure_message); 267254721Semaste 268254721Semaste locker.Lock (m_sequence_mutex); 269254721Semaste return true; 270254721Semaste} 271254721Semaste 272254721Semaste 273254721Semastebool 274254721SemasteGDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr) 275254721Semaste{ 276254721Semaste return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL); 277254721Semaste} 278254721Semaste 279254721Semastesize_t 280254721SemasteGDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec) 281254721Semaste{ 282254721Semaste uint8_t buffer[8192]; 283254721Semaste Error error; 284254721Semaste 285254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE)); 286254721Semaste 287254721Semaste // Check for a packet from our cache first without trying any reading... 288254721Semaste if (CheckForPacket (NULL, 0, packet)) 289254721Semaste return packet.GetStringRef().size(); 290254721Semaste 291254721Semaste bool timed_out = false; 292254721Semaste while (IsConnected() && !timed_out) 293254721Semaste { 294254721Semaste lldb::ConnectionStatus status = eConnectionStatusNoConnection; 295254721Semaste size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); 296254721Semaste 297254721Semaste if (log) 298254721Semaste log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64, 299254721Semaste __PRETTY_FUNCTION__, 300254721Semaste timeout_usec, 301254721Semaste Communication::ConnectionStatusAsCString (status), 302254721Semaste error.AsCString(), 303254721Semaste (uint64_t)bytes_read); 304254721Semaste 305254721Semaste if (bytes_read > 0) 306254721Semaste { 307254721Semaste if (CheckForPacket (buffer, bytes_read, packet)) 308254721Semaste return packet.GetStringRef().size(); 309254721Semaste } 310254721Semaste else 311254721Semaste { 312254721Semaste switch (status) 313254721Semaste { 314254721Semaste case eConnectionStatusTimedOut: 315254721Semaste timed_out = true; 316254721Semaste break; 317254721Semaste case eConnectionStatusSuccess: 318254721Semaste //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); 319254721Semaste break; 320254721Semaste 321254721Semaste case eConnectionStatusEndOfFile: 322254721Semaste case eConnectionStatusNoConnection: 323254721Semaste case eConnectionStatusLostConnection: 324254721Semaste case eConnectionStatusError: 325254721Semaste Disconnect(); 326254721Semaste break; 327254721Semaste } 328254721Semaste } 329254721Semaste } 330254721Semaste packet.Clear (); 331254721Semaste return 0; 332254721Semaste} 333254721Semaste 334254721Semastebool 335254721SemasteGDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet) 336254721Semaste{ 337254721Semaste // Put the packet data into the buffer in a thread safe fashion 338254721Semaste Mutex::Locker locker(m_bytes_mutex); 339254721Semaste 340254721Semaste Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); 341254721Semaste 342254721Semaste if (src && src_len > 0) 343254721Semaste { 344254721Semaste if (log && log->GetVerbose()) 345254721Semaste { 346254721Semaste StreamString s; 347254721Semaste log->Printf ("GDBRemoteCommunication::%s adding %u bytes: %.*s", 348254721Semaste __FUNCTION__, 349254721Semaste (uint32_t)src_len, 350254721Semaste (uint32_t)src_len, 351254721Semaste src); 352254721Semaste } 353254721Semaste m_bytes.append ((const char *)src, src_len); 354254721Semaste } 355254721Semaste 356254721Semaste // Parse up the packets into gdb remote packets 357254721Semaste if (!m_bytes.empty()) 358254721Semaste { 359254721Semaste // end_idx must be one past the last valid packet byte. Start 360254721Semaste // it off with an invalid value that is the same as the current 361254721Semaste // index. 362254721Semaste size_t content_start = 0; 363254721Semaste size_t content_length = 0; 364254721Semaste size_t total_length = 0; 365254721Semaste size_t checksum_idx = std::string::npos; 366254721Semaste 367254721Semaste switch (m_bytes[0]) 368254721Semaste { 369254721Semaste case '+': // Look for ack 370254721Semaste case '-': // Look for cancel 371254721Semaste case '\x03': // ^C to halt target 372254721Semaste content_length = total_length = 1; // The command is one byte long... 373254721Semaste break; 374254721Semaste 375254721Semaste case '$': 376254721Semaste // Look for a standard gdb packet? 377254721Semaste { 378254721Semaste size_t hash_pos = m_bytes.find('#'); 379254721Semaste if (hash_pos != std::string::npos) 380254721Semaste { 381254721Semaste if (hash_pos + 2 < m_bytes.size()) 382254721Semaste { 383254721Semaste checksum_idx = hash_pos + 1; 384254721Semaste // Skip the dollar sign 385254721Semaste content_start = 1; 386254721Semaste // Don't include the # in the content or the $ in the content length 387254721Semaste content_length = hash_pos - 1; 388254721Semaste 389254721Semaste total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes 390254721Semaste } 391254721Semaste else 392254721Semaste { 393254721Semaste // Checksum bytes aren't all here yet 394254721Semaste content_length = std::string::npos; 395254721Semaste } 396254721Semaste } 397254721Semaste } 398254721Semaste break; 399254721Semaste 400254721Semaste default: 401254721Semaste { 402254721Semaste // We have an unexpected byte and we need to flush all bad 403254721Semaste // data that is in m_bytes, so we need to find the first 404254721Semaste // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt), 405254721Semaste // or '$' character (start of packet header) or of course, 406254721Semaste // the end of the data in m_bytes... 407254721Semaste const size_t bytes_len = m_bytes.size(); 408254721Semaste bool done = false; 409254721Semaste uint32_t idx; 410254721Semaste for (idx = 1; !done && idx < bytes_len; ++idx) 411254721Semaste { 412254721Semaste switch (m_bytes[idx]) 413254721Semaste { 414254721Semaste case '+': 415254721Semaste case '-': 416254721Semaste case '\x03': 417254721Semaste case '$': 418254721Semaste done = true; 419254721Semaste break; 420254721Semaste 421254721Semaste default: 422254721Semaste break; 423254721Semaste } 424254721Semaste } 425254721Semaste if (log) 426254721Semaste log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", 427254721Semaste __FUNCTION__, idx, idx, m_bytes.c_str()); 428254721Semaste m_bytes.erase(0, idx); 429254721Semaste } 430254721Semaste break; 431254721Semaste } 432254721Semaste 433254721Semaste if (content_length == std::string::npos) 434254721Semaste { 435254721Semaste packet.Clear(); 436254721Semaste return false; 437254721Semaste } 438254721Semaste else if (total_length > 0) 439254721Semaste { 440254721Semaste 441254721Semaste // We have a valid packet... 442254721Semaste assert (content_length <= m_bytes.size()); 443254721Semaste assert (total_length <= m_bytes.size()); 444254721Semaste assert (content_length <= total_length); 445254721Semaste 446254721Semaste bool success = true; 447254721Semaste std::string &packet_str = packet.GetStringRef(); 448254721Semaste 449254721Semaste 450254721Semaste if (log) 451254721Semaste { 452254721Semaste // If logging was just enabled and we have history, then dump out what 453254721Semaste // we have to the log so we get the historical context. The Dump() call that 454254721Semaste // logs all of the packet will set a boolean so that we don't dump this more 455254721Semaste // than once 456254721Semaste if (!m_history.DidDumpToLog ()) 457254721Semaste m_history.Dump (log); 458254721Semaste 459254721Semaste log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str()); 460254721Semaste } 461254721Semaste 462254721Semaste m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length); 463254721Semaste 464254721Semaste packet_str.assign (m_bytes, content_start, content_length); 465254721Semaste 466254721Semaste if (m_bytes[0] == '$') 467254721Semaste { 468254721Semaste assert (checksum_idx < m_bytes.size()); 469254721Semaste if (::isxdigit (m_bytes[checksum_idx+0]) || 470254721Semaste ::isxdigit (m_bytes[checksum_idx+1])) 471254721Semaste { 472254721Semaste if (GetSendAcks ()) 473254721Semaste { 474254721Semaste const char *packet_checksum_cstr = &m_bytes[checksum_idx]; 475254721Semaste char packet_checksum = strtol (packet_checksum_cstr, NULL, 16); 476254721Semaste char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size()); 477254721Semaste success = packet_checksum == actual_checksum; 478254721Semaste if (!success) 479254721Semaste { 480254721Semaste if (log) 481254721Semaste log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", 482254721Semaste (int)(total_length), 483254721Semaste m_bytes.c_str(), 484254721Semaste (uint8_t)packet_checksum, 485254721Semaste (uint8_t)actual_checksum); 486254721Semaste } 487254721Semaste // Send the ack or nack if needed 488254721Semaste if (!success) 489254721Semaste SendNack(); 490254721Semaste else 491254721Semaste SendAck(); 492254721Semaste } 493254721Semaste } 494254721Semaste else 495254721Semaste { 496254721Semaste success = false; 497254721Semaste if (log) 498254721Semaste log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str()); 499254721Semaste } 500254721Semaste } 501254721Semaste 502254721Semaste m_bytes.erase(0, total_length); 503254721Semaste packet.SetFilePos(0); 504254721Semaste return success; 505254721Semaste } 506254721Semaste } 507254721Semaste packet.Clear(); 508254721Semaste return false; 509254721Semaste} 510254721Semaste 511254721SemasteError 512254721SemasteGDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url, 513254721Semaste const char *unix_socket_name, // For handshaking 514254721Semaste lldb_private::ProcessLaunchInfo &launch_info) 515254721Semaste{ 516254721Semaste Error error; 517254721Semaste // If we locate debugserver, keep that located version around 518254721Semaste static FileSpec g_debugserver_file_spec; 519254721Semaste 520254721Semaste // This function will fill in the launch information for the debugserver 521254721Semaste // instance that gets launched. 522254721Semaste launch_info.Clear(); 523254721Semaste 524254721Semaste char debugserver_path[PATH_MAX]; 525254721Semaste FileSpec &debugserver_file_spec = launch_info.GetExecutableFile(); 526254721Semaste 527254721Semaste // Always check to see if we have an environment override for the path 528254721Semaste // to the debugserver to use and use it if we do. 529254721Semaste const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH"); 530254721Semaste if (env_debugserver_path) 531254721Semaste debugserver_file_spec.SetFile (env_debugserver_path, false); 532254721Semaste else 533254721Semaste debugserver_file_spec = g_debugserver_file_spec; 534254721Semaste bool debugserver_exists = debugserver_file_spec.Exists(); 535254721Semaste if (!debugserver_exists) 536254721Semaste { 537254721Semaste // The debugserver binary is in the LLDB.framework/Resources 538254721Semaste // directory. 539254721Semaste if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec)) 540254721Semaste { 541254721Semaste debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME); 542254721Semaste debugserver_exists = debugserver_file_spec.Exists(); 543254721Semaste if (debugserver_exists) 544254721Semaste { 545254721Semaste g_debugserver_file_spec = debugserver_file_spec; 546254721Semaste } 547254721Semaste else 548254721Semaste { 549254721Semaste g_debugserver_file_spec.Clear(); 550254721Semaste debugserver_file_spec.Clear(); 551254721Semaste } 552254721Semaste } 553254721Semaste } 554254721Semaste 555254721Semaste if (debugserver_exists) 556254721Semaste { 557254721Semaste debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path)); 558254721Semaste 559254721Semaste Args &debugserver_args = launch_info.GetArguments(); 560254721Semaste debugserver_args.Clear(); 561254721Semaste char arg_cstr[PATH_MAX]; 562254721Semaste 563254721Semaste // Start args with "debugserver /file/path -r --" 564254721Semaste debugserver_args.AppendArgument(debugserver_path); 565254721Semaste debugserver_args.AppendArgument(debugserver_url); 566254721Semaste // use native registers, not the GDB registers 567254721Semaste debugserver_args.AppendArgument("--native-regs"); 568254721Semaste // make debugserver run in its own session so signals generated by 569254721Semaste // special terminal key sequences (^C) don't affect debugserver 570254721Semaste debugserver_args.AppendArgument("--setsid"); 571254721Semaste 572254721Semaste if (unix_socket_name && unix_socket_name[0]) 573254721Semaste { 574254721Semaste debugserver_args.AppendArgument("--unix-socket"); 575254721Semaste debugserver_args.AppendArgument(unix_socket_name); 576254721Semaste } 577254721Semaste 578254721Semaste const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE"); 579254721Semaste if (env_debugserver_log_file) 580254721Semaste { 581254721Semaste ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file); 582254721Semaste debugserver_args.AppendArgument(arg_cstr); 583254721Semaste } 584254721Semaste 585254721Semaste const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS"); 586254721Semaste if (env_debugserver_log_flags) 587254721Semaste { 588254721Semaste ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags); 589254721Semaste debugserver_args.AppendArgument(arg_cstr); 590254721Semaste } 591254721Semaste // debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt"); 592254721Semaste // debugserver_args.AppendArgument("--log-flags=0x802e0e"); 593254721Semaste 594254721Semaste // We currently send down all arguments, attach pids, or attach 595254721Semaste // process names in dedicated GDB server packets, so we don't need 596254721Semaste // to pass them as arguments. This is currently because of all the 597254721Semaste // things we need to setup prior to launching: the environment, 598254721Semaste // current working dir, file actions, etc. 599254721Semaste#if 0 600254721Semaste // Now append the program arguments 601254721Semaste if (inferior_argv) 602254721Semaste { 603254721Semaste // Terminate the debugserver args so we can now append the inferior args 604254721Semaste debugserver_args.AppendArgument("--"); 605254721Semaste 606254721Semaste for (int i = 0; inferior_argv[i] != NULL; ++i) 607254721Semaste debugserver_args.AppendArgument (inferior_argv[i]); 608254721Semaste } 609254721Semaste else if (attach_pid != LLDB_INVALID_PROCESS_ID) 610254721Semaste { 611254721Semaste ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid); 612254721Semaste debugserver_args.AppendArgument (arg_cstr); 613254721Semaste } 614254721Semaste else if (attach_name && attach_name[0]) 615254721Semaste { 616254721Semaste if (wait_for_launch) 617254721Semaste debugserver_args.AppendArgument ("--waitfor"); 618254721Semaste else 619254721Semaste debugserver_args.AppendArgument ("--attach"); 620254721Semaste debugserver_args.AppendArgument (attach_name); 621254721Semaste } 622254721Semaste#endif 623254721Semaste 624254721Semaste // Close STDIN, STDOUT and STDERR. We might need to redirect them 625254721Semaste // to "/dev/null" if we run into any problems. 626254721Semaste// launch_info.AppendCloseFileAction (STDIN_FILENO); 627254721Semaste// launch_info.AppendCloseFileAction (STDOUT_FILENO); 628254721Semaste// launch_info.AppendCloseFileAction (STDERR_FILENO); 629254721Semaste 630254721Semaste error = Host::LaunchProcess(launch_info); 631254721Semaste } 632254721Semaste else 633254721Semaste { 634254721Semaste error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME ); 635254721Semaste } 636254721Semaste return error; 637254721Semaste} 638254721Semaste 639254721Semastevoid 640254721SemasteGDBRemoteCommunication::DumpHistory(Stream &strm) 641254721Semaste{ 642254721Semaste m_history.Dump (strm); 643254721Semaste} 644