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 Process *process) 533 { 534 Mutex::Locker locker (m_mutex); 535 536 bool success = m_major_os_version != UINT32_MAX; 537 if (IsHost()) 538 { 539 if (!success) 540 { 541 // We have a local host platform 542 success = HostInfo::GetOSVersion(m_major_os_version, m_minor_os_version, m_update_os_version); 543 m_os_version_set_while_connected = success; 544 } 545 } 546 else 547 { 548 // We have a remote platform. We can only fetch the remote 549 // OS version if we are connected, and we don't want to do it 550 // more than once. 551 552 const bool is_connected = IsConnected(); 553 554 bool fetch = false; 555 if (success) 556 { 557 // We have valid OS version info, check to make sure it wasn't 558 // manually set prior to connecting. If it was manually set prior 559 // to connecting, then lets fetch the actual OS version info 560 // if we are now connected. 561 if (is_connected && !m_os_version_set_while_connected) 562 fetch = true; 563 } 564 else 565 { 566 // We don't have valid OS version info, fetch it if we are connected 567 fetch = is_connected; 568 } 569 570 if (fetch) 571 { 572 success = GetRemoteOSVersion (); 573 m_os_version_set_while_connected = success; 574 } 575 } 576 577 if (success) 578 { 579 major = m_major_os_version; 580 minor = m_minor_os_version; 581 update = m_update_os_version; 582 } 583 else if (process) 584 { 585 // Check with the process in case it can answer the question if 586 // a process was provided 587 return process->GetHostOSVersion(major, minor, update); 588 } 589 return success; 590 } 591 592 bool 593 Platform::GetOSBuildString (std::string &s) 594 { 595 s.clear(); 596 597 if (IsHost()) 598 #if !defined(__linux__) 599 return HostInfo::GetOSBuildString(s); 600 #else 601 return false; 602 #endif 603 else 604 return GetRemoteOSBuildString (s); 605 } 606 607 bool 608 Platform::GetOSKernelDescription (std::string &s) 609 { 610 if (IsHost()) 611 #if !defined(__linux__) 612 return HostInfo::GetOSKernelDescription(s); 613 #else 614 return false; 615 #endif 616 else 617 return GetRemoteOSKernelDescription (s); 618 } 619 620 void 621 Platform::AddClangModuleCompilationOptions (Target *target, std::vector<std::string> &options) 622 { 623 std::vector<std::string> default_compilation_options = 624 { 625 "-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc" 626 }; 627 628 options.insert(options.end(), 629 default_compilation_options.begin(), 630 default_compilation_options.end()); 631 } 632 633 634 FileSpec 635 Platform::GetWorkingDirectory () 636 { 637 if (IsHost()) 638 { 639 char cwd[PATH_MAX]; 640 if (getcwd(cwd, sizeof(cwd))) 641 return FileSpec{cwd, true}; 642 else 643 return FileSpec{}; 644 } 645 else 646 { 647 if (!m_working_dir) 648 m_working_dir = GetRemoteWorkingDirectory(); 649 return m_working_dir; 650 } 651 } 652 653 654 struct RecurseCopyBaton 655 { 656 const FileSpec& dst; 657 Platform *platform_ptr; 658 Error error; 659 }; 660 661 662 static FileSpec::EnumerateDirectoryResult 663 RecurseCopy_Callback (void *baton, 664 FileSpec::FileType file_type, 665 const FileSpec &src) 666 { 667 RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton; 668 switch (file_type) 669 { 670 case FileSpec::eFileTypePipe: 671 case FileSpec::eFileTypeSocket: 672 // we have no way to copy pipes and sockets - ignore them and continue 673 return FileSpec::eEnumerateDirectoryResultNext; 674 break; 675 676 case FileSpec::eFileTypeDirectory: 677 { 678 // make the new directory and get in there 679 FileSpec dst_dir = rc_baton->dst; 680 if (!dst_dir.GetFilename()) 681 dst_dir.GetFilename() = src.GetLastPathComponent(); 682 Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir, lldb::eFilePermissionsDirectoryDefault); 683 if (error.Fail()) 684 { 685 rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", 686 dst_dir.GetCString()); 687 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 688 } 689 690 // now recurse 691 std::string src_dir_path (src.GetPath()); 692 693 // Make a filespec that only fills in the directory of a FileSpec so 694 // when we enumerate we can quickly fill in the filename for dst copies 695 FileSpec recurse_dst; 696 recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str()); 697 RecurseCopyBaton rc_baton2 = { recurse_dst, rc_baton->platform_ptr, Error() }; 698 FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2); 699 if (rc_baton2.error.Fail()) 700 { 701 rc_baton->error.SetErrorString(rc_baton2.error.AsCString()); 702 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 703 } 704 return FileSpec::eEnumerateDirectoryResultNext; 705 } 706 break; 707 708 case FileSpec::eFileTypeSymbolicLink: 709 { 710 // copy the file and keep going 711 FileSpec dst_file = rc_baton->dst; 712 if (!dst_file.GetFilename()) 713 dst_file.GetFilename() = src.GetFilename(); 714 715 FileSpec src_resolved; 716 717 rc_baton->error = FileSystem::Readlink(src, src_resolved); 718 719 if (rc_baton->error.Fail()) 720 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 721 722 rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file, src_resolved); 723 724 if (rc_baton->error.Fail()) 725 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 726 727 return FileSpec::eEnumerateDirectoryResultNext; 728 } 729 break; 730 case FileSpec::eFileTypeRegular: 731 { 732 // copy the file and keep going 733 FileSpec dst_file = rc_baton->dst; 734 if (!dst_file.GetFilename()) 735 dst_file.GetFilename() = src.GetFilename(); 736 Error err = rc_baton->platform_ptr->PutFile(src, dst_file); 737 if (err.Fail()) 738 { 739 rc_baton->error.SetErrorString(err.AsCString()); 740 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 741 } 742 return FileSpec::eEnumerateDirectoryResultNext; 743 } 744 break; 745 746 case FileSpec::eFileTypeInvalid: 747 case FileSpec::eFileTypeOther: 748 case FileSpec::eFileTypeUnknown: 749 rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str()); 750 return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out 751 break; 752 } 753 llvm_unreachable("Unhandled FileSpec::FileType!"); 754 } 755 756 Error 757 Platform::Install (const FileSpec& src, const FileSpec& dst) 758 { 759 Error error; 760 761 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 762 if (log) 763 log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str()); 764 FileSpec fixed_dst(dst); 765 766 if (!fixed_dst.GetFilename()) 767 fixed_dst.GetFilename() = src.GetFilename(); 768 769 FileSpec working_dir = GetWorkingDirectory(); 770 771 if (dst) 772 { 773 if (dst.GetDirectory()) 774 { 775 const char first_dst_dir_char = dst.GetDirectory().GetCString()[0]; 776 if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') 777 { 778 fixed_dst.GetDirectory() = dst.GetDirectory(); 779 } 780 // If the fixed destination file doesn't have a directory yet, 781 // then we must have a relative path. We will resolve this relative 782 // path against the platform's working directory 783 if (!fixed_dst.GetDirectory()) 784 { 785 FileSpec relative_spec; 786 std::string path; 787 if (working_dir) 788 { 789 relative_spec = working_dir; 790 relative_spec.AppendPathComponent(dst.GetPath()); 791 fixed_dst.GetDirectory() = relative_spec.GetDirectory(); 792 } 793 else 794 { 795 error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str()); 796 return error; 797 } 798 } 799 } 800 else 801 { 802 if (working_dir) 803 { 804 fixed_dst.GetDirectory().SetCString(working_dir.GetCString()); 805 } 806 else 807 { 808 error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str()); 809 return error; 810 } 811 } 812 } 813 else 814 { 815 if (working_dir) 816 { 817 fixed_dst.GetDirectory().SetCString(working_dir.GetCString()); 818 } 819 else 820 { 821 error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty"); 822 return error; 823 } 824 } 825 826 if (log) 827 log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str()); 828 829 if (GetSupportsRSync()) 830 { 831 error = PutFile(src, dst); 832 } 833 else 834 { 835 switch (src.GetFileType()) 836 { 837 case FileSpec::eFileTypeDirectory: 838 { 839 if (GetFileExists (fixed_dst)) 840 Unlink(fixed_dst); 841 uint32_t permissions = src.GetPermissions(); 842 if (permissions == 0) 843 permissions = eFilePermissionsDirectoryDefault; 844 error = MakeDirectory(fixed_dst, permissions); 845 if (error.Success()) 846 { 847 // Make a filespec that only fills in the directory of a FileSpec so 848 // when we enumerate we can quickly fill in the filename for dst copies 849 FileSpec recurse_dst; 850 recurse_dst.GetDirectory().SetCString(fixed_dst.GetCString()); 851 std::string src_dir_path (src.GetPath()); 852 RecurseCopyBaton baton = { recurse_dst, this, Error() }; 853 FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton); 854 return baton.error; 855 } 856 } 857 break; 858 859 case FileSpec::eFileTypeRegular: 860 if (GetFileExists (fixed_dst)) 861 Unlink(fixed_dst); 862 error = PutFile(src, fixed_dst); 863 break; 864 865 case FileSpec::eFileTypeSymbolicLink: 866 { 867 if (GetFileExists (fixed_dst)) 868 Unlink(fixed_dst); 869 FileSpec src_resolved; 870 error = FileSystem::Readlink(src, src_resolved); 871 if (error.Success()) 872 error = CreateSymlink(dst, src_resolved); 873 } 874 break; 875 case FileSpec::eFileTypePipe: 876 error.SetErrorString("platform install doesn't handle pipes"); 877 break; 878 case FileSpec::eFileTypeSocket: 879 error.SetErrorString("platform install doesn't handle sockets"); 880 break; 881 case FileSpec::eFileTypeInvalid: 882 case FileSpec::eFileTypeUnknown: 883 case FileSpec::eFileTypeOther: 884 error.SetErrorString("platform install doesn't handle non file or directory items"); 885 break; 886 } 887 } 888 return error; 889 } 890 891 bool 892 Platform::SetWorkingDirectory(const FileSpec &file_spec) 893 { 894 if (IsHost()) 895 { 896 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 897 if (log) 898 log->Printf("Platform::SetWorkingDirectory('%s')", 899 file_spec.GetCString()); 900 if (file_spec) 901 { 902 if (::chdir(file_spec.GetCString()) == 0) 903 return true; 904 } 905 return false; 906 } 907 else 908 { 909 m_working_dir.Clear(); 910 return SetRemoteWorkingDirectory(file_spec); 911 } 912 } 913 914 Error 915 Platform::MakeDirectory(const FileSpec &file_spec, uint32_t permissions) 916 { 917 if (IsHost()) 918 return FileSystem::MakeDirectory(file_spec, permissions); 919 else 920 { 921 Error error; 922 error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); 923 return error; 924 } 925 } 926 927 Error 928 Platform::GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions) 929 { 930 if (IsHost()) 931 return FileSystem::GetFilePermissions(file_spec, file_permissions); 932 else 933 { 934 Error error; 935 error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); 936 return error; 937 } 938 } 939 940 Error 941 Platform::SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions) 942 { 943 if (IsHost()) 944 return FileSystem::SetFilePermissions(file_spec, file_permissions); 945 else 946 { 947 Error error; 948 error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__); 949 return error; 950 } 951 } 952 953 ConstString 954 Platform::GetName () 955 { 956 return GetPluginName(); 957 } 958 959 const char * 960 Platform::GetHostname () 961 { 962 if (IsHost()) 963 return "127.0.0.1"; 964 965 if (m_name.empty()) 966 return NULL; 967 return m_name.c_str(); 968 } 969 970 ConstString 971 Platform::GetFullNameForDylib (ConstString basename) 972 { 973 return basename; 974 } 975 976 bool 977 Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir) 978 { 979 Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM); 980 if (log) 981 log->Printf("Platform::SetRemoteWorkingDirectory('%s')", 982 working_dir.GetCString()); 983 m_working_dir = working_dir; 984 return true; 985 } 986 987 const char * 988 Platform::GetUserName (uint32_t uid) 989 { 990 #if !defined(LLDB_DISABLE_POSIX) 991 const char *user_name = GetCachedUserName(uid); 992 if (user_name) 993 return user_name; 994 if (IsHost()) 995 { 996 std::string name; 997 if (HostInfo::LookupUserName(uid, name)) 998 return SetCachedUserName (uid, name.c_str(), name.size()); 999 } 1000 #endif 1001 return NULL; 1002 } 1003 1004 const char * 1005 Platform::GetGroupName (uint32_t gid) 1006 { 1007 #if !defined(LLDB_DISABLE_POSIX) 1008 const char *group_name = GetCachedGroupName(gid); 1009 if (group_name) 1010 return group_name; 1011 if (IsHost()) 1012 { 1013 std::string name; 1014 if (HostInfo::LookupGroupName(gid, name)) 1015 return SetCachedGroupName (gid, name.c_str(), name.size()); 1016 } 1017 #endif 1018 return NULL; 1019 } 1020 1021 bool 1022 Platform::SetOSVersion (uint32_t major, 1023 uint32_t minor, 1024 uint32_t update) 1025 { 1026 if (IsHost()) 1027 { 1028 // We don't need anyone setting the OS version for the host platform, 1029 // we should be able to figure it out by calling HostInfo::GetOSVersion(...). 1030 return false; 1031 } 1032 else 1033 { 1034 // We have a remote platform, allow setting the target OS version if 1035 // we aren't connected, since if we are connected, we should be able to 1036 // request the remote OS version from the connected platform. 1037 if (IsConnected()) 1038 return false; 1039 else 1040 { 1041 // We aren't connected and we might want to set the OS version 1042 // ahead of time before we connect so we can peruse files and 1043 // use a local SDK or PDK cache of support files to disassemble 1044 // or do other things. 1045 m_major_os_version = major; 1046 m_minor_os_version = minor; 1047 m_update_os_version = update; 1048 return true; 1049 } 1050 } 1051 return false; 1052 } 1053 1054 1055 Error 1056 Platform::ResolveExecutable (const ModuleSpec &module_spec, 1057 lldb::ModuleSP &exe_module_sp, 1058 const FileSpecList *module_search_paths_ptr) 1059 { 1060 Error error; 1061 if (module_spec.GetFileSpec().Exists()) 1062 { 1063 if (module_spec.GetArchitecture().IsValid()) 1064 { 1065 error = ModuleList::GetSharedModule (module_spec, 1066 exe_module_sp, 1067 module_search_paths_ptr, 1068 NULL, 1069 NULL); 1070 } 1071 else 1072 { 1073 // No valid architecture was specified, ask the platform for 1074 // the architectures that we should be using (in the correct order) 1075 // and see if we can find a match that way 1076 ModuleSpec arch_module_spec(module_spec); 1077 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, arch_module_spec.GetArchitecture()); ++idx) 1078 { 1079 error = ModuleList::GetSharedModule (arch_module_spec, 1080 exe_module_sp, 1081 module_search_paths_ptr, 1082 NULL, 1083 NULL); 1084 // Did we find an executable using one of the 1085 if (error.Success() && exe_module_sp) 1086 break; 1087 } 1088 } 1089 } 1090 else 1091 { 1092 error.SetErrorStringWithFormat ("'%s' does not exist", 1093 module_spec.GetFileSpec().GetPath().c_str()); 1094 } 1095 return error; 1096 } 1097 1098 Error 1099 Platform::ResolveSymbolFile (Target &target, 1100 const ModuleSpec &sym_spec, 1101 FileSpec &sym_file) 1102 { 1103 Error error; 1104 if (sym_spec.GetSymbolFileSpec().Exists()) 1105 sym_file = sym_spec.GetSymbolFileSpec(); 1106 else 1107 error.SetErrorString("unable to resolve symbol file"); 1108 return error; 1109 1110 } 1111 1112 1113 1114 bool 1115 Platform::ResolveRemotePath (const FileSpec &platform_path, 1116 FileSpec &resolved_platform_path) 1117 { 1118 resolved_platform_path = platform_path; 1119 return resolved_platform_path.ResolvePath(); 1120 } 1121 1122 1123 const ArchSpec & 1124 Platform::GetSystemArchitecture() 1125 { 1126 if (IsHost()) 1127 { 1128 if (!m_system_arch.IsValid()) 1129 { 1130 // We have a local host platform 1131 m_system_arch = HostInfo::GetArchitecture(); 1132 m_system_arch_set_while_connected = m_system_arch.IsValid(); 1133 } 1134 } 1135 else 1136 { 1137 // We have a remote platform. We can only fetch the remote 1138 // system architecture if we are connected, and we don't want to do it 1139 // more than once. 1140 1141 const bool is_connected = IsConnected(); 1142 1143 bool fetch = false; 1144 if (m_system_arch.IsValid()) 1145 { 1146 // We have valid OS version info, check to make sure it wasn't 1147 // manually set prior to connecting. If it was manually set prior 1148 // to connecting, then lets fetch the actual OS version info 1149 // if we are now connected. 1150 if (is_connected && !m_system_arch_set_while_connected) 1151 fetch = true; 1152 } 1153 else 1154 { 1155 // We don't have valid OS version info, fetch it if we are connected 1156 fetch = is_connected; 1157 } 1158 1159 if (fetch) 1160 { 1161 m_system_arch = GetRemoteSystemArchitecture (); 1162 m_system_arch_set_while_connected = m_system_arch.IsValid(); 1163 } 1164 } 1165 return m_system_arch; 1166 } 1167 1168 1169 Error 1170 Platform::ConnectRemote (Args& args) 1171 { 1172 Error error; 1173 if (IsHost()) 1174 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString()); 1175 else 1176 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetPluginName().GetCString()); 1177 return error; 1178 } 1179 1180 Error 1181 Platform::DisconnectRemote () 1182 { 1183 Error error; 1184 if (IsHost()) 1185 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetPluginName().GetCString()); 1186 else 1187 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetPluginName().GetCString()); 1188 return error; 1189 } 1190 1191 bool 1192 Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 1193 { 1194 // Take care of the host case so that each subclass can just 1195 // call this function to get the host functionality. 1196 if (IsHost()) 1197 return Host::GetProcessInfo (pid, process_info); 1198 return false; 1199 } 1200 1201 uint32_t 1202 Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info, 1203 ProcessInstanceInfoList &process_infos) 1204 { 1205 // Take care of the host case so that each subclass can just 1206 // call this function to get the host functionality. 1207 uint32_t match_count = 0; 1208 if (IsHost()) 1209 match_count = Host::FindProcesses (match_info, process_infos); 1210 return match_count; 1211 } 1212 1213 1214 Error 1215 Platform::LaunchProcess (ProcessLaunchInfo &launch_info) 1216 { 1217 Error error; 1218 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1219 if (log) 1220 log->Printf ("Platform::%s()", __FUNCTION__); 1221 1222 // Take care of the host case so that each subclass can just 1223 // call this function to get the host functionality. 1224 if (IsHost()) 1225 { 1226 if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY")) 1227 launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY); 1228 1229 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 1230 { 1231 const bool is_localhost = true; 1232 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); 1233 const bool first_arg_is_full_shell_command = false; 1234 uint32_t num_resumes = GetResumeCountForLaunchInfo (launch_info); 1235 if (log) 1236 { 1237 const FileSpec &shell = launch_info.GetShell(); 1238 const char *shell_str = (shell) ? shell.GetPath().c_str() : "<null>"; 1239 log->Printf ("Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32 ", shell is '%s'", 1240 __FUNCTION__, 1241 num_resumes, 1242 shell_str); 1243 } 1244 1245 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, 1246 is_localhost, 1247 will_debug, 1248 first_arg_is_full_shell_command, 1249 num_resumes)) 1250 return error; 1251 } 1252 else if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) 1253 { 1254 error = ShellExpandArguments(launch_info); 1255 if (error.Fail()) 1256 return error; 1257 } 1258 1259 if (log) 1260 log->Printf ("Platform::%s final launch_info resume count: %" PRIu32, __FUNCTION__, launch_info.GetResumeCount ()); 1261 1262 error = Host::LaunchProcess (launch_info); 1263 } 1264 else 1265 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes"); 1266 return error; 1267 } 1268 1269 Error 1270 Platform::ShellExpandArguments (ProcessLaunchInfo &launch_info) 1271 { 1272 if (IsHost()) 1273 return Host::ShellExpandArguments(launch_info); 1274 return Error("base lldb_private::Platform class can't expand arguments"); 1275 } 1276 1277 Error 1278 Platform::KillProcess (const lldb::pid_t pid) 1279 { 1280 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1281 if (log) 1282 log->Printf ("Platform::%s, pid %" PRIu64, __FUNCTION__, pid); 1283 1284 // Try to find a process plugin to handle this Kill request. If we can't, fall back to 1285 // the default OS implementation. 1286 size_t num_debuggers = Debugger::GetNumDebuggers(); 1287 for (size_t didx = 0; didx < num_debuggers; ++didx) 1288 { 1289 DebuggerSP debugger = Debugger::GetDebuggerAtIndex(didx); 1290 lldb_private::TargetList &targets = debugger->GetTargetList(); 1291 for (int tidx = 0; tidx < targets.GetNumTargets(); ++tidx) 1292 { 1293 ProcessSP process = targets.GetTargetAtIndex(tidx)->GetProcessSP(); 1294 if (process->GetID() == pid) 1295 return process->Destroy(true); 1296 } 1297 } 1298 1299 if (!IsHost()) 1300 { 1301 return Error("base lldb_private::Platform class can't kill remote processes unless " 1302 "they are controlled by a process plugin"); 1303 } 1304 Host::Kill(pid, SIGTERM); 1305 return Error(); 1306 } 1307 1308 lldb::ProcessSP 1309 Platform::DebugProcess (ProcessLaunchInfo &launch_info, 1310 Debugger &debugger, 1311 Target *target, // Can be NULL, if NULL create a new target, else use existing one 1312 Error &error) 1313 { 1314 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1315 if (log) 1316 log->Printf ("Platform::%s entered (target %p)", __FUNCTION__, static_cast<void*>(target)); 1317 1318 ProcessSP process_sp; 1319 // Make sure we stop at the entry point 1320 launch_info.GetFlags ().Set (eLaunchFlagDebug); 1321 // We always launch the process we are going to debug in a separate process 1322 // group, since then we can handle ^C interrupts ourselves w/o having to worry 1323 // about the target getting them as well. 1324 launch_info.SetLaunchInSeparateProcessGroup(true); 1325 1326 error = LaunchProcess (launch_info); 1327 if (error.Success()) 1328 { 1329 if (log) 1330 log->Printf ("Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 ")", __FUNCTION__, launch_info.GetProcessID ()); 1331 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 1332 { 1333 ProcessAttachInfo attach_info (launch_info); 1334 process_sp = Attach (attach_info, debugger, target, error); 1335 if (process_sp) 1336 { 1337 if (log) 1338 log->Printf ("Platform::%s Attach() succeeded, Process plugin: %s", __FUNCTION__, process_sp->GetPluginName ().AsCString ()); 1339 launch_info.SetHijackListener(attach_info.GetHijackListener()); 1340 1341 // Since we attached to the process, it will think it needs to detach 1342 // if the process object just goes away without an explicit call to 1343 // Process::Kill() or Process::Detach(), so let it know to kill the 1344 // process if this happens. 1345 process_sp->SetShouldDetach (false); 1346 1347 // If we didn't have any file actions, the pseudo terminal might 1348 // have been used where the slave side was given as the file to 1349 // open for stdin/out/err after we have already opened the master 1350 // so we can read/write stdin/out/err. 1351 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 1352 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) 1353 { 1354 process_sp->SetSTDIOFileDescriptor(pty_fd); 1355 } 1356 } 1357 else 1358 { 1359 if (log) 1360 log->Printf ("Platform::%s Attach() failed: %s", __FUNCTION__, error.AsCString ()); 1361 } 1362 } 1363 else 1364 { 1365 if (log) 1366 log->Printf ("Platform::%s LaunchProcess() returned launch_info with invalid process id", __FUNCTION__); 1367 } 1368 } 1369 else 1370 { 1371 if (log) 1372 log->Printf ("Platform::%s LaunchProcess() failed: %s", __FUNCTION__, error.AsCString ()); 1373 } 1374 1375 return process_sp; 1376 } 1377 1378 1379 lldb::PlatformSP 1380 Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr) 1381 { 1382 lldb::PlatformSP platform_sp; 1383 Error error; 1384 if (arch.IsValid()) 1385 platform_sp = Platform::Create (arch, platform_arch_ptr, error); 1386 return platform_sp; 1387 } 1388 1389 1390 //------------------------------------------------------------------ 1391 /// Lets a platform answer if it is compatible with a given 1392 /// architecture and the target triple contained within. 1393 //------------------------------------------------------------------ 1394 bool 1395 Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr) 1396 { 1397 // If the architecture is invalid, we must answer true... 1398 if (arch.IsValid()) 1399 { 1400 ArchSpec platform_arch; 1401 // Try for an exact architecture match first. 1402 if (exact_arch_match) 1403 { 1404 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 1405 { 1406 if (arch.IsExactMatch(platform_arch)) 1407 { 1408 if (compatible_arch_ptr) 1409 *compatible_arch_ptr = platform_arch; 1410 return true; 1411 } 1412 } 1413 } 1414 else 1415 { 1416 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 1417 { 1418 if (arch.IsCompatibleMatch(platform_arch)) 1419 { 1420 if (compatible_arch_ptr) 1421 *compatible_arch_ptr = platform_arch; 1422 return true; 1423 } 1424 } 1425 } 1426 } 1427 if (compatible_arch_ptr) 1428 compatible_arch_ptr->Clear(); 1429 return false; 1430 } 1431 1432 Error 1433 Platform::PutFile (const FileSpec& source, 1434 const FileSpec& destination, 1435 uint32_t uid, 1436 uint32_t gid) 1437 { 1438 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 1439 if (log) 1440 log->Printf("[PutFile] Using block by block transfer....\n"); 1441 1442 uint32_t source_open_options = File::eOpenOptionRead | File::eOpenOptionCloseOnExec; 1443 if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink) 1444 source_open_options |= File::eOpenoptionDontFollowSymlinks; 1445 1446 File source_file(source, source_open_options, lldb::eFilePermissionsUserRW); 1447 Error error; 1448 uint32_t permissions = source_file.GetPermissions(error); 1449 if (permissions == 0) 1450 permissions = lldb::eFilePermissionsFileDefault; 1451 1452 if (!source_file.IsValid()) 1453 return Error("PutFile: unable to open source file"); 1454 lldb::user_id_t dest_file = OpenFile (destination, 1455 File::eOpenOptionCanCreate | 1456 File::eOpenOptionWrite | 1457 File::eOpenOptionTruncate | 1458 File::eOpenOptionCloseOnExec, 1459 permissions, 1460 error); 1461 if (log) 1462 log->Printf ("dest_file = %" PRIu64 "\n", dest_file); 1463 1464 if (error.Fail()) 1465 return error; 1466 if (dest_file == UINT64_MAX) 1467 return Error("unable to open target file"); 1468 lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0)); 1469 uint64_t offset = 0; 1470 for (;;) 1471 { 1472 size_t bytes_read = buffer_sp->GetByteSize(); 1473 error = source_file.Read(buffer_sp->GetBytes(), bytes_read); 1474 if (error.Fail() || bytes_read == 0) 1475 break; 1476 1477 const uint64_t bytes_written = WriteFile(dest_file, offset, 1478 buffer_sp->GetBytes(), bytes_read, error); 1479 if (error.Fail()) 1480 break; 1481 1482 offset += bytes_written; 1483 if (bytes_written != bytes_read) 1484 { 1485 // We didn't write the correct number of bytes, so adjust 1486 // the file position in the source file we are reading from... 1487 source_file.SeekFromStart(offset); 1488 } 1489 } 1490 CloseFile(dest_file, error); 1491 1492 if (uid == UINT32_MAX && gid == UINT32_MAX) 1493 return error; 1494 1495 // TODO: ChownFile? 1496 1497 return error; 1498 } 1499 1500 Error 1501 Platform::GetFile(const FileSpec &source, 1502 const FileSpec &destination) 1503 { 1504 Error error("unimplemented"); 1505 return error; 1506 } 1507 1508 Error 1509 Platform::CreateSymlink(const FileSpec &src, // The name of the link is in src 1510 const FileSpec &dst) // The symlink points to dst 1511 { 1512 Error error("unimplemented"); 1513 return error; 1514 } 1515 1516 bool 1517 Platform::GetFileExists(const lldb_private::FileSpec &file_spec) 1518 { 1519 return false; 1520 } 1521 1522 Error 1523 Platform::Unlink(const FileSpec &path) 1524 { 1525 Error error("unimplemented"); 1526 return error; 1527 } 1528 1529 uint64_t 1530 Platform::ConvertMmapFlagsToPlatform(const ArchSpec &arch, unsigned flags) 1531 { 1532 uint64_t flags_platform = 0; 1533 if (flags & eMmapFlagsPrivate) 1534 flags_platform |= MAP_PRIVATE; 1535 if (flags & eMmapFlagsAnon) 1536 flags_platform |= MAP_ANON; 1537 return flags_platform; 1538 } 1539 1540 lldb_private::Error 1541 Platform::RunShellCommand(const char *command, // Shouldn't be NULL 1542 const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory 1543 int *status_ptr, // Pass NULL if you don't want the process exit status 1544 int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit 1545 std::string *command_output, // Pass NULL if you don't want the command output 1546 uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish 1547 { 1548 if (IsHost()) 1549 return Host::RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); 1550 else 1551 return Error("unimplemented"); 1552 } 1553 1554 1555 bool 1556 Platform::CalculateMD5 (const FileSpec& file_spec, 1557 uint64_t &low, 1558 uint64_t &high) 1559 { 1560 if (IsHost()) 1561 return FileSystem::CalculateMD5(file_spec, low, high); 1562 else 1563 return false; 1564 } 1565 1566 void 1567 Platform::SetLocalCacheDirectory (const char* local) 1568 { 1569 m_local_cache_directory.assign(local); 1570 } 1571 1572 const char* 1573 Platform::GetLocalCacheDirectory () 1574 { 1575 return m_local_cache_directory.c_str(); 1576 } 1577 1578 static OptionDefinition 1579 g_rsync_option_table[] = 1580 { 1581 { LLDB_OPT_SET_ALL, false, "rsync" , 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Enable rsync." }, 1582 { LLDB_OPT_SET_ALL, false, "rsync-opts" , 'R', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific options required for rsync to work." }, 1583 { LLDB_OPT_SET_ALL, false, "rsync-prefix" , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific rsync prefix put before the remote path." }, 1584 { 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." }, 1585 }; 1586 1587 static OptionDefinition 1588 g_ssh_option_table[] = 1589 { 1590 { LLDB_OPT_SET_ALL, false, "ssh" , 's', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone , "Enable SSH." }, 1591 { LLDB_OPT_SET_ALL, false, "ssh-opts" , 'S', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCommandName , "Platform-specific options required for SSH to work." }, 1592 }; 1593 1594 static OptionDefinition 1595 g_caching_option_table[] = 1596 { 1597 { LLDB_OPT_SET_ALL, false, "local-cache-dir" , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePath , "Path in which to store local copies of files." }, 1598 }; 1599 1600 OptionGroupPlatformRSync::OptionGroupPlatformRSync () 1601 { 1602 } 1603 1604 OptionGroupPlatformRSync::~OptionGroupPlatformRSync () 1605 { 1606 } 1607 1608 const lldb_private::OptionDefinition* 1609 OptionGroupPlatformRSync::GetDefinitions () 1610 { 1611 return g_rsync_option_table; 1612 } 1613 1614 void 1615 OptionGroupPlatformRSync::OptionParsingStarting (CommandInterpreter &interpreter) 1616 { 1617 m_rsync = false; 1618 m_rsync_opts.clear(); 1619 m_rsync_prefix.clear(); 1620 m_ignores_remote_hostname = false; 1621 } 1622 1623 lldb_private::Error 1624 OptionGroupPlatformRSync::SetOptionValue (CommandInterpreter &interpreter, 1625 uint32_t option_idx, 1626 const char *option_arg) 1627 { 1628 Error error; 1629 char short_option = (char) GetDefinitions()[option_idx].short_option; 1630 switch (short_option) 1631 { 1632 case 'r': 1633 m_rsync = true; 1634 break; 1635 1636 case 'R': 1637 m_rsync_opts.assign(option_arg); 1638 break; 1639 1640 case 'P': 1641 m_rsync_prefix.assign(option_arg); 1642 break; 1643 1644 case 'i': 1645 m_ignores_remote_hostname = true; 1646 break; 1647 1648 default: 1649 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1650 break; 1651 } 1652 1653 return error; 1654 } 1655 1656 uint32_t 1657 OptionGroupPlatformRSync::GetNumDefinitions () 1658 { 1659 return llvm::array_lengthof(g_rsync_option_table); 1660 } 1661 1662 lldb::BreakpointSP 1663 Platform::SetThreadCreationBreakpoint (lldb_private::Target &target) 1664 { 1665 return lldb::BreakpointSP(); 1666 } 1667 1668 OptionGroupPlatformSSH::OptionGroupPlatformSSH () 1669 { 1670 } 1671 1672 OptionGroupPlatformSSH::~OptionGroupPlatformSSH () 1673 { 1674 } 1675 1676 const lldb_private::OptionDefinition* 1677 OptionGroupPlatformSSH::GetDefinitions () 1678 { 1679 return g_ssh_option_table; 1680 } 1681 1682 void 1683 OptionGroupPlatformSSH::OptionParsingStarting (CommandInterpreter &interpreter) 1684 { 1685 m_ssh = false; 1686 m_ssh_opts.clear(); 1687 } 1688 1689 lldb_private::Error 1690 OptionGroupPlatformSSH::SetOptionValue (CommandInterpreter &interpreter, 1691 uint32_t option_idx, 1692 const char *option_arg) 1693 { 1694 Error error; 1695 char short_option = (char) GetDefinitions()[option_idx].short_option; 1696 switch (short_option) 1697 { 1698 case 's': 1699 m_ssh = true; 1700 break; 1701 1702 case 'S': 1703 m_ssh_opts.assign(option_arg); 1704 break; 1705 1706 default: 1707 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1708 break; 1709 } 1710 1711 return error; 1712 } 1713 1714 uint32_t 1715 OptionGroupPlatformSSH::GetNumDefinitions () 1716 { 1717 return llvm::array_lengthof(g_ssh_option_table); 1718 } 1719 1720 OptionGroupPlatformCaching::OptionGroupPlatformCaching () 1721 { 1722 } 1723 1724 OptionGroupPlatformCaching::~OptionGroupPlatformCaching () 1725 { 1726 } 1727 1728 const lldb_private::OptionDefinition* 1729 OptionGroupPlatformCaching::GetDefinitions () 1730 { 1731 return g_caching_option_table; 1732 } 1733 1734 void 1735 OptionGroupPlatformCaching::OptionParsingStarting (CommandInterpreter &interpreter) 1736 { 1737 m_cache_dir.clear(); 1738 } 1739 1740 lldb_private::Error 1741 OptionGroupPlatformCaching::SetOptionValue (CommandInterpreter &interpreter, 1742 uint32_t option_idx, 1743 const char *option_arg) 1744 { 1745 Error error; 1746 char short_option = (char) GetDefinitions()[option_idx].short_option; 1747 switch (short_option) 1748 { 1749 case 'c': 1750 m_cache_dir.assign(option_arg); 1751 break; 1752 1753 default: 1754 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1755 break; 1756 } 1757 1758 return error; 1759 } 1760 1761 uint32_t 1762 OptionGroupPlatformCaching::GetNumDefinitions () 1763 { 1764 return llvm::array_lengthof(g_caching_option_table); 1765 } 1766 1767 size_t 1768 Platform::GetEnvironment (StringList &environment) 1769 { 1770 environment.Clear(); 1771 return false; 1772 } 1773 1774 const std::vector<ConstString> & 1775 Platform::GetTrapHandlerSymbolNames () 1776 { 1777 if (!m_calculated_trap_handlers) 1778 { 1779 Mutex::Locker locker (m_mutex); 1780 if (!m_calculated_trap_handlers) 1781 { 1782 CalculateTrapHandlerSymbolNames(); 1783 m_calculated_trap_handlers = true; 1784 } 1785 } 1786 return m_trap_handlers; 1787 } 1788 1789 Error 1790 Platform::GetCachedExecutable (ModuleSpec &module_spec, 1791 lldb::ModuleSP &module_sp, 1792 const FileSpecList *module_search_paths_ptr, 1793 Platform &remote_platform) 1794 { 1795 const auto platform_spec = module_spec.GetFileSpec (); 1796 const auto error = LoadCachedExecutable (module_spec, 1797 module_sp, 1798 module_search_paths_ptr, 1799 remote_platform); 1800 if (error.Success ()) 1801 { 1802 module_spec.GetFileSpec () = module_sp->GetFileSpec (); 1803 module_spec.GetPlatformFileSpec () = platform_spec; 1804 } 1805 1806 return error; 1807 } 1808 1809 Error 1810 Platform::LoadCachedExecutable (const ModuleSpec &module_spec, 1811 lldb::ModuleSP &module_sp, 1812 const FileSpecList *module_search_paths_ptr, 1813 Platform &remote_platform) 1814 { 1815 return GetRemoteSharedModule (module_spec, 1816 nullptr, 1817 module_sp, 1818 [&](const ModuleSpec &spec) 1819 { 1820 return remote_platform.ResolveExecutable ( 1821 spec, module_sp, module_search_paths_ptr); 1822 }, 1823 nullptr); 1824 } 1825 1826 Error 1827 Platform::GetRemoteSharedModule (const ModuleSpec &module_spec, 1828 Process* process, 1829 lldb::ModuleSP &module_sp, 1830 const ModuleResolver &module_resolver, 1831 bool *did_create_ptr) 1832 { 1833 // Get module information from a target. 1834 ModuleSpec resolved_module_spec; 1835 bool got_module_spec = false; 1836 if (process) 1837 { 1838 // Try to get module information from the process 1839 if (process->GetModuleSpec (module_spec.GetFileSpec (), module_spec.GetArchitecture (), resolved_module_spec)) 1840 got_module_spec = true; 1841 } 1842 1843 if (!got_module_spec) 1844 { 1845 // Get module information from a target. 1846 if (!GetModuleSpec (module_spec.GetFileSpec (), module_spec.GetArchitecture (), resolved_module_spec)) 1847 return module_resolver (module_spec); 1848 } 1849 1850 // Trying to find a module by UUID on local file system. 1851 const auto error = module_resolver (resolved_module_spec); 1852 if (error.Fail ()) 1853 { 1854 if (GetCachedSharedModule (resolved_module_spec, module_sp, did_create_ptr)) 1855 return Error (); 1856 } 1857 1858 return error; 1859 } 1860 1861 bool 1862 Platform::GetCachedSharedModule (const ModuleSpec &module_spec, 1863 lldb::ModuleSP &module_sp, 1864 bool *did_create_ptr) 1865 { 1866 if (IsHost() || 1867 !GetGlobalPlatformProperties ()->GetUseModuleCache () || 1868 !GetGlobalPlatformProperties ()->GetModuleCacheDirectory ()) 1869 return false; 1870 1871 Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM); 1872 1873 // Check local cache for a module. 1874 auto error = m_module_cache->GetAndPut ( 1875 GetModuleCacheRoot (), 1876 GetCacheHostname (), 1877 module_spec, 1878 [this](const ModuleSpec &module_spec, const FileSpec &tmp_download_file_spec) 1879 { 1880 return DownloadModuleSlice (module_spec.GetFileSpec (), 1881 module_spec.GetObjectOffset (), 1882 module_spec.GetObjectSize (), 1883 tmp_download_file_spec); 1884 1885 }, 1886 [this](const ModuleSP& module_sp, const FileSpec& tmp_download_file_spec) 1887 { 1888 return DownloadSymbolFile (module_sp, tmp_download_file_spec); 1889 }, 1890 module_sp, 1891 did_create_ptr); 1892 if (error.Success ()) 1893 return true; 1894 1895 if (log) 1896 log->Printf("Platform::%s - module %s not found in local cache: %s", 1897 __FUNCTION__, module_spec.GetUUID ().GetAsString ().c_str (), error.AsCString ()); 1898 return false; 1899 } 1900 1901 Error 1902 Platform::DownloadModuleSlice (const FileSpec& src_file_spec, 1903 const uint64_t src_offset, 1904 const uint64_t src_size, 1905 const FileSpec& dst_file_spec) 1906 { 1907 Error error; 1908 1909 std::ofstream dst (dst_file_spec.GetPath(), std::ios::out | std::ios::binary); 1910 if (!dst.is_open()) 1911 { 1912 error.SetErrorStringWithFormat ("unable to open destination file: %s", dst_file_spec.GetPath ().c_str ()); 1913 return error; 1914 } 1915 1916 auto src_fd = OpenFile (src_file_spec, 1917 File::eOpenOptionRead, 1918 lldb::eFilePermissionsFileDefault, 1919 error); 1920 1921 if (error.Fail ()) 1922 { 1923 error.SetErrorStringWithFormat ("unable to open source file: %s", error.AsCString ()); 1924 return error; 1925 } 1926 1927 std::vector<char> buffer (1024); 1928 auto offset = src_offset; 1929 uint64_t total_bytes_read = 0; 1930 while (total_bytes_read < src_size) 1931 { 1932 const auto to_read = std::min (static_cast<uint64_t>(buffer.size ()), src_size - total_bytes_read); 1933 const uint64_t n_read = ReadFile (src_fd, offset, &buffer[0], to_read, error); 1934 if (error.Fail ()) 1935 break; 1936 if (n_read == 0) 1937 { 1938 error.SetErrorString ("read 0 bytes"); 1939 break; 1940 } 1941 offset += n_read; 1942 total_bytes_read += n_read; 1943 dst.write (&buffer[0], n_read); 1944 } 1945 1946 Error close_error; 1947 CloseFile (src_fd, close_error); // Ignoring close error. 1948 1949 return error; 1950 } 1951 1952 Error 1953 Platform::DownloadSymbolFile (const lldb::ModuleSP& module_sp, const FileSpec& dst_file_spec) 1954 { 1955 return Error ("Symbol file downloading not supported by the default platform."); 1956 } 1957 1958 FileSpec 1959 Platform::GetModuleCacheRoot () 1960 { 1961 auto dir_spec = GetGlobalPlatformProperties ()->GetModuleCacheDirectory (); 1962 dir_spec.AppendPathComponent (GetName ().AsCString ()); 1963 return dir_spec; 1964 } 1965 1966 const char * 1967 Platform::GetCacheHostname () 1968 { 1969 return GetHostname (); 1970 } 1971 1972 const UnixSignalsSP & 1973 Platform::GetRemoteUnixSignals() 1974 { 1975 static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>(); 1976 return s_default_unix_signals_sp; 1977 } 1978 1979 const UnixSignalsSP & 1980 Platform::GetUnixSignals() 1981 { 1982 if (IsHost()) 1983 return Host::GetUnixSignals(); 1984 return GetRemoteUnixSignals(); 1985 } 1986