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