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_uid_map_mutex (Mutex::eMutexTypeNormal), 290 m_gid_map_mutex (Mutex::eMutexTypeNormal), 291 m_uid_map(), 292 m_gid_map(), 293 m_max_uid_name_len (0), 294 m_max_gid_name_len (0), 295 m_supports_rsync (false), 296 m_rsync_opts (), 297 m_rsync_prefix (), 298 m_supports_ssh (false), 299 m_ssh_opts (), 300 m_ignores_remote_hostname (false), 301 m_trap_handlers(), 302 m_calculated_trap_handlers (false), 303 m_trap_handler_mutex() 304 { 305 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 306 if (log) 307 log->Printf ("%p Platform::Platform()", static_cast<void*>(this)); 308 } 309 310 //------------------------------------------------------------------ 311 /// Destructor. 312 /// 313 /// The destructor is virtual since this class is designed to be 314 /// inherited from by the plug-in instance. 315 //------------------------------------------------------------------ 316 Platform::~Platform() 317 { 318 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 319 if (log) 320 log->Printf ("%p Platform::~Platform()", static_cast<void*>(this)); 321 } 322 323 void 324 Platform::GetStatus (Stream &strm) 325 { 326 uint32_t major = UINT32_MAX; 327 uint32_t minor = UINT32_MAX; 328 uint32_t update = UINT32_MAX; 329 std::string s; 330 strm.Printf (" Platform: %s\n", GetPluginName().GetCString()); 331 332 ArchSpec arch (GetSystemArchitecture()); 333 if (arch.IsValid()) 334 { 335 if (!arch.GetTriple().str().empty()) 336 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str()); 337 } 338 339 if (GetOSVersion(major, minor, update)) 340 { 341 strm.Printf("OS Version: %u", major); 342 if (minor != UINT32_MAX) 343 strm.Printf(".%u", minor); 344 if (update != UINT32_MAX) 345 strm.Printf(".%u", update); 346 347 if (GetOSBuildString (s)) 348 strm.Printf(" (%s)", s.c_str()); 349 350 strm.EOL(); 351 } 352 353 if (GetOSKernelDescription (s)) 354 strm.Printf(" Kernel: %s\n", s.c_str()); 355 356 if (IsHost()) 357 { 358 strm.Printf(" Hostname: %s\n", GetHostname()); 359 } 360 else 361 { 362 const bool is_connected = IsConnected(); 363 if (is_connected) 364 strm.Printf(" Hostname: %s\n", GetHostname()); 365 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); 366 } 367 368 if (GetWorkingDirectory()) 369 { 370 strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString()); 371 } 372 if (!IsConnected()) 373 return; 374 375 std::string specific_info(GetPlatformSpecificConnectionInformation()); 376 377 if (specific_info.empty() == false) 378 strm.Printf("Platform-specific connection: %s\n", specific_info.c_str()); 379 } 380 381 382 bool 383 Platform::GetOSVersion (uint32_t &major, 384 uint32_t &minor, 385 uint32_t &update) 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 lldb::ProcessSP 1107 Platform::DebugProcess (ProcessLaunchInfo &launch_info, 1108 Debugger &debugger, 1109 Target *target, // Can be NULL, if NULL create a new target, else use existing one 1110 Error &error) 1111 { 1112 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1113 if (log) 1114 log->Printf ("Platform::%s entered (target %p)", __FUNCTION__, static_cast<void*>(target)); 1115 1116 ProcessSP process_sp; 1117 // Make sure we stop at the entry point 1118 launch_info.GetFlags ().Set (eLaunchFlagDebug); 1119 // We always launch the process we are going to debug in a separate process 1120 // group, since then we can handle ^C interrupts ourselves w/o having to worry 1121 // about the target getting them as well. 1122 launch_info.SetLaunchInSeparateProcessGroup(true); 1123 1124 error = LaunchProcess (launch_info); 1125 if (error.Success()) 1126 { 1127 if (log) 1128 log->Printf ("Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 ")", __FUNCTION__, launch_info.GetProcessID ()); 1129 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 1130 { 1131 ProcessAttachInfo attach_info (launch_info); 1132 process_sp = Attach (attach_info, debugger, target, error); 1133 if (process_sp) 1134 { 1135 if (log) 1136 log->Printf ("Platform::%s Attach() succeeded, Process plugin: %s", __FUNCTION__, process_sp->GetPluginName ().AsCString ()); 1137 launch_info.SetHijackListener(attach_info.GetHijackListener()); 1138 1139 // Since we attached to the process, it will think it needs to detach 1140 // if the process object just goes away without an explicit call to 1141 // Process::Kill() or Process::Detach(), so let it know to kill the 1142 // process if this happens. 1143 process_sp->SetShouldDetach (false); 1144 1145 // If we didn't have any file actions, the pseudo terminal might 1146 // have been used where the slave side was given as the file to 1147 // open for stdin/out/err after we have already opened the master 1148 // so we can read/write stdin/out/err. 1149 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 1150 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) 1151 { 1152 process_sp->SetSTDIOFileDescriptor(pty_fd); 1153 } 1154 } 1155 else 1156 { 1157 if (log) 1158 log->Printf ("Platform::%s Attach() failed: %s", __FUNCTION__, error.AsCString ()); 1159 } 1160 } 1161 else 1162 { 1163 if (log) 1164 log->Printf ("Platform::%s LaunchProcess() returned launch_info with invalid process id", __FUNCTION__); 1165 } 1166 } 1167 else 1168 { 1169 if (log) 1170 log->Printf ("Platform::%s LaunchProcess() failed: %s", __FUNCTION__, error.AsCString ()); 1171 } 1172 1173 return process_sp; 1174 } 1175 1176 1177 lldb::PlatformSP 1178 Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr) 1179 { 1180 lldb::PlatformSP platform_sp; 1181 Error error; 1182 if (arch.IsValid()) 1183 platform_sp = Platform::Create (arch, platform_arch_ptr, error); 1184 return platform_sp; 1185 } 1186 1187 1188 //------------------------------------------------------------------ 1189 /// Lets a platform answer if it is compatible with a given 1190 /// architecture and the target triple contained within. 1191 //------------------------------------------------------------------ 1192 bool 1193 Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr) 1194 { 1195 // If the architecture is invalid, we must answer true... 1196 if (arch.IsValid()) 1197 { 1198 ArchSpec platform_arch; 1199 // Try for an exact architecture match first. 1200 if (exact_arch_match) 1201 { 1202 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 1203 { 1204 if (arch.IsExactMatch(platform_arch)) 1205 { 1206 if (compatible_arch_ptr) 1207 *compatible_arch_ptr = platform_arch; 1208 return true; 1209 } 1210 } 1211 } 1212 else 1213 { 1214 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 1215 { 1216 if (arch.IsCompatibleMatch(platform_arch)) 1217 { 1218 if (compatible_arch_ptr) 1219 *compatible_arch_ptr = platform_arch; 1220 return true; 1221 } 1222 } 1223 } 1224 } 1225 if (compatible_arch_ptr) 1226 compatible_arch_ptr->Clear(); 1227 return false; 1228 } 1229 1230 Error 1231 Platform::PutFile (const FileSpec& source, 1232 const FileSpec& destination, 1233 uint32_t uid, 1234 uint32_t gid) 1235 { 1236 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1237 if (log) 1238 log->Printf("[PutFile] Using block by block transfer....\n"); 1239 1240 uint32_t source_open_options = File::eOpenOptionRead; 1241 if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) 1242 source_open_options |= File::eOpenoptionDontFollowSymlinks; 1243 1244 File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); 1245 Error error; 1246 uint32_t permissions = source_file.GetPermissions(error); 1247 if (permissions == 0) 1248 permissions = lldb::eFilePermissionsFileDefault; 1249 1250 if (!source_file.IsValid()) 1251 return Error("PutFile: unable to open source file"); 1252 lldb::user_id_t dest_file = OpenFile (destination, 1253 File::eOpenOptionCanCreate | 1254 File::eOpenOptionWrite | 1255 File::eOpenOptionTruncate, 1256 permissions, 1257 error); 1258 if (log) 1259 log->Printf ("dest_file = %" PRIu64 "\n", dest_file); 1260 1261 if (error.Fail()) 1262 return error; 1263 if (dest_file == UINT64_MAX) 1264 return Error("unable to open target file"); 1265 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 1266 uint64_t offset = 0; 1267 for (;;) 1268 { 1269 size_t bytes_read = buffer_sp->GetByteSize(); 1270 error = source_file.Read(buffer_sp->GetBytes(), bytes_read); 1271 if (error.Fail() || bytes_read == 0) 1272 break; 1273 1274 const uint64_t bytes_written = WriteFile(dest_file, offset, 1275 buffer_sp->GetBytes(), bytes_read, error); 1276 if (error.Fail()) 1277 break; 1278 1279 offset += bytes_written; 1280 if (bytes_written != bytes_read) 1281 { 1282 // We didn't write the correct number of bytes, so adjust 1283 // the file position in the source file we are reading from... 1284 source_file.SeekFromStart(offset); 1285 } 1286 } 1287 CloseFile(dest_file, error); 1288 1289 if (uid == UINT32_MAX && gid == UINT32_MAX) 1290 return error; 1291 1292 // TODO: ChownFile? 1293 1294 return error; 1295 } 1296 1297 Error 1298 Platform::GetFile (const FileSpec& source, 1299 const FileSpec& destination) 1300 { 1301 Error error("unimplemented"); 1302 return error; 1303 } 1304 1305 Error 1306 Platform::CreateSymlink (const char *src, // The name of the link is in src 1307 const char *dst)// The symlink points to dst 1308 { 1309 Error error("unimplemented"); 1310 return error; 1311 } 1312 1313 bool 1314 Platform::GetFileExists (const lldb_private::FileSpec& file_spec) 1315 { 1316 return false; 1317 } 1318 1319 Error 1320 Platform::Unlink (const char *path) 1321 { 1322 Error error("unimplemented"); 1323 return error; 1324 } 1325 1326 1327 1328 lldb_private::Error 1329 Platform::RunShellCommand (const char *command, // Shouldn't be NULL 1330 const char *working_dir, // Pass NULL to use the current working directory 1331 int *status_ptr, // Pass NULL if you don't want the process exit status 1332 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 1333 std::string *command_output, // Pass NULL if you don't want the command output 1334 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 1335 { 1336 if (IsHost()) 1337 return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 1338 else 1339 return Error("unimplemented"); 1340 } 1341 1342 1343 bool 1344 Platform::CalculateMD5 (const FileSpec& file_spec, 1345 uint64_t &low, 1346 uint64_t &high) 1347 { 1348 if (IsHost()) 1349 return FileSystem::CalculateMD5(file_spec, low, high); 1350 else 1351 return false; 1352 } 1353 1354 Error 1355 Platform::LaunchNativeProcess ( 1356 ProcessLaunchInfo &launch_info, 1357 lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, 1358 NativeProcessProtocolSP &process_sp) 1359 { 1360 // Platforms should override this implementation if they want to 1361 // support lldb-gdbserver. 1362 return Error("unimplemented"); 1363 } 1364 1365 Error 1366 Platform::AttachNativeProcess (lldb::pid_t pid, 1367 lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, 1368 NativeProcessProtocolSP &process_sp) 1369 { 1370 // Platforms should override this implementation if they want to 1371 // support lldb-gdbserver. 1372 return Error("unimplemented"); 1373 } 1374 1375 void 1376 Platform::SetLocalCacheDirectory (const char* local) 1377 { 1378 m_local_cache_directory.assign(local); 1379 } 1380 1381 const char* 1382 Platform::GetLocalCacheDirectory () 1383 { 1384 return m_local_cache_directory.c_str(); 1385 } 1386 1387 static OptionDefinition 1388 g_rsync_option_table[] = 1389 { 1390 { LLDB_OPT_SET_ALL, false, "rsync" , 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Enable rsync." }, 1391 { LLDB_OPT_SET_ALL, false, "rsync-opts" , 'R', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific options required for rsync to work." }, 1392 { LLDB_OPT_SET_ALL, false, "rsync-prefix" , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific rsync prefix put before the remote path." }, 1393 { 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." }, 1394 }; 1395 1396 static OptionDefinition 1397 g_ssh_option_table[] = 1398 { 1399 { LLDB_OPT_SET_ALL, false, "ssh" , 's', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Enable SSH." }, 1400 { LLDB_OPT_SET_ALL, false, "ssh-opts" , 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific options required for SSH to work." }, 1401 }; 1402 1403 static OptionDefinition 1404 g_caching_option_table[] = 1405 { 1406 { LLDB_OPT_SET_ALL, false, "local-cache-dir" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePath , "Path in which to store local copies of files." }, 1407 }; 1408 1409 OptionGroupPlatformRSync::OptionGroupPlatformRSync () 1410 { 1411 } 1412 1413 OptionGroupPlatformRSync::~OptionGroupPlatformRSync () 1414 { 1415 } 1416 1417 const lldb_private::OptionDefinition* 1418 OptionGroupPlatformRSync::GetDefinitions () 1419 { 1420 return g_rsync_option_table; 1421 } 1422 1423 void 1424 OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter) 1425 { 1426 m_rsync = false; 1427 m_rsync_opts.clear(); 1428 m_rsync_prefix.clear(); 1429 m_ignores_remote_hostname = false; 1430 } 1431 1432 lldb_private::Error 1433 OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter, 1434 uint32_t option_idx, 1435 const char *option_arg) 1436 { 1437 Error error; 1438 char short_option = (char) GetDefinitions()[option_idx].short_option; 1439 switch (short_option) 1440 { 1441 case 'r': 1442 m_rsync = true; 1443 break; 1444 1445 case 'R': 1446 m_rsync_opts.assign(option_arg); 1447 break; 1448 1449 case 'P': 1450 m_rsync_prefix.assign(option_arg); 1451 break; 1452 1453 case 'i': 1454 m_ignores_remote_hostname = true; 1455 break; 1456 1457 default: 1458 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1459 break; 1460 } 1461 1462 return error; 1463 } 1464 1465 uint32_t 1466 OptionGroupPlatformRSync::GetNumDefinitions () 1467 { 1468 return llvm::array_lengthof(g_rsync_option_table); 1469 } 1470 1471 lldb::BreakpointSP 1472 Platform::SetThreadCreationBreakpoint (lldb_private::Target &target) 1473 { 1474 return lldb::BreakpointSP(); 1475 } 1476 1477 OptionGroupPlatformSSH::OptionGroupPlatformSSH () 1478 { 1479 } 1480 1481 OptionGroupPlatformSSH::~OptionGroupPlatformSSH () 1482 { 1483 } 1484 1485 const lldb_private::OptionDefinition* 1486 OptionGroupPlatformSSH::GetDefinitions () 1487 { 1488 return g_ssh_option_table; 1489 } 1490 1491 void 1492 OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter) 1493 { 1494 m_ssh = false; 1495 m_ssh_opts.clear(); 1496 } 1497 1498 lldb_private::Error 1499 OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter, 1500 uint32_t option_idx, 1501 const char *option_arg) 1502 { 1503 Error error; 1504 char short_option = (char) GetDefinitions()[option_idx].short_option; 1505 switch (short_option) 1506 { 1507 case 's': 1508 m_ssh = true; 1509 break; 1510 1511 case 'S': 1512 m_ssh_opts.assign(option_arg); 1513 break; 1514 1515 default: 1516 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1517 break; 1518 } 1519 1520 return error; 1521 } 1522 1523 uint32_t 1524 OptionGroupPlatformSSH::GetNumDefinitions () 1525 { 1526 return llvm::array_lengthof(g_ssh_option_table); 1527 } 1528 1529 OptionGroupPlatformCaching::OptionGroupPlatformCaching () 1530 { 1531 } 1532 1533 OptionGroupPlatformCaching::~OptionGroupPlatformCaching () 1534 { 1535 } 1536 1537 const lldb_private::OptionDefinition* 1538 OptionGroupPlatformCaching::GetDefinitions () 1539 { 1540 return g_caching_option_table; 1541 } 1542 1543 void 1544 OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter) 1545 { 1546 m_cache_dir.clear(); 1547 } 1548 1549 lldb_private::Error 1550 OptionGroupPlatformCaching::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 'c': 1559 m_cache_dir.assign(option_arg); 1560 break; 1561 1562 default: 1563 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1564 break; 1565 } 1566 1567 return error; 1568 } 1569 1570 uint32_t 1571 OptionGroupPlatformCaching::GetNumDefinitions () 1572 { 1573 return llvm::array_lengthof(g_caching_option_table); 1574 } 1575 1576 size_t 1577 Platform::GetEnvironment (StringList &environment) 1578 { 1579 environment.Clear(); 1580 return false; 1581 } 1582 1583 const std::vector<ConstString> & 1584 Platform::GetTrapHandlerSymbolNames () 1585 { 1586 if (!m_calculated_trap_handlers) 1587 { 1588 Mutex::Locker locker (m_trap_handler_mutex); 1589 if (!m_calculated_trap_handlers) 1590 { 1591 CalculateTrapHandlerSymbolNames(); 1592 m_calculated_trap_handlers = true; 1593 } 1594 } 1595 return m_trap_handlers; 1596 } 1597 1598