blob: 737b8d4914b4c1f62ccf86c868e841cae1dad298 [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),
Greg Clayton604f0d32011-06-17 03:31:01 +0000164 m_sdk_sysroot (),
165 m_sdk_build (),
Greg Claytonb1888f22011-03-19 01:12:21 +0000166 m_remote_url (),
Greg Clayton58e26e02011-03-24 04:28:38 +0000167 m_name (),
Greg Claytonb1888f22011-03-19 01:12:21 +0000168 m_major_os_version (UINT32_MAX),
169 m_minor_os_version (UINT32_MAX),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000170 m_update_os_version (UINT32_MAX),
171 m_system_arch(),
172 m_uid_map_mutex (Mutex::eMutexTypeNormal),
173 m_gid_map_mutex (Mutex::eMutexTypeNormal),
174 m_uid_map(),
175 m_gid_map(),
176 m_max_uid_name_len (0),
177 m_max_gid_name_len (0)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000178{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000179 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
180 if (log)
181 log->Printf ("%p Platform::Platform()", this);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000182}
183
184//------------------------------------------------------------------
185/// Destructor.
186///
187/// The destructor is virtual since this class is designed to be
188/// inherited from by the plug-in instance.
189//------------------------------------------------------------------
190Platform::~Platform()
191{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000192 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
193 if (log)
194 log->Printf ("%p Platform::~Platform()", this);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000195}
196
Greg Clayton58e26e02011-03-24 04:28:38 +0000197void
198Platform::GetStatus (Stream &strm)
199{
200 uint32_t major = UINT32_MAX;
201 uint32_t minor = UINT32_MAX;
202 uint32_t update = UINT32_MAX;
203 std::string s;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000204 strm.Printf (" Platform: %s\n", GetShortPluginName());
Greg Clayton58e26e02011-03-24 04:28:38 +0000205
206 ArchSpec arch (GetSystemArchitecture());
207 if (arch.IsValid())
208 {
209 if (!arch.GetTriple().str().empty())
Greg Clayton24bc5d92011-03-30 18:16:51 +0000210 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000211 }
212
213 if (GetOSVersion(major, minor, update))
214 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000215 strm.Printf("OS Version: %u", major);
Greg Clayton58e26e02011-03-24 04:28:38 +0000216 if (minor != UINT32_MAX)
217 strm.Printf(".%u", minor);
218 if (update != UINT32_MAX)
219 strm.Printf(".%u", update);
220
221 if (GetOSBuildString (s))
222 strm.Printf(" (%s)", s.c_str());
223
224 strm.EOL();
225 }
226
227 if (GetOSKernelDescription (s))
Greg Clayton24bc5d92011-03-30 18:16:51 +0000228 strm.Printf(" Kernel: %s\n", s.c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000229
230 if (IsHost())
231 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000232 strm.Printf(" Hostname: %s\n", GetHostname());
Greg Clayton58e26e02011-03-24 04:28:38 +0000233 }
234 else
235 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000236 const bool is_connected = IsConnected();
237 if (is_connected)
238 strm.Printf(" Hostname: %s\n", GetHostname());
239 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
Greg Clayton58e26e02011-03-24 04:28:38 +0000240 }
241}
242
Greg Claytonb1888f22011-03-19 01:12:21 +0000243
244bool
245Platform::GetOSVersion (uint32_t &major,
246 uint32_t &minor,
247 uint32_t &update)
248{
249 bool success = m_major_os_version != UINT32_MAX;
250 if (IsHost())
251 {
252 if (!success)
253 {
254 // We have a local host platform
255 success = Host::GetOSVersion (m_major_os_version,
256 m_minor_os_version,
257 m_update_os_version);
258 m_os_version_set_while_connected = success;
259 }
260 }
261 else
262 {
263 // We have a remote platform. We can only fetch the remote
264 // OS version if we are connected, and we don't want to do it
265 // more than once.
266
267 const bool is_connected = IsConnected();
268
Greg Clayton58e26e02011-03-24 04:28:38 +0000269 bool fetch = false;
Greg Claytonb1888f22011-03-19 01:12:21 +0000270 if (success)
271 {
272 // We have valid OS version info, check to make sure it wasn't
273 // manually set prior to connecting. If it was manually set prior
274 // to connecting, then lets fetch the actual OS version info
275 // if we are now connected.
276 if (is_connected && !m_os_version_set_while_connected)
Greg Clayton58e26e02011-03-24 04:28:38 +0000277 fetch = true;
Greg Claytonb1888f22011-03-19 01:12:21 +0000278 }
279 else
280 {
281 // We don't have valid OS version info, fetch it if we are connected
Greg Clayton58e26e02011-03-24 04:28:38 +0000282 fetch = is_connected;
Greg Claytonb1888f22011-03-19 01:12:21 +0000283 }
284
Greg Clayton58e26e02011-03-24 04:28:38 +0000285 if (fetch)
Greg Claytonb1888f22011-03-19 01:12:21 +0000286 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000287 success = GetRemoteOSVersion ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000288 m_os_version_set_while_connected = success;
289 }
290 }
291
292 if (success)
293 {
294 major = m_major_os_version;
295 minor = m_minor_os_version;
296 update = m_update_os_version;
297 }
298 return success;
299}
Greg Clayton58e26e02011-03-24 04:28:38 +0000300
301bool
302Platform::GetOSBuildString (std::string &s)
303{
304 if (IsHost())
305 return Host::GetOSBuildString (s);
306 else
307 return GetRemoteOSBuildString (s);
308}
309
310bool
311Platform::GetOSKernelDescription (std::string &s)
312{
313 if (IsHost())
314 return Host::GetOSKernelDescription (s);
315 else
316 return GetRemoteOSKernelDescription (s);
317}
318
319const char *
Greg Claytonb72d0f02011-04-12 05:54:46 +0000320Platform::GetName ()
321{
322 const char *name = GetHostname();
323 if (name == NULL || name[0] == '\0')
324 name = GetShortPluginName();
325 return name;
326}
327
328const char *
Greg Clayton58e26e02011-03-24 04:28:38 +0000329Platform::GetHostname ()
330{
Greg Clayton5e342f52011-04-13 22:47:15 +0000331 if (IsHost())
332 return "localhost";
Greg Clayton24bc5d92011-03-30 18:16:51 +0000333
334 if (m_name.empty())
335 return NULL;
336 return m_name.c_str();
337}
338
339const char *
340Platform::GetUserName (uint32_t uid)
341{
342 const char *user_name = GetCachedUserName(uid);
343 if (user_name)
344 return user_name;
345 if (IsHost())
346 {
347 std::string name;
348 if (Host::GetUserName(uid, name))
349 return SetCachedUserName (uid, name.c_str(), name.size());
350 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000351 return NULL;
352}
353
Greg Clayton24bc5d92011-03-30 18:16:51 +0000354const char *
355Platform::GetGroupName (uint32_t gid)
356{
357 const char *group_name = GetCachedGroupName(gid);
358 if (group_name)
359 return group_name;
360 if (IsHost())
361 {
362 std::string name;
363 if (Host::GetGroupName(gid, name))
364 return SetCachedGroupName (gid, name.c_str(), name.size());
365 }
366 return NULL;
367}
Greg Clayton58e26e02011-03-24 04:28:38 +0000368
Greg Claytonb1888f22011-03-19 01:12:21 +0000369bool
370Platform::SetOSVersion (uint32_t major,
371 uint32_t minor,
372 uint32_t update)
373{
374 if (IsHost())
375 {
376 // We don't need anyone setting the OS version for the host platform,
377 // we should be able to figure it out by calling Host::GetOSVersion(...).
378 return false;
379 }
380 else
381 {
382 // We have a remote platform, allow setting the target OS version if
383 // we aren't connected, since if we are connected, we should be able to
384 // request the remote OS version from the connected platform.
385 if (IsConnected())
386 return false;
387 else
388 {
389 // We aren't connected and we might want to set the OS version
390 // ahead of time before we connect so we can peruse files and
391 // use a local SDK or PDK cache of support files to disassemble
392 // or do other things.
393 m_major_os_version = major;
394 m_minor_os_version = minor;
395 m_update_os_version = update;
396 return true;
397 }
398 }
399 return false;
400}
401
402
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000403Error
404Platform::ResolveExecutable (const FileSpec &exe_file,
405 const ArchSpec &exe_arch,
406 lldb::ModuleSP &exe_module_sp)
407{
408 Error error;
409 if (exe_file.Exists())
410 {
411 if (exe_arch.IsValid())
412 {
413 error = ModuleList::GetSharedModule (exe_file,
414 exe_arch,
415 NULL,
416 NULL,
417 0,
418 exe_module_sp,
419 NULL,
420 NULL);
421 }
422 else
423 {
424 // No valid architecture was specified, ask the platform for
425 // the architectures that we should be using (in the correct order)
426 // and see if we can find a match that way
427 ArchSpec platform_arch;
428 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
429 {
430 error = ModuleList::GetSharedModule (exe_file,
431 platform_arch,
432 NULL,
433 NULL,
434 0,
435 exe_module_sp,
436 NULL,
437 NULL);
438 // Did we find an executable using one of the
439 if (error.Success() && exe_module_sp)
440 break;
441 }
442 }
443 }
444 else
445 {
446 error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
447 exe_file.GetDirectory().AsCString(""),
448 exe_file.GetDirectory() ? "/" : "",
449 exe_file.GetFilename().AsCString(""));
450 }
451 return error;
452}
453
Greg Claytonf2bf8702011-08-11 16:25:18 +0000454bool
455Platform::ResolveRemotePath (const FileSpec &platform_path,
456 FileSpec &resolved_platform_path)
457{
458 resolved_platform_path = platform_path;
459 return resolved_platform_path.ResolvePath();
460}
461
Greg Claytonb1888f22011-03-19 01:12:21 +0000462
463const ArchSpec &
464Platform::GetSystemArchitecture()
465{
466 if (IsHost())
467 {
468 if (!m_system_arch.IsValid())
469 {
470 // We have a local host platform
471 m_system_arch = Host::GetArchitecture();
472 m_system_arch_set_while_connected = m_system_arch.IsValid();
473 }
474 }
475 else
476 {
477 // We have a remote platform. We can only fetch the remote
478 // system architecture if we are connected, and we don't want to do it
479 // more than once.
480
481 const bool is_connected = IsConnected();
482
483 bool fetch = false;
484 if (m_system_arch.IsValid())
485 {
486 // We have valid OS version info, check to make sure it wasn't
487 // manually set prior to connecting. If it was manually set prior
488 // to connecting, then lets fetch the actual OS version info
489 // if we are now connected.
490 if (is_connected && !m_system_arch_set_while_connected)
491 fetch = true;
492 }
493 else
494 {
495 // We don't have valid OS version info, fetch it if we are connected
496 fetch = is_connected;
497 }
498
499 if (fetch)
500 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000501 m_system_arch = GetRemoteSystemArchitecture ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000502 m_system_arch_set_while_connected = m_system_arch.IsValid();
503 }
504 }
505 return m_system_arch;
506}
507
508
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000509Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000510Platform::ConnectRemote (Args& args)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000511{
512 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000513 if (IsHost())
514 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
515 else
516 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000517 return error;
518}
519
520Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000521Platform::DisconnectRemote ()
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000522{
523 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000524 if (IsHost())
525 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
526 else
527 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000528 return error;
529}
Greg Clayton24bc5d92011-03-30 18:16:51 +0000530
531bool
Greg Claytonb72d0f02011-04-12 05:54:46 +0000532Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000533{
534 // Take care of the host case so that each subclass can just
Greg Claytonb72d0f02011-04-12 05:54:46 +0000535 // call this function to get the host functionality.
Greg Clayton24bc5d92011-03-30 18:16:51 +0000536 if (IsHost())
537 return Host::GetProcessInfo (pid, process_info);
538 return false;
539}
540
541uint32_t
Greg Claytonb72d0f02011-04-12 05:54:46 +0000542Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
543 ProcessInstanceInfoList &process_infos)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000544{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000545 // Take care of the host case so that each subclass can just
546 // call this function to get the host functionality.
Greg Clayton24bc5d92011-03-30 18:16:51 +0000547 uint32_t match_count = 0;
548 if (IsHost())
549 match_count = Host::FindProcesses (match_info, process_infos);
550 return match_count;
551}
Greg Claytonb72d0f02011-04-12 05:54:46 +0000552
553
554Error
555Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
556{
557 Error error;
558 // Take care of the host case so that each subclass can just
559 // call this function to get the host functionality.
560 if (IsHost())
561 error = Host::LaunchProcess (launch_info);
562 else
563 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
564 return error;
565}
566
567lldb::ProcessSP
568Platform::DebugProcess (ProcessLaunchInfo &launch_info,
569 Debugger &debugger,
570 Target *target, // Can be NULL, if NULL create a new target, else use existing one
571 Listener &listener,
572 Error &error)
573{
574 ProcessSP process_sp;
575 // Make sure we stop at the entry point
576 launch_info.GetFlags ().Set (eLaunchFlagDebug);
577 error = LaunchProcess (launch_info);
578 if (error.Success())
579 {
Greg Clayton527154d2011-11-15 03:53:30 +0000580 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000581 {
Greg Clayton527154d2011-11-15 03:53:30 +0000582 ProcessAttachInfo attach_info (launch_info);
583 process_sp = Attach (attach_info, debugger, target, listener, error);
Greg Claytonffa43a62011-11-17 04:46:02 +0000584 if (process_sp)
585 {
586 // Since we attached to the process, it will think it needs to detach
587 // if the process object just goes away without an explicit call to
588 // Process::Kill() or Process::Detach(), so let it know to kill the
589 // process if this happens.
590 process_sp->SetShouldDetach (false);
Greg Clayton464c6162011-11-17 22:14:31 +0000591
592 // If we didn't have any file actions, the pseudo terminal might
593 // have been used where the slave side was given as the file to
594 // open for stdin/out/err after we have already opened the master
595 // so we can read/write stdin/out/err.
596 int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
597 if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd)
598 {
599 process_sp->SetSTDIOFileDescriptor(pty_fd);
600 }
Greg Claytonffa43a62011-11-17 04:46:02 +0000601 }
Greg Claytonb72d0f02011-04-12 05:54:46 +0000602 }
603 }
604 return process_sp;
605}