Platform.cpp revision cb8977d726be451df9978a74088435667fa37da2
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/PluginManager.h" 18#include "lldb/Host/FileSpec.h" 19#include "lldb/Host/Host.h" 20#include "lldb/Target/Target.h" 21 22using namespace lldb; 23using namespace lldb_private; 24 25// Use a singleton function for g_local_platform_sp to avoid init 26// constructors since LLDB is often part of a shared library 27static PlatformSP& 28GetDefaultPlatformSP () 29{ 30 static PlatformSP g_default_platform_sp; 31 return g_default_platform_sp; 32} 33 34static Mutex & 35GetConnectedPlatformListMutex () 36{ 37 static Mutex g_remote_connected_platforms_mutex (Mutex::eMutexTypeRecursive); 38 return g_remote_connected_platforms_mutex; 39} 40static std::vector<PlatformSP> & 41GetConnectedPlatformList () 42{ 43 static std::vector<PlatformSP> g_remote_connected_platforms; 44 return g_remote_connected_platforms; 45} 46 47//------------------------------------------------------------------ 48/// Get the native host platform plug-in. 49/// 50/// There should only be one of these for each host that LLDB runs 51/// upon that should be statically compiled in and registered using 52/// preprocessor macros or other similar build mechanisms. 53/// 54/// This platform will be used as the default platform when launching 55/// or attaching to processes unless another platform is specified. 56//------------------------------------------------------------------ 57PlatformSP 58Platform::GetDefaultPlatform () 59{ 60 return GetDefaultPlatformSP (); 61} 62 63void 64Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp) 65{ 66 // The native platform should use its static void Platform::Initialize() 67 // function to register itself as the native platform. 68 GetDefaultPlatformSP () = platform_sp; 69} 70 71Error 72Platform::GetFile (const FileSpec &platform_file, 73 const UUID *uuid_ptr, 74 FileSpec &local_file) 75{ 76 // Default to the local case 77 local_file = platform_file; 78 return Error(); 79} 80 81 82PlatformSP 83Platform::Create (const char *platform_name, Error &error) 84{ 85 PlatformCreateInstance create_callback = NULL; 86 lldb::PlatformSP platform_sp; 87 if (platform_name && platform_name[0]) 88 { 89 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (platform_name); 90 if (create_callback) 91 platform_sp.reset(create_callback()); 92 else 93 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name); 94 } 95 else 96 error.SetErrorString ("invalid platform name"); 97 return platform_sp; 98} 99 100uint32_t 101Platform::GetNumConnectedRemotePlatforms () 102{ 103 Mutex::Locker locker (GetConnectedPlatformListMutex ()); 104 return GetConnectedPlatformList().size(); 105} 106 107PlatformSP 108Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx) 109{ 110 PlatformSP platform_sp; 111 { 112 Mutex::Locker locker (GetConnectedPlatformListMutex ()); 113 if (idx < GetConnectedPlatformList().size()) 114 platform_sp = GetConnectedPlatformList ()[idx]; 115 } 116 return platform_sp; 117} 118 119//------------------------------------------------------------------ 120/// Default Constructor 121//------------------------------------------------------------------ 122Platform::Platform (bool is_host) : 123 m_is_host (is_host), 124 m_is_connected (is_host), // If this is the default host platform, then we are always connected 125 m_os_version_set_while_connected (false), 126 m_system_arch_set_while_connected (false), 127 m_remote_url (), 128 m_remote_instance_name (), 129 m_major_os_version (UINT32_MAX), 130 m_minor_os_version (UINT32_MAX), 131 m_update_os_version (UINT32_MAX) 132{ 133} 134 135//------------------------------------------------------------------ 136/// Destructor. 137/// 138/// The destructor is virtual since this class is designed to be 139/// inherited from by the plug-in instance. 140//------------------------------------------------------------------ 141Platform::~Platform() 142{ 143} 144 145 146bool 147Platform::GetOSVersion (uint32_t &major, 148 uint32_t &minor, 149 uint32_t &update) 150{ 151 bool success = m_major_os_version != UINT32_MAX; 152 if (IsHost()) 153 { 154 if (!success) 155 { 156 // We have a local host platform 157 success = Host::GetOSVersion (m_major_os_version, 158 m_minor_os_version, 159 m_update_os_version); 160 m_os_version_set_while_connected = success; 161 } 162 } 163 else 164 { 165 // We have a remote platform. We can only fetch the remote 166 // OS version if we are connected, and we don't want to do it 167 // more than once. 168 169 const bool is_connected = IsConnected(); 170 171 bool fetch_os_version = false; 172 if (success) 173 { 174 // We have valid OS version info, check to make sure it wasn't 175 // manually set prior to connecting. If it was manually set prior 176 // to connecting, then lets fetch the actual OS version info 177 // if we are now connected. 178 if (is_connected && !m_os_version_set_while_connected) 179 fetch_os_version = true; 180 } 181 else 182 { 183 // We don't have valid OS version info, fetch it if we are connected 184 fetch_os_version = is_connected; 185 } 186 187 if (fetch_os_version) 188 { 189 success = FetchRemoteOSVersion (); 190 m_os_version_set_while_connected = success; 191 } 192 } 193 194 if (success) 195 { 196 major = m_major_os_version; 197 minor = m_minor_os_version; 198 update = m_update_os_version; 199 } 200 return success; 201} 202 203bool 204Platform::SetOSVersion (uint32_t major, 205 uint32_t minor, 206 uint32_t update) 207{ 208 if (IsHost()) 209 { 210 // We don't need anyone setting the OS version for the host platform, 211 // we should be able to figure it out by calling Host::GetOSVersion(...). 212 return false; 213 } 214 else 215 { 216 // We have a remote platform, allow setting the target OS version if 217 // we aren't connected, since if we are connected, we should be able to 218 // request the remote OS version from the connected platform. 219 if (IsConnected()) 220 return false; 221 else 222 { 223 // We aren't connected and we might want to set the OS version 224 // ahead of time before we connect so we can peruse files and 225 // use a local SDK or PDK cache of support files to disassemble 226 // or do other things. 227 m_major_os_version = major; 228 m_minor_os_version = minor; 229 m_update_os_version = update; 230 return true; 231 } 232 } 233 return false; 234} 235 236 237Error 238Platform::ResolveExecutable (const FileSpec &exe_file, 239 const ArchSpec &exe_arch, 240 lldb::ModuleSP &exe_module_sp) 241{ 242 Error error; 243 if (exe_file.Exists()) 244 { 245 if (exe_arch.IsValid()) 246 { 247 error = ModuleList::GetSharedModule (exe_file, 248 exe_arch, 249 NULL, 250 NULL, 251 0, 252 exe_module_sp, 253 NULL, 254 NULL); 255 } 256 else 257 { 258 // No valid architecture was specified, ask the platform for 259 // the architectures that we should be using (in the correct order) 260 // and see if we can find a match that way 261 ArchSpec platform_arch; 262 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx) 263 { 264 error = ModuleList::GetSharedModule (exe_file, 265 platform_arch, 266 NULL, 267 NULL, 268 0, 269 exe_module_sp, 270 NULL, 271 NULL); 272 // Did we find an executable using one of the 273 if (error.Success() && exe_module_sp) 274 break; 275 } 276 } 277 } 278 else 279 { 280 error.SetErrorStringWithFormat ("'%s%s%s' does not exist", 281 exe_file.GetDirectory().AsCString(""), 282 exe_file.GetDirectory() ? "/" : "", 283 exe_file.GetFilename().AsCString("")); 284 } 285 return error; 286} 287 288 289const ArchSpec & 290Platform::GetSystemArchitecture() 291{ 292 if (IsHost()) 293 { 294 if (!m_system_arch.IsValid()) 295 { 296 // We have a local host platform 297 m_system_arch = Host::GetArchitecture(); 298 m_system_arch_set_while_connected = m_system_arch.IsValid(); 299 } 300 } 301 else 302 { 303 // We have a remote platform. We can only fetch the remote 304 // system architecture if we are connected, and we don't want to do it 305 // more than once. 306 307 const bool is_connected = IsConnected(); 308 309 bool fetch = false; 310 if (m_system_arch.IsValid()) 311 { 312 // We have valid OS version info, check to make sure it wasn't 313 // manually set prior to connecting. If it was manually set prior 314 // to connecting, then lets fetch the actual OS version info 315 // if we are now connected. 316 if (is_connected && !m_system_arch_set_while_connected) 317 fetch = true; 318 } 319 else 320 { 321 // We don't have valid OS version info, fetch it if we are connected 322 fetch = is_connected; 323 } 324 325 if (fetch) 326 { 327 m_system_arch = FetchRemoteSystemArchitecture (); 328 m_system_arch_set_while_connected = m_system_arch.IsValid(); 329 } 330 } 331 return m_system_arch; 332} 333 334 335Error 336Platform::ConnectRemote (Args& args) 337{ 338 Error error; 339 if (IsHost()) 340 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName()); 341 else 342 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName()); 343 return error; 344} 345 346Error 347Platform::DisconnectRemote () 348{ 349 Error error; 350 if (IsHost()) 351 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName()); 352 else 353 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName()); 354 return error; 355} 356