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 455 const ArchSpec & 456 Platform::GetSystemArchitecture() 457 { 458 if (IsHost()) 459 { 460 if (!m_system_arch.IsValid()) 461 { 462 // We have a local host platform 463 m_system_arch = Host::GetArchitecture(); 464 m_system_arch_set_while_connected = m_system_arch.IsValid(); 465 } 466 } 467 else 468 { 469 // We have a remote platform. We can only fetch the remote 470 // system architecture if we are connected, and we don't want to do it 471 // more than once. 472 473 const bool is_connected = IsConnected(); 474 475 bool fetch = false; 476 if (m_system_arch.IsValid()) 477 { 478 // We have valid OS version info, check to make sure it wasn't 479 // manually set prior to connecting. If it was manually set prior 480 // to connecting, then lets fetch the actual OS version info 481 // if we are now connected. 482 if (is_connected && !m_system_arch_set_while_connected) 483 fetch = true; 484 } 485 else 486 { 487 // We don't have valid OS version info, fetch it if we are connected 488 fetch = is_connected; 489 } 490 491 if (fetch) 492 { 493 m_system_arch = GetRemoteSystemArchitecture (); 494 m_system_arch_set_while_connected = m_system_arch.IsValid(); 495 } 496 } 497 return m_system_arch; 498 } 499 500 501 Error 502 Platform::ConnectRemote (Args& args) 503 { 504 Error error; 505 if (IsHost()) 506 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName()); 507 else 508 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName()); 509 return error; 510 } 511 512 Error 513 Platform::DisconnectRemote () 514 { 515 Error error; 516 if (IsHost()) 517 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName()); 518 else 519 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName()); 520 return error; 521 } 522 523 bool 524 Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 525 { 526 // Take care of the host case so that each subclass can just 527 // call this function to get the host functionality. 528 if (IsHost()) 529 return Host::GetProcessInfo (pid, process_info); 530 return false; 531 } 532 533 uint32_t 534 Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info, 535 ProcessInstanceInfoList &process_infos) 536 { 537 // Take care of the host case so that each subclass can just 538 // call this function to get the host functionality. 539 uint32_t match_count = 0; 540 if (IsHost()) 541 match_count = Host::FindProcesses (match_info, process_infos); 542 return match_count; 543 } 544 545 546 Error 547 Platform::LaunchProcess (ProcessLaunchInfo &launch_info) 548 { 549 Error error; 550 // Take care of the host case so that each subclass can just 551 // call this function to get the host functionality. 552 if (IsHost()) 553 error = Host::LaunchProcess (launch_info); 554 else 555 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes"); 556 return error; 557 } 558 559 lldb::ProcessSP 560 Platform::DebugProcess (ProcessLaunchInfo &launch_info, 561 Debugger &debugger, 562 Target *target, // Can be NULL, if NULL create a new target, else use existing one 563 Listener &listener, 564 Error &error) 565 { 566 ProcessSP process_sp; 567 // Make sure we stop at the entry point 568 launch_info.GetFlags ().Set (eLaunchFlagDebug); 569 error = LaunchProcess (launch_info); 570 if (error.Success()) 571 { 572 lldb::pid_t pid = launch_info.GetProcessID(); 573 if (pid != LLDB_INVALID_PROCESS_ID) 574 { 575 process_sp = Attach (pid, debugger, target, listener, error); 576 577 // if (process_sp) 578 // { 579 // if (launch_info.GetFlags().IsClear (eLaunchFlagStopAtEntry)) 580 // process_sp->Resume(); 581 // } 582 } 583 } 584 return process_sp; 585 } 586 587