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