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