1 //===-- PlatformRemoteGDBServer.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 "PlatformRemoteGDBServer.h" 11 #include "lldb/Host/Config.h" 12 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Breakpoint/BreakpointLocation.h" 17 #include "lldb/Core/Debugger.h" 18 #include "lldb/Core/Error.h" 19 #include "lldb/Core/Log.h" 20 #include "lldb/Core/Module.h" 21 #include "lldb/Core/ModuleList.h" 22 #include "lldb/Core/ModuleSpec.h" 23 #include "lldb/Core/PluginManager.h" 24 #include "lldb/Core/StreamString.h" 25 #include "lldb/Host/ConnectionFileDescriptor.h" 26 #include "lldb/Host/FileSpec.h" 27 #include "lldb/Host/Host.h" 28 #include "lldb/Host/HostInfo.h" 29 #include "lldb/Host/StringConvert.h" 30 #include "lldb/Target/Process.h" 31 #include "lldb/Target/Target.h" 32 33 #include "Utility/UriParser.h" 34 35 #include "Plugins/Process/Utility/GDBRemoteSignals.h" 36 37 using namespace lldb; 38 using namespace lldb_private; 39 using namespace lldb_private::platform_gdb_server; 40 41 static bool g_initialized = false; 42 43 void 44 PlatformRemoteGDBServer::Initialize () 45 { 46 Platform::Initialize (); 47 48 if (g_initialized == false) 49 { 50 g_initialized = true; 51 PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetPluginNameStatic(), 52 PlatformRemoteGDBServer::GetDescriptionStatic(), 53 PlatformRemoteGDBServer::CreateInstance); 54 } 55 } 56 57 void 58 PlatformRemoteGDBServer::Terminate () 59 { 60 if (g_initialized) 61 { 62 g_initialized = false; 63 PluginManager::UnregisterPlugin (PlatformRemoteGDBServer::CreateInstance); 64 } 65 66 Platform::Terminate (); 67 } 68 69 PlatformSP 70 PlatformRemoteGDBServer::CreateInstance (bool force, const ArchSpec *arch) 71 { 72 bool create = force; 73 if (!create) 74 { 75 create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified(); 76 } 77 if (create) 78 return PlatformSP(new PlatformRemoteGDBServer()); 79 return PlatformSP(); 80 } 81 82 83 ConstString 84 PlatformRemoteGDBServer::GetPluginNameStatic() 85 { 86 static ConstString g_name("remote-gdb-server"); 87 return g_name; 88 } 89 90 const char * 91 PlatformRemoteGDBServer::GetDescriptionStatic() 92 { 93 return "A platform that uses the GDB remote protocol as the communication transport."; 94 } 95 96 const char * 97 PlatformRemoteGDBServer::GetDescription () 98 { 99 if (m_platform_description.empty()) 100 { 101 if (IsConnected()) 102 { 103 // Send the get description packet 104 } 105 } 106 107 if (!m_platform_description.empty()) 108 return m_platform_description.c_str(); 109 return GetDescriptionStatic(); 110 } 111 112 Error 113 PlatformRemoteGDBServer::ResolveExecutable (const ModuleSpec &module_spec, 114 lldb::ModuleSP &exe_module_sp, 115 const FileSpecList *module_search_paths_ptr) 116 { 117 // copied from PlatformRemoteiOS 118 119 Error error; 120 // Nothing special to do here, just use the actual file and architecture 121 122 ModuleSpec resolved_module_spec(module_spec); 123 124 // Resolve any executable within an apk on Android? 125 //Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); 126 127 if (resolved_module_spec.GetFileSpec().Exists() || 128 module_spec.GetUUID().IsValid()) 129 { 130 if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid()) 131 { 132 error = ModuleList::GetSharedModule (resolved_module_spec, 133 exe_module_sp, 134 module_search_paths_ptr, 135 NULL, 136 NULL); 137 138 if (exe_module_sp && exe_module_sp->GetObjectFile()) 139 return error; 140 exe_module_sp.reset(); 141 } 142 // No valid architecture was specified or the exact arch wasn't 143 // found so ask the platform for the architectures that we should be 144 // using (in the correct order) and see if we can find a match that way 145 StreamString arch_names; 146 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx) 147 { 148 error = ModuleList::GetSharedModule (resolved_module_spec, 149 exe_module_sp, 150 module_search_paths_ptr, 151 NULL, 152 NULL); 153 // Did we find an executable using one of the 154 if (error.Success()) 155 { 156 if (exe_module_sp && exe_module_sp->GetObjectFile()) 157 break; 158 else 159 error.SetErrorToGenericError(); 160 } 161 162 if (idx > 0) 163 arch_names.PutCString (", "); 164 arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName()); 165 } 166 167 if (error.Fail() || !exe_module_sp) 168 { 169 if (resolved_module_spec.GetFileSpec().Readable()) 170 { 171 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", 172 resolved_module_spec.GetFileSpec().GetPath().c_str(), 173 GetPluginName().GetCString(), 174 arch_names.GetString().c_str()); 175 } 176 else 177 { 178 error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); 179 } 180 } 181 } 182 else 183 { 184 error.SetErrorStringWithFormat ("'%s' does not exist", 185 resolved_module_spec.GetFileSpec().GetPath().c_str()); 186 } 187 188 return error; 189 } 190 191 bool 192 PlatformRemoteGDBServer::GetModuleSpec (const FileSpec& module_file_spec, 193 const ArchSpec& arch, 194 ModuleSpec &module_spec) 195 { 196 Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM); 197 198 const auto module_path = module_file_spec.GetPath (false); 199 200 if (!m_gdb_client.GetModuleInfo (module_file_spec, arch, module_spec)) 201 { 202 if (log) 203 log->Printf ("PlatformRemoteGDBServer::%s - failed to get module info for %s:%s", 204 __FUNCTION__, module_path.c_str (), arch.GetTriple ().getTriple ().c_str ()); 205 return false; 206 } 207 208 if (log) 209 { 210 StreamString stream; 211 module_spec.Dump (stream); 212 log->Printf ("PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s", 213 __FUNCTION__, module_path.c_str (), arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ()); 214 } 215 216 return true; 217 } 218 219 Error 220 PlatformRemoteGDBServer::GetFileWithUUID (const FileSpec &platform_file, 221 const UUID *uuid_ptr, 222 FileSpec &local_file) 223 { 224 // Default to the local case 225 local_file = platform_file; 226 return Error(); 227 } 228 229 //------------------------------------------------------------------ 230 /// Default Constructor 231 //------------------------------------------------------------------ 232 PlatformRemoteGDBServer::PlatformRemoteGDBServer () : 233 Platform (false), // This is a remote platform 234 m_gdb_client () 235 { 236 } 237 238 //------------------------------------------------------------------ 239 /// Destructor. 240 /// 241 /// The destructor is virtual since this class is designed to be 242 /// inherited from by the plug-in instance. 243 //------------------------------------------------------------------ 244 PlatformRemoteGDBServer::~PlatformRemoteGDBServer() 245 { 246 } 247 248 bool 249 PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 250 { 251 ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture(); 252 253 if (idx == 0) 254 { 255 arch = remote_arch; 256 return arch.IsValid(); 257 } 258 else if (idx == 1 && remote_arch.IsValid() && remote_arch.GetTriple().isArch64Bit()) 259 { 260 arch.SetTriple(remote_arch.GetTriple().get32BitArchVariant()); 261 return arch.IsValid(); 262 } 263 return false; 264 } 265 266 size_t 267 PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) 268 { 269 // This isn't needed if the z/Z packets are supported in the GDB remote 270 // server. But we might need a packet to detect this. 271 return 0; 272 } 273 274 bool 275 PlatformRemoteGDBServer::GetRemoteOSVersion () 276 { 277 uint32_t major, minor, update; 278 if (m_gdb_client.GetOSVersion (major, minor, update)) 279 { 280 m_major_os_version = major; 281 m_minor_os_version = minor; 282 m_update_os_version = update; 283 return true; 284 } 285 return false; 286 } 287 288 bool 289 PlatformRemoteGDBServer::GetRemoteOSBuildString (std::string &s) 290 { 291 return m_gdb_client.GetOSBuildString (s); 292 } 293 294 bool 295 PlatformRemoteGDBServer::GetRemoteOSKernelDescription (std::string &s) 296 { 297 return m_gdb_client.GetOSKernelDescription (s); 298 } 299 300 // Remote Platform subclasses need to override this function 301 ArchSpec 302 PlatformRemoteGDBServer::GetRemoteSystemArchitecture () 303 { 304 return m_gdb_client.GetSystemArchitecture(); 305 } 306 307 FileSpec 308 PlatformRemoteGDBServer::GetRemoteWorkingDirectory() 309 { 310 if (IsConnected()) 311 { 312 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 313 FileSpec working_dir; 314 if (m_gdb_client.GetWorkingDir(working_dir) && log) 315 log->Printf("PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", 316 working_dir.GetCString()); 317 return working_dir; 318 } 319 else 320 { 321 return Platform::GetRemoteWorkingDirectory(); 322 } 323 } 324 325 bool 326 PlatformRemoteGDBServer::SetRemoteWorkingDirectory(const FileSpec &working_dir) 327 { 328 if (IsConnected()) 329 { 330 // Clear the working directory it case it doesn't get set correctly. This will 331 // for use to re-read it 332 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 333 if (log) 334 log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", 335 working_dir.GetCString()); 336 return m_gdb_client.SetWorkingDir(working_dir) == 0; 337 } 338 else 339 return Platform::SetRemoteWorkingDirectory(working_dir); 340 } 341 342 bool 343 PlatformRemoteGDBServer::IsConnected () const 344 { 345 return m_gdb_client.IsConnected(); 346 } 347 348 Error 349 PlatformRemoteGDBServer::ConnectRemote (Args& args) 350 { 351 Error error; 352 if (IsConnected()) 353 { 354 error.SetErrorStringWithFormat ("the platform is already connected to '%s', execute 'platform disconnect' to close the current connection", 355 GetHostname()); 356 } 357 else 358 { 359 if (args.GetArgumentCount() == 1) 360 { 361 m_gdb_client.SetConnection(new ConnectionFileDescriptor()); 362 // we're going to reuse the hostname when we connect to the debugserver 363 int port; 364 std::string path; 365 const char *url = args.GetArgumentAtIndex(0); 366 if (!url) 367 return Error("URL is null."); 368 if (!UriParser::Parse(url, m_platform_scheme, m_platform_hostname, port, path)) 369 return Error("Invalid URL: %s", url); 370 371 const ConnectionStatus status = m_gdb_client.Connect(url, &error); 372 if (status == eConnectionStatusSuccess) 373 { 374 if (m_gdb_client.HandshakeWithServer(&error)) 375 { 376 m_gdb_client.GetHostInfo(); 377 // If a working directory was set prior to connecting, send it down now 378 if (m_working_dir) 379 m_gdb_client.SetWorkingDir(m_working_dir); 380 } 381 else 382 { 383 m_gdb_client.Disconnect(); 384 if (error.Success()) 385 error.SetErrorString("handshake failed"); 386 } 387 } 388 } 389 else 390 { 391 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); 392 } 393 } 394 return error; 395 } 396 397 Error 398 PlatformRemoteGDBServer::DisconnectRemote () 399 { 400 Error error; 401 m_gdb_client.Disconnect(&error); 402 m_remote_signals_sp.reset(); 403 return error; 404 } 405 406 const char * 407 PlatformRemoteGDBServer::GetHostname () 408 { 409 m_gdb_client.GetHostname (m_name); 410 if (m_name.empty()) 411 return NULL; 412 return m_name.c_str(); 413 } 414 415 const char * 416 PlatformRemoteGDBServer::GetUserName (uint32_t uid) 417 { 418 // Try and get a cache user name first 419 const char *cached_user_name = Platform::GetUserName(uid); 420 if (cached_user_name) 421 return cached_user_name; 422 std::string name; 423 if (m_gdb_client.GetUserName(uid, name)) 424 return SetCachedUserName(uid, name.c_str(), name.size()); 425 426 SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets 427 return NULL; 428 } 429 430 const char * 431 PlatformRemoteGDBServer::GetGroupName (uint32_t gid) 432 { 433 const char *cached_group_name = Platform::GetGroupName(gid); 434 if (cached_group_name) 435 return cached_group_name; 436 std::string name; 437 if (m_gdb_client.GetGroupName(gid, name)) 438 return SetCachedGroupName(gid, name.c_str(), name.size()); 439 440 SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets 441 return NULL; 442 } 443 444 uint32_t 445 PlatformRemoteGDBServer::FindProcesses (const ProcessInstanceInfoMatch &match_info, 446 ProcessInstanceInfoList &process_infos) 447 { 448 return m_gdb_client.FindProcesses (match_info, process_infos); 449 } 450 451 bool 452 PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 453 { 454 return m_gdb_client.GetProcessInfo (pid, process_info); 455 } 456 457 458 Error 459 PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) 460 { 461 Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 462 Error error; 463 464 if (log) 465 log->Printf ("PlatformRemoteGDBServer::%s() called", __FUNCTION__); 466 467 auto num_file_actions = launch_info.GetNumFileActions (); 468 for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) 469 { 470 const auto file_action = launch_info.GetFileActionAtIndex (i); 471 if (file_action->GetAction () != FileAction::eFileActionOpen) 472 continue; 473 switch(file_action->GetFD()) 474 { 475 case STDIN_FILENO: 476 m_gdb_client.SetSTDIN(file_action->GetFileSpec()); 477 break; 478 case STDOUT_FILENO: 479 m_gdb_client.SetSTDOUT(file_action->GetFileSpec()); 480 break; 481 case STDERR_FILENO: 482 m_gdb_client.SetSTDERR(file_action->GetFileSpec()); 483 break; 484 } 485 } 486 487 m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)); 488 m_gdb_client.SetDetachOnError (launch_info.GetFlags().Test (eLaunchFlagDetachOnError)); 489 490 FileSpec working_dir = launch_info.GetWorkingDirectory(); 491 if (working_dir) 492 { 493 m_gdb_client.SetWorkingDir(working_dir); 494 } 495 496 // Send the environment and the program + arguments after we connect 497 const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector(); 498 499 if (envp) 500 { 501 const char *env_entry; 502 for (int i=0; (env_entry = envp[i]); ++i) 503 { 504 if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0) 505 break; 506 } 507 } 508 509 ArchSpec arch_spec = launch_info.GetArchitecture(); 510 const char *arch_triple = arch_spec.GetTriple().str().c_str(); 511 512 m_gdb_client.SendLaunchArchPacket(arch_triple); 513 if (log) 514 log->Printf ("PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'", __FUNCTION__, arch_triple ? arch_triple : "<NULL>"); 515 516 int arg_packet_err; 517 { 518 // Scope for the scoped timeout object 519 process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_client, 5); 520 arg_packet_err = m_gdb_client.SendArgumentsPacket (launch_info); 521 } 522 523 if (arg_packet_err == 0) 524 { 525 std::string error_str; 526 if (m_gdb_client.GetLaunchSuccess (error_str)) 527 { 528 const auto pid = m_gdb_client.GetCurrentProcessID (false); 529 if (pid != LLDB_INVALID_PROCESS_ID) 530 { 531 launch_info.SetProcessID (pid); 532 if (log) 533 log->Printf ("PlatformRemoteGDBServer::%s() pid %" PRIu64 " launched successfully", __FUNCTION__, pid); 534 } 535 else 536 { 537 if (log) 538 log->Printf ("PlatformRemoteGDBServer::%s() launch succeeded but we didn't get a valid process id back!", __FUNCTION__); 539 error.SetErrorString ("failed to get PID"); 540 } 541 } 542 else 543 { 544 error.SetErrorString (error_str.c_str()); 545 if (log) 546 log->Printf ("PlatformRemoteGDBServer::%s() launch failed: %s", __FUNCTION__, error.AsCString ()); 547 } 548 } 549 else 550 { 551 error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err); 552 } 553 return error; 554 } 555 556 Error 557 PlatformRemoteGDBServer::KillProcess (const lldb::pid_t pid) 558 { 559 if (!KillSpawnedProcess(pid)) 560 return Error("failed to kill remote spawned process"); 561 return Error(); 562 } 563 564 lldb::ProcessSP 565 PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info, 566 Debugger &debugger, 567 Target *target, // Can be NULL, if NULL create a new target, else use existing one 568 Error &error) 569 { 570 lldb::ProcessSP process_sp; 571 if (IsRemote()) 572 { 573 if (IsConnected()) 574 { 575 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 576 std::string connect_url; 577 if (!LaunchGDBServer(debugserver_pid, connect_url)) 578 { 579 error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 580 } 581 else 582 { 583 if (target == NULL) 584 { 585 TargetSP new_target_sp; 586 587 error = debugger.GetTargetList().CreateTarget (debugger, 588 NULL, 589 NULL, 590 false, 591 NULL, 592 new_target_sp); 593 target = new_target_sp.get(); 594 } 595 else 596 error.Clear(); 597 598 if (target && error.Success()) 599 { 600 debugger.GetTargetList().SetSelectedTarget(target); 601 602 // The darwin always currently uses the GDB remote debugger plug-in 603 // so even when debugging locally we are debugging remotely! 604 process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL); 605 606 if (process_sp) 607 { 608 error = process_sp->ConnectRemote (nullptr, connect_url.c_str()); 609 // Retry the connect remote one time... 610 if (error.Fail()) 611 error = process_sp->ConnectRemote (nullptr, connect_url.c_str()); 612 if (error.Success()) 613 error = process_sp->Launch(launch_info); 614 else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 615 { 616 printf ("error: connect remote failed (%s)\n", error.AsCString()); 617 KillSpawnedProcess(debugserver_pid); 618 } 619 } 620 } 621 } 622 } 623 else 624 { 625 error.SetErrorString("not connected to remote gdb server"); 626 } 627 } 628 return process_sp; 629 630 } 631 632 bool 633 PlatformRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) 634 { 635 ArchSpec remote_arch = GetRemoteSystemArchitecture (); 636 llvm::Triple &remote_triple = remote_arch.GetTriple (); 637 638 uint16_t port = 0; 639 std::string socket_name; 640 bool launch_result = false; 641 if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS) 642 { 643 // When remote debugging to iOS, we use a USB mux that always talks 644 // to localhost, so we will need the remote debugserver to accept connections 645 // only from localhost, no matter what our current hostname is 646 launch_result = m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, port, socket_name); 647 } 648 else 649 { 650 // All other hosts should use their actual hostname 651 launch_result = m_gdb_client.LaunchGDBServer (nullptr, pid, port, socket_name); 652 } 653 654 if (!launch_result) 655 return false; 656 657 connect_url = MakeGdbServerUrl(m_platform_scheme, 658 m_platform_hostname, 659 port, 660 (socket_name.empty()) ? nullptr : socket_name.c_str()); 661 return true; 662 } 663 664 bool 665 PlatformRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid) 666 { 667 return m_gdb_client.KillSpawnedProcess (pid); 668 } 669 670 lldb::ProcessSP 671 PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info, 672 Debugger &debugger, 673 Target *target, // Can be NULL, if NULL create a new target, else use existing one 674 Error &error) 675 { 676 lldb::ProcessSP process_sp; 677 if (IsRemote()) 678 { 679 if (IsConnected()) 680 { 681 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 682 std::string connect_url; 683 if (!LaunchGDBServer(debugserver_pid, connect_url)) 684 { 685 error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 686 } 687 else 688 { 689 if (target == NULL) 690 { 691 TargetSP new_target_sp; 692 693 error = debugger.GetTargetList().CreateTarget (debugger, 694 NULL, 695 NULL, 696 false, 697 NULL, 698 new_target_sp); 699 target = new_target_sp.get(); 700 } 701 else 702 error.Clear(); 703 704 if (target && error.Success()) 705 { 706 debugger.GetTargetList().SetSelectedTarget(target); 707 708 // The darwin always currently uses the GDB remote debugger plug-in 709 // so even when debugging locally we are debugging remotely! 710 process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); 711 if (process_sp) 712 { 713 error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); 714 if (error.Success()) 715 { 716 auto listener = attach_info.GetHijackListener(); 717 if (listener != nullptr) 718 process_sp->HijackProcessEvents(listener.get()); 719 error = process_sp->Attach(attach_info); 720 } 721 722 if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) 723 { 724 KillSpawnedProcess(debugserver_pid); 725 } 726 } 727 } 728 } 729 } 730 else 731 { 732 error.SetErrorString("not connected to remote gdb server"); 733 } 734 } 735 return process_sp; 736 } 737 738 Error 739 PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, uint32_t mode) 740 { 741 Error error = m_gdb_client.MakeDirectory(file_spec, mode); 742 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 743 if (log) 744 log->Printf ("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) error = %u (%s)", 745 file_spec.GetCString(), mode, error.GetError(), error.AsCString()); 746 return error; 747 } 748 749 750 Error 751 PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, 752 uint32_t &file_permissions) 753 { 754 Error error = m_gdb_client.GetFilePermissions(file_spec, file_permissions); 755 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 756 if (log) 757 log->Printf ("PlatformRemoteGDBServer::GetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", 758 file_spec.GetCString(), file_permissions, error.GetError(), error.AsCString()); 759 return error; 760 } 761 762 Error 763 PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, 764 uint32_t file_permissions) 765 { 766 Error error = m_gdb_client.SetFilePermissions(file_spec, file_permissions); 767 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 768 if (log) 769 log->Printf ("PlatformRemoteGDBServer::SetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", 770 file_spec.GetCString(), file_permissions, error.GetError(), error.AsCString()); 771 return error; 772 } 773 774 775 lldb::user_id_t 776 PlatformRemoteGDBServer::OpenFile (const FileSpec& file_spec, 777 uint32_t flags, 778 uint32_t mode, 779 Error &error) 780 { 781 return m_gdb_client.OpenFile (file_spec, flags, mode, error); 782 } 783 784 bool 785 PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error) 786 { 787 return m_gdb_client.CloseFile (fd, error); 788 } 789 790 lldb::user_id_t 791 PlatformRemoteGDBServer::GetFileSize (const FileSpec& file_spec) 792 { 793 return m_gdb_client.GetFileSize(file_spec); 794 } 795 796 uint64_t 797 PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd, 798 uint64_t offset, 799 void *dst, 800 uint64_t dst_len, 801 Error &error) 802 { 803 return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error); 804 } 805 806 uint64_t 807 PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd, 808 uint64_t offset, 809 const void* src, 810 uint64_t src_len, 811 Error &error) 812 { 813 return m_gdb_client.WriteFile (fd, offset, src, src_len, error); 814 } 815 816 Error 817 PlatformRemoteGDBServer::PutFile (const FileSpec& source, 818 const FileSpec& destination, 819 uint32_t uid, 820 uint32_t gid) 821 { 822 return Platform::PutFile(source,destination,uid,gid); 823 } 824 825 Error 826 PlatformRemoteGDBServer::CreateSymlink(const FileSpec &src, // The name of the link is in src 827 const FileSpec &dst) // The symlink points to dst 828 { 829 Error error = m_gdb_client.CreateSymlink(src, dst); 830 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 831 if (log) 832 log->Printf ("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') error = %u (%s)", 833 src.GetCString(), dst.GetCString(), error.GetError(), error.AsCString()); 834 return error; 835 } 836 837 Error 838 PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) 839 { 840 Error error = m_gdb_client.Unlink(file_spec); 841 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 842 if (log) 843 log->Printf ("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", 844 file_spec.GetCString(), error.GetError(), error.AsCString()); 845 return error; 846 } 847 848 bool 849 PlatformRemoteGDBServer::GetFileExists (const FileSpec& file_spec) 850 { 851 return m_gdb_client.GetFileExists (file_spec); 852 } 853 854 Error 855 PlatformRemoteGDBServer::RunShellCommand(const char *command, // Shouldn't be NULL 856 const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory 857 int *status_ptr, // Pass NULL if you don't want the process exit status 858 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 859 std::string *command_output, // Pass NULL if you don't want the command output 860 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 861 { 862 return m_gdb_client.RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 863 } 864 865 void 866 PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames () 867 { 868 m_trap_handlers.push_back (ConstString ("_sigtramp")); 869 } 870 871 const UnixSignalsSP & 872 PlatformRemoteGDBServer::GetRemoteUnixSignals() 873 { 874 if (!IsConnected()) 875 return Platform::GetRemoteUnixSignals(); 876 877 if (m_remote_signals_sp) 878 return m_remote_signals_sp; 879 880 // If packet not implemented or JSON failed to parse, 881 // we'll guess the signal set based on the remote architecture. 882 m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture()); 883 884 const char packet[] = "jSignalsInfo"; 885 StringExtractorGDBRemote response; 886 auto result = m_gdb_client.SendPacketAndWaitForResponse( 887 packet, strlen(packet), response, false); 888 889 if (result != decltype(result)::Success || 890 response.GetResponseType() != response.eResponse) 891 return m_remote_signals_sp; 892 893 auto object_sp = StructuredData::ParseJSON(response.GetStringRef()); 894 if (!object_sp || !object_sp->IsValid()) 895 return m_remote_signals_sp; 896 897 auto array_sp = object_sp->GetAsArray(); 898 if (!array_sp || !array_sp->IsValid()) 899 return m_remote_signals_sp; 900 901 auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>(); 902 903 bool done = array_sp->ForEach( 904 [&remote_signals_sp](StructuredData::Object *object) -> bool 905 { 906 if (!object || !object->IsValid()) 907 return false; 908 909 auto dict = object->GetAsDictionary(); 910 if (!dict || !dict->IsValid()) 911 return false; 912 913 // Signal number and signal name are required. 914 int signo; 915 if (!dict->GetValueForKeyAsInteger("signo", signo)) 916 return false; 917 918 std::string name; 919 if (!dict->GetValueForKeyAsString("name", name)) 920 return false; 921 922 // We can live without short_name, description, etc. 923 bool suppress{false}; 924 auto object_sp = dict->GetValueForKey("suppress"); 925 if (object_sp && object_sp->IsValid()) 926 suppress = object_sp->GetBooleanValue(); 927 928 bool stop{false}; 929 object_sp = dict->GetValueForKey("stop"); 930 if (object_sp && object_sp->IsValid()) 931 stop = object_sp->GetBooleanValue(); 932 933 bool notify{false}; 934 object_sp = dict->GetValueForKey("notify"); 935 if (object_sp && object_sp->IsValid()) 936 notify = object_sp->GetBooleanValue(); 937 938 std::string description{""}; 939 object_sp = dict->GetValueForKey("description"); 940 if (object_sp && object_sp->IsValid()) 941 description = object_sp->GetStringValue(); 942 943 remote_signals_sp->AddSignal(signo, 944 name.c_str(), 945 suppress, stop, notify, 946 description.c_str()); 947 return true; 948 }); 949 950 if (done) 951 m_remote_signals_sp = std::move(remote_signals_sp); 952 953 return m_remote_signals_sp; 954 } 955 956 std::string 957 PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme, 958 const std::string &platform_hostname, 959 uint16_t port, 960 const char* socket_name) 961 { 962 const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME"); 963 const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); 964 const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET"); 965 int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0; 966 967 return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(), 968 override_hostname ? override_hostname : platform_hostname.c_str(), 969 port + port_offset, 970 socket_name); 971 } 972 973 std::string 974 PlatformRemoteGDBServer::MakeUrl(const char* scheme, 975 const char* hostname, 976 uint16_t port, 977 const char* path) 978 { 979 StreamString result; 980 result.Printf("%s://%s", scheme, hostname); 981 if (port != 0) 982 result.Printf(":%u", port); 983 if (path) 984 result.Write(path, strlen(path)); 985 return result.GetString(); 986 } 987