blob: e3a4e817bebbd3de0d9129f5c6f0cecc9e5f9b92 [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 Claytonb1888f22011-03-19 01:12:21 +0000454
455const ArchSpec &
456Platform::GetSystemArchitecture()
457{
458 if (IsHost())
459 {
460 if (!m_system_arch.IsValid())
461 {
462 // We have a local host platform
463 m_system_arch = Host::GetArchitecture();
464 m_system_arch_set_while_connected = m_system_arch.IsValid();
465 }
466 }
467 else
468 {
469 // We have a remote platform. We can only fetch the remote
470 // system architecture if we are connected, and we don't want to do it
471 // more than once.
472
473 const bool is_connected = IsConnected();
474
475 bool fetch = false;
476 if (m_system_arch.IsValid())
477 {
478 // We have valid OS version info, check to make sure it wasn't
479 // manually set prior to connecting. If it was manually set prior
480 // to connecting, then lets fetch the actual OS version info
481 // if we are now connected.
482 if (is_connected && !m_system_arch_set_while_connected)
483 fetch = true;
484 }
485 else
486 {
487 // We don't have valid OS version info, fetch it if we are connected
488 fetch = is_connected;
489 }
490
491 if (fetch)
492 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000493 m_system_arch = GetRemoteSystemArchitecture ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000494 m_system_arch_set_while_connected = m_system_arch.IsValid();
495 }
496 }
497 return m_system_arch;
498}
499
500
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000501Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000502Platform::ConnectRemote (Args& args)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000503{
504 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000505 if (IsHost())
506 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
507 else
508 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000509 return error;
510}
511
512Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000513Platform::DisconnectRemote ()
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000514{
515 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000516 if (IsHost())
517 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
518 else
519 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000520 return error;
521}
Greg Clayton24bc5d92011-03-30 18:16:51 +0000522
523bool
Greg Claytonb72d0f02011-04-12 05:54:46 +0000524Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000525{
526 // Take care of the host case so that each subclass can just
Greg Claytonb72d0f02011-04-12 05:54:46 +0000527 // call this function to get the host functionality.
Greg Clayton24bc5d92011-03-30 18:16:51 +0000528 if (IsHost())
529 return Host::GetProcessInfo (pid, process_info);
530 return false;
531}
532
533uint32_t
Greg Claytonb72d0f02011-04-12 05:54:46 +0000534Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
535 ProcessInstanceInfoList &process_infos)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000536{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000537 // Take care of the host case so that each subclass can just
538 // call this function to get the host functionality.
Greg Clayton24bc5d92011-03-30 18:16:51 +0000539 uint32_t match_count = 0;
540 if (IsHost())
541 match_count = Host::FindProcesses (match_info, process_infos);
542 return match_count;
543}
Greg Claytonb72d0f02011-04-12 05:54:46 +0000544
545
546Error
547Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
548{
549 Error error;
550 // Take care of the host case so that each subclass can just
551 // call this function to get the host functionality.
552 if (IsHost())
553 error = Host::LaunchProcess (launch_info);
554 else
555 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
556 return error;
557}
558
559lldb::ProcessSP
560Platform::DebugProcess (ProcessLaunchInfo &launch_info,
561 Debugger &debugger,
562 Target *target, // Can be NULL, if NULL create a new target, else use existing one
563 Listener &listener,
564 Error &error)
565{
566 ProcessSP process_sp;
567 // Make sure we stop at the entry point
568 launch_info.GetFlags ().Set (eLaunchFlagDebug);
569 error = LaunchProcess (launch_info);
570 if (error.Success())
571 {
572 lldb::pid_t pid = launch_info.GetProcessID();
573 if (pid != LLDB_INVALID_PROCESS_ID)
574 {
575 process_sp = Attach (pid, debugger, target, listener, error);
576
577// if (process_sp)
578// {
579// if (launch_info.GetFlags().IsClear (eLaunchFlagStopAtEntry))
580// process_sp->Resume();
581// }
582 }
583 }
584 return process_sp;
585}
586