blob: a6df50d9e708d0164b97827a0814ba52817e7ab5 [file] [log] [blame]
Greg Claytone4b9c1f2011-03-08 22:40:15 +00001//===-- 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"
Greg Claytonb1888f22011-03-19 01:12:21 +000019#include "lldb/Host/Host.h"
Greg Claytone4b9c1f2011-03-08 22:40:15 +000020#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
Greg Claytone4b9c1f2011-03-08 22:40:15 +000034static 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
Greg Claytone4b9c1f2011-03-08 22:40:15 +000071Error
Greg Claytoncb8977d2011-03-23 00:09:55 +000072Platform::GetFile (const FileSpec &platform_file,
73 const UUID *uuid_ptr,
74 FileSpec &local_file)
Greg Claytone4b9c1f2011-03-08 22:40:15 +000075{
76 // Default to the local case
77 local_file = platform_file;
78 return Error();
79}
80
81
82PlatformSP
Greg Claytonb1888f22011-03-19 01:12:21 +000083Platform::Create (const char *platform_name, Error &error)
Greg Claytone4b9c1f2011-03-08 22:40:15 +000084{
85 PlatformCreateInstance create_callback = NULL;
86 lldb::PlatformSP platform_sp;
Greg Claytonb1888f22011-03-19 01:12:21 +000087 if (platform_name && platform_name[0])
Greg Claytone4b9c1f2011-03-08 22:40:15 +000088 {
89 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (platform_name);
90 if (create_callback)
Greg Claytone4b9c1f2011-03-08 22:40:15 +000091 platform_sp.reset(create_callback());
Greg Claytone4b9c1f2011-03-08 22:40:15 +000092 else
Greg Claytonb1888f22011-03-19 01:12:21 +000093 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
Greg Claytone4b9c1f2011-03-08 22:40:15 +000094 }
95 else
Greg Claytonb1888f22011-03-19 01:12:21 +000096 error.SetErrorString ("invalid platform name");
Greg Claytone4b9c1f2011-03-08 22:40:15 +000097 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//------------------------------------------------------------------
Greg Claytonb1888f22011-03-19 01:12:21 +0000122Platform::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 (),
Greg Claytoncb8977d2011-03-23 00:09:55 +0000128 m_remote_instance_name (),
Greg Claytonb1888f22011-03-19 01:12:21 +0000129 m_major_os_version (UINT32_MAX),
130 m_minor_os_version (UINT32_MAX),
131 m_update_os_version (UINT32_MAX)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000132{
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
Greg Claytonb1888f22011-03-19 01:12:21 +0000145
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
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000237Error
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
Greg Claytonb1888f22011-03-19 01:12:21 +0000288
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
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000335Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000336Platform::ConnectRemote (Args& args)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000337{
338 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000339 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());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000343 return error;
344}
345
346Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000347Platform::DisconnectRemote ()
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000348{
349 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000350 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());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000354 return error;
355}