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