Platform.cpp revision 81a96aa6242f7b559770f5dc62316253cb8cb0d4
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// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/Breakpoint/BreakpointIDList.h" 17#include "lldb/Core/Error.h" 18#include "lldb/Core/Log.h" 19#include "lldb/Core/ModuleSpec.h" 20#include "lldb/Core/PluginManager.h" 21#include "lldb/Host/FileSpec.h" 22#include "lldb/Host/Host.h" 23#include "lldb/Target/Process.h" 24#include "lldb/Target/Target.h" 25 26using namespace lldb; 27using namespace lldb_private; 28 29// Use a singleton function for g_local_platform_sp to avoid init 30// constructors since LLDB is often part of a shared library 31static PlatformSP& 32GetDefaultPlatformSP () 33{ 34 static PlatformSP g_default_platform_sp; 35 return g_default_platform_sp; 36} 37 38static Mutex & 39GetConnectedPlatformListMutex () 40{ 41 static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive); 42 return g_remote_connected_platforms_mutex; 43} 44static std::vector<PlatformSP> & 45GetConnectedPlatformList () 46{ 47 static std::vector<PlatformSP> g_remote_connected_platforms; 48 return g_remote_connected_platforms; 49} 50 51 52const char * 53Platform::GetHostPlatformName () 54{ 55 return "host"; 56} 57 58//------------------------------------------------------------------ 59/// Get the native host platform plug-in. 60/// 61/// There should only be one of these for each host that LLDB runs 62/// upon that should be statically compiled in and registered using 63/// preprocessor macros or other similar build mechanisms. 64/// 65/// This platform will be used as the default platform when launching 66/// or attaching to processes unless another platform is specified. 67//------------------------------------------------------------------ 68PlatformSP 69Platform::GetDefaultPlatform () 70{ 71 return GetDefaultPlatformSP (); 72} 73 74void 75Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp) 76{ 77 // The native platform should use its static void Platform::Initialize() 78 // function to register itself as the native platform. 79 GetDefaultPlatformSP () = platform_sp; 80} 81 82Error 83Platform::GetFile (const FileSpec &platform_file, 84 const UUID *uuid_ptr, 85 FileSpec &local_file) 86{ 87 // Default to the local case 88 local_file = platform_file; 89 return Error(); 90} 91 92FileSpecList 93Platform::LocateExecutableScriptingResources (Target *target, Module &module) 94{ 95 return FileSpecList(); 96} 97 98Platform* 99Platform::FindPlugin (Process *process, const char *plugin_name) 100{ 101 PlatformCreateInstance create_callback = NULL; 102 if (plugin_name) 103 { 104 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name); 105 if (create_callback) 106 { 107 ArchSpec arch; 108 if (process) 109 { 110 arch = process->GetTarget().GetArchitecture(); 111 } 112 STD_UNIQUE_PTR(Platform) instance_ap(create_callback(process, &arch)); 113 if (instance_ap.get()) 114 return instance_ap.release(); 115 } 116 } 117 else 118 { 119 for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx) 120 { 121 STD_UNIQUE_PTR(Platform) instance_ap(create_callback(process, false)); 122 if (instance_ap.get()) 123 return instance_ap.release(); 124 } 125 } 126 return NULL; 127} 128 129Error 130Platform::GetSharedModule (const ModuleSpec &module_spec, 131 ModuleSP &module_sp, 132 const FileSpecList *module_search_paths_ptr, 133 ModuleSP *old_module_sp_ptr, 134 bool *did_create_ptr) 135{ 136 // Don't do any path remapping for the default implementation 137 // of the platform GetSharedModule function, just call through 138 // to our static ModuleList function. Platform subclasses that 139 // implement remote debugging, might have a developer kits 140 // installed that have cached versions of the files for the 141 // remote target, or might implement a download and cache 142 // locally implementation. 143 const bool always_create = false; 144 return ModuleList::GetSharedModule (module_spec, 145 module_sp, 146 module_search_paths_ptr, 147 old_module_sp_ptr, 148 did_create_ptr, 149 always_create); 150} 151 152PlatformSP 153Platform::Create (const char *platform_name, Error &error) 154{ 155 PlatformCreateInstance create_callback = NULL; 156 lldb::PlatformSP platform_sp; 157 if (platform_name && platform_name[0]) 158 { 159 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (platform_name); 160 if (create_callback) 161 platform_sp.reset(create_callback(true, NULL)); 162 else 163 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name); 164 } 165 else 166 error.SetErrorString ("invalid platform name"); 167 return platform_sp; 168} 169 170 171PlatformSP 172Platform::Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error) 173{ 174 lldb::PlatformSP platform_sp; 175 if (arch.IsValid()) 176 { 177 uint32_t idx; 178 PlatformCreateInstance create_callback; 179 // First try exact arch matches across all platform plug-ins 180 bool exact = true; 181 for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) 182 { 183 if (create_callback) 184 { 185 platform_sp.reset(create_callback(false, &arch)); 186 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr)) 187 return platform_sp; 188 } 189 } 190 // Next try compatible arch matches across all platform plug-ins 191 exact = false; 192 for (idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex (idx)); ++idx) 193 { 194 if (create_callback) 195 { 196 platform_sp.reset(create_callback(false, &arch)); 197 if (platform_sp && platform_sp->IsCompatibleArchitecture(arch, exact, platform_arch_ptr)) 198 return platform_sp; 199 } 200 } 201 } 202 else 203 error.SetErrorString ("invalid platform name"); 204 if (platform_arch_ptr) 205 platform_arch_ptr->Clear(); 206 platform_sp.reset(); 207 return platform_sp; 208} 209 210uint32_t 211Platform::GetNumConnectedRemotePlatforms () 212{ 213 Mutex::Locker locker (GetConnectedPlatformListMutex ()); 214 return GetConnectedPlatformList().size(); 215} 216 217PlatformSP 218Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx) 219{ 220 PlatformSP platform_sp; 221 { 222 Mutex::Locker locker (GetConnectedPlatformListMutex ()); 223 if (idx < GetConnectedPlatformList().size()) 224 platform_sp = GetConnectedPlatformList ()[idx]; 225 } 226 return platform_sp; 227} 228 229//------------------------------------------------------------------ 230/// Default Constructor 231//------------------------------------------------------------------ 232Platform::Platform (bool is_host) : 233 m_is_host (is_host), 234 m_os_version_set_while_connected (false), 235 m_system_arch_set_while_connected (false), 236 m_sdk_sysroot (), 237 m_sdk_build (), 238 m_remote_url (), 239 m_name (), 240 m_major_os_version (UINT32_MAX), 241 m_minor_os_version (UINT32_MAX), 242 m_update_os_version (UINT32_MAX), 243 m_system_arch(), 244 m_uid_map_mutex (Mutex::eMutexTypeNormal), 245 m_gid_map_mutex (Mutex::eMutexTypeNormal), 246 m_uid_map(), 247 m_gid_map(), 248 m_max_uid_name_len (0), 249 m_max_gid_name_len (0) 250{ 251 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 252 if (log) 253 log->Printf ("%p Platform::Platform()", this); 254} 255 256//------------------------------------------------------------------ 257/// Destructor. 258/// 259/// The destructor is virtual since this class is designed to be 260/// inherited from by the plug-in instance. 261//------------------------------------------------------------------ 262Platform::~Platform() 263{ 264 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 265 if (log) 266 log->Printf ("%p Platform::~Platform()", this); 267} 268 269void 270Platform::GetStatus (Stream &strm) 271{ 272 uint32_t major = UINT32_MAX; 273 uint32_t minor = UINT32_MAX; 274 uint32_t update = UINT32_MAX; 275 std::string s; 276 strm.Printf (" Platform: %s\n", GetShortPluginName()); 277 278 ArchSpec arch (GetSystemArchitecture()); 279 if (arch.IsValid()) 280 { 281 if (!arch.GetTriple().str().empty()) 282 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str()); 283 } 284 285 if (GetOSVersion(major, minor, update)) 286 { 287 strm.Printf("OS Version: %u", major); 288 if (minor != UINT32_MAX) 289 strm.Printf(".%u", minor); 290 if (update != UINT32_MAX) 291 strm.Printf(".%u", update); 292 293 if (GetOSBuildString (s)) 294 strm.Printf(" (%s)", s.c_str()); 295 296 strm.EOL(); 297 } 298 299 if (GetOSKernelDescription (s)) 300 strm.Printf(" Kernel: %s\n", s.c_str()); 301 302 if (IsHost()) 303 { 304 strm.Printf(" Hostname: %s\n", GetHostname()); 305 } 306 else 307 { 308 const bool is_connected = IsConnected(); 309 if (is_connected) 310 strm.Printf(" Hostname: %s\n", GetHostname()); 311 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); 312 } 313} 314 315 316bool 317Platform::GetOSVersion (uint32_t &major, 318 uint32_t &minor, 319 uint32_t &update) 320{ 321 bool success = m_major_os_version != UINT32_MAX; 322 if (IsHost()) 323 { 324 if (!success) 325 { 326 // We have a local host platform 327 success = Host::GetOSVersion (m_major_os_version, 328 m_minor_os_version, 329 m_update_os_version); 330 m_os_version_set_while_connected = success; 331 } 332 } 333 else 334 { 335 // We have a remote platform. We can only fetch the remote 336 // OS version if we are connected, and we don't want to do it 337 // more than once. 338 339 const bool is_connected = IsConnected(); 340 341 bool fetch = false; 342 if (success) 343 { 344 // We have valid OS version info, check to make sure it wasn't 345 // manually set prior to connecting. If it was manually set prior 346 // to connecting, then lets fetch the actual OS version info 347 // if we are now connected. 348 if (is_connected && !m_os_version_set_while_connected) 349 fetch = true; 350 } 351 else 352 { 353 // We don't have valid OS version info, fetch it if we are connected 354 fetch = is_connected; 355 } 356 357 if (fetch) 358 { 359 success = GetRemoteOSVersion (); 360 m_os_version_set_while_connected = success; 361 } 362 } 363 364 if (success) 365 { 366 major = m_major_os_version; 367 minor = m_minor_os_version; 368 update = m_update_os_version; 369 } 370 return success; 371} 372 373bool 374Platform::GetOSBuildString (std::string &s) 375{ 376 if (IsHost()) 377 return Host::GetOSBuildString (s); 378 else 379 return GetRemoteOSBuildString (s); 380} 381 382bool 383Platform::GetOSKernelDescription (std::string &s) 384{ 385 if (IsHost()) 386 return Host::GetOSKernelDescription (s); 387 else 388 return GetRemoteOSKernelDescription (s); 389} 390 391const char * 392Platform::GetName () 393{ 394 const char *name = GetHostname(); 395 if (name == NULL || name[0] == '\0') 396 name = GetShortPluginName(); 397 return name; 398} 399 400const char * 401Platform::GetHostname () 402{ 403 if (IsHost()) 404 return "localhost"; 405 406 if (m_name.empty()) 407 return NULL; 408 return m_name.c_str(); 409} 410 411const char * 412Platform::GetUserName (uint32_t uid) 413{ 414 const char *user_name = GetCachedUserName(uid); 415 if (user_name) 416 return user_name; 417 if (IsHost()) 418 { 419 std::string name; 420 if (Host::GetUserName(uid, name)) 421 return SetCachedUserName (uid, name.c_str(), name.size()); 422 } 423 return NULL; 424} 425 426const char * 427Platform::GetGroupName (uint32_t gid) 428{ 429 const char *group_name = GetCachedGroupName(gid); 430 if (group_name) 431 return group_name; 432 if (IsHost()) 433 { 434 std::string name; 435 if (Host::GetGroupName(gid, name)) 436 return SetCachedGroupName (gid, name.c_str(), name.size()); 437 } 438 return NULL; 439} 440 441bool 442Platform::SetOSVersion (uint32_t major, 443 uint32_t minor, 444 uint32_t update) 445{ 446 if (IsHost()) 447 { 448 // We don't need anyone setting the OS version for the host platform, 449 // we should be able to figure it out by calling Host::GetOSVersion(...). 450 return false; 451 } 452 else 453 { 454 // We have a remote platform, allow setting the target OS version if 455 // we aren't connected, since if we are connected, we should be able to 456 // request the remote OS version from the connected platform. 457 if (IsConnected()) 458 return false; 459 else 460 { 461 // We aren't connected and we might want to set the OS version 462 // ahead of time before we connect so we can peruse files and 463 // use a local SDK or PDK cache of support files to disassemble 464 // or do other things. 465 m_major_os_version = major; 466 m_minor_os_version = minor; 467 m_update_os_version = update; 468 return true; 469 } 470 } 471 return false; 472} 473 474 475Error 476Platform::ResolveExecutable (const FileSpec &exe_file, 477 const ArchSpec &exe_arch, 478 lldb::ModuleSP &exe_module_sp, 479 const FileSpecList *module_search_paths_ptr) 480{ 481 Error error; 482 if (exe_file.Exists()) 483 { 484 ModuleSpec module_spec (exe_file, exe_arch); 485 if (module_spec.GetArchitecture().IsValid()) 486 { 487 error = ModuleList::GetSharedModule (module_spec, 488 exe_module_sp, 489 module_search_paths_ptr, 490 NULL, 491 NULL); 492 } 493 else 494 { 495 // No valid architecture was specified, ask the platform for 496 // the architectures that we should be using (in the correct order) 497 // and see if we can find a match that way 498 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) 499 { 500 error = ModuleList::GetSharedModule (module_spec, 501 exe_module_sp, 502 module_search_paths_ptr, 503 NULL, 504 NULL); 505 // Did we find an executable using one of the 506 if (error.Success() && exe_module_sp) 507 break; 508 } 509 } 510 } 511 else 512 { 513 error.SetErrorStringWithFormat ("'%s%s%s' does not exist", 514 exe_file.GetDirectory().AsCString(""), 515 exe_file.GetDirectory() ? "/" : "", 516 exe_file.GetFilename().AsCString("")); 517 } 518 return error; 519} 520 521Error 522Platform::ResolveSymbolFile (Target &target, 523 const ModuleSpec &sym_spec, 524 FileSpec &sym_file) 525{ 526 Error error; 527 if (sym_spec.GetSymbolFileSpec().Exists()) 528 sym_file = sym_spec.GetSymbolFileSpec(); 529 else 530 error.SetErrorString("unable to resolve symbol file"); 531 return error; 532 533} 534 535 536 537bool 538Platform::ResolveRemotePath (const FileSpec &platform_path, 539 FileSpec &resolved_platform_path) 540{ 541 resolved_platform_path = platform_path; 542 return resolved_platform_path.ResolvePath(); 543} 544 545 546const ArchSpec & 547Platform::GetSystemArchitecture() 548{ 549 if (IsHost()) 550 { 551 if (!m_system_arch.IsValid()) 552 { 553 // We have a local host platform 554 m_system_arch = Host::GetArchitecture(); 555 m_system_arch_set_while_connected = m_system_arch.IsValid(); 556 } 557 } 558 else 559 { 560 // We have a remote platform. We can only fetch the remote 561 // system architecture if we are connected, and we don't want to do it 562 // more than once. 563 564 const bool is_connected = IsConnected(); 565 566 bool fetch = false; 567 if (m_system_arch.IsValid()) 568 { 569 // We have valid OS version info, check to make sure it wasn't 570 // manually set prior to connecting. If it was manually set prior 571 // to connecting, then lets fetch the actual OS version info 572 // if we are now connected. 573 if (is_connected && !m_system_arch_set_while_connected) 574 fetch = true; 575 } 576 else 577 { 578 // We don't have valid OS version info, fetch it if we are connected 579 fetch = is_connected; 580 } 581 582 if (fetch) 583 { 584 m_system_arch = GetRemoteSystemArchitecture (); 585 m_system_arch_set_while_connected = m_system_arch.IsValid(); 586 } 587 } 588 return m_system_arch; 589} 590 591 592Error 593Platform::ConnectRemote (Args& args) 594{ 595 Error error; 596 if (IsHost()) 597 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName()); 598 else 599 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName()); 600 return error; 601} 602 603Error 604Platform::DisconnectRemote () 605{ 606 Error error; 607 if (IsHost()) 608 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName()); 609 else 610 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName()); 611 return error; 612} 613 614bool 615Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 616{ 617 // Take care of the host case so that each subclass can just 618 // call this function to get the host functionality. 619 if (IsHost()) 620 return Host::GetProcessInfo (pid, process_info); 621 return false; 622} 623 624uint32_t 625Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info, 626 ProcessInstanceInfoList &process_infos) 627{ 628 // Take care of the host case so that each subclass can just 629 // call this function to get the host functionality. 630 uint32_t match_count = 0; 631 if (IsHost()) 632 match_count = Host::FindProcesses (match_info, process_infos); 633 return match_count; 634} 635 636 637Error 638Platform::LaunchProcess (ProcessLaunchInfo &launch_info) 639{ 640 Error error; 641 // Take care of the host case so that each subclass can just 642 // call this function to get the host functionality. 643 if (IsHost()) 644 { 645 if (::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY")) 646 launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY); 647 648 if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) 649 { 650 const bool is_localhost = true; 651 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug); 652 const bool first_arg_is_full_shell_command = false; 653 if (!launch_info.ConvertArgumentsForLaunchingInShell (error, 654 is_localhost, 655 will_debug, 656 first_arg_is_full_shell_command)) 657 return error; 658 } 659 660 error = Host::LaunchProcess (launch_info); 661 } 662 else 663 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes"); 664 return error; 665} 666 667lldb::ProcessSP 668Platform::DebugProcess (ProcessLaunchInfo &launch_info, 669 Debugger &debugger, 670 Target *target, // Can be NULL, if NULL create a new target, else use existing one 671 Listener &listener, 672 Error &error) 673{ 674 ProcessSP process_sp; 675 // Make sure we stop at the entry point 676 launch_info.GetFlags ().Set (eLaunchFlagDebug); 677 // We always launch the process we are going to debug in a separate process 678 // group, since then we can handle ^C interrupts ourselves w/o having to worry 679 // about the target getting them as well. 680 launch_info.SetLaunchInSeparateProcessGroup(true); 681 682 error = LaunchProcess (launch_info); 683 if (error.Success()) 684 { 685 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) 686 { 687 ProcessAttachInfo attach_info (launch_info); 688 process_sp = Attach (attach_info, debugger, target, listener, error); 689 if (process_sp) 690 { 691 // Since we attached to the process, it will think it needs to detach 692 // if the process object just goes away without an explicit call to 693 // Process::Kill() or Process::Detach(), so let it know to kill the 694 // process if this happens. 695 process_sp->SetShouldDetach (false); 696 697 // If we didn't have any file actions, the pseudo terminal might 698 // have been used where the slave side was given as the file to 699 // open for stdin/out/err after we have already opened the master 700 // so we can read/write stdin/out/err. 701 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 702 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) 703 { 704 process_sp->SetSTDIOFileDescriptor(pty_fd); 705 } 706 } 707 } 708 } 709 return process_sp; 710} 711 712 713lldb::PlatformSP 714Platform::GetPlatformForArchitecture (const ArchSpec &arch, ArchSpec *platform_arch_ptr) 715{ 716 lldb::PlatformSP platform_sp; 717 Error error; 718 if (arch.IsValid()) 719 platform_sp = Platform::Create (arch, platform_arch_ptr, error); 720 return platform_sp; 721} 722 723 724//------------------------------------------------------------------ 725/// Lets a platform answer if it is compatible with a given 726/// architecture and the target triple contained within. 727//------------------------------------------------------------------ 728bool 729Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match, ArchSpec *compatible_arch_ptr) 730{ 731 // If the architecture is invalid, we must answer true... 732 if (arch.IsValid()) 733 { 734 ArchSpec platform_arch; 735 // Try for an exact architecture match first. 736 if (exact_arch_match) 737 { 738 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 739 { 740 if (arch.IsExactMatch(platform_arch)) 741 { 742 if (compatible_arch_ptr) 743 *compatible_arch_ptr = platform_arch; 744 return true; 745 } 746 } 747 } 748 else 749 { 750 for (uint32_t arch_idx=0; GetSupportedArchitectureAtIndex (arch_idx, platform_arch); ++arch_idx) 751 { 752 if (arch.IsCompatibleMatch(platform_arch)) 753 { 754 if (compatible_arch_ptr) 755 *compatible_arch_ptr = platform_arch; 756 return true; 757 } 758 } 759 } 760 } 761 if (compatible_arch_ptr) 762 compatible_arch_ptr->Clear(); 763 return false; 764 765} 766 767 768lldb::BreakpointSP 769Platform::SetThreadCreationBreakpoint (lldb_private::Target &target) 770{ 771 return lldb::BreakpointSP(); 772} 773 774size_t 775Platform::GetEnvironment (StringList &environment) 776{ 777 environment.Clear(); 778 return false; 779} 780 781