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