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