GDBRemoteCommunicationServer.cpp revision 516f0849819d094d4eab39a1f27b770259103ff8
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 11#include "GDBRemoteCommunicationServer.h" 12 13// C Includes 14// C++ Includes 15// Other libraries and framework includes 16#include "llvm/ADT/Triple.h" 17#include "lldb/Interpreter/Args.h" 18#include "lldb/Core/ConnectionFileDescriptor.h" 19#include "lldb/Core/Log.h" 20#include "lldb/Core/State.h" 21#include "lldb/Core/StreamString.h" 22#include "lldb/Host/Endian.h" 23#include "lldb/Host/Host.h" 24#include "lldb/Host/TimeValue.h" 25#include "lldb/Target/Process.h" 26 27// Project includes 28#include "Utility/StringExtractorGDBRemote.h" 29#include "ProcessGDBRemote.h" 30#include "ProcessGDBRemoteLog.h" 31 32using namespace lldb; 33using namespace lldb_private; 34 35//---------------------------------------------------------------------- 36// GDBRemoteCommunicationServer constructor 37//---------------------------------------------------------------------- 38GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) : 39 GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), 40 m_async_thread (LLDB_INVALID_HOST_THREAD), 41 m_process_launch_info (), 42 m_process_launch_error (), 43 m_proc_infos (), 44 m_proc_infos_index (0), 45 m_lo_port_num (0), 46 m_hi_port_num (0) 47{ 48} 49 50//---------------------------------------------------------------------- 51// Destructor 52//---------------------------------------------------------------------- 53GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() 54{ 55} 56 57 58//void * 59//GDBRemoteCommunicationServer::AsyncThread (void *arg) 60//{ 61// GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg; 62// 63// LogSP log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); 64// if (log) 65// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID()); 66// 67// StringExtractorGDBRemote packet; 68// 69// while () 70// { 71// if (packet. 72// } 73// 74// if (log) 75// log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID()); 76// 77// process->m_async_thread = LLDB_INVALID_HOST_THREAD; 78// return NULL; 79//} 80// 81bool 82GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, 83 Error &error, 84 bool &interrupt, 85 bool &quit) 86{ 87 StringExtractorGDBRemote packet; 88 if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec)) 89 { 90 const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType (); 91 switch (packet_type) 92 { 93 case StringExtractorGDBRemote::eServerPacketType_nack: 94 case StringExtractorGDBRemote::eServerPacketType_ack: 95 break; 96 97 case StringExtractorGDBRemote::eServerPacketType_invalid: 98 error.SetErrorString("invalid packet"); 99 quit = true; 100 break; 101 102 case StringExtractorGDBRemote::eServerPacketType_interrupt: 103 error.SetErrorString("interrupt received"); 104 interrupt = true; 105 break; 106 107 case StringExtractorGDBRemote::eServerPacketType_unimplemented: 108 return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0; 109 110 case StringExtractorGDBRemote::eServerPacketType_A: 111 return Handle_A (packet); 112 113 case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo: 114 return Handle_qfProcessInfo (packet); 115 116 case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo: 117 return Handle_qsProcessInfo (packet); 118 119 case StringExtractorGDBRemote::eServerPacketType_qC: 120 return Handle_qC (packet); 121 122 case StringExtractorGDBRemote::eServerPacketType_qHostInfo: 123 return Handle_qHostInfo (packet); 124 125 case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer: 126 return Handle_qLaunchGDBServer (packet); 127 128 case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess: 129 return Handle_qLaunchSuccess (packet); 130 131 case StringExtractorGDBRemote::eServerPacketType_qGroupName: 132 return Handle_qGroupName (packet); 133 134 case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID: 135 return Handle_qProcessInfoPID (packet); 136 137 case StringExtractorGDBRemote::eServerPacketType_qSpeedTest: 138 return Handle_qSpeedTest (packet); 139 140 case StringExtractorGDBRemote::eServerPacketType_qUserName: 141 return Handle_qUserName (packet); 142 143 case StringExtractorGDBRemote::eServerPacketType_QEnvironment: 144 return Handle_QEnvironment (packet); 145 146 case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR: 147 return Handle_QSetDisableASLR (packet); 148 149 case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN: 150 return Handle_QSetSTDIN (packet); 151 152 case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT: 153 return Handle_QSetSTDOUT (packet); 154 155 case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR: 156 return Handle_QSetSTDERR (packet); 157 158 case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir: 159 return Handle_QSetWorkingDir (packet); 160 161 case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: 162 return Handle_QStartNoAckMode (packet); 163 } 164 return true; 165 } 166 else 167 { 168 if (!IsConnected()) 169 error.SetErrorString("lost connection"); 170 else 171 error.SetErrorString("timeout"); 172 } 173 174 return false; 175} 176 177size_t 178GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) 179{ 180 // TODO: Log the packet we aren't handling... 181 return SendPacketNoLock ("", 0); 182} 183 184size_t 185GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err) 186{ 187 char packet[16]; 188 int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err); 189 assert (packet_len < sizeof(packet)); 190 return SendPacketNoLock (packet, packet_len); 191} 192 193 194size_t 195GDBRemoteCommunicationServer::SendOKResponse () 196{ 197 return SendPacketNoLock ("OK", 2); 198} 199 200bool 201GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr) 202{ 203 return GetAck(); 204} 205 206bool 207GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet) 208{ 209 StreamString response; 210 211 // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00 212 213 ArchSpec host_arch (Host::GetArchitecture ()); 214 const llvm::Triple &host_triple = host_arch.GetTriple(); 215 response.PutCString("triple:"); 216 response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); 217 response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); 218 219 uint32_t cpu = host_arch.GetMachOCPUType(); 220 uint32_t sub = host_arch.GetMachOCPUSubType(); 221 if (cpu != LLDB_INVALID_CPUTYPE) 222 response.Printf ("cputype:%u;", cpu); 223 if (sub != LLDB_INVALID_CPUTYPE) 224 response.Printf ("cpusubtype:%u;", sub); 225 226 switch (lldb::endian::InlHostByteOrder()) 227 { 228 case eByteOrderBig: response.PutCString ("endian:big;"); break; 229 case eByteOrderLittle: response.PutCString ("endian:little;"); break; 230 case eByteOrderPDP: response.PutCString ("endian:pdp;"); break; 231 default: response.PutCString ("endian:unknown;"); break; 232 } 233 234 uint32_t major = UINT32_MAX; 235 uint32_t minor = UINT32_MAX; 236 uint32_t update = UINT32_MAX; 237 if (Host::GetOSVersion (major, minor, update)) 238 { 239 if (major != UINT32_MAX) 240 { 241 response.Printf("os_version:%u", major); 242 if (minor != UINT32_MAX) 243 { 244 response.Printf(".%u", minor); 245 if (update != UINT32_MAX) 246 response.Printf(".%u", update); 247 } 248 response.PutChar(';'); 249 } 250 } 251 252 std::string s; 253 if (Host::GetOSBuildString (s)) 254 { 255 response.PutCString ("os_build:"); 256 response.PutCStringAsRawHex8(s.c_str()); 257 response.PutChar(';'); 258 } 259 if (Host::GetOSKernelDescription (s)) 260 { 261 response.PutCString ("os_kernel:"); 262 response.PutCStringAsRawHex8(s.c_str()); 263 response.PutChar(';'); 264 } 265 if (Host::GetHostname (s)) 266 { 267 response.PutCString ("hostname:"); 268 response.PutCStringAsRawHex8(s.c_str()); 269 response.PutChar(';'); 270 } 271 272 return SendPacketNoLock (response.GetData(), response.GetSize()) > 0; 273} 274 275static void 276CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response) 277{ 278 response.Printf ("pid:%llu;ppid:%llu;uid:%i;gid:%i;euid:%i;egid:%i;", 279 proc_info.GetProcessID(), 280 proc_info.GetParentProcessID(), 281 proc_info.GetUserID(), 282 proc_info.GetGroupID(), 283 proc_info.GetEffectiveUserID(), 284 proc_info.GetEffectiveGroupID()); 285 response.PutCString ("name:"); 286 response.PutCStringAsRawHex8(proc_info.GetName()); 287 response.PutChar(';'); 288 const ArchSpec &proc_arch = proc_info.GetArchitecture(); 289 if (proc_arch.IsValid()) 290 { 291 const llvm::Triple &proc_triple = proc_arch.GetTriple(); 292 response.PutCString("triple:"); 293 response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); 294 response.PutChar(';'); 295 } 296} 297 298bool 299GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet) 300{ 301 // Packet format: "qProcessInfoPID:%i" where %i is the pid 302 packet.SetFilePos(::strlen ("qProcessInfoPID:")); 303 lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID); 304 if (pid != LLDB_INVALID_PROCESS_ID) 305 { 306 ProcessInstanceInfo proc_info; 307 if (Host::GetProcessInfo(pid, proc_info)) 308 { 309 StreamString response; 310 CreateProcessInfoResponse (proc_info, response); 311 return SendPacketNoLock (response.GetData(), response.GetSize()); 312 } 313 } 314 return SendErrorResponse (1); 315} 316 317bool 318GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet) 319{ 320 m_proc_infos_index = 0; 321 m_proc_infos.Clear(); 322 323 ProcessInstanceInfoMatch match_info; 324 packet.SetFilePos(::strlen ("qfProcessInfo")); 325 if (packet.GetChar() == ':') 326 { 327 328 std::string key; 329 std::string value; 330 while (packet.GetNameColonValue(key, value)) 331 { 332 bool success = true; 333 if (key.compare("name") == 0) 334 { 335 StringExtractor extractor; 336 extractor.GetStringRef().swap(value); 337 extractor.GetHexByteString (value); 338 match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false); 339 } 340 else if (key.compare("name_match") == 0) 341 { 342 if (value.compare("equals") == 0) 343 { 344 match_info.SetNameMatchType (eNameMatchEquals); 345 } 346 else if (value.compare("starts_with") == 0) 347 { 348 match_info.SetNameMatchType (eNameMatchStartsWith); 349 } 350 else if (value.compare("ends_with") == 0) 351 { 352 match_info.SetNameMatchType (eNameMatchEndsWith); 353 } 354 else if (value.compare("contains") == 0) 355 { 356 match_info.SetNameMatchType (eNameMatchContains); 357 } 358 else if (value.compare("regex") == 0) 359 { 360 match_info.SetNameMatchType (eNameMatchRegularExpression); 361 } 362 else 363 { 364 success = false; 365 } 366 } 367 else if (key.compare("pid") == 0) 368 { 369 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 370 } 371 else if (key.compare("parent_pid") == 0) 372 { 373 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); 374 } 375 else if (key.compare("uid") == 0) 376 { 377 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 378 } 379 else if (key.compare("gid") == 0) 380 { 381 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 382 } 383 else if (key.compare("euid") == 0) 384 { 385 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 386 } 387 else if (key.compare("egid") == 0) 388 { 389 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); 390 } 391 else if (key.compare("all_users") == 0) 392 { 393 match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success)); 394 } 395 else if (key.compare("triple") == 0) 396 { 397 match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL); 398 } 399 else 400 { 401 success = false; 402 } 403 404 if (!success) 405 return SendErrorResponse (2); 406 } 407 } 408 409 if (Host::FindProcesses (match_info, m_proc_infos)) 410 { 411 // We found something, return the first item by calling the get 412 // subsequent process info packet handler... 413 return Handle_qsProcessInfo (packet); 414 } 415 return SendErrorResponse (3); 416} 417 418bool 419GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet) 420{ 421 if (m_proc_infos_index < m_proc_infos.GetSize()) 422 { 423 StreamString response; 424 CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); 425 ++m_proc_infos_index; 426 return SendPacketNoLock (response.GetData(), response.GetSize()); 427 } 428 return SendErrorResponse (4); 429} 430 431bool 432GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet) 433{ 434 // Packet format: "qUserName:%i" where %i is the uid 435 packet.SetFilePos(::strlen ("qUserName:")); 436 uint32_t uid = packet.GetU32 (UINT32_MAX); 437 if (uid != UINT32_MAX) 438 { 439 std::string name; 440 if (Host::GetUserName (uid, name)) 441 { 442 StreamString response; 443 response.PutCStringAsRawHex8 (name.c_str()); 444 return SendPacketNoLock (response.GetData(), response.GetSize()); 445 } 446 } 447 return SendErrorResponse (5); 448 449} 450 451bool 452GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet) 453{ 454 // Packet format: "qGroupName:%i" where %i is the gid 455 packet.SetFilePos(::strlen ("qGroupName:")); 456 uint32_t gid = packet.GetU32 (UINT32_MAX); 457 if (gid != UINT32_MAX) 458 { 459 std::string name; 460 if (Host::GetGroupName (gid, name)) 461 { 462 StreamString response; 463 response.PutCStringAsRawHex8 (name.c_str()); 464 return SendPacketNoLock (response.GetData(), response.GetSize()); 465 } 466 } 467 return SendErrorResponse (6); 468} 469 470bool 471GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet) 472{ 473 packet.SetFilePos(::strlen ("qSpeedTest:")); 474 475 std::string key; 476 std::string value; 477 bool success = packet.GetNameColonValue(key, value); 478 if (success && key.compare("response_size") == 0) 479 { 480 uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success); 481 if (success) 482 { 483 if (response_size == 0) 484 return SendOKResponse(); 485 StreamString response; 486 uint32_t bytes_left = response_size; 487 response.PutCString("data:"); 488 while (bytes_left > 0) 489 { 490 if (bytes_left >= 26) 491 { 492 response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 493 bytes_left -= 26; 494 } 495 else 496 { 497 response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 498 bytes_left = 0; 499 } 500 } 501 return SendPacketNoLock (response.GetData(), response.GetSize()); 502 } 503 } 504 return SendErrorResponse (7); 505} 506 507 508static void * 509AcceptPortFromInferior (void *arg) 510{ 511 const char *connect_url = (const char *)arg; 512 ConnectionFileDescriptor file_conn; 513 Error error; 514 if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess) 515 { 516 char pid_str[256]; 517 ::memset (pid_str, 0, sizeof(pid_str)); 518 ConnectionStatus status; 519 const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL); 520 if (pid_str_len > 0) 521 { 522 int pid = atoi (pid_str); 523 return (void *)(intptr_t)pid; 524 } 525 } 526 return NULL; 527} 528// 529//static bool 530//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds) 531//{ 532// const int time_delta_usecs = 100000; 533// const int num_retries = timeout_in_seconds/time_delta_usecs; 534// for (int i=0; i<num_retries; i++) 535// { 536// struct proc_bsdinfo bsd_info; 537// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, 538// (uint64_t) 0, 539// &bsd_info, 540// PROC_PIDTBSDINFO_SIZE); 541// 542// switch (error) 543// { 544// case EINVAL: 545// case ENOTSUP: 546// case ESRCH: 547// case EPERM: 548// return false; 549// 550// default: 551// break; 552// 553// case 0: 554// if (bsd_info.pbi_status == SSTOP) 555// return true; 556// } 557// ::usleep (time_delta_usecs); 558// } 559// return false; 560//} 561 562bool 563GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet) 564{ 565 // The 'A' packet is the most over designed packet ever here with 566 // redundant argument indexes, redundant argument lengths and needed hex 567 // encoded argument string values. Really all that is needed is a comma 568 // separated hex encoded argument value list, but we will stay true to the 569 // documented version of the 'A' packet here... 570 571 packet.SetFilePos(1); // Skip the 'A' 572 bool success = true; 573 while (success && packet.GetBytesLeft() > 0) 574 { 575 // Decode the decimal argument string length. This length is the 576 // number of hex nibbles in the argument string value. 577 const uint32_t arg_len = packet.GetU32(UINT32_MAX); 578 if (arg_len == UINT32_MAX) 579 success = false; 580 else 581 { 582 // Make sure the argument hex string length is followed by a comma 583 if (packet.GetChar() != ',') 584 success = false; 585 else 586 { 587 // Decode the argument index. We ignore this really becuase 588 // who would really send down the arguments in a random order??? 589 const uint32_t arg_idx = packet.GetU32(UINT32_MAX); 590 if (arg_idx == UINT32_MAX) 591 success = false; 592 else 593 { 594 // Make sure the argument index is followed by a comma 595 if (packet.GetChar() != ',') 596 success = false; 597 else 598 { 599 // Decode the argument string value from hex bytes 600 // back into a UTF8 string and make sure the length 601 // matches the one supplied in the packet 602 std::string arg; 603 if (packet.GetHexByteString(arg) != (arg_len / 2)) 604 success = false; 605 else 606 { 607 // If there are any bytes lft 608 if (packet.GetBytesLeft()) 609 { 610 if (packet.GetChar() != ',') 611 success = false; 612 } 613 614 if (success) 615 { 616 if (arg_idx == 0) 617 m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false); 618 m_process_launch_info.GetArguments().AppendArgument(arg.c_str()); 619 } 620 } 621 } 622 } 623 } 624 } 625 } 626 627 if (success) 628 { 629 m_process_launch_info.GetFlags().Set (eLaunchFlagDebug); 630 m_process_launch_error = Host::LaunchProcess (m_process_launch_info); 631 if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 632 { 633 return SendOKResponse (); 634 } 635 } 636 return SendErrorResponse (8); 637} 638 639bool 640GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet) 641{ 642 lldb::pid_t pid = m_process_launch_info.GetProcessID(); 643 StreamString response; 644 response.Printf("QC%llx", pid); 645 if (m_is_platform) 646 { 647 // If we launch a process and this GDB server is acting as a platform, 648 // then we need to clear the process launch state so we can start 649 // launching another process. In order to launch a process a bunch or 650 // packets need to be sent: environment packets, working directory, 651 // disable ASLR, and many more settings. When we launch a process we 652 // then need to know when to clear this information. Currently we are 653 // selecting the 'qC' packet as that packet which seems to make the most 654 // sense. 655 if (pid != LLDB_INVALID_PROCESS_ID) 656 { 657 m_process_launch_info.Clear(); 658 } 659 } 660 return SendPacketNoLock (response.GetData(), response.GetSize()); 661} 662 663bool 664GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) 665{ 666 // Spawn a local debugserver as a platform so we can then attach or launch 667 // a process... 668 669 if (m_is_platform) 670 { 671 // Sleep and wait a bit for debugserver to start to listen... 672 ConnectionFileDescriptor file_conn; 673 char connect_url[PATH_MAX]; 674 Error error; 675 char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX"; 676 if (::mktemp (unix_socket_name) == NULL) 677 { 678 error.SetErrorString ("failed to make temporary path for a unix socket"); 679 } 680 else 681 { 682 ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); 683 // Spawn a new thread to accept the port that gets bound after 684 // binding to port 0 (zero). 685 lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name, 686 AcceptPortFromInferior, 687 connect_url, 688 &error); 689 690 if (IS_VALID_LLDB_HOST_THREAD(accept_thread)) 691 { 692 // Spawn a debugserver and try to get 693 ProcessLaunchInfo debugserver_launch_info; 694 error = StartDebugserverProcess ("localhost:0", 695 unix_socket_name, 696 debugserver_launch_info); 697 698 lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); 699 if (error.Success()) 700 { 701 bool success = false; 702 703 thread_result_t accept_thread_result = NULL; 704 if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error)) 705 { 706 if (accept_thread_result) 707 { 708 uint16_t port = (intptr_t)accept_thread_result; 709 char response[256]; 710 const int response_len = ::snprintf (response, sizeof(response), "pid:%llu;port:%u;", debugserver_pid, port); 711 assert (response_len < sizeof(response)); 712 //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); 713 success = SendPacketNoLock (response, response_len) > 0; 714 } 715 } 716 ::unlink (unix_socket_name); 717 718 if (!success) 719 { 720 if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 721 ::kill (debugserver_pid, SIGINT); 722 } 723 return success; 724 } 725 } 726 } 727 } 728 return SendErrorResponse (13); 729} 730 731bool 732GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet) 733{ 734 if (m_process_launch_error.Success()) 735 return SendOKResponse(); 736 StreamString response; 737 response.PutChar('E'); 738 response.PutCString(m_process_launch_error.AsCString("<unknown error>")); 739 return SendPacketNoLock (response.GetData(), response.GetSize()); 740} 741 742bool 743GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet) 744{ 745 packet.SetFilePos(::strlen ("QEnvironment:")); 746 const uint32_t bytes_left = packet.GetBytesLeft(); 747 if (bytes_left > 0) 748 { 749 m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek()); 750 return SendOKResponse (); 751 } 752 return SendErrorResponse (9); 753} 754 755bool 756GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet) 757{ 758 packet.SetFilePos(::strlen ("QSetDisableASLR:")); 759 if (packet.GetU32(0)) 760 m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR); 761 else 762 m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR); 763 return SendOKResponse (); 764} 765 766bool 767GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet) 768{ 769 packet.SetFilePos(::strlen ("QSetWorkingDir:")); 770 std::string path; 771 packet.GetHexByteString(path); 772 m_process_launch_info.SwapWorkingDirectory (path); 773 return SendOKResponse (); 774} 775 776bool 777GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet) 778{ 779 packet.SetFilePos(::strlen ("QSetSTDIN:")); 780 ProcessLaunchInfo::FileAction file_action; 781 std::string path; 782 packet.GetHexByteString(path); 783 const bool read = false; 784 const bool write = true; 785 if (file_action.Open(STDIN_FILENO, path.c_str(), read, write)) 786 { 787 m_process_launch_info.AppendFileAction(file_action); 788 return SendOKResponse (); 789 } 790 return SendErrorResponse (10); 791} 792 793bool 794GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet) 795{ 796 packet.SetFilePos(::strlen ("QSetSTDOUT:")); 797 ProcessLaunchInfo::FileAction file_action; 798 std::string path; 799 packet.GetHexByteString(path); 800 const bool read = true; 801 const bool write = false; 802 if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write)) 803 { 804 m_process_launch_info.AppendFileAction(file_action); 805 return SendOKResponse (); 806 } 807 return SendErrorResponse (11); 808} 809 810bool 811GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet) 812{ 813 packet.SetFilePos(::strlen ("QSetSTDERR:")); 814 ProcessLaunchInfo::FileAction file_action; 815 std::string path; 816 packet.GetHexByteString(path); 817 const bool read = true; 818 const bool write = false; 819 if (file_action.Open(STDERR_FILENO, path.c_str(), read, write)) 820 { 821 m_process_launch_info.AppendFileAction(file_action); 822 return SendOKResponse (); 823 } 824 return SendErrorResponse (12); 825} 826 827bool 828GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet) 829{ 830 // Send response first before changing m_send_acks to we ack this packet 831 SendOKResponse (); 832 m_send_acks = false; 833 return true; 834} 835