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