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