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