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 10263363Semaste#include <errno.h> 11254721Semaste 12254721Semaste#include "GDBRemoteCommunicationServer.h" 13263363Semaste#include "lldb/Core/StreamGDBRemote.h" 14254721Semaste 15254721Semaste// C Includes 16254721Semaste// C++ Includes 17254721Semaste// Other libraries and framework includes 18254721Semaste#include "llvm/ADT/Triple.h" 19254721Semaste#include "lldb/Interpreter/Args.h" 20254721Semaste#include "lldb/Core/ConnectionFileDescriptor.h" 21254721Semaste#include "lldb/Core/Log.h" 22254721Semaste#include "lldb/Core/State.h" 23254721Semaste#include "lldb/Core/StreamString.h" 24254721Semaste#include "lldb/Host/Endian.h" 25263363Semaste#include "lldb/Host/File.h" 26254721Semaste#include "lldb/Host/Host.h" 27254721Semaste#include "lldb/Host/TimeValue.h" 28269024Semaste#include "lldb/Target/Platform.h" 29254721Semaste#include "lldb/Target/Process.h" 30254721Semaste 31254721Semaste// Project includes 32254721Semaste#include "Utility/StringExtractorGDBRemote.h" 33254721Semaste#include "ProcessGDBRemote.h" 34254721Semaste#include "ProcessGDBRemoteLog.h" 35254721Semaste 36254721Semasteusing namespace lldb; 37254721Semasteusing namespace lldb_private; 38254721Semaste 39254721Semaste//---------------------------------------------------------------------- 40254721Semaste// GDBRemoteCommunicationServer constructor 41254721Semaste//---------------------------------------------------------------------- 42254721SemasteGDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) : 43254721Semaste GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), 44269024Semaste m_platform_sp (Platform::GetDefaultPlatform ()), 45254721Semaste m_async_thread (LLDB_INVALID_HOST_THREAD), 46254721Semaste m_process_launch_info (), 47254721Semaste m_process_launch_error (), 48263363Semaste m_spawned_pids (), 49263363Semaste m_spawned_pids_mutex (Mutex::eMutexTypeRecursive), 50254721Semaste m_proc_infos (), 51254721Semaste m_proc_infos_index (0), 52263367Semaste m_port_map (), 53263367Semaste m_port_offset(0) 54254721Semaste{ 55254721Semaste} 56254721Semaste 57269024SemasteGDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform, 58269024Semaste const lldb::PlatformSP& platform_sp) : 59269024Semaste GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), 60269024Semaste m_platform_sp (platform_sp), 61269024Semaste m_async_thread (LLDB_INVALID_HOST_THREAD), 62269024Semaste m_process_launch_info (), 63269024Semaste m_process_launch_error (), 64269024Semaste m_spawned_pids (), 65269024Semaste m_spawned_pids_mutex (Mutex::eMutexTypeRecursive), 66269024Semaste m_proc_infos (), 67269024Semaste m_proc_infos_index (0), 68269024Semaste m_port_map (), 69269024Semaste m_port_offset(0) 70269024Semaste{ 71269024Semaste assert(platform_sp); 72269024Semaste} 73269024Semaste 74254721Semaste//---------------------------------------------------------------------- 75254721Semaste// Destructor 76254721Semaste//---------------------------------------------------------------------- 77254721SemasteGDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() 78254721Semaste{ 79254721Semaste} 80254721Semaste 81254721Semaste 82254721Semaste//void * 83254721Semaste//GDBRemoteCommunicationServer::AsyncThread (void *arg) 84254721Semaste//{ 85254721Semaste// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg; 86254721Semaste// 87254721Semaste// Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); 88254721Semaste// if (log) 89254721Semaste// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID()); 90254721Semaste// 91254721Semaste// StringExtractorGDBRemote packet; 92263363Semaste// 93254721Semaste// while () 94254721Semaste// { 95254721Semaste// if (packet. 96254721Semaste// } 97254721Semaste// 98254721Semaste// if (log) 99254721Semaste// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID()); 100254721Semaste// 101254721Semaste// process->m_async_thread = LLDB_INVALID_HOST_THREAD; 102254721Semaste// return NULL; 103254721Semaste//} 104254721Semaste// 105254721Semastebool 106263363SemasteGDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, 107254721Semaste Error &error, 108263363Semaste bool &interrupt, 109254721Semaste bool &quit) 110254721Semaste{ 111254721Semaste StringExtractorGDBRemote packet; 112269024Semaste PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); 113269024Semaste if (packet_result == PacketResult::Success) 114254721Semaste { 115254721Semaste const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType (); 116254721Semaste switch (packet_type) 117254721Semaste { 118269024Semaste case StringExtractorGDBRemote::eServerPacketType_nack: 119269024Semaste case StringExtractorGDBRemote::eServerPacketType_ack: 120269024Semaste break; 121254721Semaste 122269024Semaste case StringExtractorGDBRemote::eServerPacketType_invalid: 123269024Semaste error.SetErrorString("invalid packet"); 124269024Semaste quit = true; 125269024Semaste break; 126254721Semaste 127269024Semaste case StringExtractorGDBRemote::eServerPacketType_interrupt: 128269024Semaste error.SetErrorString("interrupt received"); 129269024Semaste interrupt = true; 130269024Semaste break; 131263363Semaste 132269024Semaste default: 133269024Semaste case StringExtractorGDBRemote::eServerPacketType_unimplemented: 134269024Semaste packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str()); 135269024Semaste break; 136254721Semaste 137269024Semaste case StringExtractorGDBRemote::eServerPacketType_A: 138269024Semaste packet_result = Handle_A (packet); 139269024Semaste break; 140254721Semaste 141269024Semaste case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo: 142269024Semaste packet_result = Handle_qfProcessInfo (packet); 143269024Semaste break; 144263363Semaste 145269024Semaste case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo: 146269024Semaste packet_result = Handle_qsProcessInfo (packet); 147269024Semaste break; 148263363Semaste 149269024Semaste case StringExtractorGDBRemote::eServerPacketType_qC: 150269024Semaste packet_result = Handle_qC (packet); 151269024Semaste break; 152263363Semaste 153269024Semaste case StringExtractorGDBRemote::eServerPacketType_qHostInfo: 154269024Semaste packet_result = Handle_qHostInfo (packet); 155269024Semaste break; 156263363Semaste 157269024Semaste case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer: 158269024Semaste packet_result = Handle_qLaunchGDBServer (packet); 159269024Semaste break; 160263363Semaste 161269024Semaste case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess: 162269024Semaste packet_result = Handle_qKillSpawnedProcess (packet); 163269024Semaste break; 164263363Semaste 165269024Semaste case StringExtractorGDBRemote::eServerPacketType_k: 166269024Semaste packet_result = Handle_k (packet); 167269024Semaste break; 168263363Semaste 169269024Semaste case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess: 170269024Semaste packet_result = Handle_qLaunchSuccess (packet); 171269024Semaste break; 172254721Semaste 173269024Semaste case StringExtractorGDBRemote::eServerPacketType_qGroupName: 174269024Semaste packet_result = Handle_qGroupName (packet); 175269024Semaste break; 176254721Semaste 177269024Semaste case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID: 178269024Semaste packet_result = Handle_qProcessInfoPID (packet); 179269024Semaste break; 180254721Semaste 181269024Semaste case StringExtractorGDBRemote::eServerPacketType_qSpeedTest: 182269024Semaste packet_result = Handle_qSpeedTest (packet); 183269024Semaste break; 184254721Semaste 185269024Semaste case StringExtractorGDBRemote::eServerPacketType_qUserName: 186269024Semaste packet_result = Handle_qUserName (packet); 187269024Semaste break; 188263363Semaste 189269024Semaste case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir: 190269024Semaste packet_result = Handle_qGetWorkingDir(packet); 191269024Semaste break; 192263363Semaste 193269024Semaste case StringExtractorGDBRemote::eServerPacketType_QEnvironment: 194269024Semaste packet_result = Handle_QEnvironment (packet); 195269024Semaste break; 196263363Semaste 197269024Semaste case StringExtractorGDBRemote::eServerPacketType_QLaunchArch: 198269024Semaste packet_result = Handle_QLaunchArch (packet); 199269024Semaste break; 200263363Semaste 201269024Semaste case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR: 202269024Semaste packet_result = Handle_QSetDisableASLR (packet); 203269024Semaste break; 204263363Semaste 205269024Semaste case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN: 206269024Semaste packet_result = Handle_QSetSTDIN (packet); 207269024Semaste break; 208263363Semaste 209269024Semaste case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT: 210269024Semaste packet_result = Handle_QSetSTDOUT (packet); 211269024Semaste break; 212254721Semaste 213269024Semaste case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR: 214269024Semaste packet_result = Handle_QSetSTDERR (packet); 215269024Semaste break; 216263363Semaste 217269024Semaste case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir: 218269024Semaste packet_result = Handle_QSetWorkingDir (packet); 219269024Semaste break; 220263363Semaste 221269024Semaste case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: 222269024Semaste packet_result = Handle_QStartNoAckMode (packet); 223269024Semaste break; 224263363Semaste 225269024Semaste case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir: 226269024Semaste packet_result = Handle_qPlatform_mkdir (packet); 227269024Semaste break; 228263367Semaste 229269024Semaste case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod: 230269024Semaste packet_result = Handle_qPlatform_chmod (packet); 231269024Semaste break; 232263363Semaste 233269024Semaste case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell: 234269024Semaste packet_result = Handle_qPlatform_shell (packet); 235269024Semaste break; 236263363Semaste 237269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_open: 238269024Semaste packet_result = Handle_vFile_Open (packet); 239269024Semaste break; 240263363Semaste 241269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_close: 242269024Semaste packet_result = Handle_vFile_Close (packet); 243269024Semaste break; 244263363Semaste 245269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_pread: 246269024Semaste packet_result = Handle_vFile_pRead (packet); 247269024Semaste break; 248263363Semaste 249269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite: 250269024Semaste packet_result = Handle_vFile_pWrite (packet); 251269024Semaste break; 252263363Semaste 253269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_size: 254269024Semaste packet_result = Handle_vFile_Size (packet); 255269024Semaste break; 256263363Semaste 257269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_mode: 258269024Semaste packet_result = Handle_vFile_Mode (packet); 259269024Semaste break; 260263363Semaste 261269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_exists: 262269024Semaste packet_result = Handle_vFile_Exists (packet); 263269024Semaste break; 264263367Semaste 265269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_stat: 266269024Semaste packet_result = Handle_vFile_Stat (packet); 267269024Semaste break; 268269024Semaste 269269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_md5: 270269024Semaste packet_result = Handle_vFile_MD5 (packet); 271269024Semaste break; 272269024Semaste 273269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_symlink: 274269024Semaste packet_result = Handle_vFile_symlink (packet); 275269024Semaste break; 276269024Semaste 277269024Semaste case StringExtractorGDBRemote::eServerPacketType_vFile_unlink: 278269024Semaste packet_result = Handle_vFile_unlink (packet); 279269024Semaste break; 280254721Semaste } 281254721Semaste } 282254721Semaste else 283254721Semaste { 284254721Semaste if (!IsConnected()) 285269024Semaste { 286254721Semaste error.SetErrorString("lost connection"); 287269024Semaste quit = true; 288269024Semaste } 289254721Semaste else 290269024Semaste { 291254721Semaste error.SetErrorString("timeout"); 292269024Semaste } 293254721Semaste } 294269024Semaste return packet_result == PacketResult::Success; 295269024Semaste} 296254721Semaste 297269024Semastelldb_private::Error 298269024SemasteGDBRemoteCommunicationServer::SetLaunchArguments (const char *const args[], int argc) 299269024Semaste{ 300269024Semaste if ((argc < 1) || !args || !args[0] || !args[0][0]) 301269024Semaste return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__); 302269024Semaste 303269024Semaste m_process_launch_info.SetArguments (const_cast<const char**> (args), true); 304269024Semaste return lldb_private::Error (); 305254721Semaste} 306254721Semaste 307269024Semastelldb_private::Error 308269024SemasteGDBRemoteCommunicationServer::SetLaunchFlags (unsigned int launch_flags) 309269024Semaste{ 310269024Semaste m_process_launch_info.GetFlags ().Set (launch_flags); 311269024Semaste return lldb_private::Error (); 312269024Semaste} 313269024Semaste 314269024Semastelldb_private::Error 315269024SemasteGDBRemoteCommunicationServer::LaunchProcess () 316269024Semaste{ 317269024Semaste if (!m_process_launch_info.GetArguments ().GetArgumentCount ()) 318269024Semaste return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__); 319269024Semaste 320269024Semaste // specify the process monitor if not already set. This should 321269024Semaste // generally be what happens since we need to reap started 322269024Semaste // processes. 323269024Semaste if (!m_process_launch_info.GetMonitorProcessCallback ()) 324269024Semaste m_process_launch_info.SetMonitorProcessCallback(ReapDebuggedProcess, this, false); 325269024Semaste 326269024Semaste lldb_private::Error error = m_platform_sp->LaunchProcess (m_process_launch_info); 327269024Semaste if (!error.Success ()) 328269024Semaste { 329269024Semaste fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0)); 330269024Semaste return error; 331269024Semaste } 332269024Semaste 333269024Semaste printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID()); 334269024Semaste 335269024Semaste // add to list of spawned processes. On an lldb-gdbserver, we 336269024Semaste // would expect there to be only one. 337269024Semaste lldb::pid_t pid; 338269024Semaste if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID ) 339269024Semaste { 340269024Semaste Mutex::Locker locker (m_spawned_pids_mutex); 341269024Semaste m_spawned_pids.insert(pid); 342269024Semaste } 343269024Semaste 344269024Semaste return error; 345269024Semaste} 346269024Semaste 347269024SemasteGDBRemoteCommunication::PacketResult 348254721SemasteGDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) 349254721Semaste{ 350254721Semaste // TODO: Log the packet we aren't handling... 351254721Semaste return SendPacketNoLock ("", 0); 352254721Semaste} 353254721Semaste 354269024SemasteGDBRemoteCommunication::PacketResult 355254721SemasteGDBRemoteCommunicationServer::SendErrorResponse (uint8_t err) 356254721Semaste{ 357254721Semaste char packet[16]; 358254721Semaste int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err); 359254721Semaste assert (packet_len < (int)sizeof(packet)); 360254721Semaste return SendPacketNoLock (packet, packet_len); 361254721Semaste} 362254721Semaste 363254721Semaste 364269024SemasteGDBRemoteCommunication::PacketResult 365254721SemasteGDBRemoteCommunicationServer::SendOKResponse () 366254721Semaste{ 367254721Semaste return SendPacketNoLock ("OK", 2); 368254721Semaste} 369254721Semaste 370254721Semastebool 371254721SemasteGDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr) 372254721Semaste{ 373269024Semaste return GetAck() == PacketResult::Success; 374254721Semaste} 375254721Semaste 376269024SemasteGDBRemoteCommunication::PacketResult 377254721SemasteGDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet) 378254721Semaste{ 379254721Semaste StreamString response; 380263363Semaste 381254721Semaste // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 382254721Semaste 383254721Semaste ArchSpec host_arch (Host::GetArchitecture ()); 384254721Semaste const llvm::Triple &host_triple = host_arch.GetTriple(); 385254721Semaste response.PutCString("triple:"); 386254721Semaste response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); 387254721Semaste response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); 388254721Semaste 389269024Semaste const char* distribution_id = host_arch.GetDistributionId ().AsCString (); 390269024Semaste if (distribution_id) 391269024Semaste { 392269024Semaste response.PutCString("distribution_id:"); 393269024Semaste response.PutCStringAsRawHex8(distribution_id); 394269024Semaste response.PutCString(";"); 395269024Semaste } 396269024Semaste 397254721Semaste uint32_t cpu = host_arch.GetMachOCPUType(); 398254721Semaste uint32_t sub = host_arch.GetMachOCPUSubType(); 399254721Semaste if (cpu != LLDB_INVALID_CPUTYPE) 400254721Semaste response.Printf ("cputype:%u;", cpu); 401254721Semaste if (sub != LLDB_INVALID_CPUTYPE) 402254721Semaste response.Printf ("cpusubtype:%u;", sub); 403263363Semaste 404254721Semaste if (cpu == ArchSpec::kCore_arm_any) 405254721Semaste response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes. 406254721Semaste else 407254721Semaste response.Printf("watchpoint_exceptions_received:after;"); 408263363Semaste 409254721Semaste switch (lldb::endian::InlHostByteOrder()) 410254721Semaste { 411254721Semaste case eByteOrderBig: response.PutCString ("endian:big;"); break; 412254721Semaste case eByteOrderLittle: response.PutCString ("endian:little;"); break; 413254721Semaste case eByteOrderPDP: response.PutCString ("endian:pdp;"); break; 414254721Semaste default: response.PutCString ("endian:unknown;"); break; 415254721Semaste } 416263363Semaste 417254721Semaste uint32_t major = UINT32_MAX; 418254721Semaste uint32_t minor = UINT32_MAX; 419254721Semaste uint32_t update = UINT32_MAX; 420254721Semaste if (Host::GetOSVersion (major, minor, update)) 421254721Semaste { 422254721Semaste if (major != UINT32_MAX) 423254721Semaste { 424254721Semaste response.Printf("os_version:%u", major); 425254721Semaste if (minor != UINT32_MAX) 426254721Semaste { 427254721Semaste response.Printf(".%u", minor); 428254721Semaste if (update != UINT32_MAX) 429254721Semaste response.Printf(".%u", update); 430254721Semaste } 431254721Semaste response.PutChar(';'); 432254721Semaste } 433254721Semaste } 434254721Semaste 435254721Semaste std::string s; 436254721Semaste if (Host::GetOSBuildString (s)) 437254721Semaste { 438254721Semaste response.PutCString ("os_build:"); 439254721Semaste response.PutCStringAsRawHex8(s.c_str()); 440254721Semaste response.PutChar(';'); 441254721Semaste } 442254721Semaste if (Host::GetOSKernelDescription (s)) 443254721Semaste { 444254721Semaste response.PutCString ("os_kernel:"); 445254721Semaste response.PutCStringAsRawHex8(s.c_str()); 446254721Semaste response.PutChar(';'); 447254721Semaste } 448263367Semaste#if defined(__APPLE__) 449263367Semaste 450263367Semaste#if defined(__arm__) 451263367Semaste // For iOS devices, we are connected through a USB Mux so we never pretend 452263367Semaste // to actually have a hostname as far as the remote lldb that is connecting 453263367Semaste // to this lldb-platform is concerned 454263367Semaste response.PutCString ("hostname:"); 455263367Semaste response.PutCStringAsRawHex8("localhost"); 456263367Semaste response.PutChar(';'); 457263367Semaste#else // #if defined(__arm__) 458254721Semaste if (Host::GetHostname (s)) 459254721Semaste { 460254721Semaste response.PutCString ("hostname:"); 461254721Semaste response.PutCStringAsRawHex8(s.c_str()); 462254721Semaste response.PutChar(';'); 463254721Semaste } 464263363Semaste 465263367Semaste#endif // #if defined(__arm__) 466263367Semaste 467263367Semaste#else // #if defined(__APPLE__) 468263367Semaste if (Host::GetHostname (s)) 469263367Semaste { 470263367Semaste response.PutCString ("hostname:"); 471263367Semaste response.PutCStringAsRawHex8(s.c_str()); 472263367Semaste response.PutChar(';'); 473263367Semaste } 474263367Semaste#endif // #if defined(__APPLE__) 475263367Semaste 476269024Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 477254721Semaste} 478254721Semaste 479254721Semastestatic void 480254721SemasteCreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response) 481254721Semaste{ 482254721Semaste response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;", 483254721Semaste proc_info.GetProcessID(), 484254721Semaste proc_info.GetParentProcessID(), 485254721Semaste proc_info.GetUserID(), 486254721Semaste proc_info.GetGroupID(), 487254721Semaste proc_info.GetEffectiveUserID(), 488254721Semaste proc_info.GetEffectiveGroupID()); 489254721Semaste response.PutCString ("name:"); 490254721Semaste response.PutCStringAsRawHex8(proc_info.GetName()); 491254721Semaste response.PutChar(';'); 492254721Semaste const ArchSpec &proc_arch = proc_info.GetArchitecture(); 493254721Semaste if (proc_arch.IsValid()) 494254721Semaste { 495254721Semaste const llvm::Triple &proc_triple = proc_arch.GetTriple(); 496254721Semaste response.PutCString("triple:"); 497254721Semaste response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); 498254721Semaste response.PutChar(';'); 499254721Semaste } 500254721Semaste} 501254721Semaste 502269024SemasteGDBRemoteCommunication::PacketResult 503254721SemasteGDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet) 504254721Semaste{ 505254721Semaste // Packet format: "qProcessInfoPID:%i" where %i is the pid 506254721Semaste packet.SetFilePos(::strlen ("qProcessInfoPID:")); 507254721Semaste lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID); 508254721Semaste if (pid != LLDB_INVALID_PROCESS_ID) 509254721Semaste { 510254721Semaste ProcessInstanceInfo proc_info; 511254721Semaste if (Host::GetProcessInfo(pid, proc_info)) 512254721Semaste { 513254721Semaste StreamString response; 514254721Semaste CreateProcessInfoResponse (proc_info, response); 515254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 516254721Semaste } 517254721Semaste } 518254721Semaste return SendErrorResponse (1); 519254721Semaste} 520254721Semaste 521269024SemasteGDBRemoteCommunication::PacketResult 522254721SemasteGDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet) 523254721Semaste{ 524254721Semaste m_proc_infos_index = 0; 525254721Semaste m_proc_infos.Clear(); 526254721Semaste 527254721Semaste ProcessInstanceInfoMatch match_info; 528254721Semaste packet.SetFilePos(::strlen ("qfProcessInfo")); 529254721Semaste if (packet.GetChar() == ':') 530254721Semaste { 531263363Semaste 532254721Semaste std::string key; 533254721Semaste std::string value; 534254721Semaste while (packet.GetNameColonValue(key, value)) 535254721Semaste { 536254721Semaste bool success = true; 537254721Semaste if (key.compare("name") == 0) 538254721Semaste { 539254721Semaste StringExtractor extractor; 540254721Semaste extractor.GetStringRef().swap(value); 541254721Semaste extractor.GetHexByteString (value); 542254721Semaste match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false); 543254721Semaste } 544254721Semaste else if (key.compare("name_match") == 0) 545254721Semaste { 546254721Semaste if (value.compare("equals") == 0) 547254721Semaste { 548254721Semaste match_info.SetNameMatchType (eNameMatchEquals); 549254721Semaste } 550254721Semaste else if (value.compare("starts_with") == 0) 551254721Semaste { 552254721Semaste match_info.SetNameMatchType (eNameMatchStartsWith); 553254721Semaste } 554254721Semaste else if (value.compare("ends_with") == 0) 555254721Semaste { 556254721Semaste match_info.SetNameMatchType (eNameMatchEndsWith); 557254721Semaste } 558254721Semaste else if (value.compare("contains") == 0) 559254721Semaste { 560254721Semaste match_info.SetNameMatchType (eNameMatchContains); 561254721Semaste } 562263363Semaste else if (value.compare("regex") == 0) 563254721Semaste { 564254721Semaste match_info.SetNameMatchType (eNameMatchRegularExpression); 565254721Semaste } 566263363Semaste else 567254721Semaste { 568254721Semaste success = false; 569254721Semaste } 570254721Semaste } 571254721Semaste else if (key.compare("pid") == 0) 572254721Semaste { 573254721Semaste match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 574254721Semaste } 575254721Semaste else if (key.compare("parent_pid") == 0) 576254721Semaste { 577254721Semaste match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 578254721Semaste } 579254721Semaste else if (key.compare("uid") == 0) 580254721Semaste { 581254721Semaste match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 582254721Semaste } 583254721Semaste else if (key.compare("gid") == 0) 584254721Semaste { 585254721Semaste match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 586254721Semaste } 587254721Semaste else if (key.compare("euid") == 0) 588254721Semaste { 589254721Semaste match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 590254721Semaste } 591254721Semaste else if (key.compare("egid") == 0) 592254721Semaste { 593254721Semaste match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 594254721Semaste } 595254721Semaste else if (key.compare("all_users") == 0) 596254721Semaste { 597254721Semaste match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success)); 598254721Semaste } 599254721Semaste else if (key.compare("triple") == 0) 600254721Semaste { 601254721Semaste match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL); 602254721Semaste } 603254721Semaste else 604254721Semaste { 605254721Semaste success = false; 606254721Semaste } 607263363Semaste 608254721Semaste if (!success) 609254721Semaste return SendErrorResponse (2); 610254721Semaste } 611254721Semaste } 612254721Semaste 613254721Semaste if (Host::FindProcesses (match_info, m_proc_infos)) 614254721Semaste { 615254721Semaste // We found something, return the first item by calling the get 616254721Semaste // subsequent process info packet handler... 617254721Semaste return Handle_qsProcessInfo (packet); 618254721Semaste } 619254721Semaste return SendErrorResponse (3); 620254721Semaste} 621254721Semaste 622269024SemasteGDBRemoteCommunication::PacketResult 623254721SemasteGDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet) 624254721Semaste{ 625254721Semaste if (m_proc_infos_index < m_proc_infos.GetSize()) 626254721Semaste { 627254721Semaste StreamString response; 628254721Semaste CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); 629254721Semaste ++m_proc_infos_index; 630254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 631254721Semaste } 632254721Semaste return SendErrorResponse (4); 633254721Semaste} 634254721Semaste 635269024SemasteGDBRemoteCommunication::PacketResult 636254721SemasteGDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet) 637254721Semaste{ 638254721Semaste // Packet format: "qUserName:%i" where %i is the uid 639254721Semaste packet.SetFilePos(::strlen ("qUserName:")); 640254721Semaste uint32_t uid = packet.GetU32 (UINT32_MAX); 641254721Semaste if (uid != UINT32_MAX) 642254721Semaste { 643254721Semaste std::string name; 644254721Semaste if (Host::GetUserName (uid, name)) 645254721Semaste { 646254721Semaste StreamString response; 647254721Semaste response.PutCStringAsRawHex8 (name.c_str()); 648254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 649254721Semaste } 650254721Semaste } 651254721Semaste return SendErrorResponse (5); 652263363Semaste 653254721Semaste} 654254721Semaste 655269024SemasteGDBRemoteCommunication::PacketResult 656254721SemasteGDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet) 657254721Semaste{ 658254721Semaste // Packet format: "qGroupName:%i" where %i is the gid 659254721Semaste packet.SetFilePos(::strlen ("qGroupName:")); 660254721Semaste uint32_t gid = packet.GetU32 (UINT32_MAX); 661254721Semaste if (gid != UINT32_MAX) 662254721Semaste { 663254721Semaste std::string name; 664254721Semaste if (Host::GetGroupName (gid, name)) 665254721Semaste { 666254721Semaste StreamString response; 667254721Semaste response.PutCStringAsRawHex8 (name.c_str()); 668254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 669254721Semaste } 670254721Semaste } 671254721Semaste return SendErrorResponse (6); 672254721Semaste} 673254721Semaste 674269024SemasteGDBRemoteCommunication::PacketResult 675254721SemasteGDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet) 676254721Semaste{ 677254721Semaste packet.SetFilePos(::strlen ("qSpeedTest:")); 678254721Semaste 679254721Semaste std::string key; 680254721Semaste std::string value; 681254721Semaste bool success = packet.GetNameColonValue(key, value); 682254721Semaste if (success && key.compare("response_size") == 0) 683254721Semaste { 684254721Semaste uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); 685254721Semaste if (success) 686254721Semaste { 687254721Semaste if (response_size == 0) 688254721Semaste return SendOKResponse(); 689254721Semaste StreamString response; 690254721Semaste uint32_t bytes_left = response_size; 691254721Semaste response.PutCString("data:"); 692254721Semaste while (bytes_left > 0) 693254721Semaste { 694254721Semaste if (bytes_left >= 26) 695254721Semaste { 696254721Semaste response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 697254721Semaste bytes_left -= 26; 698254721Semaste } 699254721Semaste else 700254721Semaste { 701254721Semaste response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 702254721Semaste bytes_left = 0; 703254721Semaste } 704254721Semaste } 705254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 706254721Semaste } 707254721Semaste } 708254721Semaste return SendErrorResponse (7); 709254721Semaste} 710254721Semaste 711254721Semaste 712254721Semastestatic void * 713254721SemasteAcceptPortFromInferior (void *arg) 714254721Semaste{ 715254721Semaste const char *connect_url = (const char *)arg; 716254721Semaste ConnectionFileDescriptor file_conn; 717254721Semaste Error error; 718254721Semaste if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess) 719254721Semaste { 720254721Semaste char pid_str[256]; 721254721Semaste ::memset (pid_str, 0, sizeof(pid_str)); 722254721Semaste ConnectionStatus status; 723254721Semaste const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL); 724254721Semaste if (pid_str_len > 0) 725254721Semaste { 726254721Semaste int pid = atoi (pid_str); 727254721Semaste return (void *)(intptr_t)pid; 728254721Semaste } 729254721Semaste } 730254721Semaste return NULL; 731254721Semaste} 732254721Semaste// 733254721Semaste//static bool 734254721Semaste//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) 735254721Semaste//{ 736254721Semaste// const int time_delta_usecs = 100000; 737254721Semaste// const int num_retries = timeout_in_seconds/time_delta_usecs; 738254721Semaste// for (int i=0; i<num_retries; i++) 739254721Semaste// { 740254721Semaste// struct proc_bsdinfo bsd_info; 741263363Semaste// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, 742263363Semaste// (uint64_t) 0, 743263363Semaste// &bsd_info, 744254721Semaste// PROC_PIDTBSDINFO_SIZE); 745263363Semaste// 746254721Semaste// switch (error) 747254721Semaste// { 748254721Semaste// case EINVAL: 749254721Semaste// case ENOTSUP: 750254721Semaste// case ESRCH: 751254721Semaste// case EPERM: 752254721Semaste// return false; 753263363Semaste// 754254721Semaste// default: 755254721Semaste// break; 756263363Semaste// 757254721Semaste// case 0: 758254721Semaste// if (bsd_info.pbi_status == SSTOP) 759254721Semaste// return true; 760254721Semaste// } 761254721Semaste// ::usleep (time_delta_usecs); 762254721Semaste// } 763254721Semaste// return false; 764254721Semaste//} 765254721Semaste 766269024SemasteGDBRemoteCommunication::PacketResult 767254721SemasteGDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet) 768254721Semaste{ 769263363Semaste // The 'A' packet is the most over designed packet ever here with 770263363Semaste // redundant argument indexes, redundant argument lengths and needed hex 771263363Semaste // encoded argument string values. Really all that is needed is a comma 772254721Semaste // separated hex encoded argument value list, but we will stay true to the 773254721Semaste // documented version of the 'A' packet here... 774254721Semaste 775254721Semaste packet.SetFilePos(1); // Skip the 'A' 776254721Semaste bool success = true; 777254721Semaste while (success && packet.GetBytesLeft() > 0) 778254721Semaste { 779254721Semaste // Decode the decimal argument string length. This length is the 780254721Semaste // number of hex nibbles in the argument string value. 781254721Semaste const uint32_t arg_len = packet.GetU32(UINT32_MAX); 782254721Semaste if (arg_len == UINT32_MAX) 783254721Semaste success = false; 784254721Semaste else 785254721Semaste { 786254721Semaste // Make sure the argument hex string length is followed by a comma 787254721Semaste if (packet.GetChar() != ',') 788254721Semaste success = false; 789254721Semaste else 790254721Semaste { 791254721Semaste // Decode the argument index. We ignore this really becuase 792254721Semaste // who would really send down the arguments in a random order??? 793254721Semaste const uint32_t arg_idx = packet.GetU32(UINT32_MAX); 794254721Semaste if (arg_idx == UINT32_MAX) 795254721Semaste success = false; 796254721Semaste else 797254721Semaste { 798254721Semaste // Make sure the argument index is followed by a comma 799254721Semaste if (packet.GetChar() != ',') 800254721Semaste success = false; 801254721Semaste else 802254721Semaste { 803254721Semaste // Decode the argument string value from hex bytes 804254721Semaste // back into a UTF8 string and make sure the length 805254721Semaste // matches the one supplied in the packet 806254721Semaste std::string arg; 807254721Semaste if (packet.GetHexByteString(arg) != (arg_len / 2)) 808254721Semaste success = false; 809254721Semaste else 810254721Semaste { 811254721Semaste // If there are any bytes lft 812254721Semaste if (packet.GetBytesLeft()) 813254721Semaste { 814254721Semaste if (packet.GetChar() != ',') 815254721Semaste success = false; 816254721Semaste } 817263363Semaste 818254721Semaste if (success) 819254721Semaste { 820254721Semaste if (arg_idx == 0) 821254721Semaste m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false); 822254721Semaste m_process_launch_info.GetArguments().AppendArgument(arg.c_str()); 823254721Semaste } 824254721Semaste } 825254721Semaste } 826254721Semaste } 827254721Semaste } 828254721Semaste } 829254721Semaste } 830254721Semaste 831254721Semaste if (success) 832254721Semaste { 833269024Semaste // FIXME: remove linux restriction once eLaunchFlagDebug is supported 834269024Semaste#if !defined (__linux__) 835254721Semaste m_process_launch_info.GetFlags().Set (eLaunchFlagDebug); 836269024Semaste#endif 837269024Semaste m_process_launch_error = LaunchProcess (); 838254721Semaste if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 839254721Semaste { 840254721Semaste return SendOKResponse (); 841254721Semaste } 842254721Semaste } 843254721Semaste return SendErrorResponse (8); 844254721Semaste} 845254721Semaste 846269024SemasteGDBRemoteCommunication::PacketResult 847254721SemasteGDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet) 848254721Semaste{ 849254721Semaste lldb::pid_t pid = m_process_launch_info.GetProcessID(); 850254721Semaste StreamString response; 851254721Semaste response.Printf("QC%" PRIx64, pid); 852254721Semaste if (m_is_platform) 853254721Semaste { 854263363Semaste // If we launch a process and this GDB server is acting as a platform, 855263363Semaste // then we need to clear the process launch state so we can start 856254721Semaste // launching another process. In order to launch a process a bunch or 857254721Semaste // packets need to be sent: environment packets, working directory, 858263363Semaste // disable ASLR, and many more settings. When we launch a process we 859254721Semaste // then need to know when to clear this information. Currently we are 860254721Semaste // selecting the 'qC' packet as that packet which seems to make the most 861254721Semaste // sense. 862254721Semaste if (pid != LLDB_INVALID_PROCESS_ID) 863254721Semaste { 864254721Semaste m_process_launch_info.Clear(); 865254721Semaste } 866254721Semaste } 867254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 868254721Semaste} 869254721Semaste 870254721Semastebool 871263363SemasteGDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid) 872263363Semaste{ 873263363Semaste Mutex::Locker locker (m_spawned_pids_mutex); 874263367Semaste FreePortForProcess(pid); 875263363Semaste return m_spawned_pids.erase(pid) > 0; 876263363Semaste} 877263363Semastebool 878263363SemasteGDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton, 879263363Semaste lldb::pid_t pid, 880263363Semaste bool exited, 881263363Semaste int signal, // Zero for no signal 882263363Semaste int status) // Exit value of process if signal is zero 883263363Semaste{ 884263363Semaste GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton; 885263363Semaste server->DebugserverProcessReaped (pid); 886263363Semaste return true; 887263363Semaste} 888263363Semaste 889263363Semastebool 890269024SemasteGDBRemoteCommunicationServer::DebuggedProcessReaped (lldb::pid_t pid) 891269024Semaste{ 892269024Semaste // reap a process that we were debugging (but not debugserver) 893269024Semaste Mutex::Locker locker (m_spawned_pids_mutex); 894269024Semaste return m_spawned_pids.erase(pid) > 0; 895269024Semaste} 896269024Semaste 897269024Semastebool 898269024SemasteGDBRemoteCommunicationServer::ReapDebuggedProcess (void *callback_baton, 899269024Semaste lldb::pid_t pid, 900269024Semaste bool exited, 901269024Semaste int signal, // Zero for no signal 902269024Semaste int status) // Exit value of process if signal is zero 903269024Semaste{ 904269024Semaste GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton; 905269024Semaste server->DebuggedProcessReaped (pid); 906269024Semaste return true; 907269024Semaste} 908269024Semaste 909269024SemasteGDBRemoteCommunication::PacketResult 910254721SemasteGDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) 911254721Semaste{ 912263363Semaste#ifdef _WIN32 913269024Semaste return SendErrorResponse(9); 914263363Semaste#else 915254721Semaste // Spawn a local debugserver as a platform so we can then attach or launch 916254721Semaste // a process... 917254721Semaste 918254721Semaste if (m_is_platform) 919254721Semaste { 920254721Semaste // Sleep and wait a bit for debugserver to start to listen... 921254721Semaste ConnectionFileDescriptor file_conn; 922254721Semaste Error error; 923263363Semaste std::string hostname; 924263363Semaste // TODO: /tmp/ should not be hardcoded. User might want to override /tmp 925263363Semaste // with the TMPDIR environnement variable 926263367Semaste packet.SetFilePos(::strlen ("qLaunchGDBServer;")); 927263367Semaste std::string name; 928263367Semaste std::string value; 929263367Semaste uint16_t port = UINT16_MAX; 930263367Semaste while (packet.GetNameColonValue(name, value)) 931254721Semaste { 932263367Semaste if (name.compare ("host") == 0) 933263367Semaste hostname.swap(value); 934263367Semaste else if (name.compare ("port") == 0) 935263367Semaste port = Args::StringToUInt32(value.c_str(), 0, 0); 936254721Semaste } 937263367Semaste if (port == UINT16_MAX) 938263367Semaste port = GetNextAvailablePort(); 939263363Semaste 940263367Semaste // Spawn a new thread to accept the port that gets bound after 941263367Semaste // binding to port 0 (zero). 942263363Semaste 943263367Semaste if (error.Success()) 944263367Semaste { 945263367Semaste // Spawn a debugserver and try to get the port it listens to. 946263367Semaste ProcessLaunchInfo debugserver_launch_info; 947263367Semaste if (hostname.empty()) 948263367Semaste hostname = "localhost"; 949263367Semaste Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 950263367Semaste if (log) 951269024Semaste log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port); 952263367Semaste 953263367Semaste debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); 954263367Semaste 955269024Semaste error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(), 956269024Semaste port, 957269024Semaste debugserver_launch_info, 958269024Semaste port); 959263367Semaste 960263367Semaste lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); 961263367Semaste 962263367Semaste 963263367Semaste if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 964254721Semaste { 965263367Semaste Mutex::Locker locker (m_spawned_pids_mutex); 966263367Semaste m_spawned_pids.insert(debugserver_pid); 967263367Semaste if (port > 0) 968263367Semaste AssociatePortWithProcess(port, debugserver_pid); 969263367Semaste } 970263367Semaste else 971263367Semaste { 972263367Semaste if (port > 0) 973263367Semaste FreePort (port); 974263367Semaste } 975263363Semaste 976263367Semaste if (error.Success()) 977263367Semaste { 978269024Semaste char response[256]; 979269024Semaste const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); 980269024Semaste assert (response_len < sizeof(response)); 981269024Semaste PacketResult packet_result = SendPacketNoLock (response, response_len); 982263363Semaste 983269024Semaste if (packet_result != PacketResult::Success) 984263363Semaste { 985263367Semaste if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 986263367Semaste ::kill (debugserver_pid, SIGINT); 987254721Semaste } 988269024Semaste return packet_result; 989254721Semaste } 990254721Semaste } 991254721Semaste } 992263363Semaste return SendErrorResponse (9); 993263363Semaste#endif 994254721Semaste} 995254721Semaste 996254721Semastebool 997269024SemasteGDBRemoteCommunicationServer::KillSpawnedProcess (lldb::pid_t pid) 998263363Semaste{ 999269024Semaste // make sure we know about this process 1000263363Semaste { 1001269024Semaste Mutex::Locker locker (m_spawned_pids_mutex); 1002269024Semaste if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 1003269024Semaste return false; 1004269024Semaste } 1005263363Semaste 1006269024Semaste // first try a SIGTERM (standard kill) 1007269024Semaste Host::Kill (pid, SIGTERM); 1008263363Semaste 1009269024Semaste // check if that worked 1010269024Semaste for (size_t i=0; i<10; ++i) 1011269024Semaste { 1012263363Semaste { 1013263363Semaste Mutex::Locker locker (m_spawned_pids_mutex); 1014263363Semaste if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 1015269024Semaste { 1016269024Semaste // it is now killed 1017269024Semaste return true; 1018269024Semaste } 1019263363Semaste } 1020269024Semaste usleep (10000); 1021269024Semaste } 1022263363Semaste 1023269024Semaste // check one more time after the final usleep 1024269024Semaste { 1025269024Semaste Mutex::Locker locker (m_spawned_pids_mutex); 1026269024Semaste if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 1027269024Semaste return true; 1028269024Semaste } 1029269024Semaste 1030269024Semaste // the launched process still lives. Now try killling it again, 1031269024Semaste // this time with an unblockable signal. 1032269024Semaste Host::Kill (pid, SIGKILL); 1033269024Semaste 1034269024Semaste for (size_t i=0; i<10; ++i) 1035269024Semaste { 1036263363Semaste { 1037269024Semaste Mutex::Locker locker (m_spawned_pids_mutex); 1038269024Semaste if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 1039263363Semaste { 1040269024Semaste // it is now killed 1041269024Semaste return true; 1042263363Semaste } 1043263363Semaste } 1044269024Semaste usleep (10000); 1045269024Semaste } 1046263363Semaste 1047269024Semaste // check one more time after the final usleep 1048269024Semaste // Scope for locker 1049269024Semaste { 1050269024Semaste Mutex::Locker locker (m_spawned_pids_mutex); 1051269024Semaste if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 1052269024Semaste return true; 1053269024Semaste } 1054269024Semaste 1055269024Semaste // no luck - the process still lives 1056269024Semaste return false; 1057269024Semaste} 1058269024Semaste 1059269024SemasteGDBRemoteCommunication::PacketResult 1060269024SemasteGDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) 1061269024Semaste{ 1062269024Semaste packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); 1063269024Semaste 1064269024Semaste lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); 1065269024Semaste 1066269024Semaste // verify that we know anything about this pid. 1067269024Semaste // Scope for locker 1068269024Semaste { 1069269024Semaste Mutex::Locker locker (m_spawned_pids_mutex); 1070269024Semaste if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 1071263363Semaste { 1072269024Semaste // not a pid we know about 1073269024Semaste return SendErrorResponse (10); 1074263363Semaste } 1075269024Semaste } 1076263363Semaste 1077269024Semaste // go ahead and attempt to kill the spawned process 1078269024Semaste if (KillSpawnedProcess (pid)) 1079269024Semaste return SendOKResponse (); 1080269024Semaste else 1081269024Semaste return SendErrorResponse (11); 1082269024Semaste} 1083269024Semaste 1084269024SemasteGDBRemoteCommunication::PacketResult 1085269024SemasteGDBRemoteCommunicationServer::Handle_k (StringExtractorGDBRemote &packet) 1086269024Semaste{ 1087269024Semaste // ignore for now if we're lldb_platform 1088269024Semaste if (m_is_platform) 1089269024Semaste return SendUnimplementedResponse (packet.GetStringRef().c_str()); 1090269024Semaste 1091269024Semaste // shutdown all spawned processes 1092269024Semaste std::set<lldb::pid_t> spawned_pids_copy; 1093269024Semaste 1094269024Semaste // copy pids 1095269024Semaste { 1096269024Semaste Mutex::Locker locker (m_spawned_pids_mutex); 1097269024Semaste spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ()); 1098269024Semaste } 1099269024Semaste 1100269024Semaste // nuke the spawned processes 1101269024Semaste for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it) 1102269024Semaste { 1103269024Semaste lldb::pid_t spawned_pid = *it; 1104269024Semaste if (!KillSpawnedProcess (spawned_pid)) 1105263363Semaste { 1106269024Semaste fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid); 1107263363Semaste } 1108263363Semaste } 1109269024Semaste 1110269024Semaste // TODO figure out how to shut down gracefully at this point 1111269024Semaste return SendOKResponse (); 1112263363Semaste} 1113263363Semaste 1114269024SemasteGDBRemoteCommunication::PacketResult 1115254721SemasteGDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet) 1116254721Semaste{ 1117254721Semaste if (m_process_launch_error.Success()) 1118254721Semaste return SendOKResponse(); 1119263363Semaste StreamString response; 1120254721Semaste response.PutChar('E'); 1121254721Semaste response.PutCString(m_process_launch_error.AsCString("<unknown error>")); 1122254721Semaste return SendPacketNoLock (response.GetData(), response.GetSize()); 1123254721Semaste} 1124254721Semaste 1125269024SemasteGDBRemoteCommunication::PacketResult 1126254721SemasteGDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet) 1127254721Semaste{ 1128254721Semaste packet.SetFilePos(::strlen ("QEnvironment:")); 1129254721Semaste const uint32_t bytes_left = packet.GetBytesLeft(); 1130254721Semaste if (bytes_left > 0) 1131254721Semaste { 1132254721Semaste m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek()); 1133254721Semaste return SendOKResponse (); 1134254721Semaste } 1135263367Semaste return SendErrorResponse (12); 1136254721Semaste} 1137254721Semaste 1138269024SemasteGDBRemoteCommunication::PacketResult 1139263363SemasteGDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet) 1140263363Semaste{ 1141263363Semaste packet.SetFilePos(::strlen ("QLaunchArch:")); 1142263363Semaste const uint32_t bytes_left = packet.GetBytesLeft(); 1143263363Semaste if (bytes_left > 0) 1144263363Semaste { 1145263363Semaste const char* arch_triple = packet.Peek(); 1146263363Semaste ArchSpec arch_spec(arch_triple,NULL); 1147263363Semaste m_process_launch_info.SetArchitecture(arch_spec); 1148263363Semaste return SendOKResponse(); 1149263363Semaste } 1150263367Semaste return SendErrorResponse(13); 1151263363Semaste} 1152263363Semaste 1153269024SemasteGDBRemoteCommunication::PacketResult 1154254721SemasteGDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet) 1155254721Semaste{ 1156254721Semaste packet.SetFilePos(::strlen ("QSetDisableASLR:")); 1157254721Semaste if (packet.GetU32(0)) 1158254721Semaste m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR); 1159254721Semaste else 1160254721Semaste m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR); 1161254721Semaste return SendOKResponse (); 1162254721Semaste} 1163254721Semaste 1164269024SemasteGDBRemoteCommunication::PacketResult 1165254721SemasteGDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet) 1166254721Semaste{ 1167254721Semaste packet.SetFilePos(::strlen ("QSetWorkingDir:")); 1168254721Semaste std::string path; 1169254721Semaste packet.GetHexByteString(path); 1170263367Semaste if (m_is_platform) 1171263367Semaste { 1172263367Semaste#ifdef _WIN32 1173263367Semaste // Not implemented on Windows 1174263367Semaste return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_QSetWorkingDir unimplemented"); 1175263367Semaste#else 1176263367Semaste // If this packet is sent to a platform, then change the current working directory 1177263367Semaste if (::chdir(path.c_str()) != 0) 1178263367Semaste return SendErrorResponse(errno); 1179263367Semaste#endif 1180263367Semaste } 1181263367Semaste else 1182263367Semaste { 1183263367Semaste m_process_launch_info.SwapWorkingDirectory (path); 1184263367Semaste } 1185254721Semaste return SendOKResponse (); 1186254721Semaste} 1187254721Semaste 1188269024SemasteGDBRemoteCommunication::PacketResult 1189263367SemasteGDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet) 1190263367Semaste{ 1191263367Semaste StreamString response; 1192263367Semaste 1193263367Semaste if (m_is_platform) 1194263367Semaste { 1195263367Semaste // If this packet is sent to a platform, then change the current working directory 1196263367Semaste char cwd[PATH_MAX]; 1197263367Semaste if (getcwd(cwd, sizeof(cwd)) == NULL) 1198263367Semaste { 1199263367Semaste return SendErrorResponse(errno); 1200263367Semaste } 1201263367Semaste else 1202263367Semaste { 1203263367Semaste response.PutBytesAsRawHex8(cwd, strlen(cwd)); 1204269024Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1205263367Semaste } 1206263367Semaste } 1207263367Semaste else 1208263367Semaste { 1209263367Semaste const char *working_dir = m_process_launch_info.GetWorkingDirectory(); 1210263367Semaste if (working_dir && working_dir[0]) 1211263367Semaste { 1212263367Semaste response.PutBytesAsRawHex8(working_dir, strlen(working_dir)); 1213269024Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1214263367Semaste } 1215263367Semaste else 1216263367Semaste { 1217263367Semaste return SendErrorResponse(14); 1218263367Semaste } 1219263367Semaste } 1220263367Semaste} 1221263367Semaste 1222269024SemasteGDBRemoteCommunication::PacketResult 1223254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet) 1224254721Semaste{ 1225254721Semaste packet.SetFilePos(::strlen ("QSetSTDIN:")); 1226254721Semaste ProcessLaunchInfo::FileAction file_action; 1227254721Semaste std::string path; 1228254721Semaste packet.GetHexByteString(path); 1229254721Semaste const bool read = false; 1230254721Semaste const bool write = true; 1231254721Semaste if (file_action.Open(STDIN_FILENO, path.c_str(), read, write)) 1232254721Semaste { 1233254721Semaste m_process_launch_info.AppendFileAction(file_action); 1234254721Semaste return SendOKResponse (); 1235254721Semaste } 1236263367Semaste return SendErrorResponse (15); 1237254721Semaste} 1238254721Semaste 1239269024SemasteGDBRemoteCommunication::PacketResult 1240254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet) 1241254721Semaste{ 1242254721Semaste packet.SetFilePos(::strlen ("QSetSTDOUT:")); 1243254721Semaste ProcessLaunchInfo::FileAction file_action; 1244254721Semaste std::string path; 1245254721Semaste packet.GetHexByteString(path); 1246254721Semaste const bool read = true; 1247254721Semaste const bool write = false; 1248254721Semaste if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write)) 1249254721Semaste { 1250254721Semaste m_process_launch_info.AppendFileAction(file_action); 1251254721Semaste return SendOKResponse (); 1252254721Semaste } 1253263367Semaste return SendErrorResponse (16); 1254254721Semaste} 1255254721Semaste 1256269024SemasteGDBRemoteCommunication::PacketResult 1257254721SemasteGDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet) 1258254721Semaste{ 1259254721Semaste packet.SetFilePos(::strlen ("QSetSTDERR:")); 1260254721Semaste ProcessLaunchInfo::FileAction file_action; 1261254721Semaste std::string path; 1262254721Semaste packet.GetHexByteString(path); 1263254721Semaste const bool read = true; 1264254721Semaste const bool write = false; 1265254721Semaste if (file_action.Open(STDERR_FILENO, path.c_str(), read, write)) 1266254721Semaste { 1267254721Semaste m_process_launch_info.AppendFileAction(file_action); 1268254721Semaste return SendOKResponse (); 1269254721Semaste } 1270263367Semaste return SendErrorResponse (17); 1271254721Semaste} 1272254721Semaste 1273269024SemasteGDBRemoteCommunication::PacketResult 1274254721SemasteGDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet) 1275254721Semaste{ 1276254721Semaste // Send response first before changing m_send_acks to we ack this packet 1277269024Semaste PacketResult packet_result = SendOKResponse (); 1278254721Semaste m_send_acks = false; 1279269024Semaste return packet_result; 1280254721Semaste} 1281263363Semaste 1282269024SemasteGDBRemoteCommunication::PacketResult 1283263367SemasteGDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet) 1284263363Semaste{ 1285263367Semaste packet.SetFilePos(::strlen("qPlatform_mkdir:")); 1286263363Semaste mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); 1287263367Semaste if (packet.GetChar() == ',') 1288263367Semaste { 1289263367Semaste std::string path; 1290263367Semaste packet.GetHexByteString(path); 1291263367Semaste Error error = Host::MakeDirectory(path.c_str(),mode); 1292263367Semaste if (error.Success()) 1293263367Semaste return SendPacketNoLock ("OK", 2); 1294263367Semaste else 1295263367Semaste return SendErrorResponse(error.GetError()); 1296263367Semaste } 1297263367Semaste return SendErrorResponse(20); 1298263363Semaste} 1299263363Semaste 1300269024SemasteGDBRemoteCommunication::PacketResult 1301263367SemasteGDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet) 1302263367Semaste{ 1303263367Semaste packet.SetFilePos(::strlen("qPlatform_chmod:")); 1304263367Semaste 1305263367Semaste mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); 1306263367Semaste if (packet.GetChar() == ',') 1307263367Semaste { 1308263367Semaste std::string path; 1309263367Semaste packet.GetHexByteString(path); 1310263367Semaste Error error = Host::SetFilePermissions (path.c_str(), mode); 1311263367Semaste if (error.Success()) 1312263367Semaste return SendPacketNoLock ("OK", 2); 1313263367Semaste else 1314263367Semaste return SendErrorResponse(error.GetError()); 1315263367Semaste } 1316263367Semaste return SendErrorResponse(19); 1317263367Semaste} 1318263367Semaste 1319269024SemasteGDBRemoteCommunication::PacketResult 1320263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet) 1321263363Semaste{ 1322263363Semaste packet.SetFilePos(::strlen("vFile:open:")); 1323263363Semaste std::string path; 1324263363Semaste packet.GetHexByteStringTerminatedBy(path,','); 1325263367Semaste if (!path.empty()) 1326263367Semaste { 1327263367Semaste if (packet.GetChar() == ',') 1328263367Semaste { 1329263367Semaste uint32_t flags = packet.GetHexMaxU32(false, 0); 1330263367Semaste if (packet.GetChar() == ',') 1331263367Semaste { 1332263367Semaste mode_t mode = packet.GetHexMaxU32(false, 0600); 1333263367Semaste Error error; 1334263367Semaste int fd = ::open (path.c_str(), flags, mode); 1335263367Semaste const int save_errno = fd == -1 ? errno : 0; 1336263367Semaste StreamString response; 1337263367Semaste response.PutChar('F'); 1338263367Semaste response.Printf("%i", fd); 1339263367Semaste if (save_errno) 1340263367Semaste response.Printf(",%i", save_errno); 1341263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1342263367Semaste } 1343263367Semaste } 1344263367Semaste } 1345263367Semaste return SendErrorResponse(18); 1346263363Semaste} 1347263363Semaste 1348269024SemasteGDBRemoteCommunication::PacketResult 1349263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet) 1350263363Semaste{ 1351263363Semaste packet.SetFilePos(::strlen("vFile:close:")); 1352263363Semaste int fd = packet.GetS32(-1); 1353263363Semaste Error error; 1354263363Semaste int err = -1; 1355263363Semaste int save_errno = 0; 1356263363Semaste if (fd >= 0) 1357263363Semaste { 1358263363Semaste err = close(fd); 1359263363Semaste save_errno = err == -1 ? errno : 0; 1360263363Semaste } 1361263363Semaste else 1362263363Semaste { 1363263363Semaste save_errno = EINVAL; 1364263363Semaste } 1365263363Semaste StreamString response; 1366263363Semaste response.PutChar('F'); 1367263363Semaste response.Printf("%i", err); 1368263363Semaste if (save_errno) 1369263363Semaste response.Printf(",%i", save_errno); 1370263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1371263363Semaste} 1372263363Semaste 1373269024SemasteGDBRemoteCommunication::PacketResult 1374263363SemasteGDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet) 1375263363Semaste{ 1376263363Semaste#ifdef _WIN32 1377263363Semaste // Not implemented on Windows 1378263367Semaste return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pRead() unimplemented"); 1379263363Semaste#else 1380263363Semaste StreamGDBRemote response; 1381263363Semaste packet.SetFilePos(::strlen("vFile:pread:")); 1382263363Semaste int fd = packet.GetS32(-1); 1383263367Semaste if (packet.GetChar() == ',') 1384263363Semaste { 1385263367Semaste uint64_t count = packet.GetU64(UINT64_MAX); 1386263367Semaste if (packet.GetChar() == ',') 1387263367Semaste { 1388263367Semaste uint64_t offset = packet.GetU64(UINT32_MAX); 1389263367Semaste if (count == UINT64_MAX) 1390263367Semaste { 1391263367Semaste response.Printf("F-1:%i", EINVAL); 1392263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1393263367Semaste } 1394263367Semaste 1395263367Semaste std::string buffer(count, 0); 1396263367Semaste const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset); 1397263367Semaste const int save_errno = bytes_read == -1 ? errno : 0; 1398263367Semaste response.PutChar('F'); 1399263367Semaste response.Printf("%zi", bytes_read); 1400263367Semaste if (save_errno) 1401263367Semaste response.Printf(",%i", save_errno); 1402263367Semaste else 1403263367Semaste { 1404263367Semaste response.PutChar(';'); 1405263367Semaste response.PutEscapedBytes(&buffer[0], bytes_read); 1406263367Semaste } 1407263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1408263367Semaste } 1409263363Semaste } 1410263367Semaste return SendErrorResponse(21); 1411263367Semaste 1412263363Semaste#endif 1413263363Semaste} 1414263363Semaste 1415269024SemasteGDBRemoteCommunication::PacketResult 1416263363SemasteGDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet) 1417263363Semaste{ 1418263363Semaste#ifdef _WIN32 1419263367Semaste return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pWrite() unimplemented"); 1420263363Semaste#else 1421263363Semaste packet.SetFilePos(::strlen("vFile:pwrite:")); 1422263363Semaste 1423263363Semaste StreamGDBRemote response; 1424263363Semaste response.PutChar('F'); 1425263363Semaste 1426263363Semaste int fd = packet.GetU32(UINT32_MAX); 1427263367Semaste if (packet.GetChar() == ',') 1428263363Semaste { 1429263367Semaste off_t offset = packet.GetU64(UINT32_MAX); 1430263367Semaste if (packet.GetChar() == ',') 1431263367Semaste { 1432263367Semaste std::string buffer; 1433263367Semaste if (packet.GetEscapedBinaryData(buffer)) 1434263367Semaste { 1435263367Semaste const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset); 1436263367Semaste const int save_errno = bytes_written == -1 ? errno : 0; 1437263367Semaste response.Printf("%zi", bytes_written); 1438263367Semaste if (save_errno) 1439263367Semaste response.Printf(",%i", save_errno); 1440263367Semaste } 1441263367Semaste else 1442263367Semaste { 1443263367Semaste response.Printf ("-1,%i", EINVAL); 1444263367Semaste } 1445263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1446263367Semaste } 1447263363Semaste } 1448263367Semaste return SendErrorResponse(27); 1449263363Semaste#endif 1450263363Semaste} 1451263363Semaste 1452269024SemasteGDBRemoteCommunication::PacketResult 1453263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet) 1454263363Semaste{ 1455263363Semaste packet.SetFilePos(::strlen("vFile:size:")); 1456263363Semaste std::string path; 1457263363Semaste packet.GetHexByteString(path); 1458263367Semaste if (!path.empty()) 1459263363Semaste { 1460263367Semaste lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false)); 1461263367Semaste StreamString response; 1462263367Semaste response.PutChar('F'); 1463263367Semaste response.PutHex64(retcode); 1464263367Semaste if (retcode == UINT64_MAX) 1465263367Semaste { 1466263367Semaste response.PutChar(','); 1467263367Semaste response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode() 1468263367Semaste } 1469263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1470263363Semaste } 1471263367Semaste return SendErrorResponse(22); 1472263363Semaste} 1473263363Semaste 1474269024SemasteGDBRemoteCommunication::PacketResult 1475263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet) 1476263363Semaste{ 1477263363Semaste packet.SetFilePos(::strlen("vFile:mode:")); 1478263363Semaste std::string path; 1479263363Semaste packet.GetHexByteString(path); 1480263367Semaste if (!path.empty()) 1481263367Semaste { 1482263367Semaste Error error; 1483263367Semaste const uint32_t mode = File::GetPermissions(path.c_str(), error); 1484263367Semaste StreamString response; 1485263367Semaste response.Printf("F%u", mode); 1486263367Semaste if (mode == 0 || error.Fail()) 1487263367Semaste response.Printf(",%i", (int)error.GetError()); 1488263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1489263367Semaste } 1490263367Semaste return SendErrorResponse(23); 1491263363Semaste} 1492263363Semaste 1493269024SemasteGDBRemoteCommunication::PacketResult 1494263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet) 1495263363Semaste{ 1496263363Semaste packet.SetFilePos(::strlen("vFile:exists:")); 1497263363Semaste std::string path; 1498263363Semaste packet.GetHexByteString(path); 1499263367Semaste if (!path.empty()) 1500263367Semaste { 1501263367Semaste bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false)); 1502263367Semaste StreamString response; 1503263367Semaste response.PutChar('F'); 1504263367Semaste response.PutChar(','); 1505263367Semaste if (retcode) 1506263367Semaste response.PutChar('1'); 1507263367Semaste else 1508263367Semaste response.PutChar('0'); 1509263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1510263367Semaste } 1511263367Semaste return SendErrorResponse(24); 1512263367Semaste} 1513263367Semaste 1514269024SemasteGDBRemoteCommunication::PacketResult 1515263367SemasteGDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet) 1516263367Semaste{ 1517263367Semaste packet.SetFilePos(::strlen("vFile:symlink:")); 1518263367Semaste std::string dst, src; 1519263367Semaste packet.GetHexByteStringTerminatedBy(dst, ','); 1520263367Semaste packet.GetChar(); // Skip ',' char 1521263367Semaste packet.GetHexByteString(src); 1522263367Semaste Error error = Host::Symlink(src.c_str(), dst.c_str()); 1523263363Semaste StreamString response; 1524263367Semaste response.Printf("F%u,%u", error.GetError(), error.GetError()); 1525263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1526263363Semaste} 1527263363Semaste 1528269024SemasteGDBRemoteCommunication::PacketResult 1529263367SemasteGDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet) 1530263363Semaste{ 1531263367Semaste packet.SetFilePos(::strlen("vFile:unlink:")); 1532263363Semaste std::string path; 1533263367Semaste packet.GetHexByteString(path); 1534263367Semaste Error error = Host::Unlink(path.c_str()); 1535263367Semaste StreamString response; 1536263367Semaste response.Printf("F%u,%u", error.GetError(), error.GetError()); 1537263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1538263367Semaste} 1539263367Semaste 1540269024SemasteGDBRemoteCommunication::PacketResult 1541263367SemasteGDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet) 1542263367Semaste{ 1543263367Semaste packet.SetFilePos(::strlen("qPlatform_shell:")); 1544263367Semaste std::string path; 1545263363Semaste std::string working_dir; 1546263363Semaste packet.GetHexByteStringTerminatedBy(path,','); 1547263367Semaste if (!path.empty()) 1548263363Semaste { 1549263367Semaste if (packet.GetChar() == ',') 1550263367Semaste { 1551263367Semaste // FIXME: add timeout to qPlatform_shell packet 1552263367Semaste // uint32_t timeout = packet.GetHexMaxU32(false, 32); 1553263367Semaste uint32_t timeout = 10; 1554263367Semaste if (packet.GetChar() == ',') 1555263367Semaste packet.GetHexByteString(working_dir); 1556263367Semaste int status, signo; 1557263367Semaste std::string output; 1558263367Semaste Error err = Host::RunShellCommand(path.c_str(), 1559263367Semaste working_dir.empty() ? NULL : working_dir.c_str(), 1560263367Semaste &status, &signo, &output, timeout); 1561263367Semaste StreamGDBRemote response; 1562263367Semaste if (err.Fail()) 1563263367Semaste { 1564263367Semaste response.PutCString("F,"); 1565263367Semaste response.PutHex32(UINT32_MAX); 1566263367Semaste } 1567263367Semaste else 1568263367Semaste { 1569263367Semaste response.PutCString("F,"); 1570263367Semaste response.PutHex32(status); 1571263367Semaste response.PutChar(','); 1572263367Semaste response.PutHex32(signo); 1573263367Semaste response.PutChar(','); 1574263367Semaste response.PutEscapedBytes(output.c_str(), output.size()); 1575263367Semaste } 1576263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1577263367Semaste } 1578263363Semaste } 1579263367Semaste return SendErrorResponse(24); 1580263363Semaste} 1581263363Semaste 1582269024SemasteGDBRemoteCommunication::PacketResult 1583263363SemasteGDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet) 1584263363Semaste{ 1585263367Semaste return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented"); 1586263363Semaste} 1587263363Semaste 1588269024SemasteGDBRemoteCommunication::PacketResult 1589263363SemasteGDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet) 1590263363Semaste{ 1591263367Semaste packet.SetFilePos(::strlen("vFile:MD5:")); 1592263363Semaste std::string path; 1593263363Semaste packet.GetHexByteString(path); 1594263367Semaste if (!path.empty()) 1595263363Semaste { 1596263367Semaste uint64_t a,b; 1597263367Semaste StreamGDBRemote response; 1598263367Semaste if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false) 1599263367Semaste { 1600263367Semaste response.PutCString("F,"); 1601263367Semaste response.PutCString("x"); 1602263367Semaste } 1603263367Semaste else 1604263367Semaste { 1605263367Semaste response.PutCString("F,"); 1606263367Semaste response.PutHex64(a); 1607263367Semaste response.PutHex64(b); 1608263367Semaste } 1609263367Semaste return SendPacketNoLock(response.GetData(), response.GetSize()); 1610263363Semaste } 1611263367Semaste return SendErrorResponse(25); 1612263363Semaste} 1613263367Semaste 1614