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