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