1254721Semaste//===-- GDBRemoteCommunicationServer.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 "GDBRemoteCommunicationServer.h" 12254721Semaste 13254721Semaste// C Includes 14254721Semaste// C++ Includes 15254721Semaste// Other libraries and framework includes 16254721Semaste#include "llvm/ADT/Triple.h" 17254721Semaste#include "lldb/Interpreter/Args.h" 18254721Semaste#include "lldb/Core/ConnectionFileDescriptor.h" 19254721Semaste#include "lldb/Core/Log.h" 20254721Semaste#include "lldb/Core/State.h" 21254721Semaste#include "lldb/Core/StreamString.h" 22254721Semaste#include "lldb/Host/Endian.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 "Utility/StringExtractorGDBRemote.h" 29254721Semaste#include "ProcessGDBRemote.h" 30254721Semaste#include "ProcessGDBRemoteLog.h" 31254721Semaste 32254721Semasteusing namespace lldb; 33254721Semasteusing namespace lldb_private; 34254721Semaste 35254721Semaste//---------------------------------------------------------------------- 36254721Semaste// GDBRemoteCommunicationServer constructor 37254721Semaste//---------------------------------------------------------------------- 38254721SemasteGDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) : 39254721Semaste GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), 40254721Semaste m_async_thread (LLDB_INVALID_HOST_THREAD), 41254721Semaste m_process_launch_info (), 42254721Semaste m_process_launch_error (), 43254721Semaste m_proc_infos (), 44254721Semaste m_proc_infos_index (0), 45254721Semaste m_lo_port_num (0), 46254721Semaste m_hi_port_num (0) 47254721Semaste{ 48254721Semaste} 49254721Semaste 50254721Semaste//---------------------------------------------------------------------- 51254721Semaste// Destructor 52254721Semaste//---------------------------------------------------------------------- 53254721SemasteGDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() 54254721Semaste{ 55254721Semaste} 56254721Semaste 57254721Semaste 58254721Semaste//void * 59254721Semaste//GDBRemoteCommunicationServer::AsyncThread (void *arg) 60254721Semaste//{ 61254721Semaste// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg; 62254721Semaste// 63254721Semaste// Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); 64254721Semaste// if (log) 65254721Semaste// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID()); 66254721Semaste// 67254721Semaste// StringExtractorGDBRemote packet; 68254721Semaste// 69254721Semaste// while () 70254721Semaste// { 71254721Semaste// if (packet. 72254721Semaste// } 73254721Semaste// 74254721Semaste// if (log) 75254721Semaste// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID()); 76254721Semaste// 77254721Semaste// process->m_async_thread = LLDB_INVALID_HOST_THREAD; 78254721Semaste// return NULL; 79254721Semaste//} 80254721Semaste// 81254721Semastebool 82254721SemasteGDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, 83254721Semaste Error &error, 84254721Semaste bool &interrupt, 85254721Semaste bool &quit) 86254721Semaste{ 87254721Semaste StringExtractorGDBRemote packet; 88254721Semaste if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec)) 89254721Semaste { 90254721Semaste const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType (); 91254721Semaste switch (packet_type) 92254721Semaste { 93254721Semaste case StringExtractorGDBRemote::eServerPacketType_nack: 94254721Semaste case StringExtractorGDBRemote::eServerPacketType_ack: 95254721Semaste break; 96254721Semaste 97254721Semaste case StringExtractorGDBRemote::eServerPacketType_invalid: 98254721Semaste error.SetErrorString("invalid packet"); 99254721Semaste quit = true; 100254721Semaste break; 101254721Semaste 102254721Semaste case StringExtractorGDBRemote::eServerPacketType_interrupt: 103254721Semaste error.SetErrorString("interrupt received"); 104254721Semaste interrupt = true; 105254721Semaste break; 106254721Semaste 107254721Semaste case StringExtractorGDBRemote::eServerPacketType_unimplemented: 108254721Semaste return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0; 109254721Semaste 110254721Semaste case StringExtractorGDBRemote::eServerPacketType_A: 111254721Semaste return Handle_A (packet); 112254721Semaste 113254721Semaste case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo: 114254721Semaste return Handle_qfProcessInfo (packet); 115254721Semaste 116254721Semaste case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo: 117254721Semaste return Handle_qsProcessInfo (packet); 118254721Semaste 119254721Semaste case StringExtractorGDBRemote::eServerPacketType_qC: 120254721Semaste return Handle_qC (packet); 121254721Semaste 122254721Semaste case StringExtractorGDBRemote::eServerPacketType_qHostInfo: 123254721Semaste return Handle_qHostInfo (packet); 124254721Semaste 125254721Semaste case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer: 126254721Semaste return Handle_qLaunchGDBServer (packet); 127254721Semaste 128254721Semaste case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess: 129254721Semaste return Handle_qLaunchSuccess (packet); 130254721Semaste 131254721Semaste case StringExtractorGDBRemote::eServerPacketType_qGroupName: 132254721Semaste return Handle_qGroupName (packet); 133254721Semaste 134254721Semaste case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID: 135254721Semaste return Handle_qProcessInfoPID (packet); 136254721Semaste 137254721Semaste case StringExtractorGDBRemote::eServerPacketType_qSpeedTest: 138254721Semaste return Handle_qSpeedTest (packet); 139254721Semaste 140254721Semaste case StringExtractorGDBRemote::eServerPacketType_qUserName: 141254721Semaste return Handle_qUserName (packet); 142254721Semaste 143254721Semaste case StringExtractorGDBRemote::eServerPacketType_QEnvironment: 144254721Semaste return Handle_QEnvironment (packet); 145254721Semaste 146254721Semaste case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR: 147254721Semaste return Handle_QSetDisableASLR (packet); 148254721Semaste 149254721Semaste case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN: 150254721Semaste return Handle_QSetSTDIN (packet); 151254721Semaste 152254721Semaste case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT: 153254721Semaste return Handle_QSetSTDOUT (packet); 154254721Semaste 155254721Semaste case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR: 156254721Semaste return Handle_QSetSTDERR (packet); 157254721Semaste 158254721Semaste case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir: 159254721Semaste return Handle_QSetWorkingDir (packet); 160254721Semaste 161254721Semaste case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: 162254721Semaste return Handle_QStartNoAckMode (packet); 163254721Semaste } 164254721Semaste return true; 165254721Semaste } 166254721Semaste else 167254721Semaste { 168254721Semaste if (!IsConnected()) 169254721Semaste error.SetErrorString("lost connection"); 170254721Semaste else 171254721Semaste error.SetErrorString("timeout"); 172254721Semaste } 173254721Semaste 174254721Semaste return false; 175254721Semaste} 176254721Semaste 177254721Semastesize_t 178254721SemasteGDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) 179254721Semaste{ 180254721Semaste // TODO: Log the packet we aren't handling... 181254721Semaste return SendPacketNoLock ("", 0); 182254721Semaste} 183254721Semaste 184254721Semastesize_t 185254721SemasteGDBRemoteCommunicationServer::SendErrorResponse (uint8_t err) 186254721Semaste{ 187254721Semaste char packet[16]; 188254721Semaste int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err); 189254721Semaste assert (packet_len < (int)sizeof(packet)); 190254721Semaste return SendPacketNoLock (packet, packet_len); 191254721Semaste} 192254721Semaste 193254721Semaste 194254721Semastesize_t 195254721SemasteGDBRemoteCommunicationServer::SendOKResponse () 196254721Semaste{ 197254721Semaste return SendPacketNoLock ("OK", 2); 198254721Semaste} 199254721Semaste 200254721Semastebool 201254721SemasteGDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr) 202254721Semaste{ 203254721Semaste return GetAck(); 204254721Semaste} 205254721Semaste 206254721Semastebool 207254721SemasteGDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet) 208254721Semaste{ 209254721Semaste StreamString response; 210254721Semaste 211254721Semaste // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 212254721Semaste 213254721Semaste ArchSpec host_arch (Host::GetArchitecture ()); 214254721Semaste const llvm::Triple &host_triple = host_arch.GetTriple(); 215254721Semaste response.PutCString("triple:"); 216254721Semaste response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); 217254721Semaste response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); 218254721Semaste 219254721Semaste uint32_t cpu = host_arch.GetMachOCPUType(); 220254721Semaste uint32_t sub = host_arch.GetMachOCPUSubType(); 221254721Semaste if (cpu != LLDB_INVALID_CPUTYPE) 222254721Semaste response.Printf ("cputype:%u;", cpu); 223254721Semaste if (sub != LLDB_INVALID_CPUTYPE) 224254721Semaste response.Printf ("cpusubtype:%u;", sub); 225254721Semaste 226254721Semaste if (cpu == ArchSpec::kCore_arm_any) 227254721Semaste response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes. 228254721Semaste else 229254721Semaste response.Printf("watchpoint_exceptions_received:after;"); 230254721Semaste 231254721Semaste switch (lldb::endian::InlHostByteOrder()) 232254721Semaste { 233254721Semaste case eByteOrderBig: response.PutCString ("endian:big;"); break; 234254721Semaste case eByteOrderLittle: response.PutCString ("endian:little;"); break; 235254721Semaste case eByteOrderPDP: response.PutCString ("endian:pdp;"); break; 236254721Semaste default: response.PutCString ("endian:unknown;"); break; 237254721Semaste } 238254721Semaste 239254721Semaste uint32_t major = UINT32_MAX; 240254721Semaste uint32_t minor = UINT32_MAX; 241254721Semaste uint32_t update = UINT32_MAX; 242254721Semaste if (Host::GetOSVersion (major, minor, update)) 243254721Semaste { 244254721Semaste if (major != UINT32_MAX) 245254721Semaste { 246254721Semaste response.Printf("os_version:%u", major); 247254721Semaste if (minor != UINT32_MAX) 248254721Semaste { 249254721Semaste response.Printf(".%u", minor); 250254721Semaste if (update != UINT32_MAX) 251254721Semaste response.Printf(".%u", update); 252254721Semaste } 253254721Semaste response.PutChar(';'); 254254721Semaste } 255254721Semaste } 256254721Semaste 257254721Semaste std::string s; 258254721Semaste if (Host::GetOSBuildString (s)) 259254721Semaste { 260254721Semaste response.PutCString ("os_build:"); 261254721Semaste response.PutCStringAsRawHex8(s.c_str()); 262254721Semaste response.PutChar(';'); 263254721Semaste } 264254721Semaste if (Host::GetOSKernelDescription (s)) 265254721Semaste { 266254721Semaste response.PutCString ("os_kernel:"); 267254721Semaste response.PutCStringAsRawHex8(s.c_str()); 268254721Semaste response.PutChar(';'); 269254721Semaste } 270254721Semaste if (Host::GetHostname (s)) 271254721Semaste { 272254721Semaste response.PutCString ("hostname:"); 273254721Semaste response.PutCStringAsRawHex8(s.c_str()); 274254721Semaste response.PutChar(';'); 275254721Semaste } 276254721Semaste 277254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()) > 0; 278254721Semaste} 279254721Semaste 280254721Semastestatic void 281254721SemasteCreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response) 282254721Semaste{ 283254721Semaste response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;", 284254721Semaste proc_info.GetProcessID(), 285254721Semaste proc_info.GetParentProcessID(), 286254721Semaste proc_info.GetUserID(), 287254721Semaste proc_info.GetGroupID(), 288254721Semaste proc_info.GetEffectiveUserID(), 289254721Semaste proc_info.GetEffectiveGroupID()); 290254721Semaste response.PutCString ("name:"); 291254721Semaste response.PutCStringAsRawHex8(proc_info.GetName()); 292254721Semaste response.PutChar(';'); 293254721Semaste const ArchSpec &proc_arch = proc_info.GetArchitecture(); 294254721Semaste if (proc_arch.IsValid()) 295254721Semaste { 296254721Semaste const llvm::Triple &proc_triple = proc_arch.GetTriple(); 297254721Semaste response.PutCString("triple:"); 298254721Semaste response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); 299254721Semaste response.PutChar(';'); 300254721Semaste } 301254721Semaste} 302254721Semaste 303254721Semastebool 304254721SemasteGDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet) 305254721Semaste{ 306254721Semaste // Packet format: "qProcessInfoPID:%i" where %i is the pid 307254721Semaste packet.SetFilePos(::strlen ("qProcessInfoPID:")); 308254721Semaste lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID); 309254721Semaste if (pid != LLDB_INVALID_PROCESS_ID) 310254721Semaste { 311254721Semaste ProcessInstanceInfo proc_info; 312254721Semaste if (Host::GetProcessInfo(pid, proc_info)) 313254721Semaste { 314254721Semaste StreamString response; 315254721Semaste CreateProcessInfoResponse (proc_info, response); 316254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 317254721Semaste } 318254721Semaste } 319254721Semaste return SendErrorResponse (1); 320254721Semaste} 321254721Semaste 322254721Semastebool 323254721SemasteGDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet) 324254721Semaste{ 325254721Semaste m_proc_infos_index = 0; 326254721Semaste m_proc_infos.Clear(); 327254721Semaste 328254721Semaste ProcessInstanceInfoMatch match_info; 329254721Semaste packet.SetFilePos(::strlen ("qfProcessInfo")); 330254721Semaste if (packet.GetChar() == ':') 331254721Semaste { 332254721Semaste 333254721Semaste std::string key; 334254721Semaste std::string value; 335254721Semaste while (packet.GetNameColonValue(key, value)) 336254721Semaste { 337254721Semaste bool success = true; 338254721Semaste if (key.compare("name") == 0) 339254721Semaste { 340254721Semaste StringExtractor extractor; 341254721Semaste extractor.GetStringRef().swap(value); 342254721Semaste extractor.GetHexByteString (value); 343254721Semaste match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false); 344254721Semaste } 345254721Semaste else if (key.compare("name_match") == 0) 346254721Semaste { 347254721Semaste if (value.compare("equals") == 0) 348254721Semaste { 349254721Semaste match_info.SetNameMatchType (eNameMatchEquals); 350254721Semaste } 351254721Semaste else if (value.compare("starts_with") == 0) 352254721Semaste { 353254721Semaste match_info.SetNameMatchType (eNameMatchStartsWith); 354254721Semaste } 355254721Semaste else if (value.compare("ends_with") == 0) 356254721Semaste { 357254721Semaste match_info.SetNameMatchType (eNameMatchEndsWith); 358254721Semaste } 359254721Semaste else if (value.compare("contains") == 0) 360254721Semaste { 361254721Semaste match_info.SetNameMatchType (eNameMatchContains); 362254721Semaste } 363254721Semaste else if (value.compare("regex") == 0) 364254721Semaste { 365254721Semaste match_info.SetNameMatchType (eNameMatchRegularExpression); 366254721Semaste } 367254721Semaste else 368254721Semaste { 369254721Semaste success = false; 370254721Semaste } 371254721Semaste } 372254721Semaste else if (key.compare("pid") == 0) 373254721Semaste { 374254721Semaste match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 375254721Semaste } 376254721Semaste else if (key.compare("parent_pid") == 0) 377254721Semaste { 378254721Semaste match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 379254721Semaste } 380254721Semaste else if (key.compare("uid") == 0) 381254721Semaste { 382254721Semaste match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 383254721Semaste } 384254721Semaste else if (key.compare("gid") == 0) 385254721Semaste { 386254721Semaste match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 387254721Semaste } 388254721Semaste else if (key.compare("euid") == 0) 389254721Semaste { 390254721Semaste match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 391254721Semaste } 392254721Semaste else if (key.compare("egid") == 0) 393254721Semaste { 394254721Semaste match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 395254721Semaste } 396254721Semaste else if (key.compare("all_users") == 0) 397254721Semaste { 398254721Semaste match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success)); 399254721Semaste } 400254721Semaste else if (key.compare("triple") == 0) 401254721Semaste { 402254721Semaste match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL); 403254721Semaste } 404254721Semaste else 405254721Semaste { 406254721Semaste success = false; 407254721Semaste } 408254721Semaste 409254721Semaste if (!success) 410254721Semaste return SendErrorResponse (2); 411254721Semaste } 412254721Semaste } 413254721Semaste 414254721Semaste if (Host::FindProcesses (match_info, m_proc_infos)) 415254721Semaste { 416254721Semaste // We found something, return the first item by calling the get 417254721Semaste // subsequent process info packet handler... 418254721Semaste return Handle_qsProcessInfo (packet); 419254721Semaste } 420254721Semaste return SendErrorResponse (3); 421254721Semaste} 422254721Semaste 423254721Semastebool 424254721SemasteGDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet) 425254721Semaste{ 426254721Semaste if (m_proc_infos_index < m_proc_infos.GetSize()) 427254721Semaste { 428254721Semaste StreamString response; 429254721Semaste CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); 430254721Semaste ++m_proc_infos_index; 431254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 432254721Semaste } 433254721Semaste return SendErrorResponse (4); 434254721Semaste} 435254721Semaste 436254721Semastebool 437254721SemasteGDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet) 438254721Semaste{ 439254721Semaste // Packet format: "qUserName:%i" where %i is the uid 440254721Semaste packet.SetFilePos(::strlen ("qUserName:")); 441254721Semaste uint32_t uid = packet.GetU32 (UINT32_MAX); 442254721Semaste if (uid != UINT32_MAX) 443254721Semaste { 444254721Semaste std::string name; 445254721Semaste if (Host::GetUserName (uid, name)) 446254721Semaste { 447254721Semaste StreamString response; 448254721Semaste response.PutCStringAsRawHex8 (name.c_str()); 449254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 450254721Semaste } 451254721Semaste } 452254721Semaste return SendErrorResponse (5); 453254721Semaste 454254721Semaste} 455254721Semaste 456254721Semastebool 457254721SemasteGDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet) 458254721Semaste{ 459254721Semaste // Packet format: "qGroupName:%i" where %i is the gid 460254721Semaste packet.SetFilePos(::strlen ("qGroupName:")); 461254721Semaste uint32_t gid = packet.GetU32 (UINT32_MAX); 462254721Semaste if (gid != UINT32_MAX) 463254721Semaste { 464254721Semaste std::string name; 465254721Semaste if (Host::GetGroupName (gid, name)) 466254721Semaste { 467254721Semaste StreamString response; 468254721Semaste response.PutCStringAsRawHex8 (name.c_str()); 469254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 470254721Semaste } 471254721Semaste } 472254721Semaste return SendErrorResponse (6); 473254721Semaste} 474254721Semaste 475254721Semastebool 476254721SemasteGDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet) 477254721Semaste{ 478254721Semaste packet.SetFilePos(::strlen ("qSpeedTest:")); 479254721Semaste 480254721Semaste std::string key; 481254721Semaste std::string value; 482254721Semaste bool success = packet.GetNameColonValue(key, value); 483254721Semaste if (success && key.compare("response_size") == 0) 484254721Semaste { 485254721Semaste uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); 486254721Semaste if (success) 487254721Semaste { 488254721Semaste if (response_size == 0) 489254721Semaste return SendOKResponse(); 490254721Semaste StreamString response; 491254721Semaste uint32_t bytes_left = response_size; 492254721Semaste response.PutCString("data:"); 493254721Semaste while (bytes_left > 0) 494254721Semaste { 495254721Semaste if (bytes_left >= 26) 496254721Semaste { 497254721Semaste response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 498254721Semaste bytes_left -= 26; 499254721Semaste } 500254721Semaste else 501254721Semaste { 502254721Semaste response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 503254721Semaste bytes_left = 0; 504254721Semaste } 505254721Semaste } 506254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 507254721Semaste } 508254721Semaste } 509254721Semaste return SendErrorResponse (7); 510254721Semaste} 511254721Semaste 512254721Semaste 513254721Semastestatic void * 514254721SemasteAcceptPortFromInferior (void *arg) 515254721Semaste{ 516254721Semaste const char *connect_url = (const char *)arg; 517254721Semaste ConnectionFileDescriptor file_conn; 518254721Semaste Error error; 519254721Semaste if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess) 520254721Semaste { 521254721Semaste char pid_str[256]; 522254721Semaste ::memset (pid_str, 0, sizeof(pid_str)); 523254721Semaste ConnectionStatus status; 524254721Semaste const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL); 525254721Semaste if (pid_str_len > 0) 526254721Semaste { 527254721Semaste int pid = atoi (pid_str); 528254721Semaste return (void *)(intptr_t)pid; 529254721Semaste } 530254721Semaste } 531254721Semaste return NULL; 532254721Semaste} 533254721Semaste// 534254721Semaste//static bool 535254721Semaste//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) 536254721Semaste//{ 537254721Semaste// const int time_delta_usecs = 100000; 538254721Semaste// const int num_retries = timeout_in_seconds/time_delta_usecs; 539254721Semaste// for (int i=0; i<num_retries; i++) 540254721Semaste// { 541254721Semaste// struct proc_bsdinfo bsd_info; 542254721Semaste// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, 543254721Semaste// (uint64_t) 0, 544254721Semaste// &bsd_info, 545254721Semaste// PROC_PIDTBSDINFO_SIZE); 546254721Semaste// 547254721Semaste// switch (error) 548254721Semaste// { 549254721Semaste// case EINVAL: 550254721Semaste// case ENOTSUP: 551254721Semaste// case ESRCH: 552254721Semaste// case EPERM: 553254721Semaste// return false; 554254721Semaste// 555254721Semaste// default: 556254721Semaste// break; 557254721Semaste// 558254721Semaste// case 0: 559254721Semaste// if (bsd_info.pbi_status == SSTOP) 560254721Semaste// return true; 561254721Semaste// } 562254721Semaste// ::usleep (time_delta_usecs); 563254721Semaste// } 564254721Semaste// return false; 565254721Semaste//} 566254721Semaste 567254721Semastebool 568254721SemasteGDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet) 569254721Semaste{ 570254721Semaste // The 'A' packet is the most over designed packet ever here with 571254721Semaste // redundant argument indexes, redundant argument lengths and needed hex 572254721Semaste // encoded argument string values. Really all that is needed is a comma 573254721Semaste // separated hex encoded argument value list, but we will stay true to the 574254721Semaste // documented version of the 'A' packet here... 575254721Semaste 576254721Semaste packet.SetFilePos(1); // Skip the 'A' 577254721Semaste bool success = true; 578254721Semaste while (success && packet.GetBytesLeft() > 0) 579254721Semaste { 580254721Semaste // Decode the decimal argument string length. This length is the 581254721Semaste // number of hex nibbles in the argument string value. 582254721Semaste const uint32_t arg_len = packet.GetU32(UINT32_MAX); 583254721Semaste if (arg_len == UINT32_MAX) 584254721Semaste success = false; 585254721Semaste else 586254721Semaste { 587254721Semaste // Make sure the argument hex string length is followed by a comma 588254721Semaste if (packet.GetChar() != ',') 589254721Semaste success = false; 590254721Semaste else 591254721Semaste { 592254721Semaste // Decode the argument index. We ignore this really becuase 593254721Semaste // who would really send down the arguments in a random order??? 594254721Semaste const uint32_t arg_idx = packet.GetU32(UINT32_MAX); 595254721Semaste if (arg_idx == UINT32_MAX) 596254721Semaste success = false; 597254721Semaste else 598254721Semaste { 599254721Semaste // Make sure the argument index is followed by a comma 600254721Semaste if (packet.GetChar() != ',') 601254721Semaste success = false; 602254721Semaste else 603254721Semaste { 604254721Semaste // Decode the argument string value from hex bytes 605254721Semaste // back into a UTF8 string and make sure the length 606254721Semaste // matches the one supplied in the packet 607254721Semaste std::string arg; 608254721Semaste if (packet.GetHexByteString(arg) != (arg_len / 2)) 609254721Semaste success = false; 610254721Semaste else 611254721Semaste { 612254721Semaste // If there are any bytes lft 613254721Semaste if (packet.GetBytesLeft()) 614254721Semaste { 615254721Semaste if (packet.GetChar() != ',') 616254721Semaste success = false; 617254721Semaste } 618254721Semaste 619254721Semaste if (success) 620254721Semaste { 621254721Semaste if (arg_idx == 0) 622254721Semaste m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false); 623254721Semaste m_process_launch_info.GetArguments().AppendArgument(arg.c_str()); 624254721Semaste } 625254721Semaste } 626254721Semaste } 627254721Semaste } 628254721Semaste } 629254721Semaste } 630254721Semaste } 631254721Semaste 632254721Semaste if (success) 633254721Semaste { 634254721Semaste m_process_launch_info.GetFlags().Set (eLaunchFlagDebug); 635254721Semaste m_process_launch_error = Host::LaunchProcess (m_process_launch_info); 636254721Semaste if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 637254721Semaste { 638254721Semaste return SendOKResponse (); 639254721Semaste } 640254721Semaste } 641254721Semaste return SendErrorResponse (8); 642254721Semaste} 643254721Semaste 644254721Semastebool 645254721SemasteGDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet) 646254721Semaste{ 647254721Semaste lldb::pid_t pid = m_process_launch_info.GetProcessID(); 648254721Semaste StreamString response; 649254721Semaste response.Printf("QC%" PRIx64, pid); 650254721Semaste if (m_is_platform) 651254721Semaste { 652254721Semaste // If we launch a process and this GDB server is acting as a platform, 653254721Semaste // then we need to clear the process launch state so we can start 654254721Semaste // launching another process. In order to launch a process a bunch or 655254721Semaste // packets need to be sent: environment packets, working directory, 656254721Semaste // disable ASLR, and many more settings. When we launch a process we 657254721Semaste // then need to know when to clear this information. Currently we are 658254721Semaste // selecting the 'qC' packet as that packet which seems to make the most 659254721Semaste // sense. 660254721Semaste if (pid != LLDB_INVALID_PROCESS_ID) 661254721Semaste { 662254721Semaste m_process_launch_info.Clear(); 663254721Semaste } 664254721Semaste } 665254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 666254721Semaste} 667254721Semaste 668254721Semastebool 669254721SemasteGDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) 670254721Semaste{ 671254721Semaste // Spawn a local debugserver as a platform so we can then attach or launch 672254721Semaste // a process... 673254721Semaste 674254721Semaste if (m_is_platform) 675254721Semaste { 676254721Semaste // Sleep and wait a bit for debugserver to start to listen... 677254721Semaste ConnectionFileDescriptor file_conn; 678254721Semaste char connect_url[PATH_MAX]; 679254721Semaste Error error; 680254721Semaste char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX"; 681254721Semaste if (::mktemp (unix_socket_name) == NULL) 682254721Semaste { 683254721Semaste error.SetErrorString ("failed to make temporary path for a unix socket"); 684254721Semaste } 685254721Semaste else 686254721Semaste { 687254721Semaste ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); 688254721Semaste // Spawn a new thread to accept the port that gets bound after 689254721Semaste // binding to port 0 (zero). 690254721Semaste lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name, 691254721Semaste AcceptPortFromInferior, 692254721Semaste connect_url, 693254721Semaste &error); 694254721Semaste 695254721Semaste if (IS_VALID_LLDB_HOST_THREAD(accept_thread)) 696254721Semaste { 697254721Semaste // Spawn a debugserver and try to get 698254721Semaste ProcessLaunchInfo debugserver_launch_info; 699254721Semaste error = StartDebugserverProcess ("localhost:0", 700254721Semaste unix_socket_name, 701254721Semaste debugserver_launch_info); 702254721Semaste 703254721Semaste lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); 704254721Semaste if (error.Success()) 705254721Semaste { 706254721Semaste bool success = false; 707254721Semaste 708254721Semaste thread_result_t accept_thread_result = NULL; 709254721Semaste if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error)) 710254721Semaste { 711254721Semaste if (accept_thread_result) 712254721Semaste { 713254721Semaste uint16_t port = (intptr_t)accept_thread_result; 714254721Semaste char response[256]; 715254721Semaste const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port); 716254721Semaste assert (response_len < (int)sizeof(response)); 717254721Semaste //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); 718254721Semaste success = SendPacketNoLock (response, response_len) > 0; 719254721Semaste } 720254721Semaste } 721254721Semaste ::unlink (unix_socket_name); 722254721Semaste 723254721Semaste if (!success) 724254721Semaste { 725254721Semaste if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 726254721Semaste ::kill (debugserver_pid, SIGINT); 727254721Semaste } 728254721Semaste return success; 729254721Semaste } 730254721Semaste } 731254721Semaste } 732254721Semaste } 733254721Semaste return SendErrorResponse (13); 734254721Semaste} 735254721Semaste 736254721Semastebool 737254721SemasteGDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet) 738254721Semaste{ 739254721Semaste if (m_process_launch_error.Success()) 740254721Semaste return SendOKResponse(); 741254721Semaste StreamString response; 742254721Semaste response.PutChar('E'); 743254721Semaste response.PutCString(m_process_launch_error.AsCString("<unknown error>")); 744254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 745254721Semaste} 746254721Semaste 747254721Semastebool 748254721SemasteGDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet) 749254721Semaste{ 750254721Semaste packet.SetFilePos(::strlen ("QEnvironment:")); 751254721Semaste const uint32_t bytes_left = packet.GetBytesLeft(); 752254721Semaste if (bytes_left > 0) 753254721Semaste { 754254721Semaste m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek()); 755254721Semaste return SendOKResponse (); 756254721Semaste } 757254721Semaste return SendErrorResponse (9); 758254721Semaste} 759254721Semaste 760254721Semastebool 761254721SemasteGDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet) 762254721Semaste{ 763254721Semaste packet.SetFilePos(::strlen ("QSetDisableASLR:")); 764254721Semaste if (packet.GetU32(0)) 765254721Semaste m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR); 766254721Semaste else 767254721Semaste m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR); 768254721Semaste return SendOKResponse (); 769254721Semaste} 770254721Semaste 771254721Semastebool 772254721SemasteGDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet) 773254721Semaste{ 774254721Semaste packet.SetFilePos(::strlen ("QSetWorkingDir:")); 775254721Semaste std::string path; 776254721Semaste packet.GetHexByteString(path); 777254721Semaste m_process_launch_info.SwapWorkingDirectory (path); 778254721Semaste return SendOKResponse (); 779254721Semaste} 780254721Semaste 781254721Semastebool 782254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet) 783254721Semaste{ 784254721Semaste packet.SetFilePos(::strlen ("QSetSTDIN:")); 785254721Semaste ProcessLaunchInfo::FileAction file_action; 786254721Semaste std::string path; 787254721Semaste packet.GetHexByteString(path); 788254721Semaste const bool read = false; 789254721Semaste const bool write = true; 790254721Semaste if (file_action.Open(STDIN_FILENO, path.c_str(), read, write)) 791254721Semaste { 792254721Semaste m_process_launch_info.AppendFileAction(file_action); 793254721Semaste return SendOKResponse (); 794254721Semaste } 795254721Semaste return SendErrorResponse (10); 796254721Semaste} 797254721Semaste 798254721Semastebool 799254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet) 800254721Semaste{ 801254721Semaste packet.SetFilePos(::strlen ("QSetSTDOUT:")); 802254721Semaste ProcessLaunchInfo::FileAction file_action; 803254721Semaste std::string path; 804254721Semaste packet.GetHexByteString(path); 805254721Semaste const bool read = true; 806254721Semaste const bool write = false; 807254721Semaste if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write)) 808254721Semaste { 809254721Semaste m_process_launch_info.AppendFileAction(file_action); 810254721Semaste return SendOKResponse (); 811254721Semaste } 812254721Semaste return SendErrorResponse (11); 813254721Semaste} 814254721Semaste 815254721Semastebool 816254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet) 817254721Semaste{ 818254721Semaste packet.SetFilePos(::strlen ("QSetSTDERR:")); 819254721Semaste ProcessLaunchInfo::FileAction file_action; 820254721Semaste std::string path; 821254721Semaste packet.GetHexByteString(path); 822254721Semaste const bool read = true; 823254721Semaste const bool write = false; 824254721Semaste if (file_action.Open(STDERR_FILENO, path.c_str(), read, write)) 825254721Semaste { 826254721Semaste m_process_launch_info.AppendFileAction(file_action); 827254721Semaste return SendOKResponse (); 828254721Semaste } 829254721Semaste return SendErrorResponse (12); 830254721Semaste} 831254721Semaste 832254721Semastebool 833254721SemasteGDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet) 834254721Semaste{ 835254721Semaste // Send response first before changing m_send_acks to we ack this packet 836254721Semaste SendOKResponse (); 837254721Semaste m_send_acks = false; 838254721Semaste return true; 839254721Semaste} 840