Platform.cpp revision f2bf870da5819415d52bc7da98c151cedf1e6dff
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_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//------------------------------------------------------------------ 190Platform::~Platform() 191{ 192 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 193 if (log) 194 log->Printf ("%p Platform::~Platform()", this); 195} 196 197void 198Platform::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 244bool 245Platform::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 301bool 302Platform::GetOSBuildString (std::string &s) 303{ 304 if (IsHost()) 305 return Host::GetOSBuildString (s); 306 else 307 return GetRemoteOSBuildString (s); 308} 309 310bool 311Platform::GetOSKernelDescription (std::string &s) 312{ 313 if (IsHost()) 314 return Host::GetOSKernelDescription (s); 315 else 316 return GetRemoteOSKernelDescription (s); 317} 318 319const char * 320Platform::GetName () 321{ 322 const char *name = GetHostname(); 323 if (name == NULL || name[0] == '\0') 324 name = GetShortPluginName(); 325 return name; 326} 327 328const char * 329Platform::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 339const char * 340Platform::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 354const char * 355Platform::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 369bool 370Platform::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 403Error 404Platform::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 454bool 455Platform::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 463const ArchSpec & 464Platform::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 509Error 510Platform::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 520Error 521Platform::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 531bool 532Platform::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 541uint32_t 542Platform::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 554Error 555Platform::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 567lldb::ProcessSP 568Platform::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