blob: cddd37ff6be94716b1ec7dcaa3c68bb9dea5dfc7 [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
Greg Clayton24bc5d92011-03-30 18:16:51 +000081Error
82Platform::GetSharedModule (const FileSpec &platform_file,
83 const ArchSpec &arch,
84 const UUID *uuid_ptr,
85 const ConstString *object_name_ptr,
86 off_t object_offset,
87 ModuleSP &module_sp,
88 ModuleSP *old_module_sp_ptr,
89 bool *did_create_ptr)
90{
91 // Don't do any path remapping for the default implementation
92 // of the platform GetSharedModule function, just call through
93 // to our static ModuleList function. Platform subclasses that
94 // implement remote debugging, might have a developer kits
95 // installed that have cached versions of the files for the
96 // remote target, or might implement a download and cache
97 // locally implementation.
98 const bool always_create = false;
99 return ModuleList::GetSharedModule (platform_file,
100 arch,
101 uuid_ptr,
102 object_name_ptr,
103 object_offset,
104 module_sp,
105 old_module_sp_ptr,
106 did_create_ptr,
107 always_create);
108}
109
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000110
111PlatformSP
Greg Claytonb1888f22011-03-19 01:12:21 +0000112Platform::Create (const char *platform_name, Error &error)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000113{
114 PlatformCreateInstance create_callback = NULL;
115 lldb::PlatformSP platform_sp;
Greg Claytonb1888f22011-03-19 01:12:21 +0000116 if (platform_name && platform_name[0])
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000117 {
118 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (platform_name);
119 if (create_callback)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000120 platform_sp.reset(create_callback());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000121 else
Greg Claytonb1888f22011-03-19 01:12:21 +0000122 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000123 }
124 else
Greg Claytonb1888f22011-03-19 01:12:21 +0000125 error.SetErrorString ("invalid platform name");
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000126 return platform_sp;
127}
128
129uint32_t
130Platform::GetNumConnectedRemotePlatforms ()
131{
132 Mutex::Locker locker (GetConnectedPlatformListMutex ());
133 return GetConnectedPlatformList().size();
134}
135
136PlatformSP
137Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
138{
139 PlatformSP platform_sp;
140 {
141 Mutex::Locker locker (GetConnectedPlatformListMutex ());
142 if (idx < GetConnectedPlatformList().size())
143 platform_sp = GetConnectedPlatformList ()[idx];
144 }
145 return platform_sp;
146}
147
148//------------------------------------------------------------------
149/// Default Constructor
150//------------------------------------------------------------------
Greg Claytonb1888f22011-03-19 01:12:21 +0000151Platform::Platform (bool is_host) :
152 m_is_host (is_host),
Greg Claytonb1888f22011-03-19 01:12:21 +0000153 m_os_version_set_while_connected (false),
154 m_system_arch_set_while_connected (false),
155 m_remote_url (),
Greg Clayton58e26e02011-03-24 04:28:38 +0000156 m_name (),
Greg Claytonb1888f22011-03-19 01:12:21 +0000157 m_major_os_version (UINT32_MAX),
158 m_minor_os_version (UINT32_MAX),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000159 m_update_os_version (UINT32_MAX),
160 m_system_arch(),
161 m_uid_map_mutex (Mutex::eMutexTypeNormal),
162 m_gid_map_mutex (Mutex::eMutexTypeNormal),
163 m_uid_map(),
164 m_gid_map(),
165 m_max_uid_name_len (0),
166 m_max_gid_name_len (0)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000167{
168}
169
170//------------------------------------------------------------------
171/// Destructor.
172///
173/// The destructor is virtual since this class is designed to be
174/// inherited from by the plug-in instance.
175//------------------------------------------------------------------
176Platform::~Platform()
177{
178}
179
Greg Clayton58e26e02011-03-24 04:28:38 +0000180void
181Platform::GetStatus (Stream &strm)
182{
183 uint32_t major = UINT32_MAX;
184 uint32_t minor = UINT32_MAX;
185 uint32_t update = UINT32_MAX;
186 std::string s;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000187 strm.Printf (" Platform: %s\n", GetShortPluginName());
Greg Clayton58e26e02011-03-24 04:28:38 +0000188
189 ArchSpec arch (GetSystemArchitecture());
190 if (arch.IsValid())
191 {
192 if (!arch.GetTriple().str().empty())
Greg Clayton24bc5d92011-03-30 18:16:51 +0000193 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000194 }
195
196 if (GetOSVersion(major, minor, update))
197 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000198 strm.Printf("OS Version: %u", major);
Greg Clayton58e26e02011-03-24 04:28:38 +0000199 if (minor != UINT32_MAX)
200 strm.Printf(".%u", minor);
201 if (update != UINT32_MAX)
202 strm.Printf(".%u", update);
203
204 if (GetOSBuildString (s))
205 strm.Printf(" (%s)", s.c_str());
206
207 strm.EOL();
208 }
209
210 if (GetOSKernelDescription (s))
Greg Clayton24bc5d92011-03-30 18:16:51 +0000211 strm.Printf(" Kernel: %s\n", s.c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000212
213 if (IsHost())
214 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000215 strm.Printf(" Hostname: %s\n", GetHostname());
Greg Clayton58e26e02011-03-24 04:28:38 +0000216 }
217 else
218 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000219 const bool is_connected = IsConnected();
220 if (is_connected)
221 strm.Printf(" Hostname: %s\n", GetHostname());
222 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
Greg Clayton58e26e02011-03-24 04:28:38 +0000223 }
224}
225
Greg Claytonb1888f22011-03-19 01:12:21 +0000226
227bool
228Platform::GetOSVersion (uint32_t &major,
229 uint32_t &minor,
230 uint32_t &update)
231{
232 bool success = m_major_os_version != UINT32_MAX;
233 if (IsHost())
234 {
235 if (!success)
236 {
237 // We have a local host platform
238 success = Host::GetOSVersion (m_major_os_version,
239 m_minor_os_version,
240 m_update_os_version);
241 m_os_version_set_while_connected = success;
242 }
243 }
244 else
245 {
246 // We have a remote platform. We can only fetch the remote
247 // OS version if we are connected, and we don't want to do it
248 // more than once.
249
250 const bool is_connected = IsConnected();
251
Greg Clayton58e26e02011-03-24 04:28:38 +0000252 bool fetch = false;
Greg Claytonb1888f22011-03-19 01:12:21 +0000253 if (success)
254 {
255 // We have valid OS version info, check to make sure it wasn't
256 // manually set prior to connecting. If it was manually set prior
257 // to connecting, then lets fetch the actual OS version info
258 // if we are now connected.
259 if (is_connected && !m_os_version_set_while_connected)
Greg Clayton58e26e02011-03-24 04:28:38 +0000260 fetch = true;
Greg Claytonb1888f22011-03-19 01:12:21 +0000261 }
262 else
263 {
264 // We don't have valid OS version info, fetch it if we are connected
Greg Clayton58e26e02011-03-24 04:28:38 +0000265 fetch = is_connected;
Greg Claytonb1888f22011-03-19 01:12:21 +0000266 }
267
Greg Clayton58e26e02011-03-24 04:28:38 +0000268 if (fetch)
Greg Claytonb1888f22011-03-19 01:12:21 +0000269 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000270 success = GetRemoteOSVersion ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000271 m_os_version_set_while_connected = success;
272 }
273 }
274
275 if (success)
276 {
277 major = m_major_os_version;
278 minor = m_minor_os_version;
279 update = m_update_os_version;
280 }
281 return success;
282}
Greg Clayton58e26e02011-03-24 04:28:38 +0000283
284bool
285Platform::GetOSBuildString (std::string &s)
286{
287 if (IsHost())
288 return Host::GetOSBuildString (s);
289 else
290 return GetRemoteOSBuildString (s);
291}
292
293bool
294Platform::GetOSKernelDescription (std::string &s)
295{
296 if (IsHost())
297 return Host::GetOSKernelDescription (s);
298 else
299 return GetRemoteOSKernelDescription (s);
300}
301
302const char *
303Platform::GetHostname ()
304{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000305 if (IsHost() && m_name.empty())
Greg Clayton58e26e02011-03-24 04:28:38 +0000306 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000307 if (!Host::GetHostname(m_name))
308 return "localhost";
Greg Clayton58e26e02011-03-24 04:28:38 +0000309 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000310
311 if (m_name.empty())
312 return NULL;
313 return m_name.c_str();
314}
315
316const char *
317Platform::GetUserName (uint32_t uid)
318{
319 const char *user_name = GetCachedUserName(uid);
320 if (user_name)
321 return user_name;
322 if (IsHost())
323 {
324 std::string name;
325 if (Host::GetUserName(uid, name))
326 return SetCachedUserName (uid, name.c_str(), name.size());
327 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000328 return NULL;
329}
330
Greg Clayton24bc5d92011-03-30 18:16:51 +0000331const char *
332Platform::GetGroupName (uint32_t gid)
333{
334 const char *group_name = GetCachedGroupName(gid);
335 if (group_name)
336 return group_name;
337 if (IsHost())
338 {
339 std::string name;
340 if (Host::GetGroupName(gid, name))
341 return SetCachedGroupName (gid, name.c_str(), name.size());
342 }
343 return NULL;
344}
Greg Clayton58e26e02011-03-24 04:28:38 +0000345
Greg Claytonb1888f22011-03-19 01:12:21 +0000346bool
347Platform::SetOSVersion (uint32_t major,
348 uint32_t minor,
349 uint32_t update)
350{
351 if (IsHost())
352 {
353 // We don't need anyone setting the OS version for the host platform,
354 // we should be able to figure it out by calling Host::GetOSVersion(...).
355 return false;
356 }
357 else
358 {
359 // We have a remote platform, allow setting the target OS version if
360 // we aren't connected, since if we are connected, we should be able to
361 // request the remote OS version from the connected platform.
362 if (IsConnected())
363 return false;
364 else
365 {
366 // We aren't connected and we might want to set the OS version
367 // ahead of time before we connect so we can peruse files and
368 // use a local SDK or PDK cache of support files to disassemble
369 // or do other things.
370 m_major_os_version = major;
371 m_minor_os_version = minor;
372 m_update_os_version = update;
373 return true;
374 }
375 }
376 return false;
377}
378
379
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000380Error
381Platform::ResolveExecutable (const FileSpec &exe_file,
382 const ArchSpec &exe_arch,
383 lldb::ModuleSP &exe_module_sp)
384{
385 Error error;
386 if (exe_file.Exists())
387 {
388 if (exe_arch.IsValid())
389 {
390 error = ModuleList::GetSharedModule (exe_file,
391 exe_arch,
392 NULL,
393 NULL,
394 0,
395 exe_module_sp,
396 NULL,
397 NULL);
398 }
399 else
400 {
401 // No valid architecture was specified, ask the platform for
402 // the architectures that we should be using (in the correct order)
403 // and see if we can find a match that way
404 ArchSpec platform_arch;
405 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
406 {
407 error = ModuleList::GetSharedModule (exe_file,
408 platform_arch,
409 NULL,
410 NULL,
411 0,
412 exe_module_sp,
413 NULL,
414 NULL);
415 // Did we find an executable using one of the
416 if (error.Success() && exe_module_sp)
417 break;
418 }
419 }
420 }
421 else
422 {
423 error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
424 exe_file.GetDirectory().AsCString(""),
425 exe_file.GetDirectory() ? "/" : "",
426 exe_file.GetFilename().AsCString(""));
427 }
428 return error;
429}
430
Greg Claytonb1888f22011-03-19 01:12:21 +0000431
432const ArchSpec &
433Platform::GetSystemArchitecture()
434{
435 if (IsHost())
436 {
437 if (!m_system_arch.IsValid())
438 {
439 // We have a local host platform
440 m_system_arch = Host::GetArchitecture();
441 m_system_arch_set_while_connected = m_system_arch.IsValid();
442 }
443 }
444 else
445 {
446 // We have a remote platform. We can only fetch the remote
447 // system architecture if we are connected, and we don't want to do it
448 // more than once.
449
450 const bool is_connected = IsConnected();
451
452 bool fetch = false;
453 if (m_system_arch.IsValid())
454 {
455 // We have valid OS version info, check to make sure it wasn't
456 // manually set prior to connecting. If it was manually set prior
457 // to connecting, then lets fetch the actual OS version info
458 // if we are now connected.
459 if (is_connected && !m_system_arch_set_while_connected)
460 fetch = true;
461 }
462 else
463 {
464 // We don't have valid OS version info, fetch it if we are connected
465 fetch = is_connected;
466 }
467
468 if (fetch)
469 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000470 m_system_arch = GetRemoteSystemArchitecture ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000471 m_system_arch_set_while_connected = m_system_arch.IsValid();
472 }
473 }
474 return m_system_arch;
475}
476
477
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000478Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000479Platform::ConnectRemote (Args& args)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000480{
481 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000482 if (IsHost())
483 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
484 else
485 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000486 return error;
487}
488
489Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000490Platform::DisconnectRemote ()
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000491{
492 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000493 if (IsHost())
494 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
495 else
496 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000497 return error;
498}
Greg Clayton24bc5d92011-03-30 18:16:51 +0000499
500bool
501Platform::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
502{
503 // Take care of the host case so that each subclass can just
504 // call Platform::GetProcessInfo (pid, process_info)
505 if (IsHost())
506 return Host::GetProcessInfo (pid, process_info);
507 return false;
508}
509
510uint32_t
511Platform::FindProcesses (const ProcessInfoMatch &match_info,
512 ProcessInfoList &process_infos)
513{
514 uint32_t match_count = 0;
515 if (IsHost())
516 match_count = Host::FindProcesses (match_info, process_infos);
517 return match_count;
518}