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