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/DataBufferHeap.h" 18 #include "lldb/Core/Error.h" 19 #include "lldb/Core/Log.h" 20 #include "lldb/Core/ModuleSpec.h" 21 #include "lldb/Core/PluginManager.h" 22 #include "lldb/Core/StructuredData.h" 23 #include "lldb/Host/FileSpec.h" 24 #include "lldb/Host/FileSystem.h" 25 #include "lldb/Host/Host.h" 26 #include "lldb/Host/HostInfo.h" 27 #include "lldb/Target/Process.h" 28 #include "lldb/Target/Target.h" 29 #include "lldb/Utility/Utils.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 static uint32_t g_initialize_count = 0; 35 36 // Use a singleton function for g_local_platform_sp to avoid init 37 // constructors since LLDB is often part of a shared library 38 static PlatformSP& 39 GetHostPlatformSP () 40 { 41 static PlatformSP g_platform_sp; 42 return g_platform_sp; 43 } 44 45 const char * 46 Platform::GetHostPlatformName () 47 { 48 return "host"; 49 } 50 51 //------------------------------------------------------------------ 52 /// Get the native host platform plug-in. 53 /// 54 /// There should only be one of these for each host that LLDB runs 55 /// upon that should be statically compiled in and registered using 56 /// preprocessor macros or other similar build mechanisms. 57 /// 58 /// This platform will be used as the default platform when launching 59 /// or attaching to processes unless another platform is specified. 60 //------------------------------------------------------------------ 61 PlatformSP 62 Platform::GetHostPlatform () 63 { 64 return GetHostPlatformSP (); 65 } 66 67 static std::vector<PlatformSP> & 68 GetPlatformList() 69 { 70 static std::vector<PlatformSP> g_platform_list; 71 return g_platform_list; 72 } 73 74 static Mutex & 75 GetPlatformListMutex () 76 { 77 static Mutex g_mutex(Mutex::eMutexTypeRecursive); 78 return g_mutex; 79 } 80 81 void 82 Platform::Initialize () 83 { 84 g_initialize_count++; 85 } 86 87 void 88 Platform::Terminate () 89 { 90 if (g_initialize_count > 0) 91 { 92 if (--g_initialize_count == 0) 93 { 94 Mutex::Locker locker(GetPlatformListMutex ()); 95 GetPlatformList().clear(); 96 } 97 } 98 } 99 100 void 101 Platform::SetHostPlatform (const lldb::PlatformSP &platform_sp) 102 { 103 // The native platform should use its static void Platform::Initialize() 104 // function to register itself as the native platform. 105 GetHostPlatformSP () = platform_sp; 106 107 if (platform_sp) 108 { 109 Mutex::Locker locker(GetPlatformListMutex ()); 110 GetPlatformList().push_back(platform_sp); 111 } 112 } 113 114 Error 115 Platform::GetFileWithUUID (const FileSpec &platform_file, 116 const UUID *uuid_ptr, 117 FileSpec &local_file) 118 { 119 // Default to the local case 120 local_file = platform_file; 121 return Error(); 122 } 123 124 FileSpecList 125 Platform::LocateExecutableScriptingResources (Target *target, Module &module, Stream* feedback_stream) 126 { 127 return FileSpecList(); 128 } 129 130 //PlatformSP 131 //Platform::FindPlugin (Process *process, const ConstString &plugin_name) 132 //{ 133 // PlatformCreateInstance create_callback = NULL; 134 // if (plugin_name) 135 // { 136 // create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name); 137 // if (create_callback) 138 // { 139 // ArchSpec arch; 140 // if (process) 141 // { 142 // arch = process->GetTarget().GetArchitecture(); 143 // } 144 // PlatformSP platform_sp(create_callback(process, &arch)); 145 // if (platform_sp) 146 // return platform_sp; 147 // } 148 // } 149 // else 150 // { 151 // for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx) 152 // { 153 // PlatformSP platform_sp(create_callback(process, nullptr)); 154 // if (platform_sp) 155 // return platform_sp; 156 // } 157 // } 158 // return PlatformSP(); 159 //} 160 161 Error 162 Platform::GetSharedModule (const ModuleSpec &module_spec, 163 ModuleSP &module_sp, 164 const FileSpecList *module_search_paths_ptr, 165 ModuleSP *old_module_sp_ptr, 166 bool *did_create_ptr) 167 { 168 // Don't do any path remapping for the default implementation 169 // of the platform GetSharedModule function, just call through 170 // to our static ModuleList function. Platform subclasses that 171 // implement remote debugging, might have a developer kits 172 // installed that have cached versions of the files for the 173 // remote target, or might implement a download and cache 174 // locally implementation. 175 const bool always_create = false; 176 return ModuleList::GetSharedModule (module_spec, 177 module_sp, 178 module_search_paths_ptr, 179 old_module_sp_ptr, 180 did_create_ptr, 181 always_create); 182 } 183 184 PlatformSP 185 Platform::Find (const ConstString &name) 186 { 187 if (name) 188 { 189 static ConstString g_host_platform_name ("host"); 190 if (name == g_host_platform_name) 191 return GetHostPlatform(); 192 193 Mutex::Locker locker(GetPlatformListMutex ()); 194 for (const auto &platform_sp : GetPlatformList()) 195 { 196 if (platform_sp->GetName() == name) 197 return platform_sp; 198 } 199 } 200 return PlatformSP(); 201 } 202 203 PlatformSP 204 Platform::Create (const ConstString &name, Error &error) 205 { 206 PlatformCreateInstance create_callback = NULL; 207 lldb::PlatformSP platform_sp; 208 if (name) 209 { 210 static ConstString g_host_platform_name ("host"); 211 if (name == g_host_platform_name) 212 return GetHostPlatform(); 213 214 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (name); 215 if (create_callback) 216 platform_sp = create_callback(true, NULL); 217 else 218 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", name.GetCString()); 219 } 220 else 221 error.SetErrorString ("invalid platform name"); 222 223 if (platform_sp) 224 { 225 Mutex::Locker locker(GetPlatformListMutex ()); 226 GetPlatformList().push_back(platform_sp); 227 } 228 229 return platform_sp; 230 } 231 232 233 PlatformSP 234 Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error) 235 { 236 lldb::PlatformSP platform_sp; 237 if (arch.IsValid()) 238 { 239 // Scope for locker 240 { 241 // First try exact arch matches across all platforms already created 242 Mutex::Locker locker(GetPlatformListMutex ()); 243 for (const auto &platform_sp : GetPlatformList()) 244 { 245 if (platform_sp->IsCompatibleArchitecture(arch, true, platform_arch_ptr)) 246 return platform_sp; 247 } 248 249 // Next try compatible arch matches across all platforms already created 250 for (const auto &platform_sp : GetPlatformList()) 251 { 252 if (platform_sp->IsCompatibleArchitecture(arch, false, platform_arch_ptr)) 253 return platform_sp; 254 } 255 } 256 257 PlatformCreateInstance create_callback; 258 // First try exact arch matches across all platform plug-ins 259 uint32_t idx; 260 for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) 261 { 262 if (create_callback) 263 { 264 platform_sp = create_callback(false, &arch); 265 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, true, platform_arch_ptr)) 266 { 267 Mutex::Locker locker(GetPlatformListMutex ()); 268 GetPlatformList().push_back(platform_sp); 269 return platform_sp; 270 } 271 } 272 } 273 // Next try compatible arch matches across all platform plug-ins 274 for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) 275 { 276 if (create_callback) 277 { 278 platform_sp = create_callback(false, &arch); 279 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, false, platform_arch_ptr)) 280 { 281 Mutex::Locker locker(GetPlatformListMutex ()); 282 GetPlatformList().push_back(platform_sp); 283 return platform_sp; 284 } 285 } 286 } 287 } 288 else 289 error.SetErrorString ("invalid platform name"); 290 if (platform_arch_ptr) 291 platform_arch_ptr->Clear(); 292 platform_sp.reset(); 293 return platform_sp; 294 } 295 296 //------------------------------------------------------------------ 297 /// Default Constructor 298 //------------------------------------------------------------------ 299 Platform::Platform (bool is_host) : 300 m_is_host (is_host), 301 m_os_version_set_while_connected (false), 302 m_system_arch_set_while_connected (false), 303 m_sdk_sysroot (), 304 m_sdk_build (), 305 m_working_dir (), 306 m_remote_url (), 307 m_name (), 308 m_major_os_version (UINT32_MAX), 309 m_minor_os_version (UINT32_MAX), 310 m_update_os_version (UINT32_MAX), 311 m_system_arch(), 312 m_mutex (Mutex::eMutexTypeRecursive), 313 m_uid_map(), 314 m_gid_map(), 315 m_max_uid_name_len (0), 316 m_max_gid_name_len (0), 317 m_supports_rsync (false), 318 m_rsync_opts (), 319 m_rsync_prefix (), 320 m_supports_ssh (false), 321 m_ssh_opts (), 322 m_ignores_remote_hostname (false), 323 m_trap_handlers(), 324 m_calculated_trap_handlers (false) 325 { 326 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 327 if (log) 328 log->Printf ("%p Platform::Platform()", static_cast<void*>(this)); 329 } 330 331 //------------------------------------------------------------------ 332 /// Destructor. 333 /// 334 /// The destructor is virtual since this class is designed to be 335 /// inherited from by the plug-in instance. 336 //------------------------------------------------------------------ 337 Platform::~Platform() 338 { 339 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 340 if (log) 341 log->Printf ("%p Platform::~Platform()", static_cast<void*>(this)); 342 } 343 344 void 345 Platform::GetStatus (Stream &strm) 346 { 347 uint32_t major = UINT32_MAX; 348 uint32_t minor = UINT32_MAX; 349 uint32_t update = UINT32_MAX; 350 std::string s; 351 strm.Printf (" Platform: %s\n", GetPluginName().GetCString()); 352 353 ArchSpec arch (GetSystemArchitecture()); 354 if (arch.IsValid()) 355 { 356 if (!arch.GetTriple().str().empty()) 357 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str()); 358 } 359 360 if (GetOSVersion(major, minor, update)) 361 { 362 strm.Printf("OS Version: %u", major); 363 if (minor != UINT32_MAX) 364 strm.Printf(".%u", minor); 365 if (update != UINT32_MAX) 366 strm.Printf(".%u", update); 367 368 if (GetOSBuildString (s)) 369 strm.Printf(" (%s)", s.c_str()); 370 371 strm.EOL(); 372 } 373 374 if (GetOSKernelDescription (s)) 375 strm.Printf(" Kernel: %s\n", s.c_str()); 376 377 if (IsHost()) 378 { 379 strm.Printf(" Hostname: %s\n", GetHostname()); 380 } 381 else 382 { 383 const bool is_connected = IsConnected(); 384 if (is_connected) 385 strm.Printf(" Hostname: %s\n", GetHostname()); 386 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); 387 } 388 389 if (GetWorkingDirectory()) 390 { 391 strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString()); 392 } 393 if (!IsConnected()) 394 return; 395 396 std::string specific_info(GetPlatformSpecificConnectionInformation()); 397 398 if (specific_info.empty() == false) 399 strm.Printf("Platform-specific connection: %s\n", specific_info.c_str()); 400 } 401 402 403 bool 404 Platform::GetOSVersion (uint32_t &major, 405 uint32_t &minor, 406 uint32_t &update) 407 { 408 Mutex::Locker locker (m_mutex); 409 410 bool success = m_major_os_version != UINT32_MAX; 411 if (IsHost()) 412 { 413 if (!success) 414 { 415 // We have a local host platform 416 success = HostInfo::GetOSVersion(m_major_os_version, m_minor_os_version, m_update_os_version); 417 m_os_version_set_while_connected = success; 418 } 419 } 420 else 421 { 422 // We have a remote platform. We can only fetch the remote 423 // OS version if we are connected, and we don't want to do it 424 // more than once. 425 426 const bool is_connected = IsConnected(); 427 428 bool fetch = false; 429 if (success) 430 { 431 // We have valid OS version info, check to make sure it wasn't 432 // manually set prior to connecting. If it was manually set prior 433 // to connecting, then lets fetch the actual OS version info 434 // if we are now connected. 435 if (is_connected && !m_os_version_set_while_connected) 436 fetch = true; 437 } 438 else 439 { 440 // We don't have valid OS version info, fetch it if we are connected 441 fetch = is_connected; 442 } 443 444 if (fetch) 445 { 446 success = GetRemoteOSVersion (); 447 m_os_version_set_while_connected = success; 448 } 449 } 450 451 if (success) 452 { 453 major = m_major_os_version; 454 minor = m_minor_os_version; 455 update = m_update_os_version; 456 } 457 return success; 458 } 459 460 bool 461 Platform::GetOSBuildString (std::string &s) 462 { 463 s.clear(); 464 465 if (IsHost()) 466 #if !defined(__linux__) 467 return HostInfo::GetOSBuildString(s); 468 #else 469 return false; 470 #endif 471 else 472 return GetRemoteOSBuildString (s); 473 } 474 475 bool 476 Platform::GetOSKernelDescription (std::string &s) 477 { 478 if (IsHost()) 479 #if !defined(__linux__) 480 return HostInfo::GetOSKernelDescription(s); 481 #else 482 return false; 483 #endif 484 else 485 return GetRemoteOSKernelDescription (s); 486 } 487 488 void 489 Platform::AddClangModuleCompilationOptions (Target *target, std::vector<std::string> &options) 490 { 491 std::vector<std::string> default_compilation_options = 492 { 493 "-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc" 494 }; 495 496 options.insert(options.end(), 497 default_compilation_options.begin(), 498 default_compilation_options.end()); 499 } 500 501 502 ConstString 503 Platform::GetWorkingDirectory () 504 { 505 if (IsHost()) 506 { 507 char cwd[PATH_MAX]; 508 if (getcwd(cwd, sizeof(cwd))) 509 return ConstString(cwd); 510 else 511 return ConstString(); 512 } 513 else 514 { 515 if (!m_working_dir) 516 m_working_dir = GetRemoteWorkingDirectory(); 517 return m_working_dir; 518 } 519 } 520 521 522 struct RecurseCopyBaton 523 { 524 const FileSpec& dst; 525 Platform *platform_ptr; 526 Error error; 527 }; 528 529 530 static FileSpec::EnumerateDirectoryResult 531 RecurseCopy_Callback (void *baton, 532 FileSpec::FileType file_type, 533 const FileSpec &src) 534 { 535 RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton; 536 switch (file_type) 537 { 538 case FileSpec::eFileTypePipe: 539 case FileSpec::eFileTypeSocket: 540 // we have no way to copy pipes and sockets - ignore them and continue 541 return FileSpec::eEnumerateDirectoryResultNext; 542 break; 543 544 case FileSpec::eFileTypeDirectory: 545 { 546 // make the new directory and get in there 547 FileSpec dst_dir = rc_baton->dst; 548 if (!dst_dir.GetFilename()) 549 dst_dir.GetFilename() = src.GetLastPathComponent(); 550 std::string dst_dir_path (dst_dir.GetPath()); 551 Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir_path.c_str(), lldb::eFilePermissionsDirectoryDefault); 552 if (error.Fail()) 553 { 554 rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", dst_dir_path.c_str()); 555 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 556 } 557 558 // now recurse 559 std::string src_dir_path (src.GetPath()); 560 561 // Make a filespec that only fills in the directory of a FileSpec so 562 // when we enumerate we can quickly fill in the filename for dst copies 563 FileSpec recurse_dst; 564 recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str()); 565 RecurseCopyBaton rc_baton2 = { recurse_dst, rc_baton->platform_ptr, Error() }; 566 FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2); 567 if (rc_baton2.error.Fail()) 568 { 569 rc_baton->error.SetErrorString(rc_baton2.error.AsCString()); 570 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 571 } 572 return FileSpec::eEnumerateDirectoryResultNext; 573 } 574 break; 575 576 case FileSpec::eFileTypeSymbolicLink: 577 { 578 // copy the file and keep going 579 FileSpec dst_file = rc_baton->dst; 580 if (!dst_file.GetFilename()) 581 dst_file.GetFilename() = src.GetFilename(); 582 583 char buf[PATH_MAX]; 584 585 rc_baton->error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf)); 586 587 if (rc_baton->error.Fail()) 588 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 589 590 rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file.GetPath().c_str(), buf); 591 592 if (rc_baton->error.Fail()) 593 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 594 595 return FileSpec::eEnumerateDirectoryResultNext; 596 } 597 break; 598 case FileSpec::eFileTypeRegular: 599 { 600 // copy the file and keep going 601 FileSpec dst_file = rc_baton->dst; 602 if (!dst_file.GetFilename()) 603 dst_file.GetFilename() = src.GetFilename(); 604 Error err = rc_baton->platform_ptr->PutFile(src, dst_file); 605 if (err.Fail()) 606 { 607 rc_baton->error.SetErrorString(err.AsCString()); 608 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 609 } 610 return FileSpec::eEnumerateDirectoryResultNext; 611 } 612 break; 613 614 case FileSpec::eFileTypeInvalid: 615 case FileSpec::eFileTypeOther: 616 case FileSpec::eFileTypeUnknown: 617 rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str()); 618 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 619 break; 620 } 621 llvm_unreachable("Unhandled FileSpec::FileType!"); 622 } 623 624 Error 625 Platform::Install (const FileSpec& src, const FileSpec& dst) 626 { 627 Error error; 628 629 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 630 if (log) 631 log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str()); 632 FileSpec fixed_dst(dst); 633 634 if (!fixed_dst.GetFilename()) 635 fixed_dst.GetFilename() = src.GetFilename(); 636 637 ConstString working_dir = GetWorkingDirectory(); 638 639 if (dst) 640 { 641 if (dst.GetDirectory()) 642 { 643 const char first_dst_dir_char = dst.GetDirectory().GetCString()[0]; 644 if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') 645 { 646 fixed_dst.GetDirectory() = dst.GetDirectory(); 647 } 648 // If the fixed destination file doesn't have a directory yet, 649 // then we must have a relative path. We will resolve this relative 650 // path against the platform's working directory 651 if (!fixed_dst.GetDirectory()) 652 { 653 FileSpec relative_spec; 654 std::string path; 655 if (working_dir) 656 { 657 relative_spec.SetFile(working_dir.GetCString(), false); 658 relative_spec.AppendPathComponent(dst.GetPath().c_str()); 659 fixed_dst.GetDirectory() = relative_spec.GetDirectory(); 660 } 661 else 662 { 663 error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str()); 664 return error; 665 } 666 } 667 } 668 else 669 { 670 if (working_dir) 671 { 672 fixed_dst.GetDirectory() = working_dir; 673 } 674 else 675 { 676 error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str()); 677 return error; 678 } 679 } 680 } 681 else 682 { 683 if (working_dir) 684 { 685 fixed_dst.GetDirectory() = working_dir; 686 } 687 else 688 { 689 error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty"); 690 return error; 691 } 692 } 693 694 if (log) 695 log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str()); 696 697 if (GetSupportsRSync()) 698 { 699 error = PutFile(src, dst); 700 } 701 else 702 { 703 switch (src.GetFileType()) 704 { 705 case FileSpec::eFileTypeDirectory: 706 { 707 if (GetFileExists (fixed_dst)) 708 Unlink (fixed_dst.GetPath().c_str()); 709 uint32_t permissions = src.GetPermissions(); 710 if (permissions == 0) 711 permissions = eFilePermissionsDirectoryDefault; 712 std::string dst_dir_path(fixed_dst.GetPath()); 713 error = MakeDirectory(dst_dir_path.c_str(), permissions); 714 if (error.Success()) 715 { 716 // Make a filespec that only fills in the directory of a FileSpec so 717 // when we enumerate we can quickly fill in the filename for dst copies 718 FileSpec recurse_dst; 719 recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str()); 720 std::string src_dir_path (src.GetPath()); 721 RecurseCopyBaton baton = { recurse_dst, this, Error() }; 722 FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton); 723 return baton.error; 724 } 725 } 726 break; 727 728 case FileSpec::eFileTypeRegular: 729 if (GetFileExists (fixed_dst)) 730 Unlink (fixed_dst.GetPath().c_str()); 731 error = PutFile(src, fixed_dst); 732 break; 733 734 case FileSpec::eFileTypeSymbolicLink: 735 { 736 if (GetFileExists (fixed_dst)) 737 Unlink (fixed_dst.GetPath().c_str()); 738 char buf[PATH_MAX]; 739 error = FileSystem::Readlink(src.GetPath().c_str(), buf, sizeof(buf)); 740 if (error.Success()) 741 error = CreateSymlink(dst.GetPath().c_str(), buf); 742 } 743 break; 744 case FileSpec::eFileTypePipe: 745 error.SetErrorString("platform install doesn't handle pipes"); 746 break; 747 case FileSpec::eFileTypeSocket: 748 error.SetErrorString("platform install doesn't handle sockets"); 749 break; 750 case FileSpec::eFileTypeInvalid: 751 case FileSpec::eFileTypeUnknown: 752 case FileSpec::eFileTypeOther: 753 error.SetErrorString("platform install doesn't handle non file or directory items"); 754 break; 755 } 756 } 757 return error; 758 } 759 760 bool 761 Platform::SetWorkingDirectory (const ConstString &path) 762 { 763 if (IsHost()) 764 { 765 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 766 if (log) 767 log->Printf("Platform::SetWorkingDirectory('%s')", path.GetCString()); 768 #ifdef _WIN32 769 // Not implemented on Windows 770 return false; 771 #else 772 if (path) 773 { 774 if (chdir(path.GetCString()) == 0) 775 return true; 776 } 777 return false; 778 #endif 779 } 780 else 781 { 782 m_working_dir.Clear(); 783 return SetRemoteWorkingDirectory(path); 784 } 785 } 786 787 Error 788 Platform::MakeDirectory (const char *path, uint32_t permissions) 789 { 790 if (IsHost()) 791 return FileSystem::MakeDirectory(path, permissions); 792 else 793 { 794 Error error; 795 error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); 796 return error; 797 } 798 } 799 800 Error 801 Platform::GetFilePermissions (const char *path, uint32_t &file_permissions) 802 { 803 if (IsHost()) 804 return FileSystem::GetFilePermissions(path, file_permissions); 805 else 806 { 807 Error error; 808 error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); 809 return error; 810 } 811 } 812 813 Error 814 Platform::SetFilePermissions (const char *path, uint32_t file_permissions) 815 { 816 if (IsHost()) 817 return FileSystem::SetFilePermissions(path, file_permissions); 818 else 819 { 820 Error error; 821 error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); 822 return error; 823 } 824 } 825 826 ConstString 827 Platform::GetName () 828 { 829 return GetPluginName(); 830 } 831 832 const char * 833 Platform::GetHostname () 834 { 835 if (IsHost()) 836 return "127.0.0.1"; 837 838 if (m_name.empty()) 839 return NULL; 840 return m_name.c_str(); 841 } 842 843 bool 844 Platform::SetRemoteWorkingDirectory(const ConstString &path) 845 { 846 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 847 if (log) 848 log->Printf("Platform::SetRemoteWorkingDirectory('%s')", path.GetCString()); 849 m_working_dir = path; 850 return true; 851 } 852 853 const char * 854 Platform::GetUserName (uint32_t uid) 855 { 856 #if !defined(LLDB_DISABLE_POSIX) 857 const char *user_name = GetCachedUserName(uid); 858 if (user_name) 859 return user_name; 860 if (IsHost()) 861 { 862 std::string name; 863 if (HostInfo::LookupUserName(uid, name)) 864 return SetCachedUserName (uid, name.c_str(), name.size()); 865 } 866 #endif 867 return NULL; 868 } 869 870 const char * 871 Platform::GetGroupName (uint32_t gid) 872 { 873 #if !defined(LLDB_DISABLE_POSIX) 874 const char *group_name = GetCachedGroupName(gid); 875 if (group_name) 876 return group_name; 877 if (IsHost()) 878 { 879 std::string name; 880 if (HostInfo::LookupGroupName(gid, name)) 881 return SetCachedGroupName (gid, name.c_str(), name.size()); 882 } 883 #endif 884 return NULL; 885 } 886 887 bool 888 Platform::SetOSVersion (uint32_t major, 889 uint32_t minor, 890 uint32_t update) 891 { 892 if (IsHost()) 893 { 894 // We don't need anyone setting the OS version for the host platform, 895 // we should be able to figure it out by calling HostInfo::GetOSVersion(...). 896 return false; 897 } 898 else 899 { 900 // We have a remote platform, allow setting the target OS version if 901 // we aren't connected, since if we are connected, we should be able to 902 // request the remote OS version from the connected platform. 903 if (IsConnected()) 904 return false; 905 else 906 { 907 // We aren't connected and we might want to set the OS version 908 // ahead of time before we connect so we can peruse files and 909 // use a local SDK or PDK cache of support files to disassemble 910 // or do other things. 911 m_major_os_version = major; 912 m_minor_os_version = minor; 913 m_update_os_version = update; 914 return true; 915 } 916 } 917 return false; 918 } 919 920 921 Error 922 Platform::ResolveExecutable (const ModuleSpec &module_spec, 923 lldb::ModuleSP &exe_module_sp, 924 const FileSpecList *module_search_paths_ptr) 925 { 926 Error error; 927 if (module_spec.GetFileSpec().Exists()) 928 { 929 if (module_spec.GetArchitecture().IsValid()) 930 { 931 error = ModuleList::GetSharedModule (module_spec, 932 exe_module_sp, 933 module_search_paths_ptr, 934 NULL, 935 NULL); 936 } 937 else 938 { 939 // No valid architecture was specified, ask the platform for 940 // the architectures that we should be using (in the correct order) 941 // and see if we can find a match that way 942 ModuleSpec arch_module_spec(module_spec); 943 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, arch_module_spec.GetArchitecture()); ++idx) 944 { 945 error = ModuleList::GetSharedModule (arch_module_spec, 946 exe_module_sp, 947 module_search_paths_ptr, 948 NULL, 949 NULL); 950 // Did we find an executable using one of the 951 if (error.Success() && exe_module_sp) 952 break; 953 } 954 } 955 } 956 else 957 { 958 error.SetErrorStringWithFormat ("'%s' does not exist", 959 module_spec.GetFileSpec().GetPath().c_str()); 960 } 961 return error; 962 } 963 964 Error 965 Platform::ResolveSymbolFile (Target &target, 966 const ModuleSpec &sym_spec, 967 FileSpec &sym_file) 968 { 969 Error error; 970 if (sym_spec.GetSymbolFileSpec().Exists()) 971 sym_file = sym_spec.GetSymbolFileSpec(); 972 else 973 error.SetErrorString("unable to resolve symbol file"); 974 return error; 975 976 } 977 978 979 980 bool 981 Platform::ResolveRemotePath (const FileSpec &platform_path, 982 FileSpec &resolved_platform_path) 983 { 984 resolved_platform_path = platform_path; 985 return resolved_platform_path.ResolvePath(); 986 } 987 988 989 const ArchSpec & 990 Platform::GetSystemArchitecture() 991 { 992 if (IsHost()) 993 { 994 if (!m_system_arch.IsValid()) 995 { 996 // We have a local host platform 997 m_system_arch = HostInfo::GetArchitecture(); 998 m_system_arch_set_while_connected = m_system_arch.IsValid(); 999 } 1000 } 1001 else 1002 { 1003 // We have a remote platform. We can only fetch the remote 1004 // system architecture if we are connected, and we don't want to do it 1005 // more than once. 1006 1007 const bool is_connected = IsConnected(); 1008 1009 bool fetch = false; 1010 if (m_system_arch.IsValid()) 1011 { 1012 // We have valid OS version info, check to make sure it wasn't 1013 // manually set prior to connecting. If it was manually set prior 1014 // to connecting, then lets fetch the actual OS version info 1015 // if we are now connected. 1016 if (is_connected && !m_system_arch_set_while_connected) 1017 fetch = true; 1018 } 1019 else 1020 { 1021 // We don't have valid OS version info, fetch it if we are connected 1022 fetch = is_connected; 1023 } 1024 1025 if (fetch) 1026 { 1027 m_system_arch = GetRemoteSystemArchitecture (); 1028 m_system_arch_set_while_connected = m_system_arch.IsValid(); 1029 } 1030 } 1031 return m_system_arch; 1032 } 1033 1034 1035 Error 1036 Platform::ConnectRemote (Args& args) 1037 { 1038 Error error; 1039 if (IsHost()) 1040 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString()); 1041 else 1042 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString()); 1043 return error; 1044 } 1045 1046 Error 1047 Platform::DisconnectRemote () 1048 { 1049 Error error; 1050 if (IsHost()) 1051 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString()); 1052 else 1053 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString()); 1054 return error; 1055 } 1056 1057 bool 1058 Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 1059 { 1060 // Take care of the host case so that each subclass can just 1061 // call this function to get the host functionality. 1062 if (IsHost()) 1063 return Host::GetProcessInfo (pid, process_info); 1064 return false; 1065 } 1066 1067 uint32_t 1068 Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info, 1069 ProcessInstanceInfoList &process_infos) 1070 { 1071 // Take care of the host case so that each subclass can just 1072 // call this function to get the host functionality. 1073 uint32_t match_count = 0; 1074 if (IsHost()) 1075 match_count = Host::FindProcesses (match_info, process_infos); 1076 return match_count; 1077 } 1078 1079 1080 Error 1081 Platform::LaunchProcess (ProcessLaunchInfo &launch_info) 1082 { 1083 Error error; 1084 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1085 if (log) 1086 log->Printf ("Platform::%s()", __FUNCTION__); 1087 1088 // Take care of the host case so that each subclass can just 1089 // call this function to get the host functionality. 1090 if (IsHost()) 1091 { 1092 if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY")) 1093 launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY); 1094 1095 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 1096 { 1097 const bool is_localhost = true; 1098 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); 1099 const bool first_arg_is_full_shell_command = false; 1100 uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info); 1101 if (log) 1102 { 1103 const FileSpec &shell = launch_info.GetShell(); 1104 const char *shell_str = (shell) ? shell.GetPath().c_str() : "<null>"; 1105 log->Printf ("Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32 ", shell is '%s'", 1106 __FUNCTION__, 1107 num_resumes, 1108 shell_str); 1109 } 1110 1111 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, 1112 is_localhost, 1113 will_debug, 1114 first_arg_is_full_shell_command, 1115 num_resumes)) 1116 return error; 1117 } 1118 else if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) 1119 { 1120 error = ShellExpandArguments(launch_info); 1121 if (error.Fail()) 1122 return error; 1123 } 1124 1125 if (log) 1126 log->Printf ("Platform::%s final launch_info resume count: %" PRIu32, __FUNCTION__, launch_info.GetResumeCount ()); 1127 1128 error = Host::LaunchProcess (launch_info); 1129 } 1130 else 1131 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes"); 1132 return error; 1133 } 1134 1135 Error 1136 Platform::ShellExpandArguments (ProcessLaunchInfo &launch_info) 1137 { 1138 if (IsHost()) 1139 return Host::ShellExpandArguments(launch_info); 1140 return Error("base lldb_private::Platform class can't expand arguments"); 1141 } 1142 1143 Error 1144 Platform::KillProcess (const lldb::pid_t pid) 1145 { 1146 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1147 if (log) 1148 log->Printf ("Platform::%s, pid %" PRIu64, __FUNCTION__, pid); 1149 1150 if (!IsHost ()) 1151 return Error ("base lldb_private::Platform class can't launch remote processes"); 1152 1153 Host::Kill (pid, SIGTERM); 1154 return Error(); 1155 } 1156 1157 lldb::ProcessSP 1158 Platform::DebugProcess (ProcessLaunchInfo &launch_info, 1159 Debugger &debugger, 1160 Target *target, // Can be NULL, if NULL create a new target, else use existing one 1161 Error &error) 1162 { 1163 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1164 if (log) 1165 log->Printf ("Platform::%s entered (target %p)", __FUNCTION__, static_cast<void*>(target)); 1166 1167 ProcessSP process_sp; 1168 // Make sure we stop at the entry point 1169 launch_info.GetFlags ().Set (eLaunchFlagDebug); 1170 // We always launch the process we are going to debug in a separate process 1171 // group, since then we can handle ^C interrupts ourselves w/o having to worry 1172 // about the target getting them as well. 1173 launch_info.SetLaunchInSeparateProcessGroup(true); 1174 1175 error = LaunchProcess (launch_info); 1176 if (error.Success()) 1177 { 1178 if (log) 1179 log->Printf ("Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 ")", __FUNCTION__, launch_info.GetProcessID ()); 1180 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 1181 { 1182 ProcessAttachInfo attach_info (launch_info); 1183 process_sp = Attach (attach_info, debugger, target, error); 1184 if (process_sp) 1185 { 1186 if (log) 1187 log->Printf ("Platform::%s Attach() succeeded, Process plugin: %s", __FUNCTION__, process_sp->GetPluginName ().AsCString ()); 1188 launch_info.SetHijackListener(attach_info.GetHijackListener()); 1189 1190 // Since we attached to the process, it will think it needs to detach 1191 // if the process object just goes away without an explicit call to 1192 // Process::Kill() or Process::Detach(), so let it know to kill the 1193 // process if this happens. 1194 process_sp->SetShouldDetach (false); 1195 1196 // If we didn't have any file actions, the pseudo terminal might 1197 // have been used where the slave side was given as the file to 1198 // open for stdin/out/err after we have already opened the master 1199 // so we can read/write stdin/out/err. 1200 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 1201 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) 1202 { 1203 process_sp->SetSTDIOFileDescriptor(pty_fd); 1204 } 1205 } 1206 else 1207 { 1208 if (log) 1209 log->Printf ("Platform::%s Attach() failed: %s", __FUNCTION__, error.AsCString ()); 1210 } 1211 } 1212 else 1213 { 1214 if (log) 1215 log->Printf ("Platform::%s LaunchProcess() returned launch_info with invalid process id", __FUNCTION__); 1216 } 1217 } 1218 else 1219 { 1220 if (log) 1221 log->Printf ("Platform::%s LaunchProcess() failed: %s", __FUNCTION__, error.AsCString ()); 1222 } 1223 1224 return process_sp; 1225 } 1226 1227 1228 lldb::PlatformSP 1229 Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr) 1230 { 1231 lldb::PlatformSP platform_sp; 1232 Error error; 1233 if (arch.IsValid()) 1234 platform_sp = Platform::Create (arch, platform_arch_ptr, error); 1235 return platform_sp; 1236 } 1237 1238 1239 //------------------------------------------------------------------ 1240 /// Lets a platform answer if it is compatible with a given 1241 /// architecture and the target triple contained within. 1242 //------------------------------------------------------------------ 1243 bool 1244 Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr) 1245 { 1246 // If the architecture is invalid, we must answer true... 1247 if (arch.IsValid()) 1248 { 1249 ArchSpec platform_arch; 1250 // Try for an exact architecture match first. 1251 if (exact_arch_match) 1252 { 1253 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 1254 { 1255 if (arch.IsExactMatch(platform_arch)) 1256 { 1257 if (compatible_arch_ptr) 1258 *compatible_arch_ptr = platform_arch; 1259 return true; 1260 } 1261 } 1262 } 1263 else 1264 { 1265 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 1266 { 1267 if (arch.IsCompatibleMatch(platform_arch)) 1268 { 1269 if (compatible_arch_ptr) 1270 *compatible_arch_ptr = platform_arch; 1271 return true; 1272 } 1273 } 1274 } 1275 } 1276 if (compatible_arch_ptr) 1277 compatible_arch_ptr->Clear(); 1278 return false; 1279 } 1280 1281 Error 1282 Platform::PutFile (const FileSpec& source, 1283 const FileSpec& destination, 1284 uint32_t uid, 1285 uint32_t gid) 1286 { 1287 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1288 if (log) 1289 log->Printf("[PutFile] Using block by block transfer....\n"); 1290 1291 uint32_t source_open_options = File::eOpenOptionRead | File::eOpenOptionCloseOnExec; 1292 if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) 1293 source_open_options |= File::eOpenoptionDontFollowSymlinks; 1294 1295 File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); 1296 Error error; 1297 uint32_t permissions = source_file.GetPermissions(error); 1298 if (permissions == 0) 1299 permissions = lldb::eFilePermissionsFileDefault; 1300 1301 if (!source_file.IsValid()) 1302 return Error("PutFile: unable to open source file"); 1303 lldb::user_id_t dest_file = OpenFile (destination, 1304 File::eOpenOptionCanCreate | 1305 File::eOpenOptionWrite | 1306 File::eOpenOptionTruncate | 1307 File::eOpenOptionCloseOnExec, 1308 permissions, 1309 error); 1310 if (log) 1311 log->Printf ("dest_file = %" PRIu64 "\n", dest_file); 1312 1313 if (error.Fail()) 1314 return error; 1315 if (dest_file == UINT64_MAX) 1316 return Error("unable to open target file"); 1317 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 1318 uint64_t offset = 0; 1319 for (;;) 1320 { 1321 size_t bytes_read = buffer_sp->GetByteSize(); 1322 error = source_file.Read(buffer_sp->GetBytes(), bytes_read); 1323 if (error.Fail() || bytes_read == 0) 1324 break; 1325 1326 const uint64_t bytes_written = WriteFile(dest_file, offset, 1327 buffer_sp->GetBytes(), bytes_read, error); 1328 if (error.Fail()) 1329 break; 1330 1331 offset += bytes_written; 1332 if (bytes_written != bytes_read) 1333 { 1334 // We didn't write the correct number of bytes, so adjust 1335 // the file position in the source file we are reading from... 1336 source_file.SeekFromStart(offset); 1337 } 1338 } 1339 CloseFile(dest_file, error); 1340 1341 if (uid == UINT32_MAX && gid == UINT32_MAX) 1342 return error; 1343 1344 // TODO: ChownFile? 1345 1346 return error; 1347 } 1348 1349 Error 1350 Platform::GetFile (const FileSpec& source, 1351 const FileSpec& destination) 1352 { 1353 Error error("unimplemented"); 1354 return error; 1355 } 1356 1357 Error 1358 Platform::CreateSymlink (const char *src, // The name of the link is in src 1359 const char *dst)// The symlink points to dst 1360 { 1361 Error error("unimplemented"); 1362 return error; 1363 } 1364 1365 bool 1366 Platform::GetFileExists (const lldb_private::FileSpec& file_spec) 1367 { 1368 return false; 1369 } 1370 1371 Error 1372 Platform::Unlink (const char *path) 1373 { 1374 Error error("unimplemented"); 1375 return error; 1376 } 1377 1378 1379 1380 lldb_private::Error 1381 Platform::RunShellCommand (const char *command, // Shouldn't be NULL 1382 const char *working_dir, // Pass NULL to use the current working directory 1383 int *status_ptr, // Pass NULL if you don't want the process exit status 1384 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 1385 std::string *command_output, // Pass NULL if you don't want the command output 1386 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 1387 { 1388 if (IsHost()) 1389 return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 1390 else 1391 return Error("unimplemented"); 1392 } 1393 1394 1395 bool 1396 Platform::CalculateMD5 (const FileSpec& file_spec, 1397 uint64_t &low, 1398 uint64_t &high) 1399 { 1400 if (IsHost()) 1401 return FileSystem::CalculateMD5(file_spec, low, high); 1402 else 1403 return false; 1404 } 1405 1406 Error 1407 Platform::LaunchNativeProcess ( 1408 ProcessLaunchInfo &launch_info, 1409 lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, 1410 NativeProcessProtocolSP &process_sp) 1411 { 1412 // Platforms should override this implementation if they want to 1413 // support lldb-gdbserver. 1414 return Error("unimplemented"); 1415 } 1416 1417 Error 1418 Platform::AttachNativeProcess (lldb::pid_t pid, 1419 lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, 1420 NativeProcessProtocolSP &process_sp) 1421 { 1422 // Platforms should override this implementation if they want to 1423 // support lldb-gdbserver. 1424 return Error("unimplemented"); 1425 } 1426 1427 void 1428 Platform::SetLocalCacheDirectory (const char* local) 1429 { 1430 m_local_cache_directory.assign(local); 1431 } 1432 1433 const char* 1434 Platform::GetLocalCacheDirectory () 1435 { 1436 return m_local_cache_directory.c_str(); 1437 } 1438 1439 static OptionDefinition 1440 g_rsync_option_table[] = 1441 { 1442 { LLDB_OPT_SET_ALL, false, "rsync" , 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Enable rsync." }, 1443 { LLDB_OPT_SET_ALL, false, "rsync-opts" , 'R', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific options required for rsync to work." }, 1444 { LLDB_OPT_SET_ALL, false, "rsync-prefix" , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific rsync prefix put before the remote path." }, 1445 { LLDB_OPT_SET_ALL, false, "ignore-remote-hostname" , 'i', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Do not automatically fill in the remote hostname when composing the rsync command." }, 1446 }; 1447 1448 static OptionDefinition 1449 g_ssh_option_table[] = 1450 { 1451 { LLDB_OPT_SET_ALL, false, "ssh" , 's', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Enable SSH." }, 1452 { LLDB_OPT_SET_ALL, false, "ssh-opts" , 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific options required for SSH to work." }, 1453 }; 1454 1455 static OptionDefinition 1456 g_caching_option_table[] = 1457 { 1458 { LLDB_OPT_SET_ALL, false, "local-cache-dir" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePath , "Path in which to store local copies of files." }, 1459 }; 1460 1461 OptionGroupPlatformRSync::OptionGroupPlatformRSync () 1462 { 1463 } 1464 1465 OptionGroupPlatformRSync::~OptionGroupPlatformRSync () 1466 { 1467 } 1468 1469 const lldb_private::OptionDefinition* 1470 OptionGroupPlatformRSync::GetDefinitions () 1471 { 1472 return g_rsync_option_table; 1473 } 1474 1475 void 1476 OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter) 1477 { 1478 m_rsync = false; 1479 m_rsync_opts.clear(); 1480 m_rsync_prefix.clear(); 1481 m_ignores_remote_hostname = false; 1482 } 1483 1484 lldb_private::Error 1485 OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter, 1486 uint32_t option_idx, 1487 const char *option_arg) 1488 { 1489 Error error; 1490 char short_option = (char) GetDefinitions()[option_idx].short_option; 1491 switch (short_option) 1492 { 1493 case 'r': 1494 m_rsync = true; 1495 break; 1496 1497 case 'R': 1498 m_rsync_opts.assign(option_arg); 1499 break; 1500 1501 case 'P': 1502 m_rsync_prefix.assign(option_arg); 1503 break; 1504 1505 case 'i': 1506 m_ignores_remote_hostname = true; 1507 break; 1508 1509 default: 1510 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1511 break; 1512 } 1513 1514 return error; 1515 } 1516 1517 uint32_t 1518 OptionGroupPlatformRSync::GetNumDefinitions () 1519 { 1520 return llvm::array_lengthof(g_rsync_option_table); 1521 } 1522 1523 lldb::BreakpointSP 1524 Platform::SetThreadCreationBreakpoint (lldb_private::Target &target) 1525 { 1526 return lldb::BreakpointSP(); 1527 } 1528 1529 OptionGroupPlatformSSH::OptionGroupPlatformSSH () 1530 { 1531 } 1532 1533 OptionGroupPlatformSSH::~OptionGroupPlatformSSH () 1534 { 1535 } 1536 1537 const lldb_private::OptionDefinition* 1538 OptionGroupPlatformSSH::GetDefinitions () 1539 { 1540 return g_ssh_option_table; 1541 } 1542 1543 void 1544 OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter) 1545 { 1546 m_ssh = false; 1547 m_ssh_opts.clear(); 1548 } 1549 1550 lldb_private::Error 1551 OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter, 1552 uint32_t option_idx, 1553 const char *option_arg) 1554 { 1555 Error error; 1556 char short_option = (char) GetDefinitions()[option_idx].short_option; 1557 switch (short_option) 1558 { 1559 case 's': 1560 m_ssh = true; 1561 break; 1562 1563 case 'S': 1564 m_ssh_opts.assign(option_arg); 1565 break; 1566 1567 default: 1568 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1569 break; 1570 } 1571 1572 return error; 1573 } 1574 1575 uint32_t 1576 OptionGroupPlatformSSH::GetNumDefinitions () 1577 { 1578 return llvm::array_lengthof(g_ssh_option_table); 1579 } 1580 1581 OptionGroupPlatformCaching::OptionGroupPlatformCaching () 1582 { 1583 } 1584 1585 OptionGroupPlatformCaching::~OptionGroupPlatformCaching () 1586 { 1587 } 1588 1589 const lldb_private::OptionDefinition* 1590 OptionGroupPlatformCaching::GetDefinitions () 1591 { 1592 return g_caching_option_table; 1593 } 1594 1595 void 1596 OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter) 1597 { 1598 m_cache_dir.clear(); 1599 } 1600 1601 lldb_private::Error 1602 OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter, 1603 uint32_t option_idx, 1604 const char *option_arg) 1605 { 1606 Error error; 1607 char short_option = (char) GetDefinitions()[option_idx].short_option; 1608 switch (short_option) 1609 { 1610 case 'c': 1611 m_cache_dir.assign(option_arg); 1612 break; 1613 1614 default: 1615 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1616 break; 1617 } 1618 1619 return error; 1620 } 1621 1622 uint32_t 1623 OptionGroupPlatformCaching::GetNumDefinitions () 1624 { 1625 return llvm::array_lengthof(g_caching_option_table); 1626 } 1627 1628 size_t 1629 Platform::GetEnvironment (StringList &environment) 1630 { 1631 environment.Clear(); 1632 return false; 1633 } 1634 1635 const std::vector<ConstString> & 1636 Platform::GetTrapHandlerSymbolNames () 1637 { 1638 if (!m_calculated_trap_handlers) 1639 { 1640 Mutex::Locker locker (m_mutex); 1641 if (!m_calculated_trap_handlers) 1642 { 1643 CalculateTrapHandlerSymbolNames(); 1644 m_calculated_trap_handlers = true; 1645 } 1646 } 1647 return m_trap_handlers; 1648 } 1649 1650