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