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 uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid); 577 578 if (port == 0) 579 { 580 error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 581 } 582 else 583 { 584 if (target == NULL) 585 { 586 TargetSP new_target_sp; 587 588 error = debugger.GetTargetList().CreateTarget (debugger, 589 NULL, 590 NULL, 591 false, 592 NULL, 593 new_target_sp); 594 target = new_target_sp.get(); 595 } 596 else 597 error.Clear(); 598 599 if (target && error.Success()) 600 { 601 debugger.GetTargetList().SetSelectedTarget(target); 602 603 // The darwin always currently uses the GDB remote debugger plug-in 604 // so even when debugging locally we are debugging remotely! 605 process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL); 606 607 if (process_sp) 608 { 609 std::string connect_url = 610 MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port); 611 error = process_sp->ConnectRemote (nullptr, connect_url.c_str()); 612 // Retry the connect remote one time... 613 if (error.Fail()) 614 error = process_sp->ConnectRemote (nullptr, connect_url.c_str()); 615 if (error.Success()) 616 error = process_sp->Launch(launch_info); 617 else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) 618 { 619 printf ("error: connect remote failed (%s)\n", error.AsCString()); 620 KillSpawnedProcess(debugserver_pid); 621 } 622 } 623 } 624 } 625 } 626 else 627 { 628 error.SetErrorString("not connected to remote gdb server"); 629 } 630 } 631 return process_sp; 632 633 } 634 635 uint16_t 636 PlatformRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid) 637 { 638 ArchSpec remote_arch = GetRemoteSystemArchitecture (); 639 llvm::Triple &remote_triple = remote_arch.GetTriple (); 640 if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS) 641 { 642 // When remote debugging to iOS, we use a USB mux that always talks 643 // to localhost, so we will need the remote debugserver to accept connections 644 // only from localhost, no matter what our current hostname is 645 return m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1"); 646 } 647 else 648 { 649 // All other hosts should use their actual hostname 650 return m_gdb_client.LaunchGDBserverAndGetPort (pid, NULL); 651 } 652 } 653 654 bool 655 PlatformRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid) 656 { 657 return m_gdb_client.KillSpawnedProcess (pid); 658 } 659 660 lldb::ProcessSP 661 PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info, 662 Debugger &debugger, 663 Target *target, // Can be NULL, if NULL create a new target, else use existing one 664 Error &error) 665 { 666 lldb::ProcessSP process_sp; 667 if (IsRemote()) 668 { 669 if (IsConnected()) 670 { 671 lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; 672 uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid); 673 674 if (port == 0) 675 { 676 error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ()); 677 } 678 else 679 { 680 if (target == NULL) 681 { 682 TargetSP new_target_sp; 683 684 error = debugger.GetTargetList().CreateTarget (debugger, 685 NULL, 686 NULL, 687 false, 688 NULL, 689 new_target_sp); 690 target = new_target_sp.get(); 691 } 692 else 693 error.Clear(); 694 695 if (target && error.Success()) 696 { 697 debugger.GetTargetList().SetSelectedTarget(target); 698 699 // The darwin always currently uses the GDB remote debugger plug-in 700 // so even when debugging locally we are debugging remotely! 701 process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); 702 703 if (process_sp) 704 { 705 std::string connect_url = 706 MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port); 707 error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); 708 if (error.Success()) 709 { 710 auto listener = attach_info.GetHijackListener(); 711 if (listener != nullptr) 712 process_sp->HijackProcessEvents(listener.get()); 713 error = process_sp->Attach(attach_info); 714 } 715 716 if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) 717 { 718 KillSpawnedProcess(debugserver_pid); 719 } 720 } 721 } 722 } 723 } 724 else 725 { 726 error.SetErrorString("not connected to remote gdb server"); 727 } 728 } 729 return process_sp; 730 } 731 732 Error 733 PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec, uint32_t mode) 734 { 735 Error error = m_gdb_client.MakeDirectory(file_spec, mode); 736 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 737 if (log) 738 log->Printf ("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) error = %u (%s)", 739 file_spec.GetCString(), mode, error.GetError(), error.AsCString()); 740 return error; 741 } 742 743 744 Error 745 PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec, 746 uint32_t &file_permissions) 747 { 748 Error error = m_gdb_client.GetFilePermissions(file_spec, file_permissions); 749 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 750 if (log) 751 log->Printf ("PlatformRemoteGDBServer::GetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", 752 file_spec.GetCString(), file_permissions, error.GetError(), error.AsCString()); 753 return error; 754 } 755 756 Error 757 PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec, 758 uint32_t file_permissions) 759 { 760 Error error = m_gdb_client.SetFilePermissions(file_spec, file_permissions); 761 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 762 if (log) 763 log->Printf ("PlatformRemoteGDBServer::SetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", 764 file_spec.GetCString(), file_permissions, error.GetError(), error.AsCString()); 765 return error; 766 } 767 768 769 lldb::user_id_t 770 PlatformRemoteGDBServer::OpenFile (const FileSpec& file_spec, 771 uint32_t flags, 772 uint32_t mode, 773 Error &error) 774 { 775 return m_gdb_client.OpenFile (file_spec, flags, mode, error); 776 } 777 778 bool 779 PlatformRemoteGDBServer::CloseFile (lldb::user_id_t fd, Error &error) 780 { 781 return m_gdb_client.CloseFile (fd, error); 782 } 783 784 lldb::user_id_t 785 PlatformRemoteGDBServer::GetFileSize (const FileSpec& file_spec) 786 { 787 return m_gdb_client.GetFileSize(file_spec); 788 } 789 790 uint64_t 791 PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd, 792 uint64_t offset, 793 void *dst, 794 uint64_t dst_len, 795 Error &error) 796 { 797 return m_gdb_client.ReadFile (fd, offset, dst, dst_len, error); 798 } 799 800 uint64_t 801 PlatformRemoteGDBServer::WriteFile (lldb::user_id_t fd, 802 uint64_t offset, 803 const void* src, 804 uint64_t src_len, 805 Error &error) 806 { 807 return m_gdb_client.WriteFile (fd, offset, src, src_len, error); 808 } 809 810 Error 811 PlatformRemoteGDBServer::PutFile (const FileSpec& source, 812 const FileSpec& destination, 813 uint32_t uid, 814 uint32_t gid) 815 { 816 return Platform::PutFile(source,destination,uid,gid); 817 } 818 819 Error 820 PlatformRemoteGDBServer::CreateSymlink(const FileSpec &src, // The name of the link is in src 821 const FileSpec &dst) // The symlink points to dst 822 { 823 Error error = m_gdb_client.CreateSymlink(src, dst); 824 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 825 if (log) 826 log->Printf ("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') error = %u (%s)", 827 src.GetCString(), dst.GetCString(), error.GetError(), error.AsCString()); 828 return error; 829 } 830 831 Error 832 PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) 833 { 834 Error error = m_gdb_client.Unlink(file_spec); 835 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 836 if (log) 837 log->Printf ("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", 838 file_spec.GetCString(), error.GetError(), error.AsCString()); 839 return error; 840 } 841 842 bool 843 PlatformRemoteGDBServer::GetFileExists (const FileSpec& file_spec) 844 { 845 return m_gdb_client.GetFileExists (file_spec); 846 } 847 848 Error 849 PlatformRemoteGDBServer::RunShellCommand(const char *command, // Shouldn't be NULL 850 const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory 851 int *status_ptr, // Pass NULL if you don't want the process exit status 852 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 853 std::string *command_output, // Pass NULL if you don't want the command output 854 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 855 { 856 return m_gdb_client.RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 857 } 858 859 void 860 PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames () 861 { 862 m_trap_handlers.push_back (ConstString ("_sigtramp")); 863 } 864 865 const UnixSignalsSP & 866 PlatformRemoteGDBServer::GetRemoteUnixSignals() 867 { 868 if (!IsConnected()) 869 return Platform::GetRemoteUnixSignals(); 870 871 if (m_remote_signals_sp) 872 return m_remote_signals_sp; 873 874 // If packet not implemented or JSON failed to parse, 875 // we'll guess the signal set based on the remote architecture. 876 m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture()); 877 878 const char packet[] = "jSignalsInfo"; 879 StringExtractorGDBRemote response; 880 auto result = m_gdb_client.SendPacketAndWaitForResponse( 881 packet, strlen(packet), response, false); 882 883 if (result != decltype(result)::Success || 884 response.GetResponseType() != response.eResponse) 885 return m_remote_signals_sp; 886 887 auto object_sp = StructuredData::ParseJSON(response.GetStringRef()); 888 if (!object_sp || !object_sp->IsValid()) 889 return m_remote_signals_sp; 890 891 auto array_sp = object_sp->GetAsArray(); 892 if (!array_sp || !array_sp->IsValid()) 893 return m_remote_signals_sp; 894 895 auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>(); 896 897 bool done = array_sp->ForEach( 898 [&remote_signals_sp](StructuredData::Object *object) -> bool 899 { 900 if (!object || !object->IsValid()) 901 return false; 902 903 auto dict = object->GetAsDictionary(); 904 if (!dict || !dict->IsValid()) 905 return false; 906 907 // Signal number and signal name are required. 908 int signo; 909 if (!dict->GetValueForKeyAsInteger("signo", signo)) 910 return false; 911 912 std::string name; 913 if (!dict->GetValueForKeyAsString("name", name)) 914 return false; 915 916 // We can live without short_name, description, etc. 917 std::string short_name{""}; 918 auto object_sp = dict->GetValueForKey("short_name"); 919 if (object_sp && object_sp->IsValid()) 920 short_name = object_sp->GetStringValue(); 921 922 bool suppress{false}; 923 object_sp = dict->GetValueForKey("suppress"); 924 if (object_sp && object_sp->IsValid()) 925 suppress = object_sp->GetBooleanValue(); 926 927 bool stop{false}; 928 object_sp = dict->GetValueForKey("stop"); 929 if (object_sp && object_sp->IsValid()) 930 stop = object_sp->GetBooleanValue(); 931 932 bool notify{false}; 933 object_sp = dict->GetValueForKey("notify"); 934 if (object_sp && object_sp->IsValid()) 935 notify = object_sp->GetBooleanValue(); 936 937 std::string description{""}; 938 object_sp = dict->GetValueForKey("description"); 939 if (object_sp && object_sp->IsValid()) 940 description = object_sp->GetStringValue(); 941 942 remote_signals_sp->AddSignal(signo, 943 name.c_str(), 944 short_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 { 961 const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME"); 962 const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); 963 const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET"); 964 int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0; 965 966 return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(), 967 override_hostname ? override_hostname : platform_hostname.c_str(), 968 port + port_offset, 969 nullptr); 970 } 971 972 std::string 973 PlatformRemoteGDBServer::MakeUrl(const char* scheme, 974 const char* hostname, 975 uint16_t port, 976 const char* path) 977 { 978 StreamString result; 979 result.Printf("%s://%s:%u", scheme, hostname, port); 980 if (path) 981 result.Write(path, strlen(path)); 982 return result.GetString(); 983 } 984