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