1 //===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include <errno.h> 11 12 #include "GDBRemoteCommunicationServer.h" 13 #include "lldb/Core/StreamGDBRemote.h" 14 15 // C Includes 16 // C++ Includes 17 // Other libraries and framework includes 18 #include "llvm/ADT/Triple.h" 19 #include "lldb/Interpreter/Args.h" 20 #include "lldb/Core/ConnectionFileDescriptor.h" 21 #include "lldb/Core/Log.h" 22 #include "lldb/Core/State.h" 23 #include "lldb/Core/StreamString.h" 24 #include "lldb/Host/Endian.h" 25 #include "lldb/Host/File.h" 26 #include "lldb/Host/Host.h" 27 #include "lldb/Host/TimeValue.h" 28 #include "lldb/Target/Process.h" 29 30 // Project includes 31 #include "Utility/StringExtractorGDBRemote.h" 32 #include "ProcessGDBRemote.h" 33 #include "ProcessGDBRemoteLog.h" 34 35 using namespace lldb; 36 using namespace lldb_private; 37 38 //---------------------------------------------------------------------- 39 // GDBRemoteCommunicationServer constructor 40 //---------------------------------------------------------------------- 41 GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) : 42 GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), 43 m_async_thread (LLDB_INVALID_HOST_THREAD), 44 m_process_launch_info (), 45 m_process_launch_error (), 46 m_spawned_pids (), 47 m_spawned_pids_mutex (Mutex::eMutexTypeRecursive), 48 m_proc_infos (), 49 m_proc_infos_index (0), 50 m_lo_port_num (0), 51 m_hi_port_num (0), 52 m_next_port (0), 53 m_use_port_range (false) 54 { 55 // We seldom need to override the port number that the debugserver process 56 // starts with. We just pass in 0 to let the system choose a random port. 57 // In rare situation where the need arises, use two environment variables 58 // to override. 59 uint16_t lo_port_num = 0; 60 uint16_t hi_port_num = 0; 61 const char *lo_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_LO_PORT"); 62 if (lo_port_c_str) 63 lo_port_num = ::atoi(lo_port_c_str); 64 const char *hi_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_HI_PORT"); 65 if (hi_port_c_str) 66 hi_port_num = ::atoi(hi_port_c_str); 67 if (lo_port_num && hi_port_num && lo_port_num < hi_port_num) 68 { 69 SetPortRange(lo_port_num, hi_port_num); 70 } 71 } 72 73 //---------------------------------------------------------------------- 74 // Destructor 75 //---------------------------------------------------------------------- 76 GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() 77 { 78 } 79 80 81 //void * 82 //GDBRemoteCommunicationServer::AsyncThread (void *arg) 83 //{ 84 // GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg; 85 // 86 // Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); 87 // if (log) 88 // log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID()); 89 // 90 // StringExtractorGDBRemote packet; 91 // 92 // while () 93 // { 94 // if (packet. 95 // } 96 // 97 // if (log) 98 // log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID()); 99 // 100 // process->m_async_thread = LLDB_INVALID_HOST_THREAD; 101 // return NULL; 102 //} 103 // 104 bool 105 GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, 106 Error &error, 107 bool &interrupt, 108 bool &quit) 109 { 110 StringExtractorGDBRemote packet; 111 if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec)) 112 { 113 const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType (); 114 switch (packet_type) 115 { 116 case StringExtractorGDBRemote::eServerPacketType_nack: 117 case StringExtractorGDBRemote::eServerPacketType_ack: 118 break; 119 120 case StringExtractorGDBRemote::eServerPacketType_invalid: 121 error.SetErrorString("invalid packet"); 122 quit = true; 123 break; 124 125 case StringExtractorGDBRemote::eServerPacketType_interrupt: 126 error.SetErrorString("interrupt received"); 127 interrupt = true; 128 break; 129 130 case StringExtractorGDBRemote::eServerPacketType_unimplemented: 131 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0; 132 133 case StringExtractorGDBRemote::eServerPacketType_A: 134 return Handle_A (packet); 135 136 case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo: 137 return Handle_qfProcessInfo (packet); 138 139 case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo: 140 return Handle_qsProcessInfo (packet); 141 142 case StringExtractorGDBRemote::eServerPacketType_qC: 143 return Handle_qC (packet); 144 145 case StringExtractorGDBRemote::eServerPacketType_qHostInfo: 146 return Handle_qHostInfo (packet); 147 148 case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer: 149 return Handle_qLaunchGDBServer (packet); 150 151 case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess: 152 return Handle_qKillSpawnedProcess (packet); 153 154 case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess: 155 return Handle_qLaunchSuccess (packet); 156 157 case StringExtractorGDBRemote::eServerPacketType_qGroupName: 158 return Handle_qGroupName (packet); 159 160 case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID: 161 return Handle_qProcessInfoPID (packet); 162 163 case StringExtractorGDBRemote::eServerPacketType_qSpeedTest: 164 return Handle_qSpeedTest (packet); 165 166 case StringExtractorGDBRemote::eServerPacketType_qUserName: 167 return Handle_qUserName (packet); 168 169 case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir: 170 return Handle_qGetWorkingDir(packet); 171 172 case StringExtractorGDBRemote::eServerPacketType_QEnvironment: 173 return Handle_QEnvironment (packet); 174 175 case StringExtractorGDBRemote::eServerPacketType_QLaunchArch: 176 return Handle_QLaunchArch (packet); 177 178 case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR: 179 return Handle_QSetDisableASLR (packet); 180 181 case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN: 182 return Handle_QSetSTDIN (packet); 183 184 case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT: 185 return Handle_QSetSTDOUT (packet); 186 187 case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR: 188 return Handle_QSetSTDERR (packet); 189 190 case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir: 191 return Handle_QSetWorkingDir (packet); 192 193 case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: 194 return Handle_QStartNoAckMode (packet); 195 196 case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir: 197 return Handle_qPlatform_mkdir (packet); 198 199 case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod: 200 return Handle_qPlatform_chmod (packet); 201 202 case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell: 203 return Handle_qPlatform_shell (packet); 204 205 case StringExtractorGDBRemote::eServerPacketType_vFile_open: 206 return Handle_vFile_Open (packet); 207 208 case StringExtractorGDBRemote::eServerPacketType_vFile_close: 209 return Handle_vFile_Close (packet); 210 211 case StringExtractorGDBRemote::eServerPacketType_vFile_pread: 212 return Handle_vFile_pRead (packet); 213 214 case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite: 215 return Handle_vFile_pWrite (packet); 216 217 case StringExtractorGDBRemote::eServerPacketType_vFile_size: 218 return Handle_vFile_Size (packet); 219 220 case StringExtractorGDBRemote::eServerPacketType_vFile_mode: 221 return Handle_vFile_Mode (packet); 222 223 case StringExtractorGDBRemote::eServerPacketType_vFile_exists: 224 return Handle_vFile_Exists (packet); 225 226 case StringExtractorGDBRemote::eServerPacketType_vFile_stat: 227 return Handle_vFile_Stat (packet); 228 229 case StringExtractorGDBRemote::eServerPacketType_vFile_md5: 230 return Handle_vFile_MD5 (packet); 231 232 case StringExtractorGDBRemote::eServerPacketType_vFile_symlink: 233 return Handle_vFile_symlink (packet); 234 235 case StringExtractorGDBRemote::eServerPacketType_vFile_unlink: 236 return Handle_vFile_unlink (packet); 237 } 238 return true; 239 } 240 else 241 { 242 if (!IsConnected()) 243 error.SetErrorString("lost connection"); 244 else 245 error.SetErrorString("timeout"); 246 } 247 248 return false; 249 } 250 251 size_t 252 GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) 253 { 254 // TODO: Log the packet we aren't handling... 255 return SendPacketNoLock ("", 0); 256 } 257 258 size_t 259 GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err) 260 { 261 char packet[16]; 262 int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err); 263 assert (packet_len < (int)sizeof(packet)); 264 return SendPacketNoLock (packet, packet_len); 265 } 266 267 268 size_t 269 GDBRemoteCommunicationServer::SendOKResponse () 270 { 271 return SendPacketNoLock ("OK", 2); 272 } 273 274 bool 275 GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr) 276 { 277 return GetAck(); 278 } 279 280 bool 281 GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet) 282 { 283 StreamString response; 284 285 // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 286 287 ArchSpec host_arch (Host::GetArchitecture ()); 288 const llvm::Triple &host_triple = host_arch.GetTriple(); 289 response.PutCString("triple:"); 290 response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); 291 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); 292 293 uint32_t cpu = host_arch.GetMachOCPUType(); 294 uint32_t sub = host_arch.GetMachOCPUSubType(); 295 if (cpu != LLDB_INVALID_CPUTYPE) 296 response.Printf ("cputype:%u;", cpu); 297 if (sub != LLDB_INVALID_CPUTYPE) 298 response.Printf ("cpusubtype:%u;", sub); 299 300 if (cpu == ArchSpec::kCore_arm_any) 301 response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes. 302 else 303 response.Printf("watchpoint_exceptions_received:after;"); 304 305 switch (lldb::endian::InlHostByteOrder()) 306 { 307 case eByteOrderBig: response.PutCString ("endian:big;"); break; 308 case eByteOrderLittle: response.PutCString ("endian:little;"); break; 309 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break; 310 default: response.PutCString ("endian:unknown;"); break; 311 } 312 313 uint32_t major = UINT32_MAX; 314 uint32_t minor = UINT32_MAX; 315 uint32_t update = UINT32_MAX; 316 if (Host::GetOSVersion (major, minor, update)) 317 { 318 if (major != UINT32_MAX) 319 { 320 response.Printf("os_version:%u", major); 321 if (minor != UINT32_MAX) 322 { 323 response.Printf(".%u", minor); 324 if (update != UINT32_MAX) 325 response.Printf(".%u", update); 326 } 327 response.PutChar(';'); 328 } 329 } 330 331 std::string s; 332 if (Host::GetOSBuildString (s)) 333 { 334 response.PutCString ("os_build:"); 335 response.PutCStringAsRawHex8(s.c_str()); 336 response.PutChar(';'); 337 } 338 if (Host::GetOSKernelDescription (s)) 339 { 340 response.PutCString ("os_kernel:"); 341 response.PutCStringAsRawHex8(s.c_str()); 342 response.PutChar(';'); 343 } 344 if (Host::GetHostname (s)) 345 { 346 response.PutCString ("hostname:"); 347 response.PutCStringAsRawHex8(s.c_str()); 348 response.PutChar(';'); 349 } 350 351 return SendPacketNoLock (response.GetData(), response.GetSize()) > 0; 352 } 353 354 static void 355 CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response) 356 { 357 response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;", 358 proc_info.GetProcessID(), 359 proc_info.GetParentProcessID(), 360 proc_info.GetUserID(), 361 proc_info.GetGroupID(), 362 proc_info.GetEffectiveUserID(), 363 proc_info.GetEffectiveGroupID()); 364 response.PutCString ("name:"); 365 response.PutCStringAsRawHex8(proc_info.GetName()); 366 response.PutChar(';'); 367 const ArchSpec &proc_arch = proc_info.GetArchitecture(); 368 if (proc_arch.IsValid()) 369 { 370 const llvm::Triple &proc_triple = proc_arch.GetTriple(); 371 response.PutCString("triple:"); 372 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); 373 response.PutChar(';'); 374 } 375 } 376 377 bool 378 GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet) 379 { 380 // Packet format: "qProcessInfoPID:%i" where %i is the pid 381 packet.SetFilePos(::strlen ("qProcessInfoPID:")); 382 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID); 383 if (pid != LLDB_INVALID_PROCESS_ID) 384 { 385 ProcessInstanceInfo proc_info; 386 if (Host::GetProcessInfo(pid, proc_info)) 387 { 388 StreamString response; 389 CreateProcessInfoResponse (proc_info, response); 390 return SendPacketNoLock (response.GetData(), response.GetSize()); 391 } 392 } 393 return SendErrorResponse (1); 394 } 395 396 bool 397 GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet) 398 { 399 m_proc_infos_index = 0; 400 m_proc_infos.Clear(); 401 402 ProcessInstanceInfoMatch match_info; 403 packet.SetFilePos(::strlen ("qfProcessInfo")); 404 if (packet.GetChar() == ':') 405 { 406 407 std::string key; 408 std::string value; 409 while (packet.GetNameColonValue(key, value)) 410 { 411 bool success = true; 412 if (key.compare("name") == 0) 413 { 414 StringExtractor extractor; 415 extractor.GetStringRef().swap(value); 416 extractor.GetHexByteString (value); 417 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false); 418 } 419 else if (key.compare("name_match") == 0) 420 { 421 if (value.compare("equals") == 0) 422 { 423 match_info.SetNameMatchType (eNameMatchEquals); 424 } 425 else if (value.compare("starts_with") == 0) 426 { 427 match_info.SetNameMatchType (eNameMatchStartsWith); 428 } 429 else if (value.compare("ends_with") == 0) 430 { 431 match_info.SetNameMatchType (eNameMatchEndsWith); 432 } 433 else if (value.compare("contains") == 0) 434 { 435 match_info.SetNameMatchType (eNameMatchContains); 436 } 437 else if (value.compare("regex") == 0) 438 { 439 match_info.SetNameMatchType (eNameMatchRegularExpression); 440 } 441 else 442 { 443 success = false; 444 } 445 } 446 else if (key.compare("pid") == 0) 447 { 448 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 449 } 450 else if (key.compare("parent_pid") == 0) 451 { 452 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 453 } 454 else if (key.compare("uid") == 0) 455 { 456 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 457 } 458 else if (key.compare("gid") == 0) 459 { 460 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 461 } 462 else if (key.compare("euid") == 0) 463 { 464 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 465 } 466 else if (key.compare("egid") == 0) 467 { 468 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 469 } 470 else if (key.compare("all_users") == 0) 471 { 472 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success)); 473 } 474 else if (key.compare("triple") == 0) 475 { 476 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL); 477 } 478 else 479 { 480 success = false; 481 } 482 483 if (!success) 484 return SendErrorResponse (2); 485 } 486 } 487 488 if (Host::FindProcesses (match_info, m_proc_infos)) 489 { 490 // We found something, return the first item by calling the get 491 // subsequent process info packet handler... 492 return Handle_qsProcessInfo (packet); 493 } 494 return SendErrorResponse (3); 495 } 496 497 bool 498 GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet) 499 { 500 if (m_proc_infos_index < m_proc_infos.GetSize()) 501 { 502 StreamString response; 503 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); 504 ++m_proc_infos_index; 505 return SendPacketNoLock (response.GetData(), response.GetSize()); 506 } 507 return SendErrorResponse (4); 508 } 509 510 bool 511 GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet) 512 { 513 // Packet format: "qUserName:%i" where %i is the uid 514 packet.SetFilePos(::strlen ("qUserName:")); 515 uint32_t uid = packet.GetU32 (UINT32_MAX); 516 if (uid != UINT32_MAX) 517 { 518 std::string name; 519 if (Host::GetUserName (uid, name)) 520 { 521 StreamString response; 522 response.PutCStringAsRawHex8 (name.c_str()); 523 return SendPacketNoLock (response.GetData(), response.GetSize()); 524 } 525 } 526 return SendErrorResponse (5); 527 528 } 529 530 bool 531 GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet) 532 { 533 // Packet format: "qGroupName:%i" where %i is the gid 534 packet.SetFilePos(::strlen ("qGroupName:")); 535 uint32_t gid = packet.GetU32 (UINT32_MAX); 536 if (gid != UINT32_MAX) 537 { 538 std::string name; 539 if (Host::GetGroupName (gid, name)) 540 { 541 StreamString response; 542 response.PutCStringAsRawHex8 (name.c_str()); 543 return SendPacketNoLock (response.GetData(), response.GetSize()); 544 } 545 } 546 return SendErrorResponse (6); 547 } 548 549 bool 550 GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet) 551 { 552 packet.SetFilePos(::strlen ("qSpeedTest:")); 553 554 std::string key; 555 std::string value; 556 bool success = packet.GetNameColonValue(key, value); 557 if (success && key.compare("response_size") == 0) 558 { 559 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); 560 if (success) 561 { 562 if (response_size == 0) 563 return SendOKResponse(); 564 StreamString response; 565 uint32_t bytes_left = response_size; 566 response.PutCString("data:"); 567 while (bytes_left > 0) 568 { 569 if (bytes_left >= 26) 570 { 571 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 572 bytes_left -= 26; 573 } 574 else 575 { 576 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 577 bytes_left = 0; 578 } 579 } 580 return SendPacketNoLock (response.GetData(), response.GetSize()); 581 } 582 } 583 return SendErrorResponse (7); 584 } 585 586 587 static void * 588 AcceptPortFromInferior (void *arg) 589 { 590 const char *connect_url = (const char *)arg; 591 ConnectionFileDescriptor file_conn; 592 Error error; 593 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess) 594 { 595 char pid_str[256]; 596 ::memset (pid_str, 0, sizeof(pid_str)); 597 ConnectionStatus status; 598 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL); 599 if (pid_str_len > 0) 600 { 601 int pid = atoi (pid_str); 602 return (void *)(intptr_t)pid; 603 } 604 } 605 return NULL; 606 } 607 // 608 //static bool 609 //WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) 610 //{ 611 // const int time_delta_usecs = 100000; 612 // const int num_retries = timeout_in_seconds/time_delta_usecs; 613 // for (int i=0; i<num_retries; i++) 614 // { 615 // struct proc_bsdinfo bsd_info; 616 // int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, 617 // (uint64_t) 0, 618 // &bsd_info, 619 // PROC_PIDTBSDINFO_SIZE); 620 // 621 // switch (error) 622 // { 623 // case EINVAL: 624 // case ENOTSUP: 625 // case ESRCH: 626 // case EPERM: 627 // return false; 628 // 629 // default: 630 // break; 631 // 632 // case 0: 633 // if (bsd_info.pbi_status == SSTOP) 634 // return true; 635 // } 636 // ::usleep (time_delta_usecs); 637 // } 638 // return false; 639 //} 640 641 bool 642 GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet) 643 { 644 // The 'A' packet is the most over designed packet ever here with 645 // redundant argument indexes, redundant argument lengths and needed hex 646 // encoded argument string values. Really all that is needed is a comma 647 // separated hex encoded argument value list, but we will stay true to the 648 // documented version of the 'A' packet here... 649 650 packet.SetFilePos(1); // Skip the 'A' 651 bool success = true; 652 while (success && packet.GetBytesLeft() > 0) 653 { 654 // Decode the decimal argument string length. This length is the 655 // number of hex nibbles in the argument string value. 656 const uint32_t arg_len = packet.GetU32(UINT32_MAX); 657 if (arg_len == UINT32_MAX) 658 success = false; 659 else 660 { 661 // Make sure the argument hex string length is followed by a comma 662 if (packet.GetChar() != ',') 663 success = false; 664 else 665 { 666 // Decode the argument index. We ignore this really becuase 667 // who would really send down the arguments in a random order??? 668 const uint32_t arg_idx = packet.GetU32(UINT32_MAX); 669 if (arg_idx == UINT32_MAX) 670 success = false; 671 else 672 { 673 // Make sure the argument index is followed by a comma 674 if (packet.GetChar() != ',') 675 success = false; 676 else 677 { 678 // Decode the argument string value from hex bytes 679 // back into a UTF8 string and make sure the length 680 // matches the one supplied in the packet 681 std::string arg; 682 if (packet.GetHexByteString(arg) != (arg_len / 2)) 683 success = false; 684 else 685 { 686 // If there are any bytes lft 687 if (packet.GetBytesLeft()) 688 { 689 if (packet.GetChar() != ',') 690 success = false; 691 } 692 693 if (success) 694 { 695 if (arg_idx == 0) 696 m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false); 697 m_process_launch_info.GetArguments().AppendArgument(arg.c_str()); 698 } 699 } 700 } 701 } 702 } 703 } 704 } 705 706 if (success) 707 { 708 m_process_launch_info.GetFlags().Set (eLaunchFlagDebug); 709 m_process_launch_error = Host::LaunchProcess (m_process_launch_info); 710 if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 711 { 712 return SendOKResponse (); 713 } 714 } 715 return SendErrorResponse (8); 716 } 717 718 bool 719 GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet) 720 { 721 lldb::pid_t pid = m_process_launch_info.GetProcessID(); 722 StreamString response; 723 response.Printf("QC%" PRIx64, pid); 724 if (m_is_platform) 725 { 726 // If we launch a process and this GDB server is acting as a platform, 727 // then we need to clear the process launch state so we can start 728 // launching another process. In order to launch a process a bunch or 729 // packets need to be sent: environment packets, working directory, 730 // disable ASLR, and many more settings. When we launch a process we 731 // then need to know when to clear this information. Currently we are 732 // selecting the 'qC' packet as that packet which seems to make the most 733 // sense. 734 if (pid != LLDB_INVALID_PROCESS_ID) 735 { 736 m_process_launch_info.Clear(); 737 } 738 } 739 return SendPacketNoLock (response.GetData(), response.GetSize()); 740 } 741 742 bool 743 GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid) 744 { 745 Mutex::Locker locker (m_spawned_pids_mutex); 746 return m_spawned_pids.erase(pid) > 0; 747 } 748 bool 749 GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton, 750 lldb::pid_t pid, 751 bool exited, 752 int signal, // Zero for no signal 753 int status) // Exit value of process if signal is zero 754 { 755 GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton; 756 server->DebugserverProcessReaped (pid); 757 return true; 758 } 759 760 bool 761 GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) 762 { 763 #ifdef _WIN32 764 // No unix sockets on windows 765 return false; 766 #else 767 // Spawn a local debugserver as a platform so we can then attach or launch 768 // a process... 769 770 if (m_is_platform) 771 { 772 // Sleep and wait a bit for debugserver to start to listen... 773 ConnectionFileDescriptor file_conn; 774 char connect_url[PATH_MAX]; 775 Error error; 776 std::string hostname; 777 // TODO: /tmp/ should not be hardcoded. User might want to override /tmp 778 // with the TMPDIR environnement variable 779 char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX"; 780 if (::mkstemp (unix_socket_name) == -1) 781 { 782 error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno)); 783 } 784 else 785 { 786 packet.SetFilePos(::strlen ("qLaunchGDBServer:")); 787 std::string name; 788 std::string value; 789 uint16_t port = UINT16_MAX; 790 while (packet.GetNameColonValue(name, value)) 791 { 792 if (name.compare ("host") == 0) 793 hostname.swap(value); 794 else if (name.compare ("port") == 0) 795 port = Args::StringToUInt32(value.c_str(), 0, 0); 796 } 797 if (port == UINT16_MAX) 798 port = GetAndUpdateNextPort(); 799 800 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); 801 // Spawn a new thread to accept the port that gets bound after 802 // binding to port 0 (zero). 803 lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD; 804 805 if (port == 0) 806 { 807 accept_thread = Host::ThreadCreate (unix_socket_name, 808 AcceptPortFromInferior, 809 connect_url, 810 &error); 811 } 812 813 if (IS_VALID_LLDB_HOST_THREAD(accept_thread)) 814 { 815 // Spawn a debugserver and try to get the port it listens to. 816 ProcessLaunchInfo debugserver_launch_info; 817 StreamString host_and_port; 818 if (hostname.empty()) 819 hostname = "localhost"; 820 host_and_port.Printf("%s:%u", hostname.c_str(), port); 821 const char *host_and_port_cstr = host_and_port.GetString().c_str(); 822 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); 823 if (log) 824 log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr); 825 826 debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); 827 828 error = StartDebugserverProcess (host_and_port_cstr, 829 unix_socket_name, 830 debugserver_launch_info); 831 832 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); 833 834 835 if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 836 { 837 Mutex::Locker locker (m_spawned_pids_mutex); 838 m_spawned_pids.insert(debugserver_pid); 839 } 840 841 if (error.Success()) 842 { 843 bool success = false; 844 845 if (accept_thread) 846 { 847 thread_result_t accept_thread_result = NULL; 848 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error)) 849 { 850 if (accept_thread_result) 851 { 852 port = (intptr_t)accept_thread_result; 853 char response[256]; 854 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port); 855 assert (response_len < sizeof(response)); 856 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); 857 success = SendPacketNoLock (response, response_len) > 0; 858 } 859 } 860 } 861 else 862 { 863 char response[256]; 864 const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port); 865 assert (response_len < sizeof(response)); 866 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); 867 success = SendPacketNoLock (response, response_len) > 0; 868 869 } 870 ::unlink (unix_socket_name); 871 872 if (!success) 873 { 874 if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 875 ::kill (debugserver_pid, SIGINT); 876 } 877 return success; 878 } 879 } 880 } 881 } 882 return SendErrorResponse (9); 883 #endif 884 } 885 886 bool 887 GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) 888 { 889 // Spawn a local debugserver as a platform so we can then attach or launch 890 // a process... 891 892 if (m_is_platform) 893 { 894 packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); 895 896 lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); 897 898 // Scope for locker 899 { 900 Mutex::Locker locker (m_spawned_pids_mutex); 901 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 902 return SendErrorResponse (10); 903 } 904 Host::Kill (pid, SIGTERM); 905 906 for (size_t i=0; i<10; ++i) 907 { 908 // Scope for locker 909 { 910 Mutex::Locker locker (m_spawned_pids_mutex); 911 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 912 return true; 913 } 914 usleep (10000); 915 } 916 917 // Scope for locker 918 { 919 Mutex::Locker locker (m_spawned_pids_mutex); 920 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 921 return true; 922 } 923 Host::Kill (pid, SIGKILL); 924 925 for (size_t i=0; i<10; ++i) 926 { 927 // Scope for locker 928 { 929 Mutex::Locker locker (m_spawned_pids_mutex); 930 if (m_spawned_pids.find(pid) == m_spawned_pids.end()) 931 return true; 932 } 933 usleep (10000); 934 } 935 } 936 return SendErrorResponse (10); 937 } 938 939 bool 940 GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet) 941 { 942 if (m_process_launch_error.Success()) 943 return SendOKResponse(); 944 StreamString response; 945 response.PutChar('E'); 946 response.PutCString(m_process_launch_error.AsCString("<unknown error>")); 947 return SendPacketNoLock (response.GetData(), response.GetSize()); 948 } 949 950 bool 951 GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet) 952 { 953 packet.SetFilePos(::strlen ("QEnvironment:")); 954 const uint32_t bytes_left = packet.GetBytesLeft(); 955 if (bytes_left > 0) 956 { 957 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek()); 958 return SendOKResponse (); 959 } 960 return SendErrorResponse (11); 961 } 962 963 bool 964 GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet) 965 { 966 packet.SetFilePos(::strlen ("QLaunchArch:")); 967 const uint32_t bytes_left = packet.GetBytesLeft(); 968 if (bytes_left > 0) 969 { 970 const char* arch_triple = packet.Peek(); 971 ArchSpec arch_spec(arch_triple,NULL); 972 m_process_launch_info.SetArchitecture(arch_spec); 973 return SendOKResponse(); 974 } 975 return SendErrorResponse(12); 976 } 977 978 bool 979 GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet) 980 { 981 packet.SetFilePos(::strlen ("QSetDisableASLR:")); 982 if (packet.GetU32(0)) 983 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR); 984 else 985 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR); 986 return SendOKResponse (); 987 } 988 989 bool 990 GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet) 991 { 992 packet.SetFilePos(::strlen ("QSetWorkingDir:")); 993 std::string path; 994 packet.GetHexByteString(path); 995 if (m_is_platform) 996 { 997 // If this packet is sent to a platform, then change the current working directory 998 if (::chdir(path.c_str()) != 0) 999 return SendErrorResponse(errno); 1000 } 1001 else 1002 { 1003 m_process_launch_info.SwapWorkingDirectory (path); 1004 } 1005 return SendOKResponse (); 1006 } 1007 1008 bool 1009 GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet) 1010 { 1011 StreamString response; 1012 1013 if (m_is_platform) 1014 { 1015 // If this packet is sent to a platform, then change the current working directory 1016 char cwd[PATH_MAX]; 1017 if (getcwd(cwd, sizeof(cwd)) == NULL) 1018 { 1019 return SendErrorResponse(errno); 1020 } 1021 else 1022 { 1023 response.PutBytesAsRawHex8(cwd, strlen(cwd)); 1024 SendPacketNoLock(response.GetData(), response.GetSize()); 1025 return true; 1026 } 1027 } 1028 else 1029 { 1030 const char *working_dir = m_process_launch_info.GetWorkingDirectory(); 1031 if (working_dir && working_dir[0]) 1032 { 1033 response.PutBytesAsRawHex8(working_dir, strlen(working_dir)); 1034 SendPacketNoLock(response.GetData(), response.GetSize()); 1035 return true; 1036 } 1037 else 1038 { 1039 return SendErrorResponse(1); 1040 } 1041 } 1042 } 1043 1044 bool 1045 GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet) 1046 { 1047 packet.SetFilePos(::strlen ("QSetSTDIN:")); 1048 ProcessLaunchInfo::FileAction file_action; 1049 std::string path; 1050 packet.GetHexByteString(path); 1051 const bool read = false; 1052 const bool write = true; 1053 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write)) 1054 { 1055 m_process_launch_info.AppendFileAction(file_action); 1056 return SendOKResponse (); 1057 } 1058 return SendErrorResponse (13); 1059 } 1060 1061 bool 1062 GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet) 1063 { 1064 packet.SetFilePos(::strlen ("QSetSTDOUT:")); 1065 ProcessLaunchInfo::FileAction file_action; 1066 std::string path; 1067 packet.GetHexByteString(path); 1068 const bool read = true; 1069 const bool write = false; 1070 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write)) 1071 { 1072 m_process_launch_info.AppendFileAction(file_action); 1073 return SendOKResponse (); 1074 } 1075 return SendErrorResponse (14); 1076 } 1077 1078 bool 1079 GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet) 1080 { 1081 packet.SetFilePos(::strlen ("QSetSTDERR:")); 1082 ProcessLaunchInfo::FileAction file_action; 1083 std::string path; 1084 packet.GetHexByteString(path); 1085 const bool read = true; 1086 const bool write = false; 1087 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write)) 1088 { 1089 m_process_launch_info.AppendFileAction(file_action); 1090 return SendOKResponse (); 1091 } 1092 return SendErrorResponse (15); 1093 } 1094 1095 bool 1096 GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet) 1097 { 1098 // Send response first before changing m_send_acks to we ack this packet 1099 SendOKResponse (); 1100 m_send_acks = false; 1101 return true; 1102 } 1103 1104 bool 1105 GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet) 1106 { 1107 packet.SetFilePos(::strlen("qPlatform_mkdir:")); 1108 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); 1109 if (packet.GetChar() != ',') 1110 return false; 1111 std::string path; 1112 packet.GetHexByteString(path); 1113 Error error = Host::MakeDirectory(path.c_str(),mode); 1114 if (error.Success()) 1115 return SendPacketNoLock ("OK", 2); 1116 else 1117 return SendErrorResponse(error.GetError()); 1118 return true; 1119 } 1120 1121 bool 1122 GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet) 1123 { 1124 packet.SetFilePos(::strlen("qPlatform_chmod:")); 1125 1126 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); 1127 if (packet.GetChar() != ',') 1128 return false; 1129 std::string path; 1130 packet.GetHexByteString(path); 1131 Error error = Host::SetFilePermissions (path.c_str(), mode); 1132 if (error.Success()) 1133 return SendPacketNoLock ("OK", 2); 1134 else 1135 return SendErrorResponse(error.GetError()); 1136 return true; 1137 } 1138 1139 bool 1140 GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet) 1141 { 1142 packet.SetFilePos(::strlen("vFile:open:")); 1143 std::string path; 1144 packet.GetHexByteStringTerminatedBy(path,','); 1145 if (path.size() == 0) 1146 return false; 1147 if (packet.GetChar() != ',') 1148 return false; 1149 uint32_t flags = packet.GetHexMaxU32(false, UINT32_MAX); 1150 if (packet.GetChar() != ',') 1151 return false; 1152 mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); 1153 Error error; 1154 int fd = ::open (path.c_str(), flags, mode); 1155 const int save_errno = fd == -1 ? errno : 0; 1156 StreamString response; 1157 response.PutChar('F'); 1158 response.Printf("%i", fd); 1159 if (save_errno) 1160 response.Printf(",%i", save_errno); 1161 SendPacketNoLock(response.GetData(), response.GetSize()); 1162 return true; 1163 } 1164 1165 bool 1166 GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet) 1167 { 1168 packet.SetFilePos(::strlen("vFile:close:")); 1169 int fd = packet.GetS32(-1); 1170 Error error; 1171 int err = -1; 1172 int save_errno = 0; 1173 if (fd >= 0) 1174 { 1175 err = close(fd); 1176 save_errno = err == -1 ? errno : 0; 1177 } 1178 else 1179 { 1180 save_errno = EINVAL; 1181 } 1182 StreamString response; 1183 response.PutChar('F'); 1184 response.Printf("%i", err); 1185 if (save_errno) 1186 response.Printf(",%i", save_errno); 1187 SendPacketNoLock(response.GetData(), response.GetSize()); 1188 return true; 1189 } 1190 1191 bool 1192 GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet) 1193 { 1194 #ifdef _WIN32 1195 // Not implemented on Windows 1196 return false; 1197 #else 1198 StreamGDBRemote response; 1199 packet.SetFilePos(::strlen("vFile:pread:")); 1200 int fd = packet.GetS32(-1); 1201 if (packet.GetChar() != ',') 1202 return false; 1203 uint64_t count = packet.GetU64(UINT64_MAX); 1204 if (packet.GetChar() != ',') 1205 return false; 1206 uint64_t offset = packet.GetU64(UINT32_MAX); 1207 if (count == UINT64_MAX) 1208 { 1209 response.Printf("F-1:%i", EINVAL); 1210 SendPacketNoLock(response.GetData(), response.GetSize()); 1211 return true; 1212 } 1213 std::string buffer(count, 0); 1214 const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset); 1215 const int save_errno = bytes_read == -1 ? errno : 0; 1216 response.PutChar('F'); 1217 response.Printf("%zi", bytes_read); 1218 if (save_errno) 1219 response.Printf(",%i", save_errno); 1220 else 1221 { 1222 response.PutChar(';'); 1223 response.PutEscapedBytes(&buffer[0], bytes_read); 1224 } 1225 SendPacketNoLock(response.GetData(), response.GetSize()); 1226 return true; 1227 #endif 1228 } 1229 1230 bool 1231 GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet) 1232 { 1233 #ifdef _WIN32 1234 // Not implemented on Windows 1235 return false; 1236 #else 1237 packet.SetFilePos(::strlen("vFile:pwrite:")); 1238 1239 StreamGDBRemote response; 1240 response.PutChar('F'); 1241 1242 int fd = packet.GetU32(UINT32_MAX); 1243 if (packet.GetChar() != ',') 1244 return false; 1245 off_t offset = packet.GetU64(UINT32_MAX); 1246 if (packet.GetChar() != ',') 1247 return false; 1248 std::string buffer; 1249 if (packet.GetEscapedBinaryData(buffer)) 1250 { 1251 const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset); 1252 const int save_errno = bytes_written == -1 ? errno : 0; 1253 response.Printf("%zi", bytes_written); 1254 if (save_errno) 1255 response.Printf(",%i", save_errno); 1256 } 1257 else 1258 { 1259 response.Printf ("-1,%i", EINVAL); 1260 } 1261 1262 SendPacketNoLock(response.GetData(), response.GetSize()); 1263 return true; 1264 #endif 1265 } 1266 1267 bool 1268 GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet) 1269 { 1270 packet.SetFilePos(::strlen("vFile:size:")); 1271 std::string path; 1272 packet.GetHexByteString(path); 1273 if (path.empty()) 1274 return false; 1275 lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false)); 1276 StreamString response; 1277 response.PutChar('F'); 1278 response.PutHex64(retcode); 1279 if (retcode == UINT64_MAX) 1280 { 1281 response.PutChar(','); 1282 response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode() 1283 } 1284 SendPacketNoLock(response.GetData(), response.GetSize()); 1285 return true; 1286 } 1287 1288 bool 1289 GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet) 1290 { 1291 packet.SetFilePos(::strlen("vFile:mode:")); 1292 std::string path; 1293 packet.GetHexByteString(path); 1294 if (path.empty()) 1295 return false; 1296 Error error; 1297 const uint32_t mode = File::GetPermissions(path.c_str(), error); 1298 StreamString response; 1299 response.Printf("F%u", mode); 1300 if (mode == 0 || error.Fail()) 1301 response.Printf(",%i", (int)error.GetError()); 1302 SendPacketNoLock(response.GetData(), response.GetSize()); 1303 return true; 1304 } 1305 1306 bool 1307 GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet) 1308 { 1309 packet.SetFilePos(::strlen("vFile:exists:")); 1310 std::string path; 1311 packet.GetHexByteString(path); 1312 if (path.empty()) 1313 return false; 1314 bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false)); 1315 StreamString response; 1316 response.PutChar('F'); 1317 response.PutChar(','); 1318 if (retcode) 1319 response.PutChar('1'); 1320 else 1321 response.PutChar('0'); 1322 SendPacketNoLock(response.GetData(), response.GetSize()); 1323 return true; 1324 } 1325 1326 bool 1327 GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet) 1328 { 1329 packet.SetFilePos(::strlen("vFile:symlink:")); 1330 std::string dst, src; 1331 packet.GetHexByteStringTerminatedBy(dst, ','); 1332 packet.GetChar(); // Skip ',' char 1333 packet.GetHexByteString(src); 1334 Error error = Host::Symlink(src.c_str(), dst.c_str()); 1335 StreamString response; 1336 response.Printf("F%u,%u", error.GetError(), error.GetError()); 1337 SendPacketNoLock(response.GetData(), response.GetSize()); 1338 return true; 1339 } 1340 1341 bool 1342 GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet) 1343 { 1344 packet.SetFilePos(::strlen("vFile:unlink:")); 1345 std::string path; 1346 packet.GetHexByteString(path); 1347 Error error = Host::Unlink(path.c_str()); 1348 StreamString response; 1349 response.Printf("F%u,%u", error.GetError(), error.GetError()); 1350 SendPacketNoLock(response.GetData(), response.GetSize()); 1351 return true; 1352 } 1353 1354 bool 1355 GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet) 1356 { 1357 packet.SetFilePos(::strlen("qPlatform_shell:")); 1358 std::string path; 1359 std::string working_dir; 1360 packet.GetHexByteStringTerminatedBy(path,','); 1361 if (path.size() == 0) 1362 return false; 1363 if (packet.GetChar() != ',') 1364 return false; 1365 // FIXME: add timeout to qPlatform_shell packet 1366 // uint32_t timeout = packet.GetHexMaxU32(false, 32); 1367 uint32_t timeout = 10; 1368 if (packet.GetChar() == ',') 1369 packet.GetHexByteString(working_dir); 1370 int status, signo; 1371 std::string output; 1372 Error err = Host::RunShellCommand(path.c_str(), 1373 working_dir.empty() ? NULL : working_dir.c_str(), 1374 &status, &signo, &output, timeout); 1375 StreamGDBRemote response; 1376 if (err.Fail()) 1377 { 1378 response.PutCString("F,"); 1379 response.PutHex32(UINT32_MAX); 1380 } 1381 else 1382 { 1383 response.PutCString("F,"); 1384 response.PutHex32(status); 1385 response.PutChar(','); 1386 response.PutHex32(signo); 1387 response.PutChar(','); 1388 response.PutEscapedBytes(output.c_str(), output.size()); 1389 } 1390 SendPacketNoLock(response.GetData(), response.GetSize()); 1391 return true; 1392 } 1393 1394 bool 1395 GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet) 1396 { 1397 return false; 1398 } 1399 1400 bool 1401 GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet) 1402 { 1403 packet.SetFilePos(::strlen("vFile:exists:")); 1404 std::string path; 1405 packet.GetHexByteString(path); 1406 if (path.size() == 0) 1407 return false; 1408 uint64_t a,b; 1409 StreamGDBRemote response; 1410 if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false) 1411 { 1412 response.PutCString("F,"); 1413 response.PutCString("x"); 1414 } 1415 else 1416 { 1417 response.PutCString("F,"); 1418 response.PutHex64(a); 1419 response.PutHex64(b); 1420 } 1421 SendPacketNoLock(response.GetData(), response.GetSize()); 1422 return true; 1423 } 1424