blob: 0f025147608e422d6dc368b3f57dd8ddb6c0d5cf [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),
Greg Claytonb1888f22011-03-19 01:12:21 +0000124 m_os_version_set_while_connected (false),
125 m_system_arch_set_while_connected (false),
126 m_remote_url (),
Greg Clayton58e26e02011-03-24 04:28:38 +0000127 m_name (),
Greg Claytonb1888f22011-03-19 01:12:21 +0000128 m_major_os_version (UINT32_MAX),
129 m_minor_os_version (UINT32_MAX),
130 m_update_os_version (UINT32_MAX)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000131{
132}
133
134//------------------------------------------------------------------
135/// Destructor.
136///
137/// The destructor is virtual since this class is designed to be
138/// inherited from by the plug-in instance.
139//------------------------------------------------------------------
140Platform::~Platform()
141{
142}
143
Greg Clayton58e26e02011-03-24 04:28:38 +0000144void
145Platform::GetStatus (Stream &strm)
146{
147 uint32_t major = UINT32_MAX;
148 uint32_t minor = UINT32_MAX;
149 uint32_t update = UINT32_MAX;
150 std::string s;
151 strm.Printf ("Platform: %s\n", GetShortPluginName());
152
153 ArchSpec arch (GetSystemArchitecture());
154 if (arch.IsValid())
155 {
156 if (!arch.GetTriple().str().empty())
157 strm.Printf("Triple: %s\n", arch.GetTriple().str().c_str());
158 }
159
160 if (GetOSVersion(major, minor, update))
161 {
162 strm.Printf("OS: %u", major);
163 if (minor != UINT32_MAX)
164 strm.Printf(".%u", minor);
165 if (update != UINT32_MAX)
166 strm.Printf(".%u", update);
167
168 if (GetOSBuildString (s))
169 strm.Printf(" (%s)", s.c_str());
170
171 strm.EOL();
172 }
173
174 if (GetOSKernelDescription (s))
175 strm.Printf("Kernel: %s\n", s.c_str());
176
177 if (IsHost())
178 {
179 strm.Printf("Hostname: %s\n", GetHostname());
180 }
181 else
182 {
183 if (IsConnected())
184 strm.Printf("Remote hostname: %s\n", GetHostname());
185 else
186 strm.PutCString("Not connected to a remote platform.\n");
187 }
188}
189
Greg Claytonb1888f22011-03-19 01:12:21 +0000190
191bool
192Platform::GetOSVersion (uint32_t &major,
193 uint32_t &minor,
194 uint32_t &update)
195{
196 bool success = m_major_os_version != UINT32_MAX;
197 if (IsHost())
198 {
199 if (!success)
200 {
201 // We have a local host platform
202 success = Host::GetOSVersion (m_major_os_version,
203 m_minor_os_version,
204 m_update_os_version);
205 m_os_version_set_while_connected = success;
206 }
207 }
208 else
209 {
210 // We have a remote platform. We can only fetch the remote
211 // OS version if we are connected, and we don't want to do it
212 // more than once.
213
214 const bool is_connected = IsConnected();
215
Greg Clayton58e26e02011-03-24 04:28:38 +0000216 bool fetch = false;
Greg Claytonb1888f22011-03-19 01:12:21 +0000217 if (success)
218 {
219 // We have valid OS version info, check to make sure it wasn't
220 // manually set prior to connecting. If it was manually set prior
221 // to connecting, then lets fetch the actual OS version info
222 // if we are now connected.
223 if (is_connected && !m_os_version_set_while_connected)
Greg Clayton58e26e02011-03-24 04:28:38 +0000224 fetch = true;
Greg Claytonb1888f22011-03-19 01:12:21 +0000225 }
226 else
227 {
228 // We don't have valid OS version info, fetch it if we are connected
Greg Clayton58e26e02011-03-24 04:28:38 +0000229 fetch = is_connected;
Greg Claytonb1888f22011-03-19 01:12:21 +0000230 }
231
Greg Clayton58e26e02011-03-24 04:28:38 +0000232 if (fetch)
Greg Claytonb1888f22011-03-19 01:12:21 +0000233 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000234 success = GetRemoteOSVersion ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000235 m_os_version_set_while_connected = success;
236 }
237 }
238
239 if (success)
240 {
241 major = m_major_os_version;
242 minor = m_minor_os_version;
243 update = m_update_os_version;
244 }
245 return success;
246}
Greg Clayton58e26e02011-03-24 04:28:38 +0000247
248bool
249Platform::GetOSBuildString (std::string &s)
250{
251 if (IsHost())
252 return Host::GetOSBuildString (s);
253 else
254 return GetRemoteOSBuildString (s);
255}
256
257bool
258Platform::GetOSKernelDescription (std::string &s)
259{
260 if (IsHost())
261 return Host::GetOSKernelDescription (s);
262 else
263 return GetRemoteOSKernelDescription (s);
264}
265
266const char *
267Platform::GetHostname ()
268{
269 if (m_name.empty())
270 {
271 if (IsHost())
272 {
273 if (!Host::GetHostname(m_name))
274 return "localhost";
275 }
276 else
277 {
278 if (IsConnected())
279 {
280 const char *instance_name = GetRemoteHostname ();
281 if (instance_name)
282 m_name.assign (instance_name);
283 }
284 else
285 {
286 return "remote";
287 }
288 }
289 }
290 if (!m_name.empty())
291 return m_name.c_str();
292 return NULL;
293}
294
295
296
Greg Claytonb1888f22011-03-19 01:12:21 +0000297bool
298Platform::SetOSVersion (uint32_t major,
299 uint32_t minor,
300 uint32_t update)
301{
302 if (IsHost())
303 {
304 // We don't need anyone setting the OS version for the host platform,
305 // we should be able to figure it out by calling Host::GetOSVersion(...).
306 return false;
307 }
308 else
309 {
310 // We have a remote platform, allow setting the target OS version if
311 // we aren't connected, since if we are connected, we should be able to
312 // request the remote OS version from the connected platform.
313 if (IsConnected())
314 return false;
315 else
316 {
317 // We aren't connected and we might want to set the OS version
318 // ahead of time before we connect so we can peruse files and
319 // use a local SDK or PDK cache of support files to disassemble
320 // or do other things.
321 m_major_os_version = major;
322 m_minor_os_version = minor;
323 m_update_os_version = update;
324 return true;
325 }
326 }
327 return false;
328}
329
330
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000331Error
332Platform::ResolveExecutable (const FileSpec &exe_file,
333 const ArchSpec &exe_arch,
334 lldb::ModuleSP &exe_module_sp)
335{
336 Error error;
337 if (exe_file.Exists())
338 {
339 if (exe_arch.IsValid())
340 {
341 error = ModuleList::GetSharedModule (exe_file,
342 exe_arch,
343 NULL,
344 NULL,
345 0,
346 exe_module_sp,
347 NULL,
348 NULL);
349 }
350 else
351 {
352 // No valid architecture was specified, ask the platform for
353 // the architectures that we should be using (in the correct order)
354 // and see if we can find a match that way
355 ArchSpec platform_arch;
356 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
357 {
358 error = ModuleList::GetSharedModule (exe_file,
359 platform_arch,
360 NULL,
361 NULL,
362 0,
363 exe_module_sp,
364 NULL,
365 NULL);
366 // Did we find an executable using one of the
367 if (error.Success() && exe_module_sp)
368 break;
369 }
370 }
371 }
372 else
373 {
374 error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
375 exe_file.GetDirectory().AsCString(""),
376 exe_file.GetDirectory() ? "/" : "",
377 exe_file.GetFilename().AsCString(""));
378 }
379 return error;
380}
381
Greg Claytonb1888f22011-03-19 01:12:21 +0000382
383const ArchSpec &
384Platform::GetSystemArchitecture()
385{
386 if (IsHost())
387 {
388 if (!m_system_arch.IsValid())
389 {
390 // We have a local host platform
391 m_system_arch = Host::GetArchitecture();
392 m_system_arch_set_while_connected = m_system_arch.IsValid();
393 }
394 }
395 else
396 {
397 // We have a remote platform. We can only fetch the remote
398 // system architecture if we are connected, and we don't want to do it
399 // more than once.
400
401 const bool is_connected = IsConnected();
402
403 bool fetch = false;
404 if (m_system_arch.IsValid())
405 {
406 // We have valid OS version info, check to make sure it wasn't
407 // manually set prior to connecting. If it was manually set prior
408 // to connecting, then lets fetch the actual OS version info
409 // if we are now connected.
410 if (is_connected && !m_system_arch_set_while_connected)
411 fetch = true;
412 }
413 else
414 {
415 // We don't have valid OS version info, fetch it if we are connected
416 fetch = is_connected;
417 }
418
419 if (fetch)
420 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000421 m_system_arch = GetRemoteSystemArchitecture ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000422 m_system_arch_set_while_connected = m_system_arch.IsValid();
423 }
424 }
425 return m_system_arch;
426}
427
428
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000429Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000430Platform::ConnectRemote (Args& args)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000431{
432 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000433 if (IsHost())
434 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
435 else
436 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000437 return error;
438}
439
440Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000441Platform::DisconnectRemote ()
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000442{
443 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000444 if (IsHost())
445 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
446 else
447 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000448 return error;
449}