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