blob: 5c38ab33928abc3ec0c361fb398ce66a02d8cbd1 [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"
Greg Claytonb72d0f02011-04-12 05:54:46 +000017#include "lldb/Core/Log.h"
Greg Claytone4b9c1f2011-03-08 22:40:15 +000018#include "lldb/Core/PluginManager.h"
19#include "lldb/Host/FileSpec.h"
Greg Claytonb1888f22011-03-19 01:12:21 +000020#include "lldb/Host/Host.h"
Greg Claytonb72d0f02011-04-12 05:54:46 +000021#include "lldb/Target/Process.h"
Greg Claytone4b9c1f2011-03-08 22:40:15 +000022#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
Greg Claytone4b9c1f2011-03-08 22:40:15 +000036static 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
Greg Clayton5e342f52011-04-13 22:47:15 +000049
50const char *
51Platform::GetHostPlatformName ()
52{
53 return "host";
54}
55
Greg Claytone4b9c1f2011-03-08 22:40:15 +000056//------------------------------------------------------------------
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
Greg Claytone4b9c1f2011-03-08 22:40:15 +000080Error
Greg Claytoncb8977d2011-03-23 00:09:55 +000081Platform::GetFile (const FileSpec &platform_file,
82 const UUID *uuid_ptr,
83 FileSpec &local_file)
Greg Claytone4b9c1f2011-03-08 22:40:15 +000084{
85 // Default to the local case
86 local_file = platform_file;
87 return Error();
88}
89
Greg Clayton24bc5d92011-03-30 18:16:51 +000090Error
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
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000119
120PlatformSP
Greg Claytonb1888f22011-03-19 01:12:21 +0000121Platform::Create (const char *platform_name, Error &error)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000122{
123 PlatformCreateInstance create_callback = NULL;
124 lldb::PlatformSP platform_sp;
Greg Claytonb1888f22011-03-19 01:12:21 +0000125 if (platform_name && platform_name[0])
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000126 {
127 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (platform_name);
128 if (create_callback)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000129 platform_sp.reset(create_callback());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000130 else
Greg Claytonb1888f22011-03-19 01:12:21 +0000131 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000132 }
133 else
Greg Claytonb1888f22011-03-19 01:12:21 +0000134 error.SetErrorString ("invalid platform name");
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000135 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//------------------------------------------------------------------
Greg Claytonb1888f22011-03-19 01:12:21 +0000160Platform::Platform (bool is_host) :
161 m_is_host (is_host),
Greg Claytonb1888f22011-03-19 01:12:21 +0000162 m_os_version_set_while_connected (false),
163 m_system_arch_set_while_connected (false),
164 m_remote_url (),
Greg Clayton58e26e02011-03-24 04:28:38 +0000165 m_name (),
Greg Claytonb1888f22011-03-19 01:12:21 +0000166 m_major_os_version (UINT32_MAX),
167 m_minor_os_version (UINT32_MAX),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000168 m_update_os_version (UINT32_MAX),
169 m_system_arch(),
170 m_uid_map_mutex (Mutex::eMutexTypeNormal),
171 m_gid_map_mutex (Mutex::eMutexTypeNormal),
172 m_uid_map(),
173 m_gid_map(),
174 m_max_uid_name_len (0),
175 m_max_gid_name_len (0)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000176{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000177 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
178 if (log)
179 log->Printf ("%p Platform::Platform()", this);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000180}
181
182//------------------------------------------------------------------
183/// Destructor.
184///
185/// The destructor is virtual since this class is designed to be
186/// inherited from by the plug-in instance.
187//------------------------------------------------------------------
188Platform::~Platform()
189{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000190 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
191 if (log)
192 log->Printf ("%p Platform::~Platform()", this);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000193}
194
Greg Clayton58e26e02011-03-24 04:28:38 +0000195void
196Platform::GetStatus (Stream &strm)
197{
198 uint32_t major = UINT32_MAX;
199 uint32_t minor = UINT32_MAX;
200 uint32_t update = UINT32_MAX;
201 std::string s;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000202 strm.Printf (" Platform: %s\n", GetShortPluginName());
Greg Clayton58e26e02011-03-24 04:28:38 +0000203
204 ArchSpec arch (GetSystemArchitecture());
205 if (arch.IsValid())
206 {
207 if (!arch.GetTriple().str().empty())
Greg Clayton24bc5d92011-03-30 18:16:51 +0000208 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000209 }
210
211 if (GetOSVersion(major, minor, update))
212 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000213 strm.Printf("OS Version: %u", major);
Greg Clayton58e26e02011-03-24 04:28:38 +0000214 if (minor != UINT32_MAX)
215 strm.Printf(".%u", minor);
216 if (update != UINT32_MAX)
217 strm.Printf(".%u", update);
218
219 if (GetOSBuildString (s))
220 strm.Printf(" (%s)", s.c_str());
221
222 strm.EOL();
223 }
224
225 if (GetOSKernelDescription (s))
Greg Clayton24bc5d92011-03-30 18:16:51 +0000226 strm.Printf(" Kernel: %s\n", s.c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000227
228 if (IsHost())
229 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000230 strm.Printf(" Hostname: %s\n", GetHostname());
Greg Clayton58e26e02011-03-24 04:28:38 +0000231 }
232 else
233 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000234 const bool is_connected = IsConnected();
235 if (is_connected)
236 strm.Printf(" Hostname: %s\n", GetHostname());
237 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
Greg Clayton58e26e02011-03-24 04:28:38 +0000238 }
239}
240
Greg Claytonb1888f22011-03-19 01:12:21 +0000241
242bool
243Platform::GetOSVersion (uint32_t &major,
244 uint32_t &minor,
245 uint32_t &update)
246{
247 bool success = m_major_os_version != UINT32_MAX;
248 if (IsHost())
249 {
250 if (!success)
251 {
252 // We have a local host platform
253 success = Host::GetOSVersion (m_major_os_version,
254 m_minor_os_version,
255 m_update_os_version);
256 m_os_version_set_while_connected = success;
257 }
258 }
259 else
260 {
261 // We have a remote platform. We can only fetch the remote
262 // OS version if we are connected, and we don't want to do it
263 // more than once.
264
265 const bool is_connected = IsConnected();
266
Greg Clayton58e26e02011-03-24 04:28:38 +0000267 bool fetch = false;
Greg Claytonb1888f22011-03-19 01:12:21 +0000268 if (success)
269 {
270 // We have valid OS version info, check to make sure it wasn't
271 // manually set prior to connecting. If it was manually set prior
272 // to connecting, then lets fetch the actual OS version info
273 // if we are now connected.
274 if (is_connected && !m_os_version_set_while_connected)
Greg Clayton58e26e02011-03-24 04:28:38 +0000275 fetch = true;
Greg Claytonb1888f22011-03-19 01:12:21 +0000276 }
277 else
278 {
279 // We don't have valid OS version info, fetch it if we are connected
Greg Clayton58e26e02011-03-24 04:28:38 +0000280 fetch = is_connected;
Greg Claytonb1888f22011-03-19 01:12:21 +0000281 }
282
Greg Clayton58e26e02011-03-24 04:28:38 +0000283 if (fetch)
Greg Claytonb1888f22011-03-19 01:12:21 +0000284 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000285 success = GetRemoteOSVersion ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000286 m_os_version_set_while_connected = success;
287 }
288 }
289
290 if (success)
291 {
292 major = m_major_os_version;
293 minor = m_minor_os_version;
294 update = m_update_os_version;
295 }
296 return success;
297}
Greg Clayton58e26e02011-03-24 04:28:38 +0000298
299bool
300Platform::GetOSBuildString (std::string &s)
301{
302 if (IsHost())
303 return Host::GetOSBuildString (s);
304 else
305 return GetRemoteOSBuildString (s);
306}
307
308bool
309Platform::GetOSKernelDescription (std::string &s)
310{
311 if (IsHost())
312 return Host::GetOSKernelDescription (s);
313 else
314 return GetRemoteOSKernelDescription (s);
315}
316
317const char *
Greg Claytonb72d0f02011-04-12 05:54:46 +0000318Platform::GetName ()
319{
320 const char *name = GetHostname();
321 if (name == NULL || name[0] == '\0')
322 name = GetShortPluginName();
323 return name;
324}
325
326const char *
Greg Clayton58e26e02011-03-24 04:28:38 +0000327Platform::GetHostname ()
328{
Greg Clayton5e342f52011-04-13 22:47:15 +0000329 if (IsHost())
330 return "localhost";
Greg Clayton24bc5d92011-03-30 18:16:51 +0000331
332 if (m_name.empty())
333 return NULL;
334 return m_name.c_str();
335}
336
337const char *
338Platform::GetUserName (uint32_t uid)
339{
340 const char *user_name = GetCachedUserName(uid);
341 if (user_name)
342 return user_name;
343 if (IsHost())
344 {
345 std::string name;
346 if (Host::GetUserName(uid, name))
347 return SetCachedUserName (uid, name.c_str(), name.size());
348 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000349 return NULL;
350}
351
Greg Clayton24bc5d92011-03-30 18:16:51 +0000352const char *
353Platform::GetGroupName (uint32_t gid)
354{
355 const char *group_name = GetCachedGroupName(gid);
356 if (group_name)
357 return group_name;
358 if (IsHost())
359 {
360 std::string name;
361 if (Host::GetGroupName(gid, name))
362 return SetCachedGroupName (gid, name.c_str(), name.size());
363 }
364 return NULL;
365}
Greg Clayton58e26e02011-03-24 04:28:38 +0000366
Greg Claytonb1888f22011-03-19 01:12:21 +0000367bool
368Platform::SetOSVersion (uint32_t major,
369 uint32_t minor,
370 uint32_t update)
371{
372 if (IsHost())
373 {
374 // We don't need anyone setting the OS version for the host platform,
375 // we should be able to figure it out by calling Host::GetOSVersion(...).
376 return false;
377 }
378 else
379 {
380 // We have a remote platform, allow setting the target OS version if
381 // we aren't connected, since if we are connected, we should be able to
382 // request the remote OS version from the connected platform.
383 if (IsConnected())
384 return false;
385 else
386 {
387 // We aren't connected and we might want to set the OS version
388 // ahead of time before we connect so we can peruse files and
389 // use a local SDK or PDK cache of support files to disassemble
390 // or do other things.
391 m_major_os_version = major;
392 m_minor_os_version = minor;
393 m_update_os_version = update;
394 return true;
395 }
396 }
397 return false;
398}
399
400
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000401Error
402Platform::ResolveExecutable (const FileSpec &exe_file,
403 const ArchSpec &exe_arch,
404 lldb::ModuleSP &exe_module_sp)
405{
406 Error error;
407 if (exe_file.Exists())
408 {
409 if (exe_arch.IsValid())
410 {
411 error = ModuleList::GetSharedModule (exe_file,
412 exe_arch,
413 NULL,
414 NULL,
415 0,
416 exe_module_sp,
417 NULL,
418 NULL);
419 }
420 else
421 {
422 // No valid architecture was specified, ask the platform for
423 // the architectures that we should be using (in the correct order)
424 // and see if we can find a match that way
425 ArchSpec platform_arch;
426 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
427 {
428 error = ModuleList::GetSharedModule (exe_file,
429 platform_arch,
430 NULL,
431 NULL,
432 0,
433 exe_module_sp,
434 NULL,
435 NULL);
436 // Did we find an executable using one of the
437 if (error.Success() && exe_module_sp)
438 break;
439 }
440 }
441 }
442 else
443 {
444 error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
445 exe_file.GetDirectory().AsCString(""),
446 exe_file.GetDirectory() ? "/" : "",
447 exe_file.GetFilename().AsCString(""));
448 }
449 return error;
450}
451
Greg Claytonb1888f22011-03-19 01:12:21 +0000452
453const ArchSpec &
454Platform::GetSystemArchitecture()
455{
456 if (IsHost())
457 {
458 if (!m_system_arch.IsValid())
459 {
460 // We have a local host platform
461 m_system_arch = Host::GetArchitecture();
462 m_system_arch_set_while_connected = m_system_arch.IsValid();
463 }
464 }
465 else
466 {
467 // We have a remote platform. We can only fetch the remote
468 // system architecture if we are connected, and we don't want to do it
469 // more than once.
470
471 const bool is_connected = IsConnected();
472
473 bool fetch = false;
474 if (m_system_arch.IsValid())
475 {
476 // We have valid OS version info, check to make sure it wasn't
477 // manually set prior to connecting. If it was manually set prior
478 // to connecting, then lets fetch the actual OS version info
479 // if we are now connected.
480 if (is_connected && !m_system_arch_set_while_connected)
481 fetch = true;
482 }
483 else
484 {
485 // We don't have valid OS version info, fetch it if we are connected
486 fetch = is_connected;
487 }
488
489 if (fetch)
490 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000491 m_system_arch = GetRemoteSystemArchitecture ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000492 m_system_arch_set_while_connected = m_system_arch.IsValid();
493 }
494 }
495 return m_system_arch;
496}
497
498
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000499Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000500Platform::ConnectRemote (Args& args)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000501{
502 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000503 if (IsHost())
504 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
505 else
506 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000507 return error;
508}
509
510Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000511Platform::DisconnectRemote ()
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000512{
513 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000514 if (IsHost())
515 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
516 else
517 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000518 return error;
519}
Greg Clayton24bc5d92011-03-30 18:16:51 +0000520
521bool
Greg Claytonb72d0f02011-04-12 05:54:46 +0000522Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000523{
524 // Take care of the host case so that each subclass can just
Greg Claytonb72d0f02011-04-12 05:54:46 +0000525 // call this function to get the host functionality.
Greg Clayton24bc5d92011-03-30 18:16:51 +0000526 if (IsHost())
527 return Host::GetProcessInfo (pid, process_info);
528 return false;
529}
530
531uint32_t
Greg Claytonb72d0f02011-04-12 05:54:46 +0000532Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
533 ProcessInstanceInfoList &process_infos)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000534{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000535 // Take care of the host case so that each subclass can just
536 // call this function to get the host functionality.
Greg Clayton24bc5d92011-03-30 18:16:51 +0000537 uint32_t match_count = 0;
538 if (IsHost())
539 match_count = Host::FindProcesses (match_info, process_infos);
540 return match_count;
541}
Greg Claytonb72d0f02011-04-12 05:54:46 +0000542
543
544Error
545Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
546{
547 Error error;
548 // Take care of the host case so that each subclass can just
549 // call this function to get the host functionality.
550 if (IsHost())
551 error = Host::LaunchProcess (launch_info);
552 else
553 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
554 return error;
555}
556
557lldb::ProcessSP
558Platform::DebugProcess (ProcessLaunchInfo &launch_info,
559 Debugger &debugger,
560 Target *target, // Can be NULL, if NULL create a new target, else use existing one
561 Listener &listener,
562 Error &error)
563{
564 ProcessSP process_sp;
565 // Make sure we stop at the entry point
566 launch_info.GetFlags ().Set (eLaunchFlagDebug);
567 error = LaunchProcess (launch_info);
568 if (error.Success())
569 {
570 lldb::pid_t pid = launch_info.GetProcessID();
571 if (pid != LLDB_INVALID_PROCESS_ID)
572 {
573 process_sp = Attach (pid, debugger, target, listener, error);
574
575// if (process_sp)
576// {
577// if (launch_info.GetFlags().IsClear (eLaunchFlagStopAtEntry))
578// process_sp->Resume();
579// }
580 }
581 }
582 return process_sp;
583}
584