blob: 34c7337979ea7de1d29843cbeb2688c8cfe5043b [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
49//------------------------------------------------------------------
50/// Get the native host platform plug-in.
51///
52/// There should only be one of these for each host that LLDB runs
53/// upon that should be statically compiled in and registered using
54/// preprocessor macros or other similar build mechanisms.
55///
56/// This platform will be used as the default platform when launching
57/// or attaching to processes unless another platform is specified.
58//------------------------------------------------------------------
59PlatformSP
60Platform::GetDefaultPlatform ()
61{
62 return GetDefaultPlatformSP ();
63}
64
65void
66Platform::SetDefaultPlatform (const lldb::PlatformSP &platform_sp)
67{
68 // The native platform should use its static void Platform::Initialize()
69 // function to register itself as the native platform.
70 GetDefaultPlatformSP () = platform_sp;
71}
72
Greg Claytone4b9c1f2011-03-08 22:40:15 +000073Error
Greg Claytoncb8977d2011-03-23 00:09:55 +000074Platform::GetFile (const FileSpec &platform_file,
75 const UUID *uuid_ptr,
76 FileSpec &local_file)
Greg Claytone4b9c1f2011-03-08 22:40:15 +000077{
78 // Default to the local case
79 local_file = platform_file;
80 return Error();
81}
82
Greg Clayton24bc5d92011-03-30 18:16:51 +000083Error
84Platform::GetSharedModule (const FileSpec &platform_file,
85 const ArchSpec &arch,
86 const UUID *uuid_ptr,
87 const ConstString *object_name_ptr,
88 off_t object_offset,
89 ModuleSP &module_sp,
90 ModuleSP *old_module_sp_ptr,
91 bool *did_create_ptr)
92{
93 // Don't do any path remapping for the default implementation
94 // of the platform GetSharedModule function, just call through
95 // to our static ModuleList function. Platform subclasses that
96 // implement remote debugging, might have a developer kits
97 // installed that have cached versions of the files for the
98 // remote target, or might implement a download and cache
99 // locally implementation.
100 const bool always_create = false;
101 return ModuleList::GetSharedModule (platform_file,
102 arch,
103 uuid_ptr,
104 object_name_ptr,
105 object_offset,
106 module_sp,
107 old_module_sp_ptr,
108 did_create_ptr,
109 always_create);
110}
111
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000112
113PlatformSP
Greg Claytonb1888f22011-03-19 01:12:21 +0000114Platform::Create (const char *platform_name, Error &error)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000115{
116 PlatformCreateInstance create_callback = NULL;
117 lldb::PlatformSP platform_sp;
Greg Claytonb1888f22011-03-19 01:12:21 +0000118 if (platform_name && platform_name[0])
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000119 {
120 create_callback = PluginManager::GetPlatformCreateCallbackForPluginName (platform_name);
121 if (create_callback)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000122 platform_sp.reset(create_callback());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000123 else
Greg Claytonb1888f22011-03-19 01:12:21 +0000124 error.SetErrorStringWithFormat ("unable to find a plug-in for the platform named \"%s\"", platform_name);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000125 }
126 else
Greg Claytonb1888f22011-03-19 01:12:21 +0000127 error.SetErrorString ("invalid platform name");
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000128 return platform_sp;
129}
130
131uint32_t
132Platform::GetNumConnectedRemotePlatforms ()
133{
134 Mutex::Locker locker (GetConnectedPlatformListMutex ());
135 return GetConnectedPlatformList().size();
136}
137
138PlatformSP
139Platform::GetConnectedRemotePlatformAtIndex (uint32_t idx)
140{
141 PlatformSP platform_sp;
142 {
143 Mutex::Locker locker (GetConnectedPlatformListMutex ());
144 if (idx < GetConnectedPlatformList().size())
145 platform_sp = GetConnectedPlatformList ()[idx];
146 }
147 return platform_sp;
148}
149
150//------------------------------------------------------------------
151/// Default Constructor
152//------------------------------------------------------------------
Greg Claytonb1888f22011-03-19 01:12:21 +0000153Platform::Platform (bool is_host) :
154 m_is_host (is_host),
Greg Claytonb1888f22011-03-19 01:12:21 +0000155 m_os_version_set_while_connected (false),
156 m_system_arch_set_while_connected (false),
157 m_remote_url (),
Greg Clayton58e26e02011-03-24 04:28:38 +0000158 m_name (),
Greg Claytonb1888f22011-03-19 01:12:21 +0000159 m_major_os_version (UINT32_MAX),
160 m_minor_os_version (UINT32_MAX),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000161 m_update_os_version (UINT32_MAX),
162 m_system_arch(),
163 m_uid_map_mutex (Mutex::eMutexTypeNormal),
164 m_gid_map_mutex (Mutex::eMutexTypeNormal),
165 m_uid_map(),
166 m_gid_map(),
167 m_max_uid_name_len (0),
168 m_max_gid_name_len (0)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000169{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000170 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
171 if (log)
172 log->Printf ("%p Platform::Platform()", this);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000173}
174
175//------------------------------------------------------------------
176/// Destructor.
177///
178/// The destructor is virtual since this class is designed to be
179/// inherited from by the plug-in instance.
180//------------------------------------------------------------------
181Platform::~Platform()
182{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000183 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
184 if (log)
185 log->Printf ("%p Platform::~Platform()", this);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000186}
187
Greg Clayton58e26e02011-03-24 04:28:38 +0000188void
189Platform::GetStatus (Stream &strm)
190{
191 uint32_t major = UINT32_MAX;
192 uint32_t minor = UINT32_MAX;
193 uint32_t update = UINT32_MAX;
194 std::string s;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000195 strm.Printf (" Platform: %s\n", GetShortPluginName());
Greg Clayton58e26e02011-03-24 04:28:38 +0000196
197 ArchSpec arch (GetSystemArchitecture());
198 if (arch.IsValid())
199 {
200 if (!arch.GetTriple().str().empty())
Greg Clayton24bc5d92011-03-30 18:16:51 +0000201 strm.Printf(" Triple: %s\n", arch.GetTriple().str().c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000202 }
203
204 if (GetOSVersion(major, minor, update))
205 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000206 strm.Printf("OS Version: %u", major);
Greg Clayton58e26e02011-03-24 04:28:38 +0000207 if (minor != UINT32_MAX)
208 strm.Printf(".%u", minor);
209 if (update != UINT32_MAX)
210 strm.Printf(".%u", update);
211
212 if (GetOSBuildString (s))
213 strm.Printf(" (%s)", s.c_str());
214
215 strm.EOL();
216 }
217
218 if (GetOSKernelDescription (s))
Greg Clayton24bc5d92011-03-30 18:16:51 +0000219 strm.Printf(" Kernel: %s\n", s.c_str());
Greg Clayton58e26e02011-03-24 04:28:38 +0000220
221 if (IsHost())
222 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000223 strm.Printf(" Hostname: %s\n", GetHostname());
Greg Clayton58e26e02011-03-24 04:28:38 +0000224 }
225 else
226 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000227 const bool is_connected = IsConnected();
228 if (is_connected)
229 strm.Printf(" Hostname: %s\n", GetHostname());
230 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
Greg Clayton58e26e02011-03-24 04:28:38 +0000231 }
232}
233
Greg Claytonb1888f22011-03-19 01:12:21 +0000234
235bool
236Platform::GetOSVersion (uint32_t &major,
237 uint32_t &minor,
238 uint32_t &update)
239{
240 bool success = m_major_os_version != UINT32_MAX;
241 if (IsHost())
242 {
243 if (!success)
244 {
245 // We have a local host platform
246 success = Host::GetOSVersion (m_major_os_version,
247 m_minor_os_version,
248 m_update_os_version);
249 m_os_version_set_while_connected = success;
250 }
251 }
252 else
253 {
254 // We have a remote platform. We can only fetch the remote
255 // OS version if we are connected, and we don't want to do it
256 // more than once.
257
258 const bool is_connected = IsConnected();
259
Greg Clayton58e26e02011-03-24 04:28:38 +0000260 bool fetch = false;
Greg Claytonb1888f22011-03-19 01:12:21 +0000261 if (success)
262 {
263 // We have valid OS version info, check to make sure it wasn't
264 // manually set prior to connecting. If it was manually set prior
265 // to connecting, then lets fetch the actual OS version info
266 // if we are now connected.
267 if (is_connected && !m_os_version_set_while_connected)
Greg Clayton58e26e02011-03-24 04:28:38 +0000268 fetch = true;
Greg Claytonb1888f22011-03-19 01:12:21 +0000269 }
270 else
271 {
272 // We don't have valid OS version info, fetch it if we are connected
Greg Clayton58e26e02011-03-24 04:28:38 +0000273 fetch = is_connected;
Greg Claytonb1888f22011-03-19 01:12:21 +0000274 }
275
Greg Clayton58e26e02011-03-24 04:28:38 +0000276 if (fetch)
Greg Claytonb1888f22011-03-19 01:12:21 +0000277 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000278 success = GetRemoteOSVersion ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000279 m_os_version_set_while_connected = success;
280 }
281 }
282
283 if (success)
284 {
285 major = m_major_os_version;
286 minor = m_minor_os_version;
287 update = m_update_os_version;
288 }
289 return success;
290}
Greg Clayton58e26e02011-03-24 04:28:38 +0000291
292bool
293Platform::GetOSBuildString (std::string &s)
294{
295 if (IsHost())
296 return Host::GetOSBuildString (s);
297 else
298 return GetRemoteOSBuildString (s);
299}
300
301bool
302Platform::GetOSKernelDescription (std::string &s)
303{
304 if (IsHost())
305 return Host::GetOSKernelDescription (s);
306 else
307 return GetRemoteOSKernelDescription (s);
308}
309
310const char *
Greg Claytonb72d0f02011-04-12 05:54:46 +0000311Platform::GetName ()
312{
313 const char *name = GetHostname();
314 if (name == NULL || name[0] == '\0')
315 name = GetShortPluginName();
316 return name;
317}
318
319const char *
Greg Clayton58e26e02011-03-24 04:28:38 +0000320Platform::GetHostname ()
321{
Greg Clayton24bc5d92011-03-30 18:16:51 +0000322 if (IsHost() && m_name.empty())
Greg Clayton58e26e02011-03-24 04:28:38 +0000323 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000324 if (!Host::GetHostname(m_name))
325 return "localhost";
Greg Clayton58e26e02011-03-24 04:28:38 +0000326 }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000327
328 if (m_name.empty())
329 return NULL;
330 return m_name.c_str();
331}
332
333const char *
334Platform::GetUserName (uint32_t uid)
335{
336 const char *user_name = GetCachedUserName(uid);
337 if (user_name)
338 return user_name;
339 if (IsHost())
340 {
341 std::string name;
342 if (Host::GetUserName(uid, name))
343 return SetCachedUserName (uid, name.c_str(), name.size());
344 }
Greg Clayton58e26e02011-03-24 04:28:38 +0000345 return NULL;
346}
347
Greg Clayton24bc5d92011-03-30 18:16:51 +0000348const char *
349Platform::GetGroupName (uint32_t gid)
350{
351 const char *group_name = GetCachedGroupName(gid);
352 if (group_name)
353 return group_name;
354 if (IsHost())
355 {
356 std::string name;
357 if (Host::GetGroupName(gid, name))
358 return SetCachedGroupName (gid, name.c_str(), name.size());
359 }
360 return NULL;
361}
Greg Clayton58e26e02011-03-24 04:28:38 +0000362
Greg Claytonb1888f22011-03-19 01:12:21 +0000363bool
364Platform::SetOSVersion (uint32_t major,
365 uint32_t minor,
366 uint32_t update)
367{
368 if (IsHost())
369 {
370 // We don't need anyone setting the OS version for the host platform,
371 // we should be able to figure it out by calling Host::GetOSVersion(...).
372 return false;
373 }
374 else
375 {
376 // We have a remote platform, allow setting the target OS version if
377 // we aren't connected, since if we are connected, we should be able to
378 // request the remote OS version from the connected platform.
379 if (IsConnected())
380 return false;
381 else
382 {
383 // We aren't connected and we might want to set the OS version
384 // ahead of time before we connect so we can peruse files and
385 // use a local SDK or PDK cache of support files to disassemble
386 // or do other things.
387 m_major_os_version = major;
388 m_minor_os_version = minor;
389 m_update_os_version = update;
390 return true;
391 }
392 }
393 return false;
394}
395
396
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000397Error
398Platform::ResolveExecutable (const FileSpec &exe_file,
399 const ArchSpec &exe_arch,
400 lldb::ModuleSP &exe_module_sp)
401{
402 Error error;
403 if (exe_file.Exists())
404 {
405 if (exe_arch.IsValid())
406 {
407 error = ModuleList::GetSharedModule (exe_file,
408 exe_arch,
409 NULL,
410 NULL,
411 0,
412 exe_module_sp,
413 NULL,
414 NULL);
415 }
416 else
417 {
418 // No valid architecture was specified, ask the platform for
419 // the architectures that we should be using (in the correct order)
420 // and see if we can find a match that way
421 ArchSpec platform_arch;
422 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
423 {
424 error = ModuleList::GetSharedModule (exe_file,
425 platform_arch,
426 NULL,
427 NULL,
428 0,
429 exe_module_sp,
430 NULL,
431 NULL);
432 // Did we find an executable using one of the
433 if (error.Success() && exe_module_sp)
434 break;
435 }
436 }
437 }
438 else
439 {
440 error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
441 exe_file.GetDirectory().AsCString(""),
442 exe_file.GetDirectory() ? "/" : "",
443 exe_file.GetFilename().AsCString(""));
444 }
445 return error;
446}
447
Greg Claytonb1888f22011-03-19 01:12:21 +0000448
449const ArchSpec &
450Platform::GetSystemArchitecture()
451{
452 if (IsHost())
453 {
454 if (!m_system_arch.IsValid())
455 {
456 // We have a local host platform
457 m_system_arch = Host::GetArchitecture();
458 m_system_arch_set_while_connected = m_system_arch.IsValid();
459 }
460 }
461 else
462 {
463 // We have a remote platform. We can only fetch the remote
464 // system architecture if we are connected, and we don't want to do it
465 // more than once.
466
467 const bool is_connected = IsConnected();
468
469 bool fetch = false;
470 if (m_system_arch.IsValid())
471 {
472 // We have valid OS version info, check to make sure it wasn't
473 // manually set prior to connecting. If it was manually set prior
474 // to connecting, then lets fetch the actual OS version info
475 // if we are now connected.
476 if (is_connected && !m_system_arch_set_while_connected)
477 fetch = true;
478 }
479 else
480 {
481 // We don't have valid OS version info, fetch it if we are connected
482 fetch = is_connected;
483 }
484
485 if (fetch)
486 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000487 m_system_arch = GetRemoteSystemArchitecture ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000488 m_system_arch_set_while_connected = m_system_arch.IsValid();
489 }
490 }
491 return m_system_arch;
492}
493
494
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000495Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000496Platform::ConnectRemote (Args& args)
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000497{
498 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000499 if (IsHost())
500 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
501 else
502 error.SetErrorStringWithFormat ("Platform::ConnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000503 return error;
504}
505
506Error
Greg Claytoncb8977d2011-03-23 00:09:55 +0000507Platform::DisconnectRemote ()
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000508{
509 Error error;
Greg Claytoncb8977d2011-03-23 00:09:55 +0000510 if (IsHost())
511 error.SetErrorStringWithFormat ("The currently selected platform (%s) is the host platform and is always connected.", GetShortPluginName());
512 else
513 error.SetErrorStringWithFormat ("Platform::DisconnectRemote() is not supported by %s", GetShortPluginName());
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000514 return error;
515}
Greg Clayton24bc5d92011-03-30 18:16:51 +0000516
517bool
Greg Claytonb72d0f02011-04-12 05:54:46 +0000518Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000519{
520 // Take care of the host case so that each subclass can just
Greg Claytonb72d0f02011-04-12 05:54:46 +0000521 // call this function to get the host functionality.
Greg Clayton24bc5d92011-03-30 18:16:51 +0000522 if (IsHost())
523 return Host::GetProcessInfo (pid, process_info);
524 return false;
525}
526
527uint32_t
Greg Claytonb72d0f02011-04-12 05:54:46 +0000528Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
529 ProcessInstanceInfoList &process_infos)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000530{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000531 // Take care of the host case so that each subclass can just
532 // call this function to get the host functionality.
Greg Clayton24bc5d92011-03-30 18:16:51 +0000533 uint32_t match_count = 0;
534 if (IsHost())
535 match_count = Host::FindProcesses (match_info, process_infos);
536 return match_count;
537}
Greg Claytonb72d0f02011-04-12 05:54:46 +0000538
539
540Error
541Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
542{
543 Error error;
544 // Take care of the host case so that each subclass can just
545 // call this function to get the host functionality.
546 if (IsHost())
547 error = Host::LaunchProcess (launch_info);
548 else
549 error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
550 return error;
551}
552
553lldb::ProcessSP
554Platform::DebugProcess (ProcessLaunchInfo &launch_info,
555 Debugger &debugger,
556 Target *target, // Can be NULL, if NULL create a new target, else use existing one
557 Listener &listener,
558 Error &error)
559{
560 ProcessSP process_sp;
561 // Make sure we stop at the entry point
562 launch_info.GetFlags ().Set (eLaunchFlagDebug);
563 error = LaunchProcess (launch_info);
564 if (error.Success())
565 {
566 lldb::pid_t pid = launch_info.GetProcessID();
567 if (pid != LLDB_INVALID_PROCESS_ID)
568 {
569 process_sp = Attach (pid, debugger, target, listener, error);
570
571// if (process_sp)
572// {
573// if (launch_info.GetFlags().IsClear (eLaunchFlagStopAtEntry))
574// process_sp->Resume();
575// }
576 }
577 }
578 return process_sp;
579}
580