Platform.cpp revision 263363
1//===-- Platform.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 "lldb/Target/Platform.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Breakpoint/BreakpointIDList.h" 17#include "lldb/Core/Error.h" 18#include "lldb/Core/Log.h" 19#include "lldb/Core/ModuleSpec.h" 20#include "lldb/Core/PluginManager.h" 21#include "lldb/Host/FileSpec.h" 22#include "lldb/Host/Host.h" 23#include "lldb/Target/Process.h" 24#include "lldb/Target/Target.h" 25#include "lldb/Utility/Utils.h" 26 27using namespace lldb; 28using namespace lldb_private; 29 30// Use a singleton function for g_local_platform_sp to avoid init 31// constructors since LLDB is often part of a shared library 32static PlatformSP& 33GetDefaultPlatformSP () 34{ 35 static PlatformSP g_default_platform_sp; 36 return g_default_platform_sp; 37} 38 39static Mutex & 40GetConnectedPlatformListMutex () 41{ 42 static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive); 43 return g_remote_connected_platforms_mutex; 44} 45static std::vector<PlatformSP> & 46GetConnectedPlatformList () 47{ 48 static std::vector<PlatformSP> g_remote_connected_platforms; 49 return g_remote_connected_platforms; 50} 51 52 53const char * 54Platform::GetHostPlatformName () 55{ 56 return "host"; 57} 58 59//------------------------------------------------------------------ 60/// Get the native host platform plug-in. 61/// 62/// There should only be one of these for each host that LLDB runs 63/// upon that should be statically compiled in and registered using 64/// preprocessor macros or other similar build mechanisms. 65/// 66/// This platform will be used as the default platform when launching 67/// or attaching to processes unless another platform is specified. 68//------------------------------------------------------------------ 69PlatformSP 70Platform::GetDefaultPlatform () 71{ 72 return GetDefaultPlatformSP (); 73} 74 75void 76Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp) 77{ 78 // The native platform should use its static void Platform::Initialize() 79 // function to register itself as the native platform. 80 GetDefaultPlatformSP () = platform_sp; 81} 82 83Error 84Platform::GetFile (const FileSpec &platform_file, 85 const UUID *uuid_ptr, 86 FileSpec &local_file) 87{ 88 // Default to the local case 89 local_file = platform_file; 90 return Error(); 91} 92 93FileSpecList 94Platform::LocateExecutableScriptingResources (Target *target, Module &module) 95{ 96 return FileSpecList(); 97} 98 99Platform* 100Platform::FindPlugin (Process *process, const ConstString &plugin_name) 101{ 102 PlatformCreateInstance create_callback = NULL; 103 if (plugin_name) 104 { 105 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name); 106 if (create_callback) 107 { 108 ArchSpec arch; 109 if (process) 110 { 111 arch = process->GetTarget().GetArchitecture(); 112 } 113 std::unique_ptr<Platform> instance_ap(create_callback(process, &arch)); 114 if (instance_ap.get()) 115 return instance_ap.release(); 116 } 117 } 118 else 119 { 120 for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx) 121 { 122 std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr)); 123 if (instance_ap.get()) 124 return instance_ap.release(); 125 } 126 } 127 return NULL; 128} 129 130Error 131Platform::GetSharedModule (const ModuleSpec &module_spec, 132 ModuleSP &module_sp, 133 const FileSpecList *module_search_paths_ptr, 134 ModuleSP *old_module_sp_ptr, 135 bool *did_create_ptr) 136{ 137 // Don't do any path remapping for the default implementation 138 // of the platform GetSharedModule function, just call through 139 // to our static ModuleList function. Platform subclasses that 140 // implement remote debugging, might have a developer kits 141 // installed that have cached versions of the files for the 142 // remote target, or might implement a download and cache 143 // locally implementation. 144 const bool always_create = false; 145 return ModuleList::GetSharedModule (module_spec, 146 module_sp, 147 module_search_paths_ptr, 148 old_module_sp_ptr, 149 did_create_ptr, 150 always_create); 151} 152 153PlatformSP 154Platform::Create (const char *platform_name, Error &error) 155{ 156 PlatformCreateInstance create_callback = NULL; 157 lldb::PlatformSP platform_sp; 158 if (platform_name && platform_name[0]) 159 { 160 ConstString const_platform_name (platform_name); 161 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (const_platform_name); 162 if (create_callback) 163 platform_sp.reset(create_callback(true, NULL)); 164 else 165 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name); 166 } 167 else 168 error.SetErrorString ("invalid platform name"); 169 return platform_sp; 170} 171 172 173PlatformSP 174Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error) 175{ 176 lldb::PlatformSP platform_sp; 177 if (arch.IsValid()) 178 { 179 uint32_t idx; 180 PlatformCreateInstance create_callback; 181 // First try exact arch matches across all platform plug-ins 182 bool exact = true; 183 for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) 184 { 185 if (create_callback) 186 { 187 platform_sp.reset(create_callback(false, &arch)); 188 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr)) 189 return platform_sp; 190 } 191 } 192 // Next try compatible arch matches across all platform plug-ins 193 exact = false; 194 for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) 195 { 196 if (create_callback) 197 { 198 platform_sp.reset(create_callback(false, &arch)); 199 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr)) 200 return platform_sp; 201 } 202 } 203 } 204 else 205 error.SetErrorString ("invalid platform name"); 206 if (platform_arch_ptr) 207 platform_arch_ptr->Clear(); 208 platform_sp.reset(); 209 return platform_sp; 210} 211 212uint32_t 213Platform::GetNumConnectedRemotePlatforms () 214{ 215 Mutex::Locker locker (GetConnectedPlatformListMutex ()); 216 return GetConnectedPlatformList().size(); 217} 218 219PlatformSP 220Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx) 221{ 222 PlatformSP platform_sp; 223 { 224 Mutex::Locker locker (GetConnectedPlatformListMutex ()); 225 if (idx < GetConnectedPlatformList().size()) 226 platform_sp = GetConnectedPlatformList ()[idx]; 227 } 228 return platform_sp; 229} 230 231//------------------------------------------------------------------ 232/// Default Constructor 233//------------------------------------------------------------------ 234Platform::Platform (bool is_host) : 235 m_is_host (is_host), 236 m_os_version_set_while_connected (false), 237 m_system_arch_set_while_connected (false), 238 m_sdk_sysroot (), 239 m_sdk_build (), 240 m_remote_url (), 241 m_name (), 242 m_major_os_version (UINT32_MAX), 243 m_minor_os_version (UINT32_MAX), 244 m_update_os_version (UINT32_MAX), 245 m_system_arch(), 246 m_uid_map_mutex (Mutex::eMutexTypeNormal), 247 m_gid_map_mutex (Mutex::eMutexTypeNormal), 248 m_uid_map(), 249 m_gid_map(), 250 m_max_uid_name_len (0), 251 m_max_gid_name_len (0), 252 m_supports_rsync (false), 253 m_rsync_opts (), 254 m_rsync_prefix (), 255 m_supports_ssh (false), 256 m_ssh_opts (), 257 m_ignores_remote_hostname (false) 258{ 259 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 260 if (log) 261 log->Printf ("%p Platform::Platform()", this); 262} 263 264//------------------------------------------------------------------ 265/// Destructor. 266/// 267/// The destructor is virtual since this class is designed to be 268/// inherited from by the plug-in instance. 269//------------------------------------------------------------------ 270Platform::~Platform() 271{ 272 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 273 if (log) 274 log->Printf ("%p Platform::~Platform()", this); 275} 276 277void 278Platform::GetStatus (Stream &strm) 279{ 280 uint32_t major = UINT32_MAX; 281 uint32_t minor = UINT32_MAX; 282 uint32_t update = UINT32_MAX; 283 std::string s; 284 strm.Printf (" Platform: %s\n", GetPluginName().GetCString()); 285 286 ArchSpec arch (GetSystemArchitecture()); 287 if (arch.IsValid()) 288 { 289 if (!arch.GetTriple().str().empty()) 290 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str()); 291 } 292 293 if (GetOSVersion(major, minor, update)) 294 { 295 strm.Printf("OS Version: %u", major); 296 if (minor != UINT32_MAX) 297 strm.Printf(".%u", minor); 298 if (update != UINT32_MAX) 299 strm.Printf(".%u", update); 300 301 if (GetOSBuildString (s)) 302 strm.Printf(" (%s)", s.c_str()); 303 304 strm.EOL(); 305 } 306 307 if (GetOSKernelDescription (s)) 308 strm.Printf(" Kernel: %s\n", s.c_str()); 309 310 if (IsHost()) 311 { 312 strm.Printf(" Hostname: %s\n", GetHostname()); 313 } 314 else 315 { 316 const bool is_connected = IsConnected(); 317 if (is_connected) 318 strm.Printf(" Hostname: %s\n", GetHostname()); 319 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); 320 } 321 322 if (!IsConnected()) 323 return; 324 325 std::string specific_info(GetPlatformSpecificConnectionInformation()); 326 327 if (specific_info.empty() == false) 328 strm.Printf("Platform-specific connection: %s\n", specific_info.c_str()); 329} 330 331 332bool 333Platform::GetOSVersion (uint32_t &major, 334 uint32_t &minor, 335 uint32_t &update) 336{ 337 bool success = m_major_os_version != UINT32_MAX; 338 if (IsHost()) 339 { 340 if (!success) 341 { 342 // We have a local host platform 343 success = Host::GetOSVersion (m_major_os_version, 344 m_minor_os_version, 345 m_update_os_version); 346 m_os_version_set_while_connected = success; 347 } 348 } 349 else 350 { 351 // We have a remote platform. We can only fetch the remote 352 // OS version if we are connected, and we don't want to do it 353 // more than once. 354 355 const bool is_connected = IsConnected(); 356 357 bool fetch = false; 358 if (success) 359 { 360 // We have valid OS version info, check to make sure it wasn't 361 // manually set prior to connecting. If it was manually set prior 362 // to connecting, then lets fetch the actual OS version info 363 // if we are now connected. 364 if (is_connected && !m_os_version_set_while_connected) 365 fetch = true; 366 } 367 else 368 { 369 // We don't have valid OS version info, fetch it if we are connected 370 fetch = is_connected; 371 } 372 373 if (fetch) 374 { 375 success = GetRemoteOSVersion (); 376 m_os_version_set_while_connected = success; 377 } 378 } 379 380 if (success) 381 { 382 major = m_major_os_version; 383 minor = m_minor_os_version; 384 update = m_update_os_version; 385 } 386 return success; 387} 388 389bool 390Platform::GetOSBuildString (std::string &s) 391{ 392 if (IsHost()) 393 return Host::GetOSBuildString (s); 394 else 395 return GetRemoteOSBuildString (s); 396} 397 398bool 399Platform::GetOSKernelDescription (std::string &s) 400{ 401 if (IsHost()) 402 return Host::GetOSKernelDescription (s); 403 else 404 return GetRemoteOSKernelDescription (s); 405} 406 407ConstString 408Platform::GetName () 409{ 410 const char *name = GetHostname(); 411 if (name == NULL || name[0] == '\0') 412 return GetPluginName(); 413 return ConstString (name); 414} 415 416const char * 417Platform::GetHostname () 418{ 419 if (IsHost()) 420 return "localhost"; 421 422 if (m_name.empty()) 423 return NULL; 424 return m_name.c_str(); 425} 426 427const char * 428Platform::GetUserName (uint32_t uid) 429{ 430 const char *user_name = GetCachedUserName(uid); 431 if (user_name) 432 return user_name; 433 if (IsHost()) 434 { 435 std::string name; 436 if (Host::GetUserName(uid, name)) 437 return SetCachedUserName (uid, name.c_str(), name.size()); 438 } 439 return NULL; 440} 441 442const char * 443Platform::GetGroupName (uint32_t gid) 444{ 445 const char *group_name = GetCachedGroupName(gid); 446 if (group_name) 447 return group_name; 448 if (IsHost()) 449 { 450 std::string name; 451 if (Host::GetGroupName(gid, name)) 452 return SetCachedGroupName (gid, name.c_str(), name.size()); 453 } 454 return NULL; 455} 456 457bool 458Platform::SetOSVersion (uint32_t major, 459 uint32_t minor, 460 uint32_t update) 461{ 462 if (IsHost()) 463 { 464 // We don't need anyone setting the OS version for the host platform, 465 // we should be able to figure it out by calling Host::GetOSVersion(...). 466 return false; 467 } 468 else 469 { 470 // We have a remote platform, allow setting the target OS version if 471 // we aren't connected, since if we are connected, we should be able to 472 // request the remote OS version from the connected platform. 473 if (IsConnected()) 474 return false; 475 else 476 { 477 // We aren't connected and we might want to set the OS version 478 // ahead of time before we connect so we can peruse files and 479 // use a local SDK or PDK cache of support files to disassemble 480 // or do other things. 481 m_major_os_version = major; 482 m_minor_os_version = minor; 483 m_update_os_version = update; 484 return true; 485 } 486 } 487 return false; 488} 489 490 491Error 492Platform::ResolveExecutable (const FileSpec &exe_file, 493 const ArchSpec &exe_arch, 494 lldb::ModuleSP &exe_module_sp, 495 const FileSpecList *module_search_paths_ptr) 496{ 497 Error error; 498 if (exe_file.Exists()) 499 { 500 ModuleSpec module_spec (exe_file, exe_arch); 501 if (module_spec.GetArchitecture().IsValid()) 502 { 503 error = ModuleList::GetSharedModule (module_spec, 504 exe_module_sp, 505 module_search_paths_ptr, 506 NULL, 507 NULL); 508 } 509 else 510 { 511 // No valid architecture was specified, ask the platform for 512 // the architectures that we should be using (in the correct order) 513 // and see if we can find a match that way 514 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) 515 { 516 error = ModuleList::GetSharedModule (module_spec, 517 exe_module_sp, 518 module_search_paths_ptr, 519 NULL, 520 NULL); 521 // Did we find an executable using one of the 522 if (error.Success() && exe_module_sp) 523 break; 524 } 525 } 526 } 527 else 528 { 529 error.SetErrorStringWithFormat ("'%s' does not exist", 530 exe_file.GetPath().c_str()); 531 } 532 return error; 533} 534 535Error 536Platform::ResolveSymbolFile (Target &target, 537 const ModuleSpec &sym_spec, 538 FileSpec &sym_file) 539{ 540 Error error; 541 if (sym_spec.GetSymbolFileSpec().Exists()) 542 sym_file = sym_spec.GetSymbolFileSpec(); 543 else 544 error.SetErrorString("unable to resolve symbol file"); 545 return error; 546 547} 548 549 550 551bool 552Platform::ResolveRemotePath (const FileSpec &platform_path, 553 FileSpec &resolved_platform_path) 554{ 555 resolved_platform_path = platform_path; 556 return resolved_platform_path.ResolvePath(); 557} 558 559 560const ArchSpec & 561Platform::GetSystemArchitecture() 562{ 563 if (IsHost()) 564 { 565 if (!m_system_arch.IsValid()) 566 { 567 // We have a local host platform 568 m_system_arch = Host::GetArchitecture(); 569 m_system_arch_set_while_connected = m_system_arch.IsValid(); 570 } 571 } 572 else 573 { 574 // We have a remote platform. We can only fetch the remote 575 // system architecture if we are connected, and we don't want to do it 576 // more than once. 577 578 const bool is_connected = IsConnected(); 579 580 bool fetch = false; 581 if (m_system_arch.IsValid()) 582 { 583 // We have valid OS version info, check to make sure it wasn't 584 // manually set prior to connecting. If it was manually set prior 585 // to connecting, then lets fetch the actual OS version info 586 // if we are now connected. 587 if (is_connected && !m_system_arch_set_while_connected) 588 fetch = true; 589 } 590 else 591 { 592 // We don't have valid OS version info, fetch it if we are connected 593 fetch = is_connected; 594 } 595 596 if (fetch) 597 { 598 m_system_arch = GetRemoteSystemArchitecture (); 599 m_system_arch_set_while_connected = m_system_arch.IsValid(); 600 } 601 } 602 return m_system_arch; 603} 604 605 606Error 607Platform::ConnectRemote (Args& args) 608{ 609 Error error; 610 if (IsHost()) 611 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString()); 612 else 613 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString()); 614 return error; 615} 616 617Error 618Platform::DisconnectRemote () 619{ 620 Error error; 621 if (IsHost()) 622 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString()); 623 else 624 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString()); 625 return error; 626} 627 628bool 629Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 630{ 631 // Take care of the host case so that each subclass can just 632 // call this function to get the host functionality. 633 if (IsHost()) 634 return Host::GetProcessInfo (pid, process_info); 635 return false; 636} 637 638uint32_t 639Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info, 640 ProcessInstanceInfoList &process_infos) 641{ 642 // Take care of the host case so that each subclass can just 643 // call this function to get the host functionality. 644 uint32_t match_count = 0; 645 if (IsHost()) 646 match_count = Host::FindProcesses (match_info, process_infos); 647 return match_count; 648} 649 650 651Error 652Platform::LaunchProcess (ProcessLaunchInfo &launch_info) 653{ 654 Error error; 655 // Take care of the host case so that each subclass can just 656 // call this function to get the host functionality. 657 if (IsHost()) 658 { 659 if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY")) 660 launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY); 661 662 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 663 { 664 const bool is_localhost = true; 665 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); 666 const bool first_arg_is_full_shell_command = false; 667 uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info); 668 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, 669 is_localhost, 670 will_debug, 671 first_arg_is_full_shell_command, 672 num_resumes)) 673 return error; 674 } 675 676 error = Host::LaunchProcess (launch_info); 677 } 678 else 679 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes"); 680 return error; 681} 682 683lldb::ProcessSP 684Platform::DebugProcess (ProcessLaunchInfo &launch_info, 685 Debugger &debugger, 686 Target *target, // Can be NULL, if NULL create a new target, else use existing one 687 Listener &listener, 688 Error &error) 689{ 690 ProcessSP process_sp; 691 // Make sure we stop at the entry point 692 launch_info.GetFlags ().Set (eLaunchFlagDebug); 693 // We always launch the process we are going to debug in a separate process 694 // group, since then we can handle ^C interrupts ourselves w/o having to worry 695 // about the target getting them as well. 696 launch_info.SetLaunchInSeparateProcessGroup(true); 697 698 error = LaunchProcess (launch_info); 699 if (error.Success()) 700 { 701 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 702 { 703 ProcessAttachInfo attach_info (launch_info); 704 process_sp = Attach (attach_info, debugger, target, listener, error); 705 if (process_sp) 706 { 707 // Since we attached to the process, it will think it needs to detach 708 // if the process object just goes away without an explicit call to 709 // Process::Kill() or Process::Detach(), so let it know to kill the 710 // process if this happens. 711 process_sp->SetShouldDetach (false); 712 713 // If we didn't have any file actions, the pseudo terminal might 714 // have been used where the slave side was given as the file to 715 // open for stdin/out/err after we have already opened the master 716 // so we can read/write stdin/out/err. 717 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 718 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) 719 { 720 process_sp->SetSTDIOFileDescriptor(pty_fd); 721 } 722 } 723 } 724 } 725 return process_sp; 726} 727 728 729lldb::PlatformSP 730Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr) 731{ 732 lldb::PlatformSP platform_sp; 733 Error error; 734 if (arch.IsValid()) 735 platform_sp = Platform::Create (arch, platform_arch_ptr, error); 736 return platform_sp; 737} 738 739 740//------------------------------------------------------------------ 741/// Lets a platform answer if it is compatible with a given 742/// architecture and the target triple contained within. 743//------------------------------------------------------------------ 744bool 745Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr) 746{ 747 // If the architecture is invalid, we must answer true... 748 if (arch.IsValid()) 749 { 750 ArchSpec platform_arch; 751 // Try for an exact architecture match first. 752 if (exact_arch_match) 753 { 754 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 755 { 756 if (arch.IsExactMatch(platform_arch)) 757 { 758 if (compatible_arch_ptr) 759 *compatible_arch_ptr = platform_arch; 760 return true; 761 } 762 } 763 } 764 else 765 { 766 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 767 { 768 if (arch.IsCompatibleMatch(platform_arch)) 769 { 770 if (compatible_arch_ptr) 771 *compatible_arch_ptr = platform_arch; 772 return true; 773 } 774 } 775 } 776 } 777 if (compatible_arch_ptr) 778 compatible_arch_ptr->Clear(); 779 return false; 780} 781 782uint32_t 783Platform::MakeDirectory (const FileSpec &spec, 784 mode_t mode) 785{ 786 std::string path(spec.GetPath()); 787 return this->MakeDirectory(path,mode); 788} 789 790Error 791Platform::PutFile (const FileSpec& source, 792 const FileSpec& destination, 793 uint32_t uid, 794 uint32_t gid) 795{ 796 Error error("unimplemented"); 797 return error; 798} 799 800Error 801Platform::GetFile (const FileSpec& source, 802 const FileSpec& destination) 803{ 804 Error error("unimplemented"); 805 return error; 806} 807 808bool 809Platform::GetFileExists (const lldb_private::FileSpec& file_spec) 810{ 811 return false; 812} 813 814lldb_private::Error 815Platform::RunShellCommand (const char *command, // Shouldn't be NULL 816 const char *working_dir, // Pass NULL to use the current working directory 817 int *status_ptr, // Pass NULL if you don't want the process exit status 818 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 819 std::string *command_output, // Pass NULL if you don't want the command output 820 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 821{ 822 if (IsHost()) 823 return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 824 else 825 return Error("unimplemented"); 826} 827 828 829bool 830Platform::CalculateMD5 (const FileSpec& file_spec, 831 uint64_t &low, 832 uint64_t &high) 833{ 834 if (IsHost()) 835 return Host::CalculateMD5(file_spec, low, high); 836 else 837 return false; 838} 839 840void 841Platform::SetLocalCacheDirectory (const char* local) 842{ 843 m_local_cache_directory.assign(local); 844} 845 846const char* 847Platform::GetLocalCacheDirectory () 848{ 849 return m_local_cache_directory.c_str(); 850} 851 852static OptionDefinition 853g_rsync_option_table[] = 854{ 855 { LLDB_OPT_SET_ALL, false, "rsync" , 'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Enable rsync." }, 856 { LLDB_OPT_SET_ALL, false, "rsync-opts" , 'R', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific options required for rsync to work." }, 857 { LLDB_OPT_SET_ALL, false, "rsync-prefix" , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific rsync prefix put before the remote path." }, 858 { LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Do not automatically fill in the remote hostname when composing the rsync command." }, 859}; 860 861static OptionDefinition 862g_ssh_option_table[] = 863{ 864 { LLDB_OPT_SET_ALL, false, "ssh" , 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone , "Enable SSH." }, 865 { LLDB_OPT_SET_ALL, false, "ssh-opts" , 'S', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCommandName , "Platform-specific options required for SSH to work." }, 866}; 867 868static OptionDefinition 869g_caching_option_table[] = 870{ 871 { LLDB_OPT_SET_ALL, false, "local-cache-dir" , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypePath , "Path in which to store local copies of files." }, 872}; 873 874OptionGroupPlatformRSync::OptionGroupPlatformRSync () 875{ 876} 877 878OptionGroupPlatformRSync::~OptionGroupPlatformRSync () 879{ 880} 881 882const lldb_private::OptionDefinition* 883OptionGroupPlatformRSync::GetDefinitions () 884{ 885 return g_rsync_option_table; 886} 887 888void 889OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter) 890{ 891 m_rsync = false; 892 m_rsync_opts.clear(); 893 m_rsync_prefix.clear(); 894 m_ignores_remote_hostname = false; 895} 896 897lldb_private::Error 898OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter, 899 uint32_t option_idx, 900 const char *option_arg) 901{ 902 Error error; 903 char short_option = (char) GetDefinitions()[option_idx].short_option; 904 switch (short_option) 905 { 906 case 'r': 907 m_rsync = true; 908 break; 909 910 case 'R': 911 m_rsync_opts.assign(option_arg); 912 break; 913 914 case 'P': 915 m_rsync_prefix.assign(option_arg); 916 break; 917 918 case 'i': 919 m_ignores_remote_hostname = true; 920 break; 921 922 default: 923 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 924 break; 925 } 926 927 return error; 928} 929 930uint32_t 931OptionGroupPlatformRSync::GetNumDefinitions () 932{ 933 return llvm::array_lengthof(g_rsync_option_table); 934} 935 936lldb::BreakpointSP 937Platform::SetThreadCreationBreakpoint (lldb_private::Target &target) 938{ 939 return lldb::BreakpointSP(); 940} 941 942OptionGroupPlatformSSH::OptionGroupPlatformSSH () 943{ 944} 945 946OptionGroupPlatformSSH::~OptionGroupPlatformSSH () 947{ 948} 949 950const lldb_private::OptionDefinition* 951OptionGroupPlatformSSH::GetDefinitions () 952{ 953 return g_ssh_option_table; 954} 955 956void 957OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter) 958{ 959 m_ssh = false; 960 m_ssh_opts.clear(); 961} 962 963lldb_private::Error 964OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter, 965 uint32_t option_idx, 966 const char *option_arg) 967{ 968 Error error; 969 char short_option = (char) GetDefinitions()[option_idx].short_option; 970 switch (short_option) 971 { 972 case 's': 973 m_ssh = true; 974 break; 975 976 case 'S': 977 m_ssh_opts.assign(option_arg); 978 break; 979 980 default: 981 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 982 break; 983 } 984 985 return error; 986} 987 988uint32_t 989OptionGroupPlatformSSH::GetNumDefinitions () 990{ 991 return llvm::array_lengthof(g_ssh_option_table); 992} 993 994OptionGroupPlatformCaching::OptionGroupPlatformCaching () 995{ 996} 997 998OptionGroupPlatformCaching::~OptionGroupPlatformCaching () 999{ 1000} 1001 1002const lldb_private::OptionDefinition* 1003OptionGroupPlatformCaching::GetDefinitions () 1004{ 1005 return g_caching_option_table; 1006} 1007 1008void 1009OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter) 1010{ 1011 m_cache_dir.clear(); 1012} 1013 1014lldb_private::Error 1015OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter, 1016 uint32_t option_idx, 1017 const char *option_arg) 1018{ 1019 Error error; 1020 char short_option = (char) GetDefinitions()[option_idx].short_option; 1021 switch (short_option) 1022 { 1023 case 'c': 1024 m_cache_dir.assign(option_arg); 1025 break; 1026 1027 default: 1028 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1029 break; 1030 } 1031 1032 return error; 1033} 1034 1035uint32_t 1036OptionGroupPlatformCaching::GetNumDefinitions () 1037{ 1038 return llvm::array_lengthof(g_caching_option_table); 1039} 1040 1041size_t 1042Platform::GetEnvironment (StringList &environment) 1043{ 1044 environment.Clear(); 1045 return false; 1046} 1047