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