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